Merge pull request #1289 from mikaelnousiainen/bug-fixes-1

Fix a number of issues in the current Hamlib code
pull/1294/head
Michael Black 2023-05-14 07:26:34 -05:00 zatwierdzone przez GitHub
commit 10f1f3a7cd
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: 4AEE18F83AFDEB23
14 zmienionych plików z 334 dodań i 148 usunięć

Wyświetl plik

@ -2292,8 +2292,8 @@ typedef struct hamlib_port {
int value; /*!< Toggle PTT ON or OFF */
} gpio; /*!< GPIO attributes */
} parm; /*!< Port parameter union */
int client_port; /*!< client socket port for tcp connection */
RIG *rig; /*!< our parent RIG device */
int client_port; /*!< client socket port for tcp connection */
RIG *rig; /*!< our parent RIG device */
int asyncio; /*!< enable asynchronous data handling if true -- async collides with python keyword so _async is used */
#if defined(_WIN32)
hamlib_async_pipe_t *sync_data_pipe; /*!< pipe data structure for synchronous data */
@ -2304,6 +2304,7 @@ typedef struct hamlib_port {
int fd_sync_error_write; /*!< file descriptor for writing synchronous data error codes */
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 */
} hamlib_port_t;
@ -2718,6 +2719,9 @@ extern HAMLIB_EXPORT(int) rig_open HAMLIB_PARAMS((RIG *rig));
* List Set/Get functions pairs
*/
extern HAMLIB_EXPORT(int)
rig_flush_force(hamlib_port_t *port, int flush_async_data);
extern HAMLIB_EXPORT(int)
rig_flush(hamlib_port_t *port);

Wyświetl plik

@ -2125,6 +2125,13 @@ static int dummy_send_morse(RIG *rig, vfo_t vfo, const char *msg)
RETURNFUNC(RIG_OK);
}
static int dummy_stop_morse(RIG *rig, vfo_t vfo)
{
ENTERFUNC;
RETURNFUNC(RIG_OK);
}
static int dummy_send_voice_mem(RIG *rig, vfo_t vfo, int ch)
{
ENTERFUNC;
@ -2287,6 +2294,10 @@ struct rig_caps dummy_caps =
.has_get_parm = DUMMY_PARM,
.has_set_parm = RIG_PARM_SET(DUMMY_PARM),
.level_gran = {
[LVL_RF] = { .min = { .f = 0 }, .max = { .f = 1.0f }, .step = { .f = 1.0f/255.0f } },
[LVL_RFPOWER] = { .min = { .f = .05f }, .max = { .f = 1 }, .step = { .f = 1.0f/511.0f } },
[LVL_RFPOWER_METER] = { .min = { .f = .0f }, .max = { .f = 1 }, .step = { .f = 1.0f/255.0f } },
[LVL_RFPOWER_METER_WATTS] = { .min = { .f = .0f }, .max = { .f = 100 }, .step = { .f = 1.0f/255.0f } },
[LVL_CWPITCH] = { .step = { .i = 10 } },
[LVL_SPECTRUM_SPEED] = {.min = {.i = 0}, .max = {.i = 2}, .step = {.i = 1}},
[LVL_SPECTRUM_REF] = {.min = {.f = -30.0f}, .max = {.f = 10.0f}, .step = {.f = 0.5f}},
@ -2486,6 +2497,7 @@ struct rig_caps dummy_caps =
.send_dtmf = dummy_send_dtmf,
.recv_dtmf = dummy_recv_dtmf,
.send_morse = dummy_send_morse,
.stop_morse = dummy_stop_morse,
.send_voice_mem = dummy_send_voice_mem,
.set_channel = dummy_set_channel,
.get_channel = dummy_get_channel,

Wyświetl plik

@ -580,7 +580,6 @@ const struct rig_caps ic7300_caps =
[LVL_SPECTRUM_REF] = {.min = {.f = -20.0f}, .max = {.f = 20.0f}, .step = {.f = 0.5f}},
[LVL_SPECTRUM_AVG] = {.min = {.i = 0}, .max = {.i = 3}, .step = {.i = 1}},
[LVL_USB_AF] = {.min = {.f = 0.0f}, .max = {.f = 1.0f}, .step = {.f = 1.0f / 255.0f }},
[LVL_AGC_TIME] = {.min = {.f = 0.0f}, .max = {.f = 8.0f}, .step = {.f = 0.1f }},
},
.parm_gran = {},
.ext_tokens = ic7300_ext_tokens,
@ -816,7 +815,6 @@ struct rig_caps ic9700_caps =
[LVL_SPECTRUM_REF] = {.min = {.f = -20.0f}, .max = {.f = 20.0f}, .step = {.f = 0.5f}},
[LVL_SPECTRUM_AVG] = {.min = {.i = 0}, .max = {.i = 3}, .step = {.i = 1}},
[LVL_USB_AF] = {.min = {.f = 0.0f}, .max = {.f = 1.0f}, .step = {.f = 1.0f / 255.0f }},
[LVL_AGC_TIME] = {.min = {.f = 0.0f}, .max = {.f = 8.0f}, .step = {.f = 0.1f }},
},
.parm_gran = {},
.ext_tokens = ic9700_ext_tokens,
@ -1129,7 +1127,6 @@ const struct rig_caps ic705_caps =
[LVL_SPECTRUM_REF] = {.min = {.f = -20.0f}, .max = {.f = 20.0f}, .step = {.f = 0.5f}},
[LVL_SPECTRUM_AVG] = {.min = {.i = 0}, .max = {.i = 3}, .step = {.i = 1}},
[LVL_USB_AF] = {.min = {.f = 0.0f}, .max = {.f = 1.0f}, .step = {.f = 1.0f / 255.0f }},
[LVL_AGC_TIME] = {.min = {.f = 0.0f}, .max = {.f = 8.0f}, .step = {.f = 0.1f }},
},
.parm_gran = {},
.ext_tokens = ic705_ext_tokens,

