From: <n0...@us...> - 2010-01-24 23:24:26
|
Revision: 2813 http://hamlib.svn.sourceforge.net/hamlib/?rev=2813&view=rev Author: n0nb Date: 2010-01-24 23:24:20 +0000 (Sun, 24 Jan 2010) Log Message: ----------- Added initial support for Block protocol in rigctld and documented same. Rewrote testctld.pl for new block protocol and included it with source distribution. Modified Paths: -------------- trunk/tests/Makefile.am trunk/tests/rigctl.c trunk/tests/rigctl_parse.c trunk/tests/rigctld.8 trunk/tests/rigctld.c trunk/tests/testctld.pl Modified: trunk/tests/Makefile.am =================================================================== --- trunk/tests/Makefile.am 2010-01-24 23:18:44 UTC (rev 2812) +++ trunk/tests/Makefile.am 2010-01-24 23:24:20 UTC (rev 2813) @@ -72,5 +72,5 @@ for f in `./listrigs | tail -n +2 | cut -f1` ; do ( ./rigctl -m $$f -u > sup-info/support/model$$f.txt || exit 0 ) ; done ./rigctl -l |sort -n | $(srcdir)/rig_split_lst.awk -v lst_dir="sup-info" -EXTRA_DIST = rigmatrix_head.html rig_split_lst.awk $(man_MANS) +EXTRA_DIST = rigmatrix_head.html rig_split_lst.awk $(man_MANS) testctld.pl Modified: trunk/tests/rigctl.c =================================================================== --- trunk/tests/rigctl.c 2010-01-24 23:18:44 UTC (rev 2812) +++ trunk/tests/rigctl.c 2010-01-24 23:24:20 UTC (rev 2813) @@ -86,6 +86,7 @@ int interactive = 1; /* if no cmd on command line, switch to interactive */ int prompt = 1; /* Print prompt in rigctl */ int opt_end= 0; /* only used by rigctld */ +int opt_block = 0; /* only used by rigctld */ int vfo_mode; /* vfo_mode=0 means target VFO is current VFO */ char send_cmd_term = '\r'; /* send_cmd termination char */ Modified: trunk/tests/rigctl_parse.c =================================================================== --- trunk/tests/rigctl_parse.c 2010-01-24 23:18:44 UTC (rev 2812) +++ trunk/tests/rigctl_parse.c 2010-01-24 23:24:20 UTC (rev 2813) @@ -3,26 +3,26 @@ * (C) Terry Embry 2008-2009 * * This program test/control a radio using Hamlib. - * It takes commands in interactive mode as well as + * It takes commands in interactive mode as well as * from command line options. * - * $Id: rigctl_parse.c,v 1.16 2009-02-06 17:28:38 fillods Exp $ + * $Id: rigctl_parse.c,v 1.16 2009-02-06 17:28:38 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 @@ -73,7 +73,7 @@ struct test_table { unsigned char cmd; const char *name; - int (*rig_routine)(RIG*, FILE*, int, const struct test_table*, vfo_t, + int (*rig_routine)(RIG*, FILE*, int, const struct test_table*, vfo_t, const char*, const char*, const char*); int flags; const char *arg1; @@ -167,20 +167,20 @@ { 'm', "get_mode", get_mode, ARG_OUT, "Mode", "Passband" }, { 'I', "set_split_freq", set_split_freq, ARG_IN, "Tx frequency" }, { 'i', "get_split_freq", get_split_freq, ARG_OUT, "Tx frequency" }, - { 'X', "set_split_mode", set_split_mode, ARG_IN, "Mode", "Passband" }, - { 'x', "get_split_mode", get_split_mode, ARG_OUT, "Mode", "Passband" }, - { 'S', "set_split_vfo", set_split_vfo, ARG_IN, "Split mode", "TxVFO" }, - { 's', "get_split_vfo", get_split_vfo, ARG_OUT, "Split mode", "TxVFO" }, + { 'X', "set_split_mode", set_split_mode, ARG_IN, "Tx mode", "Tx passband" }, + { 'x', "get_split_mode", get_split_mode, ARG_OUT, "Tx mode", "Tx passband" }, + { 'S', "set_split_vfo", set_split_vfo, ARG_IN, "Split", "Tx VFO" }, + { 's', "get_split_vfo", get_split_vfo, ARG_OUT, "Split", "Tx VFO" }, { 'N', "set_ts", set_ts, ARG_IN, "Tuning step" }, { 'n', "get_ts", get_ts, ARG_OUT, "Tuning step" }, - { 'L', "set_level", set_level, ARG_IN, "Level", "Value" }, - { 'l', "get_level", get_level, ARG_IN1|ARG_OUT2, "Level", "Value" }, + { 'L', "set_level", set_level, ARG_IN, "Level", "Level value" }, + { 'l', "get_level", get_level, ARG_IN1|ARG_OUT2, "Level", "Level value" }, { 'U', "set_func", set_func, ARG_IN, "Func", "Func status" }, { 'u', "get_func", get_func, ARG_IN1|ARG_OUT2, "Func", "Func status" }, - { 'P', "set_parm", set_parm, ARG_IN|ARG_NOVFO, "Parm", "Value" }, - { 'p', "get_parm", get_parm, ARG_IN1|ARG_OUT2|ARG_NOVFO, "Parm", "Value" }, + { 'P', "set_parm", set_parm, ARG_IN|ARG_NOVFO, "Parm", "Parm value" }, + { 'p', "get_parm", get_parm, ARG_IN1|ARG_OUT2|ARG_NOVFO, "Parm", "Parm value" }, { 'G', "vfo_op", vfo_op, ARG_IN, "Mem/VFO op" }, - { 'g', "scan", scan, ARG_IN, "Scan fct", "Channel" }, + { 'g', "scan", scan, ARG_IN, "Scan fct", "Scan channel" }, { 'A', "set_trn", set_trn, ARG_IN|ARG_NOVFO, "Transceive" }, { 'a', "get_trn", get_trn, ARG_OUT|ARG_NOVFO, "Transceive" }, { 'R', "set_rptr_shift", set_rptr_shift, ARG_IN, "Rptr shift" }, @@ -191,10 +191,10 @@ { 'c', "get_ctcss_tone", get_ctcss_tone, ARG_OUT, "CTCSS tone" }, { 'D', "set_dcs_code", set_dcs_code, ARG_IN, "DCS code" }, { 'd', "get_dcs_code", get_dcs_code, ARG_OUT, "DCS code" }, - { 0x90, "set_ctcss_sql", set_ctcss_sql, ARG_IN, "CTCSS tone" }, - { 0x91, "get_ctcss_sql", get_ctcss_sql, ARG_OUT, "CTCSS tone" }, - { 0x92, "set_dcs_sql", set_dcs_sql, ARG_IN, "DCS code" }, - { 0x93, "get_dcs_sql", get_dcs_sql, ARG_OUT, "DCS code" }, + { 0x90, "set_ctcss_sql", set_ctcss_sql, ARG_IN, "CTCSS sql" }, + { 0x91, "get_ctcss_sql", get_ctcss_sql, ARG_OUT, "CTCSS sql" }, + { 0x92, "set_dcs_sql", set_dcs_sql, ARG_IN, "DCS sql" }, + { 0x93, "get_dcs_sql", get_dcs_sql, ARG_OUT, "DCS sql" }, { 'V', "set_vfo", set_vfo, ARG_IN|ARG_NOVFO, "VFO" }, { 'v', "get_vfo", get_vfo, ARG_OUT, "VFO" }, { 'T', "set_ptt", set_ptt, ARG_IN, "PTT" }, @@ -216,14 +216,13 @@ { 0x89, "send_dtmf", send_dtmf, ARG_IN, "Digits" }, { 0x8a, "recv_dtmf", recv_dtmf, ARG_OUT, "Digits" }, { '*', "reset", reset, ARG_IN, "Reset" }, - { '2', "power2mW", power2mW, ARG_NOVFO }, { 'w', "send_cmd", send_cmd, ARG_IN1|ARG_IN_LINE|ARG_OUT2|ARG_NOVFO, "Cmd", "Reply" }, { 'b', "send_morse", send_morse, ARG_IN|ARG_IN_LINE, "Morse" }, { 0x8b, "get_dcd", get_dcd, ARG_OUT, "DCD" }, + { '2', "power2mW", power2mW, ARG_NOVFO }, { '1', "dump_caps", dump_caps, ARG_NOVFO }, { '3', "dump_conf", dump_conf, ARG_NOVFO }, { 0x8f,"dump_state", dump_state, ARG_OUT|ARG_NOVFO }, - /* next one is 0x89 */ { 0x00, "", NULL }, }; @@ -231,7 +230,7 @@ static struct test_table *find_cmd_entry(int cmd) { int i; - for (i=0; i<MAXNBOPT && test_list[i].cmd != 0x00; i++) + for (i = 0; i < MAXNBOPT && test_list[i].cmd != 0x00; i++) if (test_list[i].cmd == cmd) break; @@ -246,14 +245,14 @@ static char parse_arg(const char *arg) { int i; - for (i=0; i<MAXNBOPT && test_list[i].cmd != 0; i++) + for (i = 0; i < MAXNBOPT && test_list[i].cmd != 0; i++) if (!strncmp(arg, test_list[i].name, MAXNAMSIZ)) return test_list[i].cmd; return 0; } -/* +/* * This scanf works even in presence of signals (timer, SIGIO, ..) */ static int scanfc(FILE *fin, const char *format, void *p) @@ -276,6 +275,7 @@ extern int interactive; extern int prompt; extern int opt_end; +extern int opt_block; extern int vfo_mode; extern char send_cmd_term; @@ -312,7 +312,7 @@ return -1; *pcmd = '\0'; - cmd = parse_arg((char *) cmd_name); + cmd = parse_arg((char *)cmd_name); break; } @@ -371,7 +371,7 @@ vfo = rig_parse_vfo(arg1); } else { if (!argv[optind]) { - fprintf(stderr, "Invalid arg for command '%s'\n", + fprintf(stderr, "Invalid arg for command '%s'\n", cmd_entry->name); exit(2); } @@ -379,7 +379,7 @@ } } - if ((cmd_entry->flags & ARG_IN_LINE) && + if ((cmd_entry->flags & ARG_IN_LINE) && (cmd_entry->flags & ARG_IN1) && cmd_entry->arg1) { if (interactive) { char *nl; @@ -390,16 +390,16 @@ fgets(arg1, MAXARGSZ, fin); nl = strchr(arg1, 0xa); if (nl) *nl = '\0'; /* chomp */ - p1 = arg1[0]==' '?arg1+1:arg1; + p1 = arg1[0] == ' ' ? arg1 + 1 : arg1; } else { if (!argv[optind]) { - fprintf(stderr, "Invalid arg for command '%s'\n", + fprintf(stderr, "Invalid arg for command '%s'\n", cmd_entry->name); exit(2); } p1 = argv[optind++]; } - } else + } else if ((cmd_entry->flags & ARG_IN1) && cmd_entry->arg1) { if (interactive) { if (prompt) @@ -409,14 +409,14 @@ p1 = arg1; } else { if (!argv[optind]) { - fprintf(stderr, "Invalid arg for command '%s'\n", + fprintf(stderr, "Invalid arg for command '%s'\n", cmd_entry->name); exit(2); } p1 = argv[optind++]; } } - if (p1 && p1[0]!='?' && (cmd_entry->flags & ARG_IN2) && cmd_entry->arg2) { + if (p1 && p1[0] != '?' && (cmd_entry->flags & ARG_IN2) && cmd_entry->arg2) { if (interactive) { if (prompt) fprintf(fout, "%s: ", cmd_entry->arg2); @@ -425,14 +425,14 @@ p2 = arg2; } else { if (!argv[optind]) { - fprintf(stderr, "Invalid arg for command '%s'\n", + fprintf(stderr, "Invalid arg for command '%s'\n", cmd_entry->name); exit(2); } p2 = argv[optind++]; } } - if (p1 && p1[0]!='?' && (cmd_entry->flags & ARG_IN3) && cmd_entry->arg3) { + if (p1 && p1[0] != '?' && (cmd_entry->flags & ARG_IN3) && cmd_entry->arg3) { if (interactive) { if (prompt) fprintf(fout, "%s: ", cmd_entry->arg3); @@ -441,7 +441,7 @@ p3 = arg3; } else { if (!argv[optind]) { - fprintf(stderr, "Invalid arg for command '%s'\n", + fprintf(stderr, "Invalid arg for command '%s'\n", cmd_entry->name); exit(2); } @@ -458,10 +458,23 @@ #endif if (!prompt) - rig_debug(RIG_DEBUG_TRACE, "rigctl: %c '%s' '%s' '%s'\n", + rig_debug(RIG_DEBUG_TRACE, "rigctl(d): %c '%s' '%s' '%s'\n", cmd, p1, p2, p3); - retcode = (*cmd_entry->rig_routine)(my_rig, fout, interactive, + /* Block protocol: output received command name and arguments response */ + if (interactive && opt_block) { + char a1[MAXARGSZ+1]; + char a2[MAXARGSZ+1]; + char a3[MAXARGSZ+1]; + + p1 == NULL ? a1[0] = '\0' : snprintf(a1, sizeof(a1), " %s", p1); + p2 == NULL ? a2[0] = '\0' : snprintf(a2, sizeof(a2), " %s", p2); + p3 == NULL ? a3[0] = '\0' : snprintf(a3, sizeof(a3), " %s", p3); + + fprintf(fout, "%s:%s%s%s\n", cmd_entry->name, a1, a2, a3); + } + + retcode = (*cmd_entry->rig_routine)(my_rig, fout, interactive, cmd_entry, vfo, p1, p2, p3); #ifdef HAVE_PTHREAD @@ -469,17 +482,19 @@ #endif if (retcode != RIG_OK) { - if (interactive && !prompt) + if (interactive && !prompt && opt_block) fprintf(fout, NETRIGCTL_RET "%d\n", retcode); /* only for rigctld */ else fprintf(fout, "%s: error = %s\n", cmd_entry->name, rigerror(retcode)); } else { if (interactive && !prompt) { /* only for rigctld */ - if (!(cmd_entry->flags & ARG_OUT) && !opt_end) /* netrigctl RIG_OK */ + if (!(cmd_entry->flags & ARG_OUT) && !opt_end) /* netrigctl RIG_OK */ fprintf(fout, NETRIGCTL_RET "0\n"); else if ((cmd_entry->flags & ARG_OUT) && opt_end) /* Nate's protocol */ fprintf(fout, "END\n"); - } + else if (opt_block) /* block marker protocol */ + fprintf(fout, NETRIGCTL_RET "0\n"); + } } fflush(fout); @@ -500,7 +515,7 @@ fprintf(fout, "Commands (some may not be available for this rig):\n"); for (i=0; test_list[i].cmd != 0; i++) { - fprintf(fout, "%c: %-16s(", isprint(test_list[i].cmd) ? + fprintf(fout, "%c: %-16s(", isprint(test_list[i].cmd) ? test_list[i].cmd:'?', test_list[i].name); nbspaces = 18; @@ -527,13 +542,13 @@ rig_get_conf(rig, cfp->token, buf); printf("%s: \"%s\"\n" "\t" - "Default: %s, Value: %s\n", - cfp->name, cfp->tooltip, + "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", + printf("\tRange: %.1f..%.1f, step %.1f\n", cfp->u.n.min, cfp->u.n.max, cfp->u.n.step); break; case RIG_CONF_COMBO: @@ -605,7 +620,7 @@ /* - * static int (f)(RIG *rig, FILE *fout, int interactive, const struct test_table *cmd, + * static int (f)(RIG *rig, FILE *fout, int interactive, const struct test_table *cmd, * vfo_t vfo, const void *arg1, const void *arg2, const void *arg3) */ @@ -628,7 +643,7 @@ if (status != RIG_OK) return status; - if (interactive && prompt) + if ((interactive && prompt) || (interactive && !prompt && opt_block)) fprintf(fout, "%s: ", cmd->arg1); /* i.e. "Frequency" */ fprintf(fout, "%"PRIll"\n", (long long)freq); @@ -714,10 +729,10 @@ status = rig_get_mode(rig, vfo, &mode, &width); if (status != RIG_OK) return status; - if (interactive && prompt) + if ((interactive && prompt) || (interactive && !prompt && opt_block)) fprintf(fout, "%s: ", cmd->arg1); fprintf(fout, "%s\n", rig_strrmode(mode)); - if (interactive && prompt) + if ((interactive && prompt) || (interactive && !prompt && opt_block)) fprintf(fout, "%s: ", cmd->arg2); fprintf(fout, "%ld\n", width); @@ -738,7 +753,7 @@ status = rig_get_vfo(rig, &vfo); if (status != RIG_OK) return status; - if (interactive && prompt) + if ((interactive && prompt) || (interactive && !prompt && opt_block)) fprintf(fout, "%s: ", cmd->arg1); fprintf(fout, "%s\n", rig_strvfo(vfo)); @@ -763,13 +778,14 @@ status = rig_get_ptt(rig, vfo, &ptt); if (status != RIG_OK) return status; - if (interactive && prompt) + if ((interactive && prompt) || (interactive && !prompt && opt_block)) fprintf(fout, "%s: ", cmd->arg1); fprintf(fout, "%d\n", ptt); return status; } +/* '0x8b' */ declare_proto_rig(get_dcd) { int status; @@ -778,7 +794,7 @@ status = rig_get_dcd(rig, vfo, &dcd); if (status != RIG_OK) return status; - if (interactive && prompt) + if ((interactive && prompt) || (interactive && !prompt && opt_block)) fprintf(fout, "%s: ", cmd->arg1); fprintf(fout, "%d\n", dcd); @@ -803,7 +819,7 @@ status = rig_get_rptr_shift(rig, vfo, &rptr_shift); if (status != RIG_OK) return status; - if (interactive && prompt) + if ((interactive && prompt) || (interactive && !prompt && opt_block)) fprintf(fout, "%s: ", cmd->arg1); fprintf(fout, "%s\n", rig_strptrshift(rptr_shift)); @@ -828,7 +844,7 @@ status = rig_get_rptr_offs(rig, vfo, &rptr_offs); if (status != RIG_OK) return status; - if (interactive && prompt) + if ((interactive && prompt) || (interactive && !prompt && opt_block)) fprintf(fout, "%s: ", cmd->arg1); fprintf(fout, "%ld\n", rptr_offs); @@ -853,7 +869,7 @@ status = rig_get_ctcss_tone(rig, vfo, &tone); if (status != RIG_OK) return status; - if (interactive && prompt) + if ((interactive && prompt) || (interactive && !prompt && opt_block)) fprintf(fout, "%s: ", cmd->arg1); fprintf(fout, "%d\n", tone); @@ -878,13 +894,14 @@ status = rig_get_dcs_code(rig, vfo, &code); if (status != RIG_OK) return status; - if (interactive && prompt) + if ((interactive && prompt) || (interactive && !prompt && opt_block)) fprintf(fout, "%s: ", cmd->arg1); fprintf(fout, "%d\n", code); return status; } +/* '0x90' */ declare_proto_rig(set_ctcss_sql) { tone_t tone; @@ -893,6 +910,7 @@ return rig_set_ctcss_sql(rig, vfo, tone); } +/* '0x91' */ declare_proto_rig(get_ctcss_sql) { int status; @@ -901,13 +919,14 @@ status = rig_get_ctcss_sql(rig, vfo, &tone); if (status != RIG_OK) return status; - if (interactive && prompt) + if ((interactive && prompt) || (interactive && !prompt && opt_block)) fprintf(fout, "%s: ", cmd->arg1); fprintf(fout, "%d\n", tone); return status; } +/* '0x92' */ declare_proto_rig(set_dcs_sql) { tone_t code; @@ -916,6 +935,7 @@ return rig_set_dcs_sql(rig, vfo, code); } +/* '0x93' */ declare_proto_rig(get_dcs_sql) { int status; @@ -924,7 +944,7 @@ status = rig_get_dcs_sql(rig, vfo, &code); if (status != RIG_OK) return status; - if (interactive && prompt) + if ((interactive && prompt) || (interactive && !prompt && opt_block)) fprintf(fout, "%s: ", cmd->arg1); fprintf(fout, "%d\n", code); @@ -947,11 +967,11 @@ int status; freq_t txfreq; vfo_t txvfo = RIG_VFO_TX; - + status = rig_get_split_freq(rig, txvfo, &txfreq); if (status != RIG_OK) return status; - if (interactive && prompt) + if ((interactive && prompt) || (interactive && !prompt && opt_block)) fprintf(fout, "%s: ", cmd->arg1); fprintf(fout, "%"PRIll"\n", (long long)txfreq); @@ -989,10 +1009,10 @@ status = rig_get_split_mode(rig, txvfo, &mode, &width); if (status != RIG_OK) return status; - if (interactive && prompt) + if ((interactive && prompt) || (interactive && !prompt && opt_block)) fprintf(fout, "%s: ", cmd->arg1); fprintf(fout, "%s\n", rig_strrmode(mode)); - if (interactive && prompt) + if ((interactive && prompt) || (interactive && !prompt && opt_block)) fprintf(fout, "%s: ", cmd->arg2); fprintf(fout, "%ld\n", width); @@ -1018,10 +1038,10 @@ status = rig_get_split_vfo(rig, vfo, &split, &tx_vfo); if (status != RIG_OK) return status; - if (interactive && prompt) + if ((interactive && prompt) || (interactive && !prompt && opt_block)) fprintf(fout, "%s: ", cmd->arg1); fprintf(fout, "%d\n", split); - if (interactive && prompt) + if ((interactive && prompt) || (interactive && !prompt && opt_block)) fprintf(fout, "%s: ", cmd->arg2); fprintf(fout, "%s\n", rig_strvfo(tx_vfo)); @@ -1046,7 +1066,7 @@ status = rig_get_ts(rig, vfo, &ts); if (status != RIG_OK) return status; - if (interactive && prompt) + if ((interactive && prompt) || (interactive && !prompt && opt_block)) fprintf(fout, "%s: ", cmd->arg1); fprintf(fout, "%ld\n", ts); @@ -1165,7 +1185,7 @@ switch (cfp->type) { case RIG_CONF_BUTTON: - /* there's not sense in retrieving value of stateless button */ + /* there's no sense in retrieving value of stateless button */ return -RIG_EINVAL; case RIG_CONF_CHECKBUTTON: @@ -1379,7 +1399,7 @@ status = rig_get_mem(rig, vfo, &ch); if (status != RIG_OK) return status; - if (interactive && prompt) + if ((interactive && prompt) || (interactive && !prompt && opt_block)) fprintf(fout, "%s: ", cmd->arg1); fprintf(fout, "%d\n", ch); @@ -1506,7 +1526,7 @@ chan.tx_vfo = rig_parse_vfo(s); } if (mem_caps->rptr_shift) { - printf("rptr shift (+-0): "); + printf("rptr shift (+-0): "); status = scanf("%s", s); chan.rptr_shift = rig_parse_rptr_shift(s); } @@ -1580,7 +1600,7 @@ { int status; channel_t chan; - + memset(&chan, 0, sizeof(channel_t)); if (isdigit(arg1[0])) { @@ -1665,7 +1685,7 @@ status = rig_get_trn(rig, &trn); if (status != RIG_OK) return status; - if (interactive && prompt) + if ((interactive && prompt) || (interactive && !prompt && opt_block)) fprintf(fout, "%s: ", cmd->arg1); fprintf(fout, "%d\n", trn); @@ -1678,7 +1698,7 @@ const char *s; s = rig_get_info(rig); - if (interactive && prompt) + if ((interactive && prompt) || (interactive && !prompt && opt_block)) fprintf(fout, "%s: ", cmd->arg1); fprintf(fout, "%s\n", s ? s : "None"); @@ -1693,7 +1713,7 @@ char widthbuf[16]; char prntbuf[256]; - fprintf(fout, "Channel: %d, Name: '%s'\n", chan->channel_num, + fprintf(fout, "Channel: %d, Name: '%s'\n", chan->channel_num, chan->channel_desc); fprintf(fout, "VFO: %s, Antenna: %d, Split: %s\n", rig_strvfo(chan->vfo), @@ -1701,12 +1721,12 @@ sprintf_freq(freqbuf, chan->freq); sprintf_freq(widthbuf, chan->width); - fprintf(fout, "Freq: %s\tMode: %s\tWidth: %s\n", + fprintf(fout, "Freq: %s\tMode: %s\tWidth: %s\n", freqbuf, rig_strrmode(chan->mode), widthbuf); sprintf_freq(freqbuf, chan->tx_freq); sprintf_freq(widthbuf, chan->tx_width); - fprintf(fout, "txFreq: %s\ttxMode: %s\ttxWidth: %s\n", + fprintf(fout, "txFreq: %s\ttxMode: %s\ttxWidth: %s\n", freqbuf, rig_strrmode(chan->tx_mode), widthbuf); sprintf_freq(freqbuf,chan->rptr_offs); @@ -1727,7 +1747,7 @@ sprintf_func(prntbuf, chan->funcs); fprintf(fout, "Functions: %s\n", prntbuf); - + fprintf(fout, "Levels:"); for (idx=0; idx<RIG_SETTING_MAX; idx++) { setting_t level = rig_idx2setting(idx); @@ -1798,13 +1818,13 @@ fprintf(fout, "0 0 0 0 0 0 0\n"); for (i=0; i<TSLSTSIZ && !RIG_IS_TS_END(rs->tuning_steps[i]); i++) - fprintf(fout, "0x%x %ld\n", + fprintf(fout, "0x%x %ld\n", rs->tuning_steps[i].modes, rs->tuning_steps[i].ts); fprintf(fout, "0 0\n"); for (i=0; i<FLTLSTSIZ && !RIG_IS_FLT_END(rs->filters[i]); i++) - fprintf(fout, "0x%x %ld\n", + fprintf(fout, "0x%x %ld\n", rs->filters[i].modes, rs->filters[i].width); fprintf(fout, "0 0\n"); @@ -1866,7 +1886,7 @@ status = rig_get_ant(rig, vfo, &ant); if (status != RIG_OK) return status; - if (interactive && prompt) + if ((interactive && prompt) || (interactive && !prompt && opt_block)) fprintf(fout, "%s: ", cmd->arg1); fprintf(fout, "%d\n", rig_setting2idx(ant)); @@ -1928,7 +1948,7 @@ status = rig_get_powerstat(rig, &stat); if (status != RIG_OK) return status; - if (interactive && prompt) + if ((interactive && prompt) || (interactive && !prompt && opt_block)) fprintf(fout, "%s: ", cmd->arg1); fprintf(fout, "%d\n", stat); @@ -2004,12 +2024,12 @@ retval = read_string(&rs->rigport, buf, BUFSZ, eom_buf, strlen(eom_buf)); if (retval < 0) break; - + if (retval < BUFSZ) buf[retval] = '\0'; else buf[BUFSZ-1] = '\0'; - + fprintf(fout, "%s\n", buf); } while (retval > 0); Modified: trunk/tests/rigctld.8 =================================================================== --- trunk/tests/rigctld.8 2010-01-24 23:18:44 UTC (rev 2812) +++ trunk/tests/rigctld.8 2010-01-24 23:24:20 UTC (rev 2813) @@ -2,7 +2,7 @@ .\" 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 RIGCTLD "8" "January 14, 2009" "Hamlib" "Rig Control Daemon" +.TH RIGCTLD "8" "January 24, 2010" "Hamlib" "Rig Control Daemon" .\" Please adjust this date whenever revising the manpage. .\" .\" Some roff macros, for reference: @@ -21,14 +21,15 @@ .B rigctld [\fIOPTION\fR]... .SH DESCRIPTION -The \fBrigctld\fP program is an EXPERIMENTAL \fBHamlib\fP rig daemon that -handles TCP client requests. This allows multiple user programs to share one -radio. Multiple radios can be controlled on different TCP ports. The syntax -of the commands are the same as \fBrigctl\fP. It is hoped that \fBrigctld\fP -will be especially useful for languages such as Perl, Python, and others. +The \fBrigctld\fP program is an EXPERIMENTAL \fBHamlib\fP rig control daemon +that handles TCP client requests. This allows multiple user programs to share +one radio. Multiple radios can be controlled on different TCP ports by use of +multiple \fBrigctld\fP processes. The syntax of the commands are the same as +\fBrigctl\fP. It is hoped that \fBrigctld\fP will be especially useful for +languages such as Perl, Python, PHP, and others. .PP .\" TeX users may be more comfortable with the \fB<whatever>\fP and -.\" \fI<whatever>\fP escape sequences to invoke bold face and italics, +.\" \fI<whatever>\fP escape sequences to invoke bold face and italics, .\" respectively. \fBrigctld\fP communicates to a client through a TCP socket using text commands shared with \fBrigctl\fP. The protocol is simple, commands are sent @@ -39,13 +40,19 @@ is zero when successful, otherwise is a regative number indicating the error code. Each line is terminated with a newline '\\n' character. .PP -Keep in mind that \fBHamlib\fP is BETA level software. +A separate \fBblock\fP protocol (-b, or --block option) extends the above +behavior by echoing the received command string as a header, any returned values +as a key: value pair, and the "RPTR x" string as the end of block marker which +includes the \fBHamlib\fP success or failure value. See the \fIPROTOCOL\fP +section for details. +.PP +Keep in mind that \fBHamlib\fP is BETA level software. While a lot of backend libraries lack complete rig support, the basic functions -are usually well supported. The API may change without publicized notice, +are usually well supported. The API may change without publicized notice, while an advancement of the minor version (e.g. 1.1.x to 1.2.x) indicates such a change. .PP -Please report bugs and provide feedback at the e-mail address given in the +Please report bugs and provide feedback at the e-mail address given in the REPORTING BUGS section. Patches and code enhancements are also welcome. .SH OPTIONS This program follows the usual GNU command line syntax, with long @@ -54,11 +61,11 @@ Here is a summary of the supported options: .TP .B \-m, --model=id -Select radio model number. See -l, "list" option below. +Select radio model number. See the -l, --list option below. .TP .B \-r, --rig-file=device Use \fIdevice\fP as the file name of the port the radio is connected. -Often a serial port, but could be a USB to serial adapter. Typically +Often a serial port, but could be a USB to serial adapter. Typically /dev/ttyS0, /dev/ttyS1, /dev/ttyUSB0, etc. .TP .B \-p, --ptt-file=device @@ -74,7 +81,7 @@ Supported types are RIG (CAT command), DTR, RTS, PARALLEL, NONE. .TP .B \-D, --dcd-type=type -Use \fItype\fP of Data Carrier Detect device. +Use \fItype\fP of Data Carrier Detect device. Supported types are RIG (CAT command), DSR, CTS, CD, PARALLEL, NONE. .TP .B \-s, --serial-speed=baud @@ -82,32 +89,29 @@ backend capabilities (set by -m above) as the default. .TP .B \-c, --civaddr=id -Use \fIid\fP as the CI-V address to communicate with the rig. Only useful for -Icom rigs. +Use \fIid\fP as the CI-V address to communicate with the rig. Only useful for +Icom rigs. .br -NB: The \fIid\fP is in decimal notation, unless prefixed by -\fI0x\fP, in which case it is hexadecimal. +N.B.: The \fIid\fP is in decimal notation, unless prefixed by +\fI0x\fP for a hexadecimal value. .TP -.B \-L, --show-conf -List all config parameters for the radio defined with -m above. +.B \-T, --listen-addr=IPADDR +Use \fIIPADDR\fP as the listening IP address. The default is ANY. .TP +.B \-t, --port=number +Use \fInumber\fP as the TCP listening port. The default is 4532. +.TP .B \-C, --set-conf=parm=val[,parm=val]* Set config parameter. e.g. --set-conf=stop_bits=2 .br Use -L option for a list. .TP -.B \-e, --end-marker -Use END marker in rigctld protocol. -.TP -.B \-t, --port=number -Use \fInumber\fP as the TCP listening port. The default is 4532. -.TP -.B \-T, --listen-addr=IPADDR -Use \fIIPADDR\fP as the listening IP address. The default is ANY. -.TP .B \-l, --list List all model numbers defined in \fBHamlib\fP and exit. .TP +.B \-L, --show-conf +List all config parameters for the radio defined with -m above. +.TP .B \-u, --dump-caps Dump capabilities for the radio defined with -m above and exit. .TP @@ -115,8 +119,17 @@ Set vfo mode, requiring an extra VFO argument in front of each appropriate command. Otherwise, VFO_CURR is assumed when this option is not set. .TP +.B \-b, --block +Use the block rigctld protocol. \fIEXPERIMENTAL\fP +.TP +.B \-e, --end-marker +Use END marker in rigctld protocol. +.br +N.B.: This option can be considered obsolete. Please consider using the block +protocol instead (see \fIPROTOCOL\fP below). +.TP .B \-v, --verbose -Set verbose mode, cumulative (see DIAGNOSTICS below). +Set verbose mode, cumulative (see \fIDIAGNOSTICS\fP below). .TP .B \-h, --help Show a summary of these options and exit. @@ -125,247 +138,252 @@ Show the version of \fBrigctld\fP and exit. .PP \fBN.B.\fP Some options may not be implemented by a given backend and will -return an error. This is most likely to occur with the \fI\-\-set-conf\fP +return an error. This is most likely to occur with the \fI\-\-set-conf\fP and \fI\-\-show-conf\fP options. .PP -Please note that the backend for the radio to be controlled, -or the radio itself may not support some commands. In that case, +Please note that the backend for the radio to be controlled, +or the radio itself may not support some commands. In that case, the operation will fail with a \fBHamlib\fP error code. .SH COMMANDS -Commands can be sent over the TCP socket either as a single char, or as a -long command name plus the value(s) on one '\\n' terminated line. See -PROTOCOL. +Commands can be sent over the TCP socket either as a single char, or as a +long command name plus the value(s) space separated on one '\\n' terminated +line. See \fIPROTOCOL\fP. .PP Since most of the \fBHamlib\fP operations have a \fIset\fP and a \fIget\fP method, -an upper case letter will be used for \fIset\fP method whereas the +an upper case letter will be used for \fIset\fP method whereas the corresponding lower case letter refers to the \fIget\fP method. Each operation also has a long name, prepend a backslash to send a long command name. .PP Example (Perl): `print $socket "\\\\dump_caps\\n";' to see what the radio's -backend can do. +backend can do (NOTE: In Perl and many other languages a '\\' will need to be +escaped with a preceding '\\' so that even though two backslash characters +appear in the code, only one will be passed to \fBrigctld\fP. This is a +possible bug!). .PP -Please note that the backend for the radio to be controlled, -or the radio itself may not support some commands. In that case, +Please note that the backend for the radio to be controlled, +or the radio itself may not support some commands. In that case, the operation will fail with a \fBHamlib\fP error message. .PP -Here is a summary of the supported commands: +Here is a summary of the supported commands (In the case of "set" commands the +quoted string is replaced by the value in the description. In the case of "get" +commands the quoted string is the key name of the value returned.): .TP -.B F, set_freq -Set frequency, in Hz. +.B F, set_freq 'Frequency' +Set 'Frequency', in Hz. .TP .B f, get_freq -Get frequency, in Hz. +Get 'Frequency', in Hz. .TP -.B M, set_mode -Set mode/passband: AM, FM, CW, CWR, USB, LSB, RTTY, RTTYR, WFM, AMS, +.B M, set_mode 'Mode' 'Passband' +Set 'Mode': USB, LSB, CW, CWR, RTTY, RTTYR, AM, FM, WFM, AMS, PKTLSB, PKTUSB, PKTFM, ECSSUSB, ECSSLSB, FAX, SAM, SAL, SAH, DSB. -The passband is the exact passband in Hz, or 0 for the default. +Set 'Passband' in Hz, or 0 for the default. .TP .B m, get_mode -Get mode/passband. +Get 'Mode' 'Passband'. Returns Mode as a string from \fIset_mode\fP above +and Passband in Hz. .TP -.B V, set_vfo -Set VFO: VFOA, VFOB, VFOC, currVFO, VFO, MEM, Main, Sub, TX, RX. +.B V, set_vfo 'VFO' +Set 'VFO': VFOA, VFOB, VFOC, currVFO, VFO, MEM, Main, Sub, TX, RX. .TP .B v, get_vfo -Get current VFO. +Get current 'VFO'. Returns VFO as a string from \fIset_vfo\fP above. .TP -.B J, set_rit -Set RIT, in Hz. +.B J, set_rit 'RIT' +Set 'RIT', in Hz. .TP .B j, get_rit -Get RIT, in Hz. +Get 'RIT', in Hz. .TP -.B Z, set_xit -Set XIT, in Hz. +.B Z, set_xit 'XIT' +Set 'XIT', in Hz. .TP .B z, get_xit -Get XIT, in Hz. +Get 'XIT', in Hz. .TP -.B T, set_ptt -Set PTT, 0 (RX) or 1 (TX). +.B T, set_ptt 'PTT' +Set 'PTT', 0 (RX) or 1 (TX). .TP .B t, get_ptt -Get PTT status. +Get 'PTT' status. .TP -.B get_dcd -Get DCD status. +.B 0x8b, get_dcd +Get 'DCD' (squelch) status, 0 (Closed) or 1 (Open) .TP -.B R, set_rptr_shift -Set repeater shift: "+", "-" or something else for none. +.B R, set_rptr_shift 'Rptr shift' +Set 'Rptr shift': "+", "-" or something else for none. .TP .B r, get_rptr_shift -Get repeater shift. +Get 'Rptr shift'. Returns "+", "-" or "None". .TP -.B O, set_rptr_offs -Set repeater offset, in Hz. +.B O, set_rptr_offs 'Rptr offset' +Set 'Rptr offset', in Hz. .TP .B o, get_rptr_offs -Get repeater offset. +Get 'Rptr offset', in Hz. .TP -.B C, set_ctcss_tone -Set CTCSS tone, in tenth of Hz. +.B C, set_ctcss_tone 'CTCSS tone' +Set 'CTCSS tone', in tenths of Hz. .TP .B c, get_ctcss_tone -Get CTCSS tone, in tenth of Hz. +Get 'CTCSS tone', in tenths of Hz. .TP -.B D, set_dcs_code -Set DCS code. +.B D, set_dcs_code 'DCS code' +Set 'DCS code'. .TP .B d, get_dcs_code -Get DCS code. +Get 'DCS code'. .TP -.B set_ctcss_sql -Set CTCSS squelch tone, in tenth of Hz. +.B 0x90, set_ctcss_sql 'CTCSS sql' +Set 'CTCSS sql' tone, in tenths of Hz. .TP -.B get_ctcss_sql -Get CTCSS squelch tone, in tenth of Hz. +.B 0x91, get_ctcss_sql +Get 'CTCSS sql' tone, in tenths of Hz. .TP -.B set_dcs_sql -Set DCS squelch code. +.B 0x92, set_dcs_sql 'DCS sql' +Set 'DCS sql' code. .TP -.B get_dcs_sql -Get DCS squelch code. +.B 0x93, get_dcs_sql +Get 'DCS sql' code. .TP -.B I, set_split_freq -Set TX frequency, in Hz. +.B I, set_split_freq 'Tx frequency' +Set 'TX frequency', in Hz. .TP .B i, get_split_freq -Get TX frequency. +Get 'TX frequency', in Hz. .TP -.B X, set_split_mode -Set transmit mode/passband: AM, FM, CW, CWR, USB, LSB, RTTY, RTTYR, WFM, AMS, +.B X, set_split_mode 'Tx mode' 'Tx passband' +Set 'Tx mode': AM, FM, CW, CWR, USB, LSB, RTTY, RTTYR, WFM, AMS, PKTLSB, PKTUSB, PKTFM, ECSSUSB, ECSSLSB, FAX, SAM, SAL, SAH, DSB. -The passband is the exact passband in Hz, or 0 for the default. +The 'Tx passband' is the exact passband in Hz, or 0 for the default. .TP .B x, get_split_mode -Get transmit mode/passband. +Get 'Tx mode' and 'Tx passband'. Returns Tx mode as a string from +\fIset_split_mode\fP above and Tx passband in Hz. .TP -.B S, set_split_vfo -Set split mode, 0 or 1, and transmit VFO. +.B S, set_split_vfo 'Split' 'Tx VFO' +Set 'Split' mode, 0 or 1, and 'Tx VFO'. .TP .B s, get_split_vfo -Get split mode and transmit VFO. +Get 'Split' mode and 'Tx VFO'. .TP -.B N, set_ts -Set tuning step, in Hz. +.B N, set_ts 'Tuning step' +Set 'Tuning step', in Hz. .TP .B n, get_ts -Get tuning step. +Get 'Tuning step', in Hz. .TP -.B U, set_func -Set func/status: -FAGC, NB, COMP, VOX, TONE, TSQL, SBKIN, FBKIN, ANF, NR, AIP, APF, MON, MN, -RF, ARO, LOCK, MUTE, VSC, REV, SQL, ABM, BC, MBC, AFC, SATMODE, SCOPE, -RESUME, TBURST, TUNER. +.B U, set_func 'Func' 'Func status' +Set 'Func' 'Func status'. Func is one of: FAGC, NB, COMP, VOX, TONE, TSQL, +SBKIN, FBKIN, ANF, NR, AIP, APF, MON, MN, RF, ARO, LOCK, MUTE, VSC, REV, SQL, +ABM, BC, MBC, AFC, SATMODE, SCOPE, RESUME, TBURST, TUNER. +Func Status argument is a non null value for "activate", "de-activate" +otherwise, much as TRUE/FALSE definitions in C language. .TP .B u, get_func -Get func status. +Get 'Func' 'Func status'. Returns Func as a string from \fIset_func\fP above +and Func status as a non null value. .TP -.B L, set_level -Set level/value: -PREAMP, ATT, VOX, AF, RF, SQL, IF, APF, NR, PBT_IN, PBT_OUT, CWPITCH, RFPOWER, -MICGAIN, KEYSPD, NOTCHF, COMP, AGC, BKINDL, BAL, METER, VOXGAIN, ANTIVOX. -SLOPE_LOW, SLOPE_HIGH, RAWSTR, SQLSTAT, SWR, ALC, STRENGTH. +.B L, set_level 'Level' 'Level value' +Set 'Level' and 'Level value'. Level is one of: PREAMP, ATT, VOX, AF, RF, SQL, +IF, APF, NR, PBT_IN, PBT_OUT, CWPITCH, RFPOWER, MICGAIN, KEYSPD, NOTCHF, COMP, +AGC, BKINDL, BAL, METER, VOXGAIN, ANTIVOX. SLOPE_LOW, SLOPE_HIGH, RAWSTR, +SQLSTAT, SWR, ALC, STRENGTH. +The Level value can be a float or an integer. .TP .B l, get_level -Get level value. +Get 'Level' 'Level value'. Returns Level as a string from \fIset_level\fP +above and Level value as a float or integer. .TP -.B P, set_parm -Set parm/value: -ANN, APO, BACKLIGHT, BEEP, TIME, BAT, KEYLIGHT. +.B P, set_parm 'Parm' 'Parm value' +Set 'Parm' 'Parm value' Parm is one of: ANN, APO, BACKLIGHT, BEEP, TIME, BAT, +KEYLIGHT. .TP .B p, get_parm -Get parm value. +Get 'Parm' 'Parm value'. Returns Parm as a string from \fIset_parm\fP +above and Parm value as a float or integer. .TP -.B B, set_bank -Set bank. +.B B, set_bank 'Bank' +Set 'Bank'. Sets the current memory bank number. .TP -.B E, set_mem -Set memory channel number. +.B E, set_mem 'Memory#' +Set 'Memory#' channel number. .TP .B e, get_mem -Get memory channel number. +Get 'Memory#' channel number. .TP -.B G, vfo_op -Perform VFO operation: -CPY, XCHG, FROM_VFO, TO_VFO, MCL, UP, DOWN, BAND_UP, BAND_DOWN, LEFT, RIGHT, -TUNE, TOGGLE. +.B G, vfo_op 'Mem/VFO op' +Perform 'Mem/VFO op'. Mem VFO operation is one of: CPY, XCHG, FROM_VFO, TO_VFO, +MCL, UP, DOWN, BAND_UP, BAND_DOWN, LEFT, RIGHT, TUNE, TOGGLE. .TP -.B g, scan_op -Perform scan operation/channel: STOP, MEM, SLCT, PRIO, PROG, DELTA, VFO, PLT. +.B g, scan 'Scan fct' 'Scan channel' +Perform 'Scan fct' 'Scan channel'. Scan function/channel is one of: STOP, MEM, +SLCT, PRIO, PROG, DELTA, VFO, PLT. .TP -.B H, set_channel -Set memory channel data. Not implemented yet. +.B H, set_channel 'Channel' +Set memory 'Channel' data. Not implemented yet. .TP .B h, get_channel -Get memory channel data. +Get memory 'Channel' data. .TP -.B A, set_trn -Set transceive mode (reporting event): OFF, RIG, POLL. +.B A, set_trn 'Transceive' +Set 'Transceive' mode (reporting event): OFF, RIG, POLL. .TP .B a, get_trn -Get transceive mode (reporting event). +Get 'Transceive' mode (reporting event) as in \fIset_trn\fP above. .TP -.B Y, set_ant -Set antenna number (0, 1, 2, ..). +.B Y, set_ant 'Antenna' +Set 'Antenna' number (0, 1, 2, ..). .TP .B y, get_ant -Get antenna number (0, 1, 2, ..). +Get 'Antenna' number (0, 1, 2, ..). .TP -.B *, reset -Reset. +.B *, reset 'Reset' +Perform rig 'Reset'. 0 = None, 1 = Software reset, 2 = VFO reset, 4 = Memory +Clear reset, 8 = Master reset. Since these values are defined as a bitmask in +rig.h, it should be possible to AND these values together to do multiple resets +at once, if the backend supports it or supports a reset action via rig control +at all. .TP -.B b, send_morse -Send morse symbols. +.B b, send_morse 'Morse' +Send 'Morse' symbols. .TP -.B 0x87, set_powerstat -Set power status. +.B 0x87, set_powerstat 'Status' +Set power On/Off/Standby 'Status'. 0 = Power Off, 1 = Power On, 2 = Power +Standby. Defined as a bitmask in rig.h. .TP .B 0x88, get_powerstat -Get power status. +Get power On/Off/Standby 'Status' as in \fIset_powerstat\fP above. .TP -.B 0x89, send_dtmf -Set DTMF digits. +.B 0x89, send_dtmf 'Digits' +Set DTMF 'Digits'. .TP .B 0x8a, recv_dtmf -Get DTMF digits. +Get DTMF 'Digits'. .TP .B _, get_info -Get misc information about the rig. +Get misc information about the rig (no value is passed). .TP .B 1, dump_caps -Not a real rig remote command, it just dumps capabilities, i.e. what the +Not a real rig remote command, it just dumps capabilities, i.e. what the backend knows about this model, and what it can do. TODO: Ensure this is in a consistent format so it can be read into a hash, dictionary, etc. .TP .B 2, power2mW -Converts a power value in a range of \fI0.0 ... 1.0\fP to the real transmit -power in milli-Watts. The \fIfrequency\fP and \fImode\fP also need to be +Converts a power value in a range of \fI0.0 ... 1.0\fP to the real transmit +power in milli-Watts. The \fIfrequency\fP and \fImode\fP also need to be provided as output power may vary according to these values. .TP -.B w, send_cmd -Send raw command string to rig. +.B w, send_cmd 'Cmd' +Send raw command string to rig. .br -For binary protocols enter values as \\0xAA\\0xBB - -.SH EXAMPLES -Start \fBrigctld\fP for a Yaesu FT-920 using an USB-to-serial adapter and -backgrounding: -.PP -$ rigctld -m 114 -r /dev/ttyUSB1 & -.PP -Start \fBrigctld\fP for a Yaesu FT-920 using a USB to serial adapter while -setting baud rate and stop bits and backgrounding: -.PP -$ rigctld -m 114 -r /dev/ttyUSB1 -s 4800 -C stop_bits=2 & -.PP -Connect to the already running \fBrigctld\fP, and set current frequency to 14.266 MHz: -.PP -$ echo "\\set_freq 14266000" | nc localhost 4532 +For binary protocols enter values as \\0xAA\\0xBB. Expect a 'Reply' from the +rig which will likely be a binary block or an ASCII string. .SH PROTOCOL +\fBDefault Protocol\fP +.br The \fBrigctld\fP protocol is intentionally simple. Commands are entered on a single line with any needed values. In Perl, reliable results are obtained by terminating each command string with a newline character, '\\n'. @@ -378,36 +396,102 @@ .PP Responses from \fBrigctld\fP are text values and match the same tokens used in the \fIset\fP commands. Each value is returned on its own line. To -signal the end of a response the "END\\n" string is sent when the '-e' option -is passed. +signal the end of a response "0\\n" is returned. .PP Example \fIget\fP (Perl code): print $socket "f\\n"; "14250000\\n" -.br -"END\\n" .PP Most \fIget\fP functions return one to three values. A notable exception is -the \fIdump_caps\fP function which returns many lines of key:value pairs. +the \fI\\dump_caps\fP function which returns many lines of key:value pairs. Future work will focus on making this output compatible with assignment to a hash, dictionary, or other key:value variable. +.PP +\fBBlock Protocol\fP +.br +An \fIEXPERIMENTAL\fP Block protocol has been introduced into \fBrigctld\fP +as of January 24, 2010. This protocol adds several rules to the strings +returned by \fBrigctld\fP. +.PP +1. The command received by \fBrigctld\fP is echoed with its long command name +followed by the value(s) received from the client terminated by a newline +as the first line of the block. +.PP +2. The last line of each block is the string "RPTR \fIx\fP\\n" wheren \fIx\fP is +the numeric return value of the Hamlib backend function that was called by the +command. +.PP +3. Any lines consisting of data values returned by the rig backend are prepended +by a string immediately followed by a colon then a space and then the value +terminated by a newline. e.g. "Frequency: 14250000\\n" +.PP +4. All commands received will be acknowledged by \fBrigctld\fP with lines from +rules 1 and 2. Lines from rule 3 are only returned when data values must be +returned to the client. +.PP +An example response to a \fI\\set_mode\fP command: +.br +set_mode: USB 2400 +.br +RPRT 0 +.PP +In this case the long command name and values are returned on the first line and +the second line contains the end of block marker and the numeric rig backend +return value indicating success. +.PP +An example response to a \fI\\get_mode\fP query: +.br +get_mode: +.br +Mode: CW +.br +Passband: 2400 +.br +RPRT 0 +.PP +In this case, as no value is passed to \fBrigctld\fP, the first line consists +only of the long command name. The final line shows that the command was +processed successfully by the rig backend. +.PP +The following commands have been tested with the Block protocol and the included +`testctld.pl' script: +.br +\fI\\set_freq\fP \fI\\get-freq\fP +.br +\fI\\set_mode\fP \fI\\get_mode\fP +.SH EXAMPLES +Start \fBrigctld\fP for a Yaesu FT-920 using an USB-to-serial adapter and +backgrounding: +.PP +$ rigctld -m 114 -r /dev/ttyUSB1 & +.PP +Start \fBrigctld\fP for a Yaesu FT-920 using a USB to serial adapter while +setting baud rate and stop bits and backgrounding: +.PP +$ rigctld -m 114 -r /dev/ttyUSB1 -s 4800 -C stop_bits=2 & +.PP +Connect to the already running \fBrigctld\fP, and set current frequency to 14.266 MHz: +.PP +$ echo "\\set_freq 14266000" | nc localhost 4532 .SH DIAGNOSTICS -The \fB-v\fP, \fB--version\fP option allows different levels of diagnostics -to be output to \fBstderr\fP and correspond to -v for BUG, -vv for ERR, --vvv for WARN, -vvvv for VERBOSE, or -vvvvv for TRACE. +The \fB-v\fP, \fB--verbose\fP, option allows different levels of diagnostics +to be output to \fBstderr\fP and correspond to -v for BUG, -vv for ERR, +-vvv for WARN, -vvvv for VERBOSE, or -vvvvv for TRACE. .PP A given verbose level is useful for providing needed debugging information to the email address below. For example, TRACE output shows all of the values sent to and received from the radio which is very useful for radio backend -library development and may be requested by the developers. +library development and may be requested by the developers. See the +\fBREADME.betatester\fP and \fBREADME.developer\fP files for more information. .SH SECURITY -No authentication whatsoever; DO NOT leave this TCP port open wide to the -Internet. Please ask if stronger security is needed. +No authentication whatsoever; DO NOT leave this TCP port open wide to the +Internet. Please ask if stronger security is needed or consider using an +SSH tunnel. .SH BUGS The daemon is not detaching and backgrounding itself. - +.br Much testing needs to be done. .SH REPORTING BUGS Report bugs to <ham...@li...>. @@ -418,7 +502,7 @@ .br <http://www.hamlib.org>. .SH COPYRIGHT -Copyright \(co 2000-2009 Stephane Fillod and the Hamlib Group. +Copyright \(co 2000-2010 Stephane Fillod and the Hamlib Group. .PP This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY Modified: trunk/tests/rigctld.c =================================================================== --- trunk/tests/rigctld.c 2010-01-24 23:18:44 UTC (rev 2812) +++ trunk/tests/rigctld.c 2010-01-24 23:24:20 UTC (rev 2813) @@ -4,23 +4,23 @@ * This program test/control a radio using Hamlib. * It takes commands from network connection. * - * $Id: rigctld.c,v 1.11 2009-01-04 14:49:17 fillods Exp $ + * $Id: rigctld.c,v 1.11 2009-01-04 14:49:17 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 @@ -63,12 +63,12 @@ #include "rigctl_parse.h" /* - * Reminder: when adding long options, + * 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:p:d:P:D:s:c:lC:t:T:LeuovhV" +#define SHORT_OPTIONS "m:r:p:d:P:D:s:c:T:t:C:lLuobevhV" static struct option long_options[] = { {"model", 1, 0, 'm'}, @@ -79,13 +79,14 @@ {"dcd-type", 1, 0, 'D'}, {"serial-speed", 1, 0, 's'}, {"civaddr", 1, 0, 'c'}, + {"listen-addr", 1, 0, 'T'}, {"port", 1, 0, 't'}, - {"listen-addr", 1, 0, 'T'}, + {"set-conf", 1, 0, 'C'}, {"list", 0, 0, 'l'}, - {"set-conf", 1, 0, 'C'}, {"show-conf",0, 0, 'L'}, {"dump-caps", 0, 0, 'u'}, {"vfo", 0, 0, 'o'}, + {"block", 0, 0, 'b'}, {"end-marker", 0, 0, 'e'}, {"verbose", 0, 0, 'v'}, {"help", 0, 0, 'h'}, @@ -104,8 +105,9 @@ void usage(void); int interactive = 1; /* no cmd because of daemon */ -int prompt= 0 ; /* Daemon mode for rigparse return string */ -int opt_end= 0 ; /* END marker for rigctld */ +int prompt = 0; /* Daemon mode for rigparse return string */ +int opt_end = 0; /* END marker for rigctld */ +int opt_block = 0; /* Block markers for rigctld */ int vfo_mode; /* vfo_mode=0 means target VFO is current VFO */ char send_cmd_term = '\r'; /* send_cmd termination char */ @@ -116,7 +118,7 @@ #define MAXCONFLEN 128 int main (int argc, char *argv[]) -{ +{ RIG *my_rig; /* handle to rig (instance) */ rig_model_t my_model = RIG_MODEL_DUMMY; @@ -278,13 +280,17 @@ case 'e': opt_end = 1; break; + case 'b': + opt_block = 1; + break; default: usage(); /* unknown option? */ exit(1); } } - rig_set_debug(verbose<2 ? RIG_DEBUG_WARN: verbose); +// rig_set_debug(verbose < 2 ? RIG_DEBUG_WARN: verbose); + rig_set_debug(verbose); rig_debug(RIG_DEBUG_VERBOSE, "rigctld, %s\n", hamlib_version); rig_debug(RIG_DEBUG_VERBOSE, "Report bugs to " @@ -293,7 +299,7 @@ my_rig = rig_init(my_model); if (!my_rig) { - fprintf(stderr, "Unknown rig num %d, or initialization error.\n", + fprintf(stderr, "Unknown rig num %d, or initialization error.\n", my_model); fprintf(stderr, "Please check with --list option.\n"); exit(2); @@ -308,7 +314,7 @@ if (rig_file) strncpy(my_rig->state.rigport.pathname, rig_file, FILPATHLEN); - /* + /* * ex: RIG_PTT_PARALLEL and /dev/parport0 */ if (ptt_type != RIG_PTT_NONE) @@ -351,18 +357,18 @@ if (verbose > 0) printf("Opened rig model %d, '%s'\n", my_rig->caps->rig_model, my_rig->caps->model_name); - rig_debug(RIG_DEBUG_VERBOSE, "Backend version: %s, Status: %s\n", + rig_debug(RIG_DEBUG_VERBOSE, "Backend version: %s, Status: %s\n", my_rig->caps->version, rig_strstatus(my_rig->caps->status)); /* * Prepare listening socket */ - sock_listen = socket(AF_INET, SOCK_STREAM, 0); + sock_listen = socket(AF_INET, SOCK_STREAM, 0); if (sock_listen < 0) { perror("ERROR opening socket"); exit(2); } - memset((char *) &serv_addr, 0, sizeof(serv_addr)); + memset((char *)&serv_addr, 0, sizeof(serv_addr)); serv_addr.sin_family = AF_INET; serv_addr.sin_port = htons(portno); @@ -370,15 +376,15 @@ if (setsockopt(sock_listen, SOL_SOCKET, SO_REUSEADDR, - (char *)&reuseaddr,sizeof(reuseaddr)) < 0) { + (char *)&reuseaddr, sizeof(reuseaddr)) < 0) { rig_debug(RIG_DEBUG_ERR, "setsockopt: %s\n", strerror(errno)); exit (1); } - if (bind(sock_listen, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) { + if (bind(sock_listen, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) { rig_debug(RIG_DEBUG_ERR, "binding: %s\n", strerror(errno)); exit (1); } - if (listen(sock_listen,4) < 0) { + if (listen(sock_listen, 4) < 0) { rig_debug(RIG_DEBUG_ERR, "listening: %s\n", strerror(errno)); exit (1); } @@ -401,7 +407,7 @@ arg->rig = my_rig; arg->clilen = sizeof(arg->cli_addr); - arg->sock = accept(sock_listen, (struct sockaddr *) &arg->cli_addr, + arg->sock = accept(sock_listen, (struct sockaddr *)&arg->cli_addr, &arg->clilen); if (arg->sock < 0) { rig_debug(RIG_DEBUG_ERR, "accept: %s\n", strerror(errno)); @@ -511,6 +517,7 @@ " -l, --list list all model numbers and exit\n" " -u, --dump-caps dump capabilities and exit\n" " -o, --vfo do not default to VFO_CURR, require extra vfo arg\n" + " -b, --block use block rigctld protocol\n", " -e, --end-marker use END marker in rigctld protocol\n" " -v, --verbose set verbose mode, cumulative\n" " -h, --help display this help and exit\n" Modified: trunk/tests/testctld.pl =================================================================== --- trunk/tests/testctld.pl 2010-01-24 23:18:44 UTC (rev 2812) +++ trunk/tests/testctld.pl 2010-01-24 23:24:20 UTC (rev 2813) @@ -3,7 +3,7 @@ # testctld.pl - (C) Nate Bargmann 2008 # A Perl test script for the rigctld program. -# $Id: testctld.pl,v 1.3 2008-01-10 03:42:35 n0nb Exp $ +# $Id$ # It connects to the rigctld TCP port (default 4532) and queries # the daemon for some common rig information. It also aims to provide @@ -13,12 +13,12 @@ # 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. @@ -27,39 +27,71 @@ # Perl modules this script uses use warnings; use strict; -use IO::Socket; +use IO::Socket::INET; # Local variables my $socket; my @answer; -my $freq = "14250000"; -my $mode = "USB"; -my $bw = "2400"; +my $get_freq; +my $get_mode; +my $get_bw; my $flags; +# values to set rig +my $set_freq = "14250000"; +my $set_mode = "USB"; +my $set_bw = "2400"; + # Thanks to Uri Guttman on comp.lang.perl.misc for this function sub get_results { my ($sock) = @_; my @lines; + my $errno; + my $line; +# my $x; - while (my $line = <$sock>) { + do { + while ( !($line = $sock->getline)) { ;} + print $line; - return @lines if $line =~ /^END$/; - push @lines, $line; - } +# return @lines if $line =~ /^RPRT\s+0$/; + if ($line) { + print $line; + push @lines, $line; + } +# else { +# return @lines; +# } + #if ($line =~ /^RPRT.*$/) { + #print $line; + #$errno = (split $line)[1]; + #print $errno; + #unless ($errno) { + #return @lines; + #} + #else { + #return $errno * -1; + #} + #} + #else { + #push @lines, $line; + #} + } until ($line ne ""); + return @lines; } -# Create the new socket. -# 'localhost' may be replaced by any hostname or IP address where a +# Create the new socket. +# 'localhost' may be replaced by any hostname or IP address where a # rigctld instance is running. # Timeout is set to 5 seconds. -$socket = new IO::Socket::INET (PeerAddr => 'localhost', +$socket = IO::Socket::INET->new(PeerAddr => 'localhost', PeerPort => 4532, Proto => 'tcp', Type => SOCK_STREAM, - Timeout => 5 ) + Timeout => 5, + Blocking => 0 ) or die $@; # Query rigctld for the rig's frequency @@ -69,8 +101,12 @@ # Get the rig's frequency from rigctld and print it to STDOUT # N.B. Replies are newline terminated, so lines in @answer end with '\n'. @answer = get_results($socket); +#$get_freq = <$socket>; +#$get_freq = $socket->getline; +#chomp($get_freq); print "The rig's frequency is: $answer[0]"; +#print "The rig's frequency is: $get_freq\n"; # Extra newline for screen formatting. print "\n"; @@ -78,26 +114,41 @@ # Do the same for the mode (reading the mode also returns the bandwidth) print $socket "m\n"; @answer = get_results($socket); +#$get_mode = <$socket>; +#chomp($get_mode); +#$get_bw = <$socket>; +#chomp($get_bw); + +#print "The rig's mode is: $get_mode\n"; +#print "The rig's bandwidth is: $get_bw\n"; print "The rig's mode is: $answer[0]"; print "The rig's bandwidth is: $answer[1]"; print "\n"; # Now set the rig's frequency -print "Setting the rig's frequency to: $freq\n"; -print $socket "F $freq\n"; -print $socket "f\n"; -@answer = get_results($socket); -print "The rig's frequency is now: $answer[0]"; -print "\n"; +#print "Setting the rig's frequency to: $set_freq\n"; +#print $socket "F $set_freq\n"; +#<$socket>; +#print $socket "f\n"; +#@answer = get_results($socket); +#$get_freq = <$socket>; +#chomp($get_freq); +#print "The rig's frequency is now: $get_freq\n"; +#print "\n"; # Setting the mode takes two parameters, mode and bandwidth -print "Setting the rig's mode to $mode and bandwidth to $bw\n"; -print $socket "\\set_mode $mode $bw\n"; -print $socket "\\get_mode\n"; -@answer = get_results($socket); -print "The rig's mode is now: $answer[0]"; -print "The rig's bandwidth is now: $answer[1]"; -print "\n"; +#print "Setting the rig's mode to $set_mode and bandwidth to $set_bw\n"; +#print $socket "\\set_mode $set_mode $set_bw\n"; +#<$socket>; +#print $socket "\\get_mode\n"; +#@answer = get_results($socket); +#$get_mode = <$socket>; +#chomp($get_mode); +#$get_bw = <$socket>; +#chomp($get_bw); +#print "The rig's mode is now: $get_mode\n"; +#print "The rig's bandwidth is now: $get_bw\n"; +#print "\n"; # Close the connection before we exit. close($socket); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |