Open Model Railroad Network (OpenMRN)
Loading...
Searching...
No Matches
net_cc3220/CC32xxWiFi.cxx
Go to the documentation of this file.
1
34//#define LOGLEVEL INFO
35
36#define SUPPORT_SL_R1_API
37
38#include "CC32xxWiFi.hxx"
39#include "CC32xxSocket.hxx"
40
41#include "freertos_drivers/common/WifiDefs.hxx"
44#include "utils/logging.h"
45
46#include <unistd.h>
47
48// Simplelink includes
49#include <ti/drivers/net/wifi/simplelink.h>
50#include <ti/drivers/net/wifi/source/protocol.h>
51
53struct CC32xxWiFi::WlanEvent : public ::SlWlanEvent_t {};
54
56struct CC32xxWiFi::NetAppEvent : public ::SlNetAppEvent_t {};
57
59struct CC32xxWiFi::SockEvent : public ::SlSockEvent_t {};
60
62struct CC32xxWiFi::SockTriggerEvent : public ::SlSockTriggerEvent_t {};
63
65struct CC32xxWiFi::HttpServerEvent : public ::SlNetAppHttpServerEvent_t {};
66
68struct CC32xxWiFi::HttpServerResponse : public ::SlNetAppHttpServerResponse_t {};
69
71struct CC32xxWiFi::NetAppRequest : public ::SlNetAppRequest_t {};
72
74struct CC32xxWiFi::NetAppResponse : public ::SlNetAppResponse_t {};
75
77struct CC32xxWiFi::FatalErrorEvent : public ::SlDeviceFatal_t {};
78
82static SlFdSet_t rfds;
83
87static SlFdSet_t wfds;
88
92static SlFdSet_t efds;
93
95static int fdHighest;
96
111static int16_t slSockets[SL_MAX_SOCKETS];
112
116{
117 fdHighest = 0;
118 for (int i = 0; i < SL_MAX_SOCKETS; ++i)
119 {
120 if (slSockets[i] != -1)
121 {
122 if (slSockets[i] > fdHighest)
123 {
124 if (SL_SOCKET_FD_ISSET(slSockets[i], &rfds) ||
125 SL_SOCKET_FD_ISSET(slSockets[i], &wfds) ||
126 SL_SOCKET_FD_ISSET(slSockets[i], &efds))
127 {
128 fdHighest = slSockets[i];
129 }
130 }
131 }
132 }
133}
134
138void add_socket(int16_t sd)
139{
140 if (sd > fdHighest)
141 {
142 fdHighest = sd;
143 }
144 for (int i = 0; i < SL_MAX_SOCKETS; ++i)
145 {
146 if (slSockets[i] == sd)
147 {
148 /* already known */
149 return;
150 }
151 }
152 for (int i = 0; i < SL_MAX_SOCKETS; ++i)
153 {
154 if (slSockets[i] == -1)
155 {
156 slSockets[i] = sd;
157 break;
158 }
159 }
160}
161
165void del_socket(int16_t sd)
166{
167 for (int i = 0; i < SL_MAX_SOCKETS; ++i)
168 {
169 if (slSockets[i] == sd)
170 {
171 slSockets[i] = -1;
172 break;
173 }
174 }
175 new_highest();
176}
177
178/*
179 * CC32xxWiFi::CC32xxWiFi()
180 */
182 : ipAddress(0)
183 , ipAcquiredCallback_(nullptr)
184 , wakeup(-1)
185 , rssi(0)
186 , wlanRole(WlanRole::UNKNOWN)
187 , started(false)
188 , connected(0)
189 , connectionFailed(0)
190 , ipAcquired(0)
191 , ipLeased(0)
192 , smartConfigStart(0)
193 , securityFailure(0)
194{
195 for (int i = 0; i < SL_MAX_SOCKETS; ++i)
196 {
197 slSockets[i] = -1;
198 }
199 SL_SOCKET_FD_ZERO(&rfds);
200 SL_SOCKET_FD_ZERO(&wfds);
201 SL_SOCKET_FD_ZERO(&efds);
202 ssid[0] = '\0';
203
205 "__SL_G_UNA", bind(&CC32xxWiFi::http_get_ip_address, this));
206}
207
209{
210 switch (sec_type)
211 {
212 default:
213 case SEC_OPEN:
214 return SL_WLAN_SEC_TYPE_OPEN;
215 case SEC_WEP:
216 return SL_WLAN_SEC_TYPE_WEP;
217 case SEC_WPA2:
218 return SL_WLAN_SEC_TYPE_WPA_WPA2;
219 }
220}
221
223{
224 auto t = SL_WLAN_SCAN_RESULT_SEC_TYPE_BITMAP(sec_type);
225 switch (t)
226 {
227 default:
228 case SL_WLAN_SECURITY_TYPE_BITMAP_OPEN:
229 return SEC_OPEN;
230 case SL_WLAN_SECURITY_TYPE_BITMAP_WEP:
231 return SEC_WEP;
232 case SL_WLAN_SECURITY_TYPE_BITMAP_WPA:
233 case SL_WLAN_SECURITY_TYPE_BITMAP_WPA2:
234 case SL_WLAN_SECURITY_TYPE_BITMAP_WPA |
235 SL_WLAN_SECURITY_TYPE_BITMAP_WPA2:
236 return SEC_WPA2;
237 }
238}
239
240
242{
243 switch (sec_type)
244 {
245 default:
246 case SL_WLAN_SEC_TYPE_OPEN:
247 return SEC_OPEN;
248 case SL_WLAN_SEC_TYPE_WEP:
249 return SEC_WEP;
250 case SL_WLAN_SEC_TYPE_WPS_PBC:
251 case SL_WLAN_SEC_TYPE_WPS_PIN:
252 case SL_WLAN_SEC_TYPE_WPA_ENT:
253 case SL_WLAN_SEC_TYPE_WPA_WPA2:
254 return SEC_WPA2;
255 }
256}
257
258/*
259 * CC32xxWiFi::wlan_country_code_get()
260 */
262{
263 uint16_t config_option = SL_WLAN_GENERAL_PARAM_OPT_COUNTRY_CODE;
264 uint16_t len = 3;
265 uint8_t country[3];
266
267 int result = sl_WlanGet(SL_WLAN_CFG_GENERAL_PARAM_ID, &config_option, &len,
268 (uint8_t*)country);
269 if (result >= 0)
270 {
271 if (!strcmp((const char*)country, "US"))
272 {
273 return CountryCode::US;
274 }
275 else if (!strcmp((const char*)country, "EU"))
276 {
277 return CountryCode::EU;
278 }
279 else if (!strcmp((const char*)country, "JP"))
280 {
281 return CountryCode::JP;
282 }
283 }
284
285 return CountryCode::UNKNOWN;
286}
287
288/*
289 * CC32xxWiFi::wlan_country_code_set()
290 */
291int CC32xxWiFi::wlan_country_code_set(CountryCode cc, bool restart)
292{
293 if (cc != wlan_country_code_get())
294 {
295 const char *country;
296 switch (cc)
297 {
298 case CountryCode::US:
299 country = "US";
300 break;
301 case CountryCode::EU:
302 country = "EU";
303 break;
304 case CountryCode::JP:
305 country = "JP";
306 break;
307 default:
308 return -1;
309 }
310
311 int result = sl_WlanSet(SL_WLAN_CFG_GENERAL_PARAM_ID,
312 SL_WLAN_GENERAL_PARAM_OPT_COUNTRY_CODE, 2,
313 (const uint8_t*)country);
314
315 if (result < 0)
316 {
317 return -1;
318 }
319 if (restart)
320 {
321 sl_Stop(0xFFFF);
322 sl_Start(0, 0, 0);
323 }
324 }
325
326 return 0;
327}
328
329/*
330 * CC32xxWiFi::wlan_set_scan_params()
331 */
332void CC32xxWiFi::wlan_set_scan_params(int mask, int min_rssi)
333{
334 SlWlanScanParamCommand_t param_config = {0};
335 uint16_t option = SL_WLAN_GENERAL_PARAM_OPT_SCAN_PARAMS;
336 uint16_t param_len = sizeof(param_config);
337 int ret = sl_WlanGet(SL_WLAN_CFG_GENERAL_PARAM_ID, &option, &param_len,
338 (_u8 *)&param_config);
339 SlCheckResult(ret);
340 bool apply = false;
341 if (mask >= 0 && param_config.ChannelsMask != (uint32_t)mask)
342 {
343 param_config.ChannelsMask = mask;
344 apply = true;
345 }
346 if (min_rssi < 0 && param_config.RssiThreshold != min_rssi)
347 {
348 param_config.RssiThreshold = min_rssi;
349 apply = true;
350 }
351 if (!apply)
352 {
353 return;
354 }
355 ret = sl_WlanSet(SL_WLAN_CFG_GENERAL_PARAM_ID,
356 SL_WLAN_GENERAL_PARAM_OPT_SCAN_PARAMS, sizeof(param_config),
357 (_u8 *)&param_config);
358 SlCheckResult(ret);
359}
360
361/*
362 * CC32xxWiFi::wlan_profile_add()
363 */
364int CC32xxWiFi::wlan_profile_add(const char *ssid, SecurityType sec_type,
365 const char *key, unsigned priority)
366{
367 SlWlanSecParams_t sec_params;
368 sec_params.Key = (int8_t*)key;
369 sec_params.KeyLen = (key == nullptr) ? 0 : strlen(key);
370 sec_params.Type = security_type_to_simplelink(sec_type);
371
372 int16_t result = sl_WlanProfileAdd((const int8_t*)ssid, strlen(ssid),
373 nullptr, &sec_params, nullptr,
374 priority, 0);
375
376 return (result >= 0) ? result : -1;
377}
378
379/*
380 * CC32xxWiFi::wlan_profile_del()
381 */
383{
384 return sl_WlanProfileDel(index);
385}
386
387/*
388 * CC32xxWiFi::wlan_profile_del()
389 */
390int CC32xxWiFi::wlan_profile_del(const char *ssid)
391{
392 for (int i = 0; i < 7; ++i)
393 {
394 char name[33];
395 if (wlan_profile_get(i, name, nullptr, nullptr) != 0)
396 {
397 /* invalid entry, move onto the next one */
398 continue;
399 }
400
401 if (strcmp(name, ssid) == 0)
402 {
403 /* found a match */
404 return sl_WlanProfileDel(i);
405 }
406 }
407
408 /* no match found */
409 return -1;
410}
411
412/*
413 * CC32xxWiFi::wlan_profile_get()
414 */
415int CC32xxWiFi::wlan_profile_get(int index, char ssid[],
416 SecurityType *sec_type, uint32_t *priority)
417{
418 SlWlanSecParams_t sec_params;
419 int16_t ssid_len;
420
421 int16_t result = sl_WlanProfileGet(index, (int8_t*)ssid, &ssid_len,
422 nullptr, &sec_params, nullptr, priority);
423
424 if (result < 0)
425 {
426 return -1;
427 }
428
429 ssid[ssid_len] = '\0';
430
431 if (sec_type)
432 {
433 *sec_type = security_type_from_simplelink(sec_params.Type);
434 }
435
436 return 0;
437}
438
439/*
440 * CC32xxWiFi::wlan_profile_text_none()
441 */
443{
444 for (int i = 0; i < 7; ++i)
445 {
446 char ssid[33];
447 if (wlan_profile_get(i, ssid, nullptr, nullptr) == 0)
448 {
449 return false;
450 }
451 }
452
453 return true;
454}
455
456/*
457 * CC32xxWiFi::wlan_power_policy_get()
458 */
460{
461 uint8_t sl_wpp = 0;
462 SlWlanPmPolicyParams_t params;
463 int length = sizeof(params);
464
465 int result = sl_WlanPolicyGet(SL_WLAN_POLICY_PM, &sl_wpp, (uint8_t*)&params,
466 (uint8_t*)&length);
467
468 if (result != 0)
469 {
470 return -1;
471 }
472
473 switch (sl_wpp)
474 {
475 default:
476 return -1;
477 case SL_WLAN_ALWAYS_ON_POLICY:
479 break;
480 case SL_WLAN_LOW_LATENCY_POLICY:
482 break;
483 case SL_WLAN_NORMAL_POLICY:
484 *wpp = WLAN_NORMAL_POLICY;
485 break;
486 case SL_WLAN_LOW_POWER_POLICY:
488 break;
489 }
490
491 return 0;
492}
493
494/*
495 * CC32xxWiFi::wlan_power_policy_set()
496 */
498{
499 int result;
500 WlanPowerPolicy temp_wpp;
501 result = wlan_power_policy_get(&temp_wpp);
502 if (result != 0)
503 {
504 return -1;
505 }
506
507 if (temp_wpp != wpp)
508 {
509 uint8_t sl_wpp;
510 switch (wpp)
511 {
512 default:
513 return -1;
515 sl_wpp = SL_WLAN_ALWAYS_ON_POLICY;
516 break;
518 sl_wpp = SL_WLAN_LOW_LATENCY_POLICY;
519 break;
521 sl_wpp = SL_WLAN_NORMAL_POLICY;
522 break;
524 sl_wpp = SL_WLAN_LOW_POWER_POLICY;
525 break;
526 }
527 result = sl_WlanPolicySet(SL_WLAN_POLICY_PM, sl_wpp, NULL, 0);
528 }
529
530 return (result != 0) ? -1 : 0;
531}
532
534 uint8_t past_policy;
535 uint8_t mask;
536 uint8_t desired_policy;
537
538 int length = sizeof(past_policy);
539 int ret;
540 ret = sl_WlanPolicyGet(
541 SL_WLAN_POLICY_CONNECTION, &past_policy, 0, (_u8 *)&length);
542 if (!ret)
543 {
544 LOG(WARNING, "Failed to get past connection policy.");
545 past_policy = 0; // This will typically result in a write.
546 }
547
548 if (policy == WLAN_CONNECTION_NO_CHANGE)
549 {
550 // SL_WLAN_CONNECTION_POLICY(Auto,Fast,anyP2P,autoProvisioning)
551 mask = SL_WLAN_CONNECTION_POLICY(1, 0, 1, 1);
552 desired_policy = SL_WLAN_CONNECTION_POLICY(1, 0, 0, 0);
553 }
554 else
555 {
556 mask = SL_WLAN_CONNECTION_POLICY(1, 1, 1, 1);
557 desired_policy = SL_WLAN_CONNECTION_POLICY(
558 1, policy == WLAN_CONNECTION_FAST_RECONNECT ? 1 : 0, 0, 0);
559 }
560
561 if ((past_policy & mask) != (desired_policy & mask))
562 {
563 sl_WlanPolicySet(SL_WLAN_POLICY_CONNECTION, desired_policy, NULL, 0);
564 }
565}
566
567/*
568 * CC32xxWiFi::wlan_rescan()
569 */
571{
572 // This will trigger an immediate rescan and then every 10 minutes a new
573 // scan will be done if we have no connection.
574 unsigned long intervalInSeconds = 600;
575 sl_WlanPolicySet(SL_WLAN_POLICY_SCAN, 1 /*enable*/, (unsigned char *)
576 &intervalInSeconds,sizeof(intervalInSeconds));
577}
578
579/*
580 * CC32xxWiFi::wlan_network_list_get()
581 */
583{
584 SlWlanNetworkEntry_t* sl_entries = new SlWlanNetworkEntry_t[count];
585
586 int result = sl_WlanGetNetworkList(0, count, sl_entries);
587
588 for (int i = 0; i < result; ++i)
589 {
590 entries[i].ssid.assign((char*)sl_entries[i].Ssid, sl_entries[i].SsidLen);
591 entries[i].sec_type = security_type_from_scan(sl_entries[i].SecurityInfo);
592 entries[i].rssi = sl_entries[i].Rssi;
593 }
594
595 delete [] sl_entries;
596 return result;
597}
598
599/*
600 * CC32xxWiFi::wlan_mac()
601 */
602void CC32xxWiFi::wlan_mac(uint8_t mac[6])
603{
604 uint16_t len = 6;
605
606 sl_NetCfgGet(SL_NETCFG_MAC_ADDRESS_GET, nullptr, &len, mac);
607}
608
609/*
610 * CC32xxWiFi::wlan_set_mac()
611 */
612void CC32xxWiFi::wlan_set_mac(uint8_t mac[6])
613{
614 sl_NetCfgSet(SL_NETCFG_MAC_ADDRESS_SET, 1, 6, mac);
615}
616
617/*
618 * CC32xxWiFi::test_mode_start()
619 */
621{
622 os_thread_create(nullptr, "sl_Task", os_thread_get_priority_max(), 2048,
623 sl_Task, nullptr);
624
625 // the following code sequnce is taken from the Radio Test Tool
626 // application example.
627
628 #define CHANNEL_MASK_ALL 0x1FFF
629 #define RSSI_TH_MAX -95
630
631 int mode = sl_Start(0, 0, 0);
632 if (mode != ROLE_STA)
633 {
634 mode = sl_WlanSetMode(ROLE_STA);
635 sl_Stop(0xFF);
636 sl_Start(0, 0, 0);
637 }
638
639 // set policy to auto only
640 sl_WlanPolicySet(SL_WLAN_POLICY_CONNECTION,
641 SL_WLAN_CONNECTION_POLICY(1, 0, 0, 0), nullptr, 0);
642
643 // disable auto provisioning
644 sl_WlanProvisioning(SL_WLAN_PROVISIONING_CMD_STOP, 0xFF, 0, nullptr, 0);
645
646 // delete all stored Wi-Fi profiles
647 sl_WlanProfileDel(0xFF);
648
649 // enable DHCP client
650 sl_NetCfgSet(SL_NETCFG_IPV4_STA_ADDR_MODE, SL_NETCFG_ADDR_DHCP, 0, 0);
651
652 // disable IPv6
653 uint32_t if_bitmap = !(SL_NETCFG_IF_IPV6_STA_LOCAL |
654 SL_NETCFG_IF_IPV6_STA_GLOBAL);
655 sl_NetCfgSet(SL_NETCFG_IF, SL_NETCFG_IF_STATE, sizeof(if_bitmap),
656 (const uint8_t*)&if_bitmap);
657
658 // configure scan parameters to default
659 SlWlanScanParamCommand_t scan_default;
660 scan_default.ChannelsMask = CHANNEL_MASK_ALL;
661 scan_default.RssiThreshold = RSSI_TH_MAX;
662 sl_WlanSet(SL_WLAN_CFG_GENERAL_PARAM_ID,
663 SL_WLAN_GENERAL_PARAM_OPT_SCAN_PARAMS,
664 sizeof(scan_default), (uint8_t*)&scan_default);
665
666 // disable scans
667 uint8_t config_opt = SL_WLAN_SCAN_POLICY(0, 0);
668 sl_WlanPolicySet(SL_WLAN_POLICY_SCAN, config_opt, nullptr, 0);
669
670 // set TX power 1v1 to max
671 uint8_t power = 0;
672 sl_WlanSet(SL_WLAN_CFG_GENERAL_PARAM_ID,
673 SL_WLAN_GENERAL_PARAM_OPT_STA_TX_POWER, 1, (uint8_t*)&power);
674
675 // set NWP power policy to "normal"
676 sl_WlanSet(SL_WLAN_POLICY_PM, SL_WLAN_NORMAL_POLICY, 0, 0);
677
678 // unregister mDNS services
679 sl_NetAppMDNSUnRegisterService(0, 0, 0);
680
681 // remove all 64 RX filters (8*8)
682 SlWlanRxFilterOperationCommandBuff_t rx_filter_id_mask;
683 memset(rx_filter_id_mask.FilterBitmap, 0xFF, 8);
684 sl_WlanSet(SL_WLAN_RX_FILTERS_ID, SL_WLAN_RX_FILTER_REMOVE,
685 sizeof(SlWlanRxFilterOperationCommandBuff_t),
686 (uint8_t*)&rx_filter_id_mask);
687
688 // set NWP role as STA
689 sl_WlanSetMode(ROLE_STA);
690
691 // restart the NWP
692 sl_Stop(0xFF);
693 sl_Start(0, 0, 0);
694}
695
696/*
697 * CC32xxWiFi::start()
698 */
699void CC32xxWiFi::start(WlanRole role, WlanPowerPolicy power_policy, WlanConnectionPolicy connection_policy)
700{
701 /* We use OSThread::get_priority_max() - 1 for the thread priorities because
702 * we want a to be among the highest, but want to reserve one higher
703 * priority so that device drivers have the option of using the highest
704 * priority for deferred processing.
705 */
706 wlanRole = role;
707 wlanPowerPolicy = power_policy;
708 connectionPolicy = connection_policy;
709
710 os_thread_create(nullptr, "sl_Task", OSThread::get_priority_max(), 2048,
711 sl_Task, nullptr);
712
713 os_thread_create(nullptr, "Wlan Task", OSThread::get_priority_max() - 1,
714 2048, wlan_task_entry, nullptr);
715}
716
717/*
718 * CC32xxWiFi::stop()
719 */
721{
722 ipAcquired = false;
723 connected = false;
724 started = false;
725 sl_Stop(0xFF);
726}
727
728/*
729 * CC32xxWiFi::wlan_connect()
730 */
731WlanConnectResult CC32xxWiFi::wlan_connect(const char *ssid,
732 const char* security_key,
733 SecurityType security_type)
734{
735 connected = 0;
736 ipAcquired = 0;
737 securityFailure = 0;
738 this->ssid[0] = '\0';
740 {
741 ipAcquiredCallback_(false);
742 }
743
744 SlWlanSecParams_t sec_params;
745 sec_params.Key = (_i8*)security_key;
746 sec_params.KeyLen = strlen(security_key);
747 sec_params.Type = security_type_to_simplelink(security_type);
748
749 int result = sl_WlanConnect((signed char*)ssid, strlen(ssid), 0,
750 &sec_params, 0);
751
752 switch (result)
753 {
754 default:
755 SlCheckError(result);
756 return WlanConnectResult::CONNECT_OK;
757 case SL_ERROR_WLAN_PASSWORD_ERROR:
758 return WlanConnectResult::PASSWORD_INVALID;
759 }
760}
761
762/*
763 * CC32xxWiFi::wlan_disconnect()
764 */
766{
767 connected = 0;
768 ipAcquired = 0;
769 securityFailure = 0;
770 ssid[0] = '\0';
772 {
773 ipAcquiredCallback_(false);
774 }
775 sl_WlanDisconnect();
776}
777
778/*
779 * CC32xxWiFi::wlan_wps_pbc_initiate()
780 */
782{
783 connected = 0;
784 ipAcquired = 0;
785 securityFailure = 0;
786 ssid[0] = '\0';
788 {
789 ipAcquiredCallback_(false);
790 }
791
792 SlWlanSecParams_t sec_params;
793 sec_params.Key = (signed char*)"";
794 sec_params.KeyLen = 0;
795 sec_params.Type = SL_WLAN_SEC_TYPE_WPS_PBC;
796
797 int result = sl_WlanConnect((signed char*)"WPS_AP", strlen("WPS_AP"), NULL,
798 &sec_params, NULL);
799 HASSERT(result >= 0);
800}
801
802/*
803 * CC32xxWiFi::wlan_setup_ap()
804 */
805void CC32xxWiFi::wlan_setup_ap(const char *ssid, const char *security_key,
806 SecurityType security_type)
807{
808 if (ssid)
809 {
810 HASSERT(strlen(ssid) <= 32);
811 sl_WlanSet(SL_WLAN_CFG_AP_ID, SL_WLAN_AP_OPT_SSID, strlen(ssid),
812 (uint8_t *)ssid);
813 if (wlanRole == WlanRole::AP)
814 {
815 str_populate(this->ssid, ssid);
816 }
817 }
818
819 uint8_t sec_type = security_type_to_simplelink(security_type);
820 sl_WlanSet(SL_WLAN_CFG_AP_ID, SL_WLAN_AP_OPT_SECURITY_TYPE, 1,
821 (uint8_t*)&sec_type);
822
823 if (sec_type == SL_WLAN_SEC_TYPE_OPEN ||
824 security_key == nullptr)
825 {
826 return;
827 }
828
829 HASSERT(strlen(security_key) <= 64);
830 sl_WlanSet(SL_WLAN_CFG_AP_ID, SL_WLAN_AP_OPT_PASSWORD,
831 strlen(security_key), (uint8_t*)security_key);
832}
833
834/*
835 * CC32xxWiFi::wlan_get_ap_config()
836 */
837void CC32xxWiFi::wlan_get_ap_config(string *ssid, SecurityType *security_type)
838{
839 if (ssid)
840 {
841 // Reads AP SSID configuration from NWP.
842 ssid->clear();
843 ssid->resize(33);
844 uint16_t len = ssid->size();
845 uint16_t config_opt = SL_WLAN_AP_OPT_SSID;
846 sl_WlanGet(SL_WLAN_CFG_AP_ID, &config_opt, &len, (_u8*) &(*ssid)[0]);
847 ssid->resize(len);
848 }
849 if (security_type)
850 {
851 uint16_t len = sizeof(*security_type);
852 uint16_t config_opt = SL_WLAN_AP_OPT_SECURITY_TYPE;
853 uint8_t sl_sec_type = 0;
854 sl_WlanGet(SL_WLAN_CFG_AP_ID, &config_opt, &len, &sl_sec_type);
855 *security_type = security_type_from_simplelink(sl_sec_type);
856 }
857}
858
860{
861 if (wlanRole != WlanRole::AP)
862 {
863 return 0;
864 }
865 uint8_t num_connected = 0;
866 uint16_t len = sizeof(num_connected);
867 auto status = sl_NetCfgGet(
868 SL_NETCFG_AP_STATIONS_NUM_CONNECTED, NULL, &len, &num_connected);
869 if (status)
870 {
871 return -1;
872 }
873 return num_connected;
874}
875
877{
878 if (!connected)
879 {
880 resetblink(WIFI_BLINK_NOTASSOCIATED);
881 }
882 else if (!ipAcquired)
883 {
884 resetblink(WIFI_BLINK_ASSOC_NOIP);
885 }
886}
887
888/*
889 * CC32xxWiFi::set_default_state()
890 */
892{
893 long result = sl_Start(0, 0, 0);
894 if (result == SL_ERROR_ROLE_STA_ERR)
895 {
896 sl_Stop(0xFF);
897 result = sl_Start(0, 0, 0);
898 }
899
900 SlCheckError(result);
901 if (wlanRole == WlanRole::AP ||
902 (wlanRole == WlanRole::UNKNOWN && result == ROLE_AP))
903 {
904 wlanRole = WlanRole::AP;
905 if (result != ROLE_AP)
906 {
907 sl_WlanSetMode(ROLE_AP);
908 sl_Stop(0xFF);
909 sl_Start(0, 0, 0);
910 }
911 // Reads AP SSID configuration from NWP.
912 uint16_t len = sizeof(ssid);
913 memset(ssid, 0, len);
914 uint16_t config_opt = SL_WLAN_AP_OPT_SSID;
915 sl_WlanGet(SL_WLAN_CFG_AP_ID, &config_opt, &len, (_u8 *)ssid);
916 }
917 else
918 {
919 wlanRole = WlanRole::STA;
921 {
922 /* no profiles saved, add the default profile */
924 strlen(WIFI_PASS) > 0 ? SEC_WPA2 : SEC_OPEN,
925 WIFI_PASS, 0);
926 }
927 if (result != ROLE_STA)
928 {
929 sl_WlanSetMode(ROLE_STA);
930 sl_Stop(0xFF);
931 sl_Start(0, 0, 0);
932 }
933
935
937 {
939 }
940 }
941 started = true;
942}
943
944/*
945 * CC32xxWiFi::wlan_set_role()
946 */
947void CC32xxWiFi::wlan_set_role(WlanRole new_role)
948{
949 switch (new_role)
950 {
951 case WlanRole::STA:
952 sl_WlanSetMode(ROLE_STA);
953 break;
954 case WlanRole::AP:
955 sl_WlanSetMode(ROLE_AP);
956 break;
957 default:
958 DIE("Unsupported wlan role");
959 }
960}
961
962/*
963 * CC32xxWiFi::wlan_task()
964 */
966{
967 int result;
969
970 /* adjust to a lower priority task */
971 vTaskPrioritySet(NULL, configMAX_PRIORITIES / 2);
972
973 SlSockAddrIn_t address;
974
975 wakeup = sl_Socket(SL_AF_INET, SL_SOCK_DGRAM, 0);
976 HASSERT(wakeup >= 0);
977
978 address.sin_family = SL_AF_INET;
979 address.sin_port = sl_Htons(8000);
980 address.sin_addr.s_addr = SL_INADDR_ANY;
981 result = sl_Bind(wakeup, (SlSockAddr_t*)&address, sizeof(address));
982 HASSERT(result >= 0);
983
984 portENTER_CRITICAL();
985 SL_SOCKET_FD_SET(wakeup, &rfds);
987 portEXIT_CRITICAL();
988
989 unsigned next_wrssi_poll = (os_get_time_monotonic() >> 20) + 800;
990
991 for ( ; /* forever */ ; )
992 {
993
994 std::vector<std::function<void()> > callbacks_to_run;
995 {
996 OSMutexLock l(&lock_);
997 if (callbacks_.size()) {
998 callbacks_to_run.swap(callbacks_);
999 }
1000 }
1001 for (unsigned i = 0; i < callbacks_to_run.size(); ++i) {
1002 callbacks_to_run[i]();
1003 }
1004
1005 SlFdSet_t rfds_tmp = rfds;
1006 SlFdSet_t wfds_tmp = wfds;
1007 SlFdSet_t efds_tmp = efds;
1008 SlTimeval_t tv;
1009 tv.tv_sec = 1;
1010 tv.tv_usec = 0;
1011
1012 result = sl_Select(fdHighest + 1, &rfds_tmp, &wfds_tmp, &efds_tmp, &tv);
1013
1014 if (result < 0)
1015 {
1016 continue;
1017 }
1018
1019 if ((os_get_time_monotonic() >> 20) > next_wrssi_poll)
1020 {
1021 next_wrssi_poll = (os_get_time_monotonic() >> 20) + 800;
1022 /* timeout, get the RSSI value */
1023 SlWlanGetRxStatResponse_t response;
1024 if (sl_WlanRxStatGet(&response, 0) == 0)
1025 {
1026 if (response.AvarageMgMntRssi) {
1027 rssi = response.AvarageMgMntRssi;
1028 }
1029 }
1030 }
1031
1032 for (int i = 0; i < SL_MAX_SOCKETS && result > 0; ++i)
1033 {
1034 if (slSockets[i] == -1)
1035 {
1036 /* socket slot not in use */
1037 continue;
1038 }
1039 if (SL_SOCKET_FD_ISSET(slSockets[i], &wfds_tmp))
1040 {
1041 --result;
1042 portENTER_CRITICAL();
1043 SL_SOCKET_FD_CLR(slSockets[i], &wfds);
1044 new_highest();
1046 s->writeActive = true;
1047 s->select_wakeup(&s->selInfoWr);
1048 portEXIT_CRITICAL();
1049 }
1050 if (SL_SOCKET_FD_ISSET(slSockets[i], &rfds_tmp))
1051 {
1052 --result;
1053 if (slSockets[i] == wakeup)
1054 {
1055 /* this is the socket we use as a signal */
1056 char data;
1057 sl_Recv(wakeup, &data, 1, 0);
1058 }
1059 else
1060 {
1061 /* standard application level socket */
1062 portENTER_CRITICAL();
1063 SL_SOCKET_FD_CLR(slSockets[i], &rfds);
1064 new_highest();
1066 s->readActive = true;
1067 s->select_wakeup(&s->selInfoRd);
1068 portEXIT_CRITICAL();
1069 }
1070 }
1071 if (SL_SOCKET_FD_ISSET(slSockets[i], &efds_tmp))
1072 {
1073 --result;
1074 portENTER_CRITICAL();
1075 SL_SOCKET_FD_CLR(slSockets[i], &efds);
1076 new_highest();
1077 portEXIT_CRITICAL();
1078 /* currently we don't handle any errors */
1079 }
1080 }
1081 }
1082}
1083
1084/*
1085 * CC32xxWiFi::select_wakeup()
1086 */
1088{
1089 if (wakeup >= 0)
1090 {
1091 SlSockAddrIn_t address;
1092 SlSocklen_t length = sizeof(SlSockAddr_t);
1093 address.sin_family = SL_AF_INET;
1094 address.sin_port = sl_Htons(8000);
1095 address.sin_addr.s_addr = sl_Htonl(SL_IPV4_VAL(127,0,0,1));
1096
1097 /* note that loopback messages only work as long as the we are
1098 * connected to an AP, or acting as an AP ourselves. If neither of
1099 * these is the case, the wakeup of sl_Select() using this method is
1100 * not necessary. The sl_Select() API has a timeout to maintain state
1101 * periodically.
1102 */
1103 char data = -1;
1104 ssize_t result = sl_SendTo(wakeup, &data, 1, 0, (SlSockAddr_t*)&address,
1105 length);
1106 while (result != 1 && connected)
1107 {
1108 usleep(MSEC_TO_USEC(50));
1109 result = sl_SendTo(wakeup, &data, 1, 0, (SlSockAddr_t*)&address,
1110 length);
1111 }
1112 }
1113}
1114
1115void CC32xxWiFi::run_on_network_thread(std::function<void()> callback)
1116{
1117 {
1118 OSMutexLock l(&lock_);
1119 callbacks_.emplace_back(std::move(callback));
1120 }
1121 select_wakeup();
1122}
1123
1124/*
1125 * CC32xxWiFi::fd_remove()
1126 */
1128{
1129 portENTER_CRITICAL();
1130 SL_SOCKET_FD_CLR(sd, &rfds);
1131 SL_SOCKET_FD_CLR(sd, &wfds);
1132 SL_SOCKET_FD_CLR(sd, &efds);
1133 del_socket(sd);
1134 portEXIT_CRITICAL();
1135}
1136
1137/*
1138 * CC32xxWiFi::fd_set_read()
1139 */
1141{
1142 portENTER_CRITICAL();
1143 if (SL_SOCKET_FD_ISSET(sd, &rfds))
1144 {
1145 /* already set */
1146 portEXIT_CRITICAL();
1147 return;
1148 }
1149 SL_SOCKET_FD_SET(sd, &rfds);
1150 add_socket(sd);
1151 portEXIT_CRITICAL();
1152 select_wakeup();
1153}
1154
1155/*
1156 * CC32xxWiFi::fd_set_write()
1157 */
1159{
1160 portENTER_CRITICAL();
1161 if (SL_SOCKET_FD_ISSET(sd, &wfds))
1162 {
1163 /* already set */
1164 portEXIT_CRITICAL();
1165 return;
1166 }
1167 SL_SOCKET_FD_SET(sd, &wfds);
1168 add_socket(sd);
1169 portEXIT_CRITICAL();
1170 select_wakeup();
1171}
1172
1173/*
1174 * CC32xxWiFi::wlan_event_handler()
1175 */
1177{
1178 if (event == nullptr)
1179 {
1180 return;
1181 }
1182
1183 switch (event->Id)
1184 {
1185 case SL_WLAN_EVENT_CONNECT:
1186 {
1187 connected = 1;
1188 connectionFailed = 0;
1189 securityFailure = 0;
1190
1191 {
1192 /* Station mode */
1193 auto connect = &event->Data.Connect;
1194 portENTER_CRITICAL();
1195 memcpy(ssid, connect->SsidName, connect->SsidLen);
1196 ssid[connect->SsidLen] = '\0';
1197 portEXIT_CRITICAL();
1198 }
1199
1200 //
1201 // Information about the connected AP (like name, MAC etc) will be
1202 // available in 'slWlanConnectAsyncResponse_t'-Applications
1203 // can use it if required
1204 //
1205 // slWlanConnectAsyncResponse_t *event_data = NULL;
1206 // event_data = &event->EventData.STAandP2PModeWlanConnected;
1207 //
1208 break;
1209 }
1210 case SL_WLAN_EVENT_DISCONNECT:
1211 {
1212 const auto *disconnect = &event->Data.Disconnect;
1213
1214 connected = 0;
1215 ipAcquired = 0;
1216 connectionFailed = 1;
1217 ssid[0] = '\0';
1218 if (SL_WLAN_DISCONNECT_SECURITY_FAILURE == disconnect->ReasonCode)
1219 {
1220 securityFailure = 1;
1221 }
1222 else
1223 {
1224 securityFailure = 0;
1225 }
1227 {
1228 ipAcquiredCallback_(false);
1229 }
1230 break;
1231 }
1232 case SL_WLAN_EVENT_STA_ADDED:
1233 // when device is in AP mode and any client connects to device cc3xxx
1234 break;
1235 case SL_WLAN_EVENT_STA_REMOVED:
1236 // when client disconnects from device (AP)
1237 break;
1238 case SL_WLAN_EVENT_PROVISIONING_STATUS:
1239 LOG(INFO, "provisioning status %u %u %u", event->Data.ProvisioningStatus.ProvisioningStatus, event->Data.ProvisioningStatus.Role, event->Data.ProvisioningStatus.WlanStatus);
1240 // when the auto provisioning kicks in
1241 break;
1242 case SL_WLAN_EVENT_PROVISIONING_PROFILE_ADDED:
1243 LOG(INFO, "provisioning profile added %s %s", event->Data.ProvisioningProfileAdded.Ssid, event->Data.ProvisioningProfileAdded.Reserved);
1244 // when the auto provisioning created a profile
1245 break;
1246 default:
1247 HASSERT(0);
1248 break;
1249 }
1250}
1251
1252/*
1253 * CC32xxWiFi::net_app_event_handler()
1254 */
1256{
1257 if (event == nullptr)
1258 {
1259 return;
1260 }
1261
1262 switch (event->Id)
1263 {
1264 case SL_NETAPP_EVENT_DHCP_IPV4_ACQUIRE_TIMEOUT:
1265 /* DHCP acquisition still continues, this is just a warning */
1266 break;
1267 case SL_NETAPP_EVENT_IPV4_ACQUIRED:
1268 {
1269 const auto* ip_aquired = &event->Data.IpAcquiredV4;
1270 ipAddress = ip_aquired->Ip;
1271 }
1272 // fall through
1273 case SL_NETAPP_EVENT_IPV6_ACQUIRED:
1274 ipAcquired = 1;
1275
1276 //
1277 // Information about the IPv4 & IPv6 details (like IP, gateway,dns
1278 // etc) will be available in 'SlIpV4AcquiredAsync_t /
1279 // SlIpV6AcquiredAsync_t' - Applications can use it if required
1280 //
1281 // For IPv4:
1282 //
1283 // SlIpV4AcquiredAsync_t *event_data = NULL;
1284 // event_data = &event->EventData.ipAcquiredV4;
1285 //
1286 // For IPv6:
1287 //
1288 // SlIpV6AcquiredAsync_t *event_data = NULL;
1289 // event_data = &event->EventData.ipAcquiredV6;
1290 //
1292 {
1293 ipAcquiredCallback_(true);
1294 }
1295 break;
1296 case SL_NETAPP_EVENT_DHCPV4_LEASED:
1297 {
1298 ipLeased = 1;
1299
1300 //
1301 // Information about the IP-Leased details(like IP-Leased,lease-time,
1302 // mac etc) will be available in 'SlIpLeasedAsync_t' - Applications
1303 // can use it if required
1304 //
1305 // SlIpLeasedAsync_t *event_data = NULL;
1306 // event_data = &event->EventData.ipLeased;
1307 //
1308
1309 break;
1310 }
1311 case SL_NETAPP_EVENT_IP_COLLISION:
1312 break;
1313 case SL_NETAPP_EVENT_IPV4_LOST:
1314 {
1315 ipAddress = 0;
1317 {
1318 ipAcquiredCallback_(false);
1319 }
1320 break;
1321 }
1322 case SL_NETAPP_EVENT_DHCPV4_RELEASED:
1323 ipLeased = 0;
1324
1325 //
1326 // Information about the IP-Released details (like IP-address, mac
1327 // etc) will be available in 'SlIpReleasedAsync_t' - Applications
1328 // can use it if required
1329 //
1330 // SlIpReleasedAsync_t *event_data = NULL;
1331 // event_data = &event->EventData.ipReleased;
1332 //
1333
1334 break;
1335 default:
1336 HASSERT(0);
1337 break;
1338 }
1339}
1340
1341/*
1342 * CC32xxWiFi::sock_event_handler()
1343 */
1345{
1346 if (event == nullptr)
1347 {
1348 return;
1349 }
1350
1351 //
1352 // Events are not expected
1353 //
1354 switch (event->Event)
1355 {
1356 case SL_SOCKET_TX_FAILED_EVENT:
1357 LOG(ALWAYS, "Socket tx fail status %d, sd %u",
1358 (int)event->SocketAsyncEvent.SockTxFailData.Status,
1359 (unsigned)event->SocketAsyncEvent.SockTxFailData.Sd);
1360 switch (event->SocketAsyncEvent.SockTxFailData.Status)
1361 {
1362 case SL_ERROR_BSD_ECLOSE:
1363 break;
1364 default:
1365 break;
1366 }
1367 break;
1368 case SL_SOCKET_ASYNC_EVENT:
1369 LOG(ALWAYS, "Socket async event %d, sd %u type %u val %d",
1370 (int)event->SocketAsyncEvent.SockAsyncData.Type,
1371 (unsigned)event->SocketAsyncEvent.SockAsyncData.Sd,
1372 (unsigned)event->SocketAsyncEvent.SockAsyncData.Type,
1373 (int)event->SocketAsyncEvent.SockAsyncData.Val);
1374 switch (event->SocketAsyncEvent.SockAsyncData.Type)
1375 {
1376 default:
1377 break;
1378 }
1379 break;
1380 default:
1381 LOG(ALWAYS, "Socket event %d", (int)event->Event);
1382 break;
1383 }
1384}
1385
1386/*
1387 * CC32xxWiFi::trigger_event_handler()
1388 */
1390{
1391 if (!event)
1392 {
1393 return;
1394 }
1395
1396 LOG(INFO, "Socket trigger event %u %d", (unsigned)event->Event,
1397 (unsigned)event->EventData);
1398}
1399
1400/*
1401 * CC32xxWiFi::http_server_callback()
1402 */
1404 HttpServerResponse *response)
1405{
1406 if(!event || !response)
1407 {
1408 return;
1409 }
1410
1411 switch (event->Event)
1412 {
1413 case SL_NETAPP_EVENT_HTTP_TOKEN_GET:
1414 {
1415 unsigned char *ptr;
1416 ptr = response->ResponseData.TokenValue.pData;
1417 response->ResponseData.TokenValue.Len = 0;
1418 string token((const char *)event->EventData.HttpTokenName.pData,
1419 event->EventData.HttpTokenName.Len);
1420 LOG(VERBOSE, "token get %s", token.c_str());
1421 {
1422 OSMutexLock l(&lock_);
1423 for (unsigned i = 0; i < httpGetTokenCallbacks_.size(); ++i)
1424 {
1425 if (token == httpGetTokenCallbacks_[i].first)
1426 {
1427 string result = httpGetTokenCallbacks_[i].second();
1428 // clip string if required
1429 if (result.size() >= SL_NETAPP_MAX_TOKEN_VALUE_LEN)
1430 {
1431 result.resize(SL_NETAPP_MAX_TOKEN_VALUE_LEN);
1432 }
1433 memcpy(ptr, result.data(), result.size());
1434 ptr += result.size();
1435 response->ResponseData.TokenValue.Len += result.size();
1436 break;
1437 }
1438 }
1439 }
1440 break;
1441 }
1442 case SL_NETAPP_EVENT_HTTP_TOKEN_POST:
1443 {
1444 string token(
1445 (const char *)event->EventData.HttpPostData.TokenName.pData,
1446 event->EventData.HttpPostData.TokenName.Len);
1447 string val(
1448 (const char *)event->EventData.HttpPostData.TokenValue.pData,
1449 event->EventData.HttpPostData.TokenValue.Len);
1450 LOG(VERBOSE, "token post %s=%s", token.c_str(), val.c_str());
1451 break;
1452 }
1453 default:
1454 break;
1455 }
1456}
1457
1458/*
1459 * CC32xxWiFi::netapp_request_callback()
1460 */
1462 NetAppRequest *request, NetAppResponse *response)
1463{
1464 if (!request || !response || request->AppId != SL_NETAPP_HTTP_SERVER_ID)
1465 {
1466 return;
1467 }
1468
1469 string uri;
1470 uint32_t content_length = 0xFFFFFFFFu;
1471
1472 uint8_t *meta_curr = request->requestData.pMetadata;
1473 uint8_t *meta_end = meta_curr + request->requestData.MetadataLen;
1474 while (meta_curr < meta_end)
1475 {
1476 uint8_t meta_type = *meta_curr; /* meta_type is one byte */
1477 meta_curr++;
1478 uint16_t meta_len = *(_u16 *)meta_curr; /* Length is two bytes */
1479 meta_curr += 2;
1480 switch (meta_type)
1481 {
1482 case SL_NETAPP_REQUEST_METADATA_TYPE_HTTP_CONTENT_LEN:
1483 memcpy(&content_length, meta_curr, meta_len);
1484 break;
1485 case SL_NETAPP_REQUEST_METADATA_TYPE_HTTP_REQUEST_URI:
1486 uri.assign((const char *)meta_curr, meta_len);
1487 break;
1488 }
1489 meta_curr += meta_len;
1490 }
1491 // Do we have more data to come?
1492 bool has_more = request->requestData.Flags &
1493 SL_NETAPP_REQUEST_RESPONSE_FLAGS_CONTINUATION;
1494 bool found = false;
1495 switch (request->Type)
1496 {
1497 case SL_NETAPP_REQUEST_HTTP_POST:
1498 {
1499 OSMutexLock l(&lock_);
1500 for (unsigned i = 0; i < httpPostCallbacks_.size(); ++i)
1501 {
1502 if (uri == httpPostCallbacks_[i].first)
1503 {
1504 found = true;
1505 httpPostCallbacks_[i].second(request->Handle,
1506 content_length, request->requestData.pMetadata,
1507 request->requestData.MetadataLen,
1508 request->requestData.pPayload,
1509 request->requestData.PayloadLen, has_more);
1510 break;
1511 }
1512 }
1513 if (found)
1514 {
1515 break;
1516 }
1517 }
1518 // Fall through to 404.
1519 default:
1520 response->Status = SL_NETAPP_HTTP_RESPONSE_404_NOT_FOUND;
1521 response->ResponseData.pMetadata = NULL;
1522 response->ResponseData.MetadataLen = 0;
1523 response->ResponseData.pPayload = NULL;
1524 response->ResponseData.PayloadLen = 0;
1525 response->ResponseData.Flags = 0;
1526 return;
1527 }
1528}
1529
1530/*
1531 * CC32xxWiFi::get_post_data()
1532 */
1533bool CC32xxWiFi::get_post_data(uint16_t handle, void *buf, size_t *len)
1534{
1535 uint16_t ulen = *len;
1536 uint32_t flags;
1537 int ret = sl_NetAppRecv(handle, &ulen, (uint8_t *)buf, &flags);
1538 if (ret < 0 || (flags & SL_NETAPP_REQUEST_RESPONSE_FLAGS_ERROR))
1539 {
1540 *len = 0;
1541 return false;
1542 }
1543 *len = ulen;
1544 return (flags & SL_NETAPP_REQUEST_RESPONSE_FLAGS_CONTINUATION) != 0;
1545}
1546
1547/*
1548 * CC32xxWiFi::send_post_response()
1549 */
1551 uint16_t handle, uint16_t http_status, const string &redirect)
1552{
1553 // Pieces together a valid metadata structure for SimpleLink.
1554 string md;
1555 uint16_t len;
1556 if (!redirect.empty())
1557 {
1558 http_status = SL_NETAPP_HTTP_RESPONSE_302_MOVED_TEMPORARILY;
1559 }
1560 md.push_back(SL_NETAPP_REQUEST_METADATA_TYPE_STATUS);
1561 len = 2;
1562 md.append((const char *)&len, 2);
1563 md.append((const char *)&http_status, 2);
1564 if (!redirect.empty())
1565 {
1566 md.push_back(SL_NETAPP_REQUEST_METADATA_TYPE_HTTP_LOCATION);
1567 len = redirect.size();
1568 md.append((const char *)&len, 2);
1569 md += redirect;
1570 }
1571 // Now we need to move the metadata content to a buffer that is
1572 // malloc'ed. This buffer will be freed asynchronously through a callback.
1573 void *buf = malloc(md.size());
1574 memcpy(buf, md.data(), md.size());
1575
1576 uint32_t flags = SL_NETAPP_REQUEST_RESPONSE_FLAGS_METADATA;
1577 sl_NetAppSend(handle, md.size(), (uint8_t *)buf, flags);
1578}
1579
1580/*
1581 * CC32xxWiFi::fatal_error_callback()
1582 */
1584{
1585 LOG(WARNING, "Simplelink experienced a fatal error.");
1586}
1587
1588
1589static void append_num(std::string* s, uint32_t d) {
1590 char num[10];
1591 integer_to_buffer(d, num);
1592 s->append(num);
1593}
1594
1595
1596template<class NUM>
1597static void append_ver_4(std::string* s, NUM d[4]) {
1598 for (int i = 0; i < 4; ++i) {
1599 if (i) s->push_back('.');
1600 append_num(s, d[i]);
1601 }
1602}
1603
1605 std::string v;
1606 SlDeviceVersion_t ver;
1607 uint8_t config_opt = SL_DEVICE_GENERAL_VERSION;
1608 uint16_t config_len = sizeof(ver);
1609
1610 int lRetVal = sl_DeviceGet(SL_DEVICE_GENERAL, &config_opt,
1611 &config_len, (unsigned char *)(&ver));
1612 HASSERT(lRetVal == 0);
1613
1614 v.push_back('H');
1615 v += SL_DRIVER_VERSION;
1616 v += " N";
1617 append_ver_4(&v, ver.NwpVersion);
1618 v += " F";
1619 append_ver_4(&v, ver.FwVersion);
1620 v += " P";
1621 uint32_t pv[4];
1622 pv[0] = ver.PhyVersion[0];
1623 pv[1] = ver.PhyVersion[1];
1624 pv[2] = ver.PhyVersion[2];
1625 pv[3] = ver.PhyVersion[3];
1626 append_ver_4(&v, pv);
1627 v += " R";
1628 append_num(&v, ver.RomVersion);
1629 v += " C";
1630 append_num(&v, ver.ChipId);
1631 return v;
1632}
1633
1634// Override weak MDNS implementations for the CC32xx platform
1635
1636/*
1637 * mdns_publish()
1638 */
1639void mdns_publish(const char *name, const char *service, uint16_t port)
1640{
1641 string full_name(name);
1642 full_name.push_back('.');
1643 full_name.append(service);
1644 full_name.append(".local");
1645 sl_NetAppMDNSRegisterService((const signed char *)full_name.c_str(),
1646 full_name.size(), (const signed char *)"OLCB", strlen("OLCB"), port,
1647 200, SL_NETAPP_MDNS_OPTIONS_IS_NOT_PERSISTENT);
1648}
1649
1650/*
1651 * mdns_unpublish()
1652 */
1653void mdns_unpublish(const char *name, const char *service)
1654{
1655 string full_name(name);
1656 full_name.push_back('.');
1657 full_name.append(service);
1658 full_name.append(".local");
1659 sl_NetAppMDNSUnRegisterService((const signed char *)full_name.c_str(),
1660 full_name.size(), SL_NETAPP_MDNS_OPTIONS_IS_NOT_PERSISTENT);
1661}
1662
1663extern "C"
1664{
1668void SimpleLinkWlanEventHandler(SlWlanEvent_t *pSlWlanEvent)
1669{
1671 static_cast<CC32xxWiFi::WlanEvent *>(pSlWlanEvent));
1672}
1673
1678void SimpleLinkNetAppEventHandler(SlNetAppEvent_t *pNetAppEvent)
1679{
1681 static_cast<CC32xxWiFi::NetAppEvent *>(pNetAppEvent));
1682}
1683
1687void SimpleLinkGeneralEventHandler(SlDeviceEvent_t *pDevEvent)
1688{
1689 /* currently unused */
1690}
1691
1695void SimpleLinkSockEventHandler(SlSockEvent_t *pSock)
1696{
1698 static_cast<CC32xxWiFi::SockEvent *>(pSock));
1699}
1700
1707 SlNetAppHttpServerEvent_t *pHttpServerEvent,
1708 SlNetAppHttpServerResponse_t *pHttpServerResponse)
1709{
1711 static_cast<CC32xxWiFi::HttpServerEvent *>(pHttpServerEvent),
1712 static_cast<CC32xxWiFi::HttpServerResponse *>(pHttpServerResponse));
1713}
1714
1722void SimpleLinkNetAppRequestEventHandler(SlNetAppRequest_t *pNetAppRequest,
1723 SlNetAppResponse_t *pNetAppResponse)
1724{
1725 LOG(VERBOSE,
1726 "netapprq app %d type %d hdl %d mdlen %u payloadlen %u flags %u",
1727 pNetAppRequest->AppId, pNetAppRequest->Type, pNetAppRequest->Handle,
1728 pNetAppRequest->requestData.MetadataLen,
1729 pNetAppRequest->requestData.PayloadLen,
1730 (unsigned)pNetAppRequest->requestData.Flags);
1732 static_cast<CC32xxWiFi::NetAppRequest *>(pNetAppRequest),
1733 static_cast<CC32xxWiFi::NetAppResponse *>(pNetAppResponse));
1734}
1735
1744{
1745 free(buffer);
1746}
1747
1752void SimpleLinkFatalErrorEventHandler(SlDeviceFatal_t *slFatalErrorEvent)
1753{
1755 static_cast<CC32xxWiFi::FatalErrorEvent*>(slFatalErrorEvent));
1756}
1757
1762void SimpleLinkSocketTriggerEventHandler(SlSockTriggerEvent_t *event)
1763{
1765 static_cast<CC32xxWiFi::SockTriggerEvent *>(event));
1766}
1767
1768extern int slcb_SetErrno(int Errno);
1769
1775int slcb_SetErrno(int Errno)
1776{
1777 errno = Errno;
1778 return 0;
1779}
1780
1781} /* extern "C" */
void SlCheckResult(int result, int expected)
Tests that a SimpleLink request has succeeded.
void SlCheckError(int result)
Tests that a SimpleLink request has succeeded (return >= 0).
static OSEvent wakeup
event used to wakeup select calls
Definition Select.cxx:40
int bind(int socket, const struct sockaddr *address, socklen_t address_len)
Bind a name to a socket.
Definition Socket.cxx:159
int connect(int socket, const struct sockaddr *address, socklen_t address_len)
Connect a socket.
Definition Socket.cxx:208
void resetblink(uint32_t pattern)
Changes the blinking pattern.
char WIFI_SSID[]
Name of wifi accesspoint to connect to.
Definition WifiDefs.cxx:42
char WIFI_PASS[]
Password of wifi connection. If empty, use no encryption.
Definition WifiDefs.cxx:44
Socket implementation for the CC32xx class WiFi devices.
uint8_t readActive
indicates our "best guess" at current socket's read active status
static CC32xxSocket * get_instance_from_sd(int sd)
Get the CC32xxSocket instance given a specific CC32xx socket descriptor.
uint8_t writeActive
indicates our "best guess" at current socket's write active status
@ SEC_WEP
WEP security mode.
@ SEC_OPEN
open (no security)
@ SEC_WPA2
WPA2 security mode.
string http_get_ip_address()
Get the IP address for a http request.
bool wlan_profile_test_none()
Test if there are any saved profiles.
unsigned securityFailure
Disconnected due to wrong password.
void net_app_event_handler(NetAppEvent *event)
This function handles network events such as IP acquisition, IP leased, IP released etc.
void trigger_event_handler(SockTriggerEvent *event)
Notifies the service about a wifi asynchronous socket event callback.
int wlan_power_policy_set(WlanPowerPolicy wpp)
Set the power policy.
int wakeup
loopback socket to wakeup select()
void wlan_connection_policy_set(WlanConnectionPolicy policy)
Sets connection policy to auto connect.
std::vector< std::pair< const char *, PostFunction > > httpPostCallbacks_
List of callbacks for http post handlers.
void netapp_request_callback(NetAppRequest *request, NetAppResponse *response)
This function handles netapp request callbacks.
void stop()
Stops the Wi-Fi in preparation for a reboot.
void set_default_state()
Set the CC32xx to its default state, including station mode.
CC32xxWiFi()
Constructor.
std::function< void(bool)> ipAcquiredCallback_
Callback for when IP is acquired.
void wlan_setup_ap(const char *ssid, const char *security_key, SecurityType security_type) override
Setup access point role credentials.
void wlan_set_scan_params(int mask, int min_rssi)
Sets the scan parameters.
void wlan_event_handler(WlanEvent *event)
This function handles WLAN events.
void wlan_get_ap_config(string *ssid, SecurityType *security_type)
Retrieve current AP config.
unsigned started
network processor started
void wlan_mac(uint8_t mac[6])
Get the device MAC address.
int16_t rssi
receive signal strength indicator
int wlan_get_ap_station_count()
Retrieves how many stations are connected to the wifi in AP mode.
void fatal_error_callback(FatalErrorEvent *event)
This Function Handles the Fatal errors.
void wlan_set_role(WlanRole new_role)
Change the default Wlan Role.
int wlan_profile_del(const char *ssid)
Delete a saved WLAN profile.
char ssid[33]
SSID of AP, or AP we are connected to.
void fd_remove(int16_t sd)
Remove a socket from the known sockets that might be part of the sl_Select fdset.
WlanRole wlanRole
the Wi-Fi role we are in
OSMutex lock_
Protects callbacks_ vector.
void connecting_update_blinker()
Updates the blinker based on connection state.
uint32_t ipAddress
assigned IP adress
void sock_event_handler(SockEvent *event)
This function handles socket events indication.
void run_on_network_thread(std::function< void()> callback)
Executes the given function on the network thread.
unsigned connected
AP connected state.
WlanConnectionPolicy
The Wlan reconnect policy.
@ WLAN_CONNECTION_FAST_RECONNECT
Reconnect to the last connected AP.
void fd_set_read(int16_t sd)
Add socket to the read fd set.
CountryCode wlan_country_code_get()
Get the current country code.
int wlan_profile_add(const char *ssid, SecurityType sec_type, const char *key, unsigned priority)
Add a saved WLAN profile.
static SecurityType security_type_from_simplelink(uint8_t sec_type)
Translates the SimpleLink code to SecurityType enum.
void start(WlanRole role=WlanRole::STA, WlanPowerPolicy power_policy=WLAN_NO_CHANGE_POLICY, WlanConnectionPolicy connection_policy=WLAN_CONNECTION_NO_CHANGE)
Startup the Wi-Fi.
std::vector< std::function< void()> > callbacks_
List of callbacks to execute on the network thread.
int wlan_profile_get(int index, char ssid[], SecurityType *sec_type, uint32_t *priority)
Get a saved WLAN profile by index.
WlanConnectionPolicy connectionPolicy
scan or reconnect to last AP
int wlan_network_list_get(WlanNetworkEntry *entries, size_t count)
Get a list of available networks.
static uint8_t security_type_to_simplelink(SecurityType sec_type)
Translates the SecurityType enum to the internal SimpleLink code.
void fd_set_write(int16_t sd)
Add socket to the write fd set.
void wlan_task()
Thread that will manage the WLAN connection inside object context.
void http_server_callback(HttpServerEvent *event, HttpServerResponse *response)
This function handles http server callback indication.
void select_wakeup()
Asynchronously wakeup the select call.
unsigned ipAcquired
IP address aquired state.
WlanPowerPolicy wlanPowerPolicy
the desired power policy
static std::string get_version()
Returns a string contianing the version numbers of the network interface.
void wlan_rescan()
Initiate rescanning available networks.
static void * wlan_task_entry(void *context)
Thread that will manage the WLAN connection.
void test_mode_start()
Startup the Wi-Fi in test mode.
void wlan_wps_pbc_initiate()
Initiate a WPS Push Button Control connection.
WlanConnectResult wlan_connect(const char *ssid, const char *security_key, SecurityType security_type)
Connect to access point.
WlanPowerPolicy
The WLAN power policy.
@ WLAN_ALWAYS_ON_POLICY
WLAN power policy always on.
@ WLAN_NORMAL_POLICY
WLAN power policy normal.
@ WLAN_LOW_LATENCY_POLICY
WLAN power policy low latency.
@ WLAN_LOW_POWER_POLICY
WLAN power policy low power.
@ WLAN_NO_CHANGE_POLICY
WLAN power policy to be left alone.
void wlan_set_mac(uint8_t mac[6])
Sets the device MAC address.
void add_http_get_token_callback(const char *token_name, std::function< std::string()> callback)
Add an HTTP get token callback.
void send_post_respose(uint16_t handle, uint16_t http_status=204, const string &redirect="")
Sends a POST response.
int wlan_country_code_set(CountryCode cc, bool restart=false)
Set the current country code.
static SecurityType security_type_from_scan(unsigned sec_type)
Translates the SimpleLink code from the network scan to SecurityType enum.
unsigned connectionFailed
Connection attempt failed status.
std::vector< std::pair< const char *, std::function< std::string()> > > httpGetTokenCallbacks_
List of callbacks for http get tokens.
unsigned ipLeased
IP address leased to a client(AP mode)
bool get_post_data(uint16_t handle, void *buf, size_t *len)
Retrieves additional payload for http POST operations.
void wlan_disconnect()
Disconnects from the current AP.
int wlan_power_policy_get(WlanPowerPolicy *wpp)
Get the power policy.
Class to allow convenient locking and unlocking of mutexes in a C context.
Definition OS.hxx:494
static int get_priority_max()
Get the maximum thread priority.
Definition OS.hxx:132
static CC32xxWiFi * instance()
Definition Singleton.hxx:77
SelectInfo selInfoRd
select wakeup metadata for read active
Definition Socket.hxx:79
SelectInfo selInfoWr
select wakeup metadata for write active
Definition Socket.hxx:80
void str_populate(char(&dst)[N], const char *src)
Populates a character array with a C string.
#define LOG(level, message...)
Conditionally write a message to the logging output.
Definition logging.h:99
static const int VERBOSE
Loglevel that is usually not printed, reporting debugging information.
Definition logging.h:59
static const int WARNING
Loglevel that is always printed, reporting a warning or a retryable error.
Definition logging.h:55
static const int INFO
Loglevel that is printed by default, reporting some status information.
Definition logging.h:57
static const int ALWAYS
Loglevel that is always printed.
Definition logging.h:49
#define HASSERT(x)
Checks that the value of expression x is true, else terminates the current process.
Definition macros.h:138
#define DIE(MSG)
Unconditionally terminates the current process with a message.
Definition macros.h:143
static int fdHighest
the highest file descriptor to select on
void SimpleLinkSocketTriggerEventHandler(SlSockTriggerEvent_t *event)
Notifies the service about a wifi asynchronous socket event callback.
void SimpleLinkNetAppRequestEventHandler(SlNetAppRequest_t *pNetAppRequest, SlNetAppResponse_t *pNetAppResponse)
This function handles resource request.
void mdns_publish(const char *name, const char *service, uint16_t port)
Publish an mDNS name.
void mdns_unpublish(const char *name, const char *service)
Unpublish an mDNS name.
void new_highest()
Find the new highest fd to select on.
void SimpleLinkHttpServerEventHandler(SlNetAppHttpServerEvent_t *pHttpServerEvent, SlNetAppHttpServerResponse_t *pHttpServerResponse)
This function gets triggered when HTTP Server receives Application defined GET and POST HTTP Tokens.
static int16_t slSockets[SL_MAX_SOCKETS]
This is not a class members so that including CC32xxWiFi.hxx does not pollute the namespace with simp...
void SimpleLinkNetAppRequestMemFreeEventHandler(uint8_t *buffer)
This function handles resource release.
void SimpleLinkFatalErrorEventHandler(SlDeviceFatal_t *slFatalErrorEvent)
This Function Handles the Fatal errors.
void SimpleLinkSockEventHandler(SlSockEvent_t *pSock)
This function handles socket events indication.
void add_socket(int16_t sd)
Add an interesting socket.
void del_socket(int16_t sd)
Delete an interesting socket.
void SimpleLinkWlanEventHandler(SlWlanEvent_t *pSlWlanEvent)
This function handles WLAN events.
void SimpleLinkGeneralEventHandler(SlDeviceEvent_t *pDevEvent)
This function handles general events.
int slcb_SetErrno(int Errno)
Helper function called by SimpleLink driver to set OS-specific errno value.
static SlFdSet_t wfds
This is not a class members so that including CC32xxWiFi.hxx does not pollute the namespace with simp...
static SlFdSet_t efds
This is not a class members so that including CC32xxWiFi.hxx does not pollute the namespace with simp...
void SimpleLinkNetAppEventHandler(SlNetAppEvent_t *pNetAppEvent)
This function handles network events such as IP acquisition, IP leased, IP released etc.
static SlFdSet_t rfds
This is not a class members so that including CC32xxWiFi.hxx does not pollute the namespace with simp...
long long os_get_time_monotonic(void)
Get the monotonic time since the system started.
Definition os.c:571
int os_thread_create(os_thread_t *thread, const char *name, int priority, size_t stack_size, void *(*start_routine)(void *), void *arg)
Create a thread.
Definition os.c:450
OS_INLINE int os_thread_get_priority_max(void)
Get the maximum thread priority.
Definition os.h:416
#define MSEC_TO_USEC(_msec)
Convert a millisecond value to a microsecond value.
Definition os.h:274
CC32xx forward declaration Helper.
CC32xx forward declaration Helper.
CC32xx forward declaration Helper.
CC32xx forward declaration Helper.
CC32xx forward declaration Helper.
CC32xx forward declaration Helper.
CC32xx forward declaration Helper.
CC32xx forward declaration Helper.
CC32xx forward declaration Helper.
metadata for a WLAN netowrk entry.
int rssi
receive signal strength indicator of the AP
SecurityType sec_type
security type of the AP
static void select_wakeup(SelectInfo *info)
Wakeup the list of clients needing woken.
Definition Select.cxx:210