1 /**
2 * Copyright (c) 2018 Linaro
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6 #define LOG_LEVEL CONFIG_WIFI_LOG_LEVEL
7 #include "eswifi_log.h"
8 LOG_MODULE_DECLARE(LOG_MODULE_NAME);
9
10 #include <zephyr/kernel.h>
11 #include <zephyr/device.h>
12 #include <string.h>
13 #include <stdio.h>
14 #include <stdlib.h>
15 #include <errno.h>
16
17 #include <zephyr/net/net_pkt.h>
18 #include <zephyr/net/net_if.h>
19
20 #include "eswifi.h"
21
22
eswifi_off_bind(struct net_context * context,const struct sockaddr * addr,socklen_t addrlen)23 static int eswifi_off_bind(struct net_context *context,
24 const struct sockaddr *addr,
25 socklen_t addrlen)
26 {
27 struct eswifi_off_socket *socket = context->offload_context;
28 struct eswifi_dev *eswifi = eswifi_by_iface_idx(context->iface);
29 int err;
30
31 LOG_DBG("");
32 eswifi_lock(eswifi);
33 err = __eswifi_bind(eswifi, socket, addr, addrlen);
34 eswifi_unlock(eswifi);
35
36 return err;
37 }
38
eswifi_off_listen(struct net_context * context,int backlog)39 static int eswifi_off_listen(struct net_context *context, int backlog)
40 {
41 struct eswifi_off_socket *socket = context->offload_context;
42 struct eswifi_dev *eswifi = eswifi_by_iface_idx(context->iface);
43 int err;
44
45 LOG_DBG("Listening backlog=%d", backlog);
46
47 eswifi_lock(eswifi);
48
49 __select_socket(eswifi, socket->index);
50
51 /* Set backlog */
52 snprintk(eswifi->buf, sizeof(eswifi->buf), "P8=%d\r", backlog);
53 err = eswifi_at_cmd(eswifi, eswifi->buf);
54 if (err < 0) {
55 LOG_ERR("Unable to start set listen backlog");
56 err = -EIO;
57 }
58
59 socket->is_server = true;
60
61 eswifi_unlock(eswifi);
62
63 return err;
64 }
65
eswifi_off_connect_work(struct k_work * work)66 static void eswifi_off_connect_work(struct k_work *work)
67 {
68 struct eswifi_off_socket *socket;
69 net_context_connect_cb_t cb;
70 struct net_context *context;
71 struct eswifi_dev *eswifi;
72 void *user_data;
73 int err;
74
75 socket = CONTAINER_OF(work, struct eswifi_off_socket, connect_work);
76 eswifi = eswifi_socket_to_dev(socket);
77
78 eswifi_lock(eswifi);
79
80 cb = socket->conn_cb;
81 context = socket->context;
82 user_data = socket->conn_data;
83
84 err = __eswifi_off_start_client(eswifi, socket);
85 if (!err) {
86 socket->state = ESWIFI_SOCKET_STATE_CONNECTED;
87 net_context_set_state(socket->context, NET_CONTEXT_CONNECTED);
88 } else {
89 socket->state = ESWIFI_SOCKET_STATE_NONE;
90 }
91
92 eswifi_unlock(eswifi);
93
94 if (cb) {
95 cb(context, err, user_data);
96 }
97 }
98
eswifi_off_connect(struct net_context * context,const struct sockaddr * addr,socklen_t addrlen,net_context_connect_cb_t cb,int32_t timeout,void * user_data)99 static int eswifi_off_connect(struct net_context *context,
100 const struct sockaddr *addr,
101 socklen_t addrlen,
102 net_context_connect_cb_t cb,
103 int32_t timeout,
104 void *user_data)
105 {
106 struct eswifi_off_socket *socket = context->offload_context;
107 struct eswifi_dev *eswifi = eswifi_by_iface_idx(context->iface);
108 int err;
109
110 LOG_DBG("timeout=%d", timeout);
111
112 if (addr->sa_family != AF_INET) {
113 LOG_ERR("Only AF_INET is supported!");
114 return -EPFNOSUPPORT;
115 }
116
117 eswifi_lock(eswifi);
118
119 if (socket->state != ESWIFI_SOCKET_STATE_NONE) {
120 eswifi_unlock(eswifi);
121 return -EBUSY;
122 }
123
124 socket->peer_addr = *addr;
125 socket->conn_data = user_data;
126 socket->conn_cb = cb;
127 socket->state = ESWIFI_SOCKET_STATE_CONNECTING;
128
129 if (timeout == 0) {
130 /* async */
131 k_work_submit_to_queue(&eswifi->work_q, &socket->connect_work);
132 eswifi_unlock(eswifi);
133 return 0;
134 }
135
136 err = __eswifi_off_start_client(eswifi, socket);
137 if (!err) {
138 socket->state = ESWIFI_SOCKET_STATE_CONNECTED;
139 } else {
140 socket->state = ESWIFI_SOCKET_STATE_NONE;
141 }
142
143 eswifi_unlock(eswifi);
144
145 if (cb) {
146 cb(context, err, user_data);
147 }
148
149 return err;
150 }
151
eswifi_off_accept(struct net_context * context,net_tcp_accept_cb_t cb,int32_t timeout,void * user_data)152 static int eswifi_off_accept(struct net_context *context,
153 net_tcp_accept_cb_t cb, int32_t timeout,
154 void *user_data)
155 {
156 struct eswifi_off_socket *socket = context->offload_context;
157 struct eswifi_dev *eswifi = eswifi_by_iface_idx(context->iface);
158 int ret;
159
160 eswifi_lock(eswifi);
161
162 ret = __eswifi_accept(eswifi, socket);
163 if (ret < 0) {
164 eswifi_unlock(eswifi);
165 return ret;
166 }
167
168 socket->accept_cb = cb;
169 socket->accept_data = user_data;
170 k_sem_reset(&socket->accept_sem);
171
172 eswifi_unlock(eswifi);
173
174 if (timeout == 0) {
175 return 0;
176 }
177
178 return k_sem_take(&socket->accept_sem, K_MSEC(timeout));
179 }
180
__eswifi_off_send_pkt(struct eswifi_dev * eswifi,struct eswifi_off_socket * socket)181 static int __eswifi_off_send_pkt(struct eswifi_dev *eswifi,
182 struct eswifi_off_socket *socket)
183 {
184 struct net_pkt *pkt = socket->tx_pkt;
185 unsigned int bytes;
186 int err, offset;
187
188 LOG_DBG("");
189
190 if (!pkt) {
191 return -EINVAL;
192 }
193
194 bytes = net_pkt_get_len(pkt);
195
196 __select_socket(eswifi, socket->index);
197
198 /* header */
199 snprintk(eswifi->buf, sizeof(eswifi->buf), "S3=%u\r", bytes);
200 offset = strlen(eswifi->buf);
201
202 /* copy payload */
203 if (net_pkt_read(pkt, &eswifi->buf[offset], bytes)) {
204 return -ENOBUFS;
205 }
206
207 offset += bytes;
208
209 err = eswifi_request(eswifi, eswifi->buf, offset + 1,
210 eswifi->buf, sizeof(eswifi->buf));
211 if (err < 0) {
212 LOG_ERR("Unable to send data");
213 return -EIO;
214 }
215
216 net_pkt_unref(pkt);
217
218 return 0;
219 }
220
eswifi_off_send_work(struct k_work * work)221 static void eswifi_off_send_work(struct k_work *work)
222 {
223 struct eswifi_off_socket *socket;
224 net_context_send_cb_t cb;
225 struct net_context *context;
226 struct eswifi_dev *eswifi;
227 void *user_data;
228 int err;
229
230 socket = CONTAINER_OF(work, struct eswifi_off_socket, send_work);
231 eswifi = eswifi_socket_to_dev(socket);
232
233 eswifi_lock(eswifi);
234
235 user_data = socket->send_data;
236 cb = socket->send_cb;
237 context = socket->context;
238
239 err = __eswifi_off_send_pkt(eswifi, socket);
240 socket->tx_pkt = NULL;
241
242 eswifi_unlock(eswifi);
243
244 if (cb) {
245 cb(context, err, user_data);
246 }
247 }
248
eswifi_off_send(struct net_pkt * pkt,net_context_send_cb_t cb,int32_t timeout,void * user_data)249 static int eswifi_off_send(struct net_pkt *pkt,
250 net_context_send_cb_t cb,
251 int32_t timeout,
252 void *user_data)
253 {
254 struct eswifi_off_socket *socket = pkt->context->offload_context;
255 struct eswifi_dev *eswifi = eswifi_by_iface_idx(socket->context->iface);
256 int err;
257
258 LOG_DBG("timeout=%d", timeout);
259
260 eswifi_lock(eswifi);
261
262 if (socket->state != ESWIFI_SOCKET_STATE_CONNECTED) {
263 eswifi_unlock(eswifi);
264 return -ENOTCONN;
265 }
266
267 if (socket->tx_pkt) {
268 eswifi_unlock(eswifi);
269 return -EBUSY;
270 }
271 socket->tx_pkt = pkt;
272
273 if (timeout == 0) {
274 socket->send_data = user_data;
275 socket->send_cb = cb;
276
277 k_work_submit_to_queue(&eswifi->work_q, &socket->send_work);
278
279 eswifi_unlock(eswifi);
280
281 return 0;
282 }
283
284 err = __eswifi_off_send_pkt(eswifi, socket);
285 socket->tx_pkt = NULL;
286
287 eswifi_unlock(eswifi);
288
289 if (cb) {
290 cb(socket->context, err, user_data);
291 }
292
293 return err;
294 }
295
eswifi_off_sendto(struct net_pkt * pkt,const struct sockaddr * dst_addr,socklen_t addrlen,net_context_send_cb_t cb,int32_t timeout,void * user_data)296 static int eswifi_off_sendto(struct net_pkt *pkt,
297 const struct sockaddr *dst_addr,
298 socklen_t addrlen,
299 net_context_send_cb_t cb,
300 int32_t timeout,
301 void *user_data)
302 {
303 struct eswifi_off_socket *socket = pkt->context->offload_context;
304 struct eswifi_dev *eswifi = eswifi_by_iface_idx(socket->context->iface);
305 int err;
306
307 LOG_DBG("timeout=%d", timeout);
308
309 eswifi_lock(eswifi);
310
311 if (socket->tx_pkt) {
312 eswifi_unlock(eswifi);
313 return -EBUSY;
314 }
315
316 socket->tx_pkt = pkt;
317
318 if (socket->state != ESWIFI_SOCKET_STATE_CONNECTED) {
319 socket->peer_addr = *dst_addr;
320 err = __eswifi_off_start_client(eswifi, socket);
321 if (err < 0) {
322 eswifi_unlock(eswifi);
323 return err;
324 }
325
326 socket->state = ESWIFI_SOCKET_STATE_CONNECTED;
327 }
328
329 if (timeout == 0) {
330 socket->send_data = user_data;
331 socket->send_cb = cb;
332
333 k_work_submit_to_queue(&eswifi->work_q, &socket->send_work);
334
335 eswifi_unlock(eswifi);
336
337 return 0;
338 }
339
340 err = __eswifi_off_send_pkt(eswifi, socket);
341 socket->tx_pkt = NULL;
342
343 eswifi_unlock(eswifi);
344
345 if (cb) {
346 cb(socket->context, err, user_data);
347 }
348
349 return err;
350 }
351
eswifi_off_recv(struct net_context * context,net_context_recv_cb_t cb,int32_t timeout,void * user_data)352 static int eswifi_off_recv(struct net_context *context,
353 net_context_recv_cb_t cb,
354 int32_t timeout,
355 void *user_data)
356 {
357 struct eswifi_off_socket *socket = context->offload_context;
358 struct eswifi_dev *eswifi = eswifi_by_iface_idx(context->iface);
359 int err;
360
361
362 LOG_DBG("");
363
364 eswifi_lock(eswifi);
365 socket->recv_cb = cb;
366 socket->recv_data = user_data;
367 k_sem_reset(&socket->read_sem);
368 eswifi_unlock(eswifi);
369
370 if (timeout == 0) {
371 return 0;
372 }
373
374 err = k_sem_take(&socket->read_sem, K_MSEC(timeout));
375
376 /* Unregister callback */
377 eswifi_lock(eswifi);
378 socket->recv_cb = NULL;
379 eswifi_unlock(eswifi);
380
381 return err;
382 }
383
eswifi_off_put(struct net_context * context)384 static int eswifi_off_put(struct net_context *context)
385 {
386 struct eswifi_off_socket *socket = context->offload_context;
387 struct eswifi_dev *eswifi = eswifi_by_iface_idx(context->iface);
388 int ret;
389
390 LOG_DBG("");
391
392 eswifi_lock(eswifi);
393
394 ret = __eswifi_socket_free(eswifi, socket);
395 if (ret) {
396 goto done;
397 }
398
399 if (--socket->usage <= 0) {
400 socket->context = NULL;
401 }
402 done:
403 eswifi_unlock(eswifi);
404 return ret;
405 }
406
eswifi_off_get(sa_family_t family,enum net_sock_type type,enum net_ip_protocol ip_proto,struct net_context ** context)407 static int eswifi_off_get(sa_family_t family,
408 enum net_sock_type type,
409 enum net_ip_protocol ip_proto,
410 struct net_context **context)
411 {
412 struct eswifi_dev *eswifi = eswifi_by_iface_idx((*context)->iface);
413 struct eswifi_off_socket *socket = NULL;
414 int idx;
415
416 LOG_DBG("");
417
418 eswifi_lock(eswifi);
419
420 idx = __eswifi_socket_new(eswifi, family, type, ip_proto, *context);
421 if (idx < 0) {
422 goto unlock;
423 }
424
425 socket = &eswifi->socket[idx];
426 (*context)->offload_context = socket;
427
428 LOG_DBG("Socket index %d", socket->index);
429
430 k_work_init(&socket->connect_work, eswifi_off_connect_work);
431 k_work_init(&socket->send_work, eswifi_off_send_work);
432 k_sem_init(&socket->read_sem, 1, 1);
433 k_sem_init(&socket->accept_sem, 1, 1);
434
435 k_work_reschedule_for_queue(&eswifi->work_q, &socket->read_work,
436 K_MSEC(500));
437
438 unlock:
439 eswifi_unlock(eswifi);
440 return idx;
441 }
442
eswifi_offload_async_msg(struct eswifi_dev * eswifi,char * msg,size_t len)443 void eswifi_offload_async_msg(struct eswifi_dev *eswifi, char *msg, size_t len)
444 {
445 static const char msg_tcp_accept[] = "[TCP SVR] Accepted ";
446
447 if (!strncmp(msg, msg_tcp_accept, sizeof(msg_tcp_accept) - 1)) {
448 struct eswifi_off_socket *socket = NULL;
449 struct in_addr *sin_addr;
450 uint8_t ip[4];
451 uint16_t port = 0;
452 char *str;
453 int i = 0;
454
455 /* extract client ip/port e.g. 192.168.1.1:8080 */
456 /* TODO: use net_ipaddr_parse */
457 str = msg + sizeof(msg_tcp_accept) - 1;
458 while (*str) {
459 if (i < 4) {
460 ip[i++] = atoi(str);
461 } else if (i < 5) {
462 port = atoi(str);
463 break;
464 }
465
466 while (*str && (*str != '.') && (*str != ':')) {
467 str++;
468 }
469
470 str++;
471 }
472
473 for (i = 0; i < ESWIFI_OFFLOAD_MAX_SOCKETS; i++) {
474 struct eswifi_off_socket *s = &eswifi->socket[i];
475 if (s->context && s->port == port &&
476 s->state == ESWIFI_SOCKET_STATE_ACCEPTING) {
477 socket = s;
478 break;
479 }
480 }
481
482 if (!socket) {
483 LOG_ERR("No listening socket");
484 return;
485 }
486
487 struct sockaddr_in *peer = net_sin(&socket->peer_addr);
488
489 sin_addr = &peer->sin_addr;
490 memcpy(&sin_addr->s4_addr, ip, 4);
491 peer->sin_port = htons(port);
492 peer->sin_family = AF_INET;
493 socket->state = ESWIFI_SOCKET_STATE_CONNECTED;
494 socket->usage++;
495
496 /* Save information about remote. */
497 socket->context->flags |= NET_CONTEXT_REMOTE_ADDR_SET;
498 memcpy(&socket->context->remote, &socket->peer_addr,
499 sizeof(struct sockaddr));
500
501 LOG_DBG("%u.%u.%u.%u connected to port %u",
502 ip[0], ip[1], ip[2], ip[3], port);
503
504 if (socket->accept_cb) {
505 socket->accept_cb(socket->context,
506 &socket->peer_addr,
507 sizeof(struct sockaddr_in), 0,
508 socket->accept_data);
509 }
510
511 k_sem_give(&socket->accept_sem);
512 k_yield();
513 }
514 }
515
516 static struct net_offload eswifi_offload = {
517 .get = eswifi_off_get,
518 .bind = eswifi_off_bind,
519 .listen = eswifi_off_listen,
520 .connect = eswifi_off_connect,
521 .accept = eswifi_off_accept,
522 .send = eswifi_off_send,
523 .sendto = eswifi_off_sendto,
524 .recv = eswifi_off_recv,
525 .put = eswifi_off_put,
526 };
527
eswifi_off_enable_dhcp(struct eswifi_dev * eswifi)528 static int eswifi_off_enable_dhcp(struct eswifi_dev *eswifi)
529 {
530 char cmd[] = "C4=1\r";
531 int err;
532
533 LOG_DBG("");
534
535 eswifi_lock(eswifi);
536
537 err = eswifi_at_cmd(eswifi, cmd);
538
539 eswifi_unlock(eswifi);
540
541 return 0;
542 }
543
eswifi_off_disable_bypass(struct eswifi_dev * eswifi)544 static int eswifi_off_disable_bypass(struct eswifi_dev *eswifi)
545 {
546 char cmd[] = "PR=0\r";
547 int err;
548
549 LOG_DBG("");
550
551 eswifi_lock(eswifi);
552
553 err = eswifi_at_cmd(eswifi, cmd);
554
555 eswifi_unlock(eswifi);
556
557 return err;
558 }
559
eswifi_offload_init(struct eswifi_dev * eswifi)560 int eswifi_offload_init(struct eswifi_dev *eswifi)
561 {
562 eswifi->iface->if_dev->offload = &eswifi_offload;
563 int err;
564
565 err = eswifi_off_enable_dhcp(eswifi);
566 if (err < 0) {
567 LOG_ERR("Unable to configure dhcp");
568 return err;
569 }
570
571 err = eswifi_off_disable_bypass(eswifi);
572 if (err < 0) {
573 LOG_ERR("Unable to disable bypass mode");
574 return err;
575 }
576
577 return 0;
578 }
579