Wyświetl plik

@ -870,7 +870,7 @@ static vfo_t icom_current_vfo(RIG *rig)
struct rig_state *rs = &rig->state;
struct icom_priv_data *priv = (struct icom_priv_data *) rs->priv;
if (priv->x25cmdfails == 0) // these newer rigs get special treatment
if (priv->x25cmdfails <= 0) // these newer rigs get special treatment
{
return icom_current_vfo_x25(rig);
}
@ -1506,7 +1506,8 @@ int icom_get_freq(RIG *rig, vfo_t vfo, freq_t *freq)
unsigned char freqbuf[MAXFRAMELEN];
int freqbuf_offset = 1;
unsigned char ackbuf[MAXFRAMELEN];
int freq_len, retval = -RIG_EINTERNAL;
int retval = RIG_OK;
int freq_len;
int cmd, subcmd;
int ack_len = sizeof(ackbuf);
int civ_731_mode = 0; // even these rigs have 5-byte channels
@ -1652,9 +1653,16 @@ int icom_get_freq(RIG *rig, vfo_t vfo, freq_t *freq)
retval = icom_transaction(rig, cmd2, subcmd2, NULL, 0, freqbuf, &freq_len);
if (retval != RIG_OK)
if (retval == RIG_OK)
{
if (priv->x25cmdfails < 0) { priv->x25cmdfails = 1; }
priv->x25cmdfails = 0;
}
else
{
if (priv->x25cmdfails < 0)
{
priv->x25cmdfails = 1;
}
rig_debug(RIG_DEBUG_TRACE,
"%s: rig probe shows 0x25 CI-V cmd not available for this rig/firmware\n",
@ -1694,8 +1702,11 @@ int icom_get_freq(RIG *rig, vfo_t vfo, freq_t *freq)
#endif
if (retval != RIG_OK)
{
if (vfo == RIG_VFO_MEM && civ_731_mode) { priv->civ_731_mode = 1; }
{
if (vfo == RIG_VFO_MEM && civ_731_mode)
{
priv->civ_731_mode = 1;
}
RETURNFUNC(retval);
}
@ -3509,13 +3520,13 @@ int icom_set_level(RIG *rig, vfo_t vfo, setting_t level, value_t val)
if (rig->state.current_mode == RIG_MODE_AM) { agcp = agc_level2; }
rig_debug(RIG_DEBUG_ERR, "%s: val.f=%g\n", __func__, val.f);
rig_debug(RIG_DEBUG_ERR, "%s: val.f=%f\n", __func__, val.f);
for (i = 0; i <= 13; ++i)
{
if (agcp[i] <= val.f)
{
rig_debug(RIG_DEBUG_ERR, "%s: agcp=%g <= val.f=%g at %d\n", __func__, agcp[i],
rig_debug(RIG_DEBUG_ERR, "%s: agcp=%f <= val.f=%f at %d\n", __func__, agcp[i],
val.f, i);
icom_val = i;
}
@ -5547,10 +5558,19 @@ int icom_set_split_freq(RIG *rig, vfo_t vfo, freq_t tx_freq)
if (retval == RIG_OK) // then we're done!!
{
priv->x25cmdfails = 0;
RETURNFUNC2(retval);
}
else
{
if (priv->x25cmdfails < 0)
{
priv->x25cmdfails = 1;
}
}
}
// Rig is in SATMODE and the command 0x25 fails in SATMODE
priv->x25cmdfails = 1;
}
@ -5732,7 +5752,7 @@ int icom_get_split_freq(RIG *rig, vfo_t vfo, freq_t *tx_freq)
// If the rigs supports the 0x25 command we'll use it
// This eliminates VFO swapping and improves split operations
// This does not work in satellite mode for the 9700
if (priv->x25cmdfails == 0)
if (priv->x25cmdfails <= 0)
{
int cmd, subcmd;
int satmode = 0;
@ -5749,7 +5769,7 @@ int icom_get_split_freq(RIG *rig, vfo_t vfo, freq_t *tx_freq)
if (satmode == 0) // only worth trying if not in satmode
{
if (priv->x25cmdfails == 0)
if (priv->x25cmdfails <= 0)
{
int retry_save = rs->rigport.retry;
rs->rigport.retry = 0;
@ -5764,11 +5784,12 @@ int icom_get_split_freq(RIG *rig, vfo_t vfo, freq_t *tx_freq)
if (retval == RIG_OK) // then we're done!!
{
priv->x25cmdfails = 0;
*tx_freq = from_bcd(ackbuf + 2, (priv->civ_731_mode ? 4 : 5) * 2);
RETURNFUNC2(retval);
}
// if (priv->x25cmdfails < 0) priv->x25cmdfails = 1;
if (priv->x25cmdfails < 0) priv->x25cmdfails = 1;
}
}
else // we're in satmode so we try another command
@ -5789,7 +5810,6 @@ int icom_get_split_freq(RIG *rig, vfo_t vfo, freq_t *tx_freq)
priv->x1cx03cmdfails = 1;
}
}
}
/* This method works also in memory mode(RIG_VFO_MEM) */
@ -6760,7 +6780,8 @@ int icom_get_split_vfo(RIG *rig, vfo_t vfo, split_t *split, vfo_t *tx_vfo)
{
rig_debug(RIG_DEBUG_VERBOSE, "%s(%d): satmode changed to reset x25cmdfails\n",
__func__, __LINE__);
priv->x25cmdfails = satmode; // reset this so it tries again
// Reset x25cmdfails to current status, because it fails in SATMODE
priv->x25cmdfails = satmode;
}
}
@ -7162,8 +7183,8 @@ int icom_set_func(RIG *rig, vfo_t vfo, setting_t func, int status)
fct_sc = S_MEM_SATMODE;
}
priv->x25cmdfails =
status; // we reset this to current status -- fails in SATMODE
// Reset x25cmdfails to current status, because it fails in SATMODE
priv->x25cmdfails = status;
priv->x1cx03cmdfails = 0; // we reset this to try it again
rig->state.cache.satmode = status;
icom_satmode_fix(rig, status);
@ -7444,7 +7465,7 @@ int icom_get_func(RIG *rig, vfo_t vfo, setting_t func, int *status)
*status = ackbuf[2 + fct_len];
icom_satmode_fix(rig, *status);
// we'll reset this based on current status
// Reset x25cmdfails to current status, because it fails in SATMODE
priv->x25cmdfails = *status;
}
else

