/*
* fetch and cache all the config descriptors through I/O
*/
-static int cache_config_descriptors(struct libusb_device *dev, HANDLE hub_handle)
+static void cache_config_descriptors(struct libusb_device *dev, HANDLE hub_handle)
{
- DWORD size, ret_size;
struct libusb_context *ctx = DEVICE_CTX(dev);
struct winusb_device_priv *priv = _device_priv(dev);
- int r;
+ DWORD size, ret_size;
uint8_t i;
USB_CONFIGURATION_DESCRIPTOR_SHORT cd_buf_short; // dummy request
PUSB_CONFIGURATION_DESCRIPTOR cd_data;
if (dev->num_configurations == 0)
- return LIBUSB_ERROR_INVALID_PARAM;
+ return;
priv->config_descriptor = calloc(dev->num_configurations, sizeof(PUSB_CONFIGURATION_DESCRIPTOR));
- if (priv->config_descriptor == NULL)
- return LIBUSB_ERROR_NO_MEM;
+ if (priv->config_descriptor == NULL) {
+ usbi_err(ctx, "could not allocate configuration descriptor array for '%s'", priv->dev_id);
+ return;
+ }
- for (i = 0, r = LIBUSB_SUCCESS; ; i++) {
- // safe loop: release all dynamic resources
+ for (i = 0; i <= dev->num_configurations; i++) {
safe_free(cd_buf_actual);
- // safe loop: end of loop condition
- if ((i >= dev->num_configurations) || (r != LIBUSB_SUCCESS))
+ if (i == dev->num_configurations)
break;
size = sizeof(cd_buf_short);
// coverity[tainted_data_argument]
if (!DeviceIoControl(hub_handle, IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION, &cd_buf_short, size,
&cd_buf_short, size, &ret_size, NULL)) {
- usbi_info(ctx, "could not access configuration descriptor (dummy) for '%s': %s", priv->dev_id, windows_error_str(0));
- LOOP_BREAK(LIBUSB_ERROR_IO);
+ usbi_info(ctx, "could not access configuration descriptor %u (dummy) for '%s': %s", i, priv->dev_id, windows_error_str(0));
+ continue;
}
if ((ret_size != size) || (cd_buf_short.desc.wTotalLength < sizeof(USB_CONFIGURATION_DESCRIPTOR))) {
- usbi_info(ctx, "unexpected configuration descriptor size (dummy) for '%s'", priv->dev_id);
- LOOP_BREAK(LIBUSB_ERROR_IO);
+ usbi_info(ctx, "unexpected configuration descriptor %u size (dummy) for '%s'", i, priv->dev_id);
+ continue;
}
size = sizeof(USB_DESCRIPTOR_REQUEST) + cd_buf_short.desc.wTotalLength;
cd_buf_actual = malloc(size);
if (cd_buf_actual == NULL) {
- usbi_err(ctx, "could not allocate configuration descriptor buffer for '%s'", priv->dev_id);
- LOOP_BREAK(LIBUSB_ERROR_NO_MEM);
+ usbi_err(ctx, "could not allocate configuration descriptor %u buffer for '%s'", i, priv->dev_id);
+ continue;
}
// Actual call
if (!DeviceIoControl(hub_handle, IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION, cd_buf_actual, size,
cd_buf_actual, size, &ret_size, NULL)) {
- usbi_err(ctx, "could not access configuration descriptor (actual) for '%s': %s", priv->dev_id, windows_error_str(0));
- LOOP_BREAK(LIBUSB_ERROR_IO);
+ usbi_err(ctx, "could not access configuration descriptor %u (actual) for '%s': %s", i, priv->dev_id, windows_error_str(0));
+ continue;
}
cd_data = (PUSB_CONFIGURATION_DESCRIPTOR)((UCHAR *)cd_buf_actual + sizeof(USB_DESCRIPTOR_REQUEST));
if ((size != ret_size) || (cd_data->wTotalLength != cd_buf_short.desc.wTotalLength)) {
- usbi_err(ctx, "unexpected configuration descriptor size (actual) for '%s'", priv->dev_id);
- LOOP_BREAK(LIBUSB_ERROR_IO);
+ usbi_err(ctx, "unexpected configuration descriptor %u size (actual) for '%s'", i, priv->dev_id);
+ continue;
}
if (cd_data->bDescriptorType != LIBUSB_DT_CONFIG) {
- usbi_err(ctx, "not a configuration descriptor for '%s'", priv->dev_id);
- LOOP_BREAK(LIBUSB_ERROR_IO);
+ usbi_err(ctx, "descriptor %u not a configuration descriptor for '%s'", i, priv->dev_id);
+ continue;
}
- usbi_dbg("cached config descriptor %d (bConfigurationValue=%u, %u bytes)",
+ usbi_dbg("cached config descriptor %u (bConfigurationValue=%u, %u bytes)",
i, cd_data->bConfigurationValue, cd_data->wTotalLength);
// Cache the descriptor
priv->config_descriptor[i] = malloc(cd_data->wTotalLength);
- if (priv->config_descriptor[i] == NULL)
- LOOP_BREAK(LIBUSB_ERROR_NO_MEM);
- memcpy(priv->config_descriptor[i], cd_data, cd_data->wTotalLength);
- }
-
- // Any failure will result in dev->num_configurations being forced to 0.
- // We need to release any memory that may have been allocated for config
- // descriptors that were successfully retrieved, otherwise that memory
- // will be leaked
- if (r != LIBUSB_SUCCESS) {
- for (i = 0; i < dev->num_configurations; i++)
- free(priv->config_descriptor[i]);
+ if (priv->config_descriptor[i] != NULL) {
+ memcpy(priv->config_descriptor[i], cd_data, cd_data->wTotalLength);
+ } else {
+ usbi_err(ctx, "could not allocate configuration descriptor %u buffer for '%s'", i, priv->dev_id);
+ }
}
-
- return r;
}
/*
priv->active_config = conn_info.CurrentConfigurationValue;
usbi_dbg("found %u configurations (active conf: %u)", dev->num_configurations, priv->active_config);
- // If we can't read the config descriptors, just set the number of confs to zero
- if (cache_config_descriptors(dev, hub_handle) != LIBUSB_SUCCESS) {
- dev->num_configurations = 0;
- priv->dev_descriptor.bNumConfigurations = 0;
- }
+ // Cache as many config descriptors as we can
+ cache_config_descriptors(dev, hub_handle);
// In their great wisdom, Microsoft decided to BREAK the USB speed report between Windows 7 and Windows 8
if (windows_version >= WINDOWS_8) {
for (index = 0; index < dev->num_configurations; index++) {
config_header = priv->config_descriptor[index];
+ if (config_header == NULL)
+ continue;
if (config_header->bConfigurationValue == bConfigurationValue) {
*buffer = (unsigned char *)priv->config_descriptor[index];
return (int)config_header->wTotalLength;