1 /***************************************************************************
2 * Copyright (C) 2018 by Mickaƫl Thomas *
5 * Copyright (C) 2016 by Maksym Hilliaka *
6 * oter@frozen-team.com *
8 * Copyright (C) 2016 by Phillip Pearson *
11 * Copyright (C) 2014 by Paul Fertser *
12 * fercerpav@gmail.com *
14 * Copyright (C) 2013 by mike brown *
15 * mike@theshedworks.org.uk *
17 * Copyright (C) 2013 by Spencer Oliver *
18 * spen@spen-soft.co.uk *
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. *
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. *
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 ***************************************************************************/
40 #include <helper/log.h>
42 #include "cmsis_dap.h"
44 struct cmsis_dap_backend_data {
45 hid_device *dev_handle;
48 static void cmsis_dap_hid_close(struct cmsis_dap *dap);
49 static int cmsis_dap_hid_alloc(struct cmsis_dap *dap, unsigned int pkt_sz);
51 static int cmsis_dap_hid_open(struct cmsis_dap *dap, uint16_t vids[], uint16_t pids[], const char *serial)
53 hid_device *dev = NULL;
55 struct hid_device_info *devs, *cur_dev;
56 unsigned short target_vid, target_pid;
61 if (hid_init() != 0) {
62 LOG_ERROR("unable to open HIDAPI");
67 * The CMSIS-DAP specification stipulates:
68 * "The Product String must contain "CMSIS-DAP" somewhere in the string. This is used by the
69 * debuggers to identify a CMSIS-DAP compliant Debug Unit that is connected to a host computer."
71 devs = hid_enumerate(0x0, 0x0);
77 if (!cur_dev->product_string) {
78 LOG_DEBUG("Cannot read product string of device 0x%x:0x%x",
79 cur_dev->vendor_id, cur_dev->product_id);
80 } else if (wcsstr(cur_dev->product_string, L"CMSIS-DAP")) {
81 /* if the user hasn't specified VID:PID *and*
82 * product string contains "CMSIS-DAP", pick it
87 /* otherwise, exhaustively compare against all VID:PID in list */
88 for (i = 0; vids[i] || pids[i]; i++) {
89 if ((vids[i] == cur_dev->vendor_id) && (pids[i] == cur_dev->product_id))
94 /* LPC-LINK2 has cmsis-dap on interface 0 and other HID functions on other interfaces */
95 if (cur_dev->vendor_id == 0x1fc9 && cur_dev->product_id == 0x0090 && cur_dev->interface_number != 0)
99 /* check serial number matches if given */
103 if (cur_dev->serial_number) {
104 size_t len = (strlen(serial) + 1) * sizeof(wchar_t);
105 wchar_t *wserial = malloc(len);
106 mbstowcs(wserial, serial, len);
108 if (wcscmp(wserial, cur_dev->serial_number) == 0) {
118 cur_dev = cur_dev->next;
122 target_vid = cur_dev->vendor_id;
123 target_pid = cur_dev->product_id;
126 if (target_vid == 0 && target_pid == 0) {
127 hid_free_enumeration(devs);
131 dap->bdata = malloc(sizeof(struct cmsis_dap_backend_data));
133 LOG_ERROR("unable to allocate memory");
137 dev = hid_open_path(cur_dev->path);
138 hid_free_enumeration(devs);
141 LOG_ERROR("unable to open CMSIS-DAP device 0x%x:0x%x", target_vid, target_pid);
145 /* allocate default packet buffer, may be changed later.
146 * currently with HIDAPI we have no way of getting the output report length
147 * without this info we cannot communicate with the adapter.
148 * For the moment we have to hard code the packet size */
150 unsigned int packet_size = 64;
152 /* atmel cmsis-dap uses 512 byte reports */
153 /* except when it doesn't e.g. with mEDBG on SAMD10 Xplained
155 /* TODO: HID report descriptor should be parsed instead of
156 * hardcoding a match by VID */
157 if (target_vid == 0x03eb && target_pid != 0x2145 && target_pid != 0x2175)
160 dap->bdata->dev_handle = dev;
162 int retval = cmsis_dap_hid_alloc(dap, packet_size);
163 if (retval != ERROR_OK) {
164 cmsis_dap_hid_close(dap);
168 dap->command = dap->packet_buffer + REPORT_ID_SIZE;
169 dap->response = dap->packet_buffer;
173 static void cmsis_dap_hid_close(struct cmsis_dap *dap)
175 hid_close(dap->bdata->dev_handle);
179 free(dap->packet_buffer);
180 dap->packet_buffer = NULL;
183 static int cmsis_dap_hid_read(struct cmsis_dap *dap, int timeout_ms)
185 int retval = hid_read_timeout(dap->bdata->dev_handle, dap->packet_buffer, dap->packet_buffer_size, timeout_ms);
188 return ERROR_TIMEOUT_REACHED;
189 } else if (retval == -1) {
190 LOG_ERROR("error reading data: %ls", hid_error(dap->bdata->dev_handle));
197 static int cmsis_dap_hid_write(struct cmsis_dap *dap, int txlen, int timeout_ms)
201 dap->packet_buffer[0] = 0; /* HID report number */
203 /* Pad the rest of the TX buffer with 0's */
204 memset(dap->command + txlen, 0, dap->packet_size - txlen);
206 /* write data to device */
207 int retval = hid_write(dap->bdata->dev_handle, dap->packet_buffer, dap->packet_buffer_size);
209 LOG_ERROR("error writing data: %ls", hid_error(dap->bdata->dev_handle));
216 static int cmsis_dap_hid_alloc(struct cmsis_dap *dap, unsigned int pkt_sz)
218 unsigned int packet_buffer_size = pkt_sz + REPORT_ID_SIZE;
219 uint8_t *buf = malloc(packet_buffer_size);
221 LOG_ERROR("unable to allocate CMSIS-DAP packet buffer");
225 dap->packet_buffer = buf;
226 dap->packet_size = pkt_sz;
227 dap->packet_buffer_size = packet_buffer_size;
229 dap->command = dap->packet_buffer + REPORT_ID_SIZE;
230 dap->response = dap->packet_buffer;
235 const struct cmsis_dap_backend cmsis_dap_hid_backend = {
237 .open = cmsis_dap_hid_open,
238 .close = cmsis_dap_hid_close,
239 .read = cmsis_dap_hid_read,
240 .write = cmsis_dap_hid_write,
241 .packet_buffer_alloc = cmsis_dap_hid_alloc,