Merge master and fix conflicts

pull/1481/head
Mikael Nousiainen 2023-11-07 09:41:29 +02:00
commit 89abbfeb3a
39 zmienionych plików z 1344 dodań i 363 usunięć

Wyświetl plik

@ -2380,6 +2380,7 @@ typedef struct hamlib_port {
int fd_sync_error_read; /*!< file descriptor for reading synchronous data error codes */
#endif
short timeout_retry; /*!< number of retries to make in case of read timeout errors, some serial interfaces may require this, 0 to disable */
int post_ptt_delay; /*!< delay after PTT to allow for relays and such */
} hamlib_port_t;
@ -2550,6 +2551,7 @@ struct rig_cache {
struct timespec time_ptt;
struct timespec time_split;
int satmode; // if rig is in satellite mode
double swr; // keep swr
};
/**
@ -2576,6 +2578,15 @@ struct multicast_s
//#endif
};
typedef unsigned int rig_comm_status_t;
#define RIG_COMM_STATUS_OK 0x00
#define RIG_COMM_STATUS_CONNECTING 0x01
#define RIG_COMM_STATUS_DISCONNECTED 0x02
#define RIG_COMM_STATUS_TERMINATED 0x03
#define RIG_COMM_STATUS_WARNING 0x04
#define RIG_COMM_STATUS_ERROR 0x05
/**
* \brief Rig state containing live data and customized fields.
*
@ -2758,7 +2769,15 @@ struct rig_state {
volatile int morse_data_handler_thread_run;
void *morse_data_handler_priv_data;
FIFO_RIG *fifo_morse;
int port_multicast; /*!< May be different so this is initially a copy of rigctl'd port selection */
int doppler; /*!< True if doppler changing detected */
char *multicast_data_addr; /*!< Multicast data UDP address for publishing rig data and state */
int multicast_data_port; /*!< Multicast data UDP port for publishing rig data and state */
char *multicast_cmd_addr; /*!< Multicast command server UDP address for sending commands to rig */
int multicast_cmd_port; /*!< Multicast command server UDP port for sending commands to rig */
volatile int multicast_receiver_run;
void *multicast_receiver_priv_data;
rig_comm_status_t comm_status; /*!< Detailed rig control status */
char device_id[HAMLIB_RIGNAMSIZ];
};
/**
@ -3703,6 +3722,7 @@ extern HAMLIB_EXPORT(const char *) rig_strscan(scan_t scan);
extern HAMLIB_EXPORT(const char *) rig_strstatus(enum rig_status_e status);
extern HAMLIB_EXPORT(const char *) rig_strmtype(chan_type_t mtype);
extern HAMLIB_EXPORT(const char *) rig_strspectrummode(enum rig_spectrum_mode_e mode);
extern HAMLIB_EXPORT(const char *) rig_strcommstatus(rig_comm_status_t vfo);
extern HAMLIB_EXPORT(rmode_t) rig_parse_mode(const char *s);
extern HAMLIB_EXPORT(vfo_t) rig_parse_vfo(const char *s);

Wyświetl plik

@ -3619,7 +3619,7 @@ int icom_get_level(RIG *rig, vfo_t vfo, setting_t level, value_t *val)
for (i = 0; extcmds && extcmds[i].id.s != 0; i++)
{
rig_debug(RIG_DEBUG_TRACE, "%s: i=%d\n", __func__, i);
//rig_debug(RIG_DEBUG_TRACE, "%s: i=%d\n", __func__, i);
if (extcmds[i].cmdparamtype == CMD_PARAM_TYPE_LEVEL && extcmds[i].id.s == level)
{

Wyświetl plik

@ -49,7 +49,7 @@
#define POWERSDR_FUNC_ALL (RIG_FUNC_VOX|RIG_FUNC_SQL|RIG_FUNC_NB|RIG_FUNC_ANF|RIG_FUNC_MUTE|RIG_FUNC_RIT|RIG_FUNC_XIT|RIG_FUNC_TUNER)
#define POWERSDR_LEVEL_ALL (RIG_LEVEL_SLOPE_HIGH|RIG_LEVEL_SLOPE_LOW|RIG_LEVEL_KEYSPD|RIG_LEVEL_RFPOWER|RIG_LEVEL_RFPOWER_METER|RIG_LEVEL_RFPOWER_METER_WATTS|RIG_LEVEL_MICGAIN|RIG_LEVEL_VOXGAIN|RIG_LEVEL_SQL|RIG_LEVEL_AF|RIG_LEVEL_AGC|RIG_LEVEL_RF|RIG_LEVEL_IF|RIG_LEVEL_STRENGTH)
#define POWERSDR_LEVEL_ALL (RIG_LEVEL_SLOPE_HIGH|RIG_LEVEL_SLOPE_LOW|RIG_LEVEL_KEYSPD|RIG_LEVEL_RFPOWER|RIG_LEVEL_RFPOWER_METER|RIG_LEVEL_RFPOWER_METER_WATTS|RIG_LEVEL_MICGAIN|RIG_LEVEL_VOXGAIN|RIG_LEVEL_SQL|RIG_LEVEL_AF|RIG_LEVEL_AGC|RIG_LEVEL_RF|RIG_LEVEL_IF|RIG_LEVEL_STRENGTH|RIG_LEVEL_SWR)
#define POWERSDR_LEVEL_SET (RIG_LEVEL_SLOPE_HIGH|RIG_LEVEL_SLOPE_LOW|RIG_LEVEL_KEYSPD|RIG_LEVEL_RFPOWER|RIG_LEVEL_MICGAIN|RIG_LEVEL_VOXGAIN|RIG_LEVEL_SQL|RIG_LEVEL_AF|RIG_LEVEL_AGC|RIG_LEVEL_RF|RIG_LEVEL_IF)
@ -837,6 +837,29 @@ int powersdr_get_level(RIG *rig, vfo_t vfo, setting_t level, value_t *val)
ans = 3;
break;
case RIG_LEVEL_SWR:
{
// if not PTT we'll return the last SWR value
// seems desirable to able to see this always
ptt_t ptt;
rig_get_ptt(rig, RIG_VFO_TX, &ptt);
if (!ptt) { val->f = rig->state.cache.swr; return RIG_OK; }
double forward=0, reverse=0;
cmd = "ZZRM5"; // get forward power
len = 5;
ans = 4;
retval = kenwood_safe_transaction(rig, cmd, lvlbuf, sizeof(lvlbuf), len + ans);
if (retval != RIG_OK) { val->f = 0; return RIG_OK;};
sscanf(lvlbuf,"ZZRM5%lg", &forward);
if (forward == 0) { val->f = 1.0; return RIG_OK;}
cmd = "ZZRM7";
retval = kenwood_safe_transaction(rig, cmd, lvlbuf, sizeof(lvlbuf), len + ans);
if (retval != RIG_OK) { val->f = 0; return RIG_OK;};
sscanf(lvlbuf,"ZZRM7%lg", &reverse);
rig->state.cache.swr = val->f = (1.0 + sqrt(reverse/forward)) / (1.0 - sqrt(reverse/forward));
return RIG_OK;
}
default:
return kenwood_get_level(rig, vfo, level, val);
}
@ -921,14 +944,20 @@ int powersdr_get_level(RIG *rig, vfo_t vfo, setting_t level, value_t *val)
case RIG_LEVEL_RFPOWER_METER:
case RIG_LEVEL_RFPOWER_METER_WATTS:
n = sscanf(lvlbuf, "ZZRM5%f", &val->f);
if (n != 1)
{
rig_debug(RIG_DEBUG_ERR, "%s: Error parsing value from lvlbuf='%s'\n",
// if not ptt then no power is going out so return 0W
ptt_t ptt;
rig_get_ptt(rig, RIG_VFO_TX, &ptt);
if (!ptt) { val->f = 0; return RIG_OK; }
n = sscanf(lvlbuf, "ZZRM5%f", &val->f);
if (n != 1)
{
rig_debug(RIG_DEBUG_ERR, "%s: Error parsing value from lvlbuf='%s'\n",
__func__, lvlbuf);
val->f = 0;
return -RIG_EPROTO;
val->f = 0;
return -RIG_EPROTO;
}
}
if (level != RIG_LEVEL_RFPOWER_METER_WATTS)
@ -1321,7 +1350,7 @@ const struct rig_caps powersdr_caps =
RIG_MODEL(RIG_MODEL_POWERSDR),
.model_name = "PowerSDR/Thetis",
.mfg_name = "FlexRadio/ANAN",
.version = "20230819.0",
.version = "20231104.0",
.copyright = "LGPL",
.status = RIG_STATUS_STABLE,
.rig_type = RIG_TYPE_TRANSCEIVER,

Wyświetl plik

@ -1862,15 +1862,17 @@ int kenwood_set_freq(RIG *rig, vfo_t vfo, freq_t freq)
}
// Malchite is so slow we don't do the get_freq
if (!RIG_IS_MALACHITE)
// And when we have detected Doppler operations we just set the freq all the time
// This should provide stable timing for set_ptt operation so relay delays are consistent
if (!RIG_IS_MALACHITE && rig->state.doppler == 0)
{
rig_get_freq(rig, tvfo, &tfreq);
rig_get_freq(rig, tvfo, &tfreq);
if (tfreq == freq)
{
rig_debug(RIG_DEBUG_TRACE, "%s: no freq change needed\n", __func__);
RETURNFUNC2(RIG_OK);
}
if (tfreq == freq)
{
rig_debug(RIG_DEBUG_TRACE, "%s: no freq change needed\n", __func__);
RETURNFUNC2(RIG_OK);
}
}
switch (tvfo)
@ -2861,7 +2863,7 @@ static int kenwood_get_micgain_minmax(RIG *rig, int *micgain_now,
if (retval != RIG_OK) { RETURNFUNC(retval); }
retval = read_string(&rs->rigport, (unsigned char *) levelbuf, sizeof(levelbuf),
NULL, ";", 1, 1);
NULL, 0, 1, 1);
rig_debug(RIG_DEBUG_TRACE, "%s: retval=%d\n", __func__, retval);

Wyświetl plik

@ -28,7 +28,7 @@
#include "token.h"
#include "idx_builtin.h"
#define BACKEND_VER "20231023"
#define BACKEND_VER "20231031"
#define EOM_KEN ';'
#define EOM_TH '\r'

Wyświetl plik

@ -461,14 +461,14 @@ static int ts590_set_level(RIG *rig, vfo_t vfo, setting_t level, value_t val)
switch (level)
{
case RIG_LEVEL_USB_AF:
kenwood_val = val.f * 10;
kenwood_val = val.f * 9;
cmd = 65; // TS-590S
if (rig->caps->rig_model == RIG_MODEL_TS590SG) cmd=72;
SNPRINTF(levelbuf, sizeof(levelbuf), "EX%03d0000%d", cmd, kenwood_val);
break;
case RIG_LEVEL_USB_AF_INPUT:
kenwood_val = val.f * 10;
kenwood_val = val.f * 9;
cmd = 64; // TS-590S
if (rig->caps->rig_model == RIG_MODEL_TS590SG) cmd=71;
SNPRINTF(levelbuf, sizeof(levelbuf), "EX%03d0000%d", cmd, kenwood_val);
@ -673,14 +673,14 @@ static int ts590_get_level(RIG *rig, vfo_t vfo, setting_t level, value_t *val)
cmd = 65; // TS-590S
if (rig->caps->rig_model == RIG_MODEL_TS590SG) cmd=72;
retval = ts590_get_ex_menu(rig, cmd, 1, &levelint);
val->f = levelint / 10.0;
val->f = levelint / 9.0;
return retval;
case RIG_LEVEL_USB_AF_INPUT:
cmd = 65; // TS-590S
if (rig->caps->rig_model == RIG_MODEL_TS590SG) cmd=71;
retval = ts590_get_ex_menu(rig, cmd, 1, &levelint);
val->f = levelint / 10.0;
val->f = levelint / 9.0;
return retval;
case RIG_LEVEL_AF:

Wyświetl plik

@ -204,6 +204,7 @@ const struct rig_caps ftdx101d_caps =
[LVL_MONITOR_GAIN] = { .min = { .f = 0 }, .max = { .f = 1.0 }, .step = { .f = 1.0f/100.0f } },
[LVL_RFPOWER] = { .min = { .f = .05 }, .max = { .f = 1.0 }, .step = { .f = 1.0f/100.0f } },
[LVL_USB_AF] = { .min = { .f = .0 }, .max = { .f = 1.0 }, .step = { .f = 1.0f/100.0f } },
[LVL_USB_AF_INPUT] = { .min = { .f = .0 }, .max = { .f = 1.0 }, .step = { .f = 1.0f/100.0f } },
},
.parm_gran = {
[PARM_BANDSELECT] = {.min = {.f = 0.0f}, .max = {.f = 1.0f}, .step = {.s = "BAND160M,BAND80M,BAND60M,BAND40M,BAND30M,BAND20M,BAND17M,BAND15M,BAND12M,BAND10M,BAND6M,BANDGEN,BANDMW,BANDUNUSED,BANDUNUSED,BANDUNUSED,BANDUNUSED,BAND4M"}}

Wyświetl plik

@ -106,6 +106,7 @@ const struct rig_caps ftdx101mp_caps =
[LVL_MONITOR_GAIN] = { .min = { .f = 0 }, .max = { .f = 1.0 }, .step = { .f = 1.0f/100.0f } },
[LVL_RFPOWER] = { .min = { .f = .05 }, .max = { .f = 1.0 }, .step = { .f = 1.0f/100.0f } },
[LVL_USB_AF] = { .min = { .f = .0 }, .max = { .f = 1.0 }, .step = { .f = 1.0f/100.0f } },
[LVL_USB_AF_INPUT] = { .min = { .f = .0 }, .max = { .f = 1.0 }, .step = { .f = 1.0f/100.0f } },
},
.parm_gran = {
[PARM_BANDSELECT] = {.min = {.f = 0.0f}, .max = {.f = 1.0f}, .step = {.s = "BAND160M,BAND80M,BANDUNUSED,BAND40M,BAND30M,BAND20M,BAND17M,BAND15M,BAND12M,BAND10M,BAND6M,BANDGEN,BANDMW,BANDUNUSED,BANDUNUSED,BANDUNUSED,BANDUNUSED,BAND4M"}}

Wyświetl plik

@ -211,6 +211,8 @@ const cal_table_float_t yaesu_default_id_meter_cal =
static ncboolean is_ft450;
static ncboolean is_ft710;
static ncboolean is_ft891;
static ncboolean is_ft897;
static ncboolean is_ft897d;
static ncboolean is_ft950;
static ncboolean is_ft991;
static ncboolean is_ft2000;
@ -497,6 +499,8 @@ int newcat_init(RIG *rig)
is_ft450 = newcat_is_rig(rig, RIG_MODEL_FT450);
is_ft450 |= newcat_is_rig(rig, RIG_MODEL_FT450D);
is_ft891 = newcat_is_rig(rig, RIG_MODEL_FT891);
is_ft897 = newcat_is_rig(rig, RIG_MODEL_FT897);
is_ft897d = newcat_is_rig(rig, RIG_MODEL_FT897D);
is_ft950 = newcat_is_rig(rig, RIG_MODEL_FT950);
is_ft991 = newcat_is_rig(rig, RIG_MODEL_FT991);
is_ft2000 = newcat_is_rig(rig, RIG_MODEL_FT2000);
@ -847,7 +851,7 @@ int newcat_60m_exception(RIG *rig, freq_t freq, mode_t mode)
}
// some rigs need to skip freq/mode settings as 60M only operates in memory mode
if (is_ft991) { return 1; }
if (is_ft991 || is_ft897 || is_ft897d || is_ftdx5000) { return 1; }
if (!is_ftdx10 && !is_ft710 && !is_ftdx101d && !is_ftdx101mp) { return 0; }
@ -4030,12 +4034,8 @@ int newcat_set_level(RIG *rig, vfo_t vfo, setting_t level, value_t val)
main_sub_vfo = (RIG_VFO_B == vfo || RIG_VFO_SUB == vfo) ? '1' : '0';
}
//TODO Replace the next line
level_info = &rig->caps->level_gran[rig_setting2idx(level)];
// with the next 2 lines
//err = check_level_param(rig, level, val, &level_info);
//if (err != RIG_OK ) { RETURNFUNC(err); }
//endTODO
err = check_level_param(rig, level, val, &level_info);
if (err != RIG_OK ) { RETURNFUNC(err); }
switch (level)
{
@ -4054,19 +4054,6 @@ int newcat_set_level(RIG *rig, vfo_t vfo, setting_t level, value_t val)
fpf = (int)((val.f / level_info->step.f) + 0.5f );
}
//TODO Remove when global level checking enabled
if (is_ft950 || is_ft891 || is_ft991 || is_ftdx3000 || is_ftdx3000dm
|| is_ftdx101d
|| is_ftdx101mp || is_ftdx10)
{
// Minimum is 5 watts on these rigs
if (fpf < 5)
{
fpf = 5;
}
}
//endTODO
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "PC%03d%c", fpf, cat_term);
break;
@ -4076,9 +4063,6 @@ int newcat_set_level(RIG *rig, vfo_t vfo, setting_t level, value_t val)
RETURNFUNC(-RIG_ENAVAIL);
}
//TODO Remove when common level checking enabled
if (val.f > 1.0) { RETURNFUNC(-RIG_EINVAL); }
fpf = (int)((val.f / level_info->step.f) + 0.5f);
if (is_ftdx10) { main_sub_vfo = '0'; }
@ -4207,22 +4191,8 @@ int newcat_set_level(RIG *rig, vfo_t vfo, setting_t level, value_t val)
RETURNFUNC(-RIG_ENAVAIL);
}
//TODO Get rid of these checks when limit checking enabled
if (val.i < 300)
{
i = 300;
}
else if (val.i > 1050)
{
i = 1050;
}
else
{
i = val.i;
}
// Most Yaesu rigs seem to use range of 0-75 to represent pitch of 300..1050 Hz in 10 Hz steps
kp = (i - level_info->min.i + (level_info->step.i / 2)) / level_info->step.i;
kp = (val.i - level_info->min.i + (level_info->step.i / 2)) / level_info->step.i;
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "KP%02d%c", kp, cat_term);
break;
@ -4264,9 +4234,6 @@ int newcat_set_level(RIG *rig, vfo_t vfo, setting_t level, value_t val)
newcat_get_mode(rig, vfo, &mode, &width);
}
//TODO Remove when level_gran check enabled
if (val.f > 1.0) { RETURNFUNC(-RIG_EINVAL); }
fpf = (int) (( val.f / level_info->step.f ) + 0.5f );
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "MG%03d%c", fpf, cat_term);
@ -4790,9 +4757,6 @@ int newcat_set_level(RIG *rig, vfo_t vfo, setting_t level, value_t val)
RETURNFUNC(-RIG_ENAVAIL);
}
//TODO Remove when full level checking enabled
if (val.f > 1.0) { RETURNFUNC(-RIG_EINVAL); }
fpf = (int)((val.f / level_info->step.f) + 0.5f);
if (is_ftdx9000)
@ -4854,24 +4818,25 @@ int newcat_set_level(RIG *rig, vfo_t vfo, setting_t level, value_t val)
if (is_ftdx101d || is_ftdx101mp)
{
rmode_t curmode = rig->state.current_vfo == RIG_VFO_A? rig->state.cache.modeMainA : rig->state.cache.modeMainB;
float valf = val.f / level_info->step.f;
switch(curmode)
{
case RIG_MODE_USB:
case RIG_MODE_LSB:
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "EX010113%03.0f%c", val.f*100, cat_term);
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "EX010113%03.0f%c", valf, cat_term);
break;
case RIG_MODE_AM:
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "EX010214%03.0f%c", val.f*100, cat_term);
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "EX010214%03.0f%c", valf, cat_term);
break;
case RIG_MODE_FM:
case RIG_MODE_FMN:
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "EX010313%03.0f%c", val.f*100, cat_term);
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "EX010313%03.0f%c", valf, cat_term);
break;
case RIG_MODE_PKTFM: // is this the right place for this?
case RIG_MODE_PKTFMN: // is this the right place for this?
case RIG_MODE_PKTUSB:
case RIG_MODE_PKTLSB:
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "EX010415%03.0f%c", val.f*100, cat_term);
SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), "EX010415%03.0f%c", valf, cat_term);
break;
default:
rig_debug(RIG_DEBUG_ERR, "%s: unknown how to set USB_AF for mode=%s\n", __func__, rig_strrmode(curmode));
@ -5498,7 +5463,7 @@ int newcat_get_level(RIG *rig, vfo_t vfo, setting_t level, value_t *val)
}
break;
default:
rig_debug(RIG_DEBUG_ERR, "%s: unknown level=%08lx\n", __func__, level);
rig_debug(RIG_DEBUG_ERR, "%s: unknown level=%08llx\n", __func__, (long long unsigned int)level);
RETURNFUNC(-RIG_EINVAL);
}
@ -5950,7 +5915,7 @@ int newcat_get_level(RIG *rig, vfo_t vfo, setting_t level, value_t *val)
case RIG_LEVEL_USB_AF_INPUT:
i = 0;
sscanf(retlvl, "%3d", &i);
val->f = i / 100.0;
val->f = i * level_info->step.f;
break;
default:

Wyświetl plik

@ -50,7 +50,7 @@
typedef char ncboolean;
/* shared function version */
#define NEWCAT_VER "20231024"
#define NEWCAT_VER "20231101"
/* Hopefully large enough for future use, 128 chars plus '\0' */
#define NEWCAT_DATA_LEN 129

