From b2310e62d64cc2c51722bbe0289b5930f7f62140 Mon Sep 17 00:00:00 2001 From: Jef Driesen Date: Mon, 25 Jan 2021 21:35:38 +0100 Subject: [PATCH 1/5] Pass the descriptor to the filter function Passing the descriptor for which the filter function is being called is a good practice and will also allow to implement some more specific filtering in the future. --- src/descriptor.c | 74 ++++++++++++++++++++++++++++-------------------- 1 file changed, 44 insertions(+), 30 deletions(-) diff --git a/src/descriptor.c b/src/descriptor.c index 794fd1d..d287393 100644 --- a/src/descriptor.c +++ b/src/descriptor.c @@ -50,22 +50,22 @@ typedef int (*dc_match_t)(const void *, const void *); -typedef int (*dc_filter_t) (dc_transport_t transport, const void *userdata, void *params); +typedef int (*dc_filter_t) (dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata, void *params); -static int dc_filter_uwatec (dc_transport_t transport, const void *userdata, void *params); -static int dc_filter_suunto (dc_transport_t transport, const void *userdata, void *params); -static int dc_filter_shearwater (dc_transport_t transport, const void *userdata, void *params); -static int dc_filter_hw (dc_transport_t transport, const void *userdata, void *params); -static int dc_filter_tecdiving (dc_transport_t transport, const void *userdata, void *params); -static int dc_filter_mares (dc_transport_t transport, const void *userdata, void *params); -static int dc_filter_divesystem (dc_transport_t transport, const void *userdata, void *params); -static int dc_filter_oceanic (dc_transport_t transport, const void *userdata, void *params); -static int dc_filter_mclean (dc_transport_t transport, const void *userdata, void *params); -static int dc_filter_atomic (dc_transport_t transport, const void *userdata, void *params); -static int dc_filter_deepsix (dc_transport_t transport, const void *userdata, void *params); -static int dc_filter_deepblu (dc_transport_t transport, const void *userdata, void *params); -static int dc_filter_oceans (dc_transport_t transport, const void *userdata, void *params); -static int dc_filter_divesoft (dc_transport_t transport, const void *userdata, void *params); +static int dc_filter_uwatec (dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata, void *params); +static int dc_filter_suunto (dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata, void *params); +static int dc_filter_shearwater (dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata, void *params); +static int dc_filter_hw (dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata, void *params); +static int dc_filter_tecdiving (dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata, void *params); +static int dc_filter_mares (dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata, void *params); +static int dc_filter_divesystem (dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata, void *params); +static int dc_filter_oceanic (dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata, void *params); +static int dc_filter_mclean (dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata, void *params); +static int dc_filter_atomic (dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata, void *params); +static int dc_filter_deepsix (dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata, void *params); +static int dc_filter_deepblu (dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata, void *params); +static int dc_filter_oceans (dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata, void *params); +static int dc_filter_divesoft (dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata, void *params); static dc_status_t dc_descriptor_iterator_next (dc_iterator_t *iterator, void *item); @@ -570,7 +570,8 @@ static const char * const rfcomm[] = { NULL }; -static int dc_filter_uwatec (dc_transport_t transport, const void *userdata, void *params) +static int +dc_filter_uwatec (dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata, void *params) { static const char * const irda[] = { "Aladin Smart Com", @@ -607,7 +608,8 @@ static int dc_filter_uwatec (dc_transport_t transport, const void *userdata, voi return 1; } -static int dc_filter_suunto (dc_transport_t transport, const void *userdata, void *params) +static int +dc_filter_suunto (dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata, void *params) { static const dc_usb_desc_t usbhid[] = { {0x1493, 0x0030}, // Eon Steel @@ -631,7 +633,8 @@ static int dc_filter_suunto (dc_transport_t transport, const void *userdata, voi return 1; } -static int dc_filter_hw (dc_transport_t transport, const void *userdata, void *params) +static int +dc_filter_hw (dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata, void *params) { static const char * const bluetooth[] = { "OSTC", @@ -647,7 +650,8 @@ static int dc_filter_hw (dc_transport_t transport, const void *userdata, void *p return 1; } -static int dc_filter_shearwater (dc_transport_t transport, const void *userdata, void *params) +static int +dc_filter_shearwater (dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata, void *params) { static const char * const bluetooth[] = { "Predator", @@ -670,7 +674,8 @@ static int dc_filter_shearwater (dc_transport_t transport, const void *userdata, return 1; } -static int dc_filter_tecdiving (dc_transport_t transport, const void *userdata, void *params) +static int +dc_filter_tecdiving (dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata, void *params) { static const char * const bluetooth[] = { "DiveComputer", @@ -685,7 +690,8 @@ static int dc_filter_tecdiving (dc_transport_t transport, const void *userdata, return 1; } -static int dc_filter_mares (dc_transport_t transport, const void *userdata, void *params) +static int +dc_filter_mares (dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata, void *params) { static const char * const bluetooth[] = { "Mares bluelink pro", @@ -699,7 +705,8 @@ static int dc_filter_mares (dc_transport_t transport, const void *userdata, void return 1; } -static int dc_filter_divesystem (dc_transport_t transport, const void *userdata, void *params) +static int +dc_filter_divesystem (dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata, void *params) { static const char * const bluetooth[] = { "DS", @@ -714,7 +721,8 @@ static int dc_filter_divesystem (dc_transport_t transport, const void *userdata, return 1; } -static int dc_filter_oceanic (dc_transport_t transport, const void *userdata, void *params) +static int +dc_filter_oceanic (dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata, void *params) { static const unsigned int model[] = { 0x4552, // Oceanic Pro Plus X @@ -741,7 +749,8 @@ static int dc_filter_oceanic (dc_transport_t transport, const void *userdata, vo return 1; } -static int dc_filter_mclean(dc_transport_t transport, const void *userdata, void *params) +static int +dc_filter_mclean(dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata, void *params) { static const char * const bluetooth[] = { "McLean Extreme", @@ -756,7 +765,8 @@ static int dc_filter_mclean(dc_transport_t transport, const void *userdata, void return 1; } -static int dc_filter_atomic (dc_transport_t transport, const void *userdata, void *params) +static int +dc_filter_atomic (dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata, void *params) { static const dc_usb_desc_t usb[] = { {0x0471, 0x0888}, // Atomic Aquatics Cobalt @@ -773,7 +783,8 @@ static int dc_filter_atomic (dc_transport_t transport, const void *userdata, voi return 1; } -static int dc_filter_deepsix (dc_transport_t transport, const void *userdata, void *params) +static int +dc_filter_deepsix (dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata, void *params) { static const char * const bluetooth[] = { "EXCURSION", @@ -789,7 +800,8 @@ static int dc_filter_deepsix (dc_transport_t transport, const void *userdata, vo return 1; } -static int dc_filter_deepblu (dc_transport_t transport, const void *userdata, void *params) +static int +dc_filter_deepblu (dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata, void *params) { static const char * const bluetooth[] = { "COSMIQ", @@ -802,7 +814,8 @@ static int dc_filter_deepblu (dc_transport_t transport, const void *userdata, vo return 1; } -static int dc_filter_oceans (dc_transport_t transport, const void *userdata, void *params) +static int +dc_filter_oceans (dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata, void *params) { static const char * const bluetooth[] = { "S1", @@ -815,7 +828,8 @@ static int dc_filter_oceans (dc_transport_t transport, const void *userdata, voi return 1; } -static int dc_filter_divesoft (dc_transport_t transport, const void *userdata, void *params) +static int +dc_filter_divesoft (dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata, void *params) { static const char * const bluetooth[] = { "Freedom", @@ -926,5 +940,5 @@ dc_descriptor_filter (dc_descriptor_t *descriptor, dc_transport_t transport, con if (descriptor == NULL || descriptor->filter == NULL || userdata == NULL) return 1; - return descriptor->filter (transport, userdata, params); + return descriptor->filter (descriptor, transport, userdata, params); } From a985b1185970c44e26d787ffd5a3e1390591a641 Mon Sep 17 00:00:00 2001 From: Jef Driesen Date: Wed, 5 Jul 2023 20:32:41 +0200 Subject: [PATCH 2/5] Replace the filter parameters with an alternative The USB I/O backend needs some additional information (e.g. interface number and in/out endpoints) to setup the USB connection. This info is currently maintained inside the descriptor filter function and gets passed to the USB backend by means of the filter parameters. This approach is not only unnecessary complex, but also makes it very difficult to expose the filter function in the public api because the data structures for those parameters are private. Therefore, this data exchange is replaced with a direct mapping between the USB VID/PID and the configuration info in the USB backend itself. --- src/bluetooth.c | 2 +- src/descriptor-private.h | 8 +--- src/descriptor.c | 85 ++++++++++++++++------------------------ src/irda.c | 2 +- src/serial_posix.c | 2 +- src/serial_win32.c | 2 +- src/usb.c | 45 ++++++++++++++++++--- src/usbhid.c | 4 +- 8 files changed, 81 insertions(+), 69 deletions(-) diff --git a/src/bluetooth.c b/src/bluetooth.c index aa5f05a..cc143b7 100644 --- a/src/bluetooth.c +++ b/src/bluetooth.c @@ -455,7 +455,7 @@ dc_bluetooth_iterator_next (dc_iterator_t *abstract, void *out) INFO (abstract->context, "Discover: address=" DC_ADDRESS_FORMAT ", name=%s", address, name ? name : ""); - if (!dc_descriptor_filter (iterator->descriptor, DC_TRANSPORT_BLUETOOTH, name, NULL)) { + if (!dc_descriptor_filter (iterator->descriptor, DC_TRANSPORT_BLUETOOTH, name)) { continue; } diff --git a/src/descriptor-private.h b/src/descriptor-private.h index d829422..06c2980 100644 --- a/src/descriptor-private.h +++ b/src/descriptor-private.h @@ -33,14 +33,8 @@ typedef struct dc_usb_desc_t { unsigned short pid; } dc_usb_desc_t; -typedef struct dc_usb_params_t { - unsigned int interface; - unsigned char endpoint_in; - unsigned char endpoint_out; -} dc_usb_params_t; - int -dc_descriptor_filter (dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata, void *params); +dc_descriptor_filter (dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata); #ifdef __cplusplus } diff --git a/src/descriptor.c b/src/descriptor.c index d287393..d90b54e 100644 --- a/src/descriptor.c +++ b/src/descriptor.c @@ -36,36 +36,26 @@ values, \ C_ARRAY_SIZE(values) - isnullterminated, \ C_ARRAY_ITEMSIZE(values), \ - match, \ - NULL, NULL, 0) - -#define DC_FILTER_INTERNAL_WITH_PARAMS(key, values, isnullterminated, match, params_dst, params_src) \ - dc_filter_internal( \ - key, \ - values, \ - C_ARRAY_SIZE(values) - isnullterminated, \ - C_ARRAY_ITEMSIZE(values), \ - match, \ - params_dst, params_src, sizeof *(params_src)) + match) typedef int (*dc_match_t)(const void *, const void *); -typedef int (*dc_filter_t) (dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata, void *params); +typedef int (*dc_filter_t) (dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata); -static int dc_filter_uwatec (dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata, void *params); -static int dc_filter_suunto (dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata, void *params); -static int dc_filter_shearwater (dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata, void *params); -static int dc_filter_hw (dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata, void *params); -static int dc_filter_tecdiving (dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata, void *params); -static int dc_filter_mares (dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata, void *params); -static int dc_filter_divesystem (dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata, void *params); -static int dc_filter_oceanic (dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata, void *params); -static int dc_filter_mclean (dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata, void *params); -static int dc_filter_atomic (dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata, void *params); -static int dc_filter_deepsix (dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata, void *params); -static int dc_filter_deepblu (dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata, void *params); -static int dc_filter_oceans (dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata, void *params); -static int dc_filter_divesoft (dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata, void *params); +static int dc_filter_uwatec (dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata); +static int dc_filter_suunto (dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata); +static int dc_filter_shearwater (dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata); +static int dc_filter_hw (dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata); +static int dc_filter_tecdiving (dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata); +static int dc_filter_mares (dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata); +static int dc_filter_divesystem (dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata); +static int dc_filter_oceanic (dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata); +static int dc_filter_mclean (dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata); +static int dc_filter_atomic (dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata); +static int dc_filter_deepsix (dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata); +static int dc_filter_deepblu (dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata); +static int dc_filter_oceans (dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata); +static int dc_filter_divesoft (dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata); static dc_status_t dc_descriptor_iterator_next (dc_iterator_t *iterator, void *item); @@ -546,16 +536,13 @@ dc_match_oceanic (const void *key, const void *value) } static int -dc_filter_internal (const void *key, const void *values, size_t count, size_t size, dc_match_t match, void *params_dst, const void *params_src, size_t params_size) +dc_filter_internal (const void *key, const void *values, size_t count, size_t size, dc_match_t match) { if (key == NULL) return 1; for (size_t i = 0; i < count; ++i) { if (match (key, (const unsigned char *) values + i * size)) { - if (params_src && params_dst) { - memcpy (params_dst, params_src, params_size); - } return 1; } } @@ -571,7 +558,7 @@ static const char * const rfcomm[] = { }; static int -dc_filter_uwatec (dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata, void *params) +dc_filter_uwatec (dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata) { static const char * const irda[] = { "Aladin Smart Com", @@ -609,7 +596,7 @@ dc_filter_uwatec (dc_descriptor_t *descriptor, dc_transport_t transport, const v } static int -dc_filter_suunto (dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata, void *params) +dc_filter_suunto (dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata) { static const dc_usb_desc_t usbhid[] = { {0x1493, 0x0030}, // Eon Steel @@ -634,7 +621,7 @@ dc_filter_suunto (dc_descriptor_t *descriptor, dc_transport_t transport, const v } static int -dc_filter_hw (dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata, void *params) +dc_filter_hw (dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata) { static const char * const bluetooth[] = { "OSTC", @@ -651,7 +638,7 @@ dc_filter_hw (dc_descriptor_t *descriptor, dc_transport_t transport, const void } static int -dc_filter_shearwater (dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata, void *params) +dc_filter_shearwater (dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata) { static const char * const bluetooth[] = { "Predator", @@ -675,7 +662,7 @@ dc_filter_shearwater (dc_descriptor_t *descriptor, dc_transport_t transport, con } static int -dc_filter_tecdiving (dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata, void *params) +dc_filter_tecdiving (dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata) { static const char * const bluetooth[] = { "DiveComputer", @@ -691,7 +678,7 @@ dc_filter_tecdiving (dc_descriptor_t *descriptor, dc_transport_t transport, cons } static int -dc_filter_mares (dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata, void *params) +dc_filter_mares (dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata) { static const char * const bluetooth[] = { "Mares bluelink pro", @@ -706,7 +693,7 @@ dc_filter_mares (dc_descriptor_t *descriptor, dc_transport_t transport, const vo } static int -dc_filter_divesystem (dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata, void *params) +dc_filter_divesystem (dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata) { static const char * const bluetooth[] = { "DS", @@ -722,7 +709,7 @@ dc_filter_divesystem (dc_descriptor_t *descriptor, dc_transport_t transport, con } static int -dc_filter_oceanic (dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata, void *params) +dc_filter_oceanic (dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata) { static const unsigned int model[] = { 0x4552, // Oceanic Pro Plus X @@ -750,7 +737,7 @@ dc_filter_oceanic (dc_descriptor_t *descriptor, dc_transport_t transport, const } static int -dc_filter_mclean(dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata, void *params) +dc_filter_mclean(dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata) { static const char * const bluetooth[] = { "McLean Extreme", @@ -766,25 +753,21 @@ dc_filter_mclean(dc_descriptor_t *descriptor, dc_transport_t transport, const vo } static int -dc_filter_atomic (dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata, void *params) +dc_filter_atomic (dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata) { static const dc_usb_desc_t usb[] = { {0x0471, 0x0888}, // Atomic Aquatics Cobalt }; - static const dc_usb_params_t usb_params = { - 0, 0x82, 0x02 - }; - if (transport == DC_TRANSPORT_USB) { - return DC_FILTER_INTERNAL_WITH_PARAMS (userdata, usb, 0, dc_match_usb, params, &usb_params); + return DC_FILTER_INTERNAL (userdata, usb, 0, dc_match_usb); } return 1; } static int -dc_filter_deepsix (dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata, void *params) +dc_filter_deepsix (dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata) { static const char * const bluetooth[] = { "EXCURSION", @@ -801,7 +784,7 @@ dc_filter_deepsix (dc_descriptor_t *descriptor, dc_transport_t transport, const } static int -dc_filter_deepblu (dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata, void *params) +dc_filter_deepblu (dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata) { static const char * const bluetooth[] = { "COSMIQ", @@ -815,7 +798,7 @@ dc_filter_deepblu (dc_descriptor_t *descriptor, dc_transport_t transport, const } static int -dc_filter_oceans (dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata, void *params) +dc_filter_oceans (dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata) { static const char * const bluetooth[] = { "S1", @@ -829,7 +812,7 @@ dc_filter_oceans (dc_descriptor_t *descriptor, dc_transport_t transport, const v } static int -dc_filter_divesoft (dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata, void *params) +dc_filter_divesoft (dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata) { static const char * const bluetooth[] = { "Freedom", @@ -935,10 +918,10 @@ dc_descriptor_get_transports (dc_descriptor_t *descriptor) } int -dc_descriptor_filter (dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata, void *params) +dc_descriptor_filter (dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata) { if (descriptor == NULL || descriptor->filter == NULL || userdata == NULL) return 1; - return descriptor->filter (descriptor, transport, userdata, params); + return descriptor->filter (descriptor, transport, userdata); } diff --git a/src/irda.c b/src/irda.c index a5bb8e4..6bd927c 100644 --- a/src/irda.c +++ b/src/irda.c @@ -226,7 +226,7 @@ dc_irda_iterator_new (dc_iterator_t **out, dc_context_t *context, dc_descriptor_ INFO (context, "Discover: address=%08x, name=%s, charset=%02x, hints=%04x", address, name, charset, hints); - if (!dc_descriptor_filter (descriptor, DC_TRANSPORT_IRDA, name, NULL)) { + if (!dc_descriptor_filter (descriptor, DC_TRANSPORT_IRDA, name)) { continue; } diff --git a/src/serial_posix.c b/src/serial_posix.c index a189e15..51b1037 100644 --- a/src/serial_posix.c +++ b/src/serial_posix.c @@ -230,7 +230,7 @@ dc_serial_iterator_next (dc_iterator_t *abstract, void *out) return DC_STATUS_NOMEMORY; } - if (!dc_descriptor_filter (iterator->descriptor, DC_TRANSPORT_SERIAL, filename, NULL)) { + if (!dc_descriptor_filter (iterator->descriptor, DC_TRANSPORT_SERIAL, filename)) { continue; } diff --git a/src/serial_win32.c b/src/serial_win32.c index aeeeb83..30fe0e9 100644 --- a/src/serial_win32.c +++ b/src/serial_win32.c @@ -228,7 +228,7 @@ dc_serial_iterator_next (dc_iterator_t *abstract, void *out) // Null terminate the string. data[data_len] = 0; - if (!dc_descriptor_filter (iterator->descriptor, DC_TRANSPORT_SERIAL, data, NULL)) { + if (!dc_descriptor_filter (iterator->descriptor, DC_TRANSPORT_SERIAL, data)) { continue; } diff --git a/src/usb.c b/src/usb.c index 758c604..80083f6 100644 --- a/src/usb.c +++ b/src/usb.c @@ -42,9 +42,21 @@ #include "descriptor-private.h" #include "iterator-private.h" #include "platform.h" +#include "array.h" #define ISINSTANCE(device) dc_iostream_isinstance((device), &dc_usb_vtable) +typedef struct dc_usb_params_t { + unsigned int interface; + unsigned char endpoint_in; + unsigned char endpoint_out; +} dc_usb_params_t; + +typedef struct dc_usb_config_t { + dc_usb_desc_t desc; + dc_usb_params_t params; +} dc_usb_config_t; + typedef struct dc_usb_session_t { size_t refcount; #ifdef HAVE_LIBUSB @@ -120,6 +132,26 @@ static const dc_iostream_vtable_t dc_usb_vtable = { dc_usb_close, /* close */ }; +static const dc_usb_config_t g_usb_config[] = { + // Atomic Aquatics Cobalt + {{0x0471, 0x0888}, {0, 0x82, 0x02}}, +}; + +static const dc_usb_params_t * +dc_usb_params_find (const dc_usb_desc_t *desc) +{ + if (desc == NULL) + return NULL; + + for (size_t i = 0; i < C_ARRAY_SIZE(g_usb_config); ++i) { + if (g_usb_config[i].desc.vid == desc->vid && + g_usb_config[i].desc.pid == desc->pid) + return &g_usb_config[i].params; + } + + return NULL; +} + static dc_status_t syserror(int errcode) { @@ -305,11 +337,13 @@ dc_usb_iterator_next (dc_iterator_t *abstract, void *out) } dc_usb_desc_t usb = {dev.idVendor, dev.idProduct}; - dc_usb_params_t params = {0, 0, 0}; - if (!dc_descriptor_filter (iterator->descriptor, DC_TRANSPORT_USB, &usb, ¶ms)) { + if (!dc_descriptor_filter (iterator->descriptor, DC_TRANSPORT_USB, &usb)) { continue; } + // Check for known USB parameters. + const dc_usb_params_t *params = dc_usb_params_find (&usb); + // Get the active configuration descriptor. struct libusb_config_descriptor *config = NULL; rc = libusb_get_active_config_descriptor (current, &config); @@ -325,7 +359,8 @@ dc_usb_iterator_next (dc_iterator_t *abstract, void *out) const struct libusb_interface *iface = &config->interface[i]; for (int j = 0; j < iface->num_altsetting; j++) { const struct libusb_interface_descriptor *desc = &iface->altsetting[j]; - if (interface == NULL && desc->bInterfaceNumber == params.interface) { + if (interface == NULL && + (params == NULL || params->interface == desc->bInterfaceNumber)) { interface = desc; } } @@ -349,12 +384,12 @@ dc_usb_iterator_next (dc_iterator_t *abstract, void *out) } if (ep_in == NULL && direction == LIBUSB_ENDPOINT_IN && - (params.endpoint_in == 0 || params.endpoint_in == desc->bEndpointAddress)) { + (params == NULL || params->endpoint_in == desc->bEndpointAddress)) { ep_in = desc; } if (ep_out == NULL && direction == LIBUSB_ENDPOINT_OUT && - (params.endpoint_out == 0 || params.endpoint_out == desc->bEndpointAddress)) { + (params == NULL || params->endpoint_out == desc->bEndpointAddress)) { ep_out = desc; } } diff --git a/src/usbhid.c b/src/usbhid.c index acd20ef..3ed94d7 100644 --- a/src/usbhid.c +++ b/src/usbhid.c @@ -439,7 +439,7 @@ dc_usbhid_iterator_next (dc_iterator_t *abstract, void *out) } dc_usb_desc_t usb = {dev.idVendor, dev.idProduct}; - if (!dc_descriptor_filter (iterator->descriptor, DC_TRANSPORT_USBHID, &usb, NULL)) { + if (!dc_descriptor_filter (iterator->descriptor, DC_TRANSPORT_USBHID, &usb)) { continue; } @@ -523,7 +523,7 @@ dc_usbhid_iterator_next (dc_iterator_t *abstract, void *out) iterator->current = current->next; dc_usb_desc_t usb = {current->vendor_id, current->product_id}; - if (!dc_descriptor_filter (iterator->descriptor, DC_TRANSPORT_USBHID, &usb, NULL)) { + if (!dc_descriptor_filter (iterator->descriptor, DC_TRANSPORT_USBHID, &usb)) { continue; } From 4a9be44afde08ff61f2c19869e8c9bb94169ff34 Mon Sep 17 00:00:00 2001 From: Jef Driesen Date: Sun, 20 Aug 2023 21:50:59 +0200 Subject: [PATCH 3/5] Use separate data structures for USB and USB HID Using separate data structures for the filtering allows to keep the USB and USB HID backends completely independent from each other. --- include/libdivecomputer/usb.h | 8 ++++++++ include/libdivecomputer/usbhid.h | 8 ++++++++ src/descriptor-private.h | 5 ----- src/descriptor.c | 20 ++++++++++++++++---- src/usbhid.c | 4 ++-- 5 files changed, 34 insertions(+), 11 deletions(-) diff --git a/include/libdivecomputer/usb.h b/include/libdivecomputer/usb.h index 6d13813..82e5881 100644 --- a/include/libdivecomputer/usb.h +++ b/include/libdivecomputer/usb.h @@ -86,6 +86,14 @@ typedef enum dc_usb_recipient_t { DC_USB_RECIPIENT_OTHER = 0x03, } dc_usb_recipient_t; +/** + * USB device descriptor. + */ +typedef struct dc_usb_desc_t { + unsigned short vid; + unsigned short pid; +} dc_usb_desc_t; + /** * Opaque object representing a USB device. */ diff --git a/include/libdivecomputer/usbhid.h b/include/libdivecomputer/usbhid.h index f1c542a..245adf0 100644 --- a/include/libdivecomputer/usbhid.h +++ b/include/libdivecomputer/usbhid.h @@ -32,6 +32,14 @@ extern "C" { #endif /* __cplusplus */ +/** + * USB HID device descriptor. + */ +typedef struct dc_usbhid_desc_t { + unsigned short vid; + unsigned short pid; +} dc_usbhid_desc_t; + /** * Opaque object representing a USB HID device. */ diff --git a/src/descriptor-private.h b/src/descriptor-private.h index 06c2980..77bdbb6 100644 --- a/src/descriptor-private.h +++ b/src/descriptor-private.h @@ -28,11 +28,6 @@ extern "C" { #endif /* __cplusplus */ -typedef struct dc_usb_desc_t { - unsigned short vid; - unsigned short pid; -} dc_usb_desc_t; - int dc_descriptor_filter (dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata); diff --git a/src/descriptor.c b/src/descriptor.c index d90b54e..79c2d7c 100644 --- a/src/descriptor.c +++ b/src/descriptor.c @@ -23,6 +23,9 @@ #include #include +#include +#include + #include "descriptor-private.h" #include "iterator-private.h" #include "platform.h" @@ -496,6 +499,15 @@ dc_match_usb (const void *key, const void *value) return k->vid == v->vid && k->pid == v->pid; } +static int +dc_match_usbhid (const void *key, const void *value) +{ + const dc_usbhid_desc_t *k = (const dc_usbhid_desc_t *) key; + const dc_usbhid_desc_t *v = (const dc_usbhid_desc_t *) value; + + return k->vid == v->vid && k->pid == v->pid; +} + static int dc_match_number_with_prefix (const void *key, const void *value) { @@ -569,7 +581,7 @@ dc_filter_uwatec (dc_descriptor_t *descriptor, dc_transport_t transport, const v "UWATEC Galileo", "UWATEC Galileo Sol", }; - static const dc_usb_desc_t usbhid[] = { + static const dc_usbhid_desc_t usbhid[] = { {0x2e6c, 0x3201}, // G2, G2 TEK {0x2e6c, 0x3211}, // G2 Console {0x2e6c, 0x4201}, // G2 HUD @@ -587,7 +599,7 @@ dc_filter_uwatec (dc_descriptor_t *descriptor, dc_transport_t transport, const v if (transport == DC_TRANSPORT_IRDA) { return DC_FILTER_INTERNAL (userdata, irda, 0, dc_match_name); } else if (transport == DC_TRANSPORT_USBHID) { - return DC_FILTER_INTERNAL (userdata, usbhid, 0, dc_match_usb); + return DC_FILTER_INTERNAL (userdata, usbhid, 0, dc_match_usbhid); } else if (transport == DC_TRANSPORT_BLE) { return DC_FILTER_INTERNAL (userdata, bluetooth, 0, dc_match_name); } @@ -598,7 +610,7 @@ dc_filter_uwatec (dc_descriptor_t *descriptor, dc_transport_t transport, const v static int dc_filter_suunto (dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata) { - static const dc_usb_desc_t usbhid[] = { + static const dc_usbhid_desc_t usbhid[] = { {0x1493, 0x0030}, // Eon Steel {0x1493, 0x0033}, // Eon Core {0x1493, 0x0035}, // D5 @@ -612,7 +624,7 @@ dc_filter_suunto (dc_descriptor_t *descriptor, dc_transport_t transport, const v }; if (transport == DC_TRANSPORT_USBHID) { - return DC_FILTER_INTERNAL (userdata, usbhid, 0, dc_match_usb); + return DC_FILTER_INTERNAL (userdata, usbhid, 0, dc_match_usbhid); } else if (transport == DC_TRANSPORT_BLE) { return DC_FILTER_INTERNAL (userdata, bluetooth, 0, dc_match_prefix); } diff --git a/src/usbhid.c b/src/usbhid.c index 3ed94d7..04e35d9 100644 --- a/src/usbhid.c +++ b/src/usbhid.c @@ -438,7 +438,7 @@ dc_usbhid_iterator_next (dc_iterator_t *abstract, void *out) return syserror (rc); } - dc_usb_desc_t usb = {dev.idVendor, dev.idProduct}; + dc_usbhid_desc_t usb = {dev.idVendor, dev.idProduct}; if (!dc_descriptor_filter (iterator->descriptor, DC_TRANSPORT_USBHID, &usb)) { continue; } @@ -522,7 +522,7 @@ dc_usbhid_iterator_next (dc_iterator_t *abstract, void *out) struct hid_device_info *current = iterator->current; iterator->current = current->next; - dc_usb_desc_t usb = {current->vendor_id, current->product_id}; + dc_usbhid_desc_t usb = {current->vendor_id, current->product_id}; if (!dc_descriptor_filter (iterator->descriptor, DC_TRANSPORT_USBHID, &usb)) { continue; } From ed871137b1f9d9a9d54c28951288eb44475e7e99 Mon Sep 17 00:00:00 2001 From: Jef Driesen Date: Sun, 20 Aug 2023 22:13:45 +0200 Subject: [PATCH 4/5] Export the filter function in the public api The functionality provided by the filter function is not only useful for the built-in transports, but also for the applications. For example in combination with a custom transport. --- contrib/msvc/libdivecomputer.vcxproj | 1 - include/libdivecomputer/descriptor.h | 3 +++ src/Makefile.am | 2 +- src/bluetooth.c | 1 - src/descriptor-private.h | 37 ---------------------------- src/descriptor.c | 2 +- src/irda.c | 1 - src/libdivecomputer.symbols | 1 + src/serial_posix.c | 1 - src/serial_win32.c | 1 - src/usb.c | 1 - src/usbhid.c | 1 - 12 files changed, 6 insertions(+), 46 deletions(-) delete mode 100644 src/descriptor-private.h diff --git a/contrib/msvc/libdivecomputer.vcxproj b/contrib/msvc/libdivecomputer.vcxproj index 7f1335c..704ef8b 100644 --- a/contrib/msvc/libdivecomputer.vcxproj +++ b/contrib/msvc/libdivecomputer.vcxproj @@ -331,7 +331,6 @@ - diff --git a/include/libdivecomputer/descriptor.h b/include/libdivecomputer/descriptor.h index a2b4495..ec6a6c6 100644 --- a/include/libdivecomputer/descriptor.h +++ b/include/libdivecomputer/descriptor.h @@ -52,6 +52,9 @@ dc_descriptor_get_model (dc_descriptor_t *descriptor); unsigned int dc_descriptor_get_transports (dc_descriptor_t *descriptor); +int +dc_descriptor_filter (dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata); + #ifdef __cplusplus } #endif /* __cplusplus */ diff --git a/src/Makefile.am b/src/Makefile.am index de59dd6..be3f2e3 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -16,7 +16,7 @@ endif libdivecomputer_la_SOURCES = \ version.c \ - descriptor-private.h descriptor.c \ + descriptor.c \ iostream-private.h iostream.c \ iterator-private.h iterator.c \ common-private.h common.c \ diff --git a/src/bluetooth.c b/src/bluetooth.c index cc143b7..309953c 100644 --- a/src/bluetooth.c +++ b/src/bluetooth.c @@ -51,7 +51,6 @@ #include "context-private.h" #include "iostream-private.h" #include "iterator-private.h" -#include "descriptor-private.h" #include "platform.h" #ifdef _WIN32 diff --git a/src/descriptor-private.h b/src/descriptor-private.h deleted file mode 100644 index 77bdbb6..0000000 --- a/src/descriptor-private.h +++ /dev/null @@ -1,37 +0,0 @@ -/* - * libdivecomputer - * - * Copyright (C) 2017 Jef Driesen - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, - * MA 02110-1301 USA - */ - -#ifndef DC_DESCRIPTOR_PRIVATE_H -#define DC_DESCRIPTOR_PRIVATE_H - -#include - -#ifdef __cplusplus -extern "C" { -#endif /* __cplusplus */ - -int -dc_descriptor_filter (dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ -#endif /* DC_DESCRIPTOR_PRIVATE_H */ diff --git a/src/descriptor.c b/src/descriptor.c index 79c2d7c..77d55f6 100644 --- a/src/descriptor.c +++ b/src/descriptor.c @@ -23,10 +23,10 @@ #include #include +#include #include #include -#include "descriptor-private.h" #include "iterator-private.h" #include "platform.h" diff --git a/src/irda.c b/src/irda.c index 6bd927c..dd5397b 100644 --- a/src/irda.c +++ b/src/irda.c @@ -47,7 +47,6 @@ #include "context-private.h" #include "iostream-private.h" #include "iterator-private.h" -#include "descriptor-private.h" #include "array.h" #include "platform.h" diff --git a/src/libdivecomputer.symbols b/src/libdivecomputer.symbols index 477f1ec..c829852 100644 --- a/src/libdivecomputer.symbols +++ b/src/libdivecomputer.symbols @@ -34,6 +34,7 @@ dc_descriptor_get_product dc_descriptor_get_type dc_descriptor_get_model dc_descriptor_get_transports +dc_descriptor_filter dc_iostream_get_transport dc_iostream_set_timeout diff --git a/src/serial_posix.c b/src/serial_posix.c index 51b1037..792a1c9 100644 --- a/src/serial_posix.c +++ b/src/serial_posix.c @@ -57,7 +57,6 @@ #include "context-private.h" #include "iostream-private.h" #include "iterator-private.h" -#include "descriptor-private.h" #include "platform.h" #include "timer.h" diff --git a/src/serial_win32.c b/src/serial_win32.c index 30fe0e9..e506cbd 100644 --- a/src/serial_win32.c +++ b/src/serial_win32.c @@ -31,7 +31,6 @@ #include "context-private.h" #include "iostream-private.h" #include "iterator-private.h" -#include "descriptor-private.h" #include "platform.h" static dc_status_t dc_serial_iterator_next (dc_iterator_t *iterator, void *item); diff --git a/src/usb.c b/src/usb.c index 80083f6..d7074cb 100644 --- a/src/usb.c +++ b/src/usb.c @@ -39,7 +39,6 @@ #include "common-private.h" #include "context-private.h" #include "iostream-private.h" -#include "descriptor-private.h" #include "iterator-private.h" #include "platform.h" #include "array.h" diff --git a/src/usbhid.c b/src/usbhid.c index 04e35d9..b7818e0 100644 --- a/src/usbhid.c +++ b/src/usbhid.c @@ -57,7 +57,6 @@ #include "common-private.h" #include "context-private.h" #include "iostream-private.h" -#include "descriptor-private.h" #include "iterator-private.h" #include "platform.h" From fe9b47f4bd8e2f23b7f3267a6bcac27fa6f0100e Mon Sep 17 00:00:00 2001 From: Jef Driesen Date: Tue, 22 Aug 2023 23:05:54 +0200 Subject: [PATCH 5/5] Document the device descriptor functions --- include/libdivecomputer/descriptor.h | 64 ++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) diff --git a/include/libdivecomputer/descriptor.h b/include/libdivecomputer/descriptor.h index ec6a6c6..bdd8c73 100644 --- a/include/libdivecomputer/descriptor.h +++ b/include/libdivecomputer/descriptor.h @@ -29,29 +29,93 @@ extern "C" { #endif /* __cplusplus */ +/** + * Opaque object representing a supported dive computer. + */ typedef struct dc_descriptor_t dc_descriptor_t; +/** + * Create an iterator to enumerate the supported dive computers. + * + * @param[out] iterator A location to store the iterator. + * @returns #DC_STATUS_SUCCESS on success, or another #dc_status_t code + * on failure. + */ dc_status_t dc_descriptor_iterator (dc_iterator_t **iterator); +/** + * Free the device descriptor. + * + * @param[in] descriptor A valid device descriptor. + */ void dc_descriptor_free (dc_descriptor_t *descriptor); +/** + * Get the vendor name of the dive computer. + * + * @param[in] descriptor A valid device descriptor. + * @returns The vendor name of the dive computer on success, or NULL on failure. + */ const char * dc_descriptor_get_vendor (dc_descriptor_t *descriptor); +/** + * Get the product name of the dive computer. + * + * @param[in] descriptor A valid device descriptor. + * @returns The product name of the dive computer on success, or NULL on + * failure. + */ const char * dc_descriptor_get_product (dc_descriptor_t *descriptor); +/** + * Get the family type of the dive computer. + * + * @param[in] descriptor A valid device descriptor. + * @returns The family type of the dive computer on success, or DC_FAMILY_NULL + * on failure. + */ dc_family_t dc_descriptor_get_type (dc_descriptor_t *descriptor); +/** + * Get the model number of the dive computer. + * + * @param[in] descriptor A valid device descriptor. + * @returns The model number of the dive computer on success, or zero on + * failure. + */ unsigned int dc_descriptor_get_model (dc_descriptor_t *descriptor); +/** + * Get all transports supported by the dive computer. + * + * @param[in] descriptor A valid device descriptor. + * @returns A bitmask with all the transports supported by the dive computer on + * success, or DC_TRANSPORT_NONE on failure. + */ unsigned int dc_descriptor_get_transports (dc_descriptor_t *descriptor); +/** + * Check if a low-level I/O device matches a supported dive computer. + * + * @param[in] descriptor A valid device descriptor. + * @param[in] transport The transport type of the I/O device. + * @param[in] userdata A pointer to a transport specific data structure: + * - DC_TRANSPORT_SERIAL: Name of the device node (string) + * - DC_TRANSPORT_USB: USB VID/PID (#dc_usb_desc_t) + * - DC_TRANSPORT_USBHID: USB VID/PID (#dc_usbhid_desc_t) + * - DC_TRANSPORT_IRDA: IrDA device name (string) + * - DC_TRANSPORT_BLUETOOTH: Bluetooth device name (string) + * - DC_TRANSPORT_BLE: Bluetooth device name (string) + * @returns Non-zero if the device matches a supported dive computer, or zero if + * there is no match. + */ int dc_descriptor_filter (dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata);