kopia lustrzana https://github.com/Hamlib/Hamlib
				
				
				
			
		
			
				
	
	
		
			417 wiersze
		
	
	
		
			9.1 KiB
		
	
	
	
		
			C
		
	
	
			
		
		
	
	
			417 wiersze
		
	
	
		
			9.1 KiB
		
	
	
	
		
			C
		
	
	
| /*
 | |
|  *  Hamlib RPC backend - main file
 | |
|  *  Copyright (c) 2001-2004 by Stephane Fillod
 | |
|  *  Contributed by Francois Retief <fgretief@sun.ac.za>
 | |
|  *
 | |
|  *	$Id: rpcrot_backend.c,v 1.8 2004-08-01 21:26:54 fillods Exp $
 | |
|  *
 | |
|  *   This library is free software; you can redistribute it and/or modify
 | |
|  *   it under the terms of the GNU Library General Public License as
 | |
|  *   published by the Free Software Foundation; either version 2 of
 | |
|  *   the License, or (at your option) any later version.
 | |
|  *
 | |
|  *   This program is distributed in the hope that it will be useful,
 | |
|  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 | |
|  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | |
|  *   GNU Library General Public License for more details.
 | |
|  *
 | |
|  *   You should have received a copy of the GNU Library General Public
 | |
|  *   License along with this library; if not, write to the Free Software
 | |
|  *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 | |
|  *
 | |
|  */
 | |
| 
 | |
| #ifdef HAVE_CONFIG_H
 | |
| #include "config.h"
 | |
| #endif
 | |
| 
 | |
| #include <stdlib.h>
 | |
| #include <stdio.h>
 | |
| #include <string.h>  /* String function definitions */
 | |
| #include <unistd.h>  /* UNIX standard function definitions */
 | |
| #include <math.h>
 | |
| #include <netdb.h>
 | |
| #include <limits.h>
 | |
| 
 | |
| #include "hamlib/rotator.h"
 | |
| #include "serial.h"
 | |
| #include "misc.h"
 | |
| #include "token.h"
 | |
| #include "register.h"
 | |
| 
 | |
| #include <rpc/rpc.h>
 | |
| #ifdef HAVE_RPC_RPCENT_H
 | |
| #include <rpc/rpcent.h>
 | |
| #endif
 | |
| 
 | |
| #include "rpcrot.h"
 | |
| #include "rpcrot_backend.h"
 | |
| 
 | |
| struct rpcrot_priv_data {
 | |
| 		CLIENT *cl;
 | |
| 		unsigned long prognum;
 | |
| };
 | |
| 
 | |
| #define ROTPROTO "udp"
 | |
| 
 | |
| /*
 | |
|  * Borrowed from stringify.h
 | |
|  * Indirect stringification.  Doing two levels allows the parameter to be a
 | |
|  * macro itself.  For example, compile with -DFOO=bar, __stringify(FOO)
 | |
|  * converts to "bar".
 | |
|  */
 | |
| 
 | |
| #define r_stringify_1(x)	#x
 | |
| #define r_stringify(x)		r_stringify_1(x)
 | |
| 
 | |
| 
 | |
| /* ************************************************************************* */
 | |
| 
 | |
| static unsigned long extract_prognum(const char val[])
 | |
| {
 | |
| 	if (val[0] == '+') {
 | |
| 		return ROTPROG + atol(val+1);
 | |
| 	} else
 | |
| 		if (val[0] < '0' || val[0] > '9') {
 | |
| 			struct rpcent *ent;
 | |
| 			ent = getrpcbyname (val);
 | |
| 			if (ent)
 | |
| 				return ent->r_number;
 | |
| 			else
 | |
| 				return 0;
 | |
| 	} else
 | |
| 		return atol(val);
 | |
| }
 | |
| 
 | |
| 
 | |
| static int rpcrot_init(ROT *rot)
 | |
| {
 | |
| 	struct rpcrot_priv_data *priv;
 | |
| 
 | |
| 	if (!rot || !rot->caps)
 | |
| 		return -RIG_EINVAL;
 | |
| 	
 | |
| 	rot->state.priv = malloc(sizeof(struct rpcrot_priv_data));
 | |
| 	if (!rot->state.priv) {
 | |
| 		/* whoops! memory shortage! */
 | |
| 		return -RIG_ENOMEM;
 | |
| 	}
 | |
| 	priv = (struct rpcrot_priv_data*)rot->state.priv;
 | |
| 
 | |
| 	rot->state.rotport.type.rig = RIG_PORT_RPC;
 | |
| 	strcpy(rot->state.rotport.pathname, "localhost");
 | |
| 	priv->prognum = ROTPROG;
 | |
| 
 | |
| 	return RIG_OK;
 | |
| }
 | |
