meson: Simplify code for libusb dependency
[libjaylink.git] / libjaylink / discovery_usb.c
blobb42afb3fc18d74eaa5bf68fba664c09a82f9e872
1 /*
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/>.
20 #include <stdlib.h>
21 #include <stdint.h>
22 #include <stdbool.h>
23 #include <string.h>
24 #include <sys/types.h>
26 #include "libjaylink.h"
27 #include "libjaylink-internal.h"
30 * libusb.h includes windows.h and therefore must be included after anything
31 * that includes winsock2.h.
33 #include <libusb.h>
35 /**
36 * @file
38 * Device discovery (USB).
41 /** @cond PRIVATE */
42 /** USB Vendor ID (VID) of SEGGER products. */
43 #define USB_VENDOR_ID 0x1366
45 /* USB Product IDs (PID) and their corresponding USB addresses. */
46 static const struct {
47 uint16_t pid;
48 enum jaylink_usb_address usb_address;
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 {0x1024, JAYLINK_USB_ADDRESS_0},
68 {0x1051, JAYLINK_USB_ADDRESS_0},
69 {0x1055, JAYLINK_USB_ADDRESS_0},
70 {0x1059, JAYLINK_USB_ADDRESS_0},
71 {0x1061, JAYLINK_USB_ADDRESS_0}
74 /** Maximum length of the USB string descriptor for the serial number. */
75 #define USB_SERIAL_NUMBER_LENGTH 12
77 /**
78 * Maximum number of digits in a serial number
80 * The serial number of a device consists of at most 9 digits but user defined
81 * serial numbers are allowed with up to 10 digits.
83 #define MAX_SERIAL_NUMBER_DIGITS 10
84 /** @endcond */
86 static bool parse_serial_number(const char *str, uint32_t *serial_number)
88 size_t length;
90 length = strlen(str);
93 * Skip the first digits which are not part of a valid serial number.
94 * This is necessary because some devices erroneously use random digits
95 * instead of zeros for padding.
97 if (length > MAX_SERIAL_NUMBER_DIGITS)
98 str = str + (length - MAX_SERIAL_NUMBER_DIGITS);
100 if (jaylink_parse_serial_number(str, serial_number) != JAYLINK_OK)
101 return false;
103 return true;
106 static bool compare_devices(const void *a, const void *b)
108 const struct jaylink_device *dev;
109 const struct libusb_device *usb_dev;
111 dev = a;
112 usb_dev = b;
114 if (dev->iface != JAYLINK_HIF_USB)
115 return false;
117 if (dev->usb_dev == usb_dev)
118 return true;
120 return false;
123 static struct jaylink_device *find_device(const struct jaylink_context *ctx,
124 const struct libusb_device *usb_dev)
126 struct list *item;
128 item = list_find_custom(ctx->devs, &compare_devices, usb_dev);
130 if (item)
131 return item->data;
133 return NULL;
136 static struct jaylink_device *probe_device(struct jaylink_context *ctx,
137 struct libusb_device *usb_dev)
139 int ret;
140 struct libusb_device_descriptor desc;
141 struct libusb_device_handle *usb_devh;
142 struct jaylink_device *dev;
143 char buf[USB_SERIAL_NUMBER_LENGTH + 1];
144 enum jaylink_usb_address usb_address;
145 uint32_t serial_number;
146 bool has_serial_number;
147 bool found_device;
149 ret = libusb_get_device_descriptor(usb_dev, &desc);
151 if (ret != LIBUSB_SUCCESS) {
152 log_warn(ctx, "Failed to get device descriptor: %s",
153 libusb_error_name(ret));
154 return NULL;
157 if (desc.idVendor != USB_VENDOR_ID)
158 return NULL;
160 found_device = false;
162 for (size_t i = 0; i < sizeof(pids) / sizeof(pids[0]); i++) {
163 if (pids[i].pid == desc.idProduct) {
164 usb_address = pids[i].usb_address;
165 found_device = true;
166 break;
170 if (!found_device)
171 return NULL;
173 log_dbg(ctx, "Found device (VID:PID = %04x:%04x, bus:address = "
174 "%03u:%03u)", desc.idVendor, desc.idProduct,
175 libusb_get_bus_number(usb_dev),
176 libusb_get_device_address(usb_dev));
179 * Search for an already allocated device instance for this device and
180 * if found return a reference to it.
182 dev = find_device(ctx, usb_dev);
184 if (dev) {
185 log_dbg(ctx, "Device: USB address = %u", dev->usb_address);
187 if (dev->has_serial_number)
188 log_dbg(ctx, "Device: Serial number = %u",
189 dev->serial_number);
190 else
191 log_dbg(ctx, "Device: Serial number = N/A");
193 log_dbg(ctx, "Using existing device instance");
194 return jaylink_ref_device(dev);
197 /* Open the device to be able to retrieve its serial number. */
198 ret = libusb_open(usb_dev, &usb_devh);
200 if (ret != LIBUSB_SUCCESS) {
201 log_warn(ctx, "Failed to open device: %s",
202 libusb_error_name(ret));
203 return NULL;
206 serial_number = 0;
207 has_serial_number = true;
209 ret = libusb_get_string_descriptor_ascii(usb_devh, desc.iSerialNumber,
210 (unsigned char *)buf, USB_SERIAL_NUMBER_LENGTH + 1);
212 libusb_close(usb_devh);
214 if (ret < 0) {
215 log_warn(ctx, "Failed to retrieve serial number: %s",
216 libusb_error_name(ret));
217 has_serial_number = false;
220 if (has_serial_number) {
221 if (!parse_serial_number(buf, &serial_number)) {
222 log_warn(ctx, "Failed to parse serial number");
223 return NULL;
227 log_dbg(ctx, "Device: USB address = %u", usb_address);
229 if (has_serial_number)
230 log_dbg(ctx, "Device: Serial number = %u", serial_number);
231 else
232 log_dbg(ctx, "Device: Serial number = N/A");
234 log_dbg(ctx, "Allocating new device instance");
236 dev = device_allocate(ctx);
238 if (!dev) {
239 log_warn(ctx, "Device instance malloc failed");
240 return NULL;
243 dev->iface = JAYLINK_HIF_USB;
244 dev->usb_dev = libusb_ref_device(usb_dev);
245 dev->usb_address = usb_address;
246 dev->serial_number = serial_number;
247 dev->has_serial_number = has_serial_number;
249 return dev;
252 JAYLINK_PRIV int discovery_usb_scan(struct jaylink_context *ctx)
254 ssize_t ret;
255 struct libusb_device **devs;
256 struct jaylink_device *dev;
257 size_t num;
259 ret = libusb_get_device_list(ctx->usb_ctx, &devs);
261 if (ret == LIBUSB_ERROR_IO) {
262 log_err(ctx, "Failed to retrieve device list: input/output "
263 "error");
264 return JAYLINK_ERR_IO;
265 } else if (ret < 0) {
266 log_err(ctx, "Failed to retrieve device list: %s",
267 libusb_error_name(ret));
268 return JAYLINK_ERR;
271 num = 0;
273 for (size_t i = 0; devs[i]; i++) {
274 dev = probe_device(ctx, devs[i]);
276 if (!dev)
277 continue;
279 ctx->discovered_devs = list_prepend(ctx->discovered_devs, dev);
280 num++;
283 libusb_free_device_list(devs, true);
284 log_dbg(ctx, "Found %zu USB device(s)", num);
286 return JAYLINK_OK;