/* Make a copy of the buffer so the caller can safely reuse it just
* after libusb_submit_transfer() has returned. This technique
- * requires more allocations than a proper double-buffering approach
- * but it takes a lot less code. */
+ * requires more dynamic allocations compared to a proper
+ * double-buffering approach but it takes a lot less code. */
transfer_buffer = malloc(len);
if (transfer_buffer == NULL) {
error(dev->ctx, "cannot allocate transfer buffer (%s)\n",
*/
current_configuration = -1;
- libusb_get_configuration((*dev)->usb_device, ¤t_configuration);
+ ret = libusb_get_configuration((*dev)->usb_device,
+ ¤t_configuration);
+ if (ret < 0) {
+ debug(ctx, "libusb_get_configuration failed: %s\n",
+ libusb_error_name(ret));
+ goto out_libusb_close;
+ }
+
if (current_configuration != (*dev)->desc->configuration) {
+ /*
+ * In principle kernel drivers bound to each interface should
+ * be detached before setting the configuration, but in
+ * practice this is not necessary for most devices.
+ *
+ * For example something like the following function would be
+ * called:
+ * libusb_detach_all_kernel_drivers((*dev)->usb_device);
+ */
ret = libusb_set_configuration((*dev)->usb_device,
(*dev)->desc->configuration);
if (ret < 0) {
* http://libusb.sourceforge.net/api-1.0/caveats.html
*/
current_configuration = -1;
- libusb_get_configuration((*dev)->usb_device, ¤t_configuration);
+ ret = libusb_get_configuration((*dev)->usb_device,
+ ¤t_configuration);
+ if (ret < 0) {
+ debug(ctx, "libusb_get_configuration after claim failed: %s\n",
+ libusb_error_name(ret));
+ goto out_libusb_release_interface;
+ }
+
if (current_configuration != (*dev)->desc->configuration) {
- debug(ctx, "libusb configuration changed\n");
- debug(ctx, "Cannot claim interface %hhu\n",
- (*dev)->desc->interface_number);
- goto out_libusb_close;
+ debug(ctx, "libusb configuration changed (expected: %hhu, current: %hhu\n",
+ (*dev)->desc->configuration, current_configuration);
+ ret = -EINVAL;
+ goto out_libusb_release_interface;
}
out:
return ret;
+out_libusb_release_interface:
+ libusb_release_interface((*dev)->usb_device,
+ (*dev)->desc->interface_number);
out_libusb_close:
libusb_close((*dev)->usb_device);
(*dev)->usb_device = NULL;