Wyświetl plik

@ -27,6 +27,7 @@ int filternum = 7;
int datamode = 0;
int vfo, vfo_tx, ptt, ptt_data, ptt_mic, ptt_tune;
int tomode = 0;
int keyspd = 25;
int
getmyline(int fd, char *buf)
@ -203,17 +204,6 @@ int main(int argc, char *argv[])
WRITE(fd, buf, strlen(buf));
}
else if (strncmp(buf, "AI", 2) == 0)
{
if (strcmp(buf, "AI;"))
{
printf("%s\n", buf);
hl_usleep(mysleep * 1000);
pbuf = "AI0;";
WRITE(fd, pbuf, strlen(pbuf));
}
}
else if (strcmp(buf, "VS;") == 0)
{
printf("%s\n", buf);
@ -251,10 +241,9 @@ int main(int argc, char *argv[])
{
sscanf(buf, "FB%d", &freqb);
}
else if (strncmp(buf, "AI;", 3) == 0)
else if (strncmp(buf, "AI", 2) == 0)
{
SNPRINTF(buf, sizeof(buf), "AI0;");
WRITE(fd, buf, strlen(buf));
// nothing to do yet
}
else if (strncmp(buf, "PS;", 3) == 0)
@ -314,7 +303,7 @@ int main(int argc, char *argv[])
}
else if (strcmp(buf, "FT;") == 0)
{
SNPRINTF(buf, sizeof(buf), "FR%d;", vfo_tx);
SNPRINTF(buf, sizeof(buf), "FT%d;", vfo_tx);
WRITE(fd, buf, strlen(buf));
}
else if (strncmp(buf, "FT", 2) == 0)
@ -358,12 +347,11 @@ int main(int argc, char *argv[])
}
}
else if (strlen(buf) > 0)
{
fprintf(stderr, "Unknown command: %s\n", buf);
}
}
return 0;

Wyświetl plik

