OpenOCD
cmsis_dap_tcp.c
Go to the documentation of this file.
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 
3 /***************************************************************************
4  * Provides CMSIS-DAP protocol over a TCP/IP socket. *
5  * UART and SWO are currently unsupported. *
6  * *
7  * Copyright (C) 2025 by Brian Kuschak <bkuschak@gmail.com> *
8  * *
9  * Adapted from cmsis_dap_usb_hid.c. Copyright (C) 2013-2018 by: *
10  * MickaĆ«l Thomas <mickael9@gmail.com> *
11  * Maksym Hilliaka <oter@frozen-team.com> *
12  * Phillip Pearson <pp@myelin.co.nz> *
13  * Paul Fertser <fercerpav@gmail.com> *
14  * mike brown <mike@theshedworks.org.uk> *
15  * Spencer Oliver <spen@spen-soft.co.uk> *
16  * *
17  ***************************************************************************/
18 
19 #ifdef HAVE_CONFIG_H
20 #include "config.h"
21 #endif
22 
23 #ifdef HAVE_ARPA_INET_H
24 #include <arpa/inet.h>
25 #endif
26 #include <errno.h>
27 #ifdef HAVE_NETDB_H
28 #include <netdb.h>
29 #endif
30 #ifdef HAVE_NETINET_TCP_H
31 #include <netinet/tcp.h>
32 #endif
33 #include <stdbool.h>
34 #include <string.h>
35 #ifdef HAVE_SYS_IOCTL_H
36 #include <sys/ioctl.h>
37 #endif
38 #ifdef HAVE_SYS_SOCKET_H
39 #include <sys/socket.h>
40 #endif
41 #include <sys/types.h>
42 #ifdef HAVE_UNISTD_H
43 #include <unistd.h>
44 #endif
45 
46 #ifdef _WIN32
47 #include <winsock2.h>
48 #include <ws2tcpip.h>
49 #endif
50 
51 #include "helper/command.h"
52 #include "helper/log.h"
53 #include "helper/replacements.h"
54 #include "helper/system.h"
55 #include "cmsis_dap.h"
56 
57 #define STRINGIFY(x) #x
58 
59 // If the protocol changes in the future, the SIGNATURE should also be changed.
60 #define DAP_PKT_HDR_SIGNATURE 0x00504144 // "DAP"
61 #define DAP_PKT_TYPE_REQUEST 0x01
62 #define DAP_PKT_TYPE_RESPONSE 0x02
63 
64 #define CMSIS_DAP_TCP_PORT 4441 // Default. Can be overridden.
65 #define CMSIS_DAP_PACKET_SIZE 1024 // Max payload size not including
66  // header.
67 
68 /* When flushing after an error, the CMSIS-DAP driver assumes the pipeline is
69  * empty if it doesn't get a response after a short 10 msec timeout. While this
70  * works for USB, it may not work for TCP/IP due to higher network latency. TCP
71  * response packets may take longer to arrive. We set a lower bound on timeout
72  * for blocking reads, to give enough time for packets to arrive.
73  *
74  * The user may override this default value by setting the parameter
75  * 'cmsis-dap tcp min_timeout'
76  */
77 #define DEFAULT_MIN_TIMEOUT_MS 150
78 
79 /* CMSIS-DAP requests are variable length. With CMSIS-DAP over USB, the
80  * transfer sizes are preserved by the USB stack. However, TCP/IP is stream
81  * oriented so we perform our own packetization to preserve the boundaries
82  * between each request. This short header is prepended to each CMSIS-DAP
83  * request and response before being sent over the socket. Little endian format
84  * is used for multibyte values.
85  */
86 struct __attribute__((packed)) cmsis_dap_tcp_packet_hdr {
87  uint32_t signature; // "DAP"
88  uint16_t length; // Not including header length.
89  uint8_t packet_type;
90  uint8_t reserved; // Reserved for future use.
91 };
92 
93 /* Defines for struct cmsis_dap_tcp_packet_hdr requested by reviewer. */
94 #define HEADER_SIGNATURE_OFFSET 0
95 #define HEADER_LENGTH_OFFSET sizeof(uint32_t)
96 #define HEADER_PACKET_TYPE_OFFSET (sizeof(uint32_t) + sizeof(uint16_t))
97 #define HEADER_RESERVED_OFFSET (sizeof(uint32_t) + sizeof(uint16_t) + \
98  sizeof(uint8_t))
99 #define HEADER_SIZE (sizeof(uint32_t) + sizeof(uint16_t) + \
100  2 * sizeof(uint8_t))
101 
103  int sockfd;
104 };
105 
106 static char *cmsis_dap_tcp_host;
110 
111 static void cmsis_dap_tcp_close(struct cmsis_dap *dap);
112 static int cmsis_dap_tcp_alloc(struct cmsis_dap *dap, unsigned int pkt_sz);
113 static void cmsis_dap_tcp_free(struct cmsis_dap *dap);
114 
115 static int cmsis_dap_tcp_open(struct cmsis_dap *dap,
116  const uint16_t vids[] __attribute__((unused)),
117  const uint16_t pids[] __attribute__((unused)),
118  const char *serial __attribute__((unused)))
119 {
120  // Skip the open if the user has not provided a hostname.
121  if (!cmsis_dap_tcp_host) {
122  LOG_ERROR("The hostname or IP address of the CMSIS-DAP adapter must be specified");
123  return ERROR_FAIL;
124  }
125 
126  // Ignore vids, pids, serial. We use host and port subcommands instead.
127 
128  dap->bdata = malloc(sizeof(struct cmsis_dap_backend_data));
129  if (!dap->bdata) {
130  LOG_ERROR("CMSIS-DAP: unable to allocate memory");
131  return ERROR_FAIL;
132  }
133 
134  struct addrinfo hints = {
135  .ai_family = AF_UNSPEC,
136  .ai_socktype = SOCK_STREAM
137  };
138  struct addrinfo *result, *rp;
139  int fd = 0;
140 
141  LOG_INFO("CMSIS-DAP: Connecting to %s:%s using TCP backend",
143 
144  /* Some of the following code was taken from remote_bitbang.c */
145  /* Obtain address(es) matching host/port */
146  int s = getaddrinfo(cmsis_dap_tcp_host, cmsis_dap_tcp_port, &hints,
147  &result);
148  if (s != 0) {
149  LOG_ERROR("CMSIS-DAP: getaddrinfo: %s\n", gai_strerror(s));
150  free(dap->bdata);
151  return ERROR_FAIL;
152  }
153 
154  /* getaddrinfo() returns a list of address structures.
155  Try each address until we successfully connect(2).
156  If socket(2) (or connect(2)) fails, we (close the socket
157  and) try the next address. */
158 
159  for (rp = result; rp ; rp = rp->ai_next) {
160  fd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
161  if (fd == -1)
162  continue;
163 
164  if (connect(fd, rp->ai_addr, rp->ai_addrlen) != -1) {
165  LOG_DEBUG("Connected.");
166  break; /* Success */
167  }
168 
169  close(fd);
170  }
171 
172  freeaddrinfo(result);
173 
174  if (!rp) { /* No address succeeded */
175  LOG_ERROR("CMSIS-DAP: unable to connect to device %s:%s",
177  log_socket_error("Failed to connect");
178  free(dap->bdata);
179  dap->bdata = NULL;
180  return ERROR_FAIL;
181  }
182 
183  /* Set NODELAY to minimize latency. */
184  int one = 1;
185  /* On Windows optval has to be a const char *. */
186  setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (const char *)&one, sizeof(one));
187 
188  dap->bdata->sockfd = fd;
189 
190  int retval = cmsis_dap_tcp_alloc(dap, CMSIS_DAP_PACKET_SIZE);
191  if (retval != ERROR_OK) {
192  cmsis_dap_tcp_close(dap);
193  return retval;
194  }
195  return ERROR_OK;
196 }
197 
198 static void cmsis_dap_tcp_close(struct cmsis_dap *dap)
199 {
200  if (close_socket(dap->bdata->sockfd) != 0)
201  log_socket_error("close_socket");
202 
203  if (dap->bdata)
204  free(dap->bdata);
205  dap->bdata = NULL;
206  cmsis_dap_tcp_free(dap);
207 }
208 
209 static int socket_bytes_available(int sock, unsigned int *out_avail)
210 {
211 #ifdef _WIN32
212  u_long avail = 0;
213  if (ioctlsocket((SOCKET)sock, FIONREAD, &avail) == SOCKET_ERROR)
214  return -1;
215 #else
216  int avail = 0;
217  if (ioctl(sock, FIONREAD, &avail) < 0)
218  return -1;
219 #endif
220  *out_avail = avail;
221  return 0;
222 }
223 
224 static inline int readall_socket(int handle, void *buffer, unsigned int count)
225 {
226  // Return after all count bytes available, or timeout, or error.
227  return recv(handle, buffer, count, MSG_WAITALL);
228 }
229 
230 static int peekall_socket(int handle, void *buffer, unsigned int count,
231  enum cmsis_dap_blocking blocking, unsigned int timeout_ms)
232 {
233  /* Windows doesn't support MSG_PEEK in combination with MSG_WAITALL:
234  * return recv(handle, buffer, count, MSG_PEEK | MSG_WAITALL);
235  *
236  * So, use this method instead which should work for Windows and others.
237  *
238  * Data remains unread on the socket until recv() is called later without
239  * the MSG_PEEK flag. Return after all count bytes available, or timeout,
240  * or error.
241  */
242 
243  if (count == 0)
244  return 0;
245 
246  while (true) {
247  int ret;
248  unsigned int avail;
249  if (socket_bytes_available(handle, &avail) < 0)
250  return -1;
251 
252  if (avail >= count) {
253  ret = recv(handle, (char *)buffer, (int)count, MSG_PEEK);
254  if (ret < 0) {
255 #ifdef _WIN32
256  int err = WSAGetLastError();
257  if (err == WSAEINTR)
258  continue;
259  if (err == WSAEWOULDBLOCK)
260  return -1;
261 #else
262  if (errno == EINTR)
263  continue;
264  if (errno == EAGAIN || errno == EWOULDBLOCK)
265  return -1; // Timeout or nonblocking.
266 #endif
267  }
268  return ret; // 0: Closed, <0: Other error, >0 Success.
269  }
270 
271  // Not enough data available.
272  if (blocking == CMSIS_DAP_NON_BLOCKING) {
273 #ifdef _WIN32
274  WSASetLastError(WSAEWOULDBLOCK);
275 #else
276  errno = EAGAIN;
277 #endif
278  return -1;
279  }
280 
281  // Blocking wait.
282  fd_set rfds;
283  FD_ZERO(&rfds);
284  OCD_FD_SET(handle, &rfds);
285 
286  struct timeval tv;
287  tv.tv_sec = timeout_ms / 1000;
288  tv.tv_usec = (timeout_ms % 1000) * 1000;
289 
290  ret = select(handle + 1, &rfds, NULL, NULL, &tv);
291  if (ret > 0)
292  continue; // Readable
293 
294  if (ret == 0) { // Timeout
295 #ifdef _WIN32
296  WSASetLastError(WSAEWOULDBLOCK);
297 #else
298  errno = EAGAIN;
299 #endif
300  return -1;
301  }
302 
303  // Error
304 #ifndef _WIN32
305  if (errno == EINTR)
306  continue;
307 #endif
308  return ret;
309  }
310 }
311 
312 static int cmsis_dap_tcp_read(struct cmsis_dap *dap, int transfer_timeout_ms,
313  enum cmsis_dap_blocking blocking)
314 {
315  int wait_ms = (blocking == CMSIS_DAP_NON_BLOCKING) ? 0 :
316  transfer_timeout_ms;
317  if (wait_ms) {
318  LOG_DEBUG_IO("CMSIS-DAP: using tcp timeout %d msec", wait_ms);
319 
320  // Don't use very short timeouts with TCP/IP as it may not be as fast
321  // to respond as USB. User configurable minimum value.
322  if (wait_ms < cmsis_dap_tcp_min_timeout_ms) {
324  LOG_DEBUG_IO("CMSIS-DAP: extending timeout to %d msec", wait_ms);
325  }
326  }
327  socket_recv_timeout(dap->bdata->sockfd, wait_ms);
328 
329  if (blocking == CMSIS_DAP_NON_BLOCKING)
331  else
332  socket_block(dap->bdata->sockfd);
333 
334  // Peek at the header first to find the length.
335  int retval = peekall_socket(dap->bdata->sockfd, dap->packet_buffer,
336  HEADER_SIZE, blocking, wait_ms);
337  LOG_DEBUG_IO("Reading header returned %d", retval);
338  if (retval == 0) {
339  LOG_DEBUG_IO("CMSIS-DAP: tcp timeout reached 1");
340  return ERROR_TIMEOUT_REACHED;
341  } else if (retval == -1) {
342  if (errno == EAGAIN || errno == EWOULDBLOCK) {
343  if (blocking == CMSIS_DAP_NON_BLOCKING)
344  return ERROR_TIMEOUT_REACHED;
345 
346  LOG_DEBUG_IO("CMSIS-DAP: tcp timeout reached 2. timeout = %d msec",
347  wait_ms);
348  return ERROR_TIMEOUT_REACHED;
349  }
350 
351  LOG_ERROR("CMSIS-DAP: error reading header");
352  log_socket_error("peek_socket");
353  return ERROR_FAIL;
354  } else if (retval != HEADER_SIZE) {
355  LOG_ERROR("CMSIS-DAP: short header read");
356  log_socket_error("peek_socket header short read");
357  return ERROR_FAIL;
358  }
359 
360  struct cmsis_dap_tcp_packet_hdr header;
361  header.signature = le_to_h_u32(dap->packet_buffer +
363  header.length = le_to_h_u16(dap->packet_buffer + HEADER_LENGTH_OFFSET);
364  header.packet_type = dap->packet_buffer[HEADER_PACKET_TYPE_OFFSET];
365  header.reserved = dap->packet_buffer[HEADER_RESERVED_OFFSET];
366 
367  if (header.signature != DAP_PKT_HDR_SIGNATURE) {
368  LOG_ERROR("CMSIS-DAP: Unrecognized packet signature 0x%08x",
369  header.signature);
370  return ERROR_FAIL;
371  } else if (header.packet_type != DAP_PKT_TYPE_RESPONSE) {
372  LOG_ERROR("CMSIS-DAP: Unrecognized packet type 0x%02x",
373  header.packet_type);
374  return ERROR_FAIL;
375  } else if (header.length + HEADER_SIZE > dap->packet_buffer_size) {
376  LOG_ERROR("CMSIS-DAP: Packet length %d too large to fit.",
377  header.length);
378  return ERROR_FAIL;
379  }
380 
381  // Read the complete packet.
382  int read_len = HEADER_SIZE + header.length;
383  LOG_DEBUG_IO("Reading %d bytes (%d payload)...", read_len, header.length);
384  retval = readall_socket(dap->bdata->sockfd, dap->packet_buffer, read_len);
385 
386  if (retval == 0) {
387  LOG_DEBUG_IO("CMSIS-DAP: tcp timeout reached 3");
388  return ERROR_TIMEOUT_REACHED;
389  } else if (retval == -1) {
390  LOG_ERROR("CMSIS-DAP: error reading data");
391  log_socket_error("read_socket");
392  return ERROR_FAIL;
393  } else if (retval != read_len) {
394  LOG_ERROR("CMSIS-DAP: short read. retval = %d. read_len = %d. "
395  "blocking = %s. wait_ms = %d", retval, read_len,
396  (blocking == CMSIS_DAP_NON_BLOCKING) ? "yes" : "no", wait_ms);
397  log_socket_error("read_socket short read");
398  return ERROR_FAIL;
399  }
400  return retval;
401 }
402 
403 static int cmsis_dap_tcp_write(struct cmsis_dap *dap, int txlen,
404  int timeout_ms __attribute__((unused)))
405 {
406  const unsigned int len = txlen + HEADER_SIZE;
407  if (len > dap->packet_buffer_size) {
408  LOG_ERROR("CMSIS-DAP: Packet length %d exceeds TCP buffer size!", len);
409  return ERROR_FAIL;
410  }
411 
412  /* Set the header values. */
418 
419  /* write data to device */
420  LOG_DEBUG_IO("Writing %d bytes (%d payload)", len, txlen);
421  int retval = write_socket(dap->bdata->sockfd, dap->packet_buffer, len);
422  if (retval < 0) {
423  log_socket_error("write_socket");
424  return ERROR_FAIL;
425  } else if (retval != (int)len) {
426  LOG_ERROR("CMSIS-DAP: error writing data");
427  log_socket_error("write_socket short write");
428  return ERROR_FAIL;
429  }
430  return retval;
431 }
432 
433 static int cmsis_dap_tcp_alloc(struct cmsis_dap *dap, unsigned int pkt_sz)
434 {
435  // Reserve space for the packet header.
436  unsigned int packet_buffer_size = pkt_sz + HEADER_SIZE;
437  uint8_t *buf = malloc(packet_buffer_size);
438  if (!buf) {
439  LOG_ERROR("CMSIS-DAP: unable to allocate CMSIS-DAP packet buffer");
440  return ERROR_FAIL;
441  }
442 
443  dap->packet_buffer = buf;
444  dap->packet_size = pkt_sz;
445  dap->packet_usable_size = pkt_sz;
446  dap->packet_buffer_size = packet_buffer_size;
447 
448  dap->command = dap->packet_buffer + HEADER_SIZE;
449  dap->response = dap->packet_buffer + HEADER_SIZE;
450  return ERROR_OK;
451 }
452 
453 static void cmsis_dap_tcp_free(struct cmsis_dap *dap)
454 {
455  free(dap->packet_buffer);
456  dap->packet_buffer = NULL;
457 }
458 
459 static void cmsis_dap_tcp_cancel_all(struct cmsis_dap *dap)
460 {
461 }
462 
463 COMMAND_HANDLER(cmsis_dap_handle_tcp_port)
464 {
465  if (CMD_ARGC != 1)
467 
469  free(cmsis_dap_tcp_port);
470 
471  cmsis_dap_tcp_port = strdup(CMD_ARGV[0]);
472  if (!cmsis_dap_tcp_port) {
473  LOG_ERROR("CMSIS-DAP: out of memory");
474  return ERROR_FAIL;
475  }
476  return ERROR_OK;
477 }
478 
479 COMMAND_HANDLER(cmsis_dap_handle_tcp_host)
480 {
481  if (CMD_ARGC != 1)
483 
484  free(cmsis_dap_tcp_host);
485  cmsis_dap_tcp_host = strdup(CMD_ARGV[0]);
486  if (!cmsis_dap_tcp_host) {
487  LOG_ERROR("CMSIS-DAP: out of memory");
488  return ERROR_FAIL;
489  }
490  return ERROR_OK;
491 }
492 
493 COMMAND_HANDLER(cmsis_dap_handle_tcp_min_timeout)
494 {
495  if (CMD_ARGC != 1)
497 
499  LOG_INFO("CMSIS-DAP: using minimum timeout of %d ms for TCP packets.",
501  return ERROR_OK;
502 }
503 
505  {
506  .name = "host",
507  .handler = &cmsis_dap_handle_tcp_host,
508  .mode = COMMAND_CONFIG,
509  .help = "set the host name to use (for TCP backend only)",
510  .usage = "<host_name>",
511  },
512  {
513  .name = "port",
514  .handler = &cmsis_dap_handle_tcp_port,
515  .mode = COMMAND_CONFIG,
516  .help = "set the port number to use for DAP (for TCP backend only)",
517  .usage = "<port_number>",
518  },
519  {
520  .name = "min_timeout",
521  .handler = &cmsis_dap_handle_tcp_min_timeout,
522  .mode = COMMAND_CONFIG,
523  .help = "set the minimum timeout in milliseconds to wait for response "
524  "packets (for TCP backend only)",
525  .usage = "<milliseconds>",
526  },
528 };
529 
531  .name = "tcp",
532  .open = cmsis_dap_tcp_open,
533  .close = cmsis_dap_tcp_close,
534  .read = cmsis_dap_tcp_read,
535  .write = cmsis_dap_tcp_write,
536  .packet_buffer_alloc = cmsis_dap_tcp_alloc,
537  .packet_buffer_free = cmsis_dap_tcp_free,
538  .cancel_all = cmsis_dap_tcp_cancel_all,
539 };
char * serial
Definition: adapter.c:49
cmsis_dap_blocking
Definition: cmsis_dap.h:61
@ CMSIS_DAP_NON_BLOCKING
Definition: cmsis_dap.h:62
#define HEADER_PACKET_TYPE_OFFSET
Definition: cmsis_dap_tcp.c:96
static int cmsis_dap_tcp_write(struct cmsis_dap *dap, int txlen, int timeout_ms __attribute__((unused)))
static void cmsis_dap_tcp_free(struct cmsis_dap *dap)
static char * cmsis_dap_tcp_host
#define HEADER_RESERVED_OFFSET
Definition: cmsis_dap_tcp.c:97
static int cmsis_dap_tcp_read(struct cmsis_dap *dap, int transfer_timeout_ms, enum cmsis_dap_blocking blocking)
#define DAP_PKT_HDR_SIGNATURE
Definition: cmsis_dap_tcp.c:60
#define DEFAULT_MIN_TIMEOUT_MS
Definition: cmsis_dap_tcp.c:77
static int readall_socket(int handle, void *buffer, unsigned int count)
static int cmsis_dap_tcp_alloc(struct cmsis_dap *dap, unsigned int pkt_sz)
static int peekall_socket(int handle, void *buffer, unsigned int count, enum cmsis_dap_blocking blocking, unsigned int timeout_ms)
static char * cmsis_dap_tcp_port
#define HEADER_SIZE
Definition: cmsis_dap_tcp.c:99
COMMAND_HANDLER(cmsis_dap_handle_tcp_port)
static char cmsis_dap_tcp_port_default[]
static void cmsis_dap_tcp_close(struct cmsis_dap *dap)
#define STRINGIFY(x)
Definition: cmsis_dap_tcp.c:57
static void cmsis_dap_tcp_cancel_all(struct cmsis_dap *dap)
#define HEADER_LENGTH_OFFSET
Definition: cmsis_dap_tcp.c:95
#define DAP_PKT_TYPE_REQUEST
Definition: cmsis_dap_tcp.c:61
static int cmsis_dap_tcp_open(struct cmsis_dap *dap, const uint16_t vids[] __attribute__((unused)), const uint16_t pids[] __attribute__((unused)), const char *serial __attribute__((unused)))
const struct command_registration cmsis_dap_tcp_subcommand_handlers[]
struct __attribute__((packed))
Definition: cmsis_dap_tcp.c:86
#define DAP_PKT_TYPE_RESPONSE
Definition: cmsis_dap_tcp.c:62
const struct cmsis_dap_backend cmsis_dap_tcp_backend
static int socket_bytes_available(int sock, unsigned int *out_avail)
#define CMSIS_DAP_TCP_PORT
Definition: cmsis_dap_tcp.c:64
static int cmsis_dap_tcp_min_timeout_ms
#define CMSIS_DAP_PACKET_SIZE
Definition: cmsis_dap_tcp.c:65
#define HEADER_SIGNATURE_OFFSET
Definition: cmsis_dap_tcp.c:94
#define CMD_ARGV
Use this macro to access the arguments for the command being handled, rather than accessing the varia...
Definition: command.h:161
#define ERROR_COMMAND_SYNTAX_ERROR
Definition: command.h:405
#define CMD_ARGC
Use this macro to access the number of arguments for the command being handled, rather than accessing...
Definition: command.h:156
#define COMMAND_PARSE_NUMBER(type, in, out)
parses the string in into out as a type, or prints a command error and passes the error code to the c...
Definition: command.h:445
#define COMMAND_REGISTRATION_DONE
Use this as the last entry in an array of command_registration records.
Definition: command.h:256
@ COMMAND_CONFIG
Definition: command.h:41
uint64_t buffer
Pointer to data buffer to send over SPI.
Definition: dw-spi-helper.h:0
uint8_t length
Definition: esp_usb_jtag.c:1
void log_socket_error(const char *socket_desc)
Definition: log.c:506
#define LOG_DEBUG_IO(expr ...)
Definition: log.h:116
#define ERROR_FAIL
Definition: log.h:188
#define LOG_ERROR(expr ...)
Definition: log.h:147
#define ERROR_TIMEOUT_REACHED
Definition: log.h:191
#define LOG_INFO(expr ...)
Definition: log.h:141
#define LOG_DEBUG(expr ...)
Definition: log.h:124
#define ERROR_OK
Definition: log.h:182
static void socket_block(int fd)
Definition: replacements.h:207
static int socket_recv_timeout(int fd, unsigned long timeout_msec)
Definition: replacements.h:242
static int close_socket(int sock)
Definition: replacements.h:198
#define OCD_FD_SET(fd, set)
Definition: replacements.h:174
static int write_socket(int handle, const void *buffer, unsigned int count)
Definition: replacements.h:180
static void socket_nonblock(int fd)
Definition: replacements.h:218
const char * name
Definition: cmsis_dap.h:67
unsigned int packet_buffer_size
Definition: cmsis_dap.h:32
unsigned int packet_usable_size
Definition: cmsis_dap.h:31
unsigned int packet_size
Definition: cmsis_dap.h:30
struct cmsis_dap_backend_data * bdata
Definition: cmsis_dap.h:28
uint8_t * response
Definition: cmsis_dap.h:35
uint8_t * command
Definition: cmsis_dap.h:34
uint8_t * packet_buffer
Definition: cmsis_dap.h:33
const char * name
Definition: command.h:239
long tv_sec
Definition: replacements.h:46
long tv_usec
Definition: replacements.h:47
static uint16_t le_to_h_u16(const uint8_t *buf)
Definition: types.h:122
static void h_u32_to_le(uint8_t *buf, uint32_t val)
Definition: types.h:178
static void h_u16_to_le(uint8_t *buf, uint16_t val)
Definition: types.h:208
static uint32_t le_to_h_u32(const uint8_t *buf)
Definition: types.h:112
#define NULL
Definition: usb.h:16
uint8_t count[4]
Definition: vdebug.c:22