OpenOCD
discovery_usb.c
Go to the documentation of this file.
1 /*
2  * This file is part of the libjaylink project.
3  *
4  * Copyright (C) 2014-2016 Marc Schink <jaylink-dev@marcschink.de>
5  *
6  * This program is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation, either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program. If not, see <http://www.gnu.org/licenses/>.
18  */
19 
20 #include <stdlib.h>
21 #include <stdint.h>
22 #include <stdbool.h>
23 #include <string.h>
24 #include <sys/types.h>
25 
26 #include "libjaylink.h"
27 #include "libjaylink-internal.h"
28 
29 /*
30  * libusb.h includes windows.h and therefore must be included after anything
31  * that includes winsock2.h.
32  */
33 #include <libusb.h>
34 
43 #define USB_VENDOR_ID 0x1366
44 
45 /* USB Product IDs (PID) and their corresponding USB addresses. */
46 static const struct {
47  uint16_t pid;
49 } pids[] = {
50  {0x0101, JAYLINK_USB_ADDRESS_0},
51  {0x0102, JAYLINK_USB_ADDRESS_1},
52  {0x0103, JAYLINK_USB_ADDRESS_2},
53  {0x0104, JAYLINK_USB_ADDRESS_3},
54  {0x0105, JAYLINK_USB_ADDRESS_0},
55  {0x0107, JAYLINK_USB_ADDRESS_0},
56  {0x0108, JAYLINK_USB_ADDRESS_0},
57  {0x1010, JAYLINK_USB_ADDRESS_0},
58  {0x1011, JAYLINK_USB_ADDRESS_0},
59  {0x1012, JAYLINK_USB_ADDRESS_0},
60  {0x1013, JAYLINK_USB_ADDRESS_0},
61  {0x1014, JAYLINK_USB_ADDRESS_0},
62  {0x1015, JAYLINK_USB_ADDRESS_0},
63  {0x1016, JAYLINK_USB_ADDRESS_0},
64  {0x1017, JAYLINK_USB_ADDRESS_0},
65  {0x1018, JAYLINK_USB_ADDRESS_0},
66  {0x1020, JAYLINK_USB_ADDRESS_0},
67  {0x1051, JAYLINK_USB_ADDRESS_0},
68  {0x1055, JAYLINK_USB_ADDRESS_0},
69  {0x1061, JAYLINK_USB_ADDRESS_0}
70 };
71 
73 #define USB_SERIAL_NUMBER_LENGTH 12
74 
81 #define MAX_SERIAL_NUMBER_DIGITS 10
82 
84 static bool parse_serial_number(const char *str, uint32_t *serial_number)
85 {
86  size_t length;
87 
88  length = strlen(str);
89 
90  /*
91  * Skip the first digits which are not part of a valid serial number.
92  * This is necessary because some devices erroneously use random digits
93  * instead of zeros for padding.
94  */
95  if (length > MAX_SERIAL_NUMBER_DIGITS)
96  str = str + (length - MAX_SERIAL_NUMBER_DIGITS);
97 
98  if (jaylink_parse_serial_number(str, serial_number) != JAYLINK_OK)
99  return false;
100 
101  return true;
102 }
103 
104 static bool compare_devices(const void *a, const void *b)
105 {
106  const struct jaylink_device *dev;
107  const struct libusb_device *usb_dev;
108 
109  dev = a;
110  usb_dev = b;
111 
112  if (dev->iface != JAYLINK_HIF_USB)
113  return false;
114 
115  if (dev->usb_dev == usb_dev)
116  return true;
117 
118  return false;
119 }
120 
121 static struct jaylink_device *find_device(const struct jaylink_context *ctx,
122  const struct libusb_device *usb_dev)
123 {
124  struct list *item;
125 
126  item = list_find_custom(ctx->devs, &compare_devices, usb_dev);
127 
128  if (item)
129  return item->data;
130 
131  return NULL;
132 }
133 
135  struct libusb_device *usb_dev)
136 {
137  int ret;
138  struct libusb_device_descriptor desc;
139  struct libusb_device_handle *usb_devh;
140  struct jaylink_device *dev;
141  char buf[USB_SERIAL_NUMBER_LENGTH + 1];
143  uint32_t serial_number;
144  bool has_serial_number;
145  bool found_device;
146 
147  ret = libusb_get_device_descriptor(usb_dev, &desc);
148 
149  if (ret != LIBUSB_SUCCESS) {
150  log_warn(ctx, "Failed to get device descriptor: %s.",
151  libusb_error_name(ret));
152  return NULL;
153  }
154 
155  if (desc.idVendor != USB_VENDOR_ID)
156  return NULL;
157 
158  found_device = false;
159 
160  for (size_t i = 0; i < sizeof(pids) / sizeof(pids[0]); i++) {
161  if (pids[i].pid == desc.idProduct) {
162  usb_address = pids[i].usb_address;
163  found_device = true;
164  break;
165  }
166  }
167 
168  if (!found_device)
169  return NULL;
170 
171  log_dbg(ctx, "Found device (VID:PID = %04x:%04x, bus:address = "
172  "%03u:%03u).", desc.idVendor, desc.idProduct,
173  libusb_get_bus_number(usb_dev),
174  libusb_get_device_address(usb_dev));
175 
176  /*
177  * Search for an already allocated device instance for this device and
178  * if found return a reference to it.
179  */
180  dev = find_device(ctx, usb_dev);
181 
182  if (dev) {
183  log_dbg(ctx, "Device: USB address = %u.", dev->usb_address);
184 
185  if (dev->has_serial_number)
186  log_dbg(ctx, "Device: Serial number = %u.",
187  dev->serial_number);
188  else
189  log_dbg(ctx, "Device: Serial number = N/A.");
190 
191  log_dbg(ctx, "Using existing device instance.");
192  return jaylink_ref_device(dev);
193  }
194 
195  /* Open the device to be able to retrieve its serial number. */
196  ret = libusb_open(usb_dev, &usb_devh);
197 
198  if (ret != LIBUSB_SUCCESS) {
199  log_warn(ctx, "Failed to open device: %s.",
200  libusb_error_name(ret));
201  return NULL;
202  }
203 
204  serial_number = 0;
205  has_serial_number = true;
206 
207  ret = libusb_get_string_descriptor_ascii(usb_devh, desc.iSerialNumber,
208  (unsigned char *)buf, USB_SERIAL_NUMBER_LENGTH + 1);
209 
210  libusb_close(usb_devh);
211 
212  if (ret < 0) {
213  log_warn(ctx, "Failed to retrieve serial number: %s.",
214  libusb_error_name(ret));
215  has_serial_number = false;
216  }
217 
218  if (has_serial_number) {
219  if (!parse_serial_number(buf, &serial_number)) {
220  log_warn(ctx, "Failed to parse serial number.");
221  return NULL;
222  }
223  }
224 
225  log_dbg(ctx, "Device: USB address = %u.", usb_address);
226 
227  if (has_serial_number)
228  log_dbg(ctx, "Device: Serial number = %u.", serial_number);
229  else
230  log_dbg(ctx, "Device: Serial number = N/A.");
231 
232  log_dbg(ctx, "Allocating new device instance.");
233 
234  dev = device_allocate(ctx);
235 
236  if (!dev) {
237  log_warn(ctx, "Device instance malloc failed.");
238  return NULL;
239  }
240 
241  dev->iface = JAYLINK_HIF_USB;
242  dev->usb_dev = libusb_ref_device(usb_dev);
243  dev->usb_address = usb_address;
246 
247  return dev;
248 }
249 
251 {
252  ssize_t ret;
253  struct libusb_device **devs;
254  struct jaylink_device *dev;
255  size_t num;
256 
257  ret = libusb_get_device_list(ctx->usb_ctx, &devs);
258 
259  if (ret == LIBUSB_ERROR_IO) {
260  log_err(ctx, "Failed to retrieve device list: input/output "
261  "error.");
262  return JAYLINK_ERR_IO;
263  } else if (ret < 0) {
264  log_err(ctx, "Failed to retrieve device list: %s.",
265  libusb_error_name(ret));
266  return JAYLINK_ERR;
267  }
268 
269  num = 0;
270 
271  for (size_t i = 0; devs[i]; i++) {
272  dev = probe_device(ctx, devs[i]);
273 
274  if (!dev)
275  continue;
276 
277  ctx->discovered_devs = list_prepend(ctx->discovered_devs, dev);
278  num++;
279  }
280 
281  libusb_free_device_list(devs, true);
282  log_dbg(ctx, "Found %zu USB device(s).", num);
283 
284  return JAYLINK_OK;
285 }
JAYLINK_PRIV int discovery_usb_scan(struct jaylink_context *ctx)
static libusb_device ** devs
The usb device list.
Definition: libusb_helper.c:34
JAYLINK_API struct jaylink_device * jaylink_ref_device(struct jaylink_device *dev)
Increment the reference count of a device.
Definition: device.c:518
static struct jaylink_device * probe_device(struct jaylink_context *ctx, struct libusb_device *usb_dev)
static bool parse_serial_number(const char *str, uint32_t *serial_number)
Definition: discovery_usb.c:84
static struct jaylink_device * find_device(const struct jaylink_context *ctx, const struct libusb_device *usb_dev)
#define NULL
Definition: usb.h:27
static bool compare_devices(const void *a, const void *b)