@ -30,8 +30,8 @@ int keyspd = 25;
int width_high = 0;
int width_low = 0;
int afgain = 50;
int usb_af = 5;
int usb_af_input = 2;
int usb_af = 9;
int usb_af_input = 9;
int mic_gain = 50;
int
@ -234,24 +234,42 @@ int main(int argc, char *argv[])
pbuf = "VS0;";
WRITE(fd, pbuf, strlen(pbuf));
}
else if (strcmp(buf, "EX0640000;") == 0)
else if (strcmp(buf, "EX0640000;") == 0) // TS-590S version
{
SNPRINTF(buf, sizeof(buf), "EX0640000%d;", usb_af_input);
WRITE(fd, buf, strlen(buf));
}
else if (strncmp(buf, "EX0640000", 9) == 0)
else if (strncmp(buf, "EX0640000", 9) == 0) // TS-590S version
{
sscanf(buf, "EX0640000%d", &usb_af_input);
}
else if (strcmp(buf, "EX0650000;") == 0)
else if (strcmp(buf, "EX0650000;") == 0) // TS-590S version
{
SNPRINTF(buf, sizeof(buf), "EX0650000%d;", usb_af);
SNPRINTF(buf, sizeof(buf), "EX0650000%d;", usb_af); // TS-590S version
WRITE(fd, buf, strlen(buf));
}
else if (strncmp(buf, "EX0650000", 9) == 0)
else if (strncmp(buf, "EX0650000", 9) == 0) // TS-590S version
{
sscanf(buf, "EX0650000%d", &usb_af);
}
else if (strcmp(buf, "EX0710000;") == 0) // TS-590SG version
{
SNPRINTF(buf, sizeof(buf), "EX0710000%d;", usb_af_input);
WRITE(fd, buf, strlen(buf));
}
else if (strncmp(buf, "EX0710000", 9) == 0) // TS-590SG version
{
sscanf(buf, "EX0710000%d", &usb_af_input);
}
else if (strcmp(buf, "EX0720000;") == 0) // TS-590SG version
{
SNPRINTF(buf, sizeof(buf), "EX0720000%d;", usb_af); // TS-590SG version
WRITE(fd, buf, strlen(buf));
}
else if (strncmp(buf, "EX0720000", 9) == 0) // TS-590S version
{
sscanf(buf, "EX0720000%d", &usb_af);
}
else if (strcmp(buf, "EX032;") == 0)
{
static int ant = 0;

Wyświetl plik

@ -61,6 +61,11 @@ static const struct confparams frontend_cfg_params[] =
"Delay in ms between each command sent out",
"0", RIG_CONF_NUMERIC, { .n = { 0, 1000, 1 } }
},
{
TOK_POST_PTT_DELAY, "post_ptt_delay", "Post ptt delay",
"Delay in ms after PTT is asserted",
"0", RIG_CONF_NUMERIC, { .n = { 0, 2000, 1 } } // 2000ms should be more than enough
},
{
TOK_TIMEOUT, "timeout", "Timeout", "Timeout in ms",
"0", RIG_CONF_NUMERIC, { .n = { 0, 10000, 1 } }
@ -71,7 +76,7 @@ static const struct confparams frontend_cfg_params[] =
},
{
TOK_TIMEOUT_RETRY, "timeout_retry", "Number of retries for read timeouts",
"Set the number of retries for data read timeouts that may occur especially with some serial interfaces",
"Set the # of retries for read timeouts that may occur with some serial interfaces",
"1", RIG_CONF_NUMERIC, { .n = { 0, 100, 1 } }
},
{
@ -84,6 +89,11 @@ static const struct confparams frontend_cfg_params[] =
"The tx/rx range list name",
"Default", RIG_CONF_STRING
},
{
TOK_DEVICE_ID, "device_id", "Device ID",
"User-specified device ID for multicast state data and commands",
"", RIG_CONF_STRING,
},
{
TOK_VFO_COMP, "vfo_comp", "VFO compensation",
@ -91,9 +101,9 @@ static const struct confparams frontend_cfg_params[] =
"0", RIG_CONF_NUMERIC, { .n = { 0.0, 1000.0, .001 } }
},
{
TOK_POLL_INTERVAL, "poll_interval", "Rig state poll interval in milliseconds",
"Polling interval in milliseconds for transceive emulation, value of 0 disables polling",
"0", RIG_CONF_NUMERIC, { .n = { 0, 1000000, 1 } }
TOK_POLL_INTERVAL, "poll_interval", "Rig state poll interval in ms",
"Polling interval in ms for transceive emulation, defaults to 1000, value of 0 disables polling",
"1000", RIG_CONF_NUMERIC, { .n = { 0, 1000000, 1 } }
},
{
TOK_PTT_TYPE, "ptt_type", "PTT type",
@ -102,7 +112,7 @@ static const struct confparams frontend_cfg_params[] =
},
{
TOK_PTT_PATHNAME, "ptt_pathname", "PTT path name",
"Path name to the device file of the Push-To-Talk",
"Path to the device of the Push-To-Talk",
"/dev/rig", RIG_CONF_STRING,
},
{
@ -117,7 +127,7 @@ static const struct confparams frontend_cfg_params[] =
},
{
TOK_DCD_PATHNAME, "dcd_pathname", "DCD path name",
"Path name to the device file of the Data Carrier Detect (or squelch)",
"Path to the device of the Data Carrier Detect (or squelch)",
"/dev/rig", RIG_CONF_STRING,
},
{
@ -172,12 +182,12 @@ static const struct confparams frontend_cfg_params[] =
},
{
TOK_ASYNC, "async", "Asynchronous data transfer support",
"True enables asynchronous data transfer for backends that support it. This allows use of transceive and spectrum data.",
"True enables async data for rigs that support it to allow use of transceive and spectrum data",
"0", RIG_CONF_CHECKBUTTON, { }
},
{
TOK_TUNER_CONTROL_PATHNAME, "tuner_control_pathname", "Tuner script/program path name",
"Path name to a script/program to control a tuner with 1 argument of 0/1 for Tuner Off/On",
"Path to a program to control a tuner with 1 argument of 0/1 for Tuner Off/On",
"hamlib_tuner_control", RIG_CONF_STRING,
},
{
@ -190,6 +200,26 @@ static const struct confparams frontend_cfg_params[] =
"Add Hz to VFOB/Sub frequency set",
"0", RIG_CONF_NUMERIC, { .n = {0, 1e12, 1}}
},
{
TOK_MULTICAST_DATA_ADDR, "multicast_data_addr", "Multicast data UDP address",
"Multicast data UDP address for publishing rig data and state, value of 0.0.0.0 disables multicast data publishing",
"224.0.0.1", RIG_CONF_STRING,
},
{
TOK_MULTICAST_DATA_PORT, "multicast_data_port", "Multicast data UDP port",
"Multicast data UDP port for publishing rig data and state",
"4532", RIG_CONF_NUMERIC, { .n = { 0, 1000000, 1 } }
},
{
TOK_MULTICAST_CMD_ADDR, "multicast_cmd_addr", "Multicast command server UDP address",
"Multicast command UDP address for sending commands to rig, value of 0.0.0.0 disables multicast command server",
"224.0.0.2", RIG_CONF_STRING,
},
{
TOK_MULTICAST_CMD_PORT, "multicast_cmd_port", "Multicast command server UDP port",
"Multicast data UDP port for sending commands to rig",
"4532", RIG_CONF_NUMERIC, { .n = { 0, 1000000, 1 } }
},
{ RIG_CONF_END, NULL, }
};
@ -602,13 +632,21 @@ static int frontend_set_conf(RIG *rig, token_t token, const char *val)
strncpy(rs->dcdport_deprecated.pathname, val, HAMLIB_FILPATHLEN - 1);
break;
case TOK_DEVICE_ID:
strncpy(rs->device_id, val, HAMLIB_RIGNAMSIZ - 1);
break;
case TOK_VFO_COMP:
rs->vfo_comp = atof(val);
break;
case TOK_POLL_INTERVAL:
rs->poll_interval = atof(val);
if (1 != sscanf(val, "%ld", &val_i))
{
return -RIG_EINVAL;
}
rs->poll_interval = val_i;
// Make sure cache times out before next poll cycle
rig_set_cache_timeout_ms(rig, HAMLIB_CACHE_ALL, atol(val));
break;
@ -735,7 +773,31 @@ static int frontend_set_conf(RIG *rig, token_t token, const char *val)
rig_debug(RIG_DEBUG_VERBOSE, "%s: offset_vfob=%ld\n", __func__, val_i);
break;
case TOK_MULTICAST_DATA_ADDR:
rs->multicast_data_addr = strdup(val);
break;
case TOK_MULTICAST_DATA_PORT:
if (1 != sscanf(val, "%ld", &val_i))
{
return -RIG_EINVAL;
}
rs->multicast_data_port = val_i;
break;
case TOK_MULTICAST_CMD_ADDR:
rs->multicast_cmd_addr = strdup(val);
break;
case TOK_MULTICAST_CMD_PORT:
if (1 != sscanf(val, "%ld", &val_i))
{
return -RIG_EINVAL;
}
rs->multicast_cmd_port = val_i;
break;
default:
return -RIG_EINVAL;
@ -770,6 +832,10 @@ static int frontend_get_conf2(RIG *rig, token_t token, char *val, int val_len)
SNPRINTF(val, val_len, "%d", rs->rigport.post_write_delay);
break;
case TOK_POST_PTT_DELAY:
SNPRINTF(val, val_len, "%d", rs->rigport.post_ptt_delay);
break;
case TOK_TIMEOUT:
SNPRINTF(val, val_len, "%d", rs->rigport.timeout);
break;
@ -932,6 +998,10 @@ static int frontend_get_conf2(RIG *rig, token_t token, char *val, int val_len)
strcpy(val, s);
break;
case TOK_DEVICE_ID:
SNPRINTF(val, val_len, "%s", rs->device_id);
break;
case TOK_VFO_COMP:
SNPRINTF(val, val_len, "%f", rs->vfo_comp);
break;
@ -1092,6 +1162,22 @@ static int frontend_get_conf2(RIG *rig, token_t token, char *val, int val_len)
SNPRINTF(val, val_len, "%d", rs->rigport.timeout_retry);
break;
case TOK_MULTICAST_DATA_ADDR:
SNPRINTF(val, val_len, "%s", rs->multicast_data_addr);
break;
case TOK_MULTICAST_DATA_PORT:
SNPRINTF(val, val_len, "%d", rs->multicast_data_port);
break;
case TOK_MULTICAST_CMD_ADDR:
SNPRINTF(val, val_len, "%s", rs->multicast_cmd_addr);
break;
case TOK_MULTICAST_CMD_PORT:
SNPRINTF(val, val_len, "%d", rs->multicast_cmd_port);
break;
default:
return -RIG_EINVAL;
}

Wyświetl plik

@ -64,8 +64,6 @@ typedef struct rig_poll_routine_priv_data_s
rig_poll_routine_args args;
} rig_poll_routine_priv_data;
// TODO: Where to start/stop rig poll routine?
void *rig_poll_routine(void *arg)
{
rig_poll_routine_args *args = (rig_poll_routine_args *)arg;
@ -75,12 +73,11 @@ void *rig_poll_routine(void *arg)
int update_occurred;
vfo_t vfo = RIG_VFO_NONE, vfo_prev = RIG_VFO_NONE;
freq_t freq_main = 0, freq_sub = 0, freq_main_prev = 0, freq_sub_prev = 0;
rmode_t mode_main = RIG_MODE_NONE, mode_sub = RIG_MODE_NONE,
mode_main_prev = RIG_MODE_NONE, mode_sub_prev = RIG_MODE_NONE;
pbwidth_t width_main = 0, width_sub = 0, width_main_prev = 0,
width_sub_prev = 0;
split_t split, split_prev = -1;
freq_t freq_main_a = 0, freq_main_b = 0, freq_main_c = 0, freq_sub_a = 0, freq_sub_b = 0, freq_sub_c = 0;
rmode_t mode_main_a = 0, mode_main_b = 0, mode_main_c = 0, mode_sub_a = 0, mode_sub_b = 0, mode_sub_c = 0;
pbwidth_t width_main_a = 0, width_main_b = 0, width_main_c = 0, width_sub_a = 0, width_sub_b = 0, width_sub_c = 0;
ptt_t ptt = RIG_PTT_OFF;
split_t split = RIG_SPLIT_OFF;
rig_debug(RIG_DEBUG_VERBOSE, "%s(%d): Starting rig poll routine thread\n",
__FILE__, __LINE__);
@ -88,10 +85,119 @@ void *rig_poll_routine(void *arg)
// Rig cache time should be equal to rig poll interval (should be set automatically by rigctld at least)
rig_set_cache_timeout_ms(rig, HAMLIB_CACHE_ALL, rs->poll_interval);
// Attempt to detect changes with the interval below (in milliseconds)
int change_detection_interval = 50;
int interval_count = 0;
update_occurred = 0;
network_publish_rig_poll_data(rig);
while (rs->poll_routine_thread_run)
{
if (rig->state.cache.freqMainA != freq_main_a)
{
freq_main_a = rig->state.cache.freqMainA;
update_occurred = 1;
}
else if (rig->state.cache.freqMainB != freq_main_b)
{
freq_main_b = rig->state.cache.freqMainB;
update_occurred = 1;
}
else if (rig->state.cache.freqMainC != freq_main_c)
{
freq_main_b = rig->state.cache.freqMainC;
update_occurred = 1;
}
else if (rig->state.cache.freqSubA != freq_sub_a)
{
freq_sub_a = rig->state.cache.freqSubA;
update_occurred = 1;
}
else if (rig->state.cache.freqSubB != freq_sub_b)
{
freq_sub_b = rig->state.cache.freqSubB;
update_occurred = 1;
}
else if (rig->state.cache.freqSubC != freq_sub_c)
{
freq_sub_c = rig->state.cache.freqSubC;
update_occurred = 1;
}
else if (rig->state.cache.ptt != ptt)
{
ptt = rig->state.cache.ptt;
update_occurred = 1;
}
else if (rig->state.cache.split != split)
{
split = rig->state.cache.split;
update_occurred = 1;
}
else if (rig->state.cache.modeMainA != mode_main_a)
{
mode_main_a = rig->state.cache.modeMainA;
update_occurred = 1;
}
else if (rig->state.cache.modeMainB != mode_main_b)
{
mode_main_b = rig->state.cache.modeMainB;
update_occurred = 1;
}
else if (rig->state.cache.modeMainC != mode_main_c)
{
mode_main_c = rig->state.cache.modeMainC;
update_occurred = 1;
}
else if (rig->state.cache.modeSubA != mode_sub_a)
{
mode_sub_a = rig->state.cache.modeSubA;
update_occurred = 1;
}
else if (rig->state.cache.modeSubB != mode_sub_b)
{
mode_sub_b = rig->state.cache.modeSubB;
update_occurred = 1;
}
else if (rig->state.cache.modeSubC != mode_sub_c)
{
mode_sub_c = rig->state.cache.modeSubC;
update_occurred = 1;
}
else if (rig->state.cache.widthMainA != width_main_a)
{
width_main_a = rig->state.cache.widthMainA;
update_occurred = 1;
}
else if (rig->state.cache.widthMainB != width_main_b)
{
width_main_b = rig->state.cache.widthMainB;
update_occurred = 1;
}
else if (rig->state.cache.widthMainC != width_main_c)
{
width_main_c = rig->state.cache.widthMainC;
update_occurred = 1;
}
else if (rig->state.cache.widthSubA != width_sub_a)
{
width_sub_a = rig->state.cache.widthSubA;
update_occurred = 1;
}
else if (rig->state.cache.widthSubB != width_sub_b)
{
width_sub_b = rig->state.cache.widthSubB;
update_occurred = 1;
}
else if (rig->state.cache.widthSubC != width_sub_c)
{
width_sub_c = rig->state.cache.widthSubC;
update_occurred = 1;
}
// The original code here actively reads rig state, which can be too intensive and intrusive
#if 0
if (rig->caps->get_vfo)
{
result = rig_get_vfo(rig, &vfo);
@ -225,15 +331,28 @@ void *rig_poll_routine(void *arg)
split_prev = split;
}
}
#endif
if (update_occurred)
{
network_publish_rig_poll_data(rig);
update_occurred = 0;
interval_count = 0;
}
hl_usleep(rs->poll_interval * 1000);
hl_usleep(change_detection_interval * 1000);
interval_count++;
// Publish updates every poll_interval if no changes have been detected
if (interval_count >= (rs->poll_interval / change_detection_interval))
{
interval_count = 0;
network_publish_rig_poll_data(rig);
}
}
network_publish_rig_poll_data(rig);
rig_debug(RIG_DEBUG_VERBOSE, "%s(%d): Stopping rig poll routine thread\n",
__FILE__,
__LINE__);
@ -291,6 +410,8 @@ int rig_poll_routine_start(RIG *rig)
RETURNFUNC(-RIG_EINTERNAL);
}
network_publish_rig_poll_data(rig);
RETURNFUNC(RIG_OK);
}
@ -336,6 +457,8 @@ int rig_poll_routine_stop(RIG *rig)
poll_routine_priv->thread_id = 0;
}
network_publish_rig_poll_data(rig);
free(rs->poll_routine_priv_data);
rs->poll_routine_priv_data = NULL;

