Logo Search packages:      
Sourcecode: hamlib version File versions  Download package

rpcrot_backend.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 */


Generated by  Doxygen 1.6.0   Back to index