From a6de41e206d8d8fa2bab59069d052d9953b5e757 Mon Sep 17 00:00:00 2001 From: Mike Black W9MDB Date: Sat, 3 Jun 2023 16:50:30 -0500 Subject: [PATCH] rigctld can now see RIG_LEVEL values correctly https://github.com/Hamlib/Hamlib/issues/1305 --- include/hamlib/rig.h | 49 ++ rigs/dummy/netrigctl.c | 67 ++- rigs/yaesu/level_gran_yaesu.h | 2 +- src/rig.c | 5 + tests/Makefile.am | 2 +- tests/dumpstate.c | 1051 +++++++++++++++++++++++++++++++++ tests/rigctl.c | 3 + tests/rigctl_parse.c | 54 +- tests/rigctl_parse.h | 1 + 9 files changed, 1219 insertions(+), 15 deletions(-) create mode 100644 tests/dumpstate.c diff --git a/include/hamlib/rig.h b/include/hamlib/rig.h index 424f404e0..c6666adae 100644 --- a/include/hamlib/rig.h +++ b/include/hamlib/rig.h @@ -2630,6 +2630,55 @@ struct rig_state { freq_t offset_vfoa; /*!< Offset to apply to VFOA/Main set_freq */ freq_t offset_vfob; /*!< Offset to apply to VFOB/Sub set_freq */ struct multicast_s *multicast; /*!< Pointer to multicast server data */ + // Adding a number of items so netrigctl can see the real rig information + // Eventually may want to add these so that rigctld can see more of the backend + // But that will come later if requested -- for now they just fill out dumpstate.c + rig_model_t rig_model; /*!< Rig model. */ + const char *model_name; /*!< Model name. */ + const char *mfg_name; /*!< Manufacturer. */ + const char *version; /*!< Driver version. */ + const char *copyright; /*!< Copyright info. */ + enum rig_status_e status; /*!< Driver status. */ + int rig_type; /*!< Rig type. */ + ptt_type_t ptt_type; /*!< Type of the PTT port. */ + dcd_type_t dcd_type; /*!< Type of the DCD port. */ + rig_port_t port_type; /*!< Type of communication port. */ + int serial_rate_min; /*!< Minimum serial speed. */ + int serial_rate_max; /*!< Maximum serial speed. */ + int serial_data_bits; /*!< Number of data bits. */ + int serial_stop_bits; /*!< Number of stop bits. */ + enum serial_parity_e serial_parity; /*!< Parity. */ + enum serial_handshake_e serial_handshake; /*!< Handshake. */ + int write_delay; /*!< Delay between each byte sent out, in mS */ + int post_write_delay; /*!< Delay between each commands send out, in mS */ + int timeout; /*!< Timeout, in mS */ + int retry; /*!< Maximum number of retries if command fails, 0 to disable */ + int targetable_vfo; /*!< Bit field list of direct VFO access commands */ + int async_data_supported; /*!< Indicates that rig is capable of outputting asynchronous data updates, such as transceive state updates or spectrum data. 1 if true, 0 otherwise. */ + int agc_level_count; /*!< Number of supported AGC levels. Zero indicates all modes should be available (for backwards-compatibility). */ + enum agc_level_e agc_levels[HAMLIB_MAX_AGC_LEVELS]; /*!< Supported AGC levels */ + tone_t *ctcss_list; /*!< CTCSS tones list, zero ended */ + tone_t *dcs_list; /*!< DCS code list, zero ended */ + vfo_op_t vfo_ops; /*!< VFO op bit field list */ + scan_t scan_ops; /*!< Scan bit field list */ + int transceive; /*!< \deprecated Use async_data_supported instead */ + int bank_qty; /*!< Number of banks */ + int chan_desc_sz; /*!< Max length of memory channel name */ + freq_range_t rx_range_list1[HAMLIB_FRQRANGESIZ]; /*!< Receive frequency range list #1 */ + freq_range_t tx_range_list1[HAMLIB_FRQRANGESIZ]; /*!< Transmit frequency range list #1 */ + freq_range_t rx_range_list2[HAMLIB_FRQRANGESIZ]; /*!< Receive frequency range list #2 */ + freq_range_t tx_range_list2[HAMLIB_FRQRANGESIZ]; /*!< Transmit frequency range list #2 */ + freq_range_t rx_range_list3[HAMLIB_FRQRANGESIZ]; /*!< Receive frequency range list #3 */ + freq_range_t tx_range_list3[HAMLIB_FRQRANGESIZ]; /*!< Transmit frequency range list #3 */ + freq_range_t rx_range_list4[HAMLIB_FRQRANGESIZ]; /*!< Receive frequency range list #4 */ + freq_range_t tx_range_list4[HAMLIB_FRQRANGESIZ]; /*!< Transmit frequency range list #4 */ + freq_range_t rx_range_list5[HAMLIB_FRQRANGESIZ]; /*!< Receive frequency range list #5 */ + freq_range_t tx_range_list5[HAMLIB_FRQRANGESIZ]; /*!< Transmit frequency range list #5 */ + struct rig_spectrum_scope spectrum_scopes[HAMLIB_MAX_SPECTRUM_SCOPES]; /*!< Supported spectrum scopes. The array index must match the scope ID. Last entry must have NULL name. */ + enum rig_spectrum_mode_e spectrum_modes[HAMLIB_MAX_SPECTRUM_MODES]; /*!< Supported spectrum scope modes. Last entry must be RIG_SPECTRUM_MODE_NONE. */ + freq_t spectrum_spans[HAMLIB_MAX_SPECTRUM_SPANS]; /*!< Supported spectrum scope frequency spans in Hz in center mode. Last entry must be 0. */ + struct rig_spectrum_avg_mode spectrum_avg_modes[HAMLIB_MAX_SPECTRUM_AVG_MODES]; /*!< Supported spectrum scope averaging modes. Last entry must have NULL name. */ + int spectrum_attenuator[HAMLIB_MAXDBLSTSIZ]; /*!< Spectrum attenuator list in dB, 0 terminated */ }; //! @cond Doxygen_Suppress diff --git a/rigs/dummy/netrigctl.c b/rigs/dummy/netrigctl.c index 60fc52f76..d2d381c60 100644 --- a/rigs/dummy/netrigctl.c +++ b/rigs/dummy/netrigctl.c @@ -263,7 +263,7 @@ static int netrigctl_open(RIG *rig) SNPRINTF(cmd, sizeof(cmd), "\\chk_vfo\n"); ret = netrigctl_transaction(rig, cmd, strlen(cmd), buf); - if (sscanf(buf, "CHKVFO %d", &priv->rigctld_vfo_mode) == 1) + if (sscanf(buf, "%d", &priv->rigctld_vfo_mode) == 1) { rig->state.vfo_opt = priv->rigctld_vfo_mode; rig_debug(RIG_DEBUG_TRACE, "%s: chkvfo=%d\n", __func__, priv->rigctld_vfo_mode); @@ -619,11 +619,6 @@ static int netrigctl_open(RIG *rig) rig->caps->has_set_parm = rs->has_set_parm = strtoll(buf, NULL, 0); -#if 0 - gran_t level_gran[RIG_SETTING_MAX]; /*!< level granularity */ - gran_t parm_gran[RIG_SETTING_MAX]; /*!< parm granularity */ -#endif - for (i = 0; i < HAMLIB_FRQRANGESIZ && !RIG_IS_FRNG_END(rs->rx_range_list[i]); i++) { @@ -835,6 +830,64 @@ static int netrigctl_open(RIG *rig) p = strtok(NULL, " "); } } + else if (strcmp(setting, "level_gran") == 0) + { + char *p = strtok(value, ";"); + + for (i = 0; p != NULL && i < RIG_SETTING_MAX; ++i) + { + int level; + sscanf(p, "%d", &level); + + if (RIG_LEVEL_IS_FLOAT(level)) + { + double min, max, step; + sscanf(p, "%*d=%lf,%lf,%lf", &min, &max, &step); + rs->level_gran[i].min.f = min; + rs->level_gran[i].max.f = max; + rs->level_gran[i].step.f = step; + } + else + { + int min, max, step; + sscanf(p, "%*d=%d,%d,%d", &min, &max, &step); + rs->level_gran[i].min.i = min; + rs->level_gran[i].max.i = max; + rs->level_gran[i].step.i = step; + + } + + p = strtok(NULL, ";"); + } + } + else if (strcmp(setting, "parm_gran") == 0) + { + char *p = strtok(value, ";"); + for (i = 0; p != NULL && i < RIG_SETTING_MAX; ++i) + { + int level; + sscanf(p, "%d", &level); + + if (RIG_LEVEL_IS_FLOAT(level)) + { + double min, max, step; + sscanf(p, "%*d=%lf,%lf,%lf", &min, &max, &step); + rs->parm_gran[i].min.f = min; + rs->parm_gran[i].max.f = max; + rs->parm_gran[i].step.f = step; + } + else + { + int min, max, step; + sscanf(p, "%*d=%d,%d,%d", &min, &max, &step); + rs->parm_gran[i].min.i = min; + rs->parm_gran[i].max.i = max; + rs->parm_gran[i].step.i = step; + } + p = strtok(NULL, ";"); + } + } + else { // not an error -- just a warning for backward compatibility @@ -2746,7 +2799,7 @@ struct rig_caps netrigctl_caps = RIG_MODEL(RIG_MODEL_NETRIGCTL), .model_name = "NET rigctl", .mfg_name = "Hamlib", - .version = "20230503.0", + .version = "20230602.0", .copyright = "LGPL", .status = RIG_STATUS_STABLE, .rig_type = RIG_TYPE_OTHER, diff --git a/rigs/yaesu/level_gran_yaesu.h b/rigs/yaesu/level_gran_yaesu.h index 105d6901a..13ec4d85d 100644 --- a/rigs/yaesu/level_gran_yaesu.h +++ b/rigs/yaesu/level_gran_yaesu.h @@ -24,7 +24,7 @@ [LVL_SWR] = { .min = { .f = 0 }, .max = { .f = 5.0 }, .step = { .f = 1.0f/255.0f } }, [LVL_BAND_SELECT] = { .min = { .i = 0 }, .max = { .i = 16 }, .step = { .i = 1 } }, // most recent rigs seem to have 15 as the maximum -- other values can be set in the backend - [LVL_NR] = { .min = { .i = 1 }, .max = { .i = 15 }, .step = { .i = 1 } }, + [LVL_NR] = { .min = { .f = 0 }, .max = { .f = 1 }, .step = { .f = 1.0f/15.0f } }, /* levels with 0-1 values -- increment based on rig's range */ [LVL_AF] = { .min = { .f = 0 }, .max = { .f = 1 }, .step = { .f = 1.0f/255.0f } }, [LVL_RF] = { .min = { .f = 0 }, .max = { .f = 1 }, .step = { .f = 1.0f/255.0f } }, diff --git a/src/rig.c b/src/rig.c index 8fa59756c..ed7074c92 100644 --- a/src/rig.c +++ b/src/rig.c @@ -669,6 +669,11 @@ RIG *HAMLIB_API rig_init(rig_model_t rig_model) //return(NULL); // this is not fatal } + if (rs->level_gran) + { + memcpy(rs->level_gran, rig->caps->level_gran, sizeof(rs->level_gran)); + } + #if 0 // this is no longer applicable -- replace it with something? // we need to be able to figure out what model radio we have diff --git a/tests/Makefile.am b/tests/Makefile.am index 8ef92741c..0e3d453d8 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -19,7 +19,7 @@ bin_PROGRAMS = rigctl rigctld rigmem rigsmtr rigswr rotctl rotctld rigctlcom rig #check_PROGRAMS = dumpmem testrig testrigopen testrigcaps testtrn testbcd testfreq listrigs testloc rig_bench testcache cachetest cachetest2 testcookie testgrid testsecurity check_PROGRAMS = dumpmem testrig testrigopen testrigcaps testtrn testbcd testfreq listrigs testloc rig_bench testcache cachetest cachetest2 testcookie testgrid hamlibmodels -RIGCOMMONSRC = rigctl_parse.c rigctl_parse.h dumpcaps.c uthash.h +RIGCOMMONSRC = rigctl_parse.c rigctl_parse.h dumpcaps.c dumpstate.c uthash.h ROTCOMMONSRC = rotctl_parse.c rotctl_parse.h dumpcaps_rot.c uthash.h AMPCOMMONSRC = ampctl_parse.c ampctl_parse.h dumpcaps_amp.c uthash.h diff --git a/tests/dumpstate.c b/tests/dumpstate.c new file mode 100644 index 000000000..5acee230f --- /dev/null +++ b/tests/dumpstate.c @@ -0,0 +1,1051 @@ +/* + * dumpstate.c - Copyright (C) 2000-2012 Stephane Fillod + * This programs dumps the capabilities of a backend rig. + * + * + * 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., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + +#include +#include + +#include +#include "misc.h" +#include "riglist.h" +#include "sprintflst.h" +#include "rigctl_parse.h" +#include "../rigs/icom/icom.h" + +void range_print(FILE *fout, const struct freq_range_list range_list[], int rx); +int range_sanity_check(const struct freq_range_list range_list[], int rx); +int ts_sanity_check(const struct tuning_step_list tuning_step[]); +static void dump_chan_caps(const channel_cap_t *chan, FILE *fout); + +struct rig_type_s +{ + int type; + char *description; +}; + +static struct rig_type_s rig_type[] = +{ + {RIG_TYPE_OTHER, "Other"}, + {RIG_FLAG_RECEIVER, "Receiver"}, + {RIG_FLAG_TRANSMITTER, "Transmitter"}, + {RIG_FLAG_SCANNER, "Scanner"}, + {RIG_FLAG_MOBILE, "Mobile"}, + {RIG_FLAG_HANDHELD, "Handheld"}, + {RIG_FLAG_COMPUTER, "Computer"}, + {RIG_FLAG_TRANSCEIVER, "Transceiver"}, + {RIG_FLAG_TRUNKING, "Trunking scanner"}, + {RIG_FLAG_APRS, "APRS"}, + {RIG_FLAG_TNC, "TNC"}, + {RIG_FLAG_DXCLUSTER, "DxCluster"}, + {RIG_FLAG_DXCLUSTER, "DxCluster"}, + {RIG_FLAG_TUNER, "Tuner"}, + {-1, "?\n"} +}; + +static int print_ext(RIG *rig, const struct confparams *cfp, rig_ptr_t ptr) +{ + return print_ext_param(cfp, ptr); +} + +/* + * the rig may be in rig_init state, but not opened + */ +int dumpstate(RIG *rig, FILE *fout) +{ + const struct rig_caps *caps; + int status, i; + int can_esplit, can_echannel; + char freqbuf[20]; + int backend_warnings = 0; + char warnbuf[4096]; + char prntbuf[1024]; /* a malloc would be better.. */ + char *label1, *label2, *label3, *label4, *label5; + char *labelrx1; // , *labelrx2, *labelrx3, *labelrx4, *labelrx5; + + warnbuf[0] = 0; + prntbuf[0] = 0; + + if (!rig || !rig->caps) + { + return -RIG_EINVAL; + } + + caps = rig->caps; + + fprintf(fout, "Caps dump for model: %u\n", rig->state.rig_model); + fprintf(fout, "Model name:\t%s\n", rig->state.model_name); + fprintf(fout, "Mfg name:\t%s\n", rig->state.mfg_name); + fprintf(fout, "Backend version:\t%s\n", rig->state.version); + fprintf(fout, "Backend copyright:\t%s\n", rig->state.copyright); + fprintf(fout, "Backend status:\t%s\n", rig_strstatus(rig->state.status)); + fprintf(fout, "Rig type:\t"); + + char *unknown = "Unknown"; + + for (i = 0; rig_type[i].type != -1; ++i) + { + if ((rig_type[i].type & rig->state.rig_type) == rig_type[i].type) + { + fprintf(fout, "%s ", rig_type[i].description); + unknown = ""; + } + } + + fprintf(fout, "%s\n", unknown); + + if (strlen(unknown) > 0) + { + strcat(warnbuf, " RIG_TYPE"); + backend_warnings++; + } + + fprintf(fout, "PTT type:\t"); + + switch (rig->state.ptt_type) + { + case RIG_PTT_RIG: + fprintf(fout, "Rig capable\n"); + break; + + case RIG_PTT_RIG_MICDATA: + fprintf(fout, "Rig capable (Mic/Data)\n"); + break; + + case RIG_PTT_PARALLEL: + fprintf(fout, "Parallel port (DATA0)\n"); + break; + + case RIG_PTT_SERIAL_RTS: + fprintf(fout, "Serial port (CTS/RTS)\n"); + break; + + case RIG_PTT_SERIAL_DTR: + fprintf(fout, "Serial port (DTR/DSR)\n"); + break; + + case RIG_PTT_NONE: + fprintf(fout, "None\n"); + break; + + default: + fprintf(fout, "Unknown\n"); + strcat(warnbuf, " PTT_TYPE"); + backend_warnings++; + } + + fprintf(fout, "DCD type:\t"); + + switch (rig->state.dcd_type) + { + case RIG_DCD_RIG: + fprintf(fout, "Rig capable\n"); + break; + + case RIG_DCD_PARALLEL: + fprintf(fout, "Parallel port (/STROBE)\n"); + break; + + case RIG_DCD_SERIAL_CTS: + fprintf(fout, "Serial port (CTS/RTS)\n"); + break; + + case RIG_DCD_SERIAL_DSR: + fprintf(fout, "Serial port (DTR/DSR)\n"); + break; + + case RIG_DCD_SERIAL_CAR: + fprintf(fout, "Serial port (CD)\n"); + break; + + case RIG_DCD_NONE: + fprintf(fout, "None\n"); + break; + + default: + fprintf(fout, "Unknown\n"); + strcat(warnbuf, " DCD_TYPE"); + backend_warnings++; + } + + fprintf(fout, "Port type:\t"); + + switch (rig->state.port_type) + { + case RIG_PORT_SERIAL: + fprintf(fout, "RS-232\n"); + fprintf(fout, + "Serial speed: %d..%d baud, %d%c%d, ctrl=%s\n", + rig->state.serial_rate_min, + rig->state.serial_rate_max, + rig->state.serial_data_bits, + rig->state.serial_parity == RIG_PARITY_NONE ? 'N' : + rig->state.serial_parity == RIG_PARITY_ODD ? 'O' : + rig->state.serial_parity == RIG_PARITY_EVEN ? 'E' : + rig->state.serial_parity == RIG_PARITY_MARK ? 'M' : 'S', + rig->state.serial_stop_bits, + rig->state.serial_handshake == RIG_HANDSHAKE_NONE ? "NONE" : + (rig->state.serial_handshake == RIG_HANDSHAKE_XONXOFF ? "XONXOFF" : "CTS/RTS") + ); + break; + + case RIG_PORT_PARALLEL: + fprintf(fout, "Parallel\n"); + break; + + case RIG_PORT_DEVICE: + fprintf(fout, "Device driver\n"); + break; + + case RIG_PORT_USB: + fprintf(fout, "USB\n"); + break; + + case RIG_PORT_NETWORK: + fprintf(fout, "Network link\n"); + break; + + case RIG_PORT_UDP_NETWORK: + fprintf(fout, "UDP Network link\n"); + break; + + case RIG_PORT_NONE: + fprintf(fout, "None\n"); + break; + + default: + fprintf(fout, "Unknown\n"); + strcat(warnbuf, " PORT_TYPE"); + backend_warnings++; + } + + fprintf(fout, + "Write delay: %dmS, timeout %dmS, %d retry\n", + rig->state.write_delay, rig->state.timeout, rig->state.retry); + fprintf(fout, + "Post Write delay: %dmS\n", + rig->state.post_write_delay); + + fprintf(fout, + "Has targetable VFO: %s\n", + rig->state.targetable_vfo ? "Y" : "N"); + + fprintf(fout, + "Has async data support: %s\n", + rig->state.async_data_supported ? "Y" : "N"); + + fprintf(fout, "Announce: 0x%x\n", rig->state.announces); + fprintf(fout, + "Max RIT: -%ld.%ldkHz/+%ld.%ldkHz\n", + rig->state.max_rit / 1000, rig->state.max_rit % 1000, + rig->state.max_rit / 1000, rig->state.max_rit % 1000); + + fprintf(fout, + "Max XIT: -%ld.%ldkHz/+%ld.%ldkHz\n", + rig->state.max_xit / 1000, rig->state.max_xit % 1000, + rig->state.max_xit / 1000, rig->state.max_xit % 1000); + + fprintf(fout, + "Max IF-SHIFT: -%ld.%ldkHz/+%ld.%ldkHz\n", + rig->state.max_ifshift / 1000, rig->state.max_ifshift % 1000, + rig->state.max_ifshift / 1000, rig->state.max_ifshift % 1000); + + fprintf(fout, "Preamp:"); + + for (i = 0; i < HAMLIB_MAXDBLSTSIZ && rig->state.preamp[i] != 0; i++) + { + fprintf(fout, " %ddB", rig->state.preamp[i]); + } + + if (i == 0) + { + fprintf(fout, " None"); + } + + fprintf(fout, "\n"); + fprintf(fout, "Attenuator:"); + + for (i = 0; i < HAMLIB_MAXDBLSTSIZ && rig->state.attenuator[i] != 0; i++) + { + fprintf(fout, " %ddB", rig->state.attenuator[i]); + } + + if (i == 0) + { + fprintf(fout, " None"); + } + + fprintf(fout, "\n"); + + + fprintf(fout, "AGC levels:"); + const struct icom_priv_caps *priv_caps = + (const struct icom_priv_caps *) rig->state.priv; + + if (priv_caps && RIG_BACKEND_NUM(rig->state.rig_model) == RIG_ICOM + && priv_caps->agc_levels_present) + { + for (i = 0; i < HAMLIB_MAX_AGC_LEVELS && priv_caps->agc_levels[i].level != RIG_AGC_LAST + && priv_caps->agc_levels[i].icom_level >= 0; i++) + { + fprintf(fout, " %d=%s", priv_caps->agc_levels[i].level, + rig_stragclevel(priv_caps->agc_levels[i].level)); + } + } + else + { + for (i = 0; i < HAMLIB_MAX_AGC_LEVELS && i < rig->state.agc_level_count; i++) + { + fprintf(fout, " %d=%s", rig->state.agc_levels[i], + rig_stragclevel(rig->state.agc_levels[i])); + } + } + + if (i == 0) + { + fprintf(fout, " %d=%s", RIG_AGC_NONE, rig_stragclevel(RIG_AGC_NONE)); + } + + fprintf(fout, "\n"); + + fprintf(fout, "CTCSS:"); + + for (i = 0; rig->state.ctcss_list && i < 60 && rig->state.ctcss_list[i] != 0; i++) + { + fprintf(fout, + " %u.%1u", + rig->state.ctcss_list[i] / 10, rig->state.ctcss_list[i] % 10); + } + + if (i == 0) + { + fprintf(fout, " None"); + } + else + { + fprintf(fout, " Hz, %d tones", i); + } + + fprintf(fout, "\n"); + + fprintf(fout, "DCS:"); + + for (i = 0; rig->state.dcs_list && i < 128 && rig->state.dcs_list[i] != 0; i++) + { + fprintf(fout, " %u", rig->state.dcs_list[i]); + } + + if (i == 0) + { + fprintf(fout, " None"); + } + else + { + fprintf(fout, ", %d codes", i); + } + + fprintf(fout, "\n"); + + rig_sprintf_func(prntbuf, sizeof(prntbuf), rig->state.has_get_func); + fprintf(fout, "Get functions: %s\n", prntbuf); + + rig_sprintf_func(prntbuf, sizeof(prntbuf), rig->state.has_set_func); + fprintf(fout, "Set functions: %s\n", prntbuf); + + fprintf(fout, "Extra functions:\n"); + rig_ext_func_foreach(rig, print_ext, fout); + + rig_sprintf_level_gran(prntbuf, sizeof(prntbuf), rig->state.has_get_level, + rig->state.level_gran); + fprintf(fout, "Get level: %s\n", prntbuf); + + if ((rig->state.has_get_level & RIG_LEVEL_RAWSTR) + && rig->state.str_cal.size == 0 + && !(rig->state.has_get_level & RIG_LEVEL_STRENGTH)) + { + + fprintf(fout, + "Warning--backend has get RAWSTR, but not calibration data\n"); + strcat(warnbuf, " RAWSTR_level"); + backend_warnings++; + } + + rig_sprintf_level_gran(prntbuf, sizeof(prntbuf), rig->state.has_set_level, + rig->state.level_gran); + fprintf(fout, "Set level: %s\n", prntbuf); + + if (rig->state.has_set_level & RIG_LEVEL_READONLY_LIST) + { + + //fprintf(fout, "Warning--backend can set readonly levels=0x%0llx\n", rig->state.has_set_level & RIG_LEVEL_READONLY_LIST); + fprintf(fout, "Warning--backend can set readonly levels\n"); + strcat(warnbuf, " READONLY_LEVEL"); + backend_warnings++; + } + + fprintf(fout, "Extra levels:\n"); + rig_ext_level_foreach(rig, print_ext, fout); + + rig_sprintf_parm_gran(prntbuf, sizeof(prntbuf), rig->state.has_get_parm, + rig->state.parm_gran); + fprintf(fout, "Get parameters: %s\n", prntbuf); + + rig_sprintf_parm_gran(prntbuf, sizeof(prntbuf), rig->state.has_set_parm, + rig->state.parm_gran); + fprintf(fout, "Set parameters: %s\n", prntbuf); + + if (rig->state.has_set_parm & RIG_PARM_READONLY_LIST) + { + fprintf(fout, "Warning--backend can set readonly parms!\n"); + strcat(warnbuf, " READONLY_PARM"); + backend_warnings++; + } + + fprintf(fout, "Extra parameters:\n"); + rig_ext_parm_foreach(rig, print_ext, fout); + + + if (rig->state.mode_list != 0) + { + rig_sprintf_mode(prntbuf, sizeof(prntbuf), rig->state.mode_list); + } + else + { + strcpy(prntbuf, "None. This backend might be bogus!\n"); + strcat(warnbuf, " MODE_LIST"); + backend_warnings++; + } + + fprintf(fout, "Mode list: %s\n", prntbuf); + + if (rig->state.vfo_list != 0) + { + rig_sprintf_vfo(prntbuf, sizeof(prntbuf), rig->state.vfo_list); + } + else + { + strcpy(prntbuf, "None. This backend might be bogus!\n"); + strcat(warnbuf, " VFO_LIST"); + backend_warnings++; + } + + fprintf(fout, "VFO list: %s\n", prntbuf); + + rig_sprintf_vfop(prntbuf, sizeof(prntbuf), rig->state.vfo_ops); + fprintf(fout, "VFO Ops: %s\n", prntbuf); + + rig_sprintf_scan(prntbuf, sizeof(prntbuf), rig->state.scan_ops); + fprintf(fout, "Scan Ops: %s\n", prntbuf); + + fprintf(fout, "Number of banks:\t%d\n", rig->state.bank_qty); + fprintf(fout, "Memory name desc size:\t%d\n", rig->state.chan_desc_sz); + + fprintf(fout, "Memories:"); + + for (i = 0; i < HAMLIB_CHANLSTSIZ && rig->state.chan_list[i].type; i++) + { + fprintf(fout, + "\n\t%d..%d: \t%s", + rig->state.chan_list[i].startc, + rig->state.chan_list[i].endc, + rig_strmtype(rig->state.chan_list[i].type)); + fprintf(fout, "\n\t Mem caps: "); + dump_chan_caps(&rig->state.chan_list[i].mem_caps, fout); + } + + if (i == 0) + { + fprintf(fout, " None"); + } + + fprintf(fout, "\n"); + + label1 = rig->state.tx_range_list1->label; + label1 = label1 == NULL ? "TBD" : label1; + fprintf(fout, "TX ranges #1 for %s:\n", label1); + range_print(fout, rig->state.tx_range_list1, 0); + + labelrx1 = rig->state.rx_range_list1->label; + labelrx1 = labelrx1 == NULL ? "TBD" : labelrx1; + fprintf(fout, "RX ranges #1 for %s:\n", labelrx1); + range_print(fout, rig->state.rx_range_list1, 1); + + label2 = rig->state.rx_range_list2->label; + label2 = label2 == NULL ? "TBD" : label2; + fprintf(fout, "TX ranges #2 for %s:\n", label2); + range_print(fout, rig->state.tx_range_list2, 0); + + label2 = rig->state.rx_range_list2->label; + label2 = label2 == NULL ? "TBD" : label2; + fprintf(fout, "RX ranges #2 for %s:\n", label2); + range_print(fout, rig->state.rx_range_list2, 1); + + label3 = rig->state.rx_range_list3->label; + label3 = label3 == NULL ? "TBD" : label3; + fprintf(fout, "TX ranges #3 for %s:\n", label3); + range_print(fout, rig->state.tx_range_list3, 0); + + label3 = rig->state.rx_range_list3->label; + label3 = label3 == NULL ? "TBD" : label3; + fprintf(fout, "RX ranges #3 for %s:\n", label3); + range_print(fout, rig->state.rx_range_list3, 1); + + label4 = rig->state.rx_range_list4->label; + label4 = label4 == NULL ? "TBD" : label4; + fprintf(fout, "TX ranges #4 for %s:\n", label4); + range_print(fout, rig->state.tx_range_list5, 0); + + label4 = rig->state.rx_range_list4->label; + label4 = label4 == NULL ? "TBD" : label4; + fprintf(fout, "RX ranges #4 for %s:\n", label4); + range_print(fout, rig->state.rx_range_list5, 1); + + label5 = rig->state.rx_range_list5->label; + label5 = label5 == NULL ? "TBD" : label5; + fprintf(fout, "TX ranges #5 for %s:\n", label5); + range_print(fout, rig->state.tx_range_list5, 0); + + label5 = rig->state.rx_range_list5->label; + label5 = label5 == NULL ? "TBD" : label5; + fprintf(fout, "RX ranges #5 for %s:\n", label5); + range_print(fout, rig->state.rx_range_list5, 1); + + status = range_sanity_check(rig->state.tx_range_list1, 0); + fprintf(fout, + "TX ranges #1 status for %s:\t%s (%d)\n", label1, + status ? "Bad" : "OK", + status); + + if (status) + { + strcat(warnbuf, " TX#1"); + backend_warnings++; + } + + status = range_sanity_check(rig->state.rx_range_list1, 1); + fprintf(fout, + "RX ranges #1 status for %s:\t%s (%d)\n", labelrx1, + status ? "Bad" : "OK", + status); + + if (status) + { + strcat(warnbuf, " RX#1"); + backend_warnings++; + } + + status = range_sanity_check(rig->state.tx_range_list2, 0); + fprintf(fout, + "TX ranges #2 status for %s:\t%s (%d)\n", label2, + status ? "Bad" : "OK", + status); + + if (status) + { + strcat(warnbuf, " TX#2"); + backend_warnings++; + } + + status = range_sanity_check(rig->state.rx_range_list2, 1); + fprintf(fout, + "RX ranges #2 status for %s:\t%s (%d)\n", label2, + status ? "Bad" : "OK", + status); + + if (status) + { + strcat(warnbuf, " RX#2"); + backend_warnings++; + } + + status = range_sanity_check(rig->state.tx_range_list3, 0); + fprintf(fout, + "TX ranges #3 status for %s:\t%s (%d)\n", label3, + status ? "Bad" : "OK", + status); + + if (status) + { + strcat(warnbuf, " TX#3"); + backend_warnings++; + } + + status = range_sanity_check(rig->state.rx_range_list3, 1); + fprintf(fout, + "RX ranges #3 status for %s:\t%s (%d)\n", label3, + status ? "Bad" : "OK", + status); + + if (status) + { + strcat(warnbuf, " RX#3"); + backend_warnings++; + } + + status = range_sanity_check(rig->state.tx_range_list4, 0); + fprintf(fout, + "TX ranges #4 status for %s:\t%s (%d)\n", label4, + status ? "Bad" : "OK", + status); + + if (status) + { + strcat(warnbuf, " TX#4"); + backend_warnings++; + } + + status = range_sanity_check(rig->state.rx_range_list4, 1); + fprintf(fout, + "RX ranges #4 status for %s:\t%s (%d)\n", label4, + status ? "Bad" : "OK", + status); + + if (status) + { + strcat(warnbuf, " RX#4"); + backend_warnings++; + } + + status = range_sanity_check(rig->state.tx_range_list5, 0); + fprintf(fout, + "TX ranges #5 status for %s:\t%s (%d)\n", label5, + status ? "Bad" : "OK", + status); + + if (status) + { + strcat(warnbuf, " TX#5"); + backend_warnings++; + } + + status = range_sanity_check(rig->state.rx_range_list5, 1); + fprintf(fout, + "RX ranges #5 status for %s:\t%s (%d)\n", label5, + status ? "Bad" : "OK", + status); + + if (status) + { + strcat(warnbuf, " RX#5"); + backend_warnings++; + } + + fprintf(fout, "Tuning steps:"); + + for (i = 0; i < HAMLIB_TSLSTSIZ && !RIG_IS_TS_END(rig->state.tuning_steps[i]); i++) + { + if (rig->state.tuning_steps[i].ts == RIG_TS_ANY) + { + strcpy(freqbuf, "ANY"); /* strcpy! Looks safe for now */ + } + else + { + sprintf_freq(freqbuf, sizeof(freqbuf), rig->state.tuning_steps[i].ts); + } + + rig_sprintf_mode(prntbuf, sizeof(prntbuf), rig->state.tuning_steps[i].modes); + fprintf(fout, "\n\t%s: \t%s", freqbuf, prntbuf); + } + + if (i == 0) + { + fprintf(fout, " None! This backend might be bogus!"); + strcat(warnbuf, " TUNING_STEPS"); + backend_warnings++; + } + + fprintf(fout, "\n"); + status = ts_sanity_check(rig->state.tuning_steps); + fprintf(fout, "Tuning steps status:\t%s (%d)\n", status ? "Bad" : "OK", status); + + if (status) + { + strcat(warnbuf, " TUNING_SANE"); + backend_warnings++; + } + + fprintf(fout, "Filters:"); + + for (i = 0; i < HAMLIB_FLTLSTSIZ && !RIG_IS_FLT_END(rig->state.filters[i]); i++) + { + if (rig->state.filters[i].width == RIG_FLT_ANY) + { + strcpy(freqbuf, "ANY"); + } + else + { + sprintf_freq(freqbuf, sizeof(freqbuf), rig->state.filters[i].width); + } + + rig_sprintf_mode(prntbuf, sizeof(prntbuf), rig->state.filters[i].modes); + fprintf(fout, "\n\t%s: \t%s", freqbuf, prntbuf); + } + + if (i == 0) + { + fprintf(fout, " None. This backend might be bogus!"); + strcat(warnbuf, " FILTERS"); + backend_warnings++; + } + + fprintf(fout, "\n"); + + fprintf(fout, "Bandwidths:"); + + for (i = 1; i < RIG_MODE_TESTS_MAX; i <<= 1) + { + pbwidth_t pbnorm = rig_passband_normal(rig, i); + + if (pbnorm == 0) + { + continue; + } + + sprintf_freq(freqbuf, sizeof(freqbuf), pbnorm); + fprintf(fout, "\n\t%s\tNormal: %s,\t", rig_strrmode(i), freqbuf); + + sprintf_freq(freqbuf, sizeof(freqbuf), rig_passband_narrow(rig, i)); + fprintf(fout, "Narrow: %s,\t", freqbuf); + + sprintf_freq(freqbuf, sizeof(freqbuf), rig_passband_wide(rig, i)); + fprintf(fout, "Wide: %s", freqbuf); + } + + fprintf(fout, "\n"); + + fprintf(fout, "Spectrum scopes:"); + + for (i = 0; i < HAMLIB_MAX_SPECTRUM_SCOPES + && rig->state.spectrum_scopes[i].name != NULL; i++) + { + fprintf(fout, " %d=\"%s\"", rig->state.spectrum_scopes[i].id, + rig->state.spectrum_scopes[i].name); + } + + if (i == 0) + { + fprintf(fout, " None"); + } + + fprintf(fout, "\n"); + + rig_sprintf_spectrum_modes(prntbuf, sizeof(prntbuf), rig->state.spectrum_modes); + fprintf(fout, "Spectrum modes: %s\n", prntbuf); + + rig_sprintf_spectrum_spans(prntbuf, sizeof(prntbuf), rig->state.spectrum_spans); + fprintf(fout, "Spectrum spans: %s\n", prntbuf); + + rig_sprintf_spectrum_avg_modes(prntbuf, sizeof(prntbuf), + rig->state.spectrum_avg_modes); + fprintf(fout, "Spectrum averaging modes: %s\n", prntbuf); + + fprintf(fout, "Spectrum attenuator:"); + + for (i = 0; i < HAMLIB_MAXDBLSTSIZ && rig->state.spectrum_attenuator[i] != 0; i++) + { + fprintf(fout, " %ddB", rig->state.spectrum_attenuator[i]); + } + + if (i == 0) + { + fprintf(fout, " None"); + } + + fprintf(fout, "\n"); + + fprintf(fout, "Has priv data:\t%c\n", rig->state.priv != NULL ? 'Y' : 'N'); + /* + * Status is either 'Y'es, 'E'mulated, 'N'o + * + * TODO: keep me up-to-date with API call list! + */ + fprintf(fout, "Has Init:\t%c\n", rig->caps->rig_init != NULL ? 'Y' : 'N'); + fprintf(fout, "Has Cleanup:\t%c\n", rig->caps->rig_cleanup != NULL ? 'Y' : 'N'); + fprintf(fout, "Has Open:\t%c\n", rig->caps->rig_open != NULL ? 'Y' : 'N'); + fprintf(fout, "Has Close:\t%c\n", rig->caps->rig_close != NULL ? 'Y' : 'N'); + fprintf(fout, "Can set Conf:\t%c\n", rig->caps->set_conf != NULL ? 'Y' : 'N'); + fprintf(fout, "Can get Conf:\t%c\n", rig->caps->get_conf != NULL ? 'Y' : 'N'); + fprintf(fout, "Can set Frequency:\t%c\n", rig->caps->set_freq != NULL ? 'Y' : 'N'); + fprintf(fout, "Can get Frequency:\t%c\n", rig->caps->get_freq != NULL ? 'Y' : 'N'); + fprintf(fout, "Can set Mode:\t%c\n", rig->caps->set_mode != NULL ? 'Y' : 'N'); + fprintf(fout, "Can get Mode:\t%c\n", rig->caps->get_mode != NULL ? 'Y' : 'N'); + fprintf(fout, "Can set VFO:\t%c\n", rig->caps->set_vfo != NULL ? 'Y' : 'N'); + fprintf(fout, "Can get VFO:\t%c\n", rig->caps->get_vfo != NULL ? 'Y' : 'N'); + fprintf(fout, "Can set PTT:\t%c\n", rig->caps->set_ptt != NULL ? 'Y' : 'N'); + fprintf(fout, "Can get PTT:\t%c\n", rig->caps->get_ptt != NULL ? 'Y' : 'N'); + fprintf(fout, "Can get DCD:\t%c\n", rig->caps->get_dcd != NULL ? 'Y' : 'N'); + fprintf(fout, + "Can set Repeater Duplex:\t%c\n", + rig->caps->set_rptr_shift != NULL ? 'Y' : 'N'); + fprintf(fout, + "Can get Repeater Duplex:\t%c\n", + rig->caps->get_rptr_shift != NULL ? 'Y' : 'N'); + fprintf(fout, + "Can set Repeater Offset:\t%c\n", + rig->caps->set_rptr_offs != NULL ? 'Y' : 'N'); + fprintf(fout, + "Can get Repeater Offset:\t%c\n", + rig->caps->get_rptr_offs != NULL ? 'Y' : 'N'); + + can_esplit = rig->caps->set_split_vfo + && (rig->caps->set_vfo + || (rig_has_vfo_op(rig, RIG_OP_TOGGLE) && rig->caps->vfo_op)); + + fprintf(fout, + "Can set Split Freq:\t%c\n", + rig->caps->set_split_freq != NULL ? 'Y' : (can_esplit + && rig->caps->set_freq ? 'E' : 'N')); + + fprintf(fout, + "Can get Split Freq:\t%c\n", + rig->caps->get_split_freq != NULL ? 'Y' : (can_esplit + && rig->caps->get_freq ? 'E' : 'N')); + + fprintf(fout, + "Can set Split Mode:\t%c\n", + rig->caps->set_split_mode != NULL ? 'Y' : (can_esplit + && rig->caps->set_mode ? 'E' : 'N')); + + fprintf(fout, + "Can get Split Mode:\t%c\n", + rig->caps->get_split_mode != NULL ? 'Y' : (can_esplit + && rig->caps->get_mode ? 'E' : 'N')); + + fprintf(fout, + "Can set Split VFO:\t%c\n", + rig->caps->set_split_vfo != NULL ? 'Y' : 'N'); + + fprintf(fout, + "Can get Split VFO:\t%c\n", + rig->caps->get_split_vfo != NULL ? 'Y' : 'N'); + + fprintf(fout, "Can set Tuning Step:\t%c\n", rig->caps->set_ts != NULL ? 'Y' : 'N'); + fprintf(fout, "Can get Tuning Step:\t%c\n", rig->caps->get_ts != NULL ? 'Y' : 'N'); + fprintf(fout, "Can set RIT:\t%c\n", rig->caps->set_rit != NULL ? 'Y' : 'N'); + fprintf(fout, "Can get RIT:\t%c\n", rig->caps->get_rit != NULL ? 'Y' : 'N'); + fprintf(fout, "Can set XIT:\t%c\n", rig->caps->set_xit != NULL ? 'Y' : 'N'); + fprintf(fout, "Can get XIT:\t%c\n", rig->caps->get_xit != NULL ? 'Y' : 'N'); + fprintf(fout, "Can set CTCSS:\t%c\n", rig->caps->set_ctcss_tone != NULL ? 'Y' : 'N'); + fprintf(fout, "Can get CTCSS:\t%c\n", rig->caps->get_ctcss_tone != NULL ? 'Y' : 'N'); + fprintf(fout, "Can set DCS:\t%c\n", rig->caps->set_dcs_code != NULL ? 'Y' : 'N'); + fprintf(fout, "Can get DCS:\t%c\n", rig->caps->get_dcs_code != NULL ? 'Y' : 'N'); + + fprintf(fout, + "Can set CTCSS Squelch:\t%c\n", + rig->caps->set_ctcss_sql != NULL ? 'Y' : 'N'); + + fprintf(fout, + "Can get CTCSS Squelch:\t%c\n", + rig->caps->get_ctcss_sql != NULL ? 'Y' : 'N'); + + fprintf(fout, + "Can set DCS Squelch:\t%c\n", + rig->caps->set_dcs_sql != NULL ? 'Y' : 'N'); + + fprintf(fout, + "Can get DCS Squelch:\t%c\n", + rig->caps->get_dcs_sql != NULL ? 'Y' : 'N'); + + fprintf(fout, + "Can set Power Stat:\t%c\n", + rig->caps->set_powerstat != NULL ? 'Y' : 'N'); + + fprintf(fout, + "Can get Power Stat:\t%c\n", + rig->caps->get_powerstat != NULL ? 'Y' : 'N'); + + fprintf(fout, "Can Reset:\t%c\n", rig->caps->reset != NULL ? 'Y' : 'N'); + fprintf(fout, "Can get Ant:\t%c\n", rig->caps->get_ant != NULL ? 'Y' : 'N'); + fprintf(fout, "Can set Ant:\t%c\n", rig->caps->set_ant != NULL ? 'Y' : 'N'); + + fprintf(fout, + "Can set Transceive:\t%c\n", + rig->caps->set_trn != NULL ? 'Y' : rig->caps->transceive == RIG_TRN_RIG ? 'E' : 'N'); + + fprintf(fout, "Can get Transceive:\t%c\n", rig->caps->get_trn != NULL ? 'Y' : 'N'); + fprintf(fout, "Can set Func:\t%c\n", rig->caps->set_func != NULL ? 'Y' : 'N'); + fprintf(fout, "Can get Func:\t%c\n", rig->caps->get_func != NULL ? 'Y' : 'N'); + fprintf(fout, "Can set Level:\t%c\n", rig->caps->set_level != NULL ? 'Y' : 'N'); + fprintf(fout, "Can get Level:\t%c\n", rig->caps->get_level != NULL ? 'Y' : 'N'); + fprintf(fout, "Can set Param:\t%c\n", rig->caps->set_parm != NULL ? 'Y' : 'N'); + fprintf(fout, "Can get Param:\t%c\n", rig->caps->get_parm != NULL ? 'Y' : 'N'); + fprintf(fout, "Can send DTMF:\t%c\n", rig->caps->send_dtmf != NULL ? 'Y' : 'N'); + fprintf(fout, "Can recv DTMF:\t%c\n", rig->caps->recv_dtmf != NULL ? 'Y' : 'N'); + fprintf(fout, "Can send Morse:\t%c\n", rig->caps->send_morse != NULL ? 'Y' : 'N'); + fprintf(fout, "Can stop Morse:\t%c\n", rig->caps->stop_morse != NULL ? 'Y' : 'N'); + fprintf(fout, "Can wait Morse:\t%c\n", rig->caps->wait_morse != NULL ? 'Y' : 'N'); + fprintf(fout, "Can send Voice:\t%c\n", + rig->caps->send_voice_mem != NULL ? 'Y' : 'N'); + + fprintf(fout, + "Can decode Events:\t%c\n", + rig->caps->decode_event != NULL ? 'Y' : 'N'); + + fprintf(fout, "Can set Bank:\t%c\n", rig->caps->set_bank != NULL ? 'Y' : 'N'); + fprintf(fout, "Can set Mem:\t%c\n", rig->caps->set_mem != NULL ? 'Y' : 'N'); + fprintf(fout, "Can get Mem:\t%c\n", rig->caps->get_mem != NULL ? 'Y' : 'N'); + + can_echannel = rig->caps->set_mem + && ((rig->caps->set_vfo + && ((rig->state.vfo_list & RIG_VFO_MEM) == RIG_VFO_MEM)) + || (rig->caps->vfo_op + && rig_has_vfo_op(rig, RIG_OP_TO_VFO | RIG_OP_FROM_VFO))); + + fprintf(fout, + "Can set Channel:\t%c\n", + rig->caps->set_channel != NULL ? 'Y' : (can_echannel ? 'E' : 'N')); + + fprintf(fout, + "Can get Channel:\t%c\n", + rig->caps->get_channel != NULL ? 'Y' : (can_echannel ? 'E' : 'N')); + + fprintf(fout, "Can ctl Mem/VFO:\t%c\n", rig->caps->vfo_op != NULL ? 'Y' : 'N'); + fprintf(fout, "Can Scan:\t%c\n", rig->caps->scan != NULL ? 'Y' : 'N'); + fprintf(fout, "Can get Info:\t%c\n", rig->caps->get_info != NULL ? 'Y' : 'N'); + fprintf(fout, "Can get power2mW:\t%c\n", caps->power2mW != NULL ? 'Y' : 'N'); + fprintf(fout, "Can get mW2power:\t%c\n", caps->mW2power != NULL ? 'Y' : 'N'); + + fprintf(fout, "\nOverall backend warnings: %d %c %s\n", backend_warnings, + warnbuf[0] != 0 ? '=' : ' ', warnbuf); + + return backend_warnings; +} + +static void dump_chan_caps(const channel_cap_t *chan, FILE *fout) +{ + if (chan->bank_num) + { + fprintf(fout, "BANK "); + } + + if (chan->ant) + { + fprintf(fout, "ANT "); + } + + if (chan->freq) + { + fprintf(fout, "FREQ "); + } + + if (chan->mode) + { + fprintf(fout, "MODE "); + } + + if (chan->width) + { + fprintf(fout, "WIDTH "); + } + + if (chan->tx_freq) + { + fprintf(fout, "TXFREQ "); + } + + if (chan->tx_mode) + { + fprintf(fout, "TXMODE "); + } + + if (chan->tx_width) + { + fprintf(fout, "TXWIDTH "); + } + + if (chan->split) + { + fprintf(fout, "SPLIT "); + } + + if (chan->rptr_shift) + { + fprintf(fout, "RPTRSHIFT "); + } + + if (chan->rptr_offs) + { + fprintf(fout, "RPTROFS "); + } + + if (chan->tuning_step) + { + fprintf(fout, "TS "); + } + + if (chan->rit) + { + fprintf(fout, "RIT "); + } + + if (chan->xit) + { + fprintf(fout, "XIT "); + } + + if (chan->funcs) + { + fprintf(fout, "FUNC "); /* TODO: iterate over the list */ + } + + if (chan->levels) + { + fprintf(fout, "LEVEL "); /* TODO: iterate over the list */ + } + + if (chan->ctcss_tone) + { + fprintf(fout, "TONE "); + } + + if (chan->ctcss_sql) + { + fprintf(fout, "CTCSS "); + } + + if (chan->dcs_code) + { + fprintf(fout, "DCSCODE "); + } + + if (chan->dcs_sql) + { + fprintf(fout, "DCSSQL "); + } + + if (chan->scan_group) + { + fprintf(fout, "SCANGRP "); + } + + if (chan->flags) + { + fprintf(fout, "FLAG "); /* TODO: iterate over the RIG_CHFLAG's */ + } + + if (chan->channel_desc) + { + fprintf(fout, "NAME "); + } + + if (chan->ext_levels) + { + fprintf(fout, "EXTLVL "); + } +} diff --git a/tests/rigctl.c b/tests/rigctl.c index 22253a9de..a400ddaa3 100644 --- a/tests/rigctl.c +++ b/tests/rigctl.c @@ -553,6 +553,9 @@ int main(int argc, char *argv[]) } rig_close(my_rig); + dumpstate(my_rig, stdout); + rig_close(my_rig); + exit(0); } dumpcaps(my_rig, stdout); diff --git a/tests/rigctl_parse.c b/tests/rigctl_parse.c index 8d25eedce..b58171f5b 100644 --- a/tests/rigctl_parse.c +++ b/tests/rigctl_parse.c @@ -4354,7 +4354,18 @@ declare_proto_rig(dump_caps) { ENTERFUNC2; - dumpcaps(rig, fout); +#if 1 + if (rig->caps->rig_model == RIG_MODEL_NETRIGCTL) + { + char cmd[32]; + SNPRINTF(cmd, sizeof(cmd), "\\dump_caps\n"); + dumpstate(rig, fout); + } + else +#endif + { + dumpcaps(rig, fout); + } RETURNFUNC2(RIG_OK); } @@ -4467,6 +4478,7 @@ declare_proto_rig(dump_state) // protocol 1 allows fields can be listed/processed in any order // protocol 1 fields can be multi-line -- just write the thing to allow for it // backward compatible as new values will just generate warnings + rig_debug(RIG_DEBUG_ERR, "%s: chk_vfo_executed=%d\n", __func__, chk_vfo_executed); if (chk_vfo_executed) // for 3.3 compatiblility { fprintf(fout, "vfo_ops=0x%x\n", rig->caps->vfo_ops); @@ -4523,14 +4535,43 @@ declare_proto_rig(dump_state) fprintf(fout, "\n"); } + + fprintf(fout, "level_gran="); + + for (i = 0; i < RIG_SETTING_MAX; ++i) + { + if (RIG_LEVEL_IS_FLOAT(i)) + { + fprintf(fout, "%d=%g,%g,%g;", i, rig->state.level_gran[i].min.f, + rig->state.level_gran[i].max.f, rig->state.level_gran[i].step.f); + } + else + { + fprintf(fout, "%d=%d,%d,%d;", i, rig->state.level_gran[i].min.i, + rig->state.level_gran[i].max.i, rig->state.level_gran[i].step.i); + } + } + + fprintf(fout, "\nparm_gran="); + + for (i = 0; i < RIG_SETTING_MAX; ++i) + { + if (RIG_LEVEL_IS_FLOAT(i)) + { + fprintf(fout, "%d=%g,%g,%g;", i, rig->state.parm_gran[i].min.f, + rig->state.parm_gran[i].max.f, rig->state.parm_gran[i].step.f); + } + else + { + fprintf(fout, "%d=%d,%d,%d;", i, rig->state.level_gran[i].min.i, + rig->state.level_gran[i].max.i, rig->state.level_gran[i].step.i); + } + } + + fprintf(fout, "\n"); fprintf(fout, "done\n"); } -#if 0 // why isn't this implemented? Does anybody care? - gran_t level_gran[RIG_SETTING_MAX]; /*!< level granularity */ - gran_t parm_gran[RIG_SETTING_MAX]; /*!< parm granularity */ -#endif - RETURNFUNC2(RIG_OK); } @@ -5054,6 +5095,7 @@ declare_proto_rig(chk_vfo) { ENTERFUNC2; +rig_debug(RIG_DEBUG_ERR, "%s: **********************************\n", __func__); if ((interactive && prompt) || (interactive && !prompt && ext_resp)) { fprintf(fout, "%s: ", cmd->arg1); /* i.e. "Frequency" */ diff --git a/tests/rigctl_parse.h b/tests/rigctl_parse.h index c3351eec6..1553d2096 100644 --- a/tests/rigctl_parse.h +++ b/tests/rigctl_parse.h @@ -36,6 +36,7 @@ */ int dumpcaps(RIG *, FILE *); +int dumpstate(RIG *, FILE *); int dumpconf(RIG *, FILE *); /*