1 /**
2 * Copyright (c) 2017 IpTronix
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #define LOG_MODULE_NAME wifi_winc1500
8 #define LOG_LEVEL CONFIG_WIFI_LOG_LEVEL
9
10 #include <zephyr/logging/log.h>
11 LOG_MODULE_REGISTER(LOG_MODULE_NAME);
12
13 #include <zephyr/kernel.h>
14 #include <zephyr/debug/stack.h>
15 #include <zephyr/device.h>
16 #include <string.h>
17 #include <errno.h>
18 #include <zephyr/net/net_pkt.h>
19 #include <zephyr/net/net_if.h>
20 #include <zephyr/net/net_l2.h>
21 #include <zephyr/net/net_context.h>
22 #include <zephyr/net/net_offload.h>
23 #include <zephyr/net/wifi_mgmt.h>
24 #include <zephyr/net/conn_mgr/connectivity_wifi_mgmt.h>
25
26 #include <zephyr/sys/printk.h>
27
28 /* We do not need <socket/include/socket.h>
29 * It seems there is a bug in ASF side: if OS is already defining sockaddr
30 * and all, ASF will not need to define it. Unfortunately its socket.h does
31 * but also defines some NM API functions there (??), so we need to redefine
32 * those here.
33 */
34 #define __SOCKET_H__
35 #define HOSTNAME_MAX_SIZE (64)
36
37 #include <driver/include/m2m_wifi.h>
38 #include <socket/include/m2m_socket_host_if.h>
39
40 NMI_API void socketInit(void);
41 typedef void (*tpfAppSocketCb) (SOCKET sock, uint8 u8Msg, void *pvMsg);
42 typedef void (*tpfAppResolveCb) (uint8 *pu8DomainName, uint32 u32ServerIP);
43 NMI_API void registerSocketCallback(tpfAppSocketCb socket_cb,
44 tpfAppResolveCb resolve_cb);
45 NMI_API SOCKET winc1500_socket(uint16 u16Domain, uint8 u8Type, uint8 u8Flags);
46 NMI_API sint8 winc1500_socket_bind(SOCKET sock, struct sockaddr *pstrAddr, uint8 u8AddrLen);
47 NMI_API sint8 winc1500_socket_listen(SOCKET sock, uint8 backlog);
48 NMI_API sint8 winc1500_socket_accept(SOCKET sock, struct sockaddr *addr, uint8 *addrlen);
49 NMI_API sint8 winc1500_socket_connect(SOCKET sock, struct sockaddr *pstrAddr, uint8 u8AddrLen);
50 NMI_API sint16 winc1500_socket_recv(SOCKET sock, void *pvRecvBuf,
51 uint16 u16BufLen, uint32 u32Timeoutmsec);
52 NMI_API sint16 winc1500_socket_send(SOCKET sock, void *pvSendBuffer,
53 uint16 u16SendLength, uint16 u16Flags);
54 NMI_API sint16 winc1500_socket_sendto(SOCKET sock, void *pvSendBuffer,
55 uint16 u16SendLength, uint16 flags,
56 struct sockaddr *pstrDestAddr, uint8 u8AddrLen);
57 NMI_API sint8 winc1500_close(SOCKET sock);
58
59 enum socket_errors {
60 SOCK_ERR_NO_ERROR = 0,
61 SOCK_ERR_INVALID_ADDRESS = -1,
62 SOCK_ERR_ADDR_ALREADY_IN_USE = -2,
63 SOCK_ERR_MAX_TCP_SOCK = -3,
64 SOCK_ERR_MAX_UDP_SOCK = -4,
65 SOCK_ERR_INVALID_ARG = -6,
66 SOCK_ERR_MAX_LISTEN_SOCK = -7,
67 SOCK_ERR_INVALID = -9,
68 SOCK_ERR_ADDR_IS_REQUIRED = -11,
69 SOCK_ERR_CONN_ABORTED = -12,
70 SOCK_ERR_TIMEOUT = -13,
71 SOCK_ERR_BUFFER_FULL = -14,
72 };
73
74 enum socket_messages {
75 SOCKET_MSG_BIND = 1,
76 SOCKET_MSG_LISTEN,
77 SOCKET_MSG_DNS_RESOLVE,
78 SOCKET_MSG_ACCEPT,
79 SOCKET_MSG_CONNECT,
80 SOCKET_MSG_RECV,
81 SOCKET_MSG_SEND,
82 SOCKET_MSG_SENDTO,
83 SOCKET_MSG_RECVFROM,
84 };
85
86 typedef struct {
87 sint8 status;
88 } tstrSocketBindMsg;
89
90 typedef struct {
91 sint8 status;
92 } tstrSocketListenMsg;
93
94 typedef struct {
95 SOCKET sock;
96 struct sockaddr_in strAddr;
97 } tstrSocketAcceptMsg;
98
99 typedef struct {
100 SOCKET sock;
101 sint8 s8Error;
102 } tstrSocketConnectMsg;
103
104 typedef struct {
105 uint8 *pu8Buffer;
106 sint16 s16BufferSize;
107 uint16 u16RemainingSize;
108 struct sockaddr_in strRemoteAddr;
109 } tstrSocketRecvMsg;
110
111 #include <driver/include/m2m_wifi.h>
112 #include <socket/include/m2m_socket_host_if.h>
113
114 #if defined(CONFIG_WIFI_WINC1500_REGION_NORTH_AMERICA)
115 #define WINC1500_REGION NORTH_AMERICA
116 #elif defined(CONFIG_WIFI_WINC1500_REGION_EUROPE)
117 #define WINC1500_REGION EUROPE
118 #elif defined(CONFIG_WIFI_WINC1500_REGION_ASIA)
119 #define WINC1500_REGION ASIA
120 #endif
121
122 #define WINC1500_BIND_TIMEOUT K_MSEC(500)
123 #define WINC1500_LISTEN_TIMEOUT K_MSEC(500)
124 #define WINC1500_BUF_TIMEOUT K_MSEC(100)
125
126 NET_BUF_POOL_DEFINE(winc1500_tx_pool, CONFIG_WIFI_WINC1500_BUF_CTR,
127 CONFIG_WIFI_WINC1500_MAX_PACKET_SIZE, 0, NULL);
128 NET_BUF_POOL_DEFINE(winc1500_rx_pool, CONFIG_WIFI_WINC1500_BUF_CTR,
129 CONFIG_WIFI_WINC1500_MAX_PACKET_SIZE, 0, NULL);
130
131 K_KERNEL_STACK_MEMBER(winc1500_stack, CONFIG_WIFI_WINC1500_THREAD_STACK_SIZE);
132 struct k_thread winc1500_thread_data;
133
134 struct socket_data {
135 struct net_context *context;
136 net_context_connect_cb_t connect_cb;
137 net_tcp_accept_cb_t accept_cb;
138 net_context_recv_cb_t recv_cb;
139 void *connect_user_data;
140 void *recv_user_data;
141 void *accept_user_data;
142 struct net_pkt *rx_pkt;
143 struct net_buf *pkt_buf;
144 int ret_code;
145 struct k_sem wait_sem;
146 };
147
148 struct winc1500_data {
149 struct socket_data socket_data[
150 CONFIG_WIFI_WINC1500_OFFLOAD_MAX_SOCKETS];
151 struct net_if *iface;
152 unsigned char mac[6];
153 scan_result_cb_t scan_cb;
154 uint8_t scan_result;
155 bool connecting;
156 bool connected;
157 };
158
159 static struct winc1500_data w1500_data;
160
161 #if LOG_LEVEL > LOG_LEVEL_OFF
stack_stats(void)162 static void stack_stats(void)
163 {
164 log_stack_usage(&winc1500_thread_data);
165 }
166 #endif /* LOG_LEVEL > LOG_LEVEL_OFF */
167
socket_error_string(int8_t err)168 static char *socket_error_string(int8_t err)
169 {
170 switch (err) {
171 case SOCK_ERR_NO_ERROR:
172 return "Successful socket operation";
173 case SOCK_ERR_INVALID_ADDRESS:
174 return "Socket address is invalid."
175 "The socket operation cannot be completed successfully"
176 " without specifying a specific address. "
177 "For example: bind is called without specifying"
178 " a port number";
179 case SOCK_ERR_ADDR_ALREADY_IN_USE:
180 return "Socket operation cannot bind on the given address."
181 " With socket operations, only one IP address per "
182 "socket is permitted. Any attempt for a new socket "
183 "to bind with an IP address already bound to another "
184 "open socket, will return the following error code. "
185 "States that bind operation failed.";
186 case SOCK_ERR_MAX_TCP_SOCK:
187 return "Exceeded the maximum number of TCP sockets."
188 "A maximum number of TCP sockets opened simultaneously"
189 " is defined through TCP_SOCK_MAX. It is not permitted"
190 " to exceed that number at socket creation."
191 " Identifies that @ref socket operation failed.";
192 case SOCK_ERR_MAX_UDP_SOCK:
193 return "Exceeded the maximum number of UDP sockets."
194 "A maximum number of UDP sockets opened simultaneously"
195 " is defined through UDP_SOCK_MAX. It is not permitted"
196 " to exceed that number at socket creation."
197 " Identifies that socket operation failed";
198 case SOCK_ERR_INVALID_ARG:
199 return "An invalid argument is passed to a function.";
200 case SOCK_ERR_MAX_LISTEN_SOCK:
201 return "Exceeded the maximum number of TCP passive listening "
202 "sockets. Identifies Identifies that listen operation"
203 " failed.";
204 case SOCK_ERR_INVALID:
205 return "The requested socket operation is not valid in the "
206 "current socket state. For example: @ref accept is "
207 "called on a TCP socket before bind or listen.";
208 case SOCK_ERR_ADDR_IS_REQUIRED:
209 return "Destination address is required. Failure to provide "
210 "the socket address required for the socket operation "
211 "to be completed. It is generated as an error to the "
212 "sendto function when the address required to send the"
213 " data to is not known.";
214 case SOCK_ERR_CONN_ABORTED:
215 return "The socket is closed by the peer. The local socket is "
216 "also closed.";
217 case SOCK_ERR_TIMEOUT:
218 return "The socket pending operation has timedout.";
219 case SOCK_ERR_BUFFER_FULL:
220 return "No buffer space available to be used for the requested"
221 " socket operation.";
222 default:
223 return "Unknown";
224 }
225 }
226
wifi_cb_msg_2_str(uint8_t message_type)227 static char *wifi_cb_msg_2_str(uint8_t message_type)
228 {
229 switch (message_type) {
230 case M2M_WIFI_RESP_CURRENT_RSSI:
231 return "M2M_WIFI_RESP_CURRENT_RSSI";
232 case M2M_WIFI_REQ_WPS:
233 return "M2M_WIFI_REQ_WPS";
234 case M2M_WIFI_RESP_IP_CONFIGURED:
235 return "M2M_WIFI_RESP_IP_CONFIGURED";
236 case M2M_WIFI_RESP_IP_CONFLICT:
237 return "M2M_WIFI_RESP_IP_CONFLICT";
238 case M2M_WIFI_RESP_CLIENT_INFO:
239 return "M2M_WIFI_RESP_CLIENT_INFO";
240
241 case M2M_WIFI_RESP_GET_SYS_TIME:
242 return "M2M_WIFI_RESP_GET_SYS_TIME";
243 case M2M_WIFI_REQ_SEND_ETHERNET_PACKET:
244 return "M2M_WIFI_REQ_SEND_ETHERNET_PACKET";
245 case M2M_WIFI_RESP_ETHERNET_RX_PACKET:
246 return "M2M_WIFI_RESP_ETHERNET_RX_PACKET";
247
248 case M2M_WIFI_RESP_CON_STATE_CHANGED:
249 return "M2M_WIFI_RESP_CON_STATE_CHANGED";
250 case M2M_WIFI_REQ_DHCP_CONF:
251 return "Response indicating that IP address was obtained.";
252 case M2M_WIFI_RESP_SCAN_DONE:
253 return "M2M_WIFI_RESP_SCAN_DONE";
254 case M2M_WIFI_RESP_SCAN_RESULT:
255 return "M2M_WIFI_RESP_SCAN_RESULT";
256 case M2M_WIFI_RESP_PROVISION_INFO:
257 return "M2M_WIFI_RESP_PROVISION_INFO";
258 default:
259 return "UNKNOWN";
260 }
261 }
262
socket_message_to_string(uint8_t message)263 static char *socket_message_to_string(uint8_t message)
264 {
265 switch (message) {
266 case SOCKET_MSG_BIND:
267 return "Bind socket event.";
268 case SOCKET_MSG_LISTEN:
269 return "Listen socket event.";
270 case SOCKET_MSG_DNS_RESOLVE:
271 return "DNS Resolution event.";
272 case SOCKET_MSG_ACCEPT:
273 return "Accept socket event.";
274 case SOCKET_MSG_CONNECT:
275 return "Connect socket event.";
276 case SOCKET_MSG_RECV:
277 return "Receive socket event.";
278 case SOCKET_MSG_SEND:
279 return "Send socket event.";
280 case SOCKET_MSG_SENDTO:
281 return "Sendto socket event.";
282 case SOCKET_MSG_RECVFROM:
283 return "Recvfrom socket event.";
284 default:
285 return "UNKNOWN.";
286 }
287 }
288
289 /**
290 * This function is called when the socket is to be opened.
291 */
winc1500_get(sa_family_t family,enum net_sock_type type,enum net_ip_protocol ip_proto,struct net_context ** context)292 static int winc1500_get(sa_family_t family,
293 enum net_sock_type type,
294 enum net_ip_protocol ip_proto,
295 struct net_context **context)
296 {
297 struct socket_data *sd;
298 SOCKET sock;
299
300 if (family != AF_INET) {
301 LOG_ERR("Only AF_INET is supported!");
302 return -1;
303 }
304
305 /* winc1500 atmel uses AF_INET 2 instead of zephyrs AF_INET 1
306 * we have checked if family is AF_INET so we can hardcode this
307 * for now.
308 */
309 sock = winc1500_socket(2, type, 0);
310 if (sock < 0) {
311 LOG_ERR("socket error!");
312 return -1;
313 }
314
315 (*context)->offload_context = (void *)(intptr_t)sock;
316 sd = &w1500_data.socket_data[sock];
317
318 k_sem_init(&sd->wait_sem, 0, 1);
319
320 sd->context = *context;
321
322 return 0;
323 }
324
325 /**
326 * This function is called when user wants to bind to local IP address.
327 */
winc1500_bind(struct net_context * context,const struct sockaddr * addr,socklen_t addrlen)328 static int winc1500_bind(struct net_context *context,
329 const struct sockaddr *addr,
330 socklen_t addrlen)
331 {
332 SOCKET socket = (intptr_t)context->offload_context;
333 int ret;
334
335 /* FIXME atmel winc1500 don't support bind on null port */
336 if (net_sin(addr)->sin_port == 0U) {
337 return 0;
338 }
339
340 ret = winc1500_socket_bind((intptr_t)context->offload_context, (struct sockaddr *)addr,
341 addrlen);
342 if (ret) {
343 LOG_ERR("bind error %d %s!",
344 ret, socket_message_to_string(ret));
345 return ret;
346 }
347
348 if (k_sem_take(&w1500_data.socket_data[socket].wait_sem,
349 WINC1500_BIND_TIMEOUT)) {
350 LOG_ERR("bind error timeout expired");
351 return -ETIMEDOUT;
352 }
353
354 return w1500_data.socket_data[socket].ret_code;
355 }
356
357 /**
358 * This function is called when user wants to mark the socket
359 * to be a listening one.
360 */
winc1500_listen(struct net_context * context,int backlog)361 static int winc1500_listen(struct net_context *context, int backlog)
362 {
363 SOCKET socket = (intptr_t)context->offload_context;
364 int ret;
365
366 ret = winc1500_socket_listen((intptr_t)context->offload_context, backlog);
367 if (ret) {
368 LOG_ERR("listen error %d %s!",
369 ret, socket_error_string(ret));
370 return ret;
371 }
372
373 if (k_sem_take(&w1500_data.socket_data[socket].wait_sem,
374 WINC1500_LISTEN_TIMEOUT)) {
375 return -ETIMEDOUT;
376 }
377
378 return w1500_data.socket_data[socket].ret_code;
379 }
380
381 /**
382 * This function is called when user wants to create a connection
383 * to a peer host.
384 */
winc1500_connect(struct net_context * context,const struct sockaddr * addr,socklen_t addrlen,net_context_connect_cb_t cb,int32_t timeout,void * user_data)385 static int winc1500_connect(struct net_context *context,
386 const struct sockaddr *addr,
387 socklen_t addrlen,
388 net_context_connect_cb_t cb,
389 int32_t timeout,
390 void *user_data)
391 {
392 SOCKET socket = (intptr_t)context->offload_context;
393 int ret;
394
395 w1500_data.socket_data[socket].connect_cb = cb;
396 w1500_data.socket_data[socket].connect_user_data = user_data;
397 w1500_data.socket_data[socket].ret_code = 0;
398
399 ret = winc1500_socket_connect(socket, (struct sockaddr *)addr, addrlen);
400 if (ret) {
401 LOG_ERR("connect error %d %s!",
402 ret, socket_error_string(ret));
403 return ret;
404 }
405
406 if (timeout != 0 &&
407 k_sem_take(&w1500_data.socket_data[socket].wait_sem, K_MSEC(timeout))) {
408 return -ETIMEDOUT;
409 }
410
411 return w1500_data.socket_data[socket].ret_code;
412 }
413
414 /**
415 * This function is called when user wants to accept a connection
416 * being established.
417 */
winc1500_accept(struct net_context * context,net_tcp_accept_cb_t cb,int32_t timeout,void * user_data)418 static int winc1500_accept(struct net_context *context,
419 net_tcp_accept_cb_t cb,
420 int32_t timeout,
421 void *user_data)
422 {
423 SOCKET socket = (intptr_t)context->offload_context;
424 int ret;
425
426 w1500_data.socket_data[socket].accept_cb = cb;
427 w1500_data.socket_data[socket].accept_user_data = user_data;
428
429 ret = winc1500_socket_accept(socket, NULL, 0);
430 if (ret) {
431 LOG_ERR("accept error %d %s!",
432 ret, socket_error_string(ret));
433 return ret;
434 }
435
436 if (timeout) {
437 if (k_sem_take(&w1500_data.socket_data[socket].wait_sem,
438 K_MSEC(timeout))) {
439 return -ETIMEDOUT;
440 }
441 }
442
443 return w1500_data.socket_data[socket].ret_code;
444 }
445
446 /**
447 * This function is called when user wants to send data to peer host.
448 */
winc1500_send(struct net_pkt * pkt,net_context_send_cb_t cb,int32_t timeout,void * user_data)449 static int winc1500_send(struct net_pkt *pkt,
450 net_context_send_cb_t cb,
451 int32_t timeout,
452 void *user_data)
453 {
454 struct net_context *context = pkt->context;
455 SOCKET socket = (intptr_t)context->offload_context;
456 int ret = 0;
457 struct net_buf *buf;
458
459 buf = net_buf_alloc(&winc1500_tx_pool, WINC1500_BUF_TIMEOUT);
460 if (!buf) {
461 return -ENOBUFS;
462 }
463
464 if (net_pkt_read(pkt, buf->data, net_pkt_get_len(pkt))) {
465 ret = -ENOBUFS;
466 goto out;
467 }
468
469 net_buf_add(buf, net_pkt_get_len(pkt));
470
471 ret = winc1500_socket_send(socket, buf->data, buf->len, 0);
472 if (ret) {
473 LOG_ERR("send error %d %s!", ret, socket_error_string(ret));
474 goto out;
475 }
476
477 net_pkt_unref(pkt);
478 out:
479 net_buf_unref(buf);
480
481 return ret;
482 }
483
484 /**
485 * This function is called when user wants to send data to peer host.
486 */
winc1500_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)487 static int winc1500_sendto(struct net_pkt *pkt,
488 const struct sockaddr *dst_addr,
489 socklen_t addrlen,
490 net_context_send_cb_t cb,
491 int32_t timeout,
492 void *user_data)
493 {
494 struct net_context *context = pkt->context;
495 SOCKET socket = (intptr_t)context->offload_context;
496 int ret = 0;
497 struct net_buf *buf;
498
499 buf = net_buf_alloc(&winc1500_tx_pool, WINC1500_BUF_TIMEOUT);
500 if (!buf) {
501 return -ENOBUFS;
502 }
503
504 if (net_pkt_read(pkt, buf->data, net_pkt_get_len(pkt))) {
505 ret = -ENOBUFS;
506 goto out;
507 }
508
509 net_buf_add(buf, net_pkt_get_len(pkt));
510
511 ret = winc1500_socket_sendto(socket, buf->data, buf->len, 0,
512 (struct sockaddr *)dst_addr, addrlen);
513 if (ret) {
514 LOG_ERR("sendto error %d %s!", ret, socket_error_string(ret));
515 goto out;
516 }
517
518 net_pkt_unref(pkt);
519 out:
520 net_buf_unref(buf);
521
522 return ret;
523 }
524
525 /**
526 */
prepare_pkt(struct socket_data * sock_data)527 static int prepare_pkt(struct socket_data *sock_data)
528 {
529 /* Get the frame from the buffer */
530 sock_data->rx_pkt = net_pkt_rx_alloc_on_iface(w1500_data.iface,
531 K_NO_WAIT);
532 if (!sock_data->rx_pkt) {
533 LOG_ERR("Could not allocate rx packet");
534 return -1;
535 }
536
537 /* Reserve a data buffer to receive the frame */
538 sock_data->pkt_buf = net_buf_alloc(&winc1500_rx_pool, K_NO_WAIT);
539 if (!sock_data->pkt_buf) {
540 LOG_ERR("Could not allocate data buffer");
541 net_pkt_unref(sock_data->rx_pkt);
542 return -1;
543 }
544
545 net_pkt_append_buffer(sock_data->rx_pkt, sock_data->pkt_buf);
546
547 return 0;
548 }
549
550 /**
551 * This function is called when user wants to receive data from peer
552 * host.
553 */
winc1500_recv(struct net_context * context,net_context_recv_cb_t cb,int32_t timeout,void * user_data)554 static int winc1500_recv(struct net_context *context,
555 net_context_recv_cb_t cb,
556 int32_t timeout,
557 void *user_data)
558 {
559 SOCKET socket = (intptr_t)context->offload_context;
560 int ret;
561
562 w1500_data.socket_data[socket].recv_cb = cb;
563 w1500_data.socket_data[socket].recv_user_data = user_data;
564 if (!cb) {
565 return 0;
566 }
567
568 ret = prepare_pkt(&w1500_data.socket_data[socket]);
569 if (ret) {
570 LOG_ERR("Could not reserve packet buffer");
571 return -ENOMEM;
572 }
573
574
575 ret = winc1500_socket_recv(socket, w1500_data.socket_data[socket].pkt_buf->data,
576 CONFIG_WIFI_WINC1500_MAX_PACKET_SIZE, timeout);
577 if (ret) {
578 LOG_ERR("recv error %d %s!",
579 ret, socket_error_string(ret));
580 return ret;
581 }
582
583 return 0;
584 }
585
586 /**
587 * This function is called when user wants to close the socket.
588 */
winc1500_put(struct net_context * context)589 static int winc1500_put(struct net_context *context)
590 {
591 SOCKET sock = (intptr_t)context->offload_context;
592 struct socket_data *sd = &w1500_data.socket_data[sock];
593 int ret;
594
595 memset(&(context->remote), 0, sizeof(struct sockaddr_in));
596 context->flags &= ~NET_CONTEXT_REMOTE_ADDR_SET;
597 ret = winc1500_close(sock);
598
599 net_pkt_unref(sd->rx_pkt);
600
601 memset(sd, 0, sizeof(struct socket_data));
602
603 return ret;
604 }
605
606 static struct net_offload winc1500_offload = {
607 .get = winc1500_get,
608 .bind = winc1500_bind,
609 .listen = winc1500_listen,
610 .connect = winc1500_connect,
611 .accept = winc1500_accept,
612 .send = winc1500_send,
613 .sendto = winc1500_sendto,
614 .recv = winc1500_recv,
615 .put = winc1500_put,
616 };
617
handle_wifi_con_state_changed(void * pvMsg)618 static void handle_wifi_con_state_changed(void *pvMsg)
619 {
620 tstrM2mWifiStateChanged *pstrWifiState =
621 (tstrM2mWifiStateChanged *)pvMsg;
622
623 switch (pstrWifiState->u8CurrState) {
624 case M2M_WIFI_DISCONNECTED:
625 LOG_DBG("Disconnected (%u)", pstrWifiState->u8ErrCode);
626
627 if (w1500_data.connecting) {
628 wifi_mgmt_raise_connect_result_event(w1500_data.iface,
629 pstrWifiState->u8ErrCode ? -EIO : 0);
630 w1500_data.connecting = false;
631
632 break;
633 }
634
635 w1500_data.connected = false;
636 wifi_mgmt_raise_disconnect_result_event(w1500_data.iface, 0);
637
638 break;
639 case M2M_WIFI_CONNECTED:
640 LOG_DBG("Connected (%u)", pstrWifiState->u8ErrCode);
641
642 w1500_data.connected = true;
643 w1500_data.connecting = false;
644 wifi_mgmt_raise_connect_result_event(w1500_data.iface, 0);
645
646 break;
647 case M2M_WIFI_UNDEF:
648 /* TODO status undefined*/
649 LOG_DBG("Undefined?");
650 break;
651 }
652 }
653
handle_wifi_dhcp_conf(void * pvMsg)654 static void handle_wifi_dhcp_conf(void *pvMsg)
655 {
656 uint8_t *pu8IPAddress = (uint8_t *)pvMsg;
657 struct in_addr addr;
658 uint8_t i;
659
660 /* Connected and got IP address*/
661 LOG_DBG("Wi-Fi connected, IP is %u.%u.%u.%u",
662 pu8IPAddress[0], pu8IPAddress[1],
663 pu8IPAddress[2], pu8IPAddress[3]);
664
665 /* TODO at this point the standby mode should be enable
666 * status = WiFi connected IP assigned
667 */
668 for (i = 0U; i < 4; i++) {
669 addr.s4_addr[i] = pu8IPAddress[i];
670 }
671
672 /* TODO fill in net mask, gateway and lease time */
673
674 net_if_ipv4_addr_add(w1500_data.iface, &addr, NET_ADDR_DHCP, 0);
675 }
676
reset_scan_data(void)677 static void reset_scan_data(void)
678 {
679 w1500_data.scan_cb = NULL;
680 w1500_data.scan_result = 0U;
681 }
682
handle_scan_result(void * pvMsg)683 static void handle_scan_result(void *pvMsg)
684 {
685 tstrM2mWifiscanResult *pstrScanResult = (tstrM2mWifiscanResult *)pvMsg;
686 struct wifi_scan_result result = { 0 };
687
688 if (!w1500_data.scan_cb) {
689 return;
690 }
691
692 if (pstrScanResult->u8AuthType == M2M_WIFI_SEC_OPEN) {
693 result.security = WIFI_SECURITY_TYPE_NONE;
694 } else if (pstrScanResult->u8AuthType == M2M_WIFI_SEC_WPA_PSK) {
695 result.security = WIFI_SECURITY_TYPE_PSK;
696 } else {
697 LOG_DBG("Security %u not supported",
698 pstrScanResult->u8AuthType);
699 goto out;
700 }
701
702 memcpy(result.ssid, pstrScanResult->au8SSID, WIFI_SSID_MAX_LEN);
703 result.ssid_length = strlen(result.ssid);
704
705 result.channel = pstrScanResult->u8ch;
706 result.rssi = pstrScanResult->s8rssi;
707
708 w1500_data.scan_cb(w1500_data.iface, 0, &result);
709
710 k_yield();
711
712 out:
713 if (w1500_data.scan_result < m2m_wifi_get_num_ap_found()) {
714 m2m_wifi_req_scan_result(w1500_data.scan_result);
715 w1500_data.scan_result++;
716 } else {
717 w1500_data.scan_cb(w1500_data.iface, 0, NULL);
718 reset_scan_data();
719 }
720 }
721
handle_scan_done(void * pvMsg)722 static void handle_scan_done(void *pvMsg)
723 {
724 tstrM2mScanDone *pstrInfo = (tstrM2mScanDone *)pvMsg;
725
726 if (!w1500_data.scan_cb) {
727 return;
728 }
729
730 if (pstrInfo->s8ScanState != M2M_SUCCESS) {
731 w1500_data.scan_cb(w1500_data.iface, -EIO, NULL);
732 reset_scan_data();
733
734 LOG_ERR("Scan failed.");
735
736 return;
737 }
738
739 w1500_data.scan_result = 0U;
740
741 if (pstrInfo->u8NumofCh >= 1) {
742 LOG_DBG("Requesting results (%u)",
743 m2m_wifi_get_num_ap_found());
744
745 m2m_wifi_req_scan_result(w1500_data.scan_result);
746 w1500_data.scan_result++;
747 } else {
748 LOG_DBG("No AP found");
749
750 w1500_data.scan_cb(w1500_data.iface, 0, NULL);
751 reset_scan_data();
752 }
753 }
754
winc1500_wifi_cb(uint8_t message_type,void * pvMsg)755 static void winc1500_wifi_cb(uint8_t message_type, void *pvMsg)
756 {
757 LOG_DBG("Msg Type %d %s",
758 message_type, wifi_cb_msg_2_str(message_type));
759
760 switch (message_type) {
761 case M2M_WIFI_RESP_CON_STATE_CHANGED:
762 handle_wifi_con_state_changed(pvMsg);
763 break;
764 case M2M_WIFI_REQ_DHCP_CONF:
765 handle_wifi_dhcp_conf(pvMsg);
766 break;
767 case M2M_WIFI_RESP_SCAN_RESULT:
768 handle_scan_result(pvMsg);
769 break;
770 case M2M_WIFI_RESP_SCAN_DONE:
771 handle_scan_done(pvMsg);
772 break;
773 default:
774 break;
775 }
776 #if LOG_LEVEL > LOG_LEVEL_OFF
777 stack_stats();
778 #endif /* LOG_LEVEL > LOG_LEVEL_OFF */
779 }
780
handle_socket_msg_connect(struct socket_data * sd,void * pvMsg)781 static void handle_socket_msg_connect(struct socket_data *sd, void *pvMsg)
782 {
783 tstrSocketConnectMsg *strConnMsg = (tstrSocketConnectMsg *)pvMsg;
784
785 LOG_ERR("CONNECT: socket %d error %d",
786 strConnMsg->sock, strConnMsg->s8Error);
787
788 if (!strConnMsg->s8Error) {
789 net_context_set_state(sd->context, NET_CONTEXT_CONNECTED);
790 }
791
792 if (sd->connect_cb) {
793 sd->connect_cb(sd->context,
794 strConnMsg->s8Error,
795 sd->connect_user_data);
796 }
797
798 sd->ret_code = strConnMsg->s8Error;
799 }
800
801
handle_socket_msg_recv(SOCKET sock,struct socket_data * sd,void * pvMsg)802 static bool handle_socket_msg_recv(SOCKET sock,
803 struct socket_data *sd, void *pvMsg)
804 {
805 tstrSocketRecvMsg *pstrRx = (tstrSocketRecvMsg *)pvMsg;
806
807 if ((pstrRx->pu8Buffer != NULL) && (pstrRx->s16BufferSize > 0)) {
808 net_buf_add(sd->pkt_buf, pstrRx->s16BufferSize);
809 net_pkt_cursor_init(sd->rx_pkt);
810
811 if (sd->recv_cb) {
812 sd->recv_cb(sd->context,
813 sd->rx_pkt,
814 NULL, NULL,
815 0,
816 sd->recv_user_data);
817 }
818 } else if (pstrRx->pu8Buffer == NULL) {
819 if (pstrRx->s16BufferSize == SOCK_ERR_CONN_ABORTED) {
820 winc1500_close(sock);
821
822 net_pkt_unref(sd->rx_pkt);
823 return false;
824 }
825 }
826 return true;
827 }
828
handle_socket_msg_bind(struct socket_data * sd,void * pvMsg)829 static void handle_socket_msg_bind(struct socket_data *sd, void *pvMsg)
830 {
831 tstrSocketBindMsg *bind_msg = (tstrSocketBindMsg *)pvMsg;
832
833 /* Holding a value of ZERO for a successful bind or otherwise
834 * a negative error code corresponding to the type of error.
835 */
836
837 if (bind_msg->status) {
838 LOG_ERR("BIND: error %d %s",
839 bind_msg->status,
840 socket_message_to_string(bind_msg->status));
841 sd->ret_code = bind_msg->status;
842 }
843 }
844
handle_socket_msg_listen(struct socket_data * sd,void * pvMsg)845 static void handle_socket_msg_listen(struct socket_data *sd, void *pvMsg)
846 {
847 tstrSocketListenMsg *listen_msg = (tstrSocketListenMsg *)pvMsg;
848
849 /* Holding a value of ZERO for a successful listen or otherwise
850 * a negative error code corresponding to the type of error.
851 */
852
853 if (listen_msg->status) {
854 LOG_ERR("winc1500_socket_cb:LISTEN: error %d %s",
855 listen_msg->status,
856 socket_message_to_string(listen_msg->status));
857 sd->ret_code = listen_msg->status;
858 }
859 }
860
handle_socket_msg_accept(struct socket_data * sd,void * pvMsg)861 static void handle_socket_msg_accept(struct socket_data *sd, void *pvMsg)
862 {
863 tstrSocketAcceptMsg *accept_msg = (tstrSocketAcceptMsg *)pvMsg;
864
865 /* On a successful accept operation, the return information is
866 * the socket ID for the accepted connection with the remote peer.
867 * Otherwise a negative error code is returned to indicate failure
868 * of the accept operation.
869 */
870
871 LOG_DBG("ACCEPT: from %d.%d.%d.%d:%d, new socket is %d",
872 accept_msg->strAddr.sin_addr.s4_addr[0],
873 accept_msg->strAddr.sin_addr.s4_addr[1],
874 accept_msg->strAddr.sin_addr.s4_addr[2],
875 accept_msg->strAddr.sin_addr.s4_addr[3],
876 ntohs(accept_msg->strAddr.sin_port),
877 accept_msg->sock);
878
879 if (accept_msg->sock < 0) {
880 LOG_ERR("ACCEPT: error %d %s",
881 accept_msg->sock,
882 socket_message_to_string(accept_msg->sock));
883 sd->ret_code = accept_msg->sock;
884 }
885
886 if (sd->accept_cb) {
887 struct socket_data *a_sd;
888 int ret;
889
890 a_sd = &w1500_data.socket_data[accept_msg->sock];
891
892 memcpy(a_sd, sd, sizeof(struct socket_data));
893
894 ret = net_context_get(AF_INET, SOCK_STREAM,
895 IPPROTO_TCP, &a_sd->context);
896 if (ret < 0) {
897 LOG_ERR("Cannot get new net context for ACCEPT");
898 return;
899 }
900 /* We get a new socket from accept_msg but we need a new
901 * context as well. The new context gives us another socket
902 * so we have to close that one first.
903 */
904 winc1500_close((intptr_t)a_sd->context->offload_context);
905
906 a_sd->context->offload_context = (void *)((intptr_t)accept_msg->sock);
907 /** The iface is reset when getting a new context. */
908 a_sd->context->iface = sd->context->iface;
909
910 net_context_set_state(a_sd->context, NET_CONTEXT_CONNECTED);
911
912 /** Setup remote */
913 a_sd->context->remote.sa_family = AF_INET;
914 net_sin(&a_sd->context->remote)->sin_port =
915 accept_msg->strAddr.sin_port;
916 net_sin(&a_sd->context->remote)->sin_addr.s_addr =
917 accept_msg->strAddr.sin_addr.s_addr;
918 a_sd->context->flags |= NET_CONTEXT_REMOTE_ADDR_SET;
919
920 sd->accept_cb(a_sd->context,
921 (struct sockaddr *)&accept_msg->strAddr,
922 sizeof(struct sockaddr_in),
923 (accept_msg->sock > 0) ?
924 0 : accept_msg->sock,
925 sd->accept_user_data);
926 }
927 }
928
winc1500_socket_cb(SOCKET sock,uint8 message,void * pvMsg)929 static void winc1500_socket_cb(SOCKET sock, uint8 message, void *pvMsg)
930 {
931 struct socket_data *sd = &w1500_data.socket_data[sock];
932
933 if (message != 6) {
934 LOG_DBG("sock %d Msg %d %s",
935 sock, message, socket_message_to_string(message));
936 }
937
938 sd->ret_code = 0;
939
940 switch (message) {
941 case SOCKET_MSG_CONNECT:
942 handle_socket_msg_connect(sd, pvMsg);
943 k_sem_give(&sd->wait_sem);
944
945 break;
946 case SOCKET_MSG_SEND:
947 break;
948 case SOCKET_MSG_RECV:
949 if (!handle_socket_msg_recv(sock, sd, pvMsg)) {
950 return;
951 }
952
953 break;
954 case SOCKET_MSG_BIND:
955 handle_socket_msg_bind(sd, pvMsg);
956 k_sem_give(&sd->wait_sem);
957
958 break;
959 case SOCKET_MSG_LISTEN:
960 handle_socket_msg_listen(sd, pvMsg);
961 k_sem_give(&sd->wait_sem);
962
963 break;
964 case SOCKET_MSG_ACCEPT:
965 handle_socket_msg_accept(sd, pvMsg);
966
967 break;
968 }
969 #if LOG_LEVEL > LOG_LEVEL_OFF
970 stack_stats();
971 #endif /* LOG_LEVEL > LOG_LEVEL_OFF */
972 }
973
winc1500_thread(void * p1,void * p2,void * p3)974 static void winc1500_thread(void *p1, void *p2, void *p3)
975 {
976 ARG_UNUSED(p1);
977 ARG_UNUSED(p2);
978 ARG_UNUSED(p3);
979
980 while (1) {
981 while (m2m_wifi_handle_events(NULL) != 0) {
982 }
983
984 k_sleep(K_MSEC(1));
985 }
986 }
987
winc1500_mgmt_scan(const struct device * dev,struct wifi_scan_params * params,scan_result_cb_t cb)988 static int winc1500_mgmt_scan(const struct device *dev,
989 struct wifi_scan_params *params,
990 scan_result_cb_t cb)
991 {
992 ARG_UNUSED(params);
993
994 if (w1500_data.scan_cb) {
995 return -EALREADY;
996 }
997
998 w1500_data.scan_cb = cb;
999
1000 if (m2m_wifi_request_scan(M2M_WIFI_CH_ALL)) {
1001 w1500_data.scan_cb = NULL;
1002 LOG_ERR("Failed to request scan");
1003 return -EIO;
1004 }
1005
1006 return 0;
1007 }
1008
winc1500_mgmt_connect(const struct device * dev,struct wifi_connect_req_params * params)1009 static int winc1500_mgmt_connect(const struct device *dev,
1010 struct wifi_connect_req_params *params)
1011 {
1012 uint8_t ssid[M2M_MAX_SSID_LEN];
1013 tuniM2MWifiAuth psk;
1014 uint8_t security;
1015 uint16_t channel;
1016 void *auth;
1017
1018 memcpy(ssid, params->ssid, params->ssid_length);
1019 ssid[params->ssid_length] = '\0';
1020
1021 if (params->security == WIFI_SECURITY_TYPE_PSK) {
1022 memcpy(psk.au8PSK, params->psk, params->psk_length);
1023 psk.au8PSK[params->psk_length] = '\0';
1024 auth = &psk;
1025
1026 security = M2M_WIFI_SEC_WPA_PSK;
1027 } else {
1028 auth = NULL;
1029 security = M2M_WIFI_SEC_OPEN;
1030 }
1031
1032 if (params->channel == WIFI_CHANNEL_ANY) {
1033 channel = M2M_WIFI_CH_ALL;
1034 } else {
1035 channel = params->channel;
1036 }
1037
1038 LOG_DBG("Connecting to %s (%u) on %s %u %s security (%s)",
1039 ssid, params->ssid_length,
1040 channel == M2M_WIFI_CH_ALL ? "channel unknown" : "channel",
1041 channel,
1042 security == M2M_WIFI_SEC_OPEN ? "without" : "with",
1043 params->psk ? (char *)psk.au8PSK : "");
1044
1045 if (m2m_wifi_connect((char *)ssid, params->ssid_length,
1046 security, auth, channel)) {
1047 return -EIO;
1048 }
1049
1050 w1500_data.connecting = true;
1051
1052 return 0;
1053 }
1054
winc1500_mgmt_disconnect(const struct device * dev)1055 static int winc1500_mgmt_disconnect(const struct device *dev)
1056 {
1057 if (!w1500_data.connected) {
1058 return -EALREADY;
1059 }
1060
1061 if (m2m_wifi_disconnect()) {
1062 return -EIO;
1063 }
1064
1065 return 0;
1066 }
1067
winc1500_mgmt_ap_enable(const struct device * dev,struct wifi_connect_req_params * params)1068 static int winc1500_mgmt_ap_enable(const struct device *dev,
1069 struct wifi_connect_req_params *params)
1070 {
1071 tstrM2MAPConfig strM2MAPConfig;
1072
1073 memset(&strM2MAPConfig, 0x00, sizeof(tstrM2MAPConfig));
1074 strncpy((char *)&strM2MAPConfig.au8SSID, params->ssid,
1075 params->ssid_length);
1076 strM2MAPConfig.u8ListenChannel = params->channel;
1077 /** security is hardcoded as open for now */
1078 strM2MAPConfig.u8SecType = M2M_WIFI_SEC_OPEN;
1079 /** DHCP: 192.168.1.1 */
1080 strM2MAPConfig.au8DHCPServerIP[0] = 0xC0;
1081 strM2MAPConfig.au8DHCPServerIP[1] = 0xA8;
1082 strM2MAPConfig.au8DHCPServerIP[2] = 0x01;
1083 strM2MAPConfig.au8DHCPServerIP[3] = 0x01;
1084
1085 if (m2m_wifi_enable_ap(&strM2MAPConfig) != M2M_SUCCESS) {
1086 return -EIO;
1087 }
1088
1089 return 0;
1090 }
1091
winc1500_mgmt_ap_disable(const struct device * dev)1092 static int winc1500_mgmt_ap_disable(const struct device *dev)
1093 {
1094 if (m2m_wifi_disable_ap() != M2M_SUCCESS) {
1095 return -EIO;
1096 }
1097
1098 return 0;
1099 }
1100
winc1500_iface_init(struct net_if * iface)1101 static void winc1500_iface_init(struct net_if *iface)
1102 {
1103 LOG_DBG("eth_init:net_if_set_link_addr:"
1104 "MAC Address %02X:%02X:%02X:%02X:%02X:%02X",
1105 w1500_data.mac[0], w1500_data.mac[1], w1500_data.mac[2],
1106 w1500_data.mac[3], w1500_data.mac[4], w1500_data.mac[5]);
1107
1108 net_if_set_link_addr(iface, w1500_data.mac, sizeof(w1500_data.mac),
1109 NET_LINK_ETHERNET);
1110
1111 iface->if_dev->offload = &winc1500_offload;
1112
1113 w1500_data.iface = iface;
1114 }
1115
winc1500_get_wifi_type(void)1116 static enum offloaded_net_if_types winc1500_get_wifi_type(void)
1117 {
1118 return L2_OFFLOADED_NET_IF_TYPE_WIFI;
1119 }
1120
1121 static const struct wifi_mgmt_ops winc1500_mgmt_ops = {
1122 .scan = winc1500_mgmt_scan,
1123 .connect = winc1500_mgmt_connect,
1124 .disconnect = winc1500_mgmt_disconnect,
1125 .ap_enable = winc1500_mgmt_ap_enable,
1126 .ap_disable = winc1500_mgmt_ap_disable,
1127 };
1128 static const struct net_wifi_mgmt_offload winc1500_api = {
1129 .wifi_iface.iface_api.init = winc1500_iface_init,
1130 .wifi_iface.get_type = winc1500_get_wifi_type,
1131 .wifi_mgmt_api = &winc1500_mgmt_ops,
1132 };
1133
winc1500_init(const struct device * dev)1134 static int winc1500_init(const struct device *dev)
1135 {
1136 tstrWifiInitParam param = {
1137 .pfAppWifiCb = winc1500_wifi_cb,
1138 };
1139 unsigned char is_valid;
1140 int ret;
1141
1142 ARG_UNUSED(dev);
1143
1144 w1500_data.connecting = false;
1145 w1500_data.connected = false;
1146
1147 ret = m2m_wifi_init(¶m);
1148 if (ret != M2M_SUCCESS) {
1149 LOG_ERR("m2m_wifi_init return error!(%d)", ret);
1150 return -EIO;
1151 }
1152
1153 socketInit();
1154 registerSocketCallback(winc1500_socket_cb, NULL);
1155
1156 if (m2m_wifi_get_otp_mac_address(w1500_data.mac, &is_valid) != M2M_SUCCESS) {
1157 LOG_ERR("Failed to get MAC address");
1158 }
1159
1160 LOG_DBG("WINC1500 MAC Address from OTP (%d) "
1161 "%02X:%02X:%02X:%02X:%02X:%02X",
1162 is_valid,
1163 w1500_data.mac[0], w1500_data.mac[1], w1500_data.mac[2],
1164 w1500_data.mac[3], w1500_data.mac[4], w1500_data.mac[5]);
1165
1166 if (m2m_wifi_set_scan_region(WINC1500_REGION) != M2M_SUCCESS) {
1167 LOG_ERR("Failed set scan region");
1168 }
1169
1170 if (m2m_wifi_set_power_profile(PWR_LOW1) != M2M_SUCCESS) {
1171 LOG_ERR("Failed set power profile");
1172 }
1173
1174 if (m2m_wifi_set_tx_power(TX_PWR_LOW) != M2M_SUCCESS) {
1175 LOG_ERR("Failed set tx power");
1176 }
1177
1178 /* monitoring thread for winc wifi callbacks */
1179 k_thread_create(&winc1500_thread_data, winc1500_stack,
1180 CONFIG_WIFI_WINC1500_THREAD_STACK_SIZE,
1181 winc1500_thread, NULL, NULL, NULL,
1182 K_PRIO_COOP(CONFIG_WIFI_WINC1500_THREAD_PRIO),
1183 0, K_NO_WAIT);
1184 k_thread_name_set(&winc1500_thread_data, "WINC1500");
1185
1186 LOG_DBG("WINC1500 driver Initialized");
1187
1188 return 0;
1189 }
1190
1191 NET_DEVICE_OFFLOAD_INIT(winc1500, CONFIG_WIFI_WINC1500_NAME,
1192 winc1500_init, NULL, &w1500_data, NULL,
1193 CONFIG_WIFI_INIT_PRIORITY, &winc1500_api,
1194 CONFIG_WIFI_WINC1500_MAX_PACKET_SIZE);
1195
1196 CONNECTIVITY_WIFI_MGMT_BIND(winc1500);
1197