Wyświetl plik

@ -2707,6 +2707,42 @@ const char *HAMLIB_API rig_get_caps_cptr(rig_model_t rig_model,
}
}
static const struct
{
rig_comm_status_t status;
const char *str;
} comm_status_str[] =
{
{ RIG_COMM_STATUS_OK, "OK" },
{ RIG_COMM_STATUS_CONNECTING, "CONNECTING" },
{ RIG_COMM_STATUS_DISCONNECTED, "DISCONNECTED" },
{ RIG_COMM_STATUS_TERMINATED, "TERMINATIED" },
{ RIG_COMM_STATUS_WARNING, "WARNING" },
{ RIG_COMM_STATUS_ERROR, "ERROR" },
{ 0xffffffff, "" },
};
/**
* \brief Convert enum RIG_COMM_STATUS... to alpha string
* \param vfo RIG_COMM_STATUS_...
* \return alpha string
*/
const char *HAMLIB_API rig_strcommstatus(rig_comm_status_t status)
{
int i;
for (i = 0; comm_status_str[i].str[0] != '\0'; i++)
{
if (status == comm_status_str[i].status)
{
return comm_status_str[i].str;
}
}
return "";
}
void errmsg(int err, char *s, const char *func, const char *file, int line)
{
rig_debug(RIG_DEBUG_ERR, "%s(%s:%d): %s: %s\b", __func__, file, line, s,

Wyświetl plik

@ -1,6 +1,6 @@
/*
* Hamlib Interface - network communication low-level support
* Copyright (c) 2021 by Mikael Nousiainen
* Copyright (c) 2021-2023 by Mikael Nousiainen
* Copyright (c) 2000-2012 by Stephane Fillod
*
* This library is free software; you can redistribute it and/or
@ -126,6 +126,20 @@ typedef struct multicast_publisher_priv_data_s
multicast_publisher_args args;
} multicast_publisher_priv_data;
typedef struct multicast_receiver_args_s
{
RIG *rig;
int socket_fd;
const char *multicast_addr;
int multicast_port;
} multicast_receiver_args;
typedef struct multicast_receiver_priv_data_s
{
pthread_t thread_id;
multicast_receiver_args args;
} multicast_receiver_priv_data;
static void handle_error(enum rig_debug_level_e lvl, const char *msg)
{
int e;
@ -714,7 +728,7 @@ static int multicast_publisher_write_packet_header(RIG *rig,
if (rs->multicast_publisher_priv_data == NULL)
{
// Silently ignore if multicast publisher is not enabled
RETURNFUNC2(RIG_OK);
return RIG_OK;
}
mcast_publisher_priv = (multicast_publisher_priv_data *)
@ -727,10 +741,10 @@ static int multicast_publisher_write_packet_header(RIG *rig,
if (result != RIG_OK)
{
RETURNFUNC2(result);
return result;
}
RETURNFUNC2(RIG_OK);
return RIG_OK;
}
// cppcheck-suppress unusedFunction
@ -773,7 +787,6 @@ int network_publish_rig_transceive_data(RIG *rig)
return multicast_publisher_write_packet_header(rig, &packet);
}
// cppcheck-suppress unusedFunction
int network_publish_rig_spectrum_data(RIG *rig, struct rig_spectrum_line *line)
{
int result;
@ -908,6 +921,8 @@ void *multicast_publisher(void *arg)
rig_debug(RIG_DEBUG_VERBOSE, "%s(%d): Starting multicast publisher\n", __FILE__,
__LINE__);
snapshot_init();
memset(&dest_addr, 0, sizeof(dest_addr));
dest_addr.sin_family = AF_INET;
dest_addr.sin_addr.s_addr = inet_addr(args->multicast_addr);
@ -930,7 +945,7 @@ void *multicast_publisher(void *arg)
// TODO: how to detect closing of pipe, indicate with error code
// TODO: error handling, flush pipe in case of error?
hl_usleep(500 * 1000);
hl_usleep(100 * 1000);
continue;
}
@ -969,6 +984,146 @@ void *multicast_publisher(void *arg)
return NULL;
}
void *multicast_receiver(void *arg)
{
char data[4096];
struct multicast_receiver_args_s *args = (struct multicast_receiver_args_s *)
arg;
RIG *rig = args->rig;
struct rig_state *rs = &rig->state;
struct sockaddr_in dest_addr;
int socket_fd = args->socket_fd;
rig_debug(RIG_DEBUG_VERBOSE, "%s(%d): Starting multicast receiver\n", __FILE__,
__LINE__);
int optval = 1;
#ifdef __MINGW32__
if (setsockopt(socket_fd, SOL_SOCKET, SO_REUSEADDR, (PCHAR)&optval, sizeof(optval)) < 0)
#else
if (setsockopt(socket_fd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval)) < 0)
#endif
{
rig_debug(RIG_DEBUG_ERR, "%s: error enabling UDP address reuse: %s\n", __func__,
strerror(errno));
return NULL;
}
// Windows does not have SO_REUSEPORT. However, SO_REUSEADDR works in a similar way.
#if defined(SO_REUSEPORT)
if (setsockopt(socket_fd, SOL_SOCKET, SO_REUSEPORT, &optval, sizeof(optval)) < 0)
{
rig_debug(RIG_DEBUG_ERR, "%s: error enabling UDP port reuse: %s\n", __func__,
strerror(errno));
return NULL;
}
#endif
memset(&dest_addr, 0, sizeof(dest_addr));
dest_addr.sin_family = AF_INET;
#ifdef __MINGW32__
// Windows cannot bind to multicast group addresses for some unknown reason
dest_addr.sin_addr.s_addr = htonl(INADDR_ANY);
#else
dest_addr.sin_addr.s_addr = inet_addr(args->multicast_addr);
#endif
dest_addr.sin_port = htons(args->multicast_port);
if (bind(socket_fd, (struct sockaddr *) &dest_addr, sizeof(dest_addr)) < 0)
{
rig_debug(RIG_DEBUG_ERR, "%s: error binding UDP socket to %s:%d: %s\n", __func__,
args->multicast_addr, args->multicast_port, strerror(errno));
return NULL;
}
struct ip_mreq mreq;
memset(&mreq, 0, sizeof(mreq));
mreq.imr_multiaddr.s_addr = inet_addr(args->multicast_addr);
mreq.imr_interface.s_addr = htonl(INADDR_ANY);
#ifdef __MINGW32__
if (setsockopt(socket_fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, (PCHAR)&mreq, sizeof(mreq)) < 0)
#else
if (setsockopt(socket_fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) < 0)
#endif
{
rig_debug(RIG_DEBUG_ERR, "%s: error joining multicast group %s:%d: %s\n", __func__,
args->multicast_addr, args->multicast_port, strerror(errno));
return NULL;
}
rs->multicast_receiver_run = 1;
while (rs->multicast_receiver_run == 1)
{
struct sockaddr_in client_addr;
socklen_t client_len = sizeof(client_addr);
fd_set rfds, efds;
struct timeval timeout;
int select_result;
ssize_t result;
timeout.tv_sec = 1;
timeout.tv_usec = 0;
FD_ZERO(&rfds);
FD_SET(socket_fd, &rfds);
efds = rfds;
select_result = select(socket_fd + 1, &rfds, NULL, &efds, &timeout);
if (select_result == 0)
{
// Select timed out
continue;
}
if (select_result < 0)
{
rig_debug(RIG_DEBUG_ERR,
"%s(): select() failed when reading UDP multicast socket data: %s\n",
__func__,
strerror(errno));
break;
}
if (FD_ISSET(socket_fd, &efds))
{
rig_debug(RIG_DEBUG_ERR,
"%s(): fd error when reading UDP multicast socket data\n", __func__);
break;
}
result = recvfrom(socket_fd, data, sizeof(data), 0, (struct sockaddr *) &client_addr, &client_len);
if (result <= 0)
{
if (result < 0)
{
if (errno == 0 || errno == EAGAIN || errno == EWOULDBLOCK)
{
continue;
}
rig_debug(RIG_DEBUG_ERR, "%s: error receiving from UDP socket %s:%d: %s\n", __func__,
args->multicast_addr, args->multicast_port, strerror(errno));
}
break;
}
// TODO: handle commands from multicast clients
rig_debug(RIG_DEBUG_VERBOSE, "%s: received %ld bytes of data: %.*s\n", __func__, (long) result, (int) result, data);
// TODO: if a new snapshot needs to be sent, call network_publish_rig_poll_data() and the publisher routine will send out a snapshot
// TODO: new logic in publisher needs to be written for other types of responses
}
rig_debug(RIG_DEBUG_VERBOSE, "%s(%d): Stopping multicast receiver\n", __FILE__,
__LINE__);
return NULL;
}
//! @endcond
/**
@ -990,11 +1145,11 @@ int network_multicast_publisher_start(RIG *rig, const char *multicast_addr,
ENTERFUNC;
rig_debug(RIG_DEBUG_VERBOSE, "%s(%d):multicast address=%s, port=%d\n", __FILE__,
rig_debug(RIG_DEBUG_VERBOSE, "%s(%d): multicast publisher address=%s, port=%d\n", __FILE__,
__LINE__,
multicast_addr, multicast_port);
if (strcmp(multicast_addr, "0.0.0.0") == 0)
if (multicast_addr == NULL || strcmp(multicast_addr, "0.0.0.0") == 0)
{
rig_debug(RIG_DEBUG_TRACE, "%s(%d): not starting multicast publisher\n",
__FILE__, __LINE__);
@ -1025,6 +1180,24 @@ int network_multicast_publisher_start(RIG *rig, const char *multicast_addr,
RETURNFUNC(-RIG_EIO);
}
// Enable non-blocking mode
u_long mode = 1;
#ifdef __MINGW32__
if (ioctlsocket(socket_fd, FIONBIO, &mode) == SOCKET_ERROR)
{
rig_debug(RIG_DEBUG_ERR, "%s: error enabling non-blocking mode for socket: %s", __func__,
strerror(errno));
RETURNFUNC(-RIG_EIO);
}
#else
if (ioctl(socket_fd, FIONBIO, &mode) < 0)
{
rig_debug(RIG_DEBUG_ERR, "%s: error enabling non-blocking mode for socket: %s", __func__,
strerror(errno));
RETURNFUNC(-RIG_EIO);
}
#endif
if (items & RIG_MULTICAST_TRANSCEIVE)
{
rig_debug(RIG_DEBUG_VERBOSE, "%s(%d) MULTICAST_TRANSCEIVE enabled\n", __FILE__,
@ -1036,11 +1209,6 @@ int network_multicast_publisher_start(RIG *rig, const char *multicast_addr,
rig_debug(RIG_DEBUG_VERBOSE, "%s(%d) MULTICAST_SPECTRUM enabled\n", __FILE__,
__LINE__);
}
else
{
rig_debug(RIG_DEBUG_ERR, "%s(%d) unknown MULTICAST item requested=0x%x\n",
__FILE__, __LINE__, items);
}
rs->snapshot_packet_sequence_number = 0;
rs->multicast_publisher_run = 1;
@ -1142,5 +1310,172 @@ int network_multicast_publisher_stop(RIG *rig)
RETURNFUNC(RIG_OK);
}
/**
* \brief Start multicast receiver
*
* Start multicast receiver.
*
* \param multicast_addr UDP address
* \param multicast_port UDP socket port
* \return RIG_OK or < 0 if error
*/
int network_multicast_receiver_start(RIG *rig, const char *multicast_addr, int multicast_port)
{
struct rig_state *rs = &rig->state;
multicast_receiver_priv_data *mcast_receiver_priv;
int socket_fd;
int status;
ENTERFUNC;
rig_debug(RIG_DEBUG_VERBOSE, "%s(%d): multicast receiver address=%s, port=%d\n", __FILE__,
__LINE__,
multicast_addr, multicast_port);
if (multicast_addr == NULL || strcmp(multicast_addr, "0.0.0.0") == 0)
{
rig_debug(RIG_DEBUG_TRACE, "%s(%d): not starting multicast receiver\n",
__FILE__, __LINE__);
return RIG_OK;
}
if (rs->multicast_receiver_priv_data != NULL)
{
rig_debug(RIG_DEBUG_ERR, "%s(%d): multicast receiver already running\n",
__FILE__,
__LINE__);
RETURNFUNC(-RIG_EINVAL);
}
status = network_init();
if (status != RIG_OK)
{
RETURNFUNC(status);
}
socket_fd = socket(AF_INET, SOCK_DGRAM, 0);
if (socket_fd < 0)
{
rig_debug(RIG_DEBUG_ERR, "%s: error opening new UDP socket: %s", __func__,
strerror(errno));
RETURNFUNC(-RIG_EIO);
}
// Enable non-blocking mode
u_long mode = 1;
#ifdef __MINGW32__
if (ioctlsocket(socket_fd, FIONBIO, &mode) == SOCKET_ERROR)
{
rig_debug(RIG_DEBUG_ERR, "%s: error enabling non-blocking mode for socket: %s", __func__,
strerror(errno));
RETURNFUNC(-RIG_EIO);
}
#else
if (ioctl(socket_fd, FIONBIO, &mode) < 0)
{
rig_debug(RIG_DEBUG_ERR, "%s: error enabling non-blocking mode for socket: %s", __func__,
strerror(errno));
RETURNFUNC(-RIG_EIO);
}
#endif
rs->multicast_receiver_run = 1;
rs->multicast_receiver_priv_data = calloc(1,
sizeof(multicast_receiver_priv_data));
if (rs->multicast_receiver_priv_data == NULL)
{
close(socket_fd);
RETURNFUNC(-RIG_ENOMEM);
}
mcast_receiver_priv = (multicast_receiver_priv_data *)
rs->multicast_receiver_priv_data;
mcast_receiver_priv->args.socket_fd = socket_fd;
mcast_receiver_priv->args.multicast_addr = multicast_addr;
mcast_receiver_priv->args.multicast_port = multicast_port;
mcast_receiver_priv->args.rig = rig;
int err = pthread_create(&mcast_receiver_priv->thread_id, NULL,
multicast_receiver,
&mcast_receiver_priv->args);
if (err)
{
rig_debug(RIG_DEBUG_ERR, "%s(%d) pthread_create error %s\n", __FILE__, __LINE__,
strerror(errno));
free(mcast_receiver_priv);
rs->multicast_receiver_priv_data = NULL;
close(socket_fd);
RETURNFUNC(-RIG_EINTERNAL);
}
RETURNFUNC(RIG_OK);
}
/**
* \brief Stop multicast receiver
*
* Stop multicast receiver
*
* \return RIG_OK or < 0 if error
*/
int network_multicast_receiver_stop(RIG *rig)
{
struct rig_state *rs = &rig->state;
multicast_receiver_priv_data *mcast_receiver_priv;
ENTERFUNC;
rs->multicast_receiver_run = 0;
mcast_receiver_priv = (multicast_receiver_priv_data *)
rs->multicast_receiver_priv_data;
if (mcast_receiver_priv == NULL)
{
RETURNFUNC(RIG_OK);
}
// Close the socket first to stop the routine
if (mcast_receiver_priv->args.socket_fd >= 0)
{
#ifdef __MINGW32__
shutdown(mcast_receiver_priv->args.socket_fd, SD_BOTH);
#else
shutdown(mcast_receiver_priv->args.socket_fd, SHUT_RDWR);
#endif
close(mcast_receiver_priv->args.socket_fd);
}
if (mcast_receiver_priv->thread_id != 0)
{
int err = pthread_join(mcast_receiver_priv->thread_id, NULL);
if (err)
{
rig_debug(RIG_DEBUG_ERR, "%s(%d): pthread_join error %s\n", __FILE__, __LINE__,
strerror(errno));
// just ignore it
}
mcast_receiver_priv->thread_id = 0;
}
if (mcast_receiver_priv->args.socket_fd >= 0)
{
mcast_receiver_priv->args.socket_fd = -1;
}
free(rs->multicast_receiver_priv_data);
rs->multicast_receiver_priv_data = NULL;
RETURNFUNC(RIG_OK);
}
#endif
/** @} */

Wyświetl plik

@ -34,8 +34,11 @@ void network_flush(hamlib_port_t *rp);
int network_publish_rig_poll_data(RIG *rig);
int network_publish_rig_transceive_data(RIG *rig);
int network_publish_rig_spectrum_data(RIG *rig, struct rig_spectrum_line *line);
int network_publish_rig_status_change(RIG *rig, int32_t status);
HAMLIB_EXPORT(int) network_multicast_publisher_start(RIG *rig, const char *multicast_addr, int multicast_port, enum multicast_item_e items);
HAMLIB_EXPORT(int) network_multicast_publisher_stop(RIG *rig);
HAMLIB_EXPORT(int) network_multicast_receiver_start(RIG *rig, const char *multicast_addr, int multicast_port);
HAMLIB_EXPORT(int) network_multicast_receiver_stop(RIG *rig);
__END_DECLS

Wyświetl plik

@ -604,6 +604,7 @@ RIG *HAMLIB_API rig_init(rig_model_t rig_model)
#if defined(HAVE_PTHREAD)
rs->rigport.asyncio = 0;
#endif
rig->state.comm_status = RIG_COMM_STATUS_CONNECTING;
rs->tuner_control_pathname = DEFAULT_TUNER_CONTROL_PATHNAME;
@ -682,7 +683,11 @@ RIG *HAMLIB_API rig_init(rig_model_t rig_model)
rs->current_vfo = RIG_VFO_CURR; /* we don't know yet! */
rs->rx_vfo = RIG_VFO_CURR; /* we don't know yet! */
rs->tx_vfo = RIG_VFO_CURR; /* we don't know yet! */
rs->poll_interval = 0; // disable polling by default
rs->poll_interval = 1000; // enable polling by default
rs->multicast_data_addr = "224.0.0.1"; // enable multicast data publishing by default
rs->multicast_data_port = 4532;
rs->multicast_cmd_addr = "224.0.0.2"; // enable multicast command server by default
rs->multicast_cmd_port = 4532;
rs->lo_freq = 0;
rs->cache.timeout_ms = 500; // 500ms cache timeout by default
rs->cache.ptt = 0;
@ -1054,6 +1059,8 @@ int HAMLIB_API rig_open(RIG *rig)
RETURNFUNC2(-RIG_EINVAL);
}
rs->comm_status = RIG_COMM_STATUS_CONNECTING;
rs->rigport.fd = -1;
if (rs->rigport.type.rig == RIG_PORT_SERIAL)
@ -1102,6 +1109,7 @@ int HAMLIB_API rig_open(RIG *rig)
rig_debug(RIG_DEBUG_VERBOSE, "%s: rs->comm_state==0?=%d\n", __func__,
rs->comm_state);
rs->comm_state = 0;
rig->state.comm_status = RIG_COMM_STATUS_ERROR;
RETURNFUNC2(status);
}
@ -1320,6 +1328,7 @@ int HAMLIB_API rig_open(RIG *rig)
if (status < 0)
{
port_close(&rs->rigport, rs->rigport.type.rig);
rig->state.comm_status = RIG_COMM_STATUS_ERROR;
RETURNFUNC2(status);
}
@ -1328,11 +1337,10 @@ int HAMLIB_API rig_open(RIG *rig)
if (status < 0)
{
port_close(&rs->rigport, rs->rigport.type.rig);
rig->state.comm_status = RIG_COMM_STATUS_ERROR;
RETURNFUNC2(status);
}
add_opened_rig(rig);
rs->comm_state = 1;
rig_debug(RIG_DEBUG_VERBOSE, "%s: %p rs->comm_state==1?=%d\n", __func__,
&rs->comm_state,
@ -1385,6 +1393,7 @@ int HAMLIB_API rig_open(RIG *rig)
port_close(&rs->rigport, rs->rigport.type.rig);
memcpy(&rs->rigport_deprecated, &rs->rigport, sizeof(hamlib_port_t_deprecated));
rs->comm_state = 0;
rig->state.comm_status = RIG_COMM_STATUS_ERROR;
RETURNFUNC2(status);
}
}
@ -1489,22 +1498,40 @@ int HAMLIB_API rig_open(RIG *rig)
memcpy(&rs->pttport_deprecated, &rs->pttport, sizeof(hamlib_port_t_deprecated));
memcpy(&rs->dcdport_deprecated, &rs->dcdport, sizeof(hamlib_port_t_deprecated));
rig_flush_force(&rs->rigport, 1);
// if (rig->caps->rig_model != RIG_MODEL_NETRIGCTL) multicast_init(rig, "224.0.0.1", 4532);
// multicast_init(rig, "224.0.0.1", 4532);
char *multicast_addr = "224.0.0.1";
int multicast_port = 4532;
enum multicast_item_e items = RIG_MULTICAST_POLL | RIG_MULTICAST_TRANSCEIVE;
// | RIG_MULTICAST_SPECTRUM;
retval = network_multicast_publisher_start(rig, multicast_addr,
multicast_port, items);
enum multicast_item_e items = RIG_MULTICAST_POLL | RIG_MULTICAST_TRANSCEIVE
| RIG_MULTICAST_SPECTRUM;
retval = network_multicast_publisher_start(rig, rs->multicast_data_addr,
rs->multicast_data_port, items);
if (retval != RIG_OK)
{
rig_debug(RIG_DEBUG_ERR, "%s: network_multicast_server failed: %s\n", __FILE__,
rig_debug(RIG_DEBUG_ERR, "%s: network_multicast_publisher_start failed: %s\n", __FILE__,
rigerror(retval));
// we will consider this non-fatal for now
}
retval = network_multicast_receiver_start(rig, rs->multicast_cmd_addr, rs->multicast_cmd_port);
if (retval != RIG_OK)
{
rig_debug(RIG_DEBUG_ERR, "%s: network_multicast_receiver_start failed: %s\n", __FILE__,
rigerror(retval));
// we will consider this non-fatal for now
}
retval = rig_poll_routine_start(rig);
if (retval != RIG_OK)
{
rig_debug(RIG_DEBUG_ERR, "%s: rig_poll_routine_start failed: %s\n", __FILE__,
rigerror(retval));
// we will consider this non-fatal for now
}
rig->state.comm_status = RIG_COMM_STATUS_OK;
add_opened_rig(rig);
RETURNFUNC2(RIG_OK);
}
@ -1544,11 +1571,15 @@ int HAMLIB_API rig_close(RIG *rig)
RETURNFUNC(-RIG_EINVAL);
}
remove_opened_rig(rig);
rig->state.comm_status = RIG_COMM_STATUS_DISCONNECTED;
morse_data_handler_stop(rig);
async_data_handler_stop(rig);
rig_poll_routine_stop(rig);
network_multicast_receiver_stop(rig);
network_multicast_publisher_stop(rig);
//while(rs->multicast_publisher_run != 2) hl_usleep(10*1000);
//multicast_stop(rig);
/*
* Let the backend say 73s to the rig.
@ -1663,8 +1694,6 @@ int HAMLIB_API rig_close(RIG *rig)
port_close(&rs->rigport, rs->rigport.type.rig);
remove_opened_rig(rig);
// zero split so it will allow it to be set again on open for rigctld
rig->state.cache.split = 0;
rs->comm_state = 0;
@ -1892,6 +1921,28 @@ int rig_set_freq(RIG *rig, vfo_t vfo, freq_t freq)
rig_strvfo(vfo), freq);
#endif
if (rig->state.doppler == 0)
{
if (vfo == RIG_VFO_A || vfo == RIG_VFO_MAIN || (vfo == RIG_VFO_CURR && rig->state.current_vfo == RIG_VFO_A))
{
if (rig->state.cache.freqMainA != freq && (((int)freq % 10) != 0))
{
rig->state.doppler = 1;
rig_debug(RIG_DEBUG_VERBOSE, "%s(%d): potential doppler detected because old freq %f != new && new freq has 1Hz or such values\n", __func__, __LINE__, rig->state.cache.freqMainA);
}
freq += rig->state.offset_vfoa;
}
else if (vfo == RIG_VFO_B || vfo == RIG_VFO_SUB || (vfo == RIG_VFO_CURR && rig->state.current_vfo == RIG_VFO_B))
{
if (rig->state.cache.freqMainB != freq && ((int)freq % 10) != 0)
{
rig->state.doppler = 1;
rig_debug(RIG_DEBUG_VERBOSE, "%s(%d): potential doppler detected because old freq %f != new && new freq has 1Hz or such values\n", __func__, __LINE__, rig->state.cache.freqMainB);
}
freq += rig->state.offset_vfob;
}
}
if (vfo == RIG_VFO_A || vfo == RIG_VFO_MAIN) { freq += rig->state.offset_vfoa; }
else if (vfo == RIG_VFO_B || vfo == RIG_VFO_SUB) { freq += rig->state.offset_vfob; }
@ -2300,9 +2351,11 @@ int HAMLIB_API rig_get_freq(RIG *rig, vfo_t vfo, freq_t *freq)
__LINE__, rig->state.vfo_opt, rig->caps->rig_model);
// If we're in vfo_mode then rigctld will do any VFO swapping we need
// If we detected doppler we skip the frequency check to make timing more consistent for relay control
if ((caps->targetable_vfo & RIG_TARGETABLE_FREQ)
|| vfo == RIG_VFO_CURR || vfo == rig->state.current_vfo
|| (rig->state.vfo_opt == 1 && rig->caps->rig_model == RIG_MODEL_NETRIGCTL))
|| (rig->state.vfo_opt == 1 && rig->caps->rig_model == RIG_MODEL_NETRIGCTL
&& rig->state.doppler == 0))
{
// If rig does not have set_vfo we need to change vfo
if (vfo == RIG_VFO_CURR && caps->set_vfo == NULL)
@ -3484,6 +3537,7 @@ int HAMLIB_API rig_set_ptt(RIG *rig, vfo_t vfo, ptt_t ptt)
memcpy(&rig->state.pttport_deprecated, &rig->state.pttport,
sizeof(rig->state.pttport_deprecated));
if (rig->state.rigport.post_ptt_delay > 0) hl_usleep(rig->state.rigport.post_ptt_delay*1000);
ELAPSED2;
RETURNFUNC(retcode);

Wyświetl plik

@ -15,35 +15,21 @@
#define SPECTRUM_MODE_FIXED "FIXED"
#define SPECTRUM_MODE_CENTER "CENTER"
char snapshot_data_pid[20];
static int snapshot_serialize_rig(cJSON *rig_node, RIG *rig)
{
cJSON *node;
char buf[1024];
#if 0
// TODO: need to assign rig an ID, e.g. from command line
snprintf(buf, sizeof(buf), "%s:%s:%d", rig->caps->model_name,
rig->state.rigport.pathname, getpid());
node = cJSON_AddStringToObject(rig_node, "id", buf);
if (node == NULL)
{
goto error;
}
#else
cJSON *id_node = cJSON_CreateObject();
cJSON_AddStringToObject(id_node, "model", rig->caps->model_name);
cJSON_AddStringToObject(id_node, "endpoint", rig->state.rigport.pathname);
char pid[16];
sprintf(pid,"%d",getpid());
cJSON_AddStringToObject(id_node, "process", pid);
cJSON_AddStringToObject(id_node, "process", snapshot_data_pid);
cJSON_AddStringToObject(id_node, "deviceId", rig->state.device_id);
cJSON_AddItemToObject(rig_node, "id", id_node);
#endif
// TODO: what kind of status should this reflect?
node = cJSON_AddStringToObject(rig_node, "status",
rig->state.comm_state ? "OK" : "CLOSED");
node = cJSON_AddStringToObject(rig_node, "status", rig_strcommstatus(rig->state.comm_status));
if (node == NULL)
{
@ -161,19 +147,26 @@ static int snapshot_serialize_vfo(cJSON *vfo_node, RIG *rig, vfo_t vfo)
}
}
split = rig->state.cache.split;
split_vfo = rig->state.cache.split_vfo;
is_rx = (split == RIG_SPLIT_OFF && vfo == rig->state.current_vfo)
|| (split == RIG_SPLIT_ON && vfo != split_vfo);
is_tx = (split == RIG_SPLIT_OFF && vfo == rig->state.current_vfo)
|| (split == RIG_SPLIT_ON && vfo == split_vfo);
ptt = rig->state.cache.ptt;
if (is_tx)
node = cJSON_AddBoolToObject(vfo_node, "ptt", ptt == RIG_PTT_OFF ? 0 : 1);
else
node = cJSON_AddBoolToObject(vfo_node, "ptt", 0);
if (node == NULL)
{
goto error;
}
split = rig->state.cache.split;
split_vfo = rig->state.cache.split_vfo;
is_rx = (split == RIG_SPLIT_OFF && vfo == rig->state.current_vfo)
|| (split == RIG_SPLIT_ON && vfo != split_vfo);
node = cJSON_AddBoolToObject(vfo_node, "rx", is_rx);
if (node == NULL)
@ -181,8 +174,6 @@ static int snapshot_serialize_vfo(cJSON *vfo_node, RIG *rig, vfo_t vfo)
goto error;
}
is_tx = (split == RIG_SPLIT_OFF && vfo == rig->state.current_vfo)
|| (split == RIG_SPLIT_ON && vfo == split_vfo);
node = cJSON_AddBoolToObject(vfo_node, "tx", is_tx);
if (node == NULL)
@ -325,6 +316,11 @@ error:
RETURNFUNC2(-RIG_EINTERNAL);
}
void snapshot_init()
{
snprintf(snapshot_data_pid, sizeof(snapshot_data_pid), "%d", getpid());
}
int snapshot_serialize(size_t buffer_length, char *buffer, RIG *rig,
struct rig_spectrum_line *spectrum_line)
{

Wyświetl plik

@ -1,6 +1,7 @@
#ifndef _SNAPSHOT_DATA_H
#define _SNAPSHOT_DATA_H
void snapshot_init();
int snapshot_serialize(size_t buffer_length, char *buffer, RIG *rig, struct rig_spectrum_line *spectrum_line);
#endif

Wyświetl plik

@ -97,6 +97,8 @@
#define TOK_TUNER_CONTROL_PATHNAME TOKEN_FRONTEND(38)
/** \brief Number of retries permitted in case of read timeouts */
#define TOK_TIMEOUT_RETRY TOKEN_FRONTEND(39)
#define TOK_POST_PTT_DELAY TOKEN_FRONTEND(40)
#define TOK_DEVICE_ID TOKEN_FRONTEND(41)
/*
* rig specific tokens
@ -131,6 +133,15 @@
#define TOK_OFFSET_VFOA TOKEN_FRONTEND(130)
/** \brief rig: Add Hz to VFOB/Sub frequency set */
#define TOK_OFFSET_VFOB TOKEN_FRONTEND(131)
/** \brief rig: Multicast data UDP address for publishing rig data and state, default 224.0.0.1, value of 0.0.0.0 disables multicast data publishing */
#define TOK_MULTICAST_DATA_ADDR TOKEN_FRONTEND(132)
/** \brief rig: Multicast data UDP port, default 4532 */
#define TOK_MULTICAST_DATA_PORT TOKEN_FRONTEND(133)
/** \brief rig: Multicast command server UDP address for sending commands to rig, default 224.0.0.2, value of 0.0.0.0 disables multicast command server */
#define TOK_MULTICAST_CMD_ADDR TOKEN_FRONTEND(134)
/** \brief rig: Multicast command server UDP port, default 4532 */
#define TOK_MULTICAST_CMD_PORT TOKEN_FRONTEND(135)
/*
* rotator specific tokens
* (strictly, should be documented as rotator_internal)

Wyświetl plik

@ -19,8 +19,8 @@ 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 testmW2power
RIGCOMMONSRC = rigctl_parse.c rigctl_parse.h dumpcaps.c dumpstate.c uthash.h rig_tests.c rig_tests.h
ROTCOMMONSRC = rotctl_parse.c rotctl_parse.h dumpcaps_rot.c uthash.h
RIGCOMMONSRC = rigctl_parse.c rigctl_parse.h dumpcaps.c dumpstate.c uthash.h rig_tests.c rig_tests.h dumpcaps.h
ROTCOMMONSRC = rotctl_parse.c rotctl_parse.h dumpcaps_rot.c uthash.h dumpcaps_rot.h
AMPCOMMONSRC = ampctl_parse.c ampctl_parse.h dumpcaps_amp.c uthash.h
rigctl_SOURCES = rigctl.c $(RIGCOMMONSRC)

Wyświetl plik

@ -298,12 +298,28 @@ int main(int argc, char *argv[])
exit(2);
}
retcode = set_conf(my_amp, conf_parms);
char *token=strtok(conf_parms,",");
if (retcode != RIG_OK)
while(token)
{
fprintf(stderr, "Config parameter error: %s\n", rigerror(retcode));
exit(2);
char mytoken[100], myvalue[100];
token_t lookup;
sscanf(token,"%99[^=]=%99s", mytoken, myvalue);
//printf("mytoken=%s,myvalue=%s\n",mytoken, myvalue);
lookup = amp_token_lookup(my_amp,mytoken);
if (lookup == 0)
{
rig_debug(RIG_DEBUG_ERR, "%s: no such token as '%s'\n", __func__, mytoken);
token = strtok(NULL, ",");
continue;
}
retcode = amp_set_conf(my_amp, amp_token_lookup(my_amp,mytoken), myvalue);
if (retcode != RIG_OK)
{
fprintf(stderr, "Config parameter error: %s\n", rigerror(retcode));
exit(2);
}
token = strtok(NULL, ",");
}
if (amp_file)

Wyświetl plik

@ -1630,7 +1630,7 @@ int set_conf(AMP *my_amp, char *conf_parms)
}
else
{
rig_debug(RIG_DEBUG_WARN, "%s: invalid token %s for this rig\n", __func__, p);
rig_debug(RIG_DEBUG_WARN, "%s: invalid token %s for this amp\n", __func__, p);
}
p = n;

Wyświetl plik

@ -323,17 +323,30 @@ int main(int argc, char *argv[])
exit(2);
}
#if 0
retcode = set_conf(my_amp, conf_parms);
char *token=strtok(conf_parms,",");
if (retcode != RIG_OK)
while(token)
{
fprintf(stderr, "Config parameter error: %s\n", rigerror(retcode));
exit(2);
char mytoken[100], myvalue[100];
token_t lookup;
sscanf(token,"%99[^=]=%99s", mytoken, myvalue);
//printf("mytoken=%s,myvalue=%s\n",mytoken, myvalue);
lookup = amp_token_lookup(my_amp,mytoken);
if (lookup == 0)
{
rig_debug(RIG_DEBUG_ERR, "%s: no such token as '%s'\n", __func__, mytoken);
token = strtok(NULL, ",");
continue;
}
retcode = amp_set_conf(my_amp, amp_token_lookup(my_amp,mytoken), myvalue);
if (retcode != RIG_OK)
{
fprintf(stderr, "Config parameter error: %s\n", rigerror(retcode));
exit(2);
}
token = strtok(NULL, ",");
}
#endif
if (amp_file)
{
strncpy(my_amp->state.ampport.pathname, amp_file, HAMLIB_FILPATHLEN - 1);

Wyświetl plik

@ -28,6 +28,7 @@
#include "sprintflst.h"
#include "rigctl_parse.h"
#include "../rigs/icom/icom.h"
#include "dumpcaps.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);
@ -1255,3 +1256,15 @@ int dumpconf(RIG *rig, FILE *fout)
return 0;
}
int dumpconf_list(RIG *rig, FILE *fout)
{
rig_token_foreach(rig, print_conf_list2, (rig_ptr_t)rig);
return 0;
}
int dumpconf_list_rot(ROT *rot, FILE *fout)
{
rot_token_foreach(rot, print_conf_list2, rot);
return 0;
}

3
tests/dumpcaps.h 100644
Wyświetl plik

@ -0,0 +1,3 @@
#include <hamlib/rig.h>
int dumpconf_list(RIG *rig, FILE *fout);

Wyświetl plik

@ -242,3 +242,10 @@ int dumpcaps_rot(ROT *rot, FILE *fout)
return backend_warnings;
}
int dumpconf_list(ROT *rot, FILE *fout)
{
rot_token_foreach(rot, print_conf_list, rot);
return 0;
}

Wyświetl plik

@ -0,0 +1,3 @@
#include <hamlib/rig.h>
int dumpconf_list(ROT *rot, FILE *fout);

Wyświetl plik

@ -30,6 +30,7 @@
#include <string.h>
#include <errno.h>
#include <getopt.h>
#include <signal.h>
#ifdef HAVE_LIBREADLINE
# if defined(HAVE_READLINE_READLINE_H)
@ -113,11 +114,86 @@ static struct option long_options[] =
extern char rig_resp_sep;
extern powerstat_t rig_powerstat;
static RIG *my_rig; /* handle to rig (instance) */
#ifdef HAVE_SIG_ATOMIC_T
static sig_atomic_t volatile ctrl_c = 0;
#else
static int volatile ctrl_c = 0;
#endif
#define MAXCONFLEN 2048
#ifdef WIN32
static BOOL WINAPI CtrlHandler(DWORD fdwCtrlType)
{
rig_debug(RIG_DEBUG_VERBOSE, "%s: called\n", __func__);
switch (fdwCtrlType)
{
case CTRL_C_EVENT:
case CTRL_CLOSE_EVENT:
ctrl_c = 1;
return TRUE;
default:
return FALSE;
}
}
#else
static void signal_handler(int sig)
{
switch (sig)
{
case SIGINT:
case SIGTERM:
fprintf(stderr, "\nTerminating application, caught signal %d\n", sig);
// Close stdin to stop reading input
fclose(stdin);
ctrl_c = 1;
break;
default:
/* do nothing */
break;
}
}
#endif
static void handle_error(enum rig_debug_level_e lvl, const char *msg)
{
int e;
#ifdef __MINGW32__
LPVOID lpMsgBuf;
lpMsgBuf = (LPVOID)"Unknown error";
e = WSAGetLastError();
if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER
| FORMAT_MESSAGE_FROM_SYSTEM
| FORMAT_MESSAGE_IGNORE_INSERTS,
NULL, e,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
// Default language
(LPTSTR)&lpMsgBuf, 0, NULL))
{
rig_debug(lvl, "%s: Network error %d: %s\n", msg, e, (char *)lpMsgBuf);
LocalFree(lpMsgBuf);
}
else
{
rig_debug(lvl, "%s: Network error %d\n", msg, e);
}
#else
e = errno;
rig_debug(lvl, "%s: Network error %d: %s\n", msg, e, strerror(e));
#endif
}
int main(int argc, char *argv[])
{
RIG *my_rig; /* handle to rig (instance) */
rig_model_t my_model = RIG_MODEL_DUMMY;
int retcode; /* generic return code from functions */
@ -151,6 +227,9 @@ int main(int argc, char *argv[])
char rigstartup[1024];
char vbuf[1024];
rig_powerstat = RIG_POWER_ON; // defaults to power on
#if HAVE_SIGACTION
struct sigaction act;
#endif
int err = setvbuf(stderr, vbuf, _IOFBF, sizeof(vbuf));
@ -476,12 +555,28 @@ int main(int argc, char *argv[])
exit(2);
}
retcode = set_conf(my_rig, conf_parms);
if (retcode != RIG_OK)
char *token=strtok(conf_parms,",");
while(token)
{
fprintf(stderr, "Config parameter error: %s\n", rigerror(retcode));
exit(2);
char mytoken[100], myvalue[100];
token_t lookup;
sscanf(token,"%99[^=]=%99s", mytoken, myvalue);
//printf("mytoken=%s,myvalue=%s\n",mytoken, myvalue);
lookup = rig_token_lookup(my_rig,mytoken);
if (lookup == 0)
{
rig_debug(RIG_DEBUG_ERR, "%s: no such token as '%s'\n", __func__, mytoken);
token = strtok(NULL, ",");
continue;
}
retcode = rig_set_conf(my_rig, rig_token_lookup(my_rig,mytoken), myvalue);
if (retcode != RIG_OK)
{
fprintf(stderr, "Config parameter error: %s\n", rigerror(retcode));
exit(2);
}
token = strtok(NULL, ",");
}
if (rig_file)
@ -648,6 +743,77 @@ int main(int argc, char *argv[])
#endif /* HAVE_LIBREADLINE */
int rig_opened = 1; // our rig is already open
#if HAVE_SIGACTION
#ifdef SIGPIPE
/* Ignore SIGPIPE as we will handle it at the write()/send() calls
that will consequently fail with EPIPE. All child threads will
inherit this disposition which is what we want. */
memset(&act, 0, sizeof act);
act.sa_handler = SIG_IGN;
act.sa_flags = SA_RESTART;
if (sigaction(SIGPIPE, &act, NULL))
{
handle_error(RIG_DEBUG_ERR, "sigaction SIGPIPE");
}
#endif
#ifdef SIGINT
memset(&act, 0, sizeof act);
act.sa_handler = signal_handler;
if (sigaction(SIGINT, &act, NULL))
{
handle_error(RIG_DEBUG_ERR, "sigaction SIGINT");
}
#endif
#ifdef SIGTERM
memset(&act, 0, sizeof act);
act.sa_handler = signal_handler;
if (sigaction(SIGTERM, &act, NULL))
{
handle_error(RIG_DEBUG_ERR, "sigaction SIGTERM");
}
#endif
#elif defined (WIN32)
if (!SetConsoleCtrlHandler(CtrlHandler, TRUE))
{
handle_error(RIG_DEBUG_ERR, "SetConsoleCtrlHandler");
}
#elif HAVE_SIGNAL
#ifdef SIGPIPE
if (SIG_ERR == signal(SIGPIPE, SIG_IGN))
{
handle_error(RIG_DEBUG_ERR, "signal SIGPIPE");
}
#endif
#ifdef SIGINT
if (SIG_ERR == signal(SIGINT, signal_handler))
{
handle_error(RIG_DEBUG_ERR, "signal SIGINT");
}
#endif
#ifdef SIGTERM
if (SIG_ERR == signal(SIGTERM, signal_handler))
{
handle_error(RIG_DEBUG_ERR, "signal SIGTERM");
}
#endif
#endif
do
{
if (!rig_opened)
@ -695,7 +861,7 @@ int main(int argc, char *argv[])
while (retry-- > 0 && retcode != RIG_OK);
}
}
while (retcode == RIG_OK || RIG_IS_SOFT_ERRCODE(-retcode));
while (!ctrl_c && (retcode == RIG_OK || RIG_IS_SOFT_ERRCODE(-retcode)));
if (interactive && prompt)
{

Wyświetl plik

@ -270,6 +270,8 @@ declare_proto_rig(hamlib_version);
declare_proto_rig(test);
declare_proto_rig(cm108_get_bit);
declare_proto_rig(cm108_set_bit);
declare_proto_rig(set_conf);
declare_proto_rig(get_conf);
/*
@ -390,6 +392,8 @@ static struct test_table test_list[] =
{ 0xa8, "hamlib_version", ACTION(hamlib_version), ARG_NOVFO },
{ 0xa9, "get_gpio", ACTION(cm108_get_bit), ARG_NOVFO | ARG_IN1 | ARG_OUT1, "GPIO#", "0/1" },
{ 0xaa, "set_gpio", ACTION(cm108_set_bit), ARG_NOVFO | ARG_IN , "GPIO#", "0/1" },
{ 0xac, "set_conf", ACTION(set_conf), ARG_NOVFO | ARG_IN , "Token", "Token Value" },
{ 0xad, "get_conf", ACTION(get_conf), ARG_NOVFO | ARG_IN1 | ARG_OUT2, "Token", "Value"},
{ 0x00, "", NULL },
};
@ -1989,6 +1993,21 @@ int print_conf_list(const struct confparams *cfp, rig_ptr_t data)
return 1; /* !=0, we want them all ! */
}
// short list for rigctl/rigctld display
int print_conf_list2(const struct confparams *cfp, rig_ptr_t data)
{
RIG *rig = (RIG *) data;
char buf[128] = "";
rig_get_conf(rig, cfp->token, buf);
fprintf(stdout,"%s: \"%s\"\n" "\t" "Default: %s, Value: %s\n",
cfp->name,
cfp->tooltip,
cfp->dflt,
buf);
return 1; /* !=0, we want them all ! */
}
static int hash_model_list(const struct rig_caps *caps, void *data)
{
@ -2040,58 +2059,6 @@ void list_models()
hash_delete_all();
}
int set_conf(RIG *my_rig, char *conf_parms)
{
char *p, *n;
int token;
rig_debug(RIG_DEBUG_TRACE, "%s: called\n", __func__);
p = conf_parms;
while (p && *p != '\0')
{
int ret;
/* FIXME: left hand value of = cannot be null */
char *q = strchr(p, '=');
if (!q)
{
return (-RIG_EINVAL);
}
*q++ = '\0';
n = strchr(q, ',');
if (n)
{
*n++ = '\0';
}
token = rig_token_lookup(my_rig, p);
if (token != 0)
{
ret = rig_set_conf(my_rig, rig_token_lookup(my_rig, p), q);
if (ret != RIG_OK)
{
return (ret);
}
}
else
{
rig_debug(RIG_DEBUG_WARN, "%s: invalid token %s for this rig\n", __func__, p);
}
p = n;
}
return (RIG_OK);
}
/*
* 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)
@ -5790,3 +5757,62 @@ declare_proto_rig(cm108_set_bit)
}
return retval;
}
declare_proto_rig(get_conf)
{
int ret;
rig_debug(RIG_DEBUG_ERR, "%s: \n", __func__);
if (arg1 == NULL || arg1[0] == '?')
{
dumpconf_list(rig, stdout);
debugmsgsave[0] = 0;
debugmsgsave2[0] = 0;
return RIG_OK;
}
token_t mytoken = rig_token_lookup(rig, arg1);
if (mytoken == 0)
{
rig_debug(RIG_DEBUG_ERR, "%s: unknown token '%s' for this rig\n", __func__, arg1);
ret = -RIG_EINVAL;
}
else
{
char value[4096]; // no max value known -- should we limit it?
ret = rig_get_conf(rig, mytoken, value);
if (ret != RIG_OK)
{
return ret;
}
fprintf(fout, "%s=%s\n", arg1, value);
}
return (ret);
}
declare_proto_rig(set_conf)
{
int ret;
rig_debug(RIG_DEBUG_TRACE, "%s: called\n", __func__);
if (arg1[0] == '?')
{
dumpconf_list(rig, fout);
debugmsgsave[0] = 0;
debugmsgsave2[0] = 0;
return RIG_OK;
}
token_t mytoken = rig_token_lookup(rig, arg1);
if (mytoken == 0)
{
rig_debug(RIG_DEBUG_ERR, "%s: unknown token '%s' for this rig\n", __func__, arg1);
ret = -RIG_EINVAL;
}
else
{
ret = rig_set_conf(rig, rig_token_lookup(rig, arg1), arg2);
}
return (ret);
}

Wyświetl plik

@ -38,6 +38,7 @@
int dumpcaps(RIG *, FILE *);
int dumpstate(RIG *, FILE *);
int dumpconf(RIG *, FILE *);
int dumpconf_list(RIG *, FILE *);
/*
* Prototypes
@ -47,6 +48,7 @@ void version();
void list_models();
int dump_chan(FILE *, RIG *, channel_t *);
int print_conf_list(const struct confparams *cfp, rig_ptr_t data);
int print_conf_list2(const struct confparams *cfp, rig_ptr_t data);
int set_conf(RIG *my_rig, char *conf_parms);
typedef void (*sync_cb_t)(int);

Wyświetl plik

@ -492,7 +492,8 @@ int main(int argc, char *argv[])
exit(2);
}
retcode = set_conf(my_rig, conf_parms);
retcode = -RIG_ENIMPL;
// retcode = set_conf(my_rig, conf_parms);
if (retcode != RIG_OK)
{

Wyświetl plik

@ -105,8 +105,6 @@ static struct option long_options[] =
{"twiddle_rit", 1, 0, 'w'},
{"uplink", 1, 0, 'x'},
{"debug-time-stamps", 0, 0, 'Z'},
{"multicast-addr", 1, 0, 'M'},
{"multicast-port", 1, 0, 'n'},
{"password", 1, 0, 'A'},
{"rigctld-idle", 0, 0, 'R'},
{"bind-all", 0, 0, 'b'},
@ -138,15 +136,13 @@ static volatile int rig_opened = 0;
static int verbose;
#ifdef HAVE_SIG_ATOMIC_T
static sig_atomic_t volatile ctrl_c;
static sig_atomic_t volatile ctrl_c = 0;
#else
static int volatile ctrl_c;
static int volatile ctrl_c = 0;
#endif
const char *portno = "4532";
const char *src_addr = NULL; /* INADDR_ANY */
const char *multicast_addr = "0.0.0.0";
int multicast_port = 4532;
extern char rigctld_password[65];
char resp_sep = '\n';
extern int lock_mode;
@ -200,6 +196,10 @@ static void signal_handler(int sig)
switch (sig)
{
case SIGINT:
case SIGTERM:
fprintf(stderr, "\nTerminating application, caught signal %d\n", sig);
// Close stdin to stop reading input
fclose(stdin);
ctrl_c = 1;
break;
@ -618,33 +618,6 @@ int main(int argc, char *argv[])
rig_set_debug_time_stamp(1);
break;
case 'M':
if (!optarg)
{
usage(); /* wrong arg count */
exit(1);
}
multicast_addr = optarg;
break;
case 'n':
if (!optarg)
{
usage(); /* wrong arg count */
exit(1);
}
multicast_port = atoi(optarg);
if (multicast_port == 0)
{
fprintf(stderr, "Invalid multicast port: %s\n", optarg);
exit(1);
}
break;
default:
usage(); /* unknown option? */
exit(1);
@ -686,13 +659,28 @@ int main(int argc, char *argv[])
fprintf(stderr, "Please check with --list option.\n");
exit(2);
}
retcode = set_conf(my_rig, conf_parms);
if (retcode != RIG_OK)
char *token=strtok(conf_parms,",");
while(token)
{
fprintf(stderr, "Config parameter error: %s\n", rigerror(retcode));
exit(2);
char mytoken[100], myvalue[100];
token_t lookup;
sscanf(token,"%99[^=]=%99s", mytoken, myvalue);
//printf("mytoken=%s,myvalue=%s\n",mytoken, myvalue);
lookup = rig_token_lookup(my_rig,mytoken);
if (lookup == 0)
{
rig_debug(RIG_DEBUG_ERR, "%s: no such token as '%s'\n", __func__, mytoken);
token = strtok(NULL, ",");
continue;
}
retcode = rig_set_conf(my_rig, rig_token_lookup(my_rig,mytoken), myvalue);
if (retcode != RIG_OK)
{
fprintf(stderr, "Config parameter error: %s\n", rigerror(retcode));
exit(2);
}
token = strtok(NULL, ",");
}
if (rig_file)
@ -867,18 +855,6 @@ int main(int argc, char *argv[])
saved_result = result;
enum multicast_item_e items = RIG_MULTICAST_POLL | RIG_MULTICAST_TRANSCEIVE |
RIG_MULTICAST_SPECTRUM;
retcode = network_multicast_publisher_start(my_rig, multicast_addr,
multicast_port, items);
if (retcode != RIG_OK)
{
rig_debug(RIG_DEBUG_ERR, "%s: network_multicast_server failed: %s\n", __FILE__,
rigerror(retcode));
// we will consider this non-fatal for now
}
do
{
sock_listen = socket(result->ai_family,
@ -992,6 +968,16 @@ int main(int argc, char *argv[])
handle_error(RIG_DEBUG_ERR, "sigaction SIGINT");
}
#endif
#ifdef SIGTERM
memset(&act, 0, sizeof act);
act.sa_handler = signal_handler;
if (sigaction(SIGTERM, &act, NULL))
{
handle_error(RIG_DEBUG_ERR, "sigaction SIGTERM");
}
#endif
#elif defined (WIN32)
@ -1016,6 +1002,14 @@ int main(int argc, char *argv[])
handle_error(RIG_DEBUG_ERR, "signal SIGINT");
}
#endif
#ifdef SIGTERM
if (SIG_ERR == signal(SIGTERM, signal_handler))
{
handle_error(RIG_DEBUG_ERR, "signal SIGTERM");
}
#endif
#endif
@ -1148,8 +1142,6 @@ int main(int argc, char *argv[])
rig_close(my_rig); /* close port */
#endif
network_multicast_publisher_stop(my_rig);
rig_cleanup(my_rig); /* if you care about memory */
#ifdef __MINGW32__
@ -1464,8 +1456,6 @@ void usage(void)
" -w, --twiddle_rit suppress VFOB getfreq so RIT can be twiddled\n"
" -x, --uplink set uplink get_freq ignore, 1=Sub, 2=Main\n"
" -Z, --debug-time-stamps enable time stamps for debug messages\n"
" -M, --multicast-addr=addr set multicast UDP address, default 0.0.0.0 (off), recommend 224.0.1.1\n"
" -n, --multicast-port=port set multicast UDP port, default 4532\n"
" -A, --password set password for rigctld access\n"
" -R, --rigctld-idle make rigctld close the rig when no clients are connected\n"
" -h, --help display this help and exit\n"

