OpenOCD
cmsis_dap_usb_hid.c
Go to the documentation of this file.
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 
34  hid_device *dev_handle;
35 };
36 
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);
39 
40 static int cmsis_dap_hid_open(struct cmsis_dap *dap, uint16_t vids[], uint16_t pids[], const char *serial)
41 {
42  hid_device *dev = NULL;
43  int i;
44  struct hid_device_info *devs, *cur_dev;
45  unsigned short target_vid, target_pid;
46 
47  target_vid = 0;
48  target_pid = 0;
49 
50  if (hid_init() != 0) {
51  LOG_ERROR("unable to open HIDAPI");
52  return ERROR_FAIL;
53  }
54 
55  /*
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."
59  */
60  devs = hid_enumerate(0x0, 0x0);
61  cur_dev = devs;
62  while (cur_dev) {
63  bool found = false;
64 
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
72  */
73  found = true;
74  }
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;
80  }
81  }
82 
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;
86 
87  if (found) {
88  /* check serial number matches if given */
89  if (!serial)
90  break;
91 
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);
96 
97  if (wcscmp(wserial, cur_dev->serial_number) == 0) {
98  free(wserial);
99  break;
100  } else {
101  free(wserial);
102  wserial = NULL;
103  }
104  }
105  }
106 
107  cur_dev = cur_dev->next;
108  }
109 
110  if (cur_dev) {
111  target_vid = cur_dev->vendor_id;
112  target_pid = cur_dev->product_id;
113  }
114 
115  if (target_vid == 0 && target_pid == 0) {
116  hid_free_enumeration(devs);
117  return ERROR_FAIL;
118  }
119 
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;
124  }
125 
126  dev = hid_open_path(cur_dev->path);
127  hid_free_enumeration(devs);
128 
129  if (!dev) {
130  LOG_ERROR("unable to open CMSIS-DAP device 0x%x:0x%x", target_vid, target_pid);
131  return ERROR_FAIL;
132  }
133 
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 */
138 
139  unsigned int packet_size = 64;
140 
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;
148 
149  dap->bdata->dev_handle = dev;
150 
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;
155  }
156 
157  dap->command = dap->packet_buffer + REPORT_ID_SIZE;
158  dap->response = dap->packet_buffer;
159  return ERROR_OK;
160 }
161 
162 static void cmsis_dap_hid_close(struct cmsis_dap *dap)
163 {
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;
170 }
171 
172 static int cmsis_dap_hid_read(struct cmsis_dap *dap, int timeout_ms)
173 {
174  int retval = hid_read_timeout(dap->bdata->dev_handle, dap->packet_buffer, dap->packet_buffer_size, timeout_ms);
175 
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;
181  }
182 
183  return retval;
184 }
185 
186 static int cmsis_dap_hid_write(struct cmsis_dap *dap, int txlen, int timeout_ms)
187 {
188  (void) timeout_ms;
189 
190  dap->packet_buffer[0] = 0; /* HID report number */
191 
192  /* Pad the rest of the TX buffer with 0's */
193  memset(dap->command + txlen, 0, dap->packet_size - txlen);
194 
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;
200  }
201 
202  return retval;
203 }
204 
205 static int cmsis_dap_hid_alloc(struct cmsis_dap *dap, unsigned int pkt_sz)
206 {
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;
212  }
213 
214  dap->packet_buffer = buf;
215  dap->packet_size = pkt_sz;
216  dap->packet_buffer_size = packet_buffer_size;
217 
218  dap->command = dap->packet_buffer + REPORT_ID_SIZE;
219  dap->response = dap->packet_buffer;
220 
221  return ERROR_OK;
222 }
223 
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,
231 };
char * serial
Definition: adapter.c:47
#define REPORT_ID_SIZE
Definition: cmsis_dap.h:40
static int cmsis_dap_hid_alloc(struct cmsis_dap *dap, unsigned int pkt_sz)
static int cmsis_dap_hid_open(struct cmsis_dap *dap, uint16_t vids[], uint16_t pids[], const char *serial)
static void cmsis_dap_hid_close(struct cmsis_dap *dap)
static int cmsis_dap_hid_read(struct cmsis_dap *dap, int timeout_ms)
const struct cmsis_dap_backend cmsis_dap_hid_backend
static int cmsis_dap_hid_write(struct cmsis_dap *dap, int txlen, int timeout_ms)
static struct libusb_device ** devs
The usb device list.
Definition: libusb_helper.c:26
#define ERROR_FAIL
Definition: log.h:161
#define LOG_ERROR(expr ...)
Definition: log.h:123
#define ERROR_TIMEOUT_REACHED
Definition: log.h:164
#define LOG_DEBUG(expr ...)
Definition: log.h:109
#define ERROR_OK
Definition: log.h:155
struct libusb_device_handle * dev_handle
const char * name
Definition: cmsis_dap.h:28
struct cmsis_dap_backend_data * bdata
Definition: cmsis_dap.h:13
uint8_t * response
Definition: cmsis_dap.h:20
uint16_t packet_size
Definition: cmsis_dap.h:15
uint8_t * command
Definition: cmsis_dap.h:19
uint8_t * packet_buffer
Definition: cmsis_dap.h:17
uint16_t packet_buffer_size
Definition: cmsis_dap.h:18
#define NULL
Definition: usb.h:16