39 #if defined(PIOS_INCLUDE_TCP)
44 #include <sys/types.h>
48 #ifndef INVALID_SOCKET
49 #define INVALID_SOCKET (-1)
53 static void PIOS_TCP_ChangeBaud(uintptr_t tcp_id, uint32_t baud);
54 static void PIOS_TCP_RegisterRxCallback(uintptr_t tcp_id,
pios_com_callback rx_in_cb, uintptr_t context);
55 static void PIOS_TCP_RegisterTxCallback(uintptr_t tcp_id,
pios_com_callback tx_out_cb, uintptr_t context);
56 static void PIOS_TCP_TxStart(uintptr_t tcp_id, uint16_t tx_bytes_avail);
57 static void PIOS_TCP_RxStart(uintptr_t tcp_id, uint16_t rx_bytes_avail);
58 static bool PIOS_TCP_Available(uintptr_t tcp_id);
64 struct sockaddr_in6 server;
65 struct sockaddr_in6 client;
66 int socket_connection;
69 uintptr_t tx_out_context;
71 uintptr_t rx_in_context;
79 .tx_start = PIOS_TCP_TxStart,
80 .rx_start = PIOS_TCP_RxStart,
81 .bind_tx_cb = PIOS_TCP_RegisterTxCallback,
82 .bind_rx_cb = PIOS_TCP_RegisterRxCallback,
83 .available = PIOS_TCP_Available,
87 static pios_tcp_dev * find_tcp_dev_by_id(uintptr_t tcp)
89 return (pios_tcp_dev *) tcp;
92 static void rx_cb_all(pios_tcp_dev *tcp_dev, uint8_t *incoming_buffer,
96 bool rx_need_yield =
false;
98 sent = tcp_dev->rx_in_cb(tcp_dev->rx_in_context, incoming_buffer, len,
99 NULL, &rx_need_yield);
108 int sent_chunk = tcp_dev->rx_in_cb(tcp_dev->rx_in_context,
109 incoming_buffer, len, NULL, &rx_need_yield);
111 if (sent_chunk < 0) {
122 static void PIOS_TCP_RxTask(
void *tcp_dev_n)
124 pios_tcp_dev *tcp_dev = (pios_tcp_dev*)tcp_dev_n;
126 const int INCOMING_BUFFER_SIZE = 16;
127 uint8_t incoming_buffer[INCOMING_BUFFER_SIZE];
134 tcp_dev->socket_connection = accept(tcp_dev->socket, NULL, NULL);
138 }
while (tcp_dev->socket_connection ==
INVALID_SOCKET && (error == EINTR || error == EAGAIN));
140 if (tcp_dev->socket_connection < 0) {
143 perror(
"Accept failed");
144 close(tcp_dev->socket);
148 fprintf(stderr,
"Connection accepted\n");
153 int result = recv(tcp_dev->socket_connection,
154 (
void *) incoming_buffer,
155 INCOMING_BUFFER_SIZE, 0);
158 if (result > 0 && tcp_dev->rx_in_cb) {
167 rx_cb_all(tcp_dev, incoming_buffer, result);
178 else if (error == EINTR)
185 close(tcp_dev->socket_connection);
194 struct pios_thread *tcpRxTaskHandle;
197 pios_tcp_dev *tcp_dev =
PIOS_malloc(
sizeof(pios_tcp_dev));
199 memset(tcp_dev, 0,
sizeof(*tcp_dev));
202 tcp_dev->rx_in_cb = NULL;
203 tcp_dev->tx_out_cb = NULL;
207 tcp_dev->socket = socket(PF_INET6, SOCK_STREAM, IPPROTO_TCP);
210 #if defined(_WIN32) || defined(WIN32) || defined(__MINGW32__)
214 setsockopt(tcp_dev->socket, IPPROTO_IPV6, IPV6_V6ONLY, &optoff,
sizeof(optoff));
220 setsockopt(tcp_dev->socket, SOL_SOCKET, SO_REUSEADDR, &optval,
sizeof(optval));
223 setsockopt(tcp_dev->socket, IPPROTO_TCP, TCP_NODELAY, &optval,
sizeof(optval));
225 memset(&tcp_dev->server, 0,
sizeof(tcp_dev->server));
226 memset(&tcp_dev->client, 0,
sizeof(tcp_dev->client));
228 tcp_dev->server.sin6_family = AF_INET6;
229 tcp_dev->server.sin6_addr = in6addr_any;
230 tcp_dev->server.sin6_port = htons(tcp_dev->cfg->port);
232 int res = bind(tcp_dev->socket, (
struct sockaddr*)&tcp_dev->server,
sizeof(tcp_dev->server));
234 perror(
"Binding socket failed");
238 res = listen(tcp_dev->socket, 10);
240 perror(
"Socket listen failed");
247 printf(
"tcp dev %p - socket %i opened - result %i\n", tcp_dev, tcp_dev->socket, res);
249 *tcp_id = (uintptr_t) tcp_dev;
255 void PIOS_TCP_ChangeBaud(uintptr_t tcp_id, uint32_t baud)
263 static void PIOS_TCP_RxStart(uintptr_t tp_id, uint16_t rx_bytes_avail)
271 static void PIOS_TCP_TxStart(uintptr_t tcp_id, uint16_t tx_bytes_avail)
273 pios_tcp_dev *tcp_dev = find_tcp_dev_by_id(tcp_id);
282 if (tcp_dev->tx_out_cb) {
283 while (tx_bytes_avail > 0) {
284 bool tx_need_yield =
false;
285 length = (tcp_dev->tx_out_cb)(tcp_dev->tx_out_context, tcp_dev->tx_buffer,
PIOS_TCP_RX_BUFFER_SIZE, NULL, &tx_need_yield);
290 len = send(tcp_dev->socket_connection, (
char *) tcp_dev->tx_buffer, length, 0);
303 static void PIOS_TCP_RegisterRxCallback(uintptr_t tcp_id,
pios_com_callback rx_in_cb, uintptr_t context)
305 pios_tcp_dev *tcp_dev = find_tcp_dev_by_id(tcp_id);
313 tcp_dev->rx_in_context = context;
314 tcp_dev->rx_in_cb = rx_in_cb;
317 static void PIOS_TCP_RegisterTxCallback(uintptr_t tcp_id,
pios_com_callback tx_out_cb, uintptr_t context)
319 pios_tcp_dev *tcp_dev = find_tcp_dev_by_id(tcp_id);
327 tcp_dev->tx_out_context = context;
328 tcp_dev->tx_out_cb = tx_out_cb;
332 static bool PIOS_TCP_Available(uintptr_t tcp_id)
334 pios_tcp_dev *tcp_dev = find_tcp_dev_by_id(tcp_id);
Main PiOS header to include all the compiled in PiOS options.
void * PIOS_malloc(size_t size)
static struct flyingpicmd_cfg_fa cfg
#define PIOS_THREAD_STACK_SIZE_MIN
struct pios_thread * PIOS_Thread_Create(void(*fp)(void *), const char *namep, size_t stack_bytes, void *argp, enum pios_thread_prio_e prio)
void PIOS_Thread_Sleep(uint32_t time_ms)
int32_t PIOS_TCP_Init(uintptr_t *tcp_id, const struct pios_tcp_cfg *cfg)
int printf(const char *format,...)
const struct pios_com_driver pios_tcp_com_driver
#define PIOS_Assert(test)
#define PIOS_TCP_RX_BUFFER_SIZE
uint16_t(* pios_com_callback)(uintptr_t context, uint8_t *buf, uint16_t buf_len, uint16_t *headroom, bool *task_woken)
void(* set_baud)(uintptr_t id, uint32_t baud)