1 /* SPDX-License-Identifier: GPL-2.0-or-later */
3 /***************************************************************************
4 * Copyright (C) 2018 by Mickaƫl Thomas *
7 * Copyright (C) 2016 by Maksym Hilliaka *
8 * oter@frozen-team.com *
10 * Copyright (C) 2016 by Phillip Pearson *
13 * Copyright (C) 2014 by Paul Fertser *
14 * fercerpav@gmail.com *
16 * Copyright (C) 2013 by mike brown *
17 * mike@theshedworks.org.uk *
19 * Copyright (C) 2013 by Spencer Oliver *
20 * spen@spen-soft.co.uk *
21 ***************************************************************************/
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
;
44 struct hid_device_info
*devs
, *cur_dev
;
45 unsigned short target_vid
, target_pid
;
50 if (hid_init() != 0) {
51 LOG_ERROR("unable to open HIDAPI");
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);
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
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
))
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)
88 /* check serial number matches if given */
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) {
107 cur_dev
= cur_dev
->next
;
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
);
120 dap
->bdata
= malloc(sizeof(struct cmsis_dap_backend_data
));
122 LOG_ERROR("unable to allocate memory");
126 dev
= hid_open_path(cur_dev
->path
);
127 hid_free_enumeration(devs
);
130 LOG_ERROR("unable to open CMSIS-DAP device 0x%x:0x%x", target_vid
, target_pid
);
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
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)
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
);
157 dap
->command
= dap
->packet_buffer
+ REPORT_ID_SIZE
;
158 dap
->response
= dap
->packet_buffer
;
162 static void cmsis_dap_hid_close(struct cmsis_dap
*dap
)
164 hid_close(dap
->bdata
->dev_handle
);
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
);
177 return ERROR_TIMEOUT_REACHED
;
178 } else if (retval
== -1) {
179 LOG_ERROR("error reading data: %ls", hid_error(dap
->bdata
->dev_handle
));
186 static int cmsis_dap_hid_write(struct cmsis_dap
*dap
, int txlen
, int 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
);
198 LOG_ERROR("error writing data: %ls", hid_error(dap
->bdata
->dev_handle
));
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
);
210 LOG_ERROR("unable to allocate CMSIS-DAP packet buffer");
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
;
224 const struct cmsis_dap_backend cmsis_dap_hid_backend
= {
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
,