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 socket(uint16 u16Domain, uint8 u8Type, uint8 u8Flags);
46 NMI_API sint8 bind(SOCKET sock, struct sockaddr *pstrAddr, uint8 u8AddrLen);
47 NMI_API sint8 listen(SOCKET sock, uint8 backlog);
48 NMI_API sint8 accept(SOCKET sock, struct sockaddr *addr, uint8 *addrlen);
49 NMI_API sint8 connect(SOCKET sock, struct sockaddr *pstrAddr, uint8 u8AddrLen);
50 NMI_API sint16 recv(SOCKET sock, void *pvRecvBuf,
51 uint16 u16BufLen, uint32 u32Timeoutmsec);
52 NMI_API sint16 send(SOCKET sock, void *pvSendBuffer,
53 uint16 u16SendLength, uint16 u16Flags);
54 NMI_API sint16 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 = 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 = bind((intptr_t)context->offload_context, (struct sockaddr *)addr, addrlen);
341 if (ret) {
342 LOG_ERR("bind error %d %s!",
343 ret, socket_message_to_string(ret));
344 return ret;
345 }
346
347 if (k_sem_take(&w1500_data.socket_data[socket].wait_sem,
348 WINC1500_BIND_TIMEOUT)) {
349 LOG_ERR("bind error timeout expired");
350 return -ETIMEDOUT;
351 }
352
353 return w1500_data.socket_data[socket].ret_code;
354 }
355
356 /**
357 * This function is called when user wants to mark the socket
358 * to be a listening one.
359 */
winc1500_listen(struct net_context * context,int backlog)360 static int winc1500_listen(struct net_context *context, int backlog)
361 {
362 SOCKET socket = (intptr_t)context->offload_context;
363 int ret;
364
365 ret = listen((intptr_t)context->offload_context, backlog);
366 if (ret) {
367 LOG_ERR("listen error %d %s!",
368 ret, socket_error_string(ret));
369 return ret;
370 }
371
372 if (k_sem_take(&w1500_data.socket_data[socket].wait_sem,
373 WINC1500_LISTEN_TIMEOUT)) {
374 return -ETIMEDOUT;
375 }
376
377 return w1500_data.socket_data[socket].ret_code;
378 }
379
380 /**
381 * This function is called when user wants to create a connection
382 * to a peer host.
383 */
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)384 static int winc1500_connect(struct net_context *context,
385 const struct sockaddr *addr,
386 socklen_t addrlen,
387 net_context_connect_cb_t cb,
388 int32_t timeout,
389 void *user_data)
390 {
391 SOCKET socket = (intptr_t)context->offload_context;
392 int ret;
393
394 w1500_data.socket_data[socket].connect_cb = cb;
395 w1500_data.socket_data[socket].connect_user_data = user_data;
396 w1500_data.socket_data[socket].ret_code = 0;
397
398 ret = connect(socket, (struct sockaddr *)addr, addrlen);
399 if (ret) {
400 LOG_ERR("connect error %d %s!",
401 ret, socket_error_string(ret));
402 return ret;
403 }
404
405 if (timeout != 0 &&
406 k_sem_take(&w1500_data.socket_data[socket].wait_sem, K_MSEC(timeout))) {
407 return -ETIMEDOUT;
408 }
409
410 return w1500_data.socket_data[socket].ret_code;
411 }
412
413 /**
414 * This function is called when user wants to accept a connection
415 * being established.
416 */
winc1500_accept(struct net_context * context,net_tcp_accept_cb_t cb,int32_t timeout,void * user_data)417 static int winc1500_accept(struct net_context *context,
418 net_tcp_accept_cb_t cb,
419 int32_t timeout,
420 void *user_data)
421 {
422 SOCKET socket = (intptr_t)context->offload_context;
423 int ret;
424
425 w1500_data.socket_data[socket].accept_cb = cb;
426 w1500_data.socket_data[socket].accept_user_data = user_data;
427
428 ret = accept(socket, NULL, 0);
429 if (ret) {
430 LOG_ERR("accept error %d %s!",
431 ret, socket_error_string(ret));
432 return ret;
433 }
434
435 if (timeout) {
436 if (k_sem_take(&w1500_data.socket_data[socket].wait_sem,
437 K_MSEC(timeout))) {
438 return -ETIMEDOUT;
439 }
440 }
441
442 return w1500_data.socket_data[socket].ret_code;
443 }
444
445 /**
446 * This function is called when user wants to send data to peer host.
447 */
winc1500_send(struct net_pkt * pkt,net_context_send_cb_t cb,int32_t timeout,void * user_data)448 static int winc1500_send(struct net_pkt *pkt,
449 net_context_send_cb_t cb,
450 int32_t timeout,
451 void *user_data)
452 {
453 struct net_context *context = pkt->context;
454 SOCKET socket = (intptr_t)context->offload_context;
455 int ret = 0;
456 struct net_buf *buf;
457
458 buf = net_buf_alloc(&winc1500_tx_pool, WINC1500_BUF_TIMEOUT);
459 if (!buf) {
460 return -ENOBUFS;
461 }
462
463 if (net_pkt_read(pkt, buf->data, net_pkt_get_len(pkt))) {
464 ret = -ENOBUFS;
465 goto out;
466 }
467
468 net_buf_add(buf, net_pkt_get_len(pkt));
469
470 ret = send(socket, buf->data, buf->len, 0);
471 if (ret) {
472 LOG_ERR("send error %d %s!", ret, socket_error_string(ret));
473 goto out;
474 }
475
476 net_pkt_unref(pkt);
477 out:
478 net_buf_unref(buf);
479
480 return ret;
481 }
482
483 /**
484 * This function is called when user wants to send data to peer host.
485 */
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)486 static int winc1500_sendto(struct net_pkt *pkt,
487 const struct sockaddr *dst_addr,
488 socklen_t addrlen,
489 net_context_send_cb_t cb,
490 int32_t timeout,
491 void *user_data)
492 {
493 struct net_context *context = pkt->context;
494 SOCKET socket = (intptr_t)context->offload_context;
495 int ret = 0;
496 struct net_buf *buf;
497
498 buf = net_buf_alloc(&winc1500_tx_pool, WINC1500_BUF_TIMEOUT);
499 if (!buf) {
500 return -ENOBUFS;
501 }
502
503 if (net_pkt_read(pkt, buf->data, net_pkt_get_len(pkt))) {
504 ret = -ENOBUFS;
505 goto out;
506 }
507
508 net_buf_add(buf, net_pkt_get_len(pkt));
509
510 ret = sendto(socket, buf->data, buf->len, 0,
511 (struct sockaddr *)dst_addr, addrlen);
512 if (ret) {
513 LOG_ERR("sendto error %d %s!", ret, socket_error_string(ret));
514 goto out;
515 }
516
517 net_pkt_unref(pkt);
518 out:
519 net_buf_unref(buf);
520
521 return ret;
522 }
523
524 /**
525 */
prepare_pkt(struct socket_data * sock_data)526 static int prepare_pkt(struct socket_data *sock_data)
527 {
528 /* Get the frame from the buffer */
529 sock_data->rx_pkt = net_pkt_rx_alloc_on_iface(w1500_data.iface,
530 K_NO_WAIT);
531 if (!sock_data->rx_pkt) {
532 LOG_ERR("Could not allocate rx packet");
533 return -1;
534 }
535
536 /* Reserve a data buffer to receive the frame */
537 sock_data->pkt_buf = net_buf_alloc(&winc1500_rx_pool, K_NO_WAIT);
538 if (!sock_data->pkt_buf) {
539 LOG_ERR("Could not allocate data buffer");
540 net_pkt_unref(sock_data->rx_pkt);
541 return -1;
542 }
543
544 net_pkt_append_buffer(sock_data->rx_pkt, sock_data->pkt_buf);
545
546 return 0;
547 }
548
549 /**
550 * This function is called when user wants to receive data from peer
551 * host.
552 */
winc1500_recv(struct net_context * context,net_context_recv_cb_t cb,int32_t timeout,void * user_data)553 static int winc1500_recv(struct net_context *context,
554 net_context_recv_cb_t cb,
555 int32_t timeout,
556 void *user_data)
557 {
558 SOCKET socket = (intptr_t)context->offload_context;
559 int ret;
560
561 w1500_data.socket_data[socket].recv_cb = cb;
562 w1500_data.socket_data[socket].recv_user_data = user_data;
563 if (!cb) {
564 return 0;
565 }
566
567 ret = prepare_pkt(&w1500_data.socket_data[socket]);
568 if (ret) {
569 LOG_ERR("Could not reserve packet buffer");
570 return -ENOMEM;
571 }
572
573
574 ret = recv(socket, w1500_data.socket_data[socket].pkt_buf->data,
575 CONFIG_WIFI_WINC1500_MAX_PACKET_SIZE, timeout);
576 if (ret) {
577 LOG_ERR("recv error %d %s!",
578 ret, socket_error_string(ret));
579 return ret;
580 }
581
582 return 0;
583 }
584
585 /**
586 * This function is called when user wants to close the socket.
587 */
winc1500_put(struct net_context * context)588 static int winc1500_put(struct net_context *context)
589 {
590 SOCKET sock = (intptr_t)context->offload_context;
591 struct socket_data *sd = &w1500_data.socket_data[sock];
592 int ret;
593
594 memset(&(context->remote), 0, sizeof(struct sockaddr_in));
595 context->flags &= ~NET_CONTEXT_REMOTE_ADDR_SET;
596 ret = winc1500_close(sock);
597
598 net_pkt_unref(sd->rx_pkt);
599
600 memset(sd, 0, sizeof(struct socket_data));
601
602 return ret;
603 }
604
605 static struct net_offload winc1500_offload = {
606 .get = winc1500_get,
607 .bind = winc1500_bind,
608 .listen = winc1500_listen,
609 .connect = winc1500_connect,
610 .accept = winc1500_accept,
611 .send = winc1500_send,
612 .sendto = winc1500_sendto,
613 .recv = winc1500_recv,
614 .put = winc1500_put,
615 };
616
handle_wifi_con_state_changed(void * pvMsg)617 static void handle_wifi_con_state_changed(void *pvMsg)
618 {
619 tstrM2mWifiStateChanged *pstrWifiState =
620 (tstrM2mWifiStateChanged *)pvMsg;
621
622 switch (pstrWifiState->u8CurrState) {
623 case M2M_WIFI_DISCONNECTED:
624 LOG_DBG("Disconnected (%u)", pstrWifiState->u8ErrCode);
625
626 if (w1500_data.connecting) {
627 wifi_mgmt_raise_connect_result_event(w1500_data.iface,
628 pstrWifiState->u8ErrCode ? -EIO : 0);
629 w1500_data.connecting = false;
630
631 break;
632 }
633
634 w1500_data.connected = false;
635 wifi_mgmt_raise_disconnect_result_event(w1500_data.iface, 0);
636
637 break;
638 case M2M_WIFI_CONNECTED:
639 LOG_DBG("Connected (%u)", pstrWifiState->u8ErrCode);
640
641 w1500_data.connected = true;
642 w1500_data.connecting = false;
643 wifi_mgmt_raise_connect_result_event(w1500_data.iface, 0);
644
645 break;
646 case M2M_WIFI_UNDEF:
647 /* TODO status undefined*/
648 LOG_DBG("Undefined?");
649 break;
650 }
651 }
652
handle_wifi_dhcp_conf(void * pvMsg)653 static void handle_wifi_dhcp_conf(void *pvMsg)
654 {
655 uint8_t *pu8IPAddress = (uint8_t *)pvMsg;
656 struct in_addr addr;
657 uint8_t i;
658
659 /* Connected and got IP address*/
660 LOG_DBG("Wi-Fi connected, IP is %u.%u.%u.%u",
661 pu8IPAddress[0], pu8IPAddress[1],
662 pu8IPAddress[2], pu8IPAddress[3]);
663
664 /* TODO at this point the standby mode should be enable
665 * status = WiFi connected IP assigned
666 */
667 for (i = 0U; i < 4; i++) {
668 addr.s4_addr[i] = pu8IPAddress[i];
669 }
670
671 /* TODO fill in net mask, gateway and lease time */
672
673 net_if_ipv4_addr_add(w1500_data.iface, &addr, NET_ADDR_DHCP, 0);
674 }
675
reset_scan_data(void)676 static void reset_scan_data(void)
677 {
678 w1500_data.scan_cb = NULL;
679 w1500_data.scan_result = 0U;
680 }
681
handle_scan_result(void * pvMsg)682 static void handle_scan_result(void *pvMsg)
683 {
684 tstrM2mWifiscanResult *pstrScanResult = (tstrM2mWifiscanResult *)pvMsg;
685 struct wifi_scan_result result;
686
687 if (!w1500_data.scan_cb) {
688 return;
689 }
690
691 if (pstrScanResult->u8AuthType == M2M_WIFI_SEC_OPEN) {
692 result.security = WIFI_SECURITY_TYPE_NONE;
693 } else if (pstrScanResult->u8AuthType == M2M_WIFI_SEC_WPA_PSK) {
694 result.security = WIFI_SECURITY_TYPE_PSK;
695 } else {
696 LOG_DBG("Security %u not supported",
697 pstrScanResult->u8AuthType);
698 goto out;
699 }
700
701 memcpy(result.ssid, pstrScanResult->au8SSID, WIFI_SSID_MAX_LEN);
702 result.ssid_length = strlen(result.ssid);
703
704 result.channel = pstrScanResult->u8ch;
705 result.rssi = pstrScanResult->s8rssi;
706
707 w1500_data.scan_cb(w1500_data.iface, 0, &result);
708
709 k_yield();
710
711 out:
712 if (w1500_data.scan_result < m2m_wifi_get_num_ap_found()) {
713 m2m_wifi_req_scan_result(w1500_data.scan_result);
714 w1500_data.scan_result++;
715 } else {
716 w1500_data.scan_cb(w1500_data.iface, 0, NULL);
717 reset_scan_data();
718 }
719 }
720
handle_scan_done(void * pvMsg)721 static void handle_scan_done(void *pvMsg)
722 {
723 tstrM2mScanDone *pstrInfo = (tstrM2mScanDone *)pvMsg;
724
725 if (!w1500_data.scan_cb) {
726 return;
727 }
728
729 if (pstrInfo->s8ScanState != M2M_SUCCESS) {
730 w1500_data.scan_cb(w1500_data.iface, -EIO, NULL);
731 reset_scan_data();
732
733 LOG_ERR("Scan failed.");
734
735 return;
736 }
737
738 w1500_data.scan_result = 0U;
739
740 if (pstrInfo->u8NumofCh >= 1) {
741 LOG_DBG("Requesting results (%u)",
742 m2m_wifi_get_num_ap_found());
743
744 m2m_wifi_req_scan_result(w1500_data.scan_result);
745 w1500_data.scan_result++;
746 } else {
747 LOG_DBG("No AP found");
748
749 w1500_data.scan_cb(w1500_data.iface, 0, NULL);
750 reset_scan_data();
751 }
752 }
753
winc1500_wifi_cb(uint8_t message_type,void * pvMsg)754 static void winc1500_wifi_cb(uint8_t message_type, void *pvMsg)
755 {
756 LOG_DBG("Msg Type %d %s",
757 message_type, wifi_cb_msg_2_str(message_type));
758
759 switch (message_type) {
760 case M2M_WIFI_RESP_CON_STATE_CHANGED:
761 handle_wifi_con_state_changed(pvMsg);
762 break;
763 case M2M_WIFI_REQ_DHCP_CONF:
764 handle_wifi_dhcp_conf(pvMsg);
765 break;
766 case M2M_WIFI_RESP_SCAN_RESULT:
767 handle_scan_result(pvMsg);
768 break;
769 case M2M_WIFI_RESP_SCAN_DONE:
770 handle_scan_done(pvMsg);
771 break;
772 default:
773 break;
774 }
775 #if LOG_LEVEL > LOG_LEVEL_OFF
776 stack_stats();
777 #endif /* LOG_LEVEL > LOG_LEVEL_OFF */
778 }
779
handle_socket_msg_connect(struct socket_data * sd,void * pvMsg)780 static void handle_socket_msg_connect(struct socket_data *sd, void *pvMsg)
781 {
782 tstrSocketConnectMsg *strConnMsg = (tstrSocketConnectMsg *)pvMsg;
783
784 LOG_ERR("CONNECT: socket %d error %d",
785 strConnMsg->sock, strConnMsg->s8Error);
786
787 if (!strConnMsg->s8Error) {
788 net_context_set_state(sd->context, NET_CONTEXT_CONNECTED);
789 }
790
791 if (sd->connect_cb) {
792 sd->connect_cb(sd->context,
793 strConnMsg->s8Error,
794 sd->connect_user_data);
795 }
796
797 sd->ret_code = strConnMsg->s8Error;
798 }
799
800
handle_socket_msg_recv(SOCKET sock,struct socket_data * sd,void * pvMsg)801 static bool handle_socket_msg_recv(SOCKET sock,
802 struct socket_data *sd, void *pvMsg)
803 {
804 tstrSocketRecvMsg *pstrRx = (tstrSocketRecvMsg *)pvMsg;
805
806 if ((pstrRx->pu8Buffer != NULL) && (pstrRx->s16BufferSize > 0)) {
807 net_buf_add(sd->pkt_buf, pstrRx->s16BufferSize);
808 net_pkt_cursor_init(sd->rx_pkt);
809
810 if (sd->recv_cb) {
811 sd->recv_cb(sd->context,
812 sd->rx_pkt,
813 NULL, NULL,
814 0,
815 sd->recv_user_data);
816 }
817 } else if (pstrRx->pu8Buffer == NULL) {
818 if (pstrRx->s16BufferSize == SOCK_ERR_CONN_ABORTED) {
819 net_pkt_unref(sd->rx_pkt);
820 return false;
821 }
822 }
823 return true;
824 }
825
handle_socket_msg_bind(struct socket_data * sd,void * pvMsg)826 static void handle_socket_msg_bind(struct socket_data *sd, void *pvMsg)
827 {
828 tstrSocketBindMsg *bind_msg = (tstrSocketBindMsg *)pvMsg;
829
830 /* Holding a value of ZERO for a successful bind or otherwise
831 * a negative error code corresponding to the type of error.
832 */
833
834 if (bind_msg->status) {
835 LOG_ERR("BIND: error %d %s",
836 bind_msg->status,
837 socket_message_to_string(bind_msg->status));
838 sd->ret_code = bind_msg->status;
839 }
840 }
841
handle_socket_msg_listen(struct socket_data * sd,void * pvMsg)842 static void handle_socket_msg_listen(struct socket_data *sd, void *pvMsg)
843 {
844 tstrSocketListenMsg *listen_msg = (tstrSocketListenMsg *)pvMsg;
845
846 /* Holding a value of ZERO for a successful listen or otherwise
847 * a negative error code corresponding to the type of error.
848 */
849
850 if (listen_msg->status) {
851 LOG_ERR("winc1500_socket_cb:LISTEN: error %d %s",
852 listen_msg->status,
853 socket_message_to_string(listen_msg->status));
854 sd->ret_code = listen_msg->status;
855 }
856 }
857
handle_socket_msg_accept(struct socket_data * sd,void * pvMsg)858 static void handle_socket_msg_accept(struct socket_data *sd, void *pvMsg)
859 {
860 tstrSocketAcceptMsg *accept_msg = (tstrSocketAcceptMsg *)pvMsg;
861
862 /* On a successful accept operation, the return information is
863 * the socket ID for the accepted connection with the remote peer.
864 * Otherwise a negative error code is returned to indicate failure
865 * of the accept operation.
866 */
867
868 LOG_DBG("ACCEPT: from %d.%d.%d.%d:%d, new socket is %d",
869 accept_msg->strAddr.sin_addr.s4_addr[0],
870 accept_msg->strAddr.sin_addr.s4_addr[1],
871 accept_msg->strAddr.sin_addr.s4_addr[2],
872 accept_msg->strAddr.sin_addr.s4_addr[3],
873 ntohs(accept_msg->strAddr.sin_port),
874 accept_msg->sock);
875
876 if (accept_msg->sock < 0) {
877 LOG_ERR("ACCEPT: error %d %s",
878 accept_msg->sock,
879 socket_message_to_string(accept_msg->sock));
880 sd->ret_code = accept_msg->sock;
881 }
882
883 if (sd->accept_cb) {
884 struct socket_data *a_sd;
885 int ret;
886
887 a_sd = &w1500_data.socket_data[accept_msg->sock];
888
889 memcpy(a_sd, sd, sizeof(struct socket_data));
890
891 ret = net_context_get(AF_INET, SOCK_STREAM,
892 IPPROTO_TCP, &a_sd->context);
893 if (ret < 0) {
894 LOG_ERR("Cannot get new net context for ACCEPT");
895 return;
896 }
897 /* We get a new socket from accept_msg but we need a new
898 * context as well. The new context gives us another socket
899 * so we have to close that one first.
900 */
901 winc1500_close((intptr_t)a_sd->context->offload_context);
902
903 a_sd->context->offload_context = (void *)((intptr_t)accept_msg->sock);
904 /** The iface is reset when getting a new context. */
905 a_sd->context->iface = sd->context->iface;
906
907 /** Setup remote */
908 a_sd->context->remote.sa_family = AF_INET;
909 net_sin(&a_sd->context->remote)->sin_port =
910 accept_msg->strAddr.sin_port;
911 net_sin(&a_sd->context->remote)->sin_addr.s_addr =
912 accept_msg->strAddr.sin_addr.s_addr;
913 a_sd->context->flags |= NET_CONTEXT_REMOTE_ADDR_SET;
914
915 sd->accept_cb(a_sd->context,
916 (struct sockaddr *)&accept_msg->strAddr,
917 sizeof(struct sockaddr_in),
918 (accept_msg->sock > 0) ?
919 0 : accept_msg->sock,
920 sd->accept_user_data);
921 }
922 }
923
winc1500_socket_cb(SOCKET sock,uint8 message,void * pvMsg)924 static void winc1500_socket_cb(SOCKET sock, uint8 message, void *pvMsg)
925 {
926 struct socket_data *sd = &w1500_data.socket_data[sock];
927
928 if (message != 6) {
929 LOG_DBG("sock %d Msg %d %s",
930 sock, message, socket_message_to_string(message));
931 }
932
933 sd->ret_code = 0;
934
935 switch (message) {
936 case SOCKET_MSG_CONNECT:
937 handle_socket_msg_connect(sd, pvMsg);
938 k_sem_give(&sd->wait_sem);
939
940 break;
941 case SOCKET_MSG_SEND:
942 break;
943 case SOCKET_MSG_RECV:
944 if (!handle_socket_msg_recv(sock, sd, pvMsg)) {
945 return;
946 }
947
948 break;
949 case SOCKET_MSG_BIND:
950 handle_socket_msg_bind(sd, pvMsg);
951 k_sem_give(&sd->wait_sem);
952
953 break;
954 case SOCKET_MSG_LISTEN:
955 handle_socket_msg_listen(sd, pvMsg);
956 k_sem_give(&sd->wait_sem);
957
958 break;
959 case SOCKET_MSG_ACCEPT:
960 handle_socket_msg_accept(sd, pvMsg);
961
962 break;
963 }
964 #if LOG_LEVEL > LOG_LEVEL_OFF
965 stack_stats();
966 #endif /* LOG_LEVEL > LOG_LEVEL_OFF */
967 }
968
winc1500_thread(void * p1,void * p2,void * p3)969 static void winc1500_thread(void *p1, void *p2, void *p3)
970 {
971 ARG_UNUSED(p1);
972 ARG_UNUSED(p2);
973 ARG_UNUSED(p3);
974
975 while (1) {
976 while (m2m_wifi_handle_events(NULL) != 0) {
977 }
978
979 k_sleep(K_MSEC(1));
980 }
981 }
982
winc1500_mgmt_scan(const struct device * dev,struct wifi_scan_params * params,scan_result_cb_t cb)983 static int winc1500_mgmt_scan(const struct device *dev,
984 struct wifi_scan_params *params,
985 scan_result_cb_t cb)
986 {
987 ARG_UNUSED(params);
988
989 if (w1500_data.scan_cb) {
990 return -EALREADY;
991 }
992
993 w1500_data.scan_cb = cb;
994
995 if (m2m_wifi_request_scan(M2M_WIFI_CH_ALL)) {
996 w1500_data.scan_cb = NULL;
997 LOG_ERR("Failed to request scan");
998 return -EIO;
999 }
1000
1001 return 0;
1002 }
1003
winc1500_mgmt_connect(const struct device * dev,struct wifi_connect_req_params * params)1004 static int winc1500_mgmt_connect(const struct device *dev,
1005 struct wifi_connect_req_params *params)
1006 {
1007 uint8_t ssid[M2M_MAX_SSID_LEN];
1008 tuniM2MWifiAuth psk;
1009 uint8_t security;
1010 uint16_t channel;
1011 void *auth;
1012
1013 memcpy(ssid, params->ssid, params->ssid_length);
1014 ssid[params->ssid_length] = '\0';
1015
1016 if (params->security == WIFI_SECURITY_TYPE_PSK) {
1017 memcpy(psk.au8PSK, params->psk, params->psk_length);
1018 psk.au8PSK[params->psk_length] = '\0';
1019 auth = &psk;
1020
1021 security = M2M_WIFI_SEC_WPA_PSK;
1022 } else {
1023 auth = NULL;
1024 security = M2M_WIFI_SEC_OPEN;
1025 }
1026
1027 if (params->channel == WIFI_CHANNEL_ANY) {
1028 channel = M2M_WIFI_CH_ALL;
1029 } else {
1030 channel = params->channel;
1031 }
1032
1033 LOG_DBG("Connecting to %s (%u) on %s %u %s security (%s)",
1034 ssid, params->ssid_length,
1035 channel == M2M_WIFI_CH_ALL ? "channel unknown" : "channel",
1036 channel,
1037 security == M2M_WIFI_SEC_OPEN ? "without" : "with",
1038 params->psk ? (char *)psk.au8PSK : "");
1039
1040 if (m2m_wifi_connect((char *)ssid, params->ssid_length,
1041 security, auth, channel)) {
1042 return -EIO;
1043 }
1044
1045 w1500_data.connecting = true;
1046
1047 return 0;
1048 }
1049
winc1500_mgmt_disconnect(const struct device * dev)1050 static int winc1500_mgmt_disconnect(const struct device *dev)
1051 {
1052 if (!w1500_data.connected) {
1053 return -EALREADY;
1054 }
1055
1056 if (m2m_wifi_disconnect()) {
1057 return -EIO;
1058 }
1059
1060 return 0;
1061 }
1062
winc1500_mgmt_ap_enable(const struct device * dev,struct wifi_connect_req_params * params)1063 static int winc1500_mgmt_ap_enable(const struct device *dev,
1064 struct wifi_connect_req_params *params)
1065 {
1066 tstrM2MAPConfig strM2MAPConfig;
1067
1068 memset(&strM2MAPConfig, 0x00, sizeof(tstrM2MAPConfig));
1069 strcpy((char *)&strM2MAPConfig.au8SSID, params->ssid);
1070 strM2MAPConfig.u8ListenChannel = params->channel;
1071 /** security is hardcoded as open for now */
1072 strM2MAPConfig.u8SecType = M2M_WIFI_SEC_OPEN;
1073 /** DHCP: 192.168.1.1 */
1074 strM2MAPConfig.au8DHCPServerIP[0] = 0xC0;
1075 strM2MAPConfig.au8DHCPServerIP[1] = 0xA8;
1076 strM2MAPConfig.au8DHCPServerIP[2] = 0x01;
1077 strM2MAPConfig.au8DHCPServerIP[3] = 0x01;
1078
1079 if (m2m_wifi_enable_ap(&strM2MAPConfig) != M2M_SUCCESS) {
1080 return -EIO;
1081 }
1082
1083 return 0;
1084 }
1085
winc1500_mgmt_ap_disable(const struct device * dev)1086 static int winc1500_mgmt_ap_disable(const struct device *dev)
1087 {
1088 if (m2m_wifi_disable_ap() != M2M_SUCCESS) {
1089 return -EIO;
1090 }
1091
1092 return 0;
1093 }
1094
winc1500_iface_init(struct net_if * iface)1095 static void winc1500_iface_init(struct net_if *iface)
1096 {
1097 LOG_DBG("eth_init:net_if_set_link_addr:"
1098 "MAC Address %02X:%02X:%02X:%02X:%02X:%02X",
1099 w1500_data.mac[0], w1500_data.mac[1], w1500_data.mac[2],
1100 w1500_data.mac[3], w1500_data.mac[4], w1500_data.mac[5]);
1101
1102 net_if_set_link_addr(iface, w1500_data.mac, sizeof(w1500_data.mac),
1103 NET_LINK_ETHERNET);
1104
1105 iface->if_dev->offload = &winc1500_offload;
1106
1107 w1500_data.iface = iface;
1108 }
1109
winc1500_get_wifi_type(void)1110 static enum offloaded_net_if_types winc1500_get_wifi_type(void)
1111 {
1112 return L2_OFFLOADED_NET_IF_TYPE_WIFI;
1113 }
1114
1115 static const struct wifi_mgmt_ops winc1500_mgmt_ops = {
1116 .scan = winc1500_mgmt_scan,
1117 .connect = winc1500_mgmt_connect,
1118 .disconnect = winc1500_mgmt_disconnect,
1119 .ap_enable = winc1500_mgmt_ap_enable,
1120 .ap_disable = winc1500_mgmt_ap_disable,
1121 };
1122 static const struct net_wifi_mgmt_offload winc1500_api = {
1123 .wifi_iface.iface_api.init = winc1500_iface_init,
1124 .wifi_iface.get_type = winc1500_get_wifi_type,
1125 .wifi_mgmt_api = &winc1500_mgmt_ops,
1126 };
1127
winc1500_init(const struct device * dev)1128 static int winc1500_init(const struct device *dev)
1129 {
1130 tstrWifiInitParam param = {
1131 .pfAppWifiCb = winc1500_wifi_cb,
1132 };
1133 unsigned char is_valid;
1134 int ret;
1135
1136 ARG_UNUSED(dev);
1137
1138 w1500_data.connecting = false;
1139 w1500_data.connected = false;
1140
1141 ret = m2m_wifi_init(¶m);
1142 if (ret != M2M_SUCCESS) {
1143 LOG_ERR("m2m_wifi_init return error!(%d)", ret);
1144 return -EIO;
1145 }
1146
1147 socketInit();
1148 registerSocketCallback(winc1500_socket_cb, NULL);
1149
1150 if (m2m_wifi_get_otp_mac_address(w1500_data.mac, &is_valid) != M2M_SUCCESS) {
1151 LOG_ERR("Failed to get MAC address");
1152 }
1153
1154 LOG_DBG("WINC1500 MAC Address from OTP (%d) "
1155 "%02X:%02X:%02X:%02X:%02X:%02X",
1156 is_valid,
1157 w1500_data.mac[0], w1500_data.mac[1], w1500_data.mac[2],
1158 w1500_data.mac[3], w1500_data.mac[4], w1500_data.mac[5]);
1159
1160 if (m2m_wifi_set_scan_region(WINC1500_REGION) != M2M_SUCCESS) {
1161 LOG_ERR("Failed set scan region");
1162 }
1163
1164 if (m2m_wifi_set_power_profile(PWR_LOW1) != M2M_SUCCESS) {
1165 LOG_ERR("Failed set power profile");
1166 }
1167
1168 if (m2m_wifi_set_tx_power(TX_PWR_LOW) != M2M_SUCCESS) {
1169 LOG_ERR("Failed set tx power");
1170 }
1171
1172 /* monitoring thread for winc wifi callbacks */
1173 k_thread_create(&winc1500_thread_data, winc1500_stack,
1174 CONFIG_WIFI_WINC1500_THREAD_STACK_SIZE,
1175 winc1500_thread, NULL, NULL, NULL,
1176 K_PRIO_COOP(CONFIG_WIFI_WINC1500_THREAD_PRIO),
1177 0, K_NO_WAIT);
1178 k_thread_name_set(&winc1500_thread_data, "WINC1500");
1179
1180 LOG_DBG("WINC1500 driver Initialized");
1181
1182 return 0;
1183 }
1184
1185 NET_DEVICE_OFFLOAD_INIT(winc1500, CONFIG_WIFI_WINC1500_NAME,
1186 winc1500_init, NULL, &w1500_data, NULL,
1187 CONFIG_WIFI_INIT_PRIORITY, &winc1500_api,
1188 CONFIG_WIFI_WINC1500_MAX_PACKET_SIZE);
1189
1190 CONNECTIVITY_WIFI_MGMT_BIND(winc1500);
1191