From a985b1185970c44e26d787ffd5a3e1390591a641 Mon Sep 17 00:00:00 2001 From: Jef Driesen Date: Wed, 5 Jul 2023 20:32:41 +0200 Subject: [PATCH] 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; }