diff options
author | Paul Fertser <fercerpav@gmail.com> | 2014-10-01 10:36:02 +0400 |
---|---|---|
committer | Spencer Oliver <spen@spen-soft.co.uk> | 2014-10-06 18:40:39 +0000 |
commit | 487c57d9a27244b6a916cce253d8aaaec5e22604 (patch) | |
tree | 415a362429677abc7046a654da2bd08c1a902841 /src/jtag/drivers/libusb1_common.c | |
parent | b631e78b25433712b4ffd03e1bc4b34a03da4f10 (diff) | |
download | riscv-openocd-487c57d9a27244b6a916cce253d8aaaec5e22604.zip riscv-openocd-487c57d9a27244b6a916cce253d8aaaec5e22604.tar.gz riscv-openocd-487c57d9a27244b6a916cce253d8aaaec5e22604.tar.bz2 |
libusb: introduce jtag_libusb_choose_interface() and use it for JLink
This introduces a new common function that allows auto-discovery of a
suitable USB interface based on class, subclass and protocol
matching. It claims the interface and returns the corresponding
endpoints number to the caller.
The need for this arised due to nRF51822 USB dongle which comes with
an "on-board Segger J-link debugger" having 3 interfaces, so the
current code can't work at all with it (in this particular case the
last interface needs to be choosen). This also removes special
handling of JLink-OB endpoint numbers as it's now possible to
autodetect them as well as the standard JLink endpoints.
Change-Id: I4d990a7a3b373efdd2949a394b32d855a168e138
Signed-off-by: Paul Fertser <fercerpav@gmail.com>
Reviewed-on: http://openocd.zylin.com/2327
Tested-by: jenkins
Reviewed-by: Spencer Oliver <spen@spen-soft.co.uk>
Diffstat (limited to 'src/jtag/drivers/libusb1_common.c')
-rw-r--r-- | src/jtag/drivers/libusb1_common.c | 50 |
1 files changed, 32 insertions, 18 deletions
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) |