summaryrefslogtreecommitdiffstats
path: root/usb_device.c
diff options
context:
space:
mode:
Diffstat (limited to 'usb_device.c')
-rw-r--r--usb_device.c66
1 files changed, 38 insertions, 28 deletions
diff --git a/usb_device.c b/usb_device.c
index 344c4cb90..0c8e3e215 100644
--- a/usb_device.c
+++ b/usb_device.c
@@ -28,10 +28,11 @@
* Possibly extract a programmer parameter and use it to initialize the given
* match value structure.
*/
-static void usb_match_value_init(struct usb_match_value *match,
+static void usb_match_value_init(const struct programmer_cfg *cfg,
+ struct usb_match_value *match,
char const *parameter)
{
- char *string = extract_programmer_param(parameter);
+ char *string = extract_programmer_param_str(cfg, parameter);
match->name = parameter;
@@ -45,21 +46,21 @@ static void usb_match_value_init(struct usb_match_value *match,
free(string);
}
-#define USB_MATCH_VALUE_INIT(NAME) \
- usb_match_value_init(&match->NAME, #NAME)
+#define USB_MATCH_VALUE_INIT(PPARAM, NAME) \
+ usb_match_value_init(PPARAM, &match->NAME, #NAME)
-void usb_match_init(struct usb_match *match)
+void usb_match_init(const struct programmer_cfg *cfg, struct usb_match *match)
{
- USB_MATCH_VALUE_INIT(vid);
- USB_MATCH_VALUE_INIT(pid);
- USB_MATCH_VALUE_INIT(bus);
- USB_MATCH_VALUE_INIT(address);
- USB_MATCH_VALUE_INIT(config);
- USB_MATCH_VALUE_INIT(interface);
- USB_MATCH_VALUE_INIT(altsetting);
- USB_MATCH_VALUE_INIT(class);
- USB_MATCH_VALUE_INIT(subclass);
- USB_MATCH_VALUE_INIT(protocol);
+ USB_MATCH_VALUE_INIT(cfg, vid);
+ USB_MATCH_VALUE_INIT(cfg, pid);
+ USB_MATCH_VALUE_INIT(cfg, bus);
+ USB_MATCH_VALUE_INIT(cfg, address);
+ USB_MATCH_VALUE_INIT(cfg, config);
+ USB_MATCH_VALUE_INIT(cfg, interface);
+ USB_MATCH_VALUE_INIT(cfg, altsetting);
+ USB_MATCH_VALUE_INIT(cfg, class);
+ USB_MATCH_VALUE_INIT(cfg, subclass);
+ USB_MATCH_VALUE_INIT(cfg, protocol);
}
void usb_match_value_default(struct usb_match_value *value,
@@ -99,7 +100,7 @@ static int check_match(struct usb_match_value const *match_value, int value)
static void add_device(struct usb_device *device,
struct usb_device **devices)
{
- struct usb_device *copy = malloc(sizeof(struct usb_device));
+ struct usb_device *copy = malloc(sizeof(*copy));
assert(copy != NULL);
@@ -224,12 +225,12 @@ int usb_device_find(struct usb_match const *match, struct usb_device **devices)
ret = LIBUSB(libusb_get_device_descriptor(list[i],
&descriptor));
- if (ret != 0) {
- msg_perr("USB: Failed to get device descriptor");
- free(*devices);
- *devices = NULL;
- return ret;
- }
+ if (ret != 0) {
+ msg_perr("USB: Failed to get device descriptor");
+ free(*devices);
+ *devices = NULL;
+ return ret;
+ }
if (check_match(&match->vid, descriptor.idVendor) &&
check_match(&match->pid, descriptor.idProduct) &&
@@ -279,8 +280,8 @@ int usb_device_show(char const *prefix, struct usb_device *device)
ret = usb_device_open(device);
if (ret != 0) {
- msg_perr("USB: Failed to open device\n");
- return ret;
+ msg_perr("USB: Failed to open device\n");
+ return ret;
}
ret = LIBUSB(libusb_get_device_descriptor(device->device, &descriptor));
@@ -341,9 +342,11 @@ int usb_device_claim(struct usb_device *device)
}
}
- ret = LIBUSB(libusb_set_auto_detach_kernel_driver(device->handle, 1));
- if (ret != 0) {
- msg_perr("USB: Failed to enable auto kernel driver detach\n");
+ ret = libusb_detach_kernel_driver(device->handle,
+ device->interface_descriptor->bInterfaceNumber);
+ if (ret != 0 && ret != LIBUSB_ERROR_NOT_FOUND && ret != LIBUSB_ERROR_NOT_SUPPORTED) {
+ msg_perr("Cannot detach the existing usb driver. %s\n",
+ libusb_error_name(ret));
return ret;
}
@@ -354,6 +357,8 @@ int usb_device_claim(struct usb_device *device)
if (ret != 0) {
msg_perr("USB: Could not claim device interface %d\n",
device->interface_descriptor->bInterfaceNumber);
+ libusb_attach_kernel_driver(device->handle,
+ device->interface_descriptor->bInterfaceNumber);
return ret;
}
@@ -380,8 +385,13 @@ struct usb_device *usb_device_free(struct usb_device *device)
{
struct usb_device *next = device->next;
- if (device->handle != NULL)
+ if (device->handle != NULL) {
+ libusb_release_interface(device->handle,
+ device->interface_descriptor->bInterfaceNumber);
+ libusb_attach_kernel_driver(device->handle,
+ device->interface_descriptor->bInterfaceNumber);
libusb_close(device->handle);
+ }
/*
* This unref balances the ref added in the add_device function.