| 
 | |
| static int rpcrot_cleanup(ROT *rot)
 | |
| {
 | |
| 	if (!rot)
 | |
| 		return -RIG_EINVAL;
 | |
| 
 | |
| 	if (rot->state.priv)
 | |
| 		free(rot->state.priv);
 | |
| 
 | |
| 	rot->state.priv = NULL;
 | |
| 
 | |
| 	return RIG_OK;
 | |
| }
 | |
| 
 | |
| /* ************************************************************************* */
 | |
| 
 | |
| /*
 | |
|  * assumes rot!=NULL, rs->priv != NULL
 | |
|  */
 | |
| static int rpcrot_open(ROT *rot)
 | |
| {
 | |
| 	struct rpcrot_priv_data *priv;
 | |
| 	struct rot_state *rs;
 | |
| 	model_x *mdl_res;
 | |
| 	rotstate_res *rs_res;
 | |
| 	rot_model_t model;
 | |
| 	const struct rot_caps *caps;
 | |
| 	char *server, *s;
 | |
| 
 | |
| 	rs = &rot->state;
 | |
| 	priv = (struct rpcrot_priv_data *)rs->priv;
 | |
| 	server = strdup(rs->rotport.pathname);
 | |
| 	s = strchr(server, ':');
 | |
| 	if (s) {
 | |
| 		unsigned long prognum;
 | |
| 		*s = '\0';
 | |
| 		prognum = extract_prognum(s+1);
 | |
| 		if (prognum == 0) {
 | |
| 			free(server);
 | |
| 			return -RIG_ECONF;
 | |
| 		}
 | |
| 		priv->prognum = prognum;
 | |
| 	}
 | |
| 
 | |
| 	priv->cl = clnt_create(server, priv->prognum, ROTVERS, ROTPROTO);
 | |
| 	if (priv->cl == NULL) {
 | |
| 		clnt_pcreateerror(server);
 | |
| 		free(server);
 | |
| 		return -RIG_ECONF;
 | |
| 	}
 | |
| 	mdl_res = getmodel_1(NULL, priv->cl);
 | |
| 	if (mdl_res == NULL) {
 | |
| 		clnt_perror(priv->cl, server);
 | |
| 		clnt_destroy(priv->cl);
 | |
| 		free(server);
 | |
| 		priv->cl = NULL;
 | |
| 		return -RIG_EPROTO;
 | |
| 	}
 | |
| 	model = *mdl_res;
 | |
| 	rig_debug(RIG_DEBUG_TRACE,"%s: model %d\n", __FUNCTION__, model);
 | |
| 
 | |
| 	/*
 | |
| 	 * autoload if necessary
 | |
| 	 */
 | |
| 	rot_check_backend(model);
 | |
| 	caps = rot_get_caps(model);
 | |
| 
 | |
| 	/*
 | |
| 	 * Load state values from remote rotator.
 | |
| 	 */
 | |
| 	rs_res = getrotstate_1(NULL, priv->cl);
 | |
| 	if (rs_res == NULL) {
 | |
| 		clnt_perror(priv->cl, server);
 | |
| 		clnt_destroy(priv->cl);
 | |
| 		free(server);
 | |
| 		priv->cl = NULL;
 | |
| 		return -RIG_EPROTO;
 | |
| 	}
 | |
| 
 | |
| 	free(server);
 | |
| 
 | |
| 	if (rs_res->rotstatus != RIG_OK) {
 | |
| 		rig_debug(RIG_DEBUG_VERBOSE, "%s: error from remote - %s\n", __FUNCTION__, rigerror(rs_res->rotstatus));
 | |
| 		return rs_res->rotstatus;
 | |
| 	}
 | |
| 
 | |
| 	rs->min_az = rs_res->rotstate_res_u.state.az_min;
 | |
| 	rs->max_az = rs_res->rotstate_res_u.state.az_max;
 | |
| 	rs->min_el = rs_res->rotstate_res_u.state.el_min;
 | |
| 	rs->max_el = rs_res->rotstate_res_u.state.el_max;
 | |
| 
 | |
| 	return RIG_OK;
 | |
| }
 | |
| 
 | |
| static int rpcrot_close(ROT *rot)
 | |
