/* * Hamlib RPC backend - main file * Copyright (c) 2001-2004 by Stephane Fillod * Contributed by Francois Retief * * $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 #include #include /* String function definitions */ #include /* UNIX standard function definitions */ #include #include #include #include "hamlib/rotator.h" #include "serial.h" #include "misc.h" #include "token.h" #include "register.h" #include #ifdef HAVE_RPC_RPCENT_H #include #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 */