27 #ifdef HAVE_NETINET_TCP_H
28 #include <netinet/tcp.h>
32 #ifdef HAVE_SYS_SOCKET_H
33 #include <sys/socket.h>
35 #include <sys/types.h>
43 #define STRINGIFY(x) #x
46 #define DAP_PKT_HDR_SIGNATURE 0x00504144
47 #define DAP_PKT_TYPE_REQUEST 0x01
48 #define DAP_PKT_TYPE_RESPONSE 0x02
50 #define CMSIS_DAP_TCP_PORT 4441
51 #define CMSIS_DAP_PACKET_SIZE 1024
63 #define DEFAULT_MIN_TIMEOUT_MS 150
80 #define HEADER_SIGNATURE_OFFSET 0
81 #define HEADER_LENGTH_OFFSET sizeof(uint32_t)
82 #define HEADER_PACKET_TYPE_OFFSET (sizeof(uint32_t) + sizeof(uint16_t))
83 #define HEADER_RESERVED_OFFSET (sizeof(uint32_t) + sizeof(uint16_t) + \
85 #define HEADER_SIZE (sizeof(uint32_t) + sizeof(uint16_t) + \
108 LOG_DEBUG(
"No TCP hostname, skipping open.");
116 LOG_ERROR(
"CMSIS-DAP: unable to allocate memory");
120 struct addrinfo hints = {
121 .ai_family = AF_UNSPEC,
122 .ai_socktype = SOCK_STREAM
124 struct addrinfo *result, *rp;
127 LOG_INFO(
"CMSIS-DAP: Connecting to %s:%s using TCP backend",
136 LOG_ERROR(
"CMSIS-DAP: getaddrinfo: %s\n", gai_strerror(s));
146 for (rp = result; rp ; rp = rp->ai_next) {
147 fd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
151 if (connect(fd, rp->ai_addr, rp->ai_addrlen) != -1) {
159 freeaddrinfo(result);
162 LOG_ERROR(
"CMSIS-DAP: unable to connect to device %s:%s",
174 setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (
const char *)&one,
sizeof(one));
209 return recv(handle,
buffer,
count, MSG_PEEK | MSG_WAITALL);
218 LOG_DEBUG_IO(
"CMSIS-DAP: using tcp timeout %d msec", wait_ms);
224 LOG_DEBUG_IO(
"CMSIS-DAP: extending timeout to %d msec", wait_ms);
241 }
else if (retval == -1) {
242 if (errno == EAGAIN || errno == EWOULDBLOCK) {
246 LOG_DEBUG_IO(
"CMSIS-DAP: tcp timeout reached 2. timeout = %d msec",
251 LOG_ERROR(
"CMSIS-DAP: error reading header");
255 LOG_ERROR(
"CMSIS-DAP: short header read");
260 struct cmsis_dap_tcp_packet_hdr header;
268 LOG_ERROR(
"CMSIS-DAP: Unrecognized packet signature 0x%08x",
272 LOG_ERROR(
"CMSIS-DAP: Unrecognized packet type 0x%02x",
276 LOG_ERROR(
"CMSIS-DAP: Packet length %d too large to fit.",
283 LOG_DEBUG_IO(
"Reading %d bytes (%d payload)...", read_len, header.length);
289 }
else if (retval == -1) {
290 LOG_ERROR(
"CMSIS-DAP: error reading data");
293 }
else if (retval != read_len) {
294 LOG_ERROR(
"CMSIS-DAP: short read. retval = %d. read_len = %d. "
295 "blocking = %s. wait_ms = %d", retval, read_len,
308 LOG_ERROR(
"CMSIS-DAP: Packet length %d exceeds TCP buffer size!", len);
320 LOG_DEBUG_IO(
"Writing %d bytes (%d payload)", len, txlen);
325 }
else if (retval != (
int)len) {
326 LOG_ERROR(
"CMSIS-DAP: error writing data");
336 unsigned int packet_buffer_size = pkt_sz +
HEADER_SIZE;
337 uint8_t *buf = malloc(packet_buffer_size);
339 LOG_ERROR(
"CMSIS-DAP: unable to allocate CMSIS-DAP packet buffer");
399 LOG_INFO(
"CMSIS-DAP: using minimum timeout of %d ms for TCP packets.",
407 .handler = &cmsis_dap_handle_tcp_host,
409 .help =
"set the host name to use (for TCP backend only)",
410 .usage =
"<host_name>",
414 .handler = &cmsis_dap_handle_tcp_port,
416 .help =
"set the port number to use for DAP (for TCP backend only)",
417 .usage =
"<port_number>",
420 .name =
"min_timeout",
421 .handler = &cmsis_dap_handle_tcp_min_timeout,
423 .help =
"set the minimum timeout in milliseconds to wait for response "
424 "packets (for TCP backend only)",
425 .usage =
"<milliseconds>",
static char *const cmsis_dap_tcp_port_default
#define HEADER_PACKET_TYPE_OFFSET
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
static int cmsis_dap_tcp_read(struct cmsis_dap *dap, int transfer_timeout_ms, enum cmsis_dap_blocking blocking)
#define DAP_PKT_HDR_SIGNATURE
#define DEFAULT_MIN_TIMEOUT_MS
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 char * cmsis_dap_tcp_port
static int peekall_socket(int handle, void *buffer, unsigned int count)
COMMAND_HANDLER(cmsis_dap_handle_tcp_port)
static void cmsis_dap_tcp_close(struct cmsis_dap *dap)
static void cmsis_dap_tcp_cancel_all(struct cmsis_dap *dap)
#define HEADER_LENGTH_OFFSET
#define DAP_PKT_TYPE_REQUEST
const struct command_registration cmsis_dap_tcp_subcommand_handlers[]
struct __attribute__((packed))
#define DAP_PKT_TYPE_RESPONSE
const struct cmsis_dap_backend cmsis_dap_tcp_backend
#define CMSIS_DAP_TCP_PORT
static int cmsis_dap_tcp_min_timeout_ms
#define CMSIS_DAP_PACKET_SIZE
#define HEADER_SIGNATURE_OFFSET
#define CMD_ARGV
Use this macro to access the arguments for the command being handled, rather than accessing the varia...
#define ERROR_COMMAND_SYNTAX_ERROR
#define CMD_ARGC
Use this macro to access the number of arguments for the command being handled, rather than accessing...
#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...
#define COMMAND_REGISTRATION_DONE
Use this as the last entry in an array of command_registration records.
uint64_t buffer
Pointer to data buffer to send over SPI.
void log_socket_error(const char *socket_desc)
#define LOG_DEBUG_IO(expr ...)
#define LOG_ERROR(expr ...)
#define ERROR_TIMEOUT_REACHED
#define LOG_INFO(expr ...)
#define LOG_DEBUG(expr ...)
static void socket_block(int fd)
static int socket_recv_timeout(int fd, unsigned long timeout_msec)
static int close_socket(int sock)
static int write_socket(int handle, const void *buffer, unsigned int count)
static void socket_nonblock(int fd)
unsigned int packet_buffer_size
unsigned int packet_usable_size
struct cmsis_dap_backend_data * bdata
static uint16_t le_to_h_u16(const uint8_t *buf)
static void h_u32_to_le(uint8_t *buf, uint32_t val)
static void h_u16_to_le(uint8_t *buf, uint16_t val)
static uint32_t le_to_h_u32(const uint8_t *buf)