diff --git a/include/hamlib/rig.h b/include/hamlib/rig.h index 00f6fe5d7..ce9dfe38d 100644 --- a/include/hamlib/rig.h +++ b/include/hamlib/rig.h @@ -2218,6 +2218,7 @@ typedef struct hamlib_port { int client_port; /*!< client socket port for tcp connection */ RIG *rig; /*!< our parent RIG device */ +#ifdef ASYNC_BUG int async; /*!< enable asynchronous data handling if true */ #if defined(_WIN32) hamlib_async_pipe_t *sync_data_pipe; /*!< pipe data structure for synchronous data */ @@ -2228,6 +2229,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 +#endif } hamlib_port_t; //! @endcond @@ -2239,7 +2241,7 @@ typedef hamlib_port_t port_t; #define HAMLIB_ELAPSED_SET 1 #define HAMLIB_ELAPSED_INVALIDATE 2 -#define HAMLIB_CACHE_ALWAYS -1 /*< value to set cache timeout to always use cache */ +#define HAMLIB_CACHE_ALWAYS (-1) /*< value to set cache timeout to always use cache */ typedef enum { HAMLIB_CACHE_ALL, // to set all cache timeouts at once @@ -2399,7 +2401,7 @@ struct rig_state { rig_ptr_t priv; /*!< Pointer to private rig state data. */ rig_ptr_t obj; /*!< Internal use by hamlib++ for event handling. */ - int async_data; /*!< Whether async data mode is on */ + int async_data_enabled; /*!< Whether async data mode is enabled */ int poll_interval; /*!< Rig state polling period in milliseconds */ freq_t current_freq; /*!< Frequency currently set */ rmode_t current_mode; /*!< Mode currently set */ diff --git a/src/conf.c b/src/conf.c index 9347f7376..40bebeae1 100644 --- a/src/conf.c +++ b/src/conf.c @@ -168,6 +168,11 @@ static const struct confparams frontend_cfg_params[] = "Suppress get_freq on VFOB for RIT tuning satellites", "Unset", RIG_CONF_COMBO, { .c = {{ "Unset", "ON", "OFF", NULL }} } }, + { + TOK_ASYNC, "async", "Asynchronous data transfer support", + "True enables asynchronous data transfer for backends that support it. This enabled handling of transceive and spectrum data, for example.", + "0", RIG_CONF_CHECKBUTTON, { } + }, { RIG_CONF_END, NULL, } }; @@ -666,6 +671,15 @@ static int frontend_set_conf(RIG *rig, token_t token, const char *val) rs->twiddle_rit = val_i ? 1 : 0; break; + case TOK_ASYNC: + if (1 != sscanf(val, "%d", &val_i)) + { + return -RIG_EINVAL; //value format error + } + + rs->async_data_enabled = val_i ? 1 : 0; + break; + default: return -RIG_EINVAL; } @@ -1010,6 +1024,9 @@ static int frontend_get_conf(RIG *rig, token_t token, char *val) sprintf(val, "%d", rs->twiddle_rit); break; + case TOK_ASYNC: + sprintf(val, "%d", rs->async_data_enabled); + break; default: return -RIG_EINVAL; diff --git a/src/network.c b/src/network.c index a08d20efa..eb3175d92 100644 --- a/src/network.c +++ b/src/network.c @@ -692,21 +692,37 @@ static int multicast_publisher_write_packet_header(RIG *rig, multicast_publisher int network_publish_rig_poll_data(RIG *rig) { + struct rig_state *rs = &rig->state; multicast_publisher_data_packet packet = { .type = MULTICAST_PUBLISHER_DATA_PACKET_TYPE_POLL, .padding = 0, .data_length = 0, }; + + if (rs->multicast_publisher_priv_data == NULL) + { + // Silently ignore call if multicast publisher is not enabled + return RIG_OK; + } + return multicast_publisher_write_packet_header(rig, &packet); } int network_publish_rig_transceive_data(RIG *rig) { + struct rig_state *rs = &rig->state; multicast_publisher_data_packet packet = { .type = MULTICAST_PUBLISHER_DATA_PACKET_TYPE_TRANSCEIVE, .padding = 0, .data_length = 0, }; + + if (rs->multicast_publisher_priv_data == NULL) + { + // Silently ignore call if multicast publisher is not enabled + return RIG_OK; + } + return multicast_publisher_write_packet_header(rig, &packet); } @@ -724,8 +740,8 @@ int network_publish_rig_spectrum_data(RIG *rig, struct rig_spectrum_line *line) if (rs->multicast_publisher_priv_data == NULL) { - // Silently ignore if multicast publisher is not enabled - RETURNFUNC(RIG_OK); + // Silently ignore call if multicast publisher is not enabled + return RIG_OK; } result = multicast_publisher_write_packet_header(rig, &packet); diff --git a/src/rig.c b/src/rig.c index 868bd07c1..d4780b557 100644 --- a/src/rig.c +++ b/src/rig.c @@ -452,18 +452,15 @@ RIG *HAMLIB_API rig_init(rig_model_t rig_model) */ rs = &rig->state; + rs->async_data_enabled = 0; rs->rigport.fd = -1; rs->pttport.fd = -1; rs->comm_state = 0; rig_debug(RIG_DEBUG_VERBOSE, "%s: rs->comm_state==0?=%d\n", __func__, rs->comm_state); rs->rigport.type.rig = caps->port_type; /* default from caps */ -#ifdef ASYNC_BUG -#ifdef HAVE_PTHREAD - rs->rigport.async = caps->async_data_supported; -#else +#if defined(ASYNC_BUG) && defined(HAVE_PTHREAD) rs->rigport.async = 0; -#endif #endif switch (caps->port_type) @@ -513,11 +510,6 @@ RIG *HAMLIB_API rig_init(rig_model_t rig_model) rs->vfo_comp = 0.0; /* override it with preferences */ rs->current_vfo = RIG_VFO_CURR; /* we don't know yet! */ rs->tx_vfo = RIG_VFO_CURR; /* we don't know yet! */ -#ifdef HAVE_PTHREAD - rs->async_data = caps->async_data_supported; -#else - rs->async_data = 0; -#endif rs->poll_interval = 0; // disable polling by default rs->lo_freq = 0; rs->cache.timeout_ms = 500; // 500ms cache timeout by default @@ -723,6 +715,12 @@ int HAMLIB_API rig_open(RIG *rig) rs = &rig->state; rs->rigport.rig = rig; +#if defined(ASYNC_BUG) && defined(HAVE_PTHREAD) + // Enable async data only if it's enabled through conf settings *and* supported by the backend + rs->async_data_enabled = rs->async_data_enabled && caps->async_data_supported; + rs->rigport.async = rs->async_data_enabled; +#endif + if (strlen(rs->rigport.pathname) > 0) { char hoststr[256], portstr[6]; @@ -6880,39 +6878,39 @@ HAMLIB_EXPORT(void) sync_callback(int lock) #ifdef ASYNC_BUG static int async_data_handler_start(RIG *rig) { - const struct rig_caps *caps = rig->caps; struct rig_state *rs = &rig->state; async_data_handler_priv_data *async_data_handler_priv; ENTERFUNC; + if (!rs->async_data_enabled) + { + rig_debug(RIG_DEBUG_TRACE, "%s: async data support disabled\n", __func__); + RETURNFUNC(RIG_OK); + } + #ifdef ASYNC_BUG #ifdef HAVE_PTHREAD - if (caps->async_data_supported) + rs->async_data_handler_thread_run = 1; + rs->async_data_handler_priv_data = calloc(1, + sizeof(async_data_handler_priv_data)); + + if (rs->async_data_handler_priv_data == NULL) { - rs->async_data_handler_thread_run = 1; - rs->async_data_handler_priv_data = calloc(1, - sizeof(async_data_handler_priv_data)); + RETURNFUNC(-RIG_ENOMEM); + } - if (rs->async_data_handler_priv_data == NULL) - { - RETURNFUNC(-RIG_ENOMEM); - } + async_data_handler_priv = (async_data_handler_priv_data *) + rs->async_data_handler_priv_data; + async_data_handler_priv->args.rig = rig; + int err = pthread_create(&async_data_handler_priv->thread_id, NULL, + async_data_handler, &async_data_handler_priv->args); - async_data_handler_priv = (async_data_handler_priv_data *) - rs->async_data_handler_priv_data; - async_data_handler_priv->args.rig = rig; - int err = pthread_create(&async_data_handler_priv->thread_id, NULL, - async_data_handler, &async_data_handler_priv->args); - - if (err) - { - rig_debug(RIG_DEBUG_ERR, "%s(%d) pthread_create error: %s\n", __FILE__, - __LINE__, - strerror(errno)); - RETURNFUNC(-RIG_EINTERNAL); - } + if (err) + { + rig_debug(RIG_DEBUG_ERR, "%s: pthread_create error: %s\n", __func__, strerror(errno)); + RETURNFUNC(-RIG_EINTERNAL); } #endif @@ -6943,8 +6941,7 @@ static int async_data_handler_stop(RIG *rig) if (err) { - rig_debug(RIG_DEBUG_ERR, "%s(%d): pthread_join error: %s\n", __FILE__, __LINE__, - strerror(errno)); + rig_debug(RIG_DEBUG_ERR, "%s: pthread_join error: %s\n", __func__, strerror(errno)); // just ignore the error } @@ -6973,9 +6970,7 @@ void *async_data_handler(void *arg) int result; #endif - rig_debug(RIG_DEBUG_VERBOSE, "%s(%d): Starting async data handler thread\n", - __FILE__, - __LINE__); + rig_debug(RIG_DEBUG_VERBOSE, "%s: Starting async data handler thread\n", __func__); // TODO: check how to enable "transceive" on recent Kenwood/Yaesu rigs // TODO: add initial support for async in Kenwood kenwood_transaction (+one) functions -> add transaction_active flag usage @@ -7045,9 +7040,7 @@ void *async_data_handler(void *arg) #endif - rig_debug(RIG_DEBUG_VERBOSE, "%s(%d): Stopping async data handler thread\n", - __FILE__, - __LINE__); + rig_debug(RIG_DEBUG_VERBOSE, "%s: Stopping async data handler thread\n", __func__); return NULL; } diff --git a/src/token.h b/src/token.h index b73174a69..46b80f19e 100644 --- a/src/token.h +++ b/src/token.h @@ -91,6 +91,9 @@ #define TOK_PTT_SHARE TOKEN_FRONTEND(35) /** \brief PTT share with other applications */ #define TOK_FLUSHX TOKEN_FRONTEND(36) +/** \brief Asynchronous data transfer support */ +#define TOK_ASYNC TOKEN_FRONTEND(37) + /* * rig specific tokens */