| {
 | |
| 	struct rpcrot_priv_data *priv;
 | |
| 
 | |
| 	priv = (struct rpcrot_priv_data*)rot->state.priv;
 | |
| 
 | |
| 	if (priv->cl)
 | |
| 		clnt_destroy(priv->cl);
 | |
| 
 | |
| 	return RIG_OK;
 | |
| }
 | |
| 
 | |
| /* ************************************************************************* */
 | |
| 
 | |
| static int rpcrot_set_position(ROT *rot, azimuth_t az, elevation_t el)
 | |
| {
 | |
| 	struct rpcrot_priv_data *priv;
 | |
| 	int *result;
 | |
| 	position_s parg;
 | |
| 
 | |
| 	priv = (struct rpcrot_priv_data *)rot->state.priv;
 | |
| 
 | |
| 	parg.az = az;
 | |
| 	parg.el = el;
 | |
| 	result = setposition_1(&parg, priv->cl);
 | |
| 	if (result == NULL) {
 | |
| 		clnt_perror(priv->cl, "setposition_1");
 | |
| 		return -RIG_EPROTO;
 | |
| 	}
 | |
| 
 | |
| 	return *result;
 | |
| }
 | |
| 
 | |
| static int rpcrot_get_position(ROT *rot, azimuth_t *az, elevation_t *el)
 | |
| {
 | |
| 	struct rpcrot_priv_data *priv;
 | |
| 	position_res *pres;
 | |
| 
 | |
| 	priv = (struct rpcrot_priv_data *)rot->state.priv;
 | |
| 	pres = getposition_1(NULL, priv->cl);
 | |
| 	if (pres == NULL) {
 | |
| 		clnt_perror(priv->cl, "getposition_1");
 | |
| 		return -RIG_EPROTO;
 | |
| 	}
 | |
| 
 | |
| 	if (pres->rotstatus == RIG_OK) {
 | |
| 		*az = pres->position_res_u.pos.az;
 | |
| 		*el = pres->position_res_u.pos.el;
 | |
| 	}
 | |
| 	return pres->rotstatus;
 | |
| }
 | |
| 
 | |
| static int rpcrot_stop(ROT *rot)
 | |
| {
 | |
| 	struct rpcrot_priv_data *priv;
 | |
| 	int *result;
 | |
| 
 | |
| 	priv = (struct rpcrot_priv_data *)rot->state.priv;
 | |
| 	result = stop_1(NULL, priv->cl);
 | |
| 	if (result == NULL) {
 | |
| 		clnt_perror(priv->cl, "stop_1");
 | |
| 		return -RIG_EPROTO;
 | |
| 	}
 | |
| 	return *result;
 | |
| }
 | |
| 
 | |
| static int rpcrot_reset(ROT *rot, rot_reset_t reset)
 | |
| {
 | |
| 	struct rpcrot_priv_data *priv;
 | |
| 	int *result;
 | |
| 	rot_reset_x rstx;
 | |
| 
 | |
| 	rstx = reset;  /* FIXME: is this correct? */
 | |
| 	priv = (struct rpcrot_priv_data *)rot->state.priv;
 | |
| 	result = reset_1(&rstx, priv->cl);
 | |
| 	if (result == NULL) {
 | |
| 		clnt_perror(priv->cl, "reset_1");
 | |
| 		return -RIG_EPROTO;
 | |
| 	}
 | |
| 	return *result;
 | |
| }
 | |
| 
 | |
| static int rpcrot_park(ROT *rot)
 | |
| {
 | |
| 	struct rpcrot_priv_data *priv;
 | |
| 	int *result;
 | |
| 
 | |
| 	priv = (struct rpcrot_priv_data *)rot->state.priv;
 | |
| 	result = park_1(NULL, priv->cl);
 | |
| 	if (result == NULL) {
 | |
| 		clnt_perror(priv->cl, "park_1");
 | |
| 		return -RIG_EPROTO;
 | |
| 	}
 | |
| 	return *result;
 | |
| }
 | |
| 
 | |
| static int rpcrot_move(ROT *rot, int direction, int speed)
 | |
| {
 | |
|     struct rpcrot_priv_data *priv;
 | |
|     move_s arg;
 | |
|     int *result;
 | |
|     arg.direction = direction;
 | |
|     arg.speed = speed;
 | |
|     priv = (struct rpcrot_priv_data *)rot->state.priv;
 | |
|     result = move_1(&arg, priv->cl);
 | |
|     if (result == NULL) {
 | |
|         clnt_perror(priv->cl, "move_1");
 | |
|         return -RIG_EPROTO;
 | |
|     }
 | |
|     return *result;
 | |
| }
 | |
