openocd: src/jtag: replace the GPL-2.0-or-later license tag
[openocd.git] / src / jtag / drivers / cmsis_dap_usb_bulk.c
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2
3 /***************************************************************************
4 * Copyright (C) 2018 by Mickaƫl Thomas *
5 * mickael9@gmail.com *
6 * *
7 * Copyright (C) 2016 by Maksym Hilliaka *
8 * oter@frozen-team.com *
9 * *
10 * Copyright (C) 2016 by Phillip Pearson *
11 * pp@myelin.co.nz *
12 * *
13 * Copyright (C) 2014 by Paul Fertser *
14 * fercerpav@gmail.com *
15 * *
16 * Copyright (C) 2013 by mike brown *
17 * mike@theshedworks.org.uk *
18 * *
19 * Copyright (C) 2013 by Spencer Oliver *
20 * spen@spen-soft.co.uk *
21 ***************************************************************************/
22
23 #ifdef HAVE_CONFIG_H
24 #include "config.h"
25 #endif
26
27 #include <helper/system.h>
28 #include <libusb.h>
29 #include <helper/log.h>
30 #include <helper/replacements.h>
31
32 #include "cmsis_dap.h"
33
34 struct cmsis_dap_backend_data {
35 struct libusb_context *usb_ctx;
36 struct libusb_device_handle *dev_handle;
37 unsigned int ep_out;
38 unsigned int ep_in;
39 int interface;
40 };
41
42 static int cmsis_dap_usb_interface = -1;
43
44 static void cmsis_dap_usb_close(struct cmsis_dap *dap);
45 static int cmsis_dap_usb_alloc(struct cmsis_dap *dap, unsigned int pkt_sz);
46
47 static int cmsis_dap_usb_open(struct cmsis_dap *dap, uint16_t vids[], uint16_t pids[], const char *serial)
48 {
49 int err;
50 struct libusb_context *ctx;
51 struct libusb_device **device_list;
52
53 err = libusb_init(&ctx);
54 if (err) {
55 LOG_ERROR("libusb initialization failed: %s", libusb_strerror(err));
56 return ERROR_FAIL;
57 }
58
59 int num_devices = libusb_get_device_list(ctx, &device_list);
60 if (num_devices < 0) {
61 LOG_ERROR("could not enumerate USB devices: %s", libusb_strerror(num_devices));
62 libusb_exit(ctx);
63 return ERROR_FAIL;
64 }
65
66 for (int i = 0; i < num_devices; i++) {
67 struct libusb_device *dev = device_list[i];
68 struct libusb_device_descriptor dev_desc;
69
70 err = libusb_get_device_descriptor(dev, &dev_desc);
71 if (err) {
72 LOG_ERROR("could not get device descriptor for device %d: %s", i, libusb_strerror(err));
73 continue;
74 }
75
76 /* Match VID/PID */
77
78 bool id_match = false;
79 bool id_filter = vids[0] || pids[0];
80 for (int id = 0; vids[id] || pids[id]; id++) {
81 id_match = !vids[id] || dev_desc.idVendor == vids[id];
82 id_match &= !pids[id] || dev_desc.idProduct == pids[id];
83
84 if (id_match)
85 break;
86 }
87
88 if (id_filter && !id_match)
89 continue;
90
91 /* Don't continue if we asked for a serial number and the device doesn't have one */
92 if (dev_desc.iSerialNumber == 0 && serial && serial[0])
93 continue;
94
95 struct libusb_device_handle *dev_handle = NULL;
96 err = libusb_open(dev, &dev_handle);
97 if (err) {
98 /* It's to be expected that most USB devices can't be opened
99 * so only report an error if it was explicitly selected
100 */
101 if (id_filter) {
102 LOG_ERROR("could not open device 0x%04x:0x%04x: %s",
103 dev_desc.idVendor, dev_desc.idProduct, libusb_strerror(err));
104 } else {
105 LOG_DEBUG("could not open device 0x%04x:0x%04x: %s",
106 dev_desc.idVendor, dev_desc.idProduct, libusb_strerror(err));
107 }
108 continue;
109 }
110
111 /* Match serial number */
112
113 bool serial_match = false;
114 char dev_serial[256] = {0};
115 if (dev_desc.iSerialNumber > 0) {
116 err = libusb_get_string_descriptor_ascii(
117 dev_handle, dev_desc.iSerialNumber,
118 (uint8_t *)dev_serial, sizeof(dev_serial));
119
120 if (err < 0) {
121 const char *msg = "could not read serial number for device 0x%04x:0x%04x: %s";
122 if (serial)
123 LOG_WARNING(msg, dev_desc.idVendor, dev_desc.idProduct,
124 libusb_strerror(err));
125 else
126 LOG_DEBUG(msg, dev_desc.idVendor, dev_desc.idProduct,
127 libusb_strerror(err));
128 } else if (serial && strncmp(dev_serial, serial, sizeof(dev_serial)) == 0) {
129 serial_match = true;
130 }
131 }
132
133 if (serial && !serial_match) {
134 libusb_close(dev_handle);
135 continue;
136 }
137
138 /* Find the CMSIS-DAP string in product string */
139
140 bool cmsis_dap_in_product_str = false;
141 char product_string[256] = {0};
142 if (dev_desc.iProduct > 0) {
143 err = libusb_get_string_descriptor_ascii(
144 dev_handle, dev_desc.iProduct,
145 (uint8_t *)product_string, sizeof(product_string));
146 if (err < 0) {
147 LOG_WARNING("could not read product string for device 0x%04x:0x%04x: %s",
148 dev_desc.idVendor, dev_desc.idProduct, libusb_strerror(err));
149 } else if (strstr(product_string, "CMSIS-DAP")) {
150 LOG_DEBUG("found product string of 0x%04x:0x%04x '%s'",
151 dev_desc.idVendor, dev_desc.idProduct, product_string);
152 cmsis_dap_in_product_str = true;
153 }
154 }
155
156 bool device_identified_reliably = cmsis_dap_in_product_str
157 || serial_match || id_match;
158
159 /* Find the CMSIS-DAP interface */
160
161 for (int config = 0; config < dev_desc.bNumConfigurations; config++) {
162 struct libusb_config_descriptor *config_desc;
163 err = libusb_get_config_descriptor(dev, config, &config_desc);
164 if (err) {
165 LOG_ERROR("could not get configuration descriptor %d for device 0x%04x:0x%04x: %s",
166 config, dev_desc.idVendor, dev_desc.idProduct, libusb_strerror(err));
167 continue;
168 }
169
170 LOG_DEBUG("enumerating interfaces of 0x%04x:0x%04x",
171 dev_desc.idVendor, dev_desc.idProduct);
172 int config_num = config_desc->bConfigurationValue;
173 const struct libusb_interface_descriptor *intf_desc_candidate = NULL;
174 const struct libusb_interface_descriptor *intf_desc_found = NULL;
175
176 for (int interface = 0; interface < config_desc->bNumInterfaces; interface++) {
177 const struct libusb_interface_descriptor *intf_desc = &config_desc->interface[interface].altsetting[0];
178 int interface_num = intf_desc->bInterfaceNumber;
179
180 /* Skip this interface if another one was requested explicitly */
181 if (cmsis_dap_usb_interface != -1 && cmsis_dap_usb_interface != interface_num)
182 continue;
183
184 /* CMSIS-DAP v2 spec says:
185 *
186 * CMSIS-DAP with default V2 configuration uses WinUSB and is therefore faster.
187 * Optionally support for streaming SWO trace is provided via an additional USB endpoint.
188 *
189 * The WinUSB configuration requires custom class support with the interface setting
190 * Class Code: 0xFF (Vendor specific)
191 * Subclass: 0x00
192 * Protocol code: 0x00
193 *
194 * Depending on the configuration it uses the following USB endpoints which should be configured
195 * in the interface descriptor in this order:
196 * - Endpoint 1: Bulk Out ā€“ used for commands received from host PC.
197 * - Endpoint 2: Bulk In ā€“ used for responses send to host PC.
198 * - Endpoint 3: Bulk In (optional) ā€“ used for streaming SWO trace (if enabled with SWO_STREAM).
199 */
200
201 /* Search for "CMSIS-DAP" in the interface string */
202 bool cmsis_dap_in_interface_str = false;
203 if (intf_desc->iInterface != 0) {
204
205 char interface_str[256] = {0};
206
207 err = libusb_get_string_descriptor_ascii(
208 dev_handle, intf_desc->iInterface,
209 (uint8_t *)interface_str, sizeof(interface_str));
210 if (err < 0) {
211 LOG_DEBUG("could not read interface string %d for device 0x%04x:0x%04x: %s",
212 intf_desc->iInterface,
213 dev_desc.idVendor, dev_desc.idProduct,
214 libusb_strerror(err));
215 } else if (strstr(interface_str, "CMSIS-DAP")) {
216 cmsis_dap_in_interface_str = true;
217 LOG_DEBUG("found interface %d string '%s'",
218 interface_num, interface_str);
219 }
220 }
221
222 /* Bypass the following check if this interface was explicitly requested. */
223 if (cmsis_dap_usb_interface == -1) {
224 if (!cmsis_dap_in_product_str && !cmsis_dap_in_interface_str)
225 continue;
226 }
227
228 /* check endpoints */
229 if (intf_desc->bNumEndpoints < 2) {
230 LOG_DEBUG("skipping interface %d, has only %d endpoints",
231 interface_num, intf_desc->bNumEndpoints);
232 continue;
233 }
234
235 if ((intf_desc->endpoint[0].bmAttributes & 3) != LIBUSB_TRANSFER_TYPE_BULK ||
236 (intf_desc->endpoint[0].bEndpointAddress & 0x80) != LIBUSB_ENDPOINT_OUT) {
237 LOG_DEBUG("skipping interface %d, endpoint[0] is not bulk out",
238 interface_num);
239 continue;
240 }
241
242 if ((intf_desc->endpoint[1].bmAttributes & 3) != LIBUSB_TRANSFER_TYPE_BULK ||
243 (intf_desc->endpoint[1].bEndpointAddress & 0x80) != LIBUSB_ENDPOINT_IN) {
244 LOG_DEBUG("skipping interface %d, endpoint[1] is not bulk in",
245 interface_num);
246 continue;
247 }
248
249 /* We can rely on the interface is really CMSIS-DAP if
250 * - we've seen CMSIS-DAP in the interface string
251 * - config asked explicitly for an interface number
252 * - the device has only one interface
253 * The later two cases should be honored only if we know
254 * we are on the right device */
255 bool intf_identified_reliably = cmsis_dap_in_interface_str
256 || (device_identified_reliably &&
257 (cmsis_dap_usb_interface != -1
258 || config_desc->bNumInterfaces == 1));
259
260 if (intf_desc->bInterfaceClass != LIBUSB_CLASS_VENDOR_SPEC ||
261 intf_desc->bInterfaceSubClass != 0 || intf_desc->bInterfaceProtocol != 0) {
262 /* If the interface is reliably identified
263 * then we need not insist on setting USB class, subclass and protocol
264 * exactly as the specification requires.
265 * At least KitProg3 uses class 0 contrary to the specification */
266 if (intf_identified_reliably) {
267 LOG_WARNING("Using CMSIS-DAPv2 interface %d with wrong class %" PRId8
268 " subclass %" PRId8 " or protocol %" PRId8,
269 interface_num,
270 intf_desc->bInterfaceClass,
271 intf_desc->bInterfaceSubClass,
272 intf_desc->bInterfaceProtocol);
273 } else {
274 LOG_DEBUG("skipping interface %d, class %" PRId8
275 " subclass %" PRId8 " protocol %" PRId8,
276 interface_num,
277 intf_desc->bInterfaceClass,
278 intf_desc->bInterfaceSubClass,
279 intf_desc->bInterfaceProtocol);
280 continue;
281
282 }
283 }
284
285 if (intf_identified_reliably) {
286 /* That's the one! */
287 intf_desc_found = intf_desc;
288 break;
289 }
290
291 if (!intf_desc_candidate && device_identified_reliably) {
292 /* This interface looks suitable for CMSIS-DAP. Store the pointer to it
293 * and keep searching for another one with CMSIS-DAP in interface string */
294 intf_desc_candidate = intf_desc;
295 }
296 }
297
298 if (!intf_desc_found) {
299 /* We were not able to identify reliably which interface is CMSIS-DAP.
300 * Let's use the first suitable if we found one */
301 intf_desc_found = intf_desc_candidate;
302 }
303
304 if (!intf_desc_found) {
305 libusb_free_config_descriptor(config_desc);
306 continue;
307 }
308
309 /* We've chosen an interface, connect to it */
310 int interface_num = intf_desc_found->bInterfaceNumber;
311 int packet_size = intf_desc_found->endpoint[0].wMaxPacketSize;
312 int ep_out = intf_desc_found->endpoint[0].bEndpointAddress;
313 int ep_in = intf_desc_found->endpoint[1].bEndpointAddress;
314
315 libusb_free_config_descriptor(config_desc);
316 libusb_free_device_list(device_list, true);
317
318 LOG_INFO("Using CMSIS-DAPv2 interface with VID:PID=0x%04x:0x%04x, serial=%s",
319 dev_desc.idVendor, dev_desc.idProduct, dev_serial);
320
321 int current_config;
322 err = libusb_get_configuration(dev_handle, &current_config);
323 if (err) {
324 LOG_ERROR("could not find current configuration: %s", libusb_strerror(err));
325 libusb_close(dev_handle);
326 libusb_exit(ctx);
327 return ERROR_FAIL;
328 }
329
330 if (config_num != current_config) {
331 err = libusb_set_configuration(dev_handle, config_num);
332 if (err) {
333 LOG_ERROR("could not set configuration: %s", libusb_strerror(err));
334 libusb_close(dev_handle);
335 libusb_exit(ctx);
336 return ERROR_FAIL;
337 }
338 }
339
340 err = libusb_claim_interface(dev_handle, interface_num);
341 if (err)
342 LOG_WARNING("could not claim interface: %s", libusb_strerror(err));
343
344 dap->bdata = malloc(sizeof(struct cmsis_dap_backend_data));
345 if (!dap->bdata) {
346 LOG_ERROR("unable to allocate memory");
347 libusb_release_interface(dev_handle, interface_num);
348 libusb_close(dev_handle);
349 libusb_exit(ctx);
350 return ERROR_FAIL;
351 }
352
353 dap->packet_size = packet_size;
354 dap->packet_buffer_size = packet_size;
355 dap->bdata->usb_ctx = ctx;
356 dap->bdata->dev_handle = dev_handle;
357 dap->bdata->ep_out = ep_out;
358 dap->bdata->ep_in = ep_in;
359 dap->bdata->interface = interface_num;
360
361 dap->packet_buffer = malloc(dap->packet_buffer_size);
362 if (!dap->packet_buffer) {
363 LOG_ERROR("unable to allocate memory");
364 cmsis_dap_usb_close(dap);
365 return ERROR_FAIL;
366 }
367
368 dap->command = dap->packet_buffer;
369 dap->response = dap->packet_buffer;
370
371 return ERROR_OK;
372 }
373
374 libusb_close(dev_handle);
375 }
376
377 libusb_free_device_list(device_list, true);
378
379 libusb_exit(ctx);
380 return ERROR_FAIL;
381 }
382
383 static void cmsis_dap_usb_close(struct cmsis_dap *dap)
384 {
385 libusb_release_interface(dap->bdata->dev_handle, dap->bdata->interface);
386 libusb_close(dap->bdata->dev_handle);
387 libusb_exit(dap->bdata->usb_ctx);
388 free(dap->bdata);
389 dap->bdata = NULL;
390 free(dap->packet_buffer);
391 dap->packet_buffer = NULL;
392 }
393
394 static int cmsis_dap_usb_read(struct cmsis_dap *dap, int timeout_ms)
395 {
396 int transferred = 0;
397 int err;
398
399 err = libusb_bulk_transfer(dap->bdata->dev_handle, dap->bdata->ep_in,
400 dap->packet_buffer, dap->packet_size, &transferred, timeout_ms);
401 if (err) {
402 if (err == LIBUSB_ERROR_TIMEOUT) {
403 return ERROR_TIMEOUT_REACHED;
404 } else {
405 LOG_ERROR("error reading data: %s", libusb_strerror(err));
406 return ERROR_FAIL;
407 }
408 }
409
410 memset(&dap->packet_buffer[transferred], 0, dap->packet_buffer_size - transferred);
411
412 return transferred;
413 }
414
415 static int cmsis_dap_usb_write(struct cmsis_dap *dap, int txlen, int timeout_ms)
416 {
417 int transferred = 0;
418 int err;
419
420 /* skip the first byte that is only used by the HID backend */
421 err = libusb_bulk_transfer(dap->bdata->dev_handle, dap->bdata->ep_out,
422 dap->packet_buffer, txlen, &transferred, timeout_ms);
423 if (err) {
424 if (err == LIBUSB_ERROR_TIMEOUT) {
425 return ERROR_TIMEOUT_REACHED;
426 } else {
427 LOG_ERROR("error writing data: %s", libusb_strerror(err));
428 return ERROR_FAIL;
429 }
430 }
431
432 return transferred;
433 }
434
435 static int cmsis_dap_usb_alloc(struct cmsis_dap *dap, unsigned int pkt_sz)
436 {
437 uint8_t *buf = malloc(pkt_sz);
438 if (!buf) {
439 LOG_ERROR("unable to allocate CMSIS-DAP packet buffer");
440 return ERROR_FAIL;
441 }
442
443 dap->packet_buffer = buf;
444 dap->packet_size = pkt_sz;
445 dap->packet_buffer_size = pkt_sz;
446
447 dap->command = dap->packet_buffer;
448 dap->response = dap->packet_buffer;
449
450 return ERROR_OK;
451 }
452
453 COMMAND_HANDLER(cmsis_dap_handle_usb_interface_command)
454 {
455 if (CMD_ARGC == 1)
456 COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], cmsis_dap_usb_interface);
457 else
458 LOG_ERROR("expected exactly one argument to cmsis_dap_usb_interface <interface_number>");
459
460 return ERROR_OK;
461 }
462
463 const struct command_registration cmsis_dap_usb_subcommand_handlers[] = {
464 {
465 .name = "interface",
466 .handler = &cmsis_dap_handle_usb_interface_command,
467 .mode = COMMAND_CONFIG,
468 .help = "set the USB interface number to use (for USB bulk backend only)",
469 .usage = "<interface_number>",
470 },
471 COMMAND_REGISTRATION_DONE
472 };
473
474 const struct cmsis_dap_backend cmsis_dap_usb_backend = {
475 .name = "usb_bulk",
476 .open = cmsis_dap_usb_open,
477 .close = cmsis_dap_usb_close,
478 .read = cmsis_dap_usb_read,
479 .write = cmsis_dap_usb_write,
480 .packet_buffer_alloc = cmsis_dap_usb_alloc,
481 };

