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  uint16_t vids[] __attribute__((unused)),
117  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_DEBUG("No TCP hostname, skipping open.");
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",
142  cmsis_dap_tcp_host ? cmsis_dap_tcp_host : "localhost",
144 
145  /* Some of the following code was taken from remote_bitbang.c */
146  /* Obtain address(es) matching host/port */
147  int s = getaddrinfo(cmsis_dap_tcp_host, cmsis_dap_tcp_port, &hints,
148  &result);
149  if (s != 0) {
150  LOG_ERROR("CMSIS-DAP: getaddrinfo: %s\n", gai_strerror(s));
151  free(dap->bdata);
152  return ERROR_FAIL;
153  }
154 
155  /* getaddrinfo() returns a list of address structures.
156  Try each address until we successfully connect(2).
157  If socket(2) (or connect(2)) fails, we (close the socket
158  and) try the next address. */
159 
160  for (rp = result; rp ; rp = rp->ai_next) {
161  fd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
162  if (fd == -1)
163  continue;
164 
165  if (connect(fd, rp->ai_addr, rp->ai_addrlen) != -1) {
166  LOG_DEBUG("Connected.");
167  break; /* Success */
168  }
169 
170  close(fd);
171  }
172 
173  freeaddrinfo(result);
174 
175  if (!rp) { /* No address succeeded */
176  LOG_ERROR("CMSIS-DAP: unable to connect to device %s:%s",
177  cmsis_dap_tcp_host ? cmsis_dap_tcp_host : "localhost",
179  log_socket_error("Failed to connect");
180  free(dap->bdata);
181  dap->bdata = NULL;
182  return ERROR_FAIL;
183  }
184 
185  /* Set NODELAY to minimize latency. */
186  int one = 1;
187  /* On Windows optval has to be a const char *. */
188  setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (const char *)&one, sizeof(one));
189 
190  dap->bdata->sockfd = fd;
191 
192  int retval = cmsis_dap_tcp_alloc(dap, CMSIS_DAP_PACKET_SIZE);
193  if (retval != ERROR_OK) {
194  cmsis_dap_tcp_close(dap);
195  return retval;
196  }
197  return ERROR_OK;
198 }
199 
200 static void cmsis_dap_tcp_close(struct cmsis_dap *dap)
201 {
202  if (close_socket(dap->bdata->sockfd) != 0)
203  log_socket_error("close_socket");
204 
205  if (dap->bdata)
206  free(dap->bdata);
207  dap->bdata = NULL;
208  cmsis_dap_tcp_free(dap);
209 }
210 
211 static int socket_bytes_available(int sock, unsigned int *out_avail)
212 {
213 #ifdef _WIN32
214  u_long avail = 0;
215  if (ioctlsocket((SOCKET)sock, FIONREAD, &avail) == SOCKET_ERROR)
216  return -1;
217 #else
218  int avail = 0;
219  if (ioctl(sock, FIONREAD, &avail) < 0)
220  return -1;
221 #endif
222  *out_avail = avail;
223  return 0;
224 }
225 
226 static inline int readall_socket(int handle, void *buffer, unsigned int count)
227 {
228  // Return after all count bytes available, or timeout, or error.
229  return recv(handle, buffer, count, MSG_WAITALL);
230 }
231 
232 static int peekall_socket(int handle, void *buffer, unsigned int count,
233  enum cmsis_dap_blocking blocking, unsigned int timeout_ms)
234 {
235  /* Windows doesn't support MSG_PEEK in combination with MSG_WAITALL:
236  * return recv(handle, buffer, count, MSG_PEEK | MSG_WAITALL);
237  *
238  * So, use this method instead which should work for Windows and others.
239  *
240  * Data remains unread on the socket until recv() is called later without
241  * the MSG_PEEK flag. Return after all count bytes available, or timeout,
242  * or error.
243  */
244 
245  if (count == 0)
246  return 0;
247 
248  while (true) {
249  int ret;
250  unsigned int avail;
251  if (socket_bytes_available(handle, &avail) < 0)
252  return -1;
253 
254  if (avail >= count) {
255  ret = recv(handle, (char *)buffer, (int)count, MSG_PEEK);
256  if (ret < 0) {
257 #ifdef _WIN32
258  int err = WSAGetLastError();
259  if (err == WSAEINTR)
260  continue;
261  if (err == WSAEWOULDBLOCK)
262  return -1;
263 #else
264  if (errno == EINTR)
265  continue;
266  if (errno == EAGAIN || errno == EWOULDBLOCK)
267  return -1; // Timeout or nonblocking.
268 #endif
269  }
270  return ret; // 0: Closed, <0: Other error, >0 Success.
271  }
272 
273  // Not enough data available.
274  if (blocking == CMSIS_DAP_NON_BLOCKING) {
275 #ifdef _WIN32
276  WSASetLastError(WSAEWOULDBLOCK);
277 #else
278  errno = EAGAIN;
279 #endif
280  return -1;
281  }
282 
283  // Blocking wait.
284  fd_set rfds;
285  FD_ZERO(&rfds);
286  FD_SET(handle, &rfds);
287 
288  struct timeval tv;
289  tv.tv_sec = timeout_ms / 1000;
290  tv.tv_usec = (timeout_ms % 1000) * 1000;
291 
292  ret = select(handle + 1, &rfds, NULL, NULL, &tv);
293  if (ret > 0)
294  continue; // Readable
295 
296  if (ret == 0) { // Timeout
297 #ifdef _WIN32
298  WSASetLastError(WSAEWOULDBLOCK);
299 #else
300  errno = EAGAIN;
301 #endif
302  return -1;
303  }
304 
305  // Error
306 #ifndef _WIN32
307  if (errno == EINTR)
308  continue;
309 #endif
310  return ret;
311  }
312 }
313 
314 static int cmsis_dap_tcp_read(struct cmsis_dap *dap, int transfer_timeout_ms,
315  enum cmsis_dap_blocking blocking)
316 {
317  int wait_ms = (blocking == CMSIS_DAP_NON_BLOCKING) ? 0 :
318  transfer_timeout_ms;
319  if (wait_ms) {
320  LOG_DEBUG_IO("CMSIS-DAP: using tcp timeout %d msec", wait_ms);
321 
322  // Don't use very short timeouts with TCP/IP as it may not be as fast
323  // to respond as USB. User configurable minimum value.
324  if (wait_ms < cmsis_dap_tcp_min_timeout_ms) {
326  LOG_DEBUG_IO("CMSIS-DAP: extending timeout to %d msec", wait_ms);
327  }
328  }
329  socket_recv_timeout(dap->bdata->sockfd, wait_ms);
330 
331  if (blocking == CMSIS_DAP_NON_BLOCKING)
333  else
334  socket_block(dap->bdata->sockfd);
335 
336  // Peek at the header first to find the length.
337  int retval = peekall_socket(dap->bdata->sockfd, dap->packet_buffer,
338  HEADER_SIZE, blocking, wait_ms);
339  LOG_DEBUG_IO("Reading header returned %d", retval);
340  if (retval == 0) {
341  LOG_DEBUG_IO("CMSIS-DAP: tcp timeout reached 1");
342  return ERROR_TIMEOUT_REACHED;
343  } else if (retval == -1) {
344  if (errno == EAGAIN || errno == EWOULDBLOCK) {
345  if (blocking == CMSIS_DAP_NON_BLOCKING)
346  return ERROR_TIMEOUT_REACHED;
347 
348  LOG_DEBUG_IO("CMSIS-DAP: tcp timeout reached 2. timeout = %d msec",
349  wait_ms);
350  return ERROR_TIMEOUT_REACHED;
351  }
352 
353  LOG_ERROR("CMSIS-DAP: error reading header");
354  log_socket_error("peek_socket");
355  return ERROR_FAIL;
356  } else if (retval != HEADER_SIZE) {
357  LOG_ERROR("CMSIS-DAP: short header read");
358  log_socket_error("peek_socket header short read");
359  return ERROR_FAIL;
360  }
361 
362  struct cmsis_dap_tcp_packet_hdr header;
363  header.signature = le_to_h_u32(dap->packet_buffer +
365  header.length = le_to_h_u16(dap->packet_buffer + HEADER_LENGTH_OFFSET);
366  header.packet_type = dap->packet_buffer[HEADER_PACKET_TYPE_OFFSET];
367  header.reserved = dap->packet_buffer[HEADER_RESERVED_OFFSET];
368 
369  if (header.signature != DAP_PKT_HDR_SIGNATURE) {
370  LOG_ERROR("CMSIS-DAP: Unrecognized packet signature 0x%08x",
371  header.signature);
372  return ERROR_FAIL;
373  } else if (header.packet_type != DAP_PKT_TYPE_RESPONSE) {
374  LOG_ERROR("CMSIS-DAP: Unrecognized packet type 0x%02x",
375  header.packet_type);
376  return ERROR_FAIL;
377  } else if (header.length + HEADER_SIZE > dap->packet_buffer_size) {
378  LOG_ERROR("CMSIS-DAP: Packet length %d too large to fit.",
379  header.length);
380  return ERROR_FAIL;
381  }
382 
383  // Read the complete packet.
384  int read_len = HEADER_SIZE + header.length;
385  LOG_DEBUG_IO("Reading %d bytes (%d payload)...", read_len, header.length);
386  retval = readall_socket(dap->bdata->sockfd, dap->packet_buffer, read_len);
387 
388  if (retval == 0) {
389  LOG_DEBUG_IO("CMSIS-DAP: tcp timeout reached 3");
390  return ERROR_TIMEOUT_REACHED;
391  } else if (retval == -1) {
392  LOG_ERROR("CMSIS-DAP: error reading data");
393  log_socket_error("read_socket");
394  return ERROR_FAIL;
395  } else if (retval != read_len) {
396  LOG_ERROR("CMSIS-DAP: short read. retval = %d. read_len = %d. "
397  "blocking = %s. wait_ms = %d", retval, read_len,
398  (blocking == CMSIS_DAP_NON_BLOCKING) ? "yes" : "no", wait_ms);
399  log_socket_error("read_socket short read");
400  return ERROR_FAIL;
401  }
402  return retval;
403 }
404 
405 static int cmsis_dap_tcp_write(struct cmsis_dap *dap, int txlen,
406  int timeout_ms __attribute__((unused)))
407 {
408  const unsigned int len = txlen + HEADER_SIZE;
409  if (len > dap->packet_buffer_size) {
410  LOG_ERROR("CMSIS-DAP: Packet length %d exceeds TCP buffer size!", len);
411  return ERROR_FAIL;
412  }
413 
414  /* Set the header values. */
420 
421  /* write data to device */
422  LOG_DEBUG_IO("Writing %d bytes (%d payload)", len, txlen);
423  int retval = write_socket(dap->bdata->sockfd, dap->packet_buffer, len);
424  if (retval < 0) {
425  log_socket_error("write_socket");
426  return ERROR_FAIL;
427  } else if (retval != (int)len) {
428  LOG_ERROR("CMSIS-DAP: error writing data");
429  log_socket_error("write_socket short write");
430  return ERROR_FAIL;
431  }
432  return retval;
433 }
434 
435 static int cmsis_dap_tcp_alloc(struct cmsis_dap *dap, unsigned int pkt_sz)
436 {
437  // Reserve space for the packet header.
438  unsigned int packet_buffer_size = pkt_sz + HEADER_SIZE;
439  uint8_t *buf = malloc(packet_buffer_size);
440  if (!buf) {
441  LOG_ERROR("CMSIS-DAP: unable to allocate CMSIS-DAP packet buffer");
442  return ERROR_FAIL;
443  }
444 
445  dap->packet_buffer = buf;
446  dap->packet_size = pkt_sz;
447  dap->packet_usable_size = pkt_sz;
448  dap->packet_buffer_size = packet_buffer_size;
449 
450  dap->command = dap->packet_buffer + HEADER_SIZE;
451  dap->response = dap->packet_buffer + HEADER_SIZE;
452  return ERROR_OK;
453 }
454 
455 static void cmsis_dap_tcp_free(struct cmsis_dap *dap)
456 {
457  free(dap->packet_buffer);
458  dap->packet_buffer = NULL;
459 }
460 
461 static void cmsis_dap_tcp_cancel_all(struct cmsis_dap *dap)
462 {
463 }
464 
465 COMMAND_HANDLER(cmsis_dap_handle_tcp_port)
466 {
467  if (CMD_ARGC != 1)
469 
471  free(cmsis_dap_tcp_port);
472 
473  cmsis_dap_tcp_port = strdup(CMD_ARGV[0]);
474  if (!cmsis_dap_tcp_port) {
475  LOG_ERROR("CMSIS-DAP: out of memory");
476  return ERROR_FAIL;
477  }
478  return ERROR_OK;
479 }
480 
481 COMMAND_HANDLER(cmsis_dap_handle_tcp_host)
482 {
483  if (CMD_ARGC != 1)
485 
486  free(cmsis_dap_tcp_host);
487  cmsis_dap_tcp_host = strdup(CMD_ARGV[0]);
488  if (!cmsis_dap_tcp_host) {
489  LOG_ERROR("CMSIS-DAP: out of memory");
490  return ERROR_FAIL;
491  }
492  return ERROR_OK;
493 }
494 
495 COMMAND_HANDLER(cmsis_dap_handle_tcp_min_timeout)
496 {
497  if (CMD_ARGC != 1)
499 
501  LOG_INFO("CMSIS-DAP: using minimum timeout of %d ms for TCP packets.",
503  return ERROR_OK;
504 }
505 
507  {
508  .name = "host",
509  .handler = &cmsis_dap_handle_tcp_host,
510  .mode = COMMAND_CONFIG,
511  .help = "set the host name to use (for TCP backend only)",
512  .usage = "<host_name>",
513  },
514  {
515  .name = "port",
516  .handler = &cmsis_dap_handle_tcp_port,
517  .mode = COMMAND_CONFIG,
518  .help = "set the port number to use for DAP (for TCP backend only)",
519  .usage = "<port_number>",
520  },
521  {
522  .name = "min_timeout",
523  .handler = &cmsis_dap_handle_tcp_min_timeout,
524  .mode = COMMAND_CONFIG,
525  .help = "set the minimum timeout in milliseconds to wait for response "
526  "packets (for TCP backend only)",
527  .usage = "<milliseconds>",
528  },
530 };
531 
533  .name = "tcp",
534  .open = cmsis_dap_tcp_open,
535  .close = cmsis_dap_tcp_close,
536  .read = cmsis_dap_tcp_read,
537  .write = cmsis_dap_tcp_write,
538  .packet_buffer_alloc = cmsis_dap_tcp_alloc,
539  .packet_buffer_free = cmsis_dap_tcp_free,
540  .cancel_all = cmsis_dap_tcp_cancel_all,
541 };
char * serial
Definition: adapter.c:43
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
static int cmsis_dap_tcp_open(struct cmsis_dap *dap, uint16_t vids[] __attribute__((unused)), uint16_t pids[] __attribute__((unused)), const char *serial __attribute__((unused)))
#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
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:156
#define ERROR_COMMAND_SYNTAX_ERROR
Definition: command.h:400
#define CMD_ARGC
Use this macro to access the number of arguments for the command being handled, rather than accessing...
Definition: command.h:151
#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:440
#define COMMAND_REGISTRATION_DONE
Use this as the last entry in an array of command_registration records.
Definition: command.h:251
@ 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:496
#define LOG_DEBUG_IO(expr ...)
Definition: log.h:102
#define ERROR_FAIL
Definition: log.h:174
#define LOG_ERROR(expr ...)
Definition: log.h:133
#define ERROR_TIMEOUT_REACHED
Definition: log.h:177
#define LOG_INFO(expr ...)
Definition: log.h:127
#define LOG_DEBUG(expr ...)
Definition: log.h:110
#define ERROR_OK
Definition: log.h:168
static void socket_block(int fd)
Definition: replacements.h:193
static int socket_recv_timeout(int fd, unsigned long timeout_msec)
Definition: replacements.h:228
static int close_socket(int sock)
Definition: replacements.h:184
static int write_socket(int handle, const void *buffer, unsigned int count)
Definition: replacements.h:166
static void socket_nonblock(int fd)
Definition: replacements.h:204
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:234
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