Wyświetl plik

@ -674,7 +674,8 @@ int main(int argc, char *argv[])
exit(2);
}
retcode = set_conf(my_rig, conf_parms);
retcode = -RIG_ENIMPL;
// retcode = set_conf(my_rig, conf_parms);
if (retcode != RIG_OK)
{

Wyświetl plik

@ -339,12 +339,28 @@ int main(int argc, char *argv[])
exit(2);
}
retcode = set_conf(my_rot, conf_parms);
char *token=strtok(conf_parms,",");
if (retcode != RIG_OK)
while(token)
{
fprintf(stderr, "Config parameter error: %s\n", rigerror(retcode));
exit(2);
char mytoken[100], myvalue[100];
token_t lookup;
sscanf(token,"%99[^=]=%99s", mytoken, myvalue);
//printf("mytoken=%s,myvalue=%s\n",mytoken, myvalue);
lookup = rot_token_lookup(my_rot,mytoken);
if (lookup == 0)
{
rig_debug(RIG_DEBUG_ERR, "%s: no such token as '%s', use -L switch to see\n", __func__, mytoken);
token = strtok(NULL, ",");
continue;
}
retcode = rot_set_conf(my_rot, rot_token_lookup(my_rot,mytoken), myvalue);
if (retcode != RIG_OK)
{
fprintf(stderr, "Config parameter error: %s\n", rigerror(retcode));
exit(2);
}
token = strtok(NULL, ",");
}
if (rot_file)

