diff --git a/.github/codeql-analysis.yml b/.github/codeql-analysis.yml index 9b72a599a..0a1390055 100644 --- a/.github/codeql-analysis.yml +++ b/.github/codeql-analysis.yml @@ -29,7 +29,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@v1 + uses: github/codeql-action/init@v2 # Override language selection by uncommenting this and choosing your languages # with: # languages: go, javascript, csharp, python, cpp, java @@ -37,7 +37,7 @@ jobs: # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). # If this step fails, then you should remove it and run the build manually (see below) #- name: Autobuild - # uses: github/codeql-action/autobuild@v1 + # uses: github/codeql-action/autobuild@v2 # â„šī¸ Command-line programs to run using the OS shell. # 📚 https://git.io/JvXDl @@ -52,4 +52,4 @@ jobs: make - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v1 + uses: github/codeql-action/analyze@v2 diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 4cac2720d..159b6aadc 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -43,7 +43,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@v1 + uses: github/codeql-action/init@v2 with: languages: ${{ matrix.language }} # If you wish to specify custom queries, you can do so here or in a config file. @@ -54,7 +54,7 @@ jobs: # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). # If this step fails, then you should remove it and run the build manually (see below) #- name: Autobuild - # uses: github/codeql-action/autobuild@v1 + # uses: github/codeql-action/autobuild@v2 # â„šī¸ Command-line programs to run using the OS shell. # 📚 https://git.io/JvXDl @@ -70,4 +70,4 @@ jobs: make - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v1 + uses: github/codeql-action/analyze@v2 diff --git a/NEWS b/NEWS index 234db18b0..74d652200 100644 --- a/NEWS +++ b/NEWS @@ -18,6 +18,9 @@ Version 4.6 Version 4.5.1 * 2022-XX-XX + * Add missing meter reading to TS-890S -- thanks to Geore Baltz N3GB + * Fix FT736 VFOB freq and mode set + * 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/include/hamlib/rotlist.h b/include/hamlib/rotlist.h index 0dbd16f4d..2ede3f893 100644 --- a/include/hamlib/rotlist.h +++ b/include/hamlib/rotlist.h @@ -325,7 +325,9 @@ #define ROT_MODEL_GS232B_EL ROT_MAKE_MODEL(ROT_GS232A, 12) #define ROT_MODEL_GS23_AZ ROT_MAKE_MODEL(ROT_GS232A, 13) - +#define ROT_ARRAYSOLUTIONS 7 +#define ROT_BACKEND ARRAYSOLUTIONS "arraysolutions" +#define ROT_MODEL_ARRAYSOLUTIONS_SAL_12_20_30 ROT_MAKE_MODEL(ROT_ARRAYSOLUTIONS, 1) /** * \brief A macro that returns the model number of the PCROTOR backend. * diff --git a/rigs/alinco/dx77.c b/rigs/alinco/dx77.c index d66988d8d..bacb7ef2a 100644 --- a/rigs/alinco/dx77.c +++ b/rigs/alinco/dx77.c @@ -156,7 +156,7 @@ const struct rig_caps dx77_caps = RIG_MODEL(RIG_MODEL_DX77), .model_name = "DX-77", .mfg_name = "Alinco", - .version = BACKEND_VER ".0", + .version = BACKEND_VER ".1", .copyright = "LGPL", .status = RIG_STATUS_STABLE, .rig_type = RIG_TYPE_TRANSCEIVER, @@ -214,7 +214,6 @@ const struct rig_caps dx77_caps = }, RIG_FRNG_END, }, - .rx_range_list2 = {RIG_FRNG_END,}, .tx_range_list1 = {RIG_FRNG_END,}, .tx_range_list2 = {RIG_FRNG_END,}, diff --git a/rigs/dummy/dummy.c b/rigs/dummy/dummy.c index f9eec63e5..f85b040e1 100644 --- a/rigs/dummy/dummy.c +++ b/rigs/dummy/dummy.c @@ -425,7 +425,7 @@ static int dummy_set_freq(RIG *rig, vfo_t vfo, freq_t freq) if (vfo == RIG_VFO_CURR) { vfo = priv->curr_vfo; } - if (vfo == RIG_VFO_CURR || RIG_VFO_TX) { vfo = vfo_fixup(rig, vfo, rig->state.cache.split); } + if (vfo == RIG_VFO_CURR || vfo == RIG_VFO_TX) { vfo = vfo_fixup(rig, vfo, rig->state.cache.split); } // if needed for testing enable this to emulate a rig with 100hz resolution #if 0 @@ -2271,7 +2271,7 @@ struct rig_caps dummy_caps = RIG_MODEL(RIG_MODEL_DUMMY), .model_name = "Dummy", .mfg_name = "Hamlib", - .version = "20221106.0", + .version = "20221128.0", .copyright = "LGPL", .status = RIG_STATUS_STABLE, .rig_type = RIG_TYPE_OTHER, diff --git a/rigs/icom/ic706.c b/rigs/icom/ic706.c index 6702a1ba6..a977e47ba 100644 --- a/rigs/icom/ic706.c +++ b/rigs/icom/ic706.c @@ -496,8 +496,6 @@ const struct rig_caps ic706mkiig_caps = .level_gran = { #include "level_gran_icom.h" - // cppcheck-suppress * - [LVL_RAWSTR] = { .min = { .i = 0 }, .max = { .i = 255 } }, }, .parm_gran = {}, .ctcss_list = common_ctcss_list, diff --git a/rigs/icom/xiegu.c b/rigs/icom/xiegu.c index ef4e3ea58..0ea13d1cb 100644 --- a/rigs/icom/xiegu.c +++ b/rigs/icom/xiegu.c @@ -365,7 +365,6 @@ const struct rig_caps x6100_caps = .max_rit = Hz(9999), .max_xit = Hz(9999), .max_ifshift = Hz(0), /* TODO */ - .targetable_vfo = 0, .vfo_ops = X108G_VFO_OPS, .targetable_vfo = RIG_TARGETABLE_FREQ | RIG_TARGETABLE_MODE, .scan_ops = X108G_SCAN_OPS, @@ -508,7 +507,7 @@ const struct rig_caps g90_caps = RIG_MODEL(RIG_MODEL_G90), .model_name = "G90", .mfg_name = "Xiegu", - .version = BACKEND_VER ".3", + .version = BACKEND_VER ".4", .copyright = "LGPL", .status = RIG_STATUS_STABLE, .rig_type = RIG_TYPE_TRANSCEIVER, diff --git a/rigs/kenwood/k3.c b/rigs/kenwood/k3.c index 64a9305ec..fa85a7d67 100644 --- a/rigs/kenwood/k3.c +++ b/rigs/kenwood/k3.c @@ -25,6 +25,7 @@ #include #include +#include #include #include "idx_builtin.h" @@ -187,7 +188,7 @@ const struct rig_caps k3_caps = RIG_MODEL(RIG_MODEL_K3), .model_name = "K3", .mfg_name = "Elecraft", - .version = BACKEND_VER ".23", + .version = BACKEND_VER ".24", .copyright = "LGPL", .status = RIG_STATUS_STABLE, .rig_type = RIG_TYPE_TRANSCEIVER, @@ -2784,7 +2785,7 @@ int k3_set_freq(RIG *rig, vfo_t vfo, freq_t freq) // if more than 1MHz probably a band change so give it some time // before continuing - if (abs((long)(tfreq - freq)) > 1e6) + if (fabs(tfreq - freq) > 1e6) { hl_usleep(200 * 1000); // give 200ms for rig to do band switch if needed } diff --git a/rigs/kenwood/kenwood.c b/rigs/kenwood/kenwood.c index 96d07ce39..055bb3e17 100644 --- a/rigs/kenwood/kenwood.c +++ b/rigs/kenwood/kenwood.c @@ -245,7 +245,8 @@ int kenwood_transaction(RIG *rig, const char *cmdstr, char *data, struct kenwood_priv_caps *caps = kenwood_caps(rig); struct rig_state *rs; - rig_debug(RIG_DEBUG_VERBOSE, "%s called cmd=%s datasize=%d\n", __func__, cmdstr, + rig_debug(RIG_DEBUG_VERBOSE, "%s called cmd=%s datasize=%d\n", __func__, + cmdstr ? cmdstr : "(NULL)", (int)datasize); if ((!cmdstr && !datasize) || (datasize && !data)) @@ -261,7 +262,7 @@ int kenwood_transaction(RIG *rig, const char *cmdstr, char *data, if (priv->is_emulation) { rs->rigport.post_write_delay = 0; } // if this is an IF cmdstr and not the first time through check cache - if (strcmp(cmdstr, "IF") == 0 && priv->cache_start.tv_sec != 0) + if (cmdstr && strcmp(cmdstr, "IF") == 0 && priv->cache_start.tv_sec != 0) { int cache_age_ms; @@ -280,8 +281,8 @@ int kenwood_transaction(RIG *rig, const char *cmdstr, char *data, // else we drop through and do the real IF command } - if (strlen(cmdstr) > 2 || strcmp(cmdstr, "RX") == 0 - || strncmp(cmdstr, "TX", 2) == 0 || strncmp(cmdstr, "ZZTX", 4) == 0) + if (cmdstr && (strlen(cmdstr) > 2 || strcmp(cmdstr, "RX") == 0 + || strncmp(cmdstr, "TX", 2) == 0 || strncmp(cmdstr, "ZZTX", 4)) == 0) { // then we must be setting something so we'll invalidate the cache rig_debug(RIG_DEBUG_TRACE, "%s: cache invalidated\n", __func__); @@ -613,7 +614,7 @@ transaction_read: transaction_quit: // update the cache - if (retval == RIG_OK && strcmp(cmdstr, "IF") == 0) + if (retval == RIG_OK && cmdstr && strcmp(cmdstr, "IF") == 0) { elapsed_ms(&priv->cache_start, HAMLIB_ELAPSED_SET); strncpy(priv->last_if_response, buffer, caps->if_len); @@ -3407,6 +3408,7 @@ int kenwood_get_level(RIG *rig, vfo_t vfo, setting_t level, value_t *val) switch (level) { int power_now, power_min, power_max; + int min_pitch, step_pitch; /* Hz */ case RIG_LEVEL_RAWSTR: if (RIG_IS_TS590S || RIG_IS_TS590SG) @@ -3739,15 +3741,29 @@ int kenwood_get_level(RIG *rig, vfo_t vfo, setting_t level, value_t *val) break; case RIG_LEVEL_CWPITCH: - retval = kenwood_safe_transaction(rig, "PT", lvlbuf, 50, 4); + if (RIG_IS_TS890S) + { + len = 5; + min_pitch = 300; + step_pitch = 5; + } + else + { + len = 4; + min_pitch = 400; + step_pitch = 50; + } + + retval = kenwood_safe_transaction(rig, "PT", lvlbuf, 50, len); if (retval != RIG_OK) { RETURNFUNC(retval); } - sscanf(lvlbuf + 2, "%d", &val->i); - val->i = (val->i * 1000) + 1000; /* 00 - 08 */ + sscanf(lvlbuf + 2, "%d", &val->i); /* 00 - 12 or 000 - 160 */ + val->i = (val->i * step_pitch) + min_pitch; /* 400 - 1000 or 300 - 1100 + */ break; case RIG_LEVEL_KEYSPD: diff --git a/rigs/kenwood/kenwood.h b/rigs/kenwood/kenwood.h index 120259350..e72787717 100644 --- a/rigs/kenwood/kenwood.h +++ b/rigs/kenwood/kenwood.h @@ -29,7 +29,7 @@ #include "misc.h" #include "idx_builtin.h" -#define BACKEND_VER "20221124" +#define BACKEND_VER "20221128" #define EOM_KEN ';' #define EOM_TH '\r' diff --git a/rigs/kenwood/ts890s.c b/rigs/kenwood/ts890s.c index e4350ee7b..bfcd067fc 100644 --- a/rigs/kenwood/ts890s.c +++ b/rigs/kenwood/ts890s.c @@ -36,8 +36,9 @@ #define TS890_AM_TX_MODES RIG_MODE_AM // TODO: Copied from TS-480, to be verified -#define TS890_LEVEL_ALL (RIG_LEVEL_RFPOWER|RIG_LEVEL_AF|RIG_LEVEL_RF|RIG_LEVEL_SQL|RIG_LEVEL_AGC|RIG_LEVEL_KEYSPD) -#define TS890_FUNC_ALL (RIG_FUNC_NB|RIG_FUNC_NB2|RIG_FUNC_COMP|RIG_FUNC_VOX|RIG_FUNC_NR|RIG_FUNC_NR|RIG_FUNC_BC|RIG_FUNC_BC2|RIG_FUNC_RIT|RIG_FUNC_XIT|RIG_FUNC_TUNER|RIG_FUNC_SEND_MORSE) +#define TS890_LEVEL_SET (RIG_LEVEL_RFPOWER|RIG_LEVEL_AF|RIG_LEVEL_RF|RIG_LEVEL_SQL|RIG_LEVEL_AGC|RIG_LEVEL_KEYSPD|RIG_LEVEL_CWPITCH) +#define TS890_LEVEL_GET (RIG_LEVEL_RFPOWER|RIG_LEVEL_AF|RIG_LEVEL_RF|RIG_LEVEL_SQL|RIG_LEVEL_AGC|RIG_LEVEL_KEYSPD|RIG_LEVEL_ALC|RIG_LEVEL_SWR|RIG_LEVEL_COMP_METER|RIG_LEVEL_ID_METER|RIG_LEVEL_VD_METER|RIG_LEVEL_TEMP_METER|RIG_LEVEL_CWPITCH) +#define TS890_FUNC_ALL (RIG_FUNC_NB|RIG_FUNC_NB2|RIG_FUNC_COMP|RIG_FUNC_VOX|RIG_FUNC_NR|RIG_FUNC_BC|RIG_FUNC_BC2|RIG_FUNC_RIT|RIG_FUNC_XIT|RIG_FUNC_TUNER|RIG_FUNC_SEND_MORSE) #define TS890_VFO_OPS (RIG_OP_UP|RIG_OP_DOWN|RIG_OP_BAND_UP|RIG_OP_BAND_DOWN|RIG_OP_CPY|RIG_OP_TUNE) @@ -95,6 +96,19 @@ int kenwood_ts890_set_level(RIG *rig, vfo_t vfo, setting_t level, value_t val) SNPRINTF(levelbuf, sizeof(levelbuf), "GC%d", kenwood_val); break; + case RIG_LEVEL_CWPITCH: + + // TODO: Merge this and formatting difference into kenwood.c + if (val.i < 300 || val.i > 1100) + { + return -RIG_EINVAL; + } + + /* 300 - 1100 Hz -> 000 - 160 */ + kenwood_val = (val.i - 298) / 5; /* Round to nearest 5Hz */ + SNPRINTF(levelbuf, sizeof(levelbuf), "PT%03d", kenwood_val); + break; + default: return kenwood_set_level(rig, vfo, level, val); } @@ -102,6 +116,55 @@ int kenwood_ts890_set_level(RIG *rig, vfo_t vfo, setting_t level, value_t val) return kenwood_transaction(rig, levelbuf, NULL, 0); } +/* Helper to get and parse meter values using RM + * Note that we turn readings on, but nothing off. + * 'pips' is the number of LED bars lit in the digital meter, max=70 + */ +static +int ts890_get_meter_reading(RIG *rig, char meter, int *pips) +{ + char reading[9]; /* 8 char + '\0' */ + int retval; + char target[] = "RMx1"; /* Turn on reading this meter */ + + target[2] = meter; + retval = kenwood_transaction(rig, target, NULL, 0); + + if (retval != RIG_OK) + { + return retval; + } + + /* Read the first value */ + retval = kenwood_transaction(rig, "RM", reading, sizeof(reading)); + + if (retval != RIG_OK) + { + return retval; + } + + /* Find the one we want */ + while (strncmp(reading, target, 3) != 0) + { + /* That wasn't it, get the next one */ + retval = kenwood_transaction(rig, NULL, reading, sizeof(reading)); + + if (retval != RIG_OK) + { + return retval; + } + + if (reading[0] != target[0] || reading[1] != target[1]) + { + /* Somebody else's data, bail */ + return -RIG_EPROTO; + } + } + + sscanf(reading + 3, "%4d", pips); + return RIG_OK; + +} int kenwood_ts890_get_level(RIG *rig, vfo_t vfo, setting_t level, value_t *val) { @@ -114,6 +177,7 @@ int kenwood_ts890_get_level(RIG *rig, vfo_t vfo, setting_t level, value_t *val) switch (level) { + // TODO: This doesn't appear in TS890_LEVEL_GET - should it? case RIG_LEVEL_VOXDELAY: retval = kenwood_safe_transaction(rig, "VD0", ackbuf, sizeof(ackbuf), 6); @@ -219,6 +283,94 @@ int kenwood_ts890_get_level(RIG *rig, vfo_t vfo, setting_t level, value_t *val) return RIG_OK; + case RIG_LEVEL_ALC: + retval = ts890_get_meter_reading(rig, '1', &levelint); + + if (retval != RIG_OK) + { + return retval; + } + + val->f = (float)levelint / 35.0; /* Half scale [0,35] -> [0.0,1.0] */ + return RIG_OK; + + case RIG_LEVEL_SWR: + retval = ts890_get_meter_reading(rig, '2', &levelint); + + if (retval != RIG_OK) + { + return retval; + } + + if (levelint < 0 || levelint >= 70) + { + val->f = 99.0; /* 99 == infinty */ + } + else + { +#if 0 + val->f = 70.0 / (70 - levelint); +#else + + /* Linear approximations of a very non-linear function */ + if (levelint < 12) { val->f = 1.0 + (float)levelint / 22.0; } + else if (levelint < 24) { val->f = 1.5 + (float)(levelint - 11) / 24.0; } + else if (levelint < 36) { val->f = 2.0 + (float)(levelint - 23) / 12.0; } + else { val->f = 3.0 + (float)(levelint - 35) / 6.0; } + +#endif + } + + return RIG_OK; + + case RIG_LEVEL_COMP_METER: + retval = ts890_get_meter_reading(rig, '3', &levelint); + + if (retval != RIG_OK) + { + return retval; + } + + if (levelint < 21) { val->f = (float)levelint / 2.0; } /* db */ + else if (levelint < 51) { val->f = 10.0 + (float)(levelint - 20) / 3.0; } + else { val->f = 20.0 + (float)(levelint - 50) / 4.0; } + + return RIG_OK; + + case RIG_LEVEL_ID_METER: + retval = ts890_get_meter_reading(rig, '4', &levelint); + + if (retval != RIG_OK) + { + return retval; + } + + val->f = (20.0 * (float)levelint) / 70.0; /* amperes */ + return RIG_OK; + + case RIG_LEVEL_VD_METER: + retval = ts890_get_meter_reading(rig, '5', &levelint); + + if (retval != RIG_OK) + { + return retval; + } + + val->f = (15.0 * (float)levelint) / 65.0; /* volts */ + return RIG_OK; + + case RIG_LEVEL_TEMP_METER: +#if 0 + retval = ts890_get_meter_reading(rig, '6', &levelint); + + if (retval != RIG_OK) + { + return retval; + } + +#endif + return -RIG_ENIMPL; + default: return kenwood_get_level(rig, vfo, level, val); } @@ -241,7 +393,7 @@ const struct rig_caps ts890s_caps = RIG_MODEL(RIG_MODEL_TS890S), .model_name = "TS-890S", .mfg_name = "Kenwood", - .version = BACKEND_VER ".6", + .version = BACKEND_VER ".7", .copyright = "LGPL", .status = RIG_STATUS_STABLE, .rig_type = RIG_TYPE_TRANSCEIVER, @@ -380,8 +532,8 @@ const struct rig_caps ts890s_caps = .send_morse = kenwood_send_morse, .wait_morse = rig_wait_morse, .scan = kenwood_scan, /* not working, invalid arguments using rigctl; kenwood_scan does only support on/off and not tone and CTCSS scan */ - .has_set_level = TS890_LEVEL_ALL, - .has_get_level = TS890_LEVEL_ALL, + .has_set_level = TS890_LEVEL_SET, + .has_get_level = TS890_LEVEL_GET, .set_level = kenwood_ts890_set_level, .get_level = kenwood_ts890_get_level, .level_gran = diff --git a/rigs/kit/fifisdr.c b/rigs/kit/fifisdr.c index 7f91bc315..1ab678736 100644 --- a/rigs/kit/fifisdr.c +++ b/rigs/kit/fifisdr.c @@ -653,7 +653,7 @@ static int fifisdr_set_level(RIG *rig, vfo_t vfo, setting_t level, value_t val) /* Transform Hamlib enum value to FiFi-SDR selector */ fifi_agc = 0; - switch ((enum agc_level_e)val.i) + switch (val.i) { case RIG_AGC_OFF: fifi_agc = 0; break; diff --git a/rigs/mds/9710.c b/rigs/mds/9710.c index 5bd40740c..f380dbc79 100644 --- a/rigs/mds/9710.c +++ b/rigs/mds/9710.c @@ -45,6 +45,9 @@ const struct rig_caps mds_9710_caps = .rx_range_list1 = { { .startf = MHz(800), .endf = MHz(880), .modes = MDS_ALL_MODES, + .low_power = 0, .high_power = 0, MDS_ALL_MODES, RIG_ANT_1, + }, + { .startf = MHz(880), .endf = MHz(960), .modes = MDS_ALL_MODES, .low_power = 0, .high_power = 0, MDS_ALL_MODES, RIG_ANT_1, }, diff --git a/rigs/yaesu/ft736.c b/rigs/yaesu/ft736.c index cd56e95eb..eda6cea0c 100644 --- a/rigs/yaesu/ft736.c +++ b/rigs/yaesu/ft736.c @@ -98,7 +98,7 @@ const struct rig_caps ft736_caps = RIG_MODEL(RIG_MODEL_FT736R), .model_name = "FT-736R", .mfg_name = "Yaesu", - .version = "20210221.0", + .version = "20211271.0", .copyright = "LGPL", .status = RIG_STATUS_STABLE, .rig_type = RIG_TYPE_TRANSCEIVER, @@ -132,7 +132,7 @@ const struct rig_caps ft736_caps = .max_rit = Hz(0), .max_xit = Hz(0), .max_ifshift = Hz(0), - .targetable_vfo = RIG_TARGETABLE_FREQ, + .targetable_vfo = RIG_TARGETABLE_FREQ | RIG_TARGETABLE_MODE, .transceive = RIG_TRN_OFF, .bank_qty = 0, .chan_desc_sz = 0, @@ -269,6 +269,9 @@ int ft736_set_freq(RIG *rig, vfo_t vfo, freq_t freq) unsigned char cmd[YAESU_CMD_LENGTH] = { 0x00, 0x00, 0x00, 0x00, 0x01}; struct ft736_priv_data *priv = (struct ft736_priv_data *)rig->state.priv; + // we will assume requesting to set VFOB is split mode + if (vfo == RIG_VFO_B) { return rig_set_split_freq(rig, vfo, freq); } + if (priv->split == RIG_SPLIT_ON) { cmd[4] = 0x1e; @@ -302,6 +305,8 @@ int ft736_set_mode(RIG *rig, vfo_t vfo, rmode_t mode, pbwidth_t width) unsigned char md; struct ft736_priv_data *priv = (struct ft736_priv_data *)rig->state.priv; + if (vfo == RIG_VFO_B) { return ft736_set_split_mode(rig, vfo, mode, width); } + if (priv->split == RIG_SPLIT_ON) { cmd[4] = 0x17; diff --git a/simulators/simicom9700.c b/simulators/simicom9700.c index 3af7015c5..25f8996b2 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..2f258374a 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 d014f0606..03e5c7879 100644 --- a/src/rig.c +++ b/src/rig.c @@ -7414,12 +7414,18 @@ HAMLIB_EXPORT(int) rig_send_raw(RIG *rig, const unsigned char *send, int nbytes; ENTERFUNC; - if (rig->caps->rig_model == RIG_MODEL_DUMMY || rig->caps->rig_model == RIG_MODEL_NONE) + if (rig->caps->rig_model == RIG_MODEL_DUMMY + || rig->caps->rig_model == RIG_MODEL_NONE) { - rig_debug(RIG_DEBUG_ERR, "%s: not implemented for model %s\n", __func__, rig->caps->model_name); + rig_debug(RIG_DEBUG_ERR, "%s: not implemented for model %s\n", __func__, + rig->caps->model_name); return -RIG_ENAVAIL; } - int retval = write_block_sync(&rs->rigport, send, send_len); + + ELAPSED1; + + rig_debug(RIG_DEBUG_VERBOSE, "%s: writing %d bytes\n", __func__, send_len); + int retval = write_block(&rs->rigport, send, send_len); if (retval < 0) { @@ -7440,23 +7446,27 @@ HAMLIB_EXPORT(int) rig_send_raw(RIG *rig, const unsigned char *send, if (*term == 0xfd) // then we want an Icom frame { + rig_debug(RIG_DEBUG_VERBOSE, "%s: reading icom frame\n", __func__); retval = read_icom_frame(&rs->rigport, buf, sizeof(buf)); nbytes = retval; } else if (term == NULL) { + rig_debug(RIG_DEBUG_VERBOSE, "%s: reading binary frame\n", __func__); nbytes = read_string_direct(&rs->rigport, buf, reply_len, (const char *)term, 1, 0, 1); } else // we'll assume the provided terminator works { + rig_debug(RIG_DEBUG_VERBOSE, "%s: reading frame terminated by '%s'\n", __func__, + term); nbytes = read_string_direct(&rs->rigport, buf, sizeof(buf), (const char *)term, 1, 0, 1); } if (retval < RIG_OK) { - rig_debug(RIG_DEBUG_ERR, "%s: write_block_sync() failed, result=%d\n", __func__, + rig_debug(RIG_DEBUG_ERR, "%s: read_string_direct, result=%d\n", __func__, retval); RETURNFUNC(retval); } @@ -7475,6 +7485,8 @@ HAMLIB_EXPORT(int) rig_send_raw(RIG *rig, const unsigned char *send, RETURNFUNC(retval); } + ELAPSED2; + RETURNFUNC(nbytes > 0 ? nbytes : -RIG_EPROTO); } diff --git a/src/sprintflst.c b/src/sprintflst.c index 0e4ed55a2..07e3c347c 100644 --- a/src/sprintflst.c +++ b/src/sprintflst.c @@ -919,7 +919,8 @@ int rig_sprintf_agc_levels(RIG *rig, char *str, int lenstr) { if (strlen(str) > 0) { strcat(str, " "); } - sprintf(tmpbuf, "%d=%s", priv_caps->agc_levels[i].icom_level, rig_stragclevel(priv_caps->agc_levels[i].level)); + sprintf(tmpbuf, "%d=%s", priv_caps->agc_levels[i].icom_level, + rig_stragclevel(priv_caps->agc_levels[i].level)); if (strlen(str) + strlen(tmpbuf) < lenstr - 1) { @@ -927,8 +928,8 @@ int rig_sprintf_agc_levels(RIG *rig, char *str, int lenstr) } else { - rig_debug(RIG_DEBUG_ERR, "%s: buffer overrun!! len=%ld > maxlen=%d\n", - __func__, strlen(str) + strlen(tmpbuf), lenstr - 1); + rig_debug(RIG_DEBUG_ERR, "%s: buffer overrun!! len=%d > maxlen=%d\n", + __func__, (int)(strlen(str) + strlen(tmpbuf)), lenstr - 1); } } } @@ -947,8 +948,8 @@ int rig_sprintf_agc_levels(RIG *rig, char *str, int lenstr) } else { - rig_debug(RIG_DEBUG_ERR, "%s: buffer overrun!! len=%ld > maxlen=%d\n", - __func__, strlen(str) + strlen(tmpbuf), lenstr - 1); + rig_debug(RIG_DEBUG_ERR, "%s: buffer overrun!! len=%d > maxlen=%d\n", + __func__, (int)(strlen(str) + strlen(tmpbuf)), lenstr - 1); } } } diff --git a/tests/ampctl_parse.c b/tests/ampctl_parse.c index 2a9e9e7b4..838b6272b 100644 --- a/tests/ampctl_parse.c +++ b/tests/ampctl_parse.c @@ -1476,6 +1476,7 @@ void usage_amp(FILE *fout) { nbspaces -= fprintf(fout, ", %s", test_list[i].arg4); } + rig_debug(RIG_DEBUG_VERBOSE, "%s: nbspace left=%d\n", __func__, nbspaces); fprintf(fout, ")\n"); } diff --git a/tests/rigctl_parse.c b/tests/rigctl_parse.c index 2fa9ab971..b8689f41d 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 command" }, + { 0xa4, "send_raw", ACTION(send_raw), ARG_NOVFO | ARG_IN1 | ARG_IN2 | ARG_OUT3, "Terminator", "Command", "Send raw answer" }, { 0x00, "", NULL }, }; @@ -665,7 +665,7 @@ int rigctl_parse(RIG *my_rig, FILE *fin, FILE *fout, char *argv[], int argc, int interactive, int prompt, int *vfo_opt, char send_cmd_term, int *ext_resp_ptr, char *resp_sep_ptr, int use_password) { - int retcode; /* generic return code from functions */ + int retcode = -RIG_EINTERNAL; /* generic return code from functions */ unsigned char cmd; struct test_table *cmd_entry = NULL; @@ -1728,15 +1728,21 @@ 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); // Update power status powerstat_t stat = RIG_POWER_ON; retcode = rig_get_powerstat(my_rig, &stat); if (retcode == RIG_OK) { rig_powerstat = stat; } + + if (rig_powerstat != RIG_POWER_ON) + { + rig_debug(RIG_DEBUG_ERR, + "%s: rig_powerstat is not on = %d\n", __func__, + rig_powerstat); + } } // Allow only certain commands when the rig is powered off @@ -5349,39 +5355,84 @@ declare_proto_rig(get_lock_mode) static int parse_hex(const char *s, unsigned char *buf, int len) { - int i; + int i = 0; buf[0] = 0; char *s2 = strdup(s); - char *p = strtok(s2,";"); - while(p) + char *p = strtok(s2, ";"); + + while (p) { unsigned int val; - sscanf(p,"0x%x", &val); + sscanf(p, "0x%x", &val); buf[i++] = val; p = strtok(NULL, ";"); } + free(s2); return i; } /* 0xa4 */ declare_proto_rig(send_raw) { - int retval; - unsigned char term[] = ";"; + int reply_len; + 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) { - arg1_len = parse_hex(arg1,send,sizeof(send)); - sendp = send; + 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) + { + arg2_len = parse_hex(arg2, send, sizeof(send)); + sendp = send; + hex_flag = 1; + } + rig_debug(RIG_DEBUG_TRACE, "%s:\n", __func__); - retval = 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); } - return retval; + + if (reply_len == 0) + { + fprintf(fout, "No answer\n"); + } + else if (hex_flag) + { + int i; + + for (i = 0; i < reply_len; ++i) + { + fprintf(fout, "0x%02x ", buf[i]); + } + + fprintf(fout, "\n"); + } + else + { + fprintf(fout, "%s\n", buf); + } + + return RIG_OK; } diff --git a/tests/testrig.c b/tests/testrig.c index 801f3ed31..48e0c73ab 100644 --- a/tests/testrig.c +++ b/tests/testrig.c @@ -9,8 +9,6 @@ #include -#include "misc.h" - #include #define SERIAL_PORT "/dev/pts/2" @@ -438,7 +436,7 @@ int main(int argc, char *argv[]) if (retcode == RIG_OK) { // cppcheck-suppress * - printf("rig_get_mode: mode = %"PRIll"\n", rmode); + printf("rig_get_mode: mode = %s\n", rig_strrmode(rmode)); } else {