From 58f2549a994062c5e3b3f68e93f349ef8e6cdfd8 Mon Sep 17 00:00:00 2001 From: Mike Black W9MDB Date: Sat, 26 Nov 2022 15:19:23 -0600 Subject: [PATCH] Change rigctl send_raw to also require terminator https://github.com/Hamlib/Hamlib/issues/1157 --- NEWS | 2 +- doc/man1/rigctl.1 | 9 ++++++--- simulators/simicom9700.c | 14 ++++++++++++++ simulators/simpowersdr.c | 12 ++++++++++++ src/rig.c | 2 ++ tests/rigctl_parse.c | 32 ++++++++++++++++++++++---------- 6 files changed, 57 insertions(+), 14 deletions(-) diff --git a/NEWS b/NEWS index f6b4d9a2f..fc6e002d7 100644 --- a/NEWS +++ b/NEWS @@ -18,7 +18,7 @@ Version 4.6 Version 4.5.1 * 2022-XX-XX - * Added send_raw to rigctl + * Added send_raw to rigctl -- see rigctl man page * Fix AGC Level dumpcaps on most rigs * Fix rig_send_raw to return bytes read, fill buffer, and also work with fixed length response/null terminator * Change all Kenwood rigs to 500ms serial timeout diff --git a/doc/man1/rigctl.1 b/doc/man1/rigctl.1 index 9deedf737..772173bef 100644 --- a/doc/man1/rigctl.1 +++ b/doc/man1/rigctl.1 @@ -1289,12 +1289,15 @@ CW Skimmer is started and "set_lock_mode 0" when CW Skimmer is stopped. Returns current lock mode status 1=On, 2=Off (only useful when using rigctld) . .TP -.BR send_raw " \(aq" \fIString\fp \(aq +.BR send_raw " \(aq" \fITerminator\fP "\(aq \(aq" \fIString\fp \(aq .EX Can send ASCII string or 0xnn values -- there can be no spaces in the command string. +Possible terminator values are CR, LF, ;, ICOM, 0-100 (bytes to read), or -1 meaning unknown (will timeout on read) Examples: - send_raw FA;MD; - send_raw 0x40;0x32;0x32;0x00 + send_raw ; FA;MD; + send_raw icom 0xFE;0xFE;0x94;0x03;0xFD + send_raw -1 0xFE;0xFE;0x94;0x03;0xFD + send_raw 14 0xFE;0xFE;0x94;0x03;0xFD . .SH READLINE . diff --git a/simulators/simicom9700.c b/simulators/simicom9700.c index 3af7015c5..291c34e1b 100644 --- a/simulators/simicom9700.c +++ b/simulators/simicom9700.c @@ -381,6 +381,20 @@ void frameParse(int fd, unsigned char *frame, int len) } frame[11] = 0xfd; + unsigned char frame2[11]; + + frame2[0] = 0xfe; + frame2[1] = 0xfe; + frame2[2] = 0x00; // send transceive frame + frame2[3] = frame[3]; // send transceive frame + frame2[4] = 0x00; + frame2[5] = 0x70; + frame2[6] = 0x28; + frame2[7] = 0x57; + frame2[8] = 0x03; + frame2[9] = 0x00; + frame2[10] = 0xfd; + n = write(fd, frame2, 11); n = write(fd, frame, 12); } else diff --git a/simulators/simpowersdr.c b/simulators/simpowersdr.c index a059c80b7..4c8d4ac49 100644 --- a/simulators/simpowersdr.c +++ b/simulators/simpowersdr.c @@ -274,6 +274,18 @@ int main(int argc, char *argv[]) n = write(fd, buf, strlen(buf)); continue; } + else if (strncmp(buf,"ZZFL;", 5)==0) + { + SNPRINTF(buf, sizeof(buf), "ZZFL+%04d;", 100); + n = write(fd, buf, strlen(buf)); + continue; + } + else if (strncmp(buf,"ZZFH;", 5)==0) + { + SNPRINTF(buf, sizeof(buf), "ZZFH+%04d;", 3500); + n = write(fd, buf, strlen(buf)); + continue; + } else if (strncmp(buf, "FL", 2) == 0) { sscanf(buf, "FL%d", &filternum); diff --git a/src/rig.c b/src/rig.c index 5a351f4f1..7c2de601d 100644 --- a/src/rig.c +++ b/src/rig.c @@ -7421,6 +7421,7 @@ HAMLIB_EXPORT(int) rig_send_raw(RIG *rig, const unsigned char *send, rig->caps->model_name); return -RIG_ENAVAIL; } + ELAPSED1; rig_debug(RIG_DEBUG_VERBOSE, "%s: writing %d bytes\n", __func__, send_len); int retval = write_block_sync(&rs->rigport, send, send_len); @@ -7482,6 +7483,7 @@ HAMLIB_EXPORT(int) rig_send_raw(RIG *rig, const unsigned char *send, { RETURNFUNC(retval); } + ELAPSED2; RETURNFUNC(nbytes > 0 ? nbytes : -RIG_EPROTO); } diff --git a/tests/rigctl_parse.c b/tests/rigctl_parse.c index f9b9332df..73e494618 100644 --- a/tests/rigctl_parse.c +++ b/tests/rigctl_parse.c @@ -371,7 +371,7 @@ static struct test_table test_list[] = { 0xa1, "get_separator", ACTION(get_separator), ARG_NOVFO, "Separator" }, { 0xa2, "set_lock_mode", ACTION(set_lock_mode), ARG_IN | ARG_NOVFO, "Locked" }, { 0xa3, "get_lock_mode", ACTION(get_lock_mode), ARG_NOVFO, "Locked" }, - { 0xa4, "send_raw", ACTION(send_raw), ARG_NOVFO | ARG_IN | ARG_OUT, "Send raw answer" }, + { 0xa4, "send_raw", ACTION(send_raw), ARG_NOVFO | ARG_IN1 | ARG_IN2 | ARG_OUT3, "Terminator", "Command","Send raw answer" }, { 0x00, "", NULL }, }; @@ -1728,7 +1728,7 @@ readline_repeat: else { - if ((rig_powerstat == RIG_POWER_OFF || rig_powerstat == RIG_POWER_STANDBY)) + if (my_rig->caps->set_powerstat && (rig_powerstat == RIG_POWER_OFF || rig_powerstat == RIG_POWER_STANDBY)) { rig_debug(RIG_DEBUG_VERBOSE, "%s: rig_powerstat is not on = %d\n", __func__, rig_powerstat); @@ -5369,27 +5369,39 @@ static int parse_hex(const char *s, unsigned char *buf, int len) declare_proto_rig(send_raw) { int reply_len; - unsigned char term[] = ";"; + unsigned char term[1]; unsigned char buf[100]; unsigned char send[100]; - unsigned char *sendp = (unsigned char *)arg1; - int arg1_len = strlen(arg1); + unsigned char *sendp = (unsigned char *)arg2; + int arg2_len = strlen(arg2); int hex_flag = 0; + int buf_len = sizeof(buf); + int val = 0; - if (strncmp(arg1, "0x", 2) == 0) + if (strcmp(arg1, ";")==0) term[0] = ';'; + else if (strcasecmp(arg1, "CR")) term[0] = 0x0d; + else if (strcasecmp(arg1, "LF")) term[0] = 0x0a; + else if (strcasecmp(arg1, "ICOM")) term[0] = 0xfd; + else if (sscanf(arg1,"%d",&val)==1) { term[0]=0; buf_len = val;} + else { + rig_debug(RIG_DEBUG_ERR, "%s: unknown arg1 val=%s, expected ';' 'CR' 'LF' 'ICOM' or # of bytes where 0 means no reply and -1 means unknown", __func__, arg1); + return -RIG_EINVAL; + } + if (strncmp(arg2, "0x", 2) == 0) { - arg1_len = parse_hex(arg1, send, sizeof(send)); + arg2_len = parse_hex(arg2, send, sizeof(send)); sendp = send; hex_flag = 1; } rig_debug(RIG_DEBUG_TRACE, "%s:\n", __func__); - reply_len = rig_send_raw(rig, (unsigned char *)sendp, arg1_len, buf, - sizeof(buf), term); + reply_len = rig_send_raw(rig, (unsigned char *)sendp, arg2_len, buf, + buf_len, term); + buf[buf_len+1] = 0; // null terminate in case it's a string if ((interactive && prompt) || (interactive && !prompt && ext_resp)) { - fprintf(fout, "%s: ", cmd->arg1); + fprintf(fout, "%s: ", cmd->arg3); } if (reply_len == 0)