b82e3dae560b298ce388f6e7e08fd93cf17607f7
[fw/openocd] / 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 int cmsis_dap_usb_open(struct cmsis_dap *dap, uint16_t vids[], uint16_t pids[], char *serial)
54 {
55         int err;
56         libusb_context *ctx;
57         libusb_device **device_list;
58
59         err = libusb_init(&ctx);
60         if (err) {
61                 LOG_ERROR("libusb initialization failed: %s", libusb_strerror(err));
62                 return ERROR_FAIL;
63         }
64
65         int num_devices = libusb_get_device_list(ctx, &device_list);
66         if (num_devices < 0) {
67                 LOG_ERROR("could not enumerate USB devices: %s", libusb_strerror(num_devices));
68                 libusb_exit(ctx);
69                 return ERROR_FAIL;
70         }
71
72         for (int i = 0; i < num_devices; i++) {
73                 libusb_device *dev = device_list[i];
74                 struct libusb_device_descriptor dev_desc;
75
76                 err = libusb_get_device_descriptor(dev, &dev_desc);
77                 if (err) {
78                         LOG_ERROR("could not get device descriptor for device %d: %s", i, libusb_strerror(err));
79                         continue;
80                 }
81
82                 /* Match VID/PID */
83
84                 bool id_match = true; /* match if we don't enter the loop (no filter) */
85                 for (int id = 0; vids[id] || pids[id]; id++) {
86                         id_match = !vids[id] || dev_desc.idVendor == vids[id];
87                         id_match &= !pids[id] || dev_desc.idProduct == pids[id];
88
89                         if (id_match)
90                                 break;
91                 }
92
93                 if (!id_match)
94                         continue;
95
96                 /* Don't continue if we asked for a serial number and the device doesn't have one */
97                 if (dev_desc.iSerialNumber == 0 && serial && serial[0])
98                         continue;
99
100                 libusb_device_handle *dev_handle = NULL;
101                 err = libusb_open(dev, &dev_handle);
102                 if (err) {
103                         /* It's to be expected that most USB devices can't be opened
104                          * so only report an error if it was explicitly selected
105                          */
106                         if (vids[0] || pids[0]) {
107                                 LOG_ERROR("could not open device 0x%04x:0x%04x: %s",
108                                                 dev_desc.idVendor, dev_desc.idProduct, libusb_strerror(err));
109                         } else {
110                                 LOG_DEBUG("could not open device 0x%04x:0x%04x: %s",
111                                                 dev_desc.idVendor, dev_desc.idProduct, libusb_strerror(err));
112                         }
113                         continue;
114                 }
115
116                 /* Match serial number */
117
118                 bool serial_match = (serial == NULL);
119                 char dev_serial[256] = {0};
120                 if (dev_desc.iSerialNumber > 0) {
121                         err = libusb_get_string_descriptor_ascii(
122                                         dev_handle, dev_desc.iSerialNumber,
123                                         (uint8_t *)dev_serial, sizeof(dev_serial));
124
125                         if (err < 0) {
126                                 LOG_ERROR("could not read serial number for device 0x%04x:0x%04x: %s",
127                                                 dev_desc.idVendor, dev_desc.idProduct, 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_match) {
134                         libusb_close(dev_handle);
135                         continue;
136                 }
137
138                 /* Find the CMSIS-DAP string in product string */
139
140                 bool cmsis_dap_found = 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_ERROR("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("CMSIS-DAP found in product string");
151                                 cmsis_dap_found = true;
152                         }
153                 }
154
155                 /* Find the CMSIS-DAP interface */
156
157                 for (int config = 0; config < dev_desc.bNumConfigurations; config++) {
158                         struct libusb_config_descriptor *config_desc;
159                         err = libusb_get_config_descriptor(dev, config, &config_desc);
160                         if (err) {
161                                 LOG_ERROR("could not get configuration descriptor %d for device 0x%04x:0x%04x: %s",
162                                                 config, dev_desc.idVendor, dev_desc.idProduct, libusb_strerror(err));
163                                 continue;
164                         }
165
166                         int config_num = config_desc->bConfigurationValue;
167
168                         for (int interface = 0; interface < config_desc->bNumInterfaces; interface++) {
169                                 const struct libusb_interface_descriptor *intf_desc = &config_desc->interface[interface].altsetting[0];
170                                 int interface_num = intf_desc->bInterfaceNumber;
171
172                                 /* Skip this interface if another one was requested explicitly */
173                                 if (cmsis_dap_usb_interface != -1 && cmsis_dap_usb_interface != interface_num)
174                                         continue;
175
176                                 /* CMSIS-DAP v2 spec says:
177                                  *
178                                  * CMSIS-DAP with default V2 configuration uses WinUSB and is therefore faster.
179                                  * Optionally support for streaming SWO trace is provided via an additional USB endpoint.
180                                  *
181                                  * The WinUSB configuration requires custom class support with the interface setting
182                                  *     Class Code: 0xFF (Vendor specific)
183                                  *     Subclass: 0x00
184                                  *     Protocol code: 0x00
185                                  *
186                                  * Depending on the configuration it uses the following USB endpoints which should be configured
187                                  * in the interface descriptor in this order:
188                                  *  - Endpoint 1: Bulk Out – used for commands received from host PC.
189                                  *  - Endpoint 2: Bulk In – used for responses send to host PC.
190                                  *  - Endpoint 3: Bulk In (optional) – used for streaming SWO trace (if enabled with SWO_STREAM).
191                                  */
192
193                                 if (intf_desc->bNumEndpoints < 2)
194                                         continue;
195
196                                 if ((intf_desc->endpoint[0].bmAttributes & 3) != LIBUSB_TRANSFER_TYPE_BULK ||
197                                                 (intf_desc->endpoint[0].bEndpointAddress & 0x80) != LIBUSB_ENDPOINT_OUT)
198                                         continue;
199
200                                 if ((intf_desc->endpoint[1].bmAttributes & 3) != LIBUSB_TRANSFER_TYPE_BULK ||
201                                                 (intf_desc->endpoint[1].bEndpointAddress & 0x80) != LIBUSB_ENDPOINT_IN)
202                                         continue;
203
204                                 /* Bypass the following checks if this interface was explicitly requested. */
205                                 if (cmsis_dap_usb_interface == -1) {
206                                         if (intf_desc->bInterfaceClass != LIBUSB_CLASS_VENDOR_SPEC ||
207                                                         intf_desc->bInterfaceSubClass != 0 || intf_desc->bInterfaceProtocol != 0)
208                                                 continue;
209
210                                         /* Search for "CMSIS-DAP" in the interface string */
211                                         if (cmsis_dap_usb_interface != -1 && !cmsis_dap_found) {
212                                                 if (intf_desc->iInterface == 0)
213                                                         continue;
214
215                                                 char interface_str[256] = {0};
216
217                                                 err = libusb_get_string_descriptor_ascii(
218                                                                 dev_handle, intf_desc->iInterface,
219                                                                 (uint8_t *)interface_str, sizeof(interface_str));
220                                                 if (err < 0) {
221                                                         LOG_ERROR("could not read interface string for device 0x%04x:0x%04x: %s",
222                                                                         dev_desc.idVendor, dev_desc.idProduct, libusb_strerror(err));
223                                                         continue;
224                                                 } else if (!strstr(interface_str, "CMSIS-DAP")) {
225                                                         continue;
226                                                 } else {
227                                                         LOG_DEBUG("CMSIS-DAP found in interface string");
228                                                 }
229                                         }
230                                 }
231
232                                 int packet_size = intf_desc->endpoint[0].wMaxPacketSize;
233                                 int ep_out = intf_desc->endpoint[0].bEndpointAddress;
234                                 int ep_in = intf_desc->endpoint[1].bEndpointAddress;
235
236                                 /* That's the one! */
237                                 libusb_free_config_descriptor(config_desc);
238                                 libusb_free_device_list(device_list, true);
239
240                                 LOG_INFO("Using CMSIS-DAPv2 interface with VID:PID=0x%04x:0x%04x, serial=%s",
241                                                 dev_desc.idVendor, dev_desc.idProduct, dev_serial);
242
243                                 int current_config;
244                                 err = libusb_get_configuration(dev_handle, &current_config);
245                                 if (err) {
246                                         LOG_ERROR("could not find current configuration: %s", libusb_strerror(err));
247                                         libusb_close(dev_handle);
248                                         libusb_exit(ctx);
249                                         return ERROR_FAIL;
250                                 }
251
252                                 if (config_num != current_config) {
253                                         err = libusb_set_configuration(dev_handle, config_num);
254                                         if (err) {
255                                                 LOG_ERROR("could not set configuration: %s", libusb_strerror(err));
256                                                 libusb_close(dev_handle);
257                                                 libusb_exit(ctx);
258                                                 return ERROR_FAIL;
259                                         }
260                                 }
261
262                                 err = libusb_claim_interface(dev_handle, interface_num);
263                                 if (err)
264                                         LOG_WARNING("could not claim interface: %s", libusb_strerror(err));
265
266                                 dap->bdata = malloc(sizeof(struct cmsis_dap_backend_data));
267                                 if (dap->bdata == NULL) {
268                                         LOG_ERROR("unable to allocate memory");
269                                         libusb_release_interface(dev_handle, interface_num);
270                                         libusb_close(dev_handle);
271                                         libusb_exit(ctx);
272                                         return ERROR_FAIL;
273                                 }
274
275                                 dap->packet_size = packet_size + 1; /* "+ 1" for compatibility with the HID backend */
276                                 dap->bdata->usb_ctx = ctx;
277                                 dap->bdata->dev_handle = dev_handle;
278                                 dap->bdata->ep_out = ep_out;
279                                 dap->bdata->ep_in = ep_in;
280                                 dap->bdata->interface = interface_num;
281                                 return ERROR_OK;
282                         }
283
284                         libusb_free_config_descriptor(config_desc);
285                 }
286
287                 libusb_close(dev_handle);
288         }
289
290         libusb_free_device_list(device_list, true);
291
292         libusb_exit(ctx);
293         return ERROR_FAIL;
294 }
295
296 static void cmsis_dap_usb_close(struct cmsis_dap *dap)
297 {
298         libusb_release_interface(dap->bdata->dev_handle, dap->bdata->interface);
299         libusb_close(dap->bdata->dev_handle);
300         libusb_exit(dap->bdata->usb_ctx);
301         free(dap->bdata);
302         dap->bdata = NULL;
303 }
304
305 static int cmsis_dap_usb_read(struct cmsis_dap *dap, int timeout_ms)
306 {
307         int transferred = 0;
308         int err;
309
310         err = libusb_bulk_transfer(dap->bdata->dev_handle, dap->bdata->ep_in,
311                                                         dap->packet_buffer, dap->packet_size, &transferred, timeout_ms);
312         if (err) {
313                 if (err == LIBUSB_ERROR_TIMEOUT) {
314                         return ERROR_TIMEOUT_REACHED;
315                 } else {
316                         LOG_ERROR("error reading data: %s", libusb_strerror(err));
317                         return ERROR_FAIL;
318                 }
319         }
320
321         memset(&dap->packet_buffer[transferred], 0, dap->packet_size - transferred);
322
323         return transferred;
324 }
325
326 static int cmsis_dap_usb_write(struct cmsis_dap *dap, int txlen, int timeout_ms)
327 {
328         int transferred = 0;
329         int err;
330
331         /* skip the first byte that is only used by the HID backend */
332         err = libusb_bulk_transfer(dap->bdata->dev_handle, dap->bdata->ep_out,
333                                                         dap->packet_buffer + 1, txlen - 1, &transferred, timeout_ms);
334         if (err) {
335                 if (err == LIBUSB_ERROR_TIMEOUT) {
336                         return ERROR_TIMEOUT_REACHED;
337                 } else {
338                         LOG_ERROR("error writing data: %s", libusb_strerror(err));
339                         return ERROR_FAIL;
340                 }
341         }
342
343         return transferred;
344 }
345
346 COMMAND_HANDLER(cmsis_dap_handle_usb_interface_command)
347 {
348         if (CMD_ARGC == 1)
349                 cmsis_dap_usb_interface = strtoul(CMD_ARGV[0], NULL, 10);
350         else
351                 LOG_ERROR("expected exactly one argument to cmsis_dap_usb_interface <interface_number>");
352
353         return ERROR_OK;
354 }
355
356 const struct command_registration cmsis_dap_usb_subcommand_handlers[] = {
357         {
358                 .name = "interface",
359                 .handler = &cmsis_dap_handle_usb_interface_command,
360                 .mode = COMMAND_CONFIG,
361                 .help = "set the USB interface number to use (for USB bulk backend only)",
362                 .usage = "<interface_number>",
363         },
364         COMMAND_REGISTRATION_DONE
365 };
366
367 const struct cmsis_dap_backend cmsis_dap_usb_backend = {
368         .name = "usb_bulk",
369         .open = cmsis_dap_usb_open,
370         .close = cmsis_dap_usb_close,
371         .read = cmsis_dap_usb_read,
372         .write = cmsis_dap_usb_write,
373 };