-
Notifications
You must be signed in to change notification settings - Fork 30
Expand file tree
/
Copy pathWifiInterface.cpp
More file actions
191 lines (157 loc) · 6.75 KB
/
WifiInterface.cpp
File metadata and controls
191 lines (157 loc) · 6.75 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
/*
*
* Copyright (c) 2022 Project CHIP Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <app/icd/server/ICDServerConfig.h>
#include <lib/support/CHIPMem.h>
#include <lib/support/CodeUtils.h>
#include <lib/support/TypeTraits.h>
#include <lib/support/logging/CHIPLogging.h>
#include <platform/silabs/wifi/WifiInterface.h>
#if CHIP_CONFIG_ENABLE_ICD_SERVER
#include <platform/silabs/wifi/icd/WifiSleepManager.h> // nogncheck
#endif // CHIP_CONFIG_ENABLE_ICD_SERVER
using namespace chip;
using namespace chip::DeviceLayer;
// TODO: We shouldn't need to have access to a global variable in the interface here
extern WfxRsi_t wfx_rsi;
// TODO: This is a workaround because we depend on the platform lib which depends on the platform implementation.
// As such we can't depend on the platform here as well
extern void HandleWFXSystemEvent(sl_wfx_generic_message_t * eventData);
namespace {
constexpr uint8_t kWlanMinRetryIntervalsInSec = 1;
constexpr uint8_t kWlanMaxRetryIntervalsInSec = 60;
uint8_t retryInterval = kWlanMinRetryIntervalsInSec;
/**
* @brief Retry timer callback that triggers a reconnection attempt.
* @param arg Pointer to bool (quickJoin) written by ScheduleConnectionAttempt when the timer was started.
*/
void RetryConnectionTimerHandler(void * arg)
{
bool quickJoin = *static_cast<bool *>(arg);
chip::DeviceLayer::Silabs::WifiInterface & wifi = chip::DeviceLayer::Silabs::WifiInterface::GetInstance();
CHIP_ERROR err = quickJoin ? wifi.QuickJoinToAccessPoint() : wifi.ConnectToAccessPoint();
if (err != CHIP_NO_ERROR)
{
ChipLogError(DeviceLayer, "Connection attempt failed.");
}
}
} // namespace
namespace chip {
namespace DeviceLayer {
namespace Silabs {
void WifiInterface::NotifyIPv6Change(bool gotIPv6Addr)
{
mHasNotifiedIPv6 = gotIPv6Addr;
sl_wfx_generic_message_t eventData = {};
eventData.header.id = gotIPv6Addr ? to_underlying(WifiEvent::kGotIPv6) : to_underlying(WifiEvent::kLostIP);
eventData.header.length = sizeof(eventData.header);
HandleWFXSystemEvent(&eventData);
}
#if (CHIP_DEVICE_CONFIG_ENABLE_IPV4)
void WifiInterface::NotifyIPv4Change(bool gotIPv4Addr)
{
mHasNotifiedIPv4 = gotIPv4Addr;
sl_wfx_generic_message_t eventData;
memset(&eventData, 0, sizeof(eventData));
eventData.header.id = gotIPv4Addr ? to_underlying(WifiEvent::kGotIPv4) : to_underlying(WifiEvent::kLostIP);
eventData.header.length = sizeof(eventData.header);
HandleWFXSystemEvent(&eventData);
}
#endif // CHIP_DEVICE_CONFIG_ENABLE_IPV4
void WifiInterface::NotifyDisconnection(WifiDisconnectionReasons reason)
{
sl_wfx_disconnect_ind_t evt = {};
evt.header.id = to_underlying(WifiEvent::kDisconnect);
evt.header.length = sizeof evt;
evt.body.reason = to_underlying(reason);
HandleWFXSystemEvent((sl_wfx_generic_message_t *) &evt);
}
void WifiInterface::NotifyConnection(const MacAddress & ap)
{
sl_wfx_connect_ind_t evt = {};
evt.header.id = to_underlying(WifiEvent::kConnect);
evt.header.length = sizeof evt;
#ifdef SL_MATTER_SIWX_WIFI_ENABLE
evt.body.channel = wfx_rsi.ap_chan;
#endif
std::copy(ap.begin(), ap.end(), evt.body.mac);
// Resetting the retry connection state machine for a successful connection
// NOTE: This is required in case an access point gets disconnected after a successful connection.
ResetConnectionRetryInterval();
HandleWFXSystemEvent((sl_wfx_generic_message_t *) &evt);
}
void WifiInterface::ResetIPNotificationStates()
{
mHasNotifiedIPv6 = false;
#if (CHIP_DEVICE_CONFIG_ENABLE_IPV4)
mHasNotifiedIPv4 = false;
#endif // CHIP_DEVICE_CONFIG_ENABLE_IPV4
}
void WifiInterface::NotifyWifiTaskInitialized(void)
{
sl_wfx_startup_ind_t evt = { 0 };
// TODO: We should move this to the init function and not the notification function
// Creating a timer which will be used to retry connection with AP (arg points to mRetryTimerQuickJoin, set in ScheduleConnectionAttempt).
mRetryTimer = osTimerNew(RetryConnectionTimerHandler, osTimerOnce, &mRetryTimerQuickJoin, NULL);
VerifyOrReturn(mRetryTimer != NULL);
evt.header.id = to_underlying(WifiEvent::kStartUp);
evt.header.length = sizeof evt;
evt.body.status = 0;
// TODO : Remove workwound when sl_wfx_startup_ind_t is unified
// Issue is same structure name but different contents
#if WF200_WIFI
MutableByteSpan macSpan(evt.body.mac_addr[SL_WFX_STA_INTERFACE], kWifiMacAddressLength);
#else
MutableByteSpan macSpan(evt.body.mac_addr, kWifiMacAddressLength);
#endif // WF200_WIFI
TEMPORARY_RETURN_IGNORED GetMacAddress(SL_WFX_STA_INTERFACE, macSpan);
HandleWFXSystemEvent((sl_wfx_generic_message_t *) &evt);
}
// TODO: The retry stategy needs to be re-worked
void WifiInterface::ScheduleConnectionAttempt(bool quickJoin)
{
mRetryTimerQuickJoin = quickJoin;
if (retryInterval > kWlanMaxRetryIntervalsInSec)
{
retryInterval = kWlanMaxRetryIntervalsInSec;
}
if (osTimerStart(mRetryTimer, pdMS_TO_TICKS(retryInterval * 1000)) != osOK)
{
ChipLogProgress(DeviceLayer, "Failed to start retry timer");
if (ConnectToAccessPoint() != CHIP_NO_ERROR)
{
ChipLogError(DeviceLayer, "ConnectToAccessPoint() failed.");
}
#if CHIP_CONFIG_ENABLE_ICD_SERVER
// Remove High performance request before giving up due to a timer start error to save battery life
TEMPORARY_RETURN_IGNORED Silabs::WifiSleepManager::GetInstance().RemoveHighPerformanceRequest();
#endif // CHIP_CONFIG_ENABLE_ICD_SERVER
return;
}
#if CHIP_CONFIG_ENABLE_ICD_SERVER
TEMPORARY_RETURN_IGNORED Silabs::WifiSleepManager::GetInstance().RemoveHighPerformanceRequest();
#endif // CHIP_CONFIG_ENABLE_ICD_SERVER
ChipLogProgress(DeviceLayer, "ScheduleConnectionAttempt : Next attempt after %d Seconds", retryInterval);
retryInterval += retryInterval;
}
void WifiInterface::ResetConnectionRetryInterval()
{
ChipLogDetail(DeviceLayer, "ResetConnectionRetryInterval: Resetting state to default");
retryInterval = kWlanMinRetryIntervalsInSec;
}
} // namespace Silabs
} // namespace DeviceLayer
} // namespace chip