| 
 | |
| #define TOK_PROGNUM TOKEN_BACKEND(1)
 | |
| 
 | |
| static const struct confparams rpcrot_cfg_params[] = {
 | |
| 	{ TOK_PROGNUM, "prognum", "Program number", "RPC program number",
 | |
| 			r_stringify(ROTPROG), RIG_CONF_NUMERIC, { .n = { 100000, ULONG_MAX, 1 } }
 | |
| 	},
 | |
| 	{ RIG_CONF_END, NULL, }
 | |
| };
 | |
| 
 | |
| /*
 | |
|  * Assumes rot!=NULL, rot->state.priv!=NULL
 | |
|  */
 | |
| int rpcrot_set_conf(ROT *rot, token_t token, const char *val)
 | |
| {
 | |
| 	struct rpcrot_priv_data *priv;
 | |
| 	struct rot_state *rs;
 | |
| 
 | |
| 	rs = &rot->state;
 | |
| 	priv = (struct rpcrot_priv_data*)rs->priv;
 | |
| 
 | |
| 	switch(token) {
 | |
| 	case TOK_PROGNUM:
 | |
| 		{
 | |
| 			unsigned long prognum;
 | |
| 			prognum = extract_prognum(val);
 | |
| 			if (prognum == 0)
 | |
| 				return -RIG_EINVAL;
 | |
| 			priv->prognum = prognum;
 | |
| 			break;
 | |
| 		}
 | |
| 	default:
 | |
| 		return -RIG_EINVAL;
 | |
| 	}
 | |
| 	return RIG_OK;
 | |
| }
 | |
| 
 | |
| /*
 | |
|  * assumes rot!=NULL,
 | |
|  * Assumes rot!=NULL, rot->state.priv!=NULL
 | |
|  *  and val points to a buffer big enough to hold the conf value.
 | |
|  */
 | |
| int rpcrot_get_conf(ROT *rot, token_t token, char *val)
 | |
| {
 | |
| 	struct rpcrot_priv_data *priv;
 | |
| 	struct rot_state *rs;
 | |
| 
 | |
| 	rs = &rot->state;
 | |
| 	priv = (struct rpcrot_priv_data*)rs->priv;
 | |
| 
 | |
| 	switch(token) {
 | |
| 	case TOK_PROGNUM:
 | |
| 		sprintf(val, "%ld", priv->prognum);
 | |
| 		break;
 | |
| 	default:
 | |
| 		return -RIG_EINVAL;
 | |
| 	}
 | |
| 	return RIG_OK;
 | |
| }
 | |
| 
 | |
| /* ************************************************************************* */
 | |
| 
 | |
| struct rot_caps rpcrot_caps = {
 | |
|   .rot_model =      ROT_MODEL_RPC,
 | |
|   .model_name =     "RPC rotator",
 | |
|   .mfg_name =       "Hamlib",
 | |
|   .version =        "0.1",
 | |
|   .copyright = 	 "LGPL",
 | |
|   .status =         RIG_STATUS_NEW,
 | |
|   .rot_type =       ROT_TYPE_OTHER,
 | |
|   .port_type =      RIG_PORT_NONE,
 | |
|   .priv =  NULL,
 | |
| 
 | |
|   .rot_init =     rpcrot_init,
 | |
|   .rot_cleanup =  rpcrot_cleanup,
 | |
|   .rot_open =     rpcrot_open,
 | |
|   .rot_close =    rpcrot_close,
 | |
| 
 | |
|   .cfgparams =  rpcrot_cfg_params,
 | |
|   .set_conf =   rpcrot_set_conf,
 | |
|   .get_conf =   rpcrot_get_conf,
 | |
| 
 | |
|   .set_position =  rpcrot_set_position,
 | |
|   .get_position =  rpcrot_get_position,
 | |
|   .stop =  rpcrot_stop,
 | |
|   .reset =  rpcrot_reset,
 | |
|   .park =  rpcrot_park,
 | |
|   .move =  rpcrot_move,
 | |
| 
 | |
| };
 | |
| 
 | |
| /* ************************************************************************* */
 | |
| 
 | |
| DECLARE_INITROT_BACKEND(rpcrot)
 | |
| {
 | |
| 	rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __FUNCTION__);
 | |
| 
 | |
| 	rot_register(&rpcrot_caps);
 | |
| 
 | |
| 	return RIG_OK;
 | |
| }
 | |
| 
 | |
| /* ************************************************************************* */
 | |
| /* end of file */
 | |
| 
 |