Wyświetl plik

@ -24,8 +24,6 @@
*
*/
// TODO: Add "symmetric" set_conf + get_conf to rigctl+rotctl
#include <hamlib/config.h>
#include <stdio.h>
@ -65,7 +63,7 @@ extern int read_history();
#include <hamlib/rotator.h>
#include "iofunc.h"
#include "misc.h"
#include "dumpcaps_rot.h"
/* HAVE_SSLEEP is defined when Windows Sleep is found
* HAVE_SLEEP is defined when POSIX sleep is found
@ -189,10 +187,12 @@ declare_proto_rot(set_parm);
declare_proto_rot(get_parm);
declare_proto_rot(get_info);
declare_proto_rot(get_status);
declare_proto_rot(inter_set_conf); /* interactive mode set_conf */
declare_proto_rot(set_conf);
declare_proto_rot(get_conf);
declare_proto_rot(send_cmd);
declare_proto_rot(dump_state);
declare_proto_rot(dump_caps);
declare_proto_rot(dump_conf);
/* Follows are functions from locator.c */
declare_proto_rot(loc2lonlat);
declare_proto_rot(lonlat2loc);
@ -224,11 +224,12 @@ struct test_table test_list[] =
{ 'u', "get_func", ACTION(get_func), ARG_IN1 | ARG_OUT2, "Func", "Func Status" },
{ 'X', "set_parm", ACTION(set_parm), ARG_IN, "Parm", "Parm Value" },
{ 'x', "get_parm", ACTION(get_parm), ARG_IN1 | ARG_OUT2, "Parm", "Parm Value" },
{ 'C', "set_conf", ACTION(inter_set_conf), ARG_IN, "Token", "Value" },
{ 'C', "set_conf", ACTION(set_conf), ARG_IN, "Token", "Value" },
{ '_', "get_info", ACTION(get_info), ARG_OUT, "Info" },
{ 's', "get_status", ACTION(get_status), ARG_OUT, "Status flags" },
{ 'w', "send_cmd", ACTION(send_cmd), ARG_IN1 | ARG_IN_LINE | ARG_OUT2, "Cmd", "Reply" },
{ '1', "dump_caps", ACTION(dump_caps), },
{ '3', "dump_conf", ACTION(dump_conf), },
{ 0x8f, "dump_state", ACTION(dump_state), ARG_OUT },
{ 'L', "lonlat2loc", ACTION(lonlat2loc), ARG_IN1 | ARG_IN2 | ARG_IN3 | ARG_OUT1, "Longitude", "Latitude", "Loc Len [2-12]", "Locator" },
{ 'l', "loc2lonlat", ACTION(loc2lonlat), ARG_IN1 | ARG_OUT1 | ARG_OUT2, "Locator", "Longitude", "Latitude" },
@ -240,6 +241,7 @@ struct test_table test_list[] =
{ 'A', "a_sp2a_lp", ACTION(az_sp2az_lp), ARG_IN1 | ARG_OUT1, "Short Path Deg", "Long Path Deg" },
{ 'a', "d_sp2d_lp", ACTION(dist_sp2dist_lp), ARG_IN1 | ARG_OUT1, "Short Path km", "Long Path km" },
{ 0x8c, "pause", ACTION(pause), ARG_IN, "Seconds" },
{ 0xad, "get_conf", ACTION(get_conf), ARG_IN1 | ARG_OUT2, "Token", "Value"},
{ 0x00, "", NULL },
};
@ -1574,7 +1576,7 @@ int print_conf_list(const struct confparams *cfp, rig_ptr_t data)
char buf[128] = "";
rot_get_conf2(rot, cfp->token, buf, sizeof(buf));
printf("%s: \"%s\"\n" "\tDefault: %s, Value: %s\n",
fprintf(stdout,"%s: \"%s\"\n" "\tDefault: %s, Value: %s\n",
cfp->name,
cfp->tooltip,
cfp->dflt,
@ -1583,14 +1585,14 @@ int print_conf_list(const struct confparams *cfp, rig_ptr_t data)
switch (cfp->type)
{
case RIG_CONF_NUMERIC:
printf("\tRange: %.1f..%.1f, step %.1f\n",
fprintf(stdout,"\tRange: %.1f..%.1f, step %.1f\n",
cfp->u.n.min,
cfp->u.n.max,
cfp->u.n.step);
break;
case RIG_CONF_CHECKBUTTON:
printf("\tCheckbox: 0,1\n");
fprintf(stdout,"\tCheckbox: 0,1\n");
break;
case RIG_CONF_COMBO:
@ -1599,14 +1601,14 @@ int print_conf_list(const struct confparams *cfp, rig_ptr_t data)
break;
}
printf("\tCombo: %s", cfp->u.c.combostr[0]);
fprintf(stdout,"\tCombo: %s", cfp->u.c.combostr[0]);
for (i = 1 ; i < RIG_COMBO_MAX && cfp->u.c.combostr[i]; i++)
{
printf(", %s", cfp->u.c.combostr[i]);
fprintf(stdout,", %s", cfp->u.c.combostr[i]);
}
printf("\n");
fprintf(stdout,"\n");
break;
default:
@ -1666,55 +1668,64 @@ void list_models()
hash_delete_all();
}
int set_conf(ROT *my_rot, char *conf_parms)
declare_proto_rot(get_conf)
{
char *p;
rot_debug(RIG_DEBUG_TRACE, "%s: called\n", __func__);
p = conf_parms;
while (p && *p != '\0')
int ret;
rig_debug(RIG_DEBUG_ERR, "%s: \n", __func__);
if (arg1 == NULL || arg1[0] == '?')
{
int token;
char *q, *n = NULL;
/* FIXME: left hand value of = cannot be null */
q = strchr(p, '=');
if (!q)
dumpconf_list(rot, fout);
debugmsgsave[0] = 0;
debugmsgsave2[0] = 0;
return RIG_OK;
}
token_t mytoken = rot_token_lookup(rot, arg1);
if (mytoken == 0)
{
rig_debug(RIG_DEBUG_ERR, "%s: unknown token '%s' for this rot\n", __func__, arg1);
ret = -RIG_EINVAL;
}
else
{
char value[4096];
ret = rot_get_conf(rot, rot_token_lookup(rot, arg1), value);
if (ret != RIG_OK)
{
return RIG_EINVAL;
return ret;
}
*q++ = '\0';
n = strchr(q, ',');
if (n)
{
*n++ = '\0';
}
token = rot_token_lookup(my_rot, p);
if (token != 0)
{
int ret;
ret = rot_set_conf(my_rot, token, q);
if (ret != RIG_OK)
{
return ret;
}
}
else
{
rig_debug(RIG_DEBUG_WARN, "%s: invalid token %s for this rig\n", __func__, p);
}
p = n;
fprintf(fout, "%s=%s\n", arg1, value);
}
return RIG_OK;
return (ret);
}
/* 'C' */
declare_proto_rot(set_conf)
{
int ret;
rig_debug(RIG_DEBUG_TRACE, "%s: called\n", __func__);
if (arg1[0] == '?')
{
dumpconf_list(rot, fout);
debugmsgsave[0] = 0;
debugmsgsave2[0] = 0;
return RIG_OK;
}
token_t mytoken = rot_token_lookup(rot, arg1);
if (mytoken == 0)
{
rig_debug(RIG_DEBUG_ERR, "%s: unknown token '%s' for this rot\n", __func__, arg1);
ret = -RIG_EINVAL;
}
else
{
ret = rot_set_conf(rot, rot_token_lookup(rot, arg1), arg2);
}
return (ret);
}
@ -2344,6 +2355,7 @@ declare_proto_rot(get_parm)
}
#if 0 // replace by set_conf
/* 'C' */
declare_proto_rot(inter_set_conf)
{
@ -2361,6 +2373,7 @@ declare_proto_rot(inter_set_conf)
SNPRINTF(buf, sizeof(buf), "%s=%s", arg1, arg2);
return set_conf(rot, buf);
}
#endif
/* '1' */
declare_proto_rot(dump_caps)
@ -2370,6 +2383,14 @@ declare_proto_rot(dump_caps)
return RIG_OK;
}
declare_proto_rot(dump_conf)
{
ENTERFUNC2;
dumpconf_list(rot, fout);
RETURNFUNC2(RIG_OK);
}
/* For rotctld internal use
* '0x8f'
@ -2862,3 +2883,20 @@ declare_proto_rot(pause)
sleep(seconds);
return RIG_OK;
}
// short list for rigctl/rigctld display
int print_conf_list2(const struct confparams *cfp, rig_ptr_t data, FILE *fout)
{
ROT *rot = (ROT *) data;
char buf[128] = "";
rot_get_conf(rot, cfp->token, buf);
fprintf(fout,"%s: \"%s\"\n" "\t" "Default: %s, Value: %s\n",
cfp->name,
cfp->tooltip,
cfp->dflt,
buf);
return 1; /* !=0, we want them all ! */
}

