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(&param);
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