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