From cb67027f8ca92f5102fdffec21459169e1e3964c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Fillod=2C=20F8CFE?= Date: Fri, 28 Dec 2001 20:34:30 +0000 Subject: [PATCH] Initial release git-svn-id: https://hamlib.svn.sourceforge.net/svnroot/hamlib/trunk@827 7ae35d74-ebe9-4afe-98af-79ac388436b8 --- dummy/rot_dummy.c | 195 ++++++++++++++++ dummy/rot_dummy.h | 31 +++ tests/rotctl.1 | 133 +++++++++++ tests/rotctl.c | 569 ++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 928 insertions(+) create mode 100644 dummy/rot_dummy.c create mode 100644 dummy/rot_dummy.h create mode 100644 tests/rotctl.1 create mode 100644 tests/rotctl.c diff --git a/dummy/rot_dummy.c b/dummy/rot_dummy.c new file mode 100644 index 000000000..581765379 --- /dev/null +++ b/dummy/rot_dummy.c @@ -0,0 +1,195 @@ +/* + * Hamlib Dummy backend - main file + * Copyright (c) 2001,2002 by Stephane Fillod + * + * $Id: rot_dummy.c,v 1.1 2001-12-28 20:29:33 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 /* Standard input/output definitions */ +#include /* String function definitions */ +#include /* UNIX standard function definitions */ +#include /* File control definitions */ +#include /* Error number definitions */ +#include /* POSIX terminal control definitions */ +#include +#include + +#include +#include +#include + +#include "rot_dummy.h" + +struct dummy_rot_priv_data { + azimuth_t az; + elevation_t el; +}; + + + +static int dummy_rot_init(ROT *rot) +{ + struct dummy_rot_priv_data *priv; + + priv = (struct dummy_rot_priv_data*) + malloc(sizeof(struct dummy_rot_priv_data)); + + if (!priv) + return -RIG_ENOMEM; + rot->state.priv = (void*)priv; + + rig_debug(RIG_DEBUG_VERBOSE,__FUNCTION__ " called\n"); + rot->state.rotport.type.rig = RIG_PORT_NONE; + + priv->az = priv->el = 0; + + return RIG_OK; +} + +static int dummy_rot_cleanup(ROT *rot) +{ + rig_debug(RIG_DEBUG_VERBOSE,__FUNCTION__ " called\n"); + + if (rot->state.priv) + free(rot->state.priv); + + rot->state.priv = NULL; + + return RIG_OK; +} + +static int dummy_rot_open(ROT *rot) +{ + rig_debug(RIG_DEBUG_VERBOSE,__FUNCTION__ " called\n"); + + return RIG_OK; +} + +static int dummy_rot_close(ROT *rot) +{ + rig_debug(RIG_DEBUG_VERBOSE,__FUNCTION__ " called\n"); + + return RIG_OK; +} + +static int dummy_rot_set_position(ROT *rot, azimuth_t az, elevation_t el) +{ + struct dummy_rot_priv_data *priv = (struct dummy_rot_priv_data *)rot->state.priv; + + rig_debug(RIG_DEBUG_VERBOSE,__FUNCTION__ " called: %f %f\n", + az, el); + priv->az = az; + priv->el = el; + + return RIG_OK; +} + + +static int dummy_rot_get_position(ROT *rot, azimuth_t *az, elevation_t *el) +{ + struct dummy_rot_priv_data *priv = (struct dummy_rot_priv_data *)rot->state.priv; + + rig_debug(RIG_DEBUG_VERBOSE,__FUNCTION__ " called\n"); + + *az = priv->az; + *el = priv->el; + + return RIG_OK; +} + + +static int dummy_rot_stop(ROT *rot) +{ + rig_debug(RIG_DEBUG_VERBOSE,__FUNCTION__ " called\n"); + + return RIG_OK; +} + + +static int dummy_rot_park(ROT *rot) +{ + rig_debug(RIG_DEBUG_VERBOSE,__FUNCTION__ " called\n"); + + return RIG_OK; +} + +static int dummy_rot_reset(ROT *rot, rot_reset_t reset) +{ + rig_debug(RIG_DEBUG_VERBOSE,__FUNCTION__ " called\n"); + + return RIG_OK; +} + + +static const char *dummy_rot_get_info(ROT *rot) +{ + rig_debug(RIG_DEBUG_VERBOSE,__FUNCTION__ " called\n"); + + return ""; +} + + + +/* + * Dummy rotator capabilities. + */ + +const struct rot_caps dummy_rot_caps = { + rot_model: ROT_MODEL_DUMMY, + model_name: "Dummy", + mfg_name: "Hamlib", + version: "0.1", + copyright: "LGPL", + status: RIG_STATUS_ALPHA, + rot_type: ROT_TYPE_OTHER, + port_type: RIG_PORT_NONE, + + min_az: -180., + max_az: 180., + min_el: 0., + max_el: 90., + + priv: NULL, /* priv */ + + rot_init: dummy_rot_init, + rot_cleanup: dummy_rot_cleanup, + rot_open: dummy_rot_open, + rot_close: dummy_rot_close, + + set_position: dummy_rot_set_position, + get_position: dummy_rot_get_position, + park: dummy_rot_park, + stop: dummy_rot_stop, + reset: dummy_rot_reset, + + get_info: dummy_rot_get_info, +}; + +int initrots_dummy(void *be_handle) +{ + rig_debug(RIG_DEBUG_VERBOSE, "dummy: _init called\n"); + + rot_register(&dummy_rot_caps); + + return RIG_OK; +} diff --git a/dummy/rot_dummy.h b/dummy/rot_dummy.h new file mode 100644 index 000000000..314179f2a --- /dev/null +++ b/dummy/rot_dummy.h @@ -0,0 +1,31 @@ +/* + * Hamlib Dummy backend - main header + * Copyright (c) 2001,2002 by Stephane Fillod + * + * $Id: rot_dummy.h,v 1.1 2001-12-28 20:29:33 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. + * + */ + +#ifndef _ROT_DUMMY_H +#define _ROT_DUMMY_H 1 + + +extern const struct rot_caps dummy_rot_caps; + +extern BACKEND_EXPORT(int) initrots_dummy(void *be_handle); + +#endif /* _ROT_DUMMY_H */ diff --git a/tests/rotctl.1 b/tests/rotctl.1 new file mode 100644 index 000000000..cdf729661 --- /dev/null +++ b/tests/rotctl.1 @@ -0,0 +1,133 @@ +.\" Hey, EMACS: -*- nroff -*- +.\" First parameter, NAME, should be all caps +.\" Second parameter, SECTION, should be 1-8, maybe w/ subsection +.\" other parameters are allowed: see man(7), man(1) +.TH ROTCTL "1" "December 28, 2001" "Hamlib" +.\" Please adjust this date whenever revising the manpage. +.\" +.\" Some roff macros, for reference: +.\" .nh disable hyphenation +.\" .hy enable hyphenation +.\" .ad l left justify +.\" .ad b justify to both left and right margins +.\" .nf disable filling +.\" .fi enable filling +.\" .br insert line break +.\" .sp insert n+1 empty lines +.\" for manpage-specific macros, see man(7) +.SH NAME +rotctl \- control antenna rotators +.SH SYNOPSIS +.B rotctl +[\fIOPTION\fR]... [\fICOMMAND\fR]... +.SH DESCRIPTION +Control antenna rotators. +\fBrotctl\fP accepts \fBcommands\fP from command line as well as in +interactive mode if none provided in command line. +.PP +.\" TeX users may be more comfortable with the \fB\fP and +.\" \fI\fP escape sequences to invode bold face and italics, +.\" respectively. +Keep in mind that \fBHamlib\fP is still ALPHA level software. +A lof of stuff hasn't been tested thoroughly, and the API may change +without publicised notice. Please report bugs and feedback at +the e-mail address given in the REPORTING BUGS section. +.SH OPTIONS +This program follow the usual GNU command line syntax, with long +options starting with two dashes (`-'). +A summary of options is included below. +.TP +.B \-m, \-\-model=id +Select rotator model number. See model list. +.TP +.B \-r, --rot-file=device +Use \fBdevice\fP as the file name of the rotator to operate. +.TP +.B \-p, --ptt-file=device +Use \fBdevice\fP as the file name of the Push-To-Talk device to operate on. +.TP +.B \-d, --dcd-file=device +Use \fBdevice\fP as the file name of the Data Carrier Detect device +to operate on. +.TP +.B \-p, --ptt-type=type +Use \fBtype\fP device as the kind of the Push-To-Talk device to operate on. +.TP +.B \-d, --dcd-type=type +Use \fBtype\fP device as the kind of the Data Carrier Detect device +to operate on. +.TP +.B \-s, --serial-speed=baud +Set serial speed to \fBbaud\fP rate. Uses maximal rotator speed as default. +.TP +.B \-L, \-\-show-conf +List all config parameters. +.TP +.B \-C, \-\-set\-conf=parm=val[,parm=val]* +Set config parameter. +.TP +.B \-l, \-\-list +List all model numbers and exit. +.TP +.B \-v, \-\-verbose +Set verbose mode, cumulative. +.TP +.B \-h, \-\-help +Show summary of options and exit. +.TP +.B \-V, \-\-version +Show version of program and exit. + +.SH COMMANDS +Commands can be entered either as a single char, or as a long command name. +Basically, the commands do not take a dash in front of them, as +the options usually do. They may be typed in when in interactive mode +or provided as argument in command line interface mode. +Since most of the Hamlib operations have a \fIset\fP and a \fIget\fP method, +upper case letter will be used for \fIset\fP method whereas the corresponding +lower case letter refers to the \fIget\fP method. +.PP +Please note that the backend for the rotator to be controlled, +or the rotator itself may not support some commands. In that case, +the operation will fail with a standard error message. +.PP +A summary of commands is included below. +.TP +.B P, set_pos +Set position: azimuth and elevation. +.TP +.B p, get_pos +Get position: azimuth and elevation. +.TP +.B K, park +Park the antenna. +.TP +.B S, stop +Stop the rotator. +.TP +.B R, reset +Reset the rotator. + +.SH RETURN VALUE +rotctl exits with: +0 if all operations went fine; 1 if there was an invalid command line +option or arg; or 2 if an error was returned by Hamlib. + +.SH AUTHOR +Written by Stephane Fillod. +.SH BUGS +.PP +This suspicious empty section... +.SH REPORTING BUGS +Report bugs to . +.br +I'm already aware of the bug in the previous section :-) +.SH COPYRIGHT +Copyright \(co 2000,2001 Stephane Fillod. +.br +This is free software; see the source for copying conditions. +There is NO warranty; not even for MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. +.SH SEE ALSO +.BR hamlib (3) + diff --git a/tests/rotctl.c b/tests/rotctl.c new file mode 100644 index 000000000..47d81191c --- /dev/null +++ b/tests/rotctl.c @@ -0,0 +1,569 @@ +/* + * rotctl.c - (C) Stephane Fillod 2000,2001 + * + * This program test/control a rotator using Hamlib. + * It takes commands in interactive mode as well as + * from command line options. + * + * $Id: rotctl.c,v 1.1 2001-12-28 20:34:30 fillods Exp $ + * + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include + +#include + +#include +#include "misc.h" + + + +#define MAXNAMSIZ 32 +#define MAXNBOPT 100 /* max number of different options */ + + +#define ARG_IN1 0x01 +#define ARG_OUT1 0x02 +#define ARG_IN2 0x04 +#define ARG_OUT2 0x08 +#define ARG_IN3 0x10 +#define ARG_OUT3 0x20 +#define ARG_IN4 0x40 +#define ARG_OUT4 0x80 + +#define ARG_NONE 0 +#define ARG_IN (ARG_IN1|ARG_IN2|ARG_IN3|ARG_IN4) +#define ARG_OUT (ARG_OUT1|ARG_OUT2|ARG_OUT3|ARG_OUT4) + +struct test_table { + unsigned char cmd; + const char *name; + int (*rot_routine)(ROT*, int, const struct test_table*, const char*, + const char*, const char*); + int flags; + const char *arg1; + const char *arg2; + const char *arg3; +}; + +/* + * Prototypes + */ +void usage(); +void usage_rot(); +void version(); +void list_models(); +static int print_conf_list(const struct confparams *cfp, rig_ptr_t data); +int set_conf(ROT *my_rot, char *conf_parms); + +rmode_t parse_mode(const char *s); +vfo_t parse_vfo(const char *s); +setting_t parse_func(const char *s); +setting_t parse_level(const char *s); +setting_t parse_parm(const char *s); +vfo_op_t parse_vfo_op(const char *s); +scan_t parse_scan(const char *s); +rptr_shift_t parse_rptr_shift(const char *s); + +#define declare_proto_rot(f) static int (f)(ROT *rot, int interactive, \ + const struct test_table *cmd, const char *arg1, \ + const char *arg2, const char *arg3) + +declare_proto_rot(set_position); +declare_proto_rot(get_position); +declare_proto_rot(stop); +declare_proto_rot(park); +declare_proto_rot(reset); + + +/* + * convention: upper case cmd is set, lowercase is get + * + * NB: 'q' 'Q' '?' are reserved by interactive mode interface + */ +struct test_table test_list[] = { + { 'P', "set_pos", set_position, ARG_IN, "Azimuth", "Elevation" }, + { 'p', "get_pos", get_position, ARG_OUT, "Azimuth", "Elevation" }, + { 'K', "park", park, ARG_NONE, }, + { 'S', "stop", stop, ARG_NONE, }, + { 'R', "reset", reset, ARG_IN, "Reset" }, + { 0x00, "", NULL }, + +}; + +/* + * Reminder: when adding long options, + * keep up to date SHORT_OPTIONS, usage()'s output and man page. thanks. + * NB: do NOT use -W since it's reserved by POSIX. + * TODO: add an option to read from a file + */ +#define SHORT_OPTIONS "m:r:s:C:LvhVl" +static struct option long_options[] = +{ + {"model", 1, 0, 'm'}, + {"rot-file", 1, 0, 'r'}, + {"serial-speed", 1, 0, 's'}, + {"list", 0, 0, 'l'}, + {"set-conf", 1, 0, 'C'}, + {"show-conf",0, 0, 'L'}, + {"verbose", 0, 0, 'v'}, + {"help", 0, 0, 'h'}, + {"version", 0, 0, 'V'}, + {0, 0, 0, 0} +}; + +struct test_table *find_cmd_entry(int cmd) +{ + int i; + for (i=0; i= MAXNBOPT || test_list[i].cmd == 0x00) + return NULL; + + return &test_list[i]; +} +/* + * TODO: use Lex + */ +char parse_arg(const char *arg) +{ + int i; + for (i=0; istate.rotport.pathname, rot_file, FILPATHLEN); + + /* FIXME: bound checking and port type == serial */ + if (serial_rate != 0) + my_rot->state.rotport.parm.serial.rate = serial_rate; + + /* + * print out conf parameters + */ + if (show_conf) { + rot_token_foreach(my_rot, print_conf_list, (rig_ptr_t)my_rot); + } + + retcode = rot_open(my_rot); + if (retcode != RIG_OK) { + fprintf(stderr,"rot_open: error = %s \n", rigerror(retcode)); + exit(2); + } + + if (verbose > 0) + printf("Opened rot model %d, '%s'\n", my_rot->caps->rot_model, + my_rot->caps->model_name); + +#define MAXARGSZ 127 + while (1) { + char arg1[MAXARGSZ+1], *p1; + char arg2[MAXARGSZ+1], *p2; + char arg3[MAXARGSZ+1], *p3; + static int last_was_ret = 1; + + if (interactive) { + printf("\nRig command: "); + + do { + scanf("%c", &cmd); + if (cmd == 0x0a || cmd == 0x0d) { + if (last_was_ret) { + printf("? for help, q to quit.\n"); + printf("\nRig command: "); + continue; + } + last_was_ret = 1; + } + } while (cmd == 0x0a || cmd == 0x0d); + + last_was_ret = 0; + + if (cmd == 'Q' || cmd == 'q') + break; + if (cmd == '?') { + usage_rot(); + continue; + } + } else { + /* parse rest of command line */ + if (optind >= argc) + break; + if (argv[optind][1] == '\0') + cmd = argv[optind][0]; + else + cmd = parse_arg(argv[optind]); + optind++; + } + + cmd_entry = find_cmd_entry(cmd); + if (!cmd_entry) { + fprintf(stderr, "Command '%c' not found!\n", cmd); + continue; + } + + p1 = p2 = p3 = NULL; + if ((cmd_entry->flags & ARG_IN1) && cmd_entry->arg1) { + if (interactive) { + printf("%s: ", cmd_entry->arg1); + scanf("%s", arg1); + p1 = arg1; + } else { + if (!argv[optind]) { + fprintf(stderr, "Invalid arg for command '%s'\n", + cmd_entry->name); + exit(2); + } + p1 = argv[optind++]; + } + } + if ((cmd_entry->flags & ARG_IN2) && cmd_entry->arg2) { + if (interactive) { + printf("%s: ", cmd_entry->arg2); + scanf("%s", arg2); + p2 = arg2; + } else { + if (!argv[optind]) { + fprintf(stderr, "Invalid arg for command '%s'\n", + cmd_entry->name); + exit(2); + } + p2 = argv[optind++]; + } + } + if ((cmd_entry->flags & ARG_IN3) && cmd_entry->arg3) { + if (interactive) { + printf("%s: ", cmd_entry->arg3); + scanf("%s", arg3); + p3 = arg3; + } else { + if (!argv[optind]) { + fprintf(stderr, "Invalid arg for command '%s'\n", + cmd_entry->name); + exit(2); + } + p3 = argv[optind++]; + } + } + retcode = (*cmd_entry->rot_routine)(my_rot, interactive, + cmd_entry, p1, p2, p3); + + if (retcode != RIG_OK ) { + printf("%s: error = %s\n", cmd_entry->name, rigerror(retcode)); + } + } + + rot_close(my_rot); /* close port */ + rot_cleanup(my_rot); /* if you care about memory */ + + return 0; +} + + + +void version() +{ + printf("rotctl, %s\n\n", hamlib_version); + printf("%s\n", hamlib_copyright); +} + +void usage_rot() +{ + int i; + + printf("Commands (may not be available for this rotator):\n"); + for (i=0; test_list[i].cmd != 0; i++) { + printf("%c: %-16s(", test_list[i].cmd, test_list[i].name); + if (test_list[i].arg1) + printf("%s", test_list[i].arg1); + if (test_list[i].arg2) + printf(",%s", test_list[i].arg2); + if (test_list[i].arg3) + printf(",%s", test_list[i].arg3); + printf(") \t"); + + if (i%2) + printf("\n"); + } + +} +void usage() +{ + printf("Usage: rotctl [OPTION]... [COMMAND]...\n" + "Send COMMANDs to a connected antenna rotator.\n\n"); + + + printf( + " -m, --model=ID select rotator model number. See model list\n" + " -r, --rot-file=DEVICE set device of the rotator to operate on\n" + " -s, --serial-speed=BAUD set serial speed of the serial port\n" + " -C, --set-conf=PARM=VAL set config parameters\n" + " -L, --show-conf list all config parameters\n" + " -l, --list list all model numbers and exit\n" + " -v, --verbose set verbose mode, cumulative\n" + " -h, --help display this help and exit\n" + " -V, --version output version information and exit\n\n" + ); + + usage_rot(); + + printf("\nReport bugs to .\n"); + +} + +static int print_conf_list(const struct confparams *cfp, rig_ptr_t data) +{ + ROT *rot = (ROT*) data; + int i; + char buf[128] = ""; + + rot_get_conf(rot, cfp->token, buf); + printf("%s: \"%s\"\n" "\t" + "Default: %s, Value: %s\n", + cfp->name, cfp->tooltip, + cfp->dflt, buf ); + + switch (cfp->type) { + case RIG_CONF_NUMERIC: + printf("\tRange: %.1f..%.1f, step %.1f\n", + cfp->u.n.min, cfp->u.n.max, cfp->u.n.step); + break; + case RIG_CONF_COMBO: + if (!cfp->u.c.combostr) + break; + printf("\tCombo: %s", cfp->u.c.combostr[0]); + for (i=1 ; iu.c.combostr[i]; i++) + printf(", %s", cfp->u.c.combostr[i]); + printf("\n"); + break; + default: + } + + return 1; /* !=0, we want them all ! */ +} + +static int print_model_list(const struct rot_caps *caps, void *data) +{ + printf("%d\t%-14s%-16s%s\n", caps->rot_model, caps->mfg_name, + caps->model_name, caps->version); + return 1; /* !=0, we want them all ! */ +} + +void list_models() +{ + int status; + + rot_load_all_backends(); + + printf("Rig#\tMfg Model Vers.\n"); + status = rot_list_foreach(print_model_list, NULL); + if (status != RIG_OK ) { + printf("rot_list_foreach: error = %s \n", rigerror(status)); + exit(2); + } +} + + +int set_conf(ROT *my_rot, char *conf_parms) +{ + char *p, *q, *n; + int ret; + + p = conf_parms; + while (p && *p != '\0') { + /* FIXME: left hand value of = cannot be null */ + q = strchr(p, '='); + if (q) *q++ = '\0'; + n = strchr(q, ','); + if (n) *n++ = '\0'; + + ret = rot_set_conf(my_rot, rot_token_lookup(my_rot, p), q); + if (ret != RIG_OK) + return ret; + p = n; + } + return RIG_OK; +} + + +/* + * static int (f)(ROT *rot, int interactive, const void *arg1, const void *arg2, const void *arg3, const void *arg4) + */ + +declare_proto_rot(set_position) +{ + azimuth_t az; + elevation_t el; + + sscanf(arg1, "%f", &az); + sscanf(arg2, "%f", &el); + return rot_set_position(rot, az, el); +} + +declare_proto_rot(get_position) +{ + int status; + azimuth_t az; + elevation_t el; + + status = rot_get_position(rot, &az, &el); + if (status != RIG_OK) + return status; + if (interactive) + printf("%s: ", cmd->arg1); + printf("%f\n", az); + if (interactive) + printf("%s: ", cmd->arg2); + printf("%f", el); + return status; +} + +declare_proto_rot(stop) +{ + return rot_stop(rot); +} + +declare_proto_rot(park) +{ + return rot_park(rot); +} + + +declare_proto_rot(reset) +{ + rot_reset_t reset; + + sscanf(arg1, "%d", &reset); + return rot_reset(rot, reset); +} +