openocd: src/jtag: replace the GPL-2.0-or-later license tag
[openocd.git] / src / jtag / drivers / cmsis_dap_usb_hid.c
blob605811d9523df91c37653cfff6a5fcd6b6cc5793
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
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 ***************************************************************************/
23 #ifdef HAVE_CONFIG_H
24 #include "config.h"
25 #endif
27 #include <string.h>
28 #include <hidapi.h>
29 #include <helper/log.h>
31 #include "cmsis_dap.h"
33 struct cmsis_dap_backend_data {
34 hid_device *dev_handle;
37 static void cmsis_dap_hid_close(struct cmsis_dap *dap);
38 static int cmsis_dap_hid_alloc(struct cmsis_dap *dap, unsigned int pkt_sz);
40 static int cmsis_dap_hid_open(struct cmsis_dap *dap, uint16_t vids[], uint16_t pids[], const char *serial)
42 hid_device *dev = NULL;
43 int i;
44 struct hid_device_info *devs, *cur_dev;
45 unsigned short target_vid, target_pid;
47 target_vid = 0;
48 target_pid = 0;
50 if (hid_init() != 0) {
51 LOG_ERROR("unable to open HIDAPI");
52 return ERROR_FAIL;
56 * The CMSIS-DAP specification stipulates:
57 * "The Product String must contain "CMSIS-DAP" somewhere in the string. This is used by the
58 * debuggers to identify a CMSIS-DAP compliant Debug Unit that is connected to a host computer."
60 devs = hid_enumerate(0x0, 0x0);
61 cur_dev = devs;
62 while (cur_dev) {
63 bool found = false;
65 if (vids[0] == 0) {
66 if (!cur_dev->product_string) {
67 LOG_DEBUG("Cannot read product string of device 0x%x:0x%x",
68 cur_dev->vendor_id, cur_dev->product_id);
69 } else if (wcsstr(cur_dev->product_string, L"CMSIS-DAP")) {
70 /* if the user hasn't specified VID:PID *and*
71 * product string contains "CMSIS-DAP", pick it
73 found = true;
75 } else {
76 /* otherwise, exhaustively compare against all VID:PID in list */
77 for (i = 0; vids[i] || pids[i]; i++) {
78 if ((vids[i] == cur_dev->vendor_id) && (pids[i] == cur_dev->product_id))
79 found = true;
83 /* LPC-LINK2 has cmsis-dap on interface 0 and other HID functions on other interfaces */
84 if (cur_dev->vendor_id == 0x1fc9 && cur_dev->product_id == 0x0090 && cur_dev->interface_number != 0)
85 found = false;
87 if (found) {
88 /* check serial number matches if given */
89 if (!serial)
90 break;
92 if (cur_dev->serial_number) {
93 size_t len = (strlen(serial) + 1) * sizeof(wchar_t);
94 wchar_t *wserial = malloc(len);
95 mbstowcs(wserial, serial, len);
97 if (wcscmp(wserial, cur_dev->serial_number) == 0) {
98 free(wserial);
99 break;
100 } else {
101 free(wserial);
102 wserial = NULL;
107 cur_dev = cur_dev->next;
110 if (cur_dev) {
111 target_vid = cur_dev->vendor_id;
112 target_pid = cur_dev->product_id;
115 if (target_vid == 0 && target_pid == 0) {
116 hid_free_enumeration(devs);
117 return ERROR_FAIL;
120 dap->bdata = malloc(sizeof(struct cmsis_dap_backend_data));
121 if (!dap->bdata) {
122 LOG_ERROR("unable to allocate memory");
123 return ERROR_FAIL;
126 dev = hid_open_path(cur_dev->path);
127 hid_free_enumeration(devs);
129 if (!dev) {
130 LOG_ERROR("unable to open CMSIS-DAP device 0x%x:0x%x", target_vid, target_pid);
131 return ERROR_FAIL;
134 /* allocate default packet buffer, may be changed later.
135 * currently with HIDAPI we have no way of getting the output report length
136 * without this info we cannot communicate with the adapter.
137 * For the moment we have to hard code the packet size */
139 unsigned int packet_size = 64;
141 /* atmel cmsis-dap uses 512 byte reports */
142 /* except when it doesn't e.g. with mEDBG on SAMD10 Xplained
143 * board */
144 /* TODO: HID report descriptor should be parsed instead of
145 * hardcoding a match by VID */
146 if (target_vid == 0x03eb && target_pid != 0x2145 && target_pid != 0x2175)
147 packet_size = 512;
149 dap->bdata->dev_handle = dev;
151 int retval = cmsis_dap_hid_alloc(dap, packet_size);
152 if (retval != ERROR_OK) {
153 cmsis_dap_hid_close(dap);
154 return ERROR_FAIL;
157 dap->command = dap->packet_buffer + REPORT_ID_SIZE;
158 dap->response = dap->packet_buffer;
159 return ERROR_OK;
162 static void cmsis_dap_hid_close(struct cmsis_dap *dap)
164 hid_close(dap->bdata->dev_handle);
165 hid_exit();
166 free(dap->bdata);
167 dap->bdata = NULL;
168 free(dap->packet_buffer);
169 dap->packet_buffer = NULL;
172 static int cmsis_dap_hid_read(struct cmsis_dap *dap, int timeout_ms)
174 int retval = hid_read_timeout(dap->bdata->dev_handle, dap->packet_buffer, dap->packet_buffer_size, timeout_ms);
176 if (retval == 0) {
177 return ERROR_TIMEOUT_REACHED;
178 } else if (retval == -1) {
179 LOG_ERROR("error reading data: %ls", hid_error(dap->bdata->dev_handle));
180 return ERROR_FAIL;
183 return retval;
186 static int cmsis_dap_hid_write(struct cmsis_dap *dap, int txlen, int timeout_ms)
188 (void) timeout_ms;
190 dap->packet_buffer[0] = 0; /* HID report number */
192 /* Pad the rest of the TX buffer with 0's */
193 memset(dap->command + txlen, 0, dap->packet_size - txlen);
195 /* write data to device */
196 int retval = hid_write(dap->bdata->dev_handle, dap->packet_buffer, dap->packet_buffer_size);
197 if (retval == -1) {
198 LOG_ERROR("error writing data: %ls", hid_error(dap->bdata->dev_handle));
199 return ERROR_FAIL;
202 return retval;
205 static int cmsis_dap_hid_alloc(struct cmsis_dap *dap, unsigned int pkt_sz)
207 unsigned int packet_buffer_size = pkt_sz + REPORT_ID_SIZE;
208 uint8_t *buf = malloc(packet_buffer_size);
209 if (!buf) {
210 LOG_ERROR("unable to allocate CMSIS-DAP packet buffer");
211 return ERROR_FAIL;
214 dap->packet_buffer = buf;
215 dap->packet_size = pkt_sz;
216 dap->packet_buffer_size = packet_buffer_size;
218 dap->command = dap->packet_buffer + REPORT_ID_SIZE;
219 dap->response = dap->packet_buffer;
221 return ERROR_OK;
224 const struct cmsis_dap_backend cmsis_dap_hid_backend = {
225 .name = "hid",
226 .open = cmsis_dap_hid_open,
227 .close = cmsis_dap_hid_close,
228 .read = cmsis_dap_hid_read,
229 .write = cmsis_dap_hid_write,
230 .packet_buffer_alloc = cmsis_dap_hid_alloc,