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

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)