1 /*
2  * Copyright (c) 2018, Texas Instruments Incorporated
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  *
6  */
7 
8 #include <stdlib.h>
9 #include <string.h>
10 
11 #include "simplelink_log.h"
12 LOG_MODULE_DECLARE(LOG_MODULE_NAME);
13 
14 #include <zephyr.h>
15 #include <stdint.h>
16 
17 #include <ti/drivers/net/wifi/simplelink.h>
18 #include <ti/net/slnetif.h>
19 #include <ti/net/slnetutils.h>
20 #include <ti/drivers/net/wifi/slnetifwifi.h>
21 #include <CC3220SF_LAUNCHXL.h>
22 
23 #include "simplelink_support.h"
24 
25 #define SET_STATUS_BIT(status, bit) {status |= (1 << (bit)); }
26 #define CLR_STATUS_BIT(status, bit) {status &= ~(1 << (bit)); }
27 #define GET_STATUS_BIT(status, bit) (0 != (status & (1 << (bit))))
28 
29 #define SL_STOP_TIMEOUT	 (200)
30 
31 #undef ASSERT_ON_ERROR
32 #define ASSERT_ON_ERROR(ret, e) __ASSERT(ret >= 0, e)
33 #define DEVICE_ERROR	 "See \"DEVICE ERRORS CODES\" in SimpleLink errors.h"
34 #define WLAN_ERROR	 "See \"WLAN ERRORS CODES\" in SimpleLink errors.h"
35 #define NETAPP_ERROR	 "See \"NETAPP ERRORS CODES\" in SimpleLink errors.h"
36 
37 #define CHANNEL_MASK_ALL	    (0x1FFF)
38 #define RSSI_TH_MAX		    (-95)
39 
40 #define SLNET_IF_WIFI_PRIO                    (5)
41 #define SLNET_IF_WIFI_NAME                    "CC32xx"
42 
43 enum status_bits {
44 	/* Network Processor is powered up */
45 	STATUS_BIT_NWP_INIT = 0,
46 	/* The device is connected to the AP */
47 	STATUS_BIT_CONNECTION,
48 	/* The device has leased IP to any connected client */
49 	STATUS_BIT_IP_LEASED,
50 	/* The device has acquired an IP */
51 	STATUS_BIT_IP_ACQUIRED,
52 	/* The device has acquired an IPv6 address */
53 	STATUS_BIT_IPV6_ACQUIRED,
54 };
55 
56 struct nwp_status {
57 	/* Callback to notify net & wifi mgmt events from SL Event Handlers */
58 	simplelink_wifi_cb_t cb;
59 
60 	/* Status Variables */
61 	uint32_t status;	/* The state of the NWP */
62 	uint32_t role;	/* The device's role (STA, P2P or AP) */
63 
64 	/* Scan results table: */
65 	SlWlanNetworkEntry_t net_entries[CONFIG_WIFI_SIMPLELINK_SCAN_COUNT];
66 };
67 
68 /* STA/AP mode state: shared with simplelink.c */
69 struct sl_connect_state sl_conn;
70 
71 /* Network Coprocessor state, including role and connection state: */
72 static struct nwp_status nwp;
73 
74 /* Minimal configuration of SlNetIfWifi for Zephyr */
75 static SlNetIf_Config_t slnetifwifi_config_zephyr = {
76 	.sockCreate = SlNetIfWifi_socket,
77 	.sockClose = SlNetIfWifi_close,
78 	.sockSelect = SlNetIfWifi_select,
79 	.sockSetOpt = SlNetIfWifi_setSockOpt,
80 	.sockGetOpt = SlNetIfWifi_getSockOpt,
81 	.sockRecvFrom = SlNetIfWifi_recvFrom,
82 	.sockSendTo = SlNetIfWifi_sendTo,
83 	.utilGetHostByName = SlNetIfWifi_getHostByName,
84 	.ifGetIPAddr = SlNetIfWifi_getIPAddr,
85 	.ifGetConnectionStatus = SlNetIfWifi_getConnectionStatus
86 };
87 
88 /* Configure the device to a default state, resetting previous parameters .*/
configure_simplelink(void)89 static int32_t configure_simplelink(void)
90 {
91 	int32_t retval = -1;
92 	int32_t mode = -1;
93 	uint32_t if_bitmap = 0U;
94 	SlWlanScanParamCommand_t scan_default = { 0 };
95 	SlWlanRxFilterOperationCommandBuff_t rx_filterid_mask = { { 0 } };
96 	uint8_t config_opt;
97 	uint8_t power;
98 
99 #if defined(CONFIG_NET_IPV4) && defined(CONFIG_NET_CONFIG_MY_IPV4_ADDR)
100 	struct in_addr addr4;
101 	SlNetCfgIpV4Args_t ipV4;
102 
103 	memset(&ipV4, 0, sizeof(ipV4));
104 #endif
105 
106 	/* Turn on NWP */
107 	mode = sl_Start(0, 0, 0);
108 	ASSERT_ON_ERROR(mode, DEVICE_ERROR);
109 
110 	if (mode != ROLE_STA) {
111 		/* Set NWP role as STA */
112 		mode = sl_WlanSetMode(ROLE_STA);
113 		ASSERT_ON_ERROR(mode, WLAN_ERROR);
114 
115 		/* For changes to take affect, we restart the NWP */
116 		retval = sl_Stop(SL_STOP_TIMEOUT);
117 		ASSERT_ON_ERROR(retval, DEVICE_ERROR);
118 
119 		mode = sl_Start(0, 0, 0);
120 		ASSERT_ON_ERROR(mode, DEVICE_ERROR);
121 	}
122 
123 	if (mode != ROLE_STA) {
124 		LOG_ERR("Failed to configure NWP to default state");
125 		return -1;
126 	}
127 
128 	/* Use Fast Connect Policy, to automatically connect to last AP: */
129 	retval = sl_WlanPolicySet(SL_WLAN_POLICY_CONNECTION,
130 				  SL_WLAN_CONNECTION_POLICY(1, 1, 0, 0),
131 				  NULL, 0);
132 	ASSERT_ON_ERROR(retval, WLAN_ERROR);
133 
134 	/* Disable Auto Provisioning*/
135 	retval = sl_WlanProvisioning(SL_WLAN_PROVISIONING_CMD_STOP, 0xFF, 0,
136 				     NULL, 0x0);
137 	ASSERT_ON_ERROR(retval, WLAN_ERROR);
138 
139 	/* Delete existing profiles */
140 	retval = sl_WlanProfileDel(0xFF);
141 	ASSERT_ON_ERROR(retval, WLAN_ERROR);
142 
143 #if defined(CONFIG_NET_IPV4) && defined(CONFIG_NET_CONFIG_MY_IPV4_ADDR)
144 	if (net_addr_pton(AF_INET, CONFIG_NET_CONFIG_MY_IPV4_ADDR, &addr4)
145 			< 0) {
146 		LOG_ERR("Invalid CONFIG_NET_CONFIG_MY_IPV4_ADDR");
147 		return -1;
148 	}
149 	ipV4.Ip = (_u32)SL_IPV4_VAL(addr4.s4_addr[0],
150 				    addr4.s4_addr[1],
151 				    addr4.s4_addr[2],
152 				    addr4.s4_addr[3]);
153 
154 #if defined(CONFIG_NET_CONFIG_MY_IPV4_GW)
155 	if (strcmp(CONFIG_NET_CONFIG_MY_IPV4_GW, "") != 0) {
156 		if (net_addr_pton(AF_INET, CONFIG_NET_CONFIG_MY_IPV4_GW,
157 				  &addr4) < 0) {
158 			LOG_ERR("Invalid CONFIG_NET_CONFIG_MY_IPV4_GW");
159 			return -1;
160 		}
161 		ipV4.IpGateway = (_u32)SL_IPV4_VAL(addr4.s4_addr[0],
162 						   addr4.s4_addr[1],
163 						   addr4.s4_addr[2],
164 						   addr4.s4_addr[3]);
165 	}
166 #endif
167 
168 #if defined(CONFIG_NET_CONFIG_MY_IPV4_NETMASK)
169 	if (strcmp(CONFIG_NET_CONFIG_MY_IPV4_NETMASK, "") != 0) {
170 		if (net_addr_pton(AF_INET, CONFIG_NET_CONFIG_MY_IPV4_NETMASK,
171 				  &addr4) < 0) {
172 			LOG_ERR("Invalid CONFIG_NET_CONFIG_MY_IPV4_NETMASK");
173 			return -1;
174 		}
175 		ipV4.IpMask = (_u32)SL_IPV4_VAL(addr4.s4_addr[0],
176 						addr4.s4_addr[1],
177 						addr4.s4_addr[2],
178 						addr4.s4_addr[3]);
179 	}
180 #endif
181 
182 	retval = sl_NetCfgSet(SL_NETCFG_IPV4_STA_ADDR_MODE,
183 			      SL_NETCFG_ADDR_STATIC,
184 			      sizeof(SlNetCfgIpV4Args_t), (_u8 *)&ipV4);
185 	ASSERT_ON_ERROR(retval, NETAPP_ERROR);
186 #else
187 	/* enable DHCP client */
188 	retval = sl_NetCfgSet(SL_NETCFG_IPV4_STA_ADDR_MODE,
189 			      SL_NETCFG_ADDR_DHCP, 0, 0);
190 	ASSERT_ON_ERROR(retval, NETAPP_ERROR);
191 #endif
192 
193 #if defined(CONFIG_NET_IPV6)
194 	if_bitmap = ~0;
195 #else
196 	/* Disable ipv6 */
197 	if_bitmap = !(SL_NETCFG_IF_IPV6_STA_LOCAL |
198 		      SL_NETCFG_IF_IPV6_STA_GLOBAL);
199 #endif
200 	retval = sl_NetCfgSet(SL_NETCFG_IF, SL_NETCFG_IF_STATE,
201 			      sizeof(if_bitmap),
202 			      (const unsigned char *)&if_bitmap);
203 	ASSERT_ON_ERROR(retval, NETAPP_ERROR);
204 
205 	/* Configure scan parameters to default */
206 	scan_default.ChannelsMask = CHANNEL_MASK_ALL;
207 	scan_default.RssiThreshold = RSSI_TH_MAX;
208 
209 	retval = sl_WlanSet(SL_WLAN_CFG_GENERAL_PARAM_ID,
210 			    SL_WLAN_GENERAL_PARAM_OPT_SCAN_PARAMS,
211 			    sizeof(scan_default), (uint8_t *)&scan_default);
212 	ASSERT_ON_ERROR(retval, WLAN_ERROR);
213 
214 	/* Disable scans: In other words, use "one-shot" scanning */
215 	config_opt = SL_WLAN_SCAN_POLICY(0, 0);
216 	retval = sl_WlanPolicySet(SL_WLAN_POLICY_SCAN, config_opt, NULL, 0);
217 	ASSERT_ON_ERROR(retval, WLAN_ERROR);
218 
219 	/* Set TX power lvl to max */
220 	power = 0U;
221 	retval = sl_WlanSet(SL_WLAN_CFG_GENERAL_PARAM_ID,
222 			    SL_WLAN_GENERAL_PARAM_OPT_STA_TX_POWER, 1,
223 			    (uint8_t *)&power);
224 	ASSERT_ON_ERROR(retval, WLAN_ERROR);
225 
226 	/* Set NWP Power policy to 'normal' */
227 	retval = sl_WlanPolicySet(SL_WLAN_POLICY_PM, SL_WLAN_NORMAL_POLICY,
228 				  NULL, 0);
229 	ASSERT_ON_ERROR(retval, WLAN_ERROR);
230 
231 	/* Unregister mDNS services */
232 	retval = sl_NetAppMDNSUnRegisterService(0, 0, 0);
233 	ASSERT_ON_ERROR(retval, NETAPP_ERROR);
234 
235 	/* Remove all 64 RX filters (8*8) */
236 	(void)memset(rx_filterid_mask.FilterBitmap, 0xFF, 8);
237 
238 	retval = sl_WlanSet(SL_WLAN_RX_FILTERS_ID, SL_WLAN_RX_FILTER_REMOVE,
239 			    sizeof(SlWlanRxFilterOperationCommandBuff_t),
240 			    (uint8_t *)&rx_filterid_mask);
241 	ASSERT_ON_ERROR(retval, WLAN_ERROR);
242 
243 	/* Set NWP role as STA */
244 	retval = sl_WlanSetMode(ROLE_STA);
245 	ASSERT_ON_ERROR(retval, WLAN_ERROR);
246 
247 	/* For changes to take affect, we restart the NWP */
248 	retval = sl_Stop(0xFF);
249 	ASSERT_ON_ERROR(retval, DEVICE_ERROR);
250 
251 	mode = sl_Start(0, 0, 0);
252 	ASSERT_ON_ERROR(mode, DEVICE_ERROR);
253 
254 	if (mode != ROLE_STA) {
255 		LOG_ERR("Failed to configure device to it's default state");
256 		retval = -1;
257 	} else {
258 		nwp.role = ROLE_STA;
259 		SET_STATUS_BIT(nwp.status, STATUS_BIT_NWP_INIT);
260 		retval = 0;
261 	}
262 
263 	return retval;
264 }
265 
266 /**
267  *  @brief SimpleLinkWlanEventHandler
268  *
269  *  This handler gets called whenever a WLAN event is reported
270  *  by the host driver / NWP.
271  *
272  *  @note See the CC3120/CC3220 NWP programmer's guide (SWRU455)
273  *	  sections 4.3.4, 4.4.5 and 4.5.5.
274  */
SimpleLinkWlanEventHandler(SlWlanEvent_t * wlan_event)275 void SimpleLinkWlanEventHandler(SlWlanEvent_t *wlan_event)
276 {
277 	SlWlanEventDisconnect_t	 *event_data = NULL;
278 
279 	if (!wlan_event) {
280 		return;
281 	}
282 
283 	switch (wlan_event->Id) {
284 	case SL_WLAN_EVENT_CONNECT:
285 		SET_STATUS_BIT(nwp.status, STATUS_BIT_CONNECTION);
286 
287 		/* Store new connection SSID and BSSID: */
288 		memcpy(sl_conn.ssid, wlan_event->Data.Connect.SsidName,
289 		       wlan_event->Data.Connect.SsidLen);
290 		memcpy(sl_conn.bssid, wlan_event->Data.Connect.Bssid,
291 		       BSSID_LEN_MAX);
292 
293 		LOG_INF("[WLAN EVENT] STA Connected to the AP: %s, "
294 			"BSSID: %x:%x:%x:%x:%x:%x",
295 			log_strdup(sl_conn.ssid), sl_conn.bssid[0],
296 			sl_conn.bssid[1], sl_conn.bssid[2],
297 			sl_conn.bssid[3], sl_conn.bssid[4],
298 			sl_conn.bssid[5]);
299 
300 		/* Continue the notification callback chain... */
301 		sl_conn.error = 0;
302 		nwp.cb(SL_WLAN_EVENT_CONNECT, &sl_conn);
303 		break;
304 
305 	case SL_WLAN_EVENT_DISCONNECT:
306 		CLR_STATUS_BIT(nwp.status, STATUS_BIT_CONNECTION);
307 		CLR_STATUS_BIT(nwp.status, STATUS_BIT_IP_ACQUIRED);
308 		CLR_STATUS_BIT(nwp.status, STATUS_BIT_IPV6_ACQUIRED);
309 
310 		event_data = &wlan_event->Data.Disconnect;
311 
312 		/* If the user has initiated 'Disconnect' request,
313 		 * 'reason_code' is SL_WLAN_DISCONNECT_USER_INITIATED
314 		 */
315 		if (SL_WLAN_DISCONNECT_USER_INITIATED ==
316 		    event_data->ReasonCode) {
317 			LOG_INF("[WLAN EVENT] "
318 				"Device disconnected from the AP: %s",
319 				log_strdup(event_data->SsidName));
320 			LOG_INF("BSSID: %x:%x:%x:%x:%x:%x on application's"
321 				" request", event_data->Bssid[0],
322 				event_data->Bssid[1], event_data->Bssid[2],
323 				event_data->Bssid[3], event_data->Bssid[4],
324 				event_data->Bssid[5]);
325 			sl_conn.error = 0;
326 		} else {
327 			LOG_ERR("[WLAN ERROR] "
328 				"Device disconnected from the AP: %s",
329 				log_strdup(event_data->SsidName));
330 			LOG_ERR("BSSID: %x:%x:%x:%x:%x:%x on error: %d",
331 				event_data->Bssid[0],
332 				event_data->Bssid[1], event_data->Bssid[2],
333 				event_data->Bssid[3], event_data->Bssid[4],
334 				event_data->Bssid[5],
335 				event_data->ReasonCode);
336 			sl_conn.error = event_data->ReasonCode;
337 		}
338 
339 		(void)memset(&(sl_conn.ssid), 0x0, sizeof(sl_conn.ssid));
340 		(void)memset(&(sl_conn.bssid), 0x0, sizeof(sl_conn.bssid));
341 
342 		/* Continue the notification callback chain... */
343 		nwp.cb(SL_WLAN_EVENT_DISCONNECT, &sl_conn);
344 		break;
345 
346 	case SL_WLAN_EVENT_STA_ADDED:
347 		memcpy(&(sl_conn.bssid), wlan_event->Data.STAAdded.Mac,
348 		       SL_WLAN_BSSID_LENGTH);
349 		LOG_INF("[WLAN EVENT] STA was added to AP: "
350 			"BSSID: %x:%x:%x:%x:%x:%x",
351 			sl_conn.bssid[0], sl_conn.bssid[1],
352 			sl_conn.bssid[2], sl_conn.bssid[3],
353 			sl_conn.bssid[4], sl_conn.bssid[5]);
354 		break;
355 	case SL_WLAN_EVENT_STA_REMOVED:
356 		memcpy(&(sl_conn.bssid), wlan_event->Data.STAAdded.Mac,
357 		       SL_WLAN_BSSID_LENGTH);
358 		LOG_INF("[WLAN EVENT] STA was removed from AP: "
359 			"BSSID: %x:%x:%x:%x:%x:%x",
360 			sl_conn.bssid[0], sl_conn.bssid[1],
361 			sl_conn.bssid[2], sl_conn.bssid[3],
362 			sl_conn.bssid[4], sl_conn.bssid[5]);
363 
364 		(void)memset(&(sl_conn.bssid), 0x0, sizeof(sl_conn.bssid));
365 		break;
366 	default:
367 		LOG_ERR("[WLAN EVENT] Unexpected event [0x%lx]",
368 			wlan_event->Id);
369 		break;
370 	}
371 }
372 
373 /**
374  *  @brief SimpleLinkNetAppEventHandler
375  *
376  *  This handler gets called whenever a Netapp event is reported
377  *  by the host driver / NWP.
378  *
379  *  @note See the CC3120/CC3220 NWP programmer's guide (SWRU455)
380  *	  section 5.7.
381  */
SimpleLinkNetAppEventHandler(SlNetAppEvent_t * netapp_event)382 void SimpleLinkNetAppEventHandler(SlNetAppEvent_t *netapp_event)
383 {
384 	SlIpV4AcquiredAsync_t *event_data = NULL;
385 	uint32_t i;
386 
387 	if (!netapp_event) {
388 		return;
389 	}
390 
391 	switch (netapp_event->Id) {
392 	case SL_NETAPP_EVENT_IPV4_ACQUIRED:
393 		SET_STATUS_BIT(nwp.status, STATUS_BIT_IP_ACQUIRED);
394 
395 		/* Ip Acquired Event Data */
396 		event_data = &netapp_event->Data.IpAcquiredV4;
397 		sl_conn.ip_addr = event_data->Ip;
398 
399 		/* Gateway IP address */
400 		sl_conn.gateway_ip = event_data->Gateway;
401 
402 		LOG_INF("[NETAPP EVENT] IP set to: IPv4=%d.%d.%d.%d, "
403 			"Gateway=%d.%d.%d.%d",
404 			SL_IPV4_BYTE(sl_conn.ip_addr, 3),
405 			SL_IPV4_BYTE(sl_conn.ip_addr, 2),
406 			SL_IPV4_BYTE(sl_conn.ip_addr, 1),
407 			SL_IPV4_BYTE(sl_conn.ip_addr, 0),
408 
409 			SL_IPV4_BYTE(sl_conn.gateway_ip, 3),
410 			SL_IPV4_BYTE(sl_conn.gateway_ip, 2),
411 			SL_IPV4_BYTE(sl_conn.gateway_ip, 1),
412 			SL_IPV4_BYTE(sl_conn.gateway_ip, 0));
413 
414 		nwp.cb(SIMPLELINK_WIFI_CB_IPACQUIRED, &sl_conn);
415 		break;
416 
417 	case SL_NETAPP_EVENT_IPV6_ACQUIRED:
418 		SET_STATUS_BIT(nwp.status, STATUS_BIT_IPV6_ACQUIRED);
419 
420 		for (i = 0U; i < 4; i++) {
421 			sl_conn.ipv6_addr[i] =
422 			  netapp_event->Data.IpAcquiredV6.Ip[i];
423 		}
424 
425 		if (LOG_LEVEL >= LOG_LEVEL_INF) {
426 			LOG_INF("[NETAPP EVENT] IP Acquired: "
427 				"IPv6=%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x",
428 				((sl_conn.ipv6_addr[0] >> 16) & 0xffff),
429 				sl_conn.ipv6_addr[0] & 0xffff,
430 				((sl_conn.ipv6_addr[1] >> 16) & 0xffff),
431 				sl_conn.ipv6_addr[1] & 0xffff,
432 				((sl_conn.ipv6_addr[2] >> 16) & 0xffff),
433 				sl_conn.ipv6_addr[2] & 0xffff,
434 				((sl_conn.ipv6_addr[3] >> 16) & 0xffff),
435 				sl_conn.ipv6_addr[3] & 0xffff);
436 
437 		}
438 
439 		nwp.cb(SIMPLELINK_WIFI_CB_IPV6ACQUIRED, &sl_conn);
440 		break;
441 
442 	case SL_DEVICE_EVENT_DROPPED_NETAPP_IP_LEASED:
443 		SET_STATUS_BIT(nwp.status, STATUS_BIT_IP_LEASED);
444 		SET_STATUS_BIT(nwp.status, STATUS_BIT_IP_ACQUIRED);
445 
446 		sl_conn.sta_ip = netapp_event->Data.IpLeased.IpAddress;
447 		LOG_INF("[NETAPP EVENT] IP Leased to Client: "
448 			"IP=%d.%d.%d.%d",
449 			SL_IPV4_BYTE(sl_conn.sta_ip, 3),
450 			SL_IPV4_BYTE(sl_conn.sta_ip, 2),
451 			SL_IPV4_BYTE(sl_conn.sta_ip, 1),
452 			SL_IPV4_BYTE(sl_conn.sta_ip, 0));
453 
454 		break;
455 
456 	case SL_DEVICE_EVENT_DROPPED_NETAPP_IP_RELEASED:
457 		LOG_INF("[NETAPP EVENT] IP is released.");
458 		break;
459 
460 	default:
461 		LOG_ERR("[NETAPP EVENT] Unexpected event [0x%lx]",
462 			netapp_event->Id);
463 		break;
464 	}
465 
466 	if ((netapp_event->Id == SL_NETAPP_EVENT_IPV4_ACQUIRED) ||
467 		(netapp_event->Id == SL_NETAPP_EVENT_IPV6_ACQUIRED)) {
468 		/* Initialize SlNetSock layer for getaddrinfo */
469 		SlNetIf_init(0);
470 		/*
471 		 * We are only using SlNetSock to support getaddrinfo()
472 		 * for the WiFi interface, so hardcoding the interface
473 		 * id to 1 here.
474 		 */
475 		SlNetIf_add(SLNETIF_ID_1, SLNET_IF_WIFI_NAME,
476 			(const SlNetIf_Config_t *)&slnetifwifi_config_zephyr,
477 			SLNET_IF_WIFI_PRIO);
478 
479 		SlNetSock_init(0);
480 		SlNetUtil_init(0);
481 	}
482 }
483 
484 /**
485  *  @brief SimpleLinkGeneralEventHandler
486  *
487  *  This handler gets called whenever a general error is reported
488  *  by the NWP / Host driver. Since these errors are not fatal,
489  *  the application can handle them.
490  *
491  *  @note See the CC3120/CC3220 NWP programmer's guide (SWRU455)
492  *	  section 17.9.
493  */
SimpleLinkGeneralEventHandler(SlDeviceEvent_t * dev_event)494 void SimpleLinkGeneralEventHandler(SlDeviceEvent_t *dev_event)
495 {
496 	if (!dev_event) {
497 		return;
498 	}
499 
500 	LOG_INF("[GENERAL EVENT] - ID=[%d] Sender=[%d]",
501 		dev_event->Data.Error.Code,
502 		dev_event->Data.Error.Source);
503 }
504 
505 /**
506  *  @brief SimpleLinkFatalErrorEventHandler
507  *
508  *  This handler gets called whenever a driver error occurs requiring
509  *  restart of the device in order to recover.
510  */
SimpleLinkFatalErrorEventHandler(SlDeviceFatal_t * fatal_err_event)511 void SimpleLinkFatalErrorEventHandler(SlDeviceFatal_t *fatal_err_event)
512 {
513 
514 	switch (fatal_err_event->Id) {
515 	case SL_DEVICE_EVENT_FATAL_DEVICE_ABORT:
516 		LOG_ERR("[ERROR] - FATAL ERROR: "
517 			"Abort NWP event detected: "
518 			"AbortType=%ld, AbortData=0x%lx",
519 			fatal_err_event->Data.DeviceAssert.Code,
520 			fatal_err_event->Data.DeviceAssert.Value);
521 		break;
522 
523 	case SL_DEVICE_EVENT_FATAL_DRIVER_ABORT:
524 		LOG_ERR("[ERROR] - FATAL ERROR: Driver Abort detected.");
525 		break;
526 
527 	case SL_DEVICE_EVENT_FATAL_NO_CMD_ACK:
528 		LOG_ERR("[ERROR] - FATAL ERROR: No Cmd Ack detected "
529 			"[cmd opcode = 0x%lx]",
530 			fatal_err_event->Data.NoCmdAck.Code);
531 		break;
532 
533 	case SL_DEVICE_EVENT_FATAL_SYNC_LOSS:
534 		LOG_ERR("[ERROR] - FATAL ERROR: Sync loss detected");
535 		break;
536 
537 	case SL_DEVICE_EVENT_FATAL_CMD_TIMEOUT:
538 		LOG_ERR("[ERROR] - FATAL ERROR: "
539 			"Async event timeout detected "
540 			"[event opcode =0x%lx]",
541 			fatal_err_event->Data.CmdTimeout.Code);
542 		break;
543 
544 	default:
545 		LOG_ERR("[ERROR] - FATAL ERROR: "
546 			"Unspecified error detected");
547 		break;
548 	}
549 }
550 
551 /* Unused, but must be defined to link.	 */
SimpleLinkSockEventHandler(SlSockEvent_t * psock)552 void SimpleLinkSockEventHandler(SlSockEvent_t *psock)
553 {
554 	ARG_UNUSED(psock);
555 }
556 
557 /* Unused, but must be defined to link.	 */
SimpleLinkHttpServerEventHandler(SlNetAppHttpServerEvent_t * http_event,SlNetAppHttpServerResponse_t * http_resp)558 void SimpleLinkHttpServerEventHandler(SlNetAppHttpServerEvent_t *http_event,
559 				      SlNetAppHttpServerResponse_t *http_resp)
560 {
561 	ARG_UNUSED(http_event);
562 	ARG_UNUSED(http_resp);
563 }
564 
565 
566 /* Unused, but must be defined to link.	 */
SimpleLinkNetAppRequestEventHandler(SlNetAppRequest_t * netapp_request,SlNetAppResponse_t * netapp_response)567 void SimpleLinkNetAppRequestEventHandler(SlNetAppRequest_t *netapp_request,
568 					 SlNetAppResponse_t *netapp_response)
569 {
570 	ARG_UNUSED(netapp_request);
571 	ARG_UNUSED(netapp_response);
572 }
573 
574 /* Unused, but must be defined to link.	 */
SimpleLinkNetAppRequestMemFreeEventHandler(uint8_t * buffer)575 void SimpleLinkNetAppRequestMemFreeEventHandler(uint8_t *buffer)
576 {
577 	ARG_UNUSED(buffer);
578 }
579 
580 /* Note: SimpleLink WiFi scan also can return the following:
581  * - BSSID
582  * - Whether network hidden or visible
583  * - Other types of security
584  */
z_simplelink_get_scan_result(int index,struct wifi_scan_result * scan_result)585 void z_simplelink_get_scan_result(int index,
586 				 struct wifi_scan_result *scan_result)
587 {
588 	SlWlanNetworkEntry_t *net_entry;
589 	int sec_bmp;
590 
591 	__ASSERT_NO_MSG(index <= CONFIG_WIFI_SIMPLELINK_SCAN_COUNT);
592 	net_entry = &nwp.net_entries[index];
593 
594 	(void)memset(scan_result, 0x0, sizeof(struct wifi_scan_result));
595 
596 	__ASSERT_NO_MSG(net_entry->SsidLen <= WIFI_SSID_MAX_LEN);
597 	memcpy(scan_result->ssid, net_entry->Ssid, net_entry->SsidLen);
598 	scan_result->ssid_length = net_entry->SsidLen;
599 	scan_result->channel = net_entry->Channel;
600 
601 	/* Parse security bitmap: */
602 	sec_bmp = net_entry->SecurityInfo;
603 	if (SL_WLAN_SCAN_RESULT_SEC_TYPE_BITMAP(sec_bmp) & 0x6) {
604 		scan_result->security = WIFI_SECURITY_TYPE_PSK;
605 	} else {
606 		scan_result->security = WIFI_SECURITY_TYPE_NONE;
607 	}
608 
609 	scan_result->rssi = net_entry->Rssi;
610 }
611 
z_simplelink_start_scan(void)612 int z_simplelink_start_scan(void)
613 {
614 	int32_t ret;
615 
616 	/* Clear the results buffer */
617 	(void)memset(&nwp.net_entries, 0x0, sizeof(nwp.net_entries));
618 
619 	/* Attempt to get scan results from NWP
620 	 * Note: If scan policy isn't set, invoking 'sl_WlanGetNetworkList()'
621 	 * for the first time triggers 'one shot' scan.
622 	 */
623 	ret = sl_WlanGetNetworkList(0, CONFIG_WIFI_SIMPLELINK_SCAN_COUNT,
624 				    &nwp.net_entries[0]);
625 	LOG_DBG("sl_WlanGetNetworkList: %d", ret);
626 
627 	return ret;
628 }
629 
z_simplelink_get_mac(unsigned char * mac)630 void z_simplelink_get_mac(unsigned char *mac)
631 {
632 	uint16_t mac_len = SL_MAC_ADDR_LEN;
633 	uint16_t config_opt = 0U;
634 
635 	sl_NetCfgGet(SL_NETCFG_MAC_ADDRESS_GET, &config_opt,
636 		     &mac_len, (uint8_t *)mac);
637 }
638 
z_simplelink_connect(struct wifi_connect_req_params * params)639 int z_simplelink_connect(struct wifi_connect_req_params *params)
640 {
641 	SlWlanSecParams_t secParams = { 0 };
642 	long lretval;
643 
644 	if (params->security == WIFI_SECURITY_TYPE_PSK) {
645 		secParams.Key = (signed char *)params->psk;
646 		secParams.KeyLen = params->psk_length;
647 		/* This is only mapping handled for now: */
648 		secParams.Type = SL_WLAN_SEC_TYPE_WPA_WPA2;
649 	} else {
650 		secParams.Key = (signed char *)NULL;
651 		secParams.KeyLen = 0;
652 		secParams.Type = SL_WLAN_SEC_TYPE_OPEN;
653 	}
654 
655 	lretval = sl_WlanConnect((signed char *)params->ssid,
656 				 params->ssid_length, 0, &secParams, 0);
657 	LOG_DBG("sl_WlanConnect: %ld", lretval);
658 
659 	return lretval;
660 }
661 
z_simplelink_disconnect(void)662 int z_simplelink_disconnect(void)
663 {
664 	long lretval;
665 
666 	lretval = sl_WlanDisconnect();
667 	LOG_DBG("sl_WlanDisconnect: %ld", lretval);
668 
669 	return lretval;
670 }
671 
z_simplelink_init(simplelink_wifi_cb_t wifi_cb)672 int z_simplelink_init(simplelink_wifi_cb_t wifi_cb)
673 {
674 	int retval;
675 
676 	__ASSERT(wifi_cb, "callback must be supplied");
677 
678 	/* Init the board: */
679 	CC3220SF_LAUNCHXL_init();
680 
681 	/* Configure SimpleLink NWP: */
682 	nwp.status = 0U;
683 	nwp.role = ROLE_RESERVED;
684 	nwp.cb = wifi_cb;
685 
686 	(void)memset(&sl_conn, 0x0, sizeof(sl_conn));
687 
688 	retval = configure_simplelink();
689 	__ASSERT(retval >= 0, "Unable to configure SimpleLink");
690 
691 	return retval;
692 }
693