kopia lustrzana https://github.com/Hamlib/Hamlib
Allow icom_rig_open() to succeed even if the rig is powered off. Fix issues with async I/O error code propagation. Allow rigctld daemon to start even if rig is powered off. Add mutex locks around rig_open()/rig_close() calls as multiple client connections could end up calling them concurrently, which could lead to all kinds of issues as the functions are not meant to be thread-safe. This also blocks execution of rigctl commands during rig open/close.
rodzic
be992b8a36
commit
1f428c8d95
|
@ -929,7 +929,7 @@ icom_rig_open(RIG *rig)
|
|||
struct rig_state *rs = &rig->state;
|
||||
struct icom_priv_data *priv = (struct icom_priv_data *) rs->priv;
|
||||
int retry_flag = 1;
|
||||
int retry_save = rs->rigport.retry;
|
||||
short retry_save = rs->rigport.retry;
|
||||
|
||||
ENTERFUNC;
|
||||
|
||||
|
@ -969,7 +969,7 @@ retry_open:
|
|||
retval = abs(rig_set_powerstat(rig, 1));
|
||||
|
||||
// this is only a fatal error if powerstat is implemented
|
||||
// if not iplemented than we're at an error here
|
||||
// if not implemented than we're at an error here
|
||||
if (retval != RIG_OK && retval != RIG_ENIMPL && retval != RIG_ENAVAIL)
|
||||
{
|
||||
rig_debug(RIG_DEBUG_WARN, "%s: unexpected retval here: %s\n",
|
||||
|
@ -978,17 +978,18 @@ retry_open:
|
|||
rig_debug(RIG_DEBUG_WARN, "%s: rig_set_powerstat failed: =%s\n", __func__,
|
||||
rigerror(retval));
|
||||
rs->rigport.retry = retry_save;
|
||||
RETURNFUNC(retval);
|
||||
}
|
||||
|
||||
// Now that we're powered up let's try again
|
||||
retval_echo = icom_get_usb_echo_off(rig);
|
||||
|
||||
if (retval_echo != 0 && retval_echo != 1)
|
||||
if (retval == RIG_OK)
|
||||
{
|
||||
rig_debug(RIG_DEBUG_ERR, "%s: Unable to determine USB echo status\n", __func__);
|
||||
rs->rigport.retry = retry_save;
|
||||
RETURNFUNC(retval);
|
||||
// Now that we're powered up let's try again
|
||||
retval_echo = icom_get_usb_echo_off(rig);
|
||||
|
||||
if (retval_echo != 0 && retval_echo != 1)
|
||||
{
|
||||
rig_debug(RIG_DEBUG_ERR, "%s: Unable to determine USB echo status\n", __func__);
|
||||
rs->rigport.retry = retry_save;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (retval != RIG_OK)
|
||||
|
@ -1005,11 +1006,14 @@ retry_open:
|
|||
}
|
||||
|
||||
rs->rigport.retry = retry_save;
|
||||
RETURNFUNC(retval);
|
||||
}
|
||||
|
||||
rig->state.current_vfo = icom_current_vfo(rig);
|
||||
priv->poweron = 1;
|
||||
priv->poweron = (retval == RIG_OK) ? 1 : 0;
|
||||
|
||||
if (priv->poweron)
|
||||
{
|
||||
rig->state.current_vfo = icom_current_vfo(rig);
|
||||
}
|
||||
|
||||
if (rig->caps->has_get_func & RIG_FUNC_SATMODE)
|
||||
{
|
||||
|
@ -7834,6 +7838,7 @@ int icom_set_powerstat(RIG *rig, powerstat_t status)
|
|||
|
||||
if (retval == RIG_OK)
|
||||
{
|
||||
rig->state.current_vfo = icom_current_vfo(rig);
|
||||
RETURNFUNC(retval);
|
||||
}
|
||||
else
|
||||
|
|
65
src/iofunc.c
65
src/iofunc.c
|
@ -437,7 +437,7 @@ extern int is_uh_radio_fd(int fd);
|
|||
static int port_read_sync_data_error_code(hamlib_port_t *p)
|
||||
{
|
||||
ssize_t total_bytes_read = 0;
|
||||
unsigned char data;
|
||||
signed char data;
|
||||
int result;
|
||||
|
||||
do {
|
||||
|
@ -810,13 +810,14 @@ static ssize_t port_read_generic(hamlib_port_t *p, void *buf, size_t count, int
|
|||
#define port_select(p,n,r,w,e,t,d) select((n),(r),(w),(e),(t))
|
||||
//! @endcond
|
||||
|
||||
static int flush_and_read_last_byte(hamlib_port_t *p, int fd, int direct)
|
||||
static int port_read_sync_data_error_code(hamlib_port_t *p, int fd, int direct)
|
||||
{
|
||||
fd_set rfds, efds;
|
||||
ssize_t total_bytes_read = 0;
|
||||
ssize_t bytes_read;
|
||||
struct timeval tv_timeout;
|
||||
int result;
|
||||
char data;
|
||||
signed char data;
|
||||
|
||||
do {
|
||||
tv_timeout.tv_sec = 0;
|
||||
|
@ -829,21 +830,32 @@ static int flush_and_read_last_byte(hamlib_port_t *p, int fd, int direct)
|
|||
result = port_select(p, fd + 1, &rfds, NULL, &efds, &tv_timeout, direct);
|
||||
if (result < 0)
|
||||
{
|
||||
rig_debug(RIG_DEBUG_VERBOSE, "%s(): select() timeout, direct=%d\n", __func__, direct);
|
||||
return -RIG_ETIMEOUT;
|
||||
}
|
||||
if (result == 0)
|
||||
{
|
||||
if (total_bytes_read > 0) {
|
||||
rig_debug(RIG_DEBUG_VERBOSE, "%s(): returning error code %d, direct=%d\n", __func__, (int) data, direct);
|
||||
return data;
|
||||
}
|
||||
|
||||
rig_debug(RIG_DEBUG_ERR, "%s(): no error code available\n", __func__);
|
||||
return -RIG_EIO;
|
||||
}
|
||||
|
||||
if (FD_ISSET(fd, &efds))
|
||||
{
|
||||
rig_debug(RIG_DEBUG_ERR, "%s(): select() indicated error\n", __func__);
|
||||
return -RIG_EIO;
|
||||
}
|
||||
|
||||
bytes_read = read(fd, &data, 1);
|
||||
total_bytes_read += bytes_read;
|
||||
} while (bytes_read > 0);
|
||||
|
||||
rig_debug(RIG_DEBUG_VERBOSE, "%s(): returning error code %d\n", __func__, data);
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
|
@ -886,28 +898,30 @@ static int port_wait_for_data(hamlib_port_t *p, int direct)
|
|||
else if (result < 0)
|
||||
{
|
||||
rig_debug(RIG_DEBUG_ERR,
|
||||
"%s(): select() error: %s\n",
|
||||
"%s(): select() error, direct=%d: %s\n",
|
||||
__func__,
|
||||
direct,
|
||||
strerror(errno));
|
||||
return -RIG_EIO;
|
||||
}
|
||||
|
||||
if (FD_ISSET(fd, &efds))
|
||||
{
|
||||
rig_debug(RIG_DEBUG_ERR, "%s(): fd error\n", __func__);
|
||||
rig_debug(RIG_DEBUG_ERR, "%s(): fd error, direct=%d\n", __func__, direct);
|
||||
return -RIG_EIO;
|
||||
}
|
||||
if (!direct)
|
||||
{
|
||||
if (FD_ISSET(errorfd, &efds))
|
||||
{
|
||||
rig_debug(RIG_DEBUG_ERR, "%s(): fd error from sync error pipe\n", __func__);
|
||||
rig_debug(RIG_DEBUG_ERR, "%s(): fd error from sync error pipe, direct=%d\n", __func__, direct);
|
||||
return -RIG_EIO;
|
||||
}
|
||||
|
||||
if (FD_ISSET(errorfd, &rfds))
|
||||
{
|
||||
return flush_and_read_last_byte(p, errorfd, 0);
|
||||
rig_debug(RIG_DEBUG_VERBOSE, "%s(): attempting to read error code, direct=%d\n", __func__, direct);
|
||||
return port_read_sync_data_error_code(p, errorfd, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1078,7 +1092,7 @@ static int read_block_generic(hamlib_port_t *p, unsigned char *rxbuffer, size_t
|
|||
struct timeval start_time, end_time, elapsed_time;
|
||||
int total_count = 0;
|
||||
|
||||
rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
|
||||
rig_debug(RIG_DEBUG_VERBOSE, "%s called, direct=%d\n", __func__, direct);
|
||||
|
||||
#ifdef ASYNC_BUG
|
||||
if (!p->async && !direct)
|
||||
|
@ -1111,11 +1125,12 @@ static int read_block_generic(hamlib_port_t *p, unsigned char *rxbuffer, size_t
|
|||
}
|
||||
|
||||
rig_debug(RIG_DEBUG_WARN,
|
||||
"%s(): Timed out %d.%d seconds after %d chars\n",
|
||||
"%s(): Timed out %d.%d seconds after %d chars, direct=%d\n",
|
||||
__func__,
|
||||
(int)elapsed_time.tv_sec,
|
||||
(int)elapsed_time.tv_usec,
|
||||
total_count);
|
||||
total_count,
|
||||
direct);
|
||||
|
||||
return -RIG_ETIMEOUT;
|
||||
}
|
||||
|
@ -1126,7 +1141,7 @@ static int read_block_generic(hamlib_port_t *p, unsigned char *rxbuffer, size_t
|
|||
{
|
||||
dump_hex((unsigned char *) rxbuffer, total_count);
|
||||
}
|
||||
rig_debug(RIG_DEBUG_ERR, "%s(): I/O error after %d chars: %d\n", __func__, total_count, result);
|
||||
rig_debug(RIG_DEBUG_ERR, "%s(): I/O error after %d chars, direct=%d: %d\n", __func__, total_count, direct, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -1138,7 +1153,7 @@ static int read_block_generic(hamlib_port_t *p, unsigned char *rxbuffer, size_t
|
|||
|
||||
if (rd_count < 0)
|
||||
{
|
||||
rig_debug(RIG_DEBUG_ERR, "%s(): read failed - %s\n", __func__, strerror(errno));
|
||||
rig_debug(RIG_DEBUG_ERR, "%s(): read failed, direct=%d - %s\n", __func__, direct, strerror(errno));
|
||||
return -RIG_EIO;
|
||||
}
|
||||
|
||||
|
@ -1148,7 +1163,7 @@ static int read_block_generic(hamlib_port_t *p, unsigned char *rxbuffer, size_t
|
|||
|
||||
if (direct)
|
||||
{
|
||||
rig_debug(RIG_DEBUG_TRACE, "%s(): RX %d bytes\n", __func__, total_count);
|
||||
rig_debug(RIG_DEBUG_TRACE, "%s(): RX %d bytes, direct=%d\n", __func__, total_count, direct);
|
||||
dump_hex((unsigned char *) rxbuffer, total_count);
|
||||
}
|
||||
|
||||
|
@ -1229,7 +1244,7 @@ static int read_string_generic(hamlib_port_t *p,
|
|||
return -RIG_EINTERNAL;
|
||||
}
|
||||
|
||||
rig_debug(RIG_DEBUG_TRACE, "%s called, rxmax=%d\n", __func__, (int)rxmax);
|
||||
rig_debug(RIG_DEBUG_TRACE, "%s called, rxmax=%d direct=%d\n", __func__, (int)rxmax, direct);
|
||||
|
||||
if (!p || !rxbuffer)
|
||||
{
|
||||
|
@ -1272,11 +1287,12 @@ static int read_string_generic(hamlib_port_t *p,
|
|||
if (!flush_flag)
|
||||
{
|
||||
rig_debug(RIG_DEBUG_WARN,
|
||||
"%s(): Timed out %d.%03d seconds after %d chars\n",
|
||||
"%s(): Timed out %d.%03d seconds after %d chars, direct=%d\n",
|
||||
__func__,
|
||||
(int)elapsed_time.tv_sec,
|
||||
(int)elapsed_time.tv_usec / 1000,
|
||||
total_count);
|
||||
total_count,
|
||||
direct);
|
||||
}
|
||||
|
||||
return -RIG_ETIMEOUT;
|
||||
|
@ -1291,7 +1307,7 @@ static int read_string_generic(hamlib_port_t *p,
|
|||
{
|
||||
dump_hex(rxbuffer, total_count);
|
||||
}
|
||||
rig_debug(RIG_DEBUG_ERR, "%s(): I/O error after %d chars: %d\n", __func__, total_count, result);
|
||||
rig_debug(RIG_DEBUG_ERR, "%s(): I/O error after %d chars, direct=%d: %d\n", __func__, total_count, direct, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -1306,7 +1322,7 @@ static int read_string_generic(hamlib_port_t *p,
|
|||
if (errno == EAGAIN)
|
||||
{
|
||||
hl_usleep(5 * 1000);
|
||||
rig_debug(RIG_DEBUG_WARN, "%s: port_read is busy?\n", __func__);
|
||||
rig_debug(RIG_DEBUG_WARN, "%s: port_read is busy? direct=%d\n", __func__, direct);
|
||||
}
|
||||
}
|
||||
while (++i < 10 && errno == EBUSY); // 50ms should be enough
|
||||
|
@ -1318,7 +1334,7 @@ static int read_string_generic(hamlib_port_t *p,
|
|||
{
|
||||
dump_hex((unsigned char *) rxbuffer, total_count);
|
||||
}
|
||||
rig_debug(RIG_DEBUG_ERR, "%s(): read failed - %s\n", __func__, strerror(errno));
|
||||
rig_debug(RIG_DEBUG_ERR, "%s(): read failed, direct=%d - %s\n", __func__, direct, strerror(errno));
|
||||
|
||||
return -RIG_EIO;
|
||||
}
|
||||
|
@ -1348,14 +1364,15 @@ static int read_string_generic(hamlib_port_t *p,
|
|||
*/
|
||||
rxbuffer[total_count] = '\000';
|
||||
|
||||
if (direct)
|
||||
{
|
||||
// if (direct)
|
||||
// {
|
||||
rig_debug(RIG_DEBUG_TRACE,
|
||||
"%s(): RX %d characters\n",
|
||||
"%s(): RX %d characters, direct=%d\n",
|
||||
__func__,
|
||||
total_count);
|
||||
total_count,
|
||||
direct);
|
||||
dump_hex((unsigned char *) rxbuffer, total_count);
|
||||
}
|
||||
// }
|
||||
|
||||
return total_count; /* return bytes count read */
|
||||
}
|
||||
|
|
17
src/rig.c
17
src/rig.c
|
@ -1070,10 +1070,12 @@ int HAMLIB_API rig_open(RIG *rig)
|
|||
|
||||
if (status != RIG_OK)
|
||||
{
|
||||
remove_opened_rig(rig);
|
||||
#ifdef ASYNC_BUG
|
||||
async_data_handler_stop(rig);
|
||||
#endif
|
||||
port_close(&rs->rigport, rs->rigport.type.rig);
|
||||
rs->comm_state = 0;
|
||||
RETURNFUNC(status);
|
||||
}
|
||||
}
|
||||
|
@ -6992,15 +6994,16 @@ void *async_data_handler(void *arg)
|
|||
|
||||
if (result < 0)
|
||||
{
|
||||
// TODO: it may be necessary to have mutex locking on transaction_active flag
|
||||
if (rs->transaction_active)
|
||||
{
|
||||
unsigned char data = (unsigned char) result;
|
||||
write_block_sync_error(&rs->rigport, &data, 1);
|
||||
}
|
||||
|
||||
// Timeouts occur always if there is nothing to receive, so they are not really errors in this case
|
||||
if (result != -RIG_ETIMEOUT)
|
||||
{
|
||||
// TODO: it may be necessary to have mutex locking on transaction_active flag
|
||||
if (rs->transaction_active)
|
||||
{
|
||||
unsigned char data = (unsigned char) result;
|
||||
write_block_sync_error(&rs->rigport, &data, 1);
|
||||
}
|
||||
|
||||
// TODO: error handling -> store errors in rig state -> to be exposed in async snapshot packets
|
||||
rig_debug(RIG_DEBUG_ERR, "%s: read_frame_direct() failed, result=%d\n",
|
||||
__func__, result);
|
||||
|
|
|
@ -135,6 +135,7 @@ static unsigned client_count;
|
|||
#endif
|
||||
|
||||
static RIG *my_rig; /* handle to rig (instance) */
|
||||
static volatile int rig_opened = 0;
|
||||
static int verbose;
|
||||
|
||||
#ifdef HAVE_SIG_ATOMIC_T
|
||||
|
@ -687,14 +688,15 @@ int main(int argc, char *argv[])
|
|||
exit(0);
|
||||
}
|
||||
|
||||
/* open and close rig connection to check early for issues */
|
||||
/* attempt to open rig to check early for issues */
|
||||
retcode = rig_open(my_rig);
|
||||
rig_opened = retcode == RIG_OK ? 1 : 0;
|
||||
|
||||
if (retcode != RIG_OK)
|
||||
{
|
||||
fprintf(stderr, "rig_open: error = %s %s %s \n", rigerror(retcode), rig_file,
|
||||
strerror(errno));
|
||||
exit(2);
|
||||
// continue even if opening the rig fails, because it may be powered off
|
||||
}
|
||||
|
||||
if (verbose > RIG_DEBUG_ERR)
|
||||
|
@ -1010,8 +1012,6 @@ int main(int argc, char *argv[])
|
|||
}
|
||||
while (retcode == 0 && !ctrl_c);
|
||||
|
||||
network_multicast_publisher_stop(my_rig);
|
||||
|
||||
#ifdef HAVE_PTHREAD
|
||||
/* allow threads to finish current action */
|
||||
mutex_rigctld(1);
|
||||
|
@ -1026,6 +1026,9 @@ int main(int argc, char *argv[])
|
|||
#else
|
||||
rig_close(my_rig); /* close port */
|
||||
#endif
|
||||
|
||||
network_multicast_publisher_stop(my_rig);
|
||||
|
||||
rig_cleanup(my_rig); /* if you care about memory */
|
||||
|
||||
#ifdef __MINGW32__
|
||||
|
@ -1132,10 +1135,9 @@ void *handle_socket(void *arg)
|
|||
|
||||
#endif
|
||||
|
||||
int rig_opened = 1; // our rig is already open
|
||||
|
||||
do
|
||||
{
|
||||
mutex_rigctld(1);
|
||||
if (!rig_opened)
|
||||
{
|
||||
retcode = rig_open(my_rig);
|
||||
|
@ -1143,6 +1145,7 @@ void *handle_socket(void *arg)
|
|||
rig_debug(RIG_DEBUG_ERR, "%s: rig_open reopened retcode=%d\n", __func__,
|
||||
retcode);
|
||||
}
|
||||
mutex_rigctld(0);
|
||||
|
||||
if (rig_opened) // only do this if rig is open
|
||||
{
|
||||
|
@ -1168,15 +1171,24 @@ void *handle_socket(void *arg)
|
|||
|
||||
do
|
||||
{
|
||||
mutex_rigctld(1);
|
||||
retcode = rig_close(my_rig);
|
||||
hl_usleep(1000 * 1000);
|
||||
rig_opened = 0;
|
||||
mutex_rigctld(0);
|
||||
rig_debug(RIG_DEBUG_ERR, "%s: rig_close retcode=%d\n", __func__, retcode);
|
||||
retcode = rig_open(my_rig);
|
||||
rig_opened = retcode == RIG_OK ? 1 : 0;
|
||||
rig_debug(RIG_DEBUG_ERR, "%s: rig_open retcode=%d, opened=%d\n", __func__,
|
||||
retcode, rig_opened);
|
||||
|
||||
hl_usleep(1000 * 1000);
|
||||
|
||||
mutex_rigctld(1);
|
||||
if (!rig_opened) {
|
||||
retcode = rig_open(my_rig);
|
||||
rig_opened = retcode == RIG_OK ? 1 : 0;
|
||||
rig_debug(RIG_DEBUG_ERR, "%s: rig_open retcode=%d, opened=%d\n", __func__,
|
||||
retcode, rig_opened);
|
||||
}
|
||||
mutex_rigctld(0);
|
||||
}
|
||||
while (retry-- > 0 && retcode != RIG_OK);
|
||||
while (!rig_opened && retry-- > 0 && retcode != RIG_OK);
|
||||
}
|
||||
}
|
||||
while (retcode == RIG_OK || RIG_IS_SOFT_ERRCODE(-retcode));
|
||||
|
|
Ładowanie…
Reference in New Issue