libusb: add debug message on adapter not found due to wrong serial
[fw/openocd] / src / jtag / drivers / libusb1_common.c
index a29b2e9105e56eaf51f645cc2ac515d2f204384f..ec52a1bce272464b68c86405301efbf608620062 100644 (file)
@@ -14,9 +14,7 @@
  *   GNU General Public License for more details.                          *
  *                                                                         *
  *   You should have received a copy of the GNU General Public License     *
- *   along with this program; if not, write to the                         *
- *   Free Software Foundation, Inc.,                                       *
- *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.           *
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>. *
  ***************************************************************************/
 
 #ifdef HAVE_CONFIG_H
@@ -73,11 +71,12 @@ int jtag_libusb_open(const uint16_t vids[], const uint16_t pids[],
                struct jtag_libusb_device_handle **out)
 {
        int cnt, idx, errCode;
-       int retval = -ENODEV;
+       int retval = ERROR_FAIL;
+       bool serial_mismatch = false;
        struct jtag_libusb_device_handle *libusb_handle = NULL;
 
        if (libusb_init(&jtag_libusb_context) < 0)
-               return -ENODEV;
+               return ERROR_FAIL;
 
        cnt = libusb_get_device_list(jtag_libusb_context, &devs);
 
@@ -101,17 +100,23 @@ int jtag_libusb_open(const uint16_t vids[], const uint16_t pids[],
                /* Device must be open to use libusb_get_string_descriptor_ascii. */
                if (serial != NULL &&
                                !string_descriptor_equal(libusb_handle, dev_desc.iSerialNumber, serial)) {
+                       serial_mismatch = true;
                        libusb_close(libusb_handle);
                        continue;
                }
 
                /* Success. */
                *out = libusb_handle;
-               retval = 0;
+               retval = ERROR_OK;
+               serial_mismatch = false;
                break;
        }
        if (cnt >= 0)
                libusb_free_device_list(devs, 1);
+
+       if (serial_mismatch)
+               LOG_INFO("No device matches the serial string");
+
        return retval;
 }
 
@@ -165,49 +170,77 @@ int jtag_libusb_set_configuration(jtag_libusb_device_handle *devh,
        int retCode = -99;
 
        struct libusb_config_descriptor *config = NULL;
+       int current_config = -1;
+
+       retCode = libusb_get_configuration(devh, &current_config);
+       if (retCode != 0)
+               return retCode;
+
+       retCode = libusb_get_config_descriptor(udev, configuration, &config);
+       if (retCode != 0 || config == NULL)
+               return retCode;
 
-       libusb_get_config_descriptor(udev, configuration, &config);
-       retCode = libusb_set_configuration(devh, config->bConfigurationValue);
+       /* Only change the configuration if it is not already set to the
+          same one. Otherwise this issues a lightweight reset and hangs
+          LPC-Link2 with JLink firmware. */
+       if (current_config != config->bConfigurationValue)
+               retCode = libusb_set_configuration(devh, config->bConfigurationValue);
 
        libusb_free_config_descriptor(config);
 
        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, int trans_type)
 {
+       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];
+                       if (trans_type > 0 && (epdesc->bmAttributes & 0x3) != trans_type)
+                               continue;
+
+                       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)