2 * This file is part of the libjaylink project.
4 * Copyright (C) 2014-2016 Marc Schink <jaylink-dev@marcschink.de>
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.
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.
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/>.
25 #include <sys/types.h>
27 #include "libjaylink.h"
28 #include "libjaylink-internal.h"
31 * libusb.h includes windows.h and therefore must be included after anything
32 * that includes winsock2.h.
43 /** USB Vendor ID (VID) of SEGGER products. */
44 #define USB_VENDOR_ID 0x1366
46 /* USB Product IDs (PID) and their corresponding USB addresses. */
47 static const uint16_t pids
[][2] = {
66 /** Maximum length of the USB string descriptor for the serial number. */
67 #define USB_SERIAL_NUMBER_LENGTH 12
70 * Maximum number of digits in a serial number
72 * The serial number of a device consists of at most 9 digits but user defined
73 * serial numbers are allowed with up to 10 digits.
75 #define MAX_SERIAL_NUMBER_DIGITS 10
78 static bool parse_serial_number(const char *str
, uint32_t *serial_number
)
85 * Skip the first digits which are not part of a valid serial number.
86 * This is necessary because some devices erroneously use random digits
87 * instead of zeros for padding.
89 if (length
> MAX_SERIAL_NUMBER_DIGITS
)
90 str
= str
+ (length
- MAX_SERIAL_NUMBER_DIGITS
);
92 if (sscanf(str
, "%" SCNu32
, serial_number
) != 1)
98 static bool compare_devices(const void *a
, const void *b
)
100 const struct jaylink_device
*dev
;
101 const struct libusb_device
*usb_dev
;
106 if (dev
->usb_dev
== usb_dev
)
112 static struct jaylink_device
*find_device(const struct jaylink_context
*ctx
,
113 const struct libusb_device
*usb_dev
)
117 item
= list_find_custom(ctx
->devs
, &compare_devices
, usb_dev
);
125 static struct jaylink_device
*probe_device(struct jaylink_context
*ctx
,
126 struct libusb_device
*usb_dev
)
129 struct libusb_device_descriptor desc
;
130 struct libusb_device_handle
*usb_devh
;
131 struct jaylink_device
*dev
;
132 char buf
[USB_SERIAL_NUMBER_LENGTH
+ 1];
134 uint32_t serial_number
;
135 bool valid_serial_number
;
139 ret
= libusb_get_device_descriptor(usb_dev
, &desc
);
141 if (ret
!= LIBUSB_SUCCESS
) {
142 log_warn(ctx
, "Failed to get device descriptor: %s.",
143 libusb_error_name(ret
));
147 if (desc
.idVendor
!= USB_VENDOR_ID
)
150 found_device
= false;
152 for (i
= 0; i
< sizeof(pids
) / sizeof(pids
[0]); i
++) {
153 if (pids
[i
][0] == desc
.idProduct
) {
155 usb_address
= pids
[i
][1];
163 log_dbg(ctx
, "Found device (VID:PID = %04x:%04x, bus:address = "
164 "%03u:%03u).", desc
.idVendor
, desc
.idProduct
,
165 libusb_get_bus_number(usb_dev
),
166 libusb_get_device_address(usb_dev
));
169 * Search for an already allocated device instance for this device and
170 * if found return a reference to it.
172 dev
= find_device(ctx
, usb_dev
);
175 log_dbg(ctx
, "Device: USB address = %u.", dev
->usb_address
);
177 if (dev
->valid_serial_number
)
178 log_dbg(ctx
, "Device: Serial number = %u.",
181 log_dbg(ctx
, "Device: Serial number = N/A.");
183 log_dbg(ctx
, "Using existing device instance.");
184 return jaylink_ref_device(dev
);
187 /* Open the device to be able to retrieve its serial number. */
188 ret
= libusb_open(usb_dev
, &usb_devh
);
190 if (ret
!= LIBUSB_SUCCESS
) {
191 log_warn(ctx
, "Failed to open device: %s.",
192 libusb_error_name(ret
));
196 valid_serial_number
= true;
198 ret
= libusb_get_string_descriptor_ascii(usb_devh
, desc
.iSerialNumber
,
199 (unsigned char *)buf
, USB_SERIAL_NUMBER_LENGTH
+ 1);
201 libusb_close(usb_devh
);
204 log_warn(ctx
, "Failed to retrieve serial number: %s.",
205 libusb_error_name(ret
));
206 valid_serial_number
= false;
209 if (valid_serial_number
) {
210 if (!parse_serial_number(buf
, &serial_number
)) {
211 log_warn(ctx
, "Failed to parse serial number.");
216 log_dbg(ctx
, "Device: USB address = %u.", usb_address
);
218 if (valid_serial_number
)
219 log_dbg(ctx
, "Device: Serial number = %u.", serial_number
);
221 log_dbg(ctx
, "Device: Serial number = N/A.");
223 log_dbg(ctx
, "Allocating new device instance.");
225 dev
= device_allocate(ctx
);
228 log_warn(ctx
, "Device instance malloc failed.");
232 dev
->interface
= JAYLINK_HIF_USB
;
233 dev
->usb_dev
= libusb_ref_device(usb_dev
);
234 dev
->usb_address
= usb_address
;
235 dev
->serial_number
= serial_number
;
236 dev
->valid_serial_number
= valid_serial_number
;
241 static int discovery_usb_scan(struct jaylink_context
*ctx
)
244 struct libusb_device
**devs
;
245 struct jaylink_device
*dev
;
249 ret
= libusb_get_device_list(ctx
->usb_ctx
, &devs
);
251 if (ret
== LIBUSB_ERROR_IO
) {
252 log_err(ctx
, "Failed to retrieve device list: input/output "
254 return JAYLINK_ERR_IO
;
255 } else if (ret
< 0) {
256 log_err(ctx
, "Failed to retrieve device list: %s.",
257 libusb_error_name(ret
));
263 for (i
= 0; devs
[i
]; i
++) {
264 dev
= probe_device(ctx
, devs
[i
]);
269 ctx
->discovered_devs
= list_prepend(ctx
->discovered_devs
, dev
);
273 libusb_free_device_list(devs
, true);
274 log_dbg(ctx
, "Found %zu USB device(s).", num
);
279 static void clear_discovery_list(struct jaylink_context
*ctx
)
283 struct jaylink_device
*dev
;
285 item
= ctx
->discovered_devs
;
288 dev
= (struct jaylink_device
*)item
->data
;
289 jaylink_unref_device(dev
);
296 ctx
->discovered_devs
= NULL
;
302 * @param[in,out] ctx libjaylink context.
303 * @param[in] hostifs Host interfaces to scan for devices. Use bitwise OR to
304 * specify multiple interfaces, or 0 to use all available
305 * interfaces. See #jaylink_host_interface for a description
308 * @retval JAYLINK_OK Success.
309 * @retval JAYLINK_ERR_ARG Invalid arguments.
310 * @retval JAYLINK_ERR_IO Input/output error.
311 * @retval JAYLINK_ERR Other error conditions.
313 * @see jaylink_get_devices()
317 JAYLINK_API
int jaylink_discovery_scan(struct jaylink_context
*ctx
,
323 return JAYLINK_ERR_ARG
;
327 clear_discovery_list(ctx
);
329 ret
= discovery_usb_scan(ctx
);
331 if (ret
!= JAYLINK_OK
) {
332 log_err(ctx
, "USB device discovery failed.");