diff options
-rw-r--r-- | src/jtag/aice/aice_usb.c | 4 | ||||
-rw-r--r-- | src/jtag/drivers/jlink.c | 30 | ||||
-rw-r--r-- | src/jtag/drivers/libusb0_common.c | 21 | ||||
-rw-r--r-- | src/jtag/drivers/libusb0_common.h | 5 | ||||
-rw-r--r-- | src/jtag/drivers/libusb1_common.c | 50 | ||||
-rw-r--r-- | src/jtag/drivers/libusb1_common.h | 18 |
6 files changed, 79 insertions, 49 deletions
diff --git a/src/jtag/aice/aice_usb.c b/src/jtag/aice/aice_usb.c index d933845..50b3b9a 100644 --- a/src/jtag/aice/aice_usb.c +++ b/src/jtag/aice/aice_usb.c @@ -2136,13 +2136,11 @@ static int aice_usb_open(struct aice_port_param_s *param) #endif /* usb_set_configuration required under win32 */ - struct jtag_libusb_device *udev = jtag_libusb_get_device(devh); jtag_libusb_set_configuration(devh, 0); - jtag_libusb_claim_interface(devh, 0); unsigned int aice_read_ep; unsigned int aice_write_ep; - jtag_libusb_get_endpoints(udev, &aice_read_ep, &aice_write_ep); + jtag_libusb_choose_interface(devh, &aice_read_ep, &aice_write_ep, -1, -1, -1); aice_handler.usb_read_ep = aice_read_ep; aice_handler.usb_write_ep = aice_write_ep; diff --git a/src/jtag/drivers/jlink.c b/src/jtag/drivers/jlink.c index 2177b08..57eea64 100644 --- a/src/jtag/drivers/jlink.c +++ b/src/jtag/drivers/jlink.c @@ -47,16 +47,12 @@ * pid = ( usb_address > 0x4) ? 0x0101 : (0x101 + usb_address) */ -#define JLINK_OB_PID 0x0105 +#define JLINK_USB_INTERFACE_CLASS 0xff +#define JLINK_USB_INTERFACE_SUBCLASS 0xff +#define JLINK_USB_INTERFACE_PROTOCOL 0xff -#define JLINK_WRITE_ENDPOINT 0x02 -#define JLINK_READ_ENDPOINT 0x81 - -#define JLINK_OB_WRITE_ENDPOINT 0x06 -#define JLINK_OB_READ_ENDPOINT 0x85 - -static unsigned int jlink_write_ep = JLINK_WRITE_ENDPOINT; -static unsigned int jlink_read_ep = JLINK_READ_ENDPOINT; +static unsigned int jlink_write_ep; +static unsigned int jlink_read_ep; static unsigned int jlink_hw_jtag_version = 2; #define JLINK_USB_TIMEOUT 1000 @@ -1746,20 +1742,12 @@ static struct jlink *jlink_usb_open() /* usb_set_configuration is only required under win32 * with libusb 0.1 and libusb0.sys. For libusb 1.0 it is a no-op * since the configuration is already set. */ - struct jtag_libusb_device *udev = jtag_libusb_get_device(devh); jtag_libusb_set_configuration(devh, 0); - jtag_libusb_claim_interface(devh, 0); - - /* Use the OB endpoints if the JLink we matched is a Jlink-OB adapter */ - uint16_t matched_pid; - if (jtag_libusb_get_pid(udev, &matched_pid) == ERROR_OK) { - if (matched_pid == JLINK_OB_PID) { - jlink_read_ep = JLINK_OB_WRITE_ENDPOINT; - jlink_write_ep = JLINK_OB_READ_ENDPOINT; - } - } - jtag_libusb_get_endpoints(udev, &jlink_read_ep, &jlink_write_ep); + jtag_libusb_choose_interface(devh, &jlink_read_ep, &jlink_write_ep, + JLINK_USB_INTERFACE_CLASS, + JLINK_USB_INTERFACE_SUBCLASS, + JLINK_USB_INTERFACE_PROTOCOL); struct jlink *result = malloc(sizeof(struct jlink)); result->usb_handle = devh; diff --git a/src/jtag/drivers/libusb0_common.c b/src/jtag/drivers/libusb0_common.c index b44b786..5b1248d 100644 --- a/src/jtag/drivers/libusb0_common.c +++ b/src/jtag/drivers/libusb0_common.c @@ -145,14 +145,23 @@ int jtag_libusb_set_configuration(jtag_libusb_device_handle *devh, udev->config[configuration].bConfigurationValue); } -int jtag_libusb_get_endpoints(struct jtag_libusb_device *udev, +int jtag_libusb_choose_interface(struct jtag_libusb_device_handle *devh, unsigned int *usb_read_ep, - unsigned int *usb_write_ep) + unsigned int *usb_write_ep, + int bclass, int subclass, int protocol) { + struct jtag_libusb_device *udev = jtag_libusb_get_device(devh); struct usb_interface *iface = udev->config->interface; struct usb_interface_descriptor *desc = iface->altsetting; + *usb_read_ep = *usb_write_ep = 0; + for (int i = 0; i < desc->bNumEndpoints; i++) { + if ((bclass > 0 && desc->bInterfaceClass != bclass) || + (subclass > 0 && desc->bInterfaceSubClass != subclass) || + (protocol > 0 && desc->bInterfaceProtocol != protocol)) + continue; + uint8_t epnum = desc->endpoint[i].bEndpointAddress; bool is_input = epnum & 0x80; LOG_DEBUG("usb ep %s %02x", is_input ? "in" : "out", epnum); @@ -160,9 +169,15 @@ int jtag_libusb_get_endpoints(struct jtag_libusb_device *udev, *usb_read_ep = epnum; else *usb_write_ep = epnum; + + if (*usb_read_ep && *usb_write_ep) { + LOG_DEBUG("Claiming interface %d", (int)desc->bInterfaceNumber); + usb_claim_interface(devh, (int)desc->bInterfaceNumber); + return ERROR_OK; + } } - return 0; + return ERROR_FAIL; } int jtag_libusb_get_pid(struct jtag_libusb_device *dev, uint16_t *pid) diff --git a/src/jtag/drivers/libusb0_common.h b/src/jtag/drivers/libusb0_common.h index 370954f..ca372a0 100644 --- a/src/jtag/drivers/libusb0_common.h +++ b/src/jtag/drivers/libusb0_common.h @@ -66,9 +66,10 @@ int jtag_libusb_bulk_read(struct jtag_libusb_device_handle *dev, int ep, char *bytes, int size, int timeout); int jtag_libusb_set_configuration(jtag_libusb_device_handle *devh, int configuration); -int jtag_libusb_get_endpoints(struct jtag_libusb_device *udev, +int jtag_libusb_choose_interface(struct jtag_libusb_device_handle *devh, unsigned int *usb_read_ep, - unsigned int *usb_write_ep); + unsigned int *usb_write_ep, + int bclass, int subclass, int protocol); int jtag_libusb_get_pid(struct jtag_libusb_device *dev, uint16_t *pid); #endif /* JTAG_USB_COMMON_H */ diff --git a/src/jtag/drivers/libusb1_common.c b/src/jtag/drivers/libusb1_common.c index 07d9f95..bda91ff 100644 --- a/src/jtag/drivers/libusb1_common.c +++ b/src/jtag/drivers/libusb1_common.c @@ -186,40 +186,54 @@ int jtag_libusb_set_configuration(jtag_libusb_device_handle *devh, return retCode; } -int jtag_libusb_get_endpoints(struct jtag_libusb_device *udev, +int jtag_libusb_choose_interface(struct jtag_libusb_device_handle *devh, unsigned int *usb_read_ep, - unsigned int *usb_write_ep) + unsigned int *usb_write_ep, + int bclass, int subclass, int protocol) { + struct jtag_libusb_device *udev = jtag_libusb_get_device(devh); const struct libusb_interface *inter; const struct libusb_interface_descriptor *interdesc; const struct libusb_endpoint_descriptor *epdesc; struct libusb_config_descriptor *config; + *usb_read_ep = *usb_write_ep = 0; + libusb_get_config_descriptor(udev, 0, &config); for (int i = 0; i < (int)config->bNumInterfaces; i++) { inter = &config->interface[i]; - for (int j = 0; j < inter->num_altsetting; j++) { - interdesc = &inter->altsetting[j]; - for (int k = 0; - k < (int)interdesc->bNumEndpoints; k++) { - epdesc = &interdesc->endpoint[k]; - - uint8_t epnum = epdesc->bEndpointAddress; - bool is_input = epnum & 0x80; - LOG_DEBUG("usb ep %s %02x", - is_input ? "in" : "out", epnum); - - if (is_input) - *usb_read_ep = epnum; - else - *usb_write_ep = epnum; + interdesc = &inter->altsetting[0]; + for (int k = 0; + k < (int)interdesc->bNumEndpoints; k++) { + if ((bclass > 0 && interdesc->bInterfaceClass != bclass) || + (subclass > 0 && interdesc->bInterfaceSubClass != subclass) || + (protocol > 0 && interdesc->bInterfaceProtocol != protocol)) + continue; + + epdesc = &interdesc->endpoint[k]; + + uint8_t epnum = epdesc->bEndpointAddress; + bool is_input = epnum & 0x80; + LOG_DEBUG("usb ep %s %02x", + is_input ? "in" : "out", epnum); + + if (is_input) + *usb_read_ep = epnum; + else + *usb_write_ep = epnum; + + if (*usb_read_ep && *usb_write_ep) { + LOG_DEBUG("Claiming interface %d", (int)interdesc->bInterfaceNumber); + libusb_claim_interface(devh, (int)interdesc->bInterfaceNumber); + libusb_free_config_descriptor(config); + return ERROR_OK; } } } libusb_free_config_descriptor(config); - return 0; + return ERROR_FAIL; } int jtag_libusb_get_pid(struct jtag_libusb_device *dev, uint16_t *pid) diff --git a/src/jtag/drivers/libusb1_common.h b/src/jtag/drivers/libusb1_common.h index a4447ca..4ef6bf7 100644 --- a/src/jtag/drivers/libusb1_common.h +++ b/src/jtag/drivers/libusb1_common.h @@ -60,9 +60,23 @@ int jtag_libusb_bulk_read(struct jtag_libusb_device_handle *dev, int ep, char *bytes, int size, int timeout); int jtag_libusb_set_configuration(jtag_libusb_device_handle *devh, int configuration); -int jtag_libusb_get_endpoints(struct jtag_libusb_device *udev, +/** + * Find the first interface optionally matching class, subclass and + * protocol and claim it. + * @param devh _libusb_ device handle. + * @param usb_read_ep A pointer to a variable where the _IN_ endpoint + * number will be stored. + * @param usb_write_ep A pointer to a variable where the _OUT_ endpoint + * number will be stored. + * @param bclass `bInterfaceClass` to match, or -1 to ignore this field. + * @param subclass `bInterfaceSubClass` to match, or -1 to ignore this field. + * @param protocol `bInterfaceProtocol` to match, or -1 to ignore this field. + * @returns Returns ERROR_OK on success, ERROR_FAIL otherwise. + */ +int jtag_libusb_choose_interface(struct jtag_libusb_device_handle *devh, unsigned int *usb_read_ep, - unsigned int *usb_write_ep); + unsigned int *usb_write_ep, + int bclass, int subclass, int protocol); int jtag_libusb_get_pid(struct jtag_libusb_device *dev, uint16_t *pid); #endif /* JTAG_USB_COMMON_H */ |