Wyświetl plik

@ -30,7 +30,7 @@ LVL_KEYSPD
[LVL_VOXDELAY] = { .min = { .i = 0 }, .max = { .i = 20 }, .step = { .i = 1 } },
[LVL_BKINDL] = { .min = { .i = 30 }, .max = { .i = 3000 }, .step = { .i = 1 } },
[LVL_BKIN_DLYMS] = { .min = { .i = 30 }, .max = { .i = 3000 }, .step = { .i = 1 } },
[LVL_AGC_TIME] = { .min = { .i = 0 }, .max = { .i = 8000 }, .step = { .i = 1 } },
[LVL_AGC_TIME] = { .min = { .f = 0.0f }, .max = { .f = 8.0f }, .step = { .f = 0.1f } },
/* level with misc units */
[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 } },

Wyświetl plik

@ -69,6 +69,11 @@ static const struct confparams frontend_cfg_params[] =
TOK_RETRY, "retry", "Retry", "Max number of retry",
"0", RIG_CONF_NUMERIC, { .n = { 0, 10, 1 } }
},
{
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",
"0", RIG_CONF_NUMERIC, { .n = { 0, 100, 1 } }
},
{
TOK_RANGE_SELECTED, "Selected range list", "Range list#",
"The tx/rx range list in use",
@ -738,6 +743,15 @@ static int frontend_set_conf(RIG *rig, token_t token, const char *val)
rs->tuner_control_pathname = strdup(val); // yeah -- need to free it
break;
case TOK_TIMEOUT_RETRY:
if (1 != sscanf(val, "%ld", &val_i))
{
return -RIG_EINVAL;
}
rs->rigport.timeout_retry = val_i;
break;
case TOK_OFFSET_VFOA:
if (1 != sscanf(val, "%ld", &val_i))
{
@ -1111,6 +1125,10 @@ static int frontend_get_conf2(RIG *rig, token_t token, char *val, int val_len)
SNPRINTF(val, val_len, "%d", rs->async_data_enabled);
break;
case TOK_TIMEOUT_RETRY:
SNPRINTF(val, val_len, "%d", rs->rigport.timeout_retry);
break;
default:
return -RIG_EINVAL;
}

Wyświetl plik

@ -787,6 +787,12 @@ int HAMLIB_API write_block_sync_error(hamlib_port_t *p,
return async_pipe_write(p->sync_data_error_pipe, txbuffer, count, p->timeout);
}
int HAMLIB_API port_flush_sync_pipes(hamlib_port_t *p)
{
// TODO: To be implemented for Windows
return RIG_OK;
}
#else
/* POSIX */
@ -970,6 +976,38 @@ int HAMLIB_API write_block_sync_error(hamlib_port_t *p,
return (int) write(p->fd_sync_error_write, txbuffer, count);
}
int HAMLIB_API port_flush_sync_pipes(hamlib_port_t *p)
{
unsigned char buf[1024];
int n;
int nbytes;
if (!p->asyncio)
{
return RIG_OK;
}
rig_debug(RIG_DEBUG_TRACE, "%s: flushing sync pipes\n", __func__);
nbytes = 0;
while ((n = read(p->fd_sync_read, buf, sizeof(buf))) > 0)
{
nbytes += n;
}
rig_debug(RIG_DEBUG_TRACE, "read flushed %d bytes from sync read pipe\n", nbytes);
nbytes = 0;
while ((n = read(p->fd_sync_error_read, buf, sizeof(buf))) > 0)
{
nbytes += n;
}
rig_debug(RIG_DEBUG_TRACE, "read flushed %d bytes from sync error read pipe\n", nbytes);
return RIG_OK;
}
#endif
/**
@ -1125,6 +1163,8 @@ static int read_block_generic(hamlib_port_t *p, unsigned char *rxbuffer,
/* Store the time of the read loop start */
gettimeofday(&start_time, NULL);
short timeout_retries = p->timeout_retry;
while (count > 0)
{
int result;
@ -1134,6 +1174,15 @@ static int read_block_generic(hamlib_port_t *p, unsigned char *rxbuffer,
if (result == -RIG_ETIMEOUT)
{
if (timeout_retries > 0)
{
timeout_retries--;
rig_debug(RIG_DEBUG_CACHE, "%s: retrying read timeout %d/%d\n", __func__,
p->timeout_retry - timeout_retries, p->timeout_retry);
hl_usleep(10 * 1000);
continue;
}
/* Record timeout time and calculate elapsed time */
gettimeofday(&end_time, NULL);
timersub(&end_time, &start_time, &elapsed_time);
@ -1283,7 +1332,7 @@ static int read_string_generic(hamlib_port_t *p,
memset(rxbuffer, 0, rxmax);
int flag = 0; // we will allow one timeout
short timeout_retries = p->timeout_retry;
while (total_count < rxmax - 1) // allow 1 byte for end-of-string
{
@ -1294,12 +1343,12 @@ static int read_string_generic(hamlib_port_t *p,
if (result == -RIG_ETIMEOUT)
{
rig_debug(RIG_DEBUG_CACHE, "%s: flag=%d\n", __func__, flag);
if (flag == 0)
if (timeout_retries > 0)
{
flag = 1;
hl_usleep(50 * 1000);
timeout_retries--;
rig_debug(RIG_DEBUG_CACHE, "%s: retrying read timeout %d/%d\n", __func__,
p->timeout_retry - timeout_retries, p->timeout_retry);
hl_usleep(10 * 1000);
continue;
}

Wyświetl plik

@ -49,6 +49,8 @@ extern HAMLIB_EXPORT(int) write_block_sync_error(hamlib_port_t *p,
const unsigned char *txbuffer,
size_t count);
extern HAMLIB_EXPORT(int) port_flush_sync_pipes(hamlib_port_t *p);
extern HAMLIB_EXPORT(int) read_string(hamlib_port_t *p,
unsigned char *rxbuffer,
size_t rxmax,

Wyświetl plik

@ -2152,25 +2152,34 @@ int HAMLIB_API parse_hoststr(char *hoststr, int hoststr_len, char host[256],
return -1;
}
//K3 was showing stacked command replies so re-enabling this
//#define RIG_FLUSH_REMOVE
int HAMLIB_API rig_flush(hamlib_port_t *port)
/**
* \brief Force flush of rig communication data buffers.
* \param port communication port
* \param flush_async_data Flushes also asynchronous I/O pipes if non-zero.
* \return status code
*
* This function should be used only in special cases like after handling raw command data from Hamlib clients.
* When asynchronous I/O is enabled, responses to raw commands may disrupt processing of all commands,
* because the responses and up in the async I/O pipes.
*/
int HAMLIB_API rig_flush_force(hamlib_port_t *port, int flush_async_data)
{
// Data should never be flushed when using async I/O
if (port->asyncio)
if (port->type.rig == RIG_PORT_NONE)
{
return RIG_OK;
}
// Flush also the async I/O pipes
if (port->asyncio && flush_async_data)
{
port_flush_sync_pipes(port);
}
#ifndef RIG_FLUSH_REMOVE
rig_debug(RIG_DEBUG_TRACE, "%s: called for %s device\n", __func__,
port->type.rig == RIG_PORT_SERIAL ? "serial" : "network");
if (port->type.rig == RIG_PORT_NONE)
{
return RIG_OK;
}
if (port->type.rig == RIG_PORT_NETWORK
|| port->type.rig == RIG_PORT_UDP_NETWORK)
{
@ -2190,6 +2199,17 @@ int HAMLIB_API rig_flush(hamlib_port_t *port)
#endif
}
int HAMLIB_API rig_flush(hamlib_port_t *port)
{
// Data should never be flushed when using async I/O
if (port->asyncio)
{
return RIG_OK;
}
return rig_flush_force(port, 0);
}
static const struct
{

113
src/rig.c
Wyświetl plik

@ -7768,82 +7768,97 @@ HAMLIB_EXPORT(int) rig_send_raw(RIG *rig, const unsigned char *send,
struct rig_state *rs = &rig->state;
unsigned char buf[200];
int nbytes;
int retval;
int simulate = rig->caps->rig_model == RIG_MODEL_DUMMY ||
rig->caps->rig_model == RIG_MODEL_NONE ||
rs->rigport.rig == RIG_PORT_NONE;
ENTERFUNC;
if (rig->caps->rig_model == RIG_MODEL_DUMMY
|| rig->caps->rig_model == RIG_MODEL_NONE)
{
rig_debug(RIG_DEBUG_ERR, "%s: not implemented for model %s\n", __func__,
rig->caps->model_name);
return -RIG_ENAVAIL;
}
ELAPSED1;
rig_debug(RIG_DEBUG_VERBOSE, "%s: writing %d bytes\n", __func__, send_len);
int retval = write_block(&rs->rigport, send, send_len);
if (retval < 0)
set_transaction_active(rig);
if (simulate)
{
// TODO: error handling? can writing to a pipe really fail in ways we can recover from?
rig_debug(RIG_DEBUG_ERR, "%s: write_block_sync() failed, result=%d\n", __func__,
retval);
rig_debug(RIG_DEBUG_VERBOSE, "%s: simulating response for model %s\n",
__func__, rig->caps->model_name);
retval = send_len;
}
else
{
retval = write_block(&rs->rigport, send, send_len);
if (retval < 0)
{
// TODO: error handling? can writing to a pipe really fail in ways we can recover from?
rig_debug(RIG_DEBUG_ERR, "%s: write_block_sync() failed, result=%d\n", __func__, retval);
}
}
if (reply)
{
if (term ==
NULL) // we have to have terminating char or else we can't read the response
if (simulate)
{
rig_debug(RIG_DEBUG_ERR, "%s: term==NULL, must have terminator to read reply\n",
__func__);
RETURNFUNC(-RIG_EINVAL);
// Simulate a response by copying the command
memcpy(buf, send, send_len);
nbytes = send_len + 1;
}
if (*term == 0xfd) // then we want an Icom frame
else
{
rig_debug(RIG_DEBUG_VERBOSE, "%s: reading icom frame\n", __func__);
retval = read_icom_frame(&rs->rigport, buf, sizeof(buf));
if (term == NULL)
{
rig_debug(RIG_DEBUG_VERBOSE, "%s: reading binary frame\n", __func__);
retval = read_string(&rs->rigport, buf, reply_len, NULL, 0, 0, 1);
}
else if (*term == 0xfd) // then we want an Icom frame
{
rig_debug(RIG_DEBUG_VERBOSE, "%s: reading icom frame\n", __func__);
retval = read_icom_frame(&rs->rigport, buf, sizeof(buf));
}
else // we'll assume the provided terminator works
{
rig_debug(RIG_DEBUG_VERBOSE, "%s: reading frame terminated by 0x%x\n", __func__, *term);
retval = read_string(&rs->rigport, buf, sizeof(buf), (const char *)term,
1, 0, 1);
}
if (retval < RIG_OK)
{
rig_debug(RIG_DEBUG_ERR, "%s: read_string, result=%d\n", __func__, retval);
rig_flush_force(&rs->rigport, 1);
set_transaction_inactive(rig);
RETURNFUNC(retval);
}
nbytes = retval;
}
else if (term == NULL)
{
rig_debug(RIG_DEBUG_VERBOSE, "%s: reading binary frame\n", __func__);
nbytes = read_string_direct(&rs->rigport, buf, reply_len, (const char *)term,
1, 0, 1);
}
else // we'll assume the provided terminator works
{
rig_debug(RIG_DEBUG_VERBOSE, "%s: reading frame terminated by '%s'\n", __func__,
term);
nbytes = read_string_direct(&rs->rigport, buf, sizeof(buf), (const char *)term,
1, 0, 1);
}
if (retval < RIG_OK)
{
rig_debug(RIG_DEBUG_ERR, "%s: read_string_direct, result=%d\n", __func__,
retval);
RETURNFUNC(retval);
}
if (nbytes >= reply_len)
{
rig_debug(RIG_DEBUG_ERR, "%s: reply_len(%d) less than reply from rig(%d)\n",
__func__, reply_len, nbytes);
return -RIG_EINVAL;
if (nbytes >= reply_len)
{
rig_debug(RIG_DEBUG_ERR, "%s: reply_len(%d) less than reply from rig(%d)\n",
__func__, reply_len, nbytes);
rig_flush_force(&rs->rigport, 1);
set_transaction_inactive(rig);
return -RIG_EINVAL;
}
}
memcpy(reply, buf, reply_len - 1);
}
else
{
rig_flush_force(&rs->rigport, 1);
set_transaction_inactive(rig);
RETURNFUNC(retval);
}
rig_flush_force(&rs->rigport, 1);
set_transaction_inactive(rig);
ELAPSED2;
RETURNFUNC(nbytes > 0 ? nbytes : -RIG_EPROTO);
RETURNFUNC(nbytes >= 0 ? nbytes : -RIG_EPROTO);
}
HAMLIB_EXPORT(int) rig_set_lock_mode(RIG *rig, int mode)

Wyświetl plik

@ -386,7 +386,7 @@ int rig_sprintf_level_gran(char *str, int nlen, setting_t level,
if (RIG_LEVEL_IS_FLOAT(rig_idx2setting(i)))
{
len += sprintf(str + len,
"%s(%g..%g/%g) ",
"%s(%f..%f/%f) ",
ms,
gran[i].min.f,
gran[i].max.f,
@ -445,7 +445,7 @@ int rot_sprintf_level_gran(char *str, int nlen, setting_t level,
if (ROT_LEVEL_IS_FLOAT(rig_idx2setting(i)))
{
len += sprintf(str + len,
"%s(%g..%g/%g) ",
"%s(%f..%f/%f) ",
ms,
gran[i].min.f,
gran[i].max.f,
@ -564,7 +564,7 @@ int rig_sprintf_parm_gran(char *str, int nlen, setting_t parm,
if (RIG_PARM_IS_FLOAT(rig_idx2setting(i)))
{
len += sprintf(str + len,
"%s(%g..%g/%g) ",
"%s(%f..%f/%f) ",
ms,
gran[i].min.f,
gran[i].max.f,
@ -623,7 +623,7 @@ int rot_sprintf_parm_gran(char *str, int nlen, setting_t parm,
if (ROT_PARM_IS_FLOAT(rig_idx2setting(i)))
{
len += sprintf(str + len,
"%s(%g..%g/%g) ",
"%s(%f..%f/%f) ",
ms,
gran[i].min.f,
gran[i].max.f,
@ -877,7 +877,7 @@ int print_ext_param(const struct confparams *cfp, rig_ptr_t ptr)
switch (cfp->type)
{
case RIG_CONF_NUMERIC:
fprintf((FILE *)ptr, "\t\tRange: %g..%g/%g\n", cfp->u.n.min, cfp->u.n.max,
fprintf((FILE *)ptr, "\t\tRange: %f..%f/%f\n", cfp->u.n.min, cfp->u.n.max,
cfp->u.n.step);
break;

Wyświetl plik

@ -95,6 +95,8 @@
#define TOK_ASYNC TOKEN_FRONTEND(37)
/** \brief Tuner external control pathname */
#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)
/*
* rig specific tokens

Wyświetl plik

@ -301,7 +301,7 @@ int dumpcaps(RIG *rig, FILE *fout)
if (priv_caps && RIG_BACKEND_NUM(rig->caps->rig_model) == RIG_ICOM
&& priv_caps->agc_levels_present)
{
for (i = 0; i <= RIG_AGC_LAST && priv_caps->agc_levels[i].level != RIG_AGC_LAST
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,
@ -310,31 +310,16 @@ int dumpcaps(RIG *rig, FILE *fout)
}
else
{
for (i = 0; i < HAMLIB_MAX_AGC_LEVELS && i < caps->agc_level_count; i++)
{
fprintf(fout, " %d=%s", caps->agc_levels[i],
rig_stragclevel(caps->agc_levels[i]));
}
if (i == 0)
{
fprintf(fout, " %d=%s", RIG_AGC_NONE, rig_stragclevel(RIG_AGC_NONE));
}
}
fprintf(fout, "\n");
if (i == 0)
{
rig_debug(RIG_DEBUG_WARN,
"%s: defaulting to all levels since rig does not have any\n", __func__);
// Fall back to printing out all levels for backwards-compatibility
for (i = RIG_AGC_OFF; i <= RIG_AGC_LAST; i++)
{
fprintf(fout, " %d=%s", i, rig_stragclevel(i));
}
fprintf(fout, " %d=%s", RIG_AGC_NONE, rig_stragclevel(RIG_AGC_NONE));
}
fprintf(fout, "\n");
@ -903,6 +888,8 @@ int dumpcaps(RIG *rig, FILE *fout)
fprintf(fout, "Can send DTMF:\t%c\n", caps->send_dtmf != NULL ? 'Y' : 'N');
fprintf(fout, "Can recv DTMF:\t%c\n", caps->recv_dtmf != NULL ? 'Y' : 'N');
fprintf(fout, "Can send Morse:\t%c\n", caps->send_morse != NULL ? 'Y' : 'N');
fprintf(fout, "Can stop Morse:\t%c\n", caps->stop_morse != NULL ? 'Y' : 'N');
fprintf(fout, "Can wait Morse:\t%c\n", caps->wait_morse != NULL ? 'Y' : 'N');
fprintf(fout, "Can send Voice:\t%c\n",
caps->send_voice_mem != NULL ? 'Y' : 'N');

Wyświetl plik

@ -1747,8 +1747,7 @@ readline_repeat:
rig_debug(RIG_DEBUG_WARN,
"%s: command %s not allowed when rig is powered off\n", __func__,
cmd_entry->name);
// retcode = -RIG_EPOWER;
retcode = RIG_OK;
retcode = -RIG_EPOWER;
}
else
{
@ -4779,7 +4778,7 @@ extern int flrig_cat_string(RIG *rig, const char *arg);
declare_proto_rig(send_cmd)
{
int retval;
struct rig_state *rs;
struct rig_state *rs = &rig->state;
int backend_num, cmd_len;
#define BUFSZ 512
char bufcmd[BUFSZ * 5]; // allow for 5 chars for binary
@ -4787,6 +4786,9 @@ declare_proto_rig(send_cmd)
char eom_buf[4] = { 0xa, 0xd, 0, 0 };
int binary = 0;
int rxbytes = BUFSZ;
int simulate = rig->caps->rig_model == RIG_MODEL_DUMMY ||
rig->caps->rig_model == RIG_MODEL_NONE ||
rs->rigport.rig == RIG_PORT_NONE;
ENTERFUNC2;
@ -4888,21 +4890,32 @@ declare_proto_rig(send_cmd)
tmpbuf);
}
rs = &rig->state;
rig_flush(&rs->rigport);
rig_debug(RIG_DEBUG_TRACE, "%s: rigport=%d, bufcmd=%s, cmd_len=%d\n", __func__,
rs->rigport.fd, hasbinary(bufcmd, cmd_len) ? "BINARY" : bufcmd, cmd_len);
// we don't want the 'w' command to wait too long
int save_retry = rs->rigport.retry;
rs->rigport.retry = 0;
retval = write_block(&rs->rigport, (unsigned char *) bufcmd, cmd_len);
rs->rigport.retry = save_retry;
if (retval != RIG_OK)
set_transaction_active(rig);
if (simulate)
{
RETURNFUNC2(retval);
rig_debug(RIG_DEBUG_VERBOSE, "%s: simulating response for model %s\n",
__func__, rig->caps->model_name);
}
else
{
rig_flush(&rs->rigport);
// we don't want the 'w' command to wait too long
int save_retry = rs->rigport.retry;
rs->rigport.retry = 0;
retval = write_block(&rs->rigport, (unsigned char *) bufcmd, cmd_len);
rs->rigport.retry = save_retry;
if (retval != RIG_OK)
{
rig_flush_force(&rs->rigport, 1);
set_transaction_inactive(rig);
RETURNFUNC2(retval);
}
}
if ((interactive && prompt) || (interactive && !prompt && ext_resp))
@ -4912,6 +4925,7 @@ declare_proto_rig(send_cmd)
fwrite(": ", 1, 2, fout); /* i.e. "Frequency" */
}
retval = 0;
do
{
if (arg2) { sscanf(arg2, "%d", &rxbytes); }
@ -4924,17 +4938,33 @@ declare_proto_rig(send_cmd)
if (arg2[0] == ';') { eom_buf[0] = ';'; }
/* Assumes CR or LF is end of line char for all ASCII protocols. */
retval = read_string(&rs->rigport, buf, rxbytes, eom_buf,
strlen(eom_buf), 0, 1);
if (retval < 0)
if (simulate)
{
rig_debug(RIG_DEBUG_ERR, "%s: read_string error %s\n", __func__,
rigerror(retval));
break;
if (retval == 0)
{
// Simulate a response by copying the command
memcpy(buf, bufcmd, cmd_len);
retval = cmd_len;
}
else
{
retval = 0;
}
}
else
{
/* Assumes CR or LF is end of line char for all ASCII protocols. */
retval = read_string(&rs->rigport, buf, rxbytes, eom_buf,
strlen(eom_buf), 0, 1);
if (retval < 0)
{
rig_debug(RIG_DEBUG_ERR, "%s: read_string error %s\n", __func__,
rigerror(retval));
break;
}
}
if (retval < BUFSZ)
{
@ -4976,6 +5006,9 @@ declare_proto_rig(send_cmd)
strncat(hexbuf, hex, hexbufbytes - 1);
}
rig_flush_force(&rs->rigport, 1);
set_transaction_inactive(rig);
rig_debug(RIG_DEBUG_TRACE, "%s: binary=%s, retval=%d\n", __func__, hexbuf,
retval);
fprintf(fout, "%s %d\n", hexbuf, retval);
@ -4990,7 +5023,10 @@ declare_proto_rig(send_cmd)
}
while (retval > 0 && rxbytes == BUFSZ);
// we use fwrite in case of any nulls in binary return
rig_flush_force(&rs->rigport, 1);
set_transaction_inactive(rig);
// we use fwrite in case of any nulls in binary return
if (binary) { fwrite(buf, 1, retval, fout); }
if (binary)
@ -4998,7 +5034,6 @@ declare_proto_rig(send_cmd)
fwrite("\n", 1, 1, fout);
}
if (retval > 0 || retval == -RIG_ETIMEOUT)
{
retval = RIG_OK;
@ -5395,13 +5430,15 @@ extern int netrigctl_send_raw(RIG *rig, char *s);
/* 0xa4 */
declare_proto_rig(send_raw)
{
int result;
int reply_len;
unsigned char term[1];
unsigned char buf[100];
unsigned char send[100];
unsigned char termbyte[1];
unsigned char *term = NULL;
unsigned char buf[200];
unsigned char send[200];
unsigned char *sendp = (unsigned char *)arg2;
int arg2_len = strlen(arg2);
int hex_flag = 0;
int is_binary = 0;
int buf_len = sizeof(buf);
int val = 0;
@ -5415,15 +5452,31 @@ declare_proto_rig(send_raw)
return retval;
}
if (strcmp(arg1, ";") == 0) { term[0] = ';'; }
else if (strcasecmp(arg1, "CR")) { term[0] = 0x0d; }
else if (strcasecmp(arg1, "LF")) { term[0] = 0x0a; }
else if (strcasecmp(arg1, "ICOM")) { term[0] = 0xfd; }
else if (sscanf(arg1, "%d", &val) == 1) { term[0] = 0; buf_len = val;}
if (strcmp(arg1, ";") == 0) { termbyte[0] = ';'; term = termbyte; }
else if (strcasecmp(arg1, "CR") == 0) { termbyte[0] = 0x0d; term = termbyte; }
else if (strcasecmp(arg1, "LF") == 0) { termbyte[0] = 0x0a; term = termbyte; }
else if (strcasecmp(arg1, "ICOM") == 0) { termbyte[0] = 0xfd; term = termbyte; }
else if (sscanf(arg1, "0x%x", &val) == 1) { termbyte[0] = val; term = termbyte; }
else if (sscanf(arg1, "%d", &val) == 1)
{
if (val < buf_len - 1)
{
// Reserve one byte more to allow padding with null
buf_len = val + 1;
}
else
{
rig_debug(RIG_DEBUG_ERR,
"%s: response length %d is larger than maximum of %d bytes",
__func__, val, buf_len);
return -RIG_EINVAL;
}
}
else
{
rig_debug(RIG_DEBUG_ERR,
"%s: unknown arg1 val=%s, expected ';' 'CR' 'LF' 'ICOM' or # of bytes where 0 means no reply and -1 means unknown",
"%s: unknown arg1 val=%s, expected ';', 'CR', 'LF', 'ICOM', 0xFF (hex byte) or "
"# of bytes where 0 means no reply and -1 means unknown",
__func__, arg1);
return -RIG_EINVAL;
}
@ -5432,12 +5485,18 @@ declare_proto_rig(send_raw)
{
arg2_len = parse_hex(arg2, send, sizeof(send));
sendp = send;
hex_flag = 1;
is_binary = 1;
}
rig_debug(RIG_DEBUG_TRACE, "%s:\n", __func__);
reply_len = rig_send_raw(rig, (unsigned char *)sendp, arg2_len, buf,
buf_len, term);
result = rig_send_raw(rig, (unsigned char *)sendp, arg2_len, buf,buf_len, term);
if (result < 0)
{
return result;
}
reply_len = result;
buf[buf_len + 1] = 0; // null terminate in case it's a string
if ((interactive && prompt) || (interactive && !prompt && ext_resp))
@ -5449,7 +5508,7 @@ declare_proto_rig(send_raw)
{
fprintf(fout, "No answer\n");
}
else if (hex_flag)
else if (is_binary)
{
int i;