Use JAYLINK_ERR_IO
[libjaylink.git] / libjaylink / discovery.c
blobaa294d655f1a54c3e26c49c22b368081ed6e5d0c
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 <stdio.h>
22 #include <inttypes.h>
23 #include <stdbool.h>
24 #include <string.h>
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.
34 #include <libusb.h>
36 /**
37 * @file
39 * Device discovery.
42 /** @cond PRIVATE */
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] = {
48 {0x0101, 0},
49 {0x0102, 1},
50 {0x0103, 2},
51 {0x0104, 3},
52 {0x0105, 0},
53 {0x0107, 0},
54 {0x0108, 0},
55 {0x1010, 0},
56 {0x1011, 0},
57 {0x1012, 0},
58 {0x1013, 0},
59 {0x1014, 0},
60 {0x1015, 0},
61 {0x1016, 0},
62 {0x1017, 0},
63 {0x1018, 0}
66 /** Maximum length of the USB string descriptor for the serial number. */
67 #define USB_SERIAL_NUMBER_LENGTH 12
69 /**
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
76 /** @endcond */
78 static bool parse_serial_number(const char *str, uint32_t *serial_number)
80 size_t length;
82 length = strlen(str);
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)
93 return false;
95 return true;
98 static bool compare_devices(const void *a, const void *b)
100 const struct jaylink_device *dev;
101 const struct libusb_device *usb_dev;
103 dev = a;
104 usb_dev = b;
106 if (dev->usb_dev == usb_dev)
107 return false;
109 return true;
112 static struct jaylink_device *find_device(const struct jaylink_context *ctx,
113 const struct libusb_device *usb_dev)
115 struct list *item;
117 item = list_find_custom(ctx->devs, &compare_devices, usb_dev);
119 if (item)
120 return item->data;
122 return NULL;
125 static struct jaylink_device *probe_device(struct jaylink_context *ctx,
126 struct libusb_device *usb_dev)
128 int ret;
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];
133 uint8_t usb_address;
134 uint32_t serial_number;
135 bool valid_serial_number;
136 bool found_device;
137 size_t i;
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));
144 return NULL;
147 if (desc.idVendor != USB_VENDOR_ID)
148 return NULL;
150 found_device = false;
152 for (i = 0; i < sizeof(pids) / sizeof(pids[0]); i++) {
153 if (pids[i][0] == desc.idProduct) {
154 found_device = true;
155 usb_address = pids[i][1];
156 break;
160 if (!found_device)
161 return NULL;
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);
174 if (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.",
179 dev->serial_number);
180 else
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));
193 return NULL;
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);
203 if (ret < 0) {
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.");
212 return NULL;
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);
220 else
221 log_dbg(ctx, "Device: Serial number = N/A.");
223 log_dbg(ctx, "Allocating new device instance.");
225 dev = device_allocate(ctx);
227 if (!dev) {
228 log_warn(ctx, "Device instance malloc failed.");
229 return NULL;
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;
238 return dev;
241 static int discovery_usb_scan(struct jaylink_context *ctx)
243 ssize_t ret;
244 struct libusb_device **devs;
245 struct jaylink_device *dev;
246 size_t num;
247 size_t i;
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 "
253 "error.");
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));
258 return JAYLINK_ERR;
261 num = 0;
263 for (i = 0; devs[i]; i++) {
264 dev = probe_device(ctx, devs[i]);
266 if (!dev)
267 continue;
269 ctx->discovered_devs = list_prepend(ctx->discovered_devs, dev);
270 num++;
273 libusb_free_device_list(devs, true);
274 log_dbg(ctx, "Found %zu USB device(s).", num);
276 return JAYLINK_OK;
279 static void clear_discovery_list(struct jaylink_context *ctx)
281 struct list *item;
282 struct list *tmp;
283 struct jaylink_device *dev;
285 item = ctx->discovered_devs;
287 while (item) {
288 dev = (struct jaylink_device *)item->data;
289 jaylink_unref_device(dev);
291 tmp = item;
292 item = item->next;
293 free(tmp);
296 ctx->discovered_devs = NULL;
300 * Scan for devices.
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
306 * of the interfaces.
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()
315 * @since 0.1.0
317 JAYLINK_API int jaylink_discovery_scan(struct jaylink_context *ctx,
318 uint32_t hostifs)
320 int ret;
322 if (!ctx)
323 return JAYLINK_ERR_ARG;
325 (void)hostifs;
327 clear_discovery_list(ctx);
329 ret = discovery_usb_scan(ctx);
331 if (ret != JAYLINK_OK) {
332 log_err(ctx, "USB device discovery failed.");
333 return ret;
336 return JAYLINK_OK;