Linking to existing account procedure

If you already have an account and want to add another login method you MUST first sign in with your existing account and then change URL to read https://review.openocd.org/login/?link to get to this page again but this time it'll work for linking. Thank you.

SSH host keys fingerprints

1024 SHA256:YKx8b7u5ZWdcbp7/4AeXNaqElP49m6QrwfXaqQGJAOk gerrit-code-review@openocd.zylin.com (DSA)
384 SHA256:jHIbSQa4REvwCFG4cq5LBlBLxmxSqelQPem/EXIrxjk gerrit-code-review@openocd.org (ECDSA)
521 SHA256:UAOPYkU9Fjtcao0Ul/Rrlnj/OsQvt+pgdYSZ4jOYdgs gerrit-code-review@openocd.org (ECDSA)
256 SHA256:A13M5QlnozFOvTllybRZH6vm7iSt0XLxbA48yfc2yfY gerrit-code-review@openocd.org (ECDSA)
256 SHA256:spYMBqEYoAOtK7yZBrcwE8ZpYt6b68Cfh9yEVetvbXg gerrit-code-review@openocd.org (ED25519)
+--[ED25519 256]--+
|=..              |
|+o..   .         |
|*.o   . .        |
|+B . . .         |
|Bo. = o S        |
|Oo.+ + =         |
|oB=.* = . o      |
| =+=.+   + E     |
|. .=o   . o      |
+----[SHA256]-----+
2048 SHA256:0Onrb7/PHjpo6iVZ7xQX2riKN83FJ3KGU0TvI0TaFG4 gerrit-code-review@openocd.zylin.com (RSA)