Wyświetl plik

@ -42,6 +42,7 @@ void usage_rot(FILE *);
void version();
void list_models();
int print_conf_list(const struct confparams *cfp, rig_ptr_t data);
int print_conf_list2(const struct confparams *cfp, rig_ptr_t data, FILE *fout);
int set_conf(ROT *my_rot, char *conf_parms);
int rotctl_parse(ROT *my_rot, FILE *fin, FILE *fout, const char **argv, int argc,

Wyświetl plik

@ -345,12 +345,28 @@ int main(int argc, char *argv[])
exit(2);
}
retcode = set_conf(my_rot, conf_parms);
char *token=strtok(conf_parms,",");
if (retcode != RIG_OK)
while(token)
{
fprintf(stderr, "Config parameter error: %s\n", rigerror(retcode));
exit(2);
char mytoken[100], myvalue[100];
token_t lookup;
sscanf(token,"%99[^=]=%99s", mytoken, myvalue);
//printf("mytoken=%s,myvalue=%s\n",mytoken, myvalue);
lookup = rot_token_lookup(my_rot,mytoken);
if (lookup == 0)
{
rig_debug(RIG_DEBUG_ERR, "%s: no such token as '%s', use -L switch to see\n", __func__, mytoken);
token = strtok(NULL, ",");
continue;
}
retcode = rot_set_conf(my_rot, rot_token_lookup(my_rot,mytoken), myvalue);
if (retcode != RIG_OK)
{
fprintf(stderr, "Config parameter error: %s\n", rigerror(retcode));
exit(2);
}
token = strtok(NULL, ",");
}
if (rot_file)