jtag/mpsse: mpsse_flush should not treat LIBUSB_ERROR_INTERRUPTED as an error
[openocd.git] / src / jtag / drivers / cmsis_dap_usb_hid.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 <string.h>
28 #include <hidapi.h>
29 #include <helper/log.h>
30
31 #include "cmsis_dap.h"
32
33 struct cmsis_dap_backend_data {
34 hid_device *dev_handle;
35 };
36
37 struct cmsis_dap_report_size {
38 unsigned short vid;
39 unsigned short pid;
40 unsigned int report_size;
41 };
42
43 static const struct cmsis_dap_report_size report_size_quirks[] = {
44 /* Third gen Atmel tools use a report size of 512 */
45 /* This list of PIDs comes from toolinfo.py in Microchip's pyedbglib. */
46 // Atmel JTAG-ICE 3
47 { .vid = 0x03eb, .pid = 0x2140, .report_size = 512 },
48 // Atmel-ICE
49 { .vid = 0x03eb, .pid = 0x2141, .report_size = 512 },
50 // Atmel Power Debugger
51 { .vid = 0x03eb, .pid = 0x2144, .report_size = 512 },
52 // EDBG (found on Xplained Pro boards)
53 { .vid = 0x03eb, .pid = 0x2111, .report_size = 512 },
54 // Zero (???)
55 { .vid = 0x03eb, .pid = 0x2157, .report_size = 512 },
56 // EDBG with Mass Storage (found on Xplained Pro boards)
57 { .vid = 0x03eb, .pid = 0x2169, .report_size = 512 },
58 // Commercially available EDBG (for third-party use)
59 { .vid = 0x03eb, .pid = 0x216a, .report_size = 512 },
60 // Kraken (???)
61 { .vid = 0x03eb, .pid = 0x2170, .report_size = 512 },
62
63 { .vid = 0, .pid = 0, .report_size = 0 }
64 };
65
66
67 static void cmsis_dap_hid_close(struct cmsis_dap *dap);
68 static int cmsis_dap_hid_alloc(struct cmsis_dap *dap, unsigned int pkt_sz);
69 static void cmsis_dap_hid_free(struct cmsis_dap *dap);
70
71 static int cmsis_dap_hid_open(struct cmsis_dap *dap, uint16_t vids[], uint16_t pids[], const char *serial)
72 {
73 hid_device *dev = NULL;
74 int i;
75 struct hid_device_info *devs, *cur_dev;
76 unsigned short target_vid, target_pid;
77
78 target_vid = 0;
79 target_pid = 0;
80
81 if (hid_init() != 0) {
82 LOG_ERROR("unable to open HIDAPI");
83 return ERROR_FAIL;
84 }
85
86 /*
87 * The CMSIS-DAP specification stipulates:
88 * "The Product String must contain "CMSIS-DAP" somewhere in the string. This is used by the
89 * debuggers to identify a CMSIS-DAP compliant Debug Unit that is connected to a host computer."
90 */
91 devs = hid_enumerate(0x0, 0x0);
92 cur_dev = devs;
93 while (cur_dev) {
94 bool found = false;
95
96 if (vids[0] == 0) {
97 if (!cur_dev->product_string) {
98 LOG_DEBUG("Cannot read product string of device 0x%x:0x%x",
99 cur_dev->vendor_id, cur_dev->product_id);
100 } else if (wcsstr(cur_dev->product_string, L"CMSIS-DAP")) {
101 /* if the user hasn't specified VID:PID *and*
102 * product string contains "CMSIS-DAP", pick it
103 */
104 found = true;
105 }
106 } else {
107 /* otherwise, exhaustively compare against all VID:PID in list */
108 for (i = 0; vids[i] || pids[i]; i++) {
109 if ((vids[i] == cur_dev->vendor_id) && (pids[i] == cur_dev->product_id))
110 found = true;
111 }
112 }
113
114 /* LPC-LINK2 has cmsis-dap on interface 0 and other HID functions on other interfaces */
115 if (cur_dev->vendor_id == 0x1fc9 && cur_dev->product_id == 0x0090 && cur_dev->interface_number != 0)
116 found = false;
117
118 if (found) {
119 /* check serial number matches if given */
120 if (!serial)
121 break;
122
123 if (cur_dev->serial_number) {
124 size_t len = (strlen(serial) + 1) * sizeof(wchar_t);
125 wchar_t *wserial = malloc(len);
126 mbstowcs(wserial, serial, len);
127
128 if (wcscmp(wserial, cur_dev->serial_number) == 0) {
129 free(wserial);
130 break;
131 } else {
132 free(wserial);
133 wserial = NULL;
134 }
135 }
136 }
137
138 cur_dev = cur_dev->next;
139 }
140
141 if (cur_dev) {
142 target_vid = cur_dev->vendor_id;
143 target_pid = cur_dev->product_id;
144 }
145
146 if (target_vid == 0 && target_pid == 0) {
147 hid_free_enumeration(devs);
148 return ERROR_FAIL;
149 }
150
151 dap->bdata = malloc(sizeof(struct cmsis_dap_backend_data));
152 if (!dap->bdata) {
153 LOG_ERROR("unable to allocate memory");
154 return ERROR_FAIL;
155 }
156
157 dev = hid_open_path(cur_dev->path);
158 hid_free_enumeration(devs);
159
160 if (!dev) {
161 LOG_ERROR("unable to open CMSIS-DAP device 0x%x:0x%x", target_vid, target_pid);
162 return ERROR_FAIL;
163 }
164
165 /* allocate default packet buffer, may be changed later.
166 * currently with HIDAPI we have no way of getting the output report length
167 * without this info we cannot communicate with the adapter.
168 * For the moment we have to hard code the packet size */
169
170 unsigned int packet_size = 64;
171
172 /* Check for adapters that are known to have unusual report lengths. */
173 for (i = 0; report_size_quirks[i].vid != 0; i++) {
174 if (report_size_quirks[i].vid == target_vid &&
175 report_size_quirks[i].pid == target_pid) {
176 packet_size = report_size_quirks[i].report_size;
177 }
178 }
179 /* TODO: HID report descriptor should be parsed instead of
180 * hardcoding a match by VID/PID */
181
182 dap->bdata->dev_handle = dev;
183
184 int retval = cmsis_dap_hid_alloc(dap, packet_size);
185 if (retval != ERROR_OK) {
186 cmsis_dap_hid_close(dap);
187 return ERROR_FAIL;
188 }
189
190 dap->command = dap->packet_buffer + REPORT_ID_SIZE;
191 dap->response = dap->packet_buffer;
192 return ERROR_OK;
193 }
194
195 static void cmsis_dap_hid_close(struct cmsis_dap *dap)
196 {
197 hid_close(dap->bdata->dev_handle);
198 hid_exit();
199 free(dap->bdata);
200 dap->bdata = NULL;
201 cmsis_dap_hid_free(dap);
202 }
203
204 static int cmsis_dap_hid_read(struct cmsis_dap *dap, int transfer_timeout_ms,
205 struct timeval *wait_timeout)
206 {
207 int timeout_ms;
208 if (wait_timeout)
209 timeout_ms = wait_timeout->tv_usec / 1000 + wait_timeout->tv_sec * 1000;
210 else
211 timeout_ms = transfer_timeout_ms;
212
213 int retval = hid_read_timeout(dap->bdata->dev_handle,
214 dap->packet_buffer, dap->packet_buffer_size,
215 timeout_ms);
216 if (retval == 0) {
217 return ERROR_TIMEOUT_REACHED;
218 } else if (retval == -1) {
219 LOG_ERROR("error reading data: %ls", hid_error(dap->bdata->dev_handle));
220 return ERROR_FAIL;
221 }
222
223 return retval;
224 }
225
226 static int cmsis_dap_hid_write(struct cmsis_dap *dap, int txlen, int timeout_ms)
227 {
228 (void) timeout_ms;
229
230 dap->packet_buffer[0] = 0; /* HID report number */
231
232 /* Pad the rest of the TX buffer with 0's */
233 memset(dap->command + txlen, 0, dap->packet_size - txlen);
234
235 /* write data to device */
236 int retval = hid_write(dap->bdata->dev_handle, dap->packet_buffer, dap->packet_buffer_size);
237 if (retval == -1) {
238 LOG_ERROR("error writing data: %ls", hid_error(dap->bdata->dev_handle));
239 return ERROR_FAIL;
240 }
241
242 return retval;
243 }
244
245 static int cmsis_dap_hid_alloc(struct cmsis_dap *dap, unsigned int pkt_sz)
246 {
247 unsigned int packet_buffer_size = pkt_sz + REPORT_ID_SIZE;
248 uint8_t *buf = malloc(packet_buffer_size);
249 if (!buf) {
250 LOG_ERROR("unable to allocate CMSIS-DAP packet buffer");
251 return ERROR_FAIL;
252 }
253
254 dap->packet_buffer = buf;
255 dap->packet_size = pkt_sz;
256 dap->packet_usable_size = pkt_sz;
257 dap->packet_buffer_size = packet_buffer_size;
258
259 dap->command = dap->packet_buffer + REPORT_ID_SIZE;
260 dap->response = dap->packet_buffer;
261
262 return ERROR_OK;
263 }
264
265 static void cmsis_dap_hid_free(struct cmsis_dap *dap)
266 {
267 free(dap->packet_buffer);
268 dap->packet_buffer = NULL;
269 }
270
271 static void cmsis_dap_hid_cancel_all(struct cmsis_dap *dap)
272 {
273 }
274
275 const struct cmsis_dap_backend cmsis_dap_hid_backend = {
276 .name = "hid",
277 .open = cmsis_dap_hid_open,
278 .close = cmsis_dap_hid_close,
279 .read = cmsis_dap_hid_read,
280 .write = cmsis_dap_hid_write,
281 .packet_buffer_alloc = cmsis_dap_hid_alloc,
282 .packet_buffer_free = cmsis_dap_hid_free,
283 .cancel_all = cmsis_dap_hid_cancel_all,
284 };

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)