Add jaylink_get_device()
[libjaylink.git] / libjaylink / discovery.c
blob1e609257e3ce1e28e51899d05a7e8b26b4b4761d
1 /*
2 * This file is part of the libjaylink project.
4 * Copyright (C) 2014-2015 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 <string.h>
24 #include <sys/types.h>
25 #include <libusb.h>
27 #include "libjaylink.h"
28 #include "libjaylink-internal.h"
30 /**
31 * @file
33 * Device discovery.
36 /** USB Vendor ID (VID) of SEGGER products. */
37 #define USB_VENDOR_ID 0x1366
39 /* USB Product IDs (PID) and their corresponding USB addresses. */
40 static const uint16_t pids[][2] = {
41 {0x0101, 0},
42 {0x0102, 1},
43 {0x0103, 2},
44 {0x0104, 3},
45 {0x0105, 0},
46 {0x0107, 0},
47 {0x0108, 0},
48 {0x1010, 0},
49 {0x1011, 0},
50 {0x1012, 0},
51 {0x1013, 0},
52 {0x1014, 0},
53 {0x1015, 0},
54 {0x1016, 0},
55 {0x1017, 0},
56 {0x1018, 0}
59 /** Maximum length of the USB string descriptor for the serial number. */
60 #define USB_SERIAL_NUMBER_LENGTH 12
62 /**
63 * Maximum number of digits in a serial number
65 * The serial number of a device consists of at most 9 digits but user defined
66 * serial numbers are allowed with up to 10 digits.
68 #define MAX_SERIAL_NUMBER_DIGITS 10
70 static struct jaylink_device **allocate_device_list(size_t length)
72 struct jaylink_device **list;
74 list = malloc(sizeof(struct jaylink_device *) * (length + 1));
76 if (!list)
77 return NULL;
79 list[length] = NULL;
81 return list;
84 static int parse_serial_number(const char *str, uint32_t *serial_number)
86 size_t length;
88 length = strlen(str);
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.
95 if (length > MAX_SERIAL_NUMBER_DIGITS)
96 str = str + (length - MAX_SERIAL_NUMBER_DIGITS);
98 if (sscanf(str, "%" SCNu32, serial_number) != 1)
99 return 0;
101 return 1;
104 static int compare_devices(const void *a, const void *b)
106 const struct jaylink_device *dev;
107 const struct libusb_device *usb_dev;
109 dev = a;
110 usb_dev = b;
112 if (dev->usb_dev == usb_dev)
113 return 0;
115 return 1;
118 static struct jaylink_device *find_device(const struct jaylink_context *ctx,
119 const struct libusb_device *usb_dev)
121 struct list *item;
123 item = list_find_custom(ctx->devs, &compare_devices, usb_dev);
125 if (item)
126 return item->data;
128 return NULL;
131 static struct jaylink_device *probe_device(struct jaylink_context *ctx,
132 struct libusb_device *usb_dev)
134 int ret;
135 struct libusb_device_descriptor desc;
136 struct libusb_device_handle *usb_devh;
137 struct jaylink_device *dev;
138 char buf[USB_SERIAL_NUMBER_LENGTH + 1];
139 uint8_t usb_address;
140 uint32_t serial_number;
141 int valid_serial_number;
142 int found_device;
143 size_t i;
145 ret = libusb_get_device_descriptor(usb_dev, &desc);
147 if (ret < 0) {
148 log_warn(ctx, "Failed to get device descriptor: %s.",
149 libusb_error_name(ret));
150 return NULL;
153 /* Check for USB Vendor ID (VID) of SEGGER. */
154 if (desc.idVendor != USB_VENDOR_ID)
155 return NULL;
157 found_device = 0;
159 for (i = 0; i < sizeof(pids) / sizeof(pids[0]); i++) {
160 if (pids[i][0] == desc.idProduct) {
161 found_device = 1;
162 usb_address = pids[i][1];
163 break;
167 if (!found_device)
168 return NULL;
170 log_dbg(ctx, "Found device (VID:PID = %04x:%04x, bus:address = "
171 "%03u:%03u).", desc.idVendor, desc.idProduct,
172 libusb_get_bus_number(usb_dev),
173 libusb_get_device_address(usb_dev));
176 * Search for an already allocated device instance for this device and
177 * if found return a reference to it.
179 dev = find_device(ctx, usb_dev);
181 if (dev) {
182 log_dbg(ctx, "Using existing device instance.");
183 return jaylink_ref_device(dev);
186 /* Open the device to be able to retrieve its serial number. */
187 ret = libusb_open(usb_dev, &usb_devh);
189 if (ret < 0) {
190 log_warn(ctx, "Failed to open device: %s.",
191 libusb_error_name(ret));
192 return NULL;
195 valid_serial_number = 1;
197 ret = libusb_get_string_descriptor_ascii(usb_devh, desc.iSerialNumber,
198 (unsigned char *)buf, USB_SERIAL_NUMBER_LENGTH + 1);
200 libusb_close(usb_devh);
202 if (ret < 0) {
203 log_warn(ctx, "Failed to retrieve serial number: %s.",
204 libusb_error_name(ret));
205 valid_serial_number = 0;
208 if (valid_serial_number) {
209 if (!parse_serial_number(buf, &serial_number)) {
210 log_warn(ctx, "Failed to parse serial number.");
211 return NULL;
215 log_dbg(ctx, "Device: USB address = %u.", usb_address);
217 if (valid_serial_number)
218 log_dbg(ctx, "Device: Serial number = %u.", serial_number);
219 else
220 log_dbg(ctx, "Device: Serial number = N/A.");
222 log_dbg(ctx, "Allocating new device instance.");
224 dev = device_allocate(ctx);
226 if (!dev) {
227 log_warn(ctx, "Device instance malloc failed.");
228 return NULL;
231 dev->usb_dev = libusb_ref_device(usb_dev);
232 dev->usb_address = usb_address;
233 dev->serial_number = serial_number;
234 dev->valid_serial_number = valid_serial_number;
236 return dev;
239 /** @private */
240 JAYLINK_PRIV ssize_t discovery_get_device_list(struct jaylink_context *ctx,
241 struct jaylink_device ***list)
243 ssize_t ret;
244 struct libusb_device **usb_devs;
245 struct jaylink_device **devs;
246 struct jaylink_device *dev;
247 size_t num_usb_devs;
248 size_t num_devs;
249 size_t i;
251 ret = libusb_get_device_list(ctx->usb_ctx, &usb_devs);
253 if (ret < 0) {
254 log_err(ctx, "Failed to retrieve device list: %s.",
255 libusb_error_name(ret));
256 return JAYLINK_ERR;
259 num_usb_devs = ret;
262 * Allocate a device list with the length of the number of all found
263 * USB devices because they all are possible J-Link devices.
265 devs = allocate_device_list(num_usb_devs);
267 if (!devs) {
268 libusb_free_device_list(usb_devs, 1);
269 log_err(ctx, "Device list malloc failed.");
270 return JAYLINK_ERR_MALLOC;
273 num_devs = 0;
275 for (i = 0; i < num_usb_devs; i++) {
276 dev = probe_device(ctx, usb_devs[i]);
278 if (dev) {
279 devs[num_devs] = dev;
280 num_devs++;
284 devs[num_devs] = NULL;
286 libusb_free_device_list(usb_devs, 1);
287 *list = devs;
289 log_dbg(ctx, "Found %zu device(s).", num_devs);
291 return num_devs;