#include "uref.h"
#include "common.h"
+#define MAX_NMB_OF_CONFIGS 255
+
struct libhusb_context {
libusb_context *lusb_ctx;
};
struct libhusb_device_handle {
struct libusb_device_handle *lusb_dev_handle;
+ /* TODO: replace with bit fields */
+ unsigned char driver_detached[MAX_NMB_OF_CONFIGS];
};
/* TODO add error translation */
return ret;
}
-int libhusb_claim_interface(libhusb_device_handle *handle, int interface_number, int force)
+int libhusb_claim_interface(libhusb_device_handle *handle, int interface_number,
+ int force)
{
- int ret;
+ int ret = -1;
+ int driver_detached = 0;
assert(handle);
- if (force) {
- ret = libusb_set_auto_detach_kernel_driver(handle->lusb_dev_handle, 1);
- if (ret == LIBUSB_ERROR_NOT_SUPPORTED)
- return -1;
+ if (interface_number < 0 || interface_number > MAX_NMB_OF_CONFIGS)
+ goto out;
+
+ if (!force)
+ goto claim_interface;
+ /*
+ * If force param has been set let's check if kernel driver is active
+ * and detach it if necessary
+ */
+ ret = libusb_kernel_driver_active(handle->lusb_dev_handle,
+ interface_number);
+ if (ret < 0) {
+ goto out;
+ } else if (ret == 1) {
+ ret = libusb_detach_kernel_driver(handle->lusb_dev_handle,
+ interface_number);
+ if (ret < 0)
+ goto out;
+
+ driver_detached = 1;
}
+claim_interface:
ret = libusb_claim_interface(handle->lusb_dev_handle, interface_number);
+ if (ret < 0)
+ goto claim_failed;
+
+ handle->driver_detached[interface_number] = 1;
+
+ return 0;
+claim_failed:
+ if (driver_detached)
+ libusb_attach_kernel_driver(handle->lusb_dev_handle,
+ interface_number);
+out:
+ /* Add proper error handling */
return ret;
}
int libhusb_release_interface(libhusb_device_handle *handle, int interface_number)
{
- int ret;
+ int ret = -1;
assert(handle);
- ret = libusb_release_interface(handle->lusb_dev_handle, interface_number);
+ if (interface_number < 0 || interface_number > MAX_NMB_OF_CONFIGS)
+ goto out;
+
+ ret = libusb_release_interface(handle->lusb_dev_handle,
+ interface_number);
+ if (ret != 0)
+ goto out;
+
+ if (handle->driver_detached[interface_number]) {
+ /*
+ * yeah we should check error code but there is no good method
+ * of handling it so for now lets just silently ignore it
+ */
+ libusb_attach_kernel_driver(handle->lusb_dev_handle,
+ interface_number);
+ handle->driver_detached[interface_number] = 0;
+ }
+out:
return ret;
}