Skip to content

Commit f195ed0

Browse files
authored
Merge pull request #2805 from particle-iot/fix/gen4-wifi-stab
[Gen 4] WiFi stuff
2 parents 0850b82 + 6d886ea commit f195ed0

File tree

3 files changed

+127
-21
lines changed

3 files changed

+127
-21
lines changed

hal/network/ncp_client/realtek/rtl_ncp_client.cpp

+82-2
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ extern "C" {
5656
#include "bt_intf.h"
5757

5858
extern "C" void rtw_efuse_boot_write(void);
59+
extern "C" uint32_t rltk_wlan_get_link_err(void);
5960

6061
void wifi_set_country_code(void) {
6162
uint8_t channel_plan;
@@ -300,6 +301,84 @@ NcpConnectionState RealtekNcpClient::connectionState() {
300301
return connState_;
301302
}
302303

304+
void RealtekNcpClient::parseDisconnectReason(char* buf, size_t bufLen) {
305+
uint16_t reason = 0;
306+
if (buf) {
307+
reason = *(uint16_t*)(buf + 6 /* skip MAC */);
308+
}
309+
uint32_t linkErr = rltk_wlan_get_link_err();
310+
311+
const char* msg = "";
312+
const char* extraMsg = "";
313+
const char* reasonMsg = "";
314+
315+
// From wifi_link_err_parse()
316+
if(linkErr & BIT(0)) {
317+
msg = "received deauth";
318+
} else if(linkErr & BIT(1)) {
319+
msg = "received deassoc";
320+
} else if (linkErr & BIT(2)) {
321+
msg = "scan stage, no beacon while connecting";
322+
} else if(linkErr & BIT(3)) {
323+
msg = "auth stage, auth timeout";
324+
if (reason == 65531) {
325+
extraMsg = "request has been declined";
326+
}
327+
} else if(linkErr & BIT(4)) {
328+
msg = "assoc stage, assoc timeout";
329+
} else if(linkErr & (BIT(5) | BIT(6) | BIT(7))) {
330+
msg = "4handshake stage, 4-way waiting timeout";
331+
} else if(linkErr & BIT(8)) {
332+
msg = "assoc stage, assoc reject (assoc rsp status > 0)";
333+
} else if(linkErr & BIT(9)) {
334+
msg = "auth stage, auth fail (auth rsp status > 0)";
335+
} else if(linkErr & BIT(10)){
336+
msg = "scan stage, scan timeout";
337+
} else if(linkErr & BIT(11)) {
338+
msg = "auth stage, WPA3 auth fail";
339+
if (reason == 65531) {
340+
extraMsg = "request has been declined";
341+
} else {
342+
extraMsg = "password error";
343+
}
344+
}
345+
346+
if(linkErr & (BIT(0) | BIT(1))) {
347+
if(linkErr & BIT(20)) {
348+
msg = "handshake done, connected stage, recv deauth/deassoc";
349+
} else if(linkErr & BIT(19)) {
350+
msg = "handshake processing, 4handshake stage, recv deauth/deassoc";
351+
} else if(linkErr & BIT(18)) {
352+
msg = "assoc successed, 4handshake stage, recv deauth/deassoc";
353+
} else if(linkErr & BIT(17)) {
354+
msg = "auth successed, assoc stage, recv deauth/deassoc";
355+
} else if(linkErr & BIT(16)) {
356+
msg = "scan done, found ssid, auth stage, recv deauth/deassoc";
357+
} else {
358+
msg = "connected stage, recv deauth/deassoc";
359+
}
360+
}
361+
362+
switch(reason) {
363+
case 17:
364+
reasonMsg = "auth stage, ap auth full";
365+
break;
366+
case 65530:
367+
reasonMsg = "SA query timeout";
368+
break;
369+
case 65534:
370+
reasonMsg = "connected stage, ap changed";
371+
break;
372+
case 65535:
373+
reasonMsg = "connected stage, loss beacon";
374+
break;
375+
default:
376+
break;
377+
}
378+
379+
LOG(WARN, "Disconnect linkError=%08x reason=%04x: %s %s %s", linkErr, reason, msg, extraMsg, reasonMsg);
380+
}
381+
303382
int RealtekNcpClient::connect(const char* ssid, const MacAddress& bssid, WifiSecurity sec, const WifiCredentials& cred) {
304383
CHECK_FALSE(needsReset_, SYSTEM_ERROR_BUSY);
305384
int rtlError = RTW_ERROR;
@@ -310,12 +389,13 @@ int RealtekNcpClient::connect(const char* ssid, const MacAddress& bssid, WifiSec
310389

311390
connectionState(NcpConnectionState::CONNECTING);
312391

313-
wifi_reg_event_handler(WIFI_EVENT_DISCONNECT, [](char* buf, int buf_len, int flags, void* userdata) -> void {
392+
wifi_reg_event_handler(WIFI_EVENT_DISCONNECT, [](char* buf, int bufLen, int flags, void* userdata) -> void {
314393
RealtekNcpClient* client = (RealtekNcpClient*)userdata;
315394
if (client->connectionState() == NcpConnectionState::CONNECTED) {
316395
LOG(TRACE, "Disconnected");
317396
client->connectionState(NcpConnectionState::DISCONNECTED);
318397
}
398+
client->parseDisconnectReason(buf, (size_t)bufLen);
319399
}, (void*)this);
320400

321401
LOG(INFO, "Try to connect to ssid: %s", ssid);
@@ -357,7 +437,7 @@ int RealtekNcpClient::getNetworkInfo(WifiNetworkInfo* info) {
357437
info->channel(channel_num);
358438
}
359439

360-
char ssid_buf[33] = {};//32 octets for SSID, plus null terminator
440+
char ssid_buf[33] = {};//32 octets for SSID, plus null terminator
361441
rtlError = wext_get_ssid(WLAN0_NAME, (unsigned char *) ssid_buf);
362442
if (rtlError < 0) {
363443
LOG(WARN, "wext_get_ssid err: %d", rtlError);

hal/network/ncp_client/realtek/rtl_ncp_client.h

+1
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ class RealtekNcpClient: public WifiNcpClient {
8181

8282
int rltkOn();
8383
int rltkOff();
84+
void parseDisconnectReason(char* buf, size_t bufLen);
8485
};
8586

8687
inline void RealtekNcpClient::lock() {

hal/src/rtl872x/ble_hal.cpp

+44-19
Original file line numberDiff line numberDiff line change
@@ -437,19 +437,14 @@ class BleGap {
437437
CHECK_TRUE(cmdQueue_, SYSTEM_ERROR_INVALID_STATE);
438438
if (os_queue_put(cmdQueue_, &cmd, BLE_ENQUEUE_TIMEOUT_MS, nullptr)) {
439439
LOG(ERROR, "os_queue_put() failed.");
440-
SPARK_ASSERT(false);
440+
if (cmd != BLE_CMD_EXIT_THREAD) {
441+
SPARK_ASSERT(false);
442+
}
443+
return SYSTEM_ERROR_TIMEOUT;
441444
}
442445
return SYSTEM_ERROR_NONE;
443446
}
444447

445-
bool isQueueAvailable() const {
446-
uint8_t command;
447-
if (!os_queue_peek(cmdQueue_, &command, 0, nullptr)) {
448-
return true;
449-
}
450-
return false;
451-
}
452-
453448
void lockMode(bool lock) {
454449
bleInLockedMode_ = lock;
455450
}
@@ -676,6 +671,9 @@ class BleGap {
676671
static constexpr uint8_t BLE_CMD_THREAD_PRIORITY = OS_THREAD_PRIORITY_NETWORK - 1; // IMPORTANT: below network for coexistence to work!
677672
static constexpr uint16_t BLE_CMD_THREAD_STACK_SIZE = 2048;
678673
static constexpr uint8_t BLE_CMD_QUEUE_SIZE = 0x20;
674+
675+
volatile bool bleCommandThreadExit_ = false;
676+
static constexpr system_tick_t BLE_WAIT_CMD_THREAD_TRY_LOCK = 10;
679677
};
680678

681679

@@ -1020,14 +1018,27 @@ void BleEventDispatcher::bleEventDispatchThread(void *context) {
10201018

10211019
void BleGap::bleCommandThread(void *context) {
10221020
BleGap* gap = (BleGap*)context;
1021+
uint8_t command = 0;
10231022
while (true) {
1024-
uint8_t command;
1023+
bool locked = false;
10251024
if (!os_queue_peek(gap->cmdQueue_, &command, CONCURRENT_WAIT_FOREVER, nullptr)) {
10261025
LOCAL_DEBUG("---> Enter ble cmd thread, cmd: %d", command);
10271026
if (command == BLE_CMD_STOP_ADV || command == BLE_CMD_STOP_ADV_NOTIFY) {
10281027
if (gap->isAdvertising()) {
10291028
LOCAL_DEBUG( "stopAdvertising in ble cmd thread");
1030-
BleLock lk;
1029+
// FIXME: duplication, but for now works as a workaround
1030+
while (!(locked = s_bleMutex.lock(BLE_WAIT_CMD_THREAD_TRY_LOCK)) && !gap->bleCommandThreadExit_) {
1031+
// Nothing
1032+
}
1033+
SCOPE_GUARD({
1034+
if (locked) {
1035+
s_bleMutex.unlock();
1036+
}
1037+
});
1038+
if (gap->bleCommandThreadExit_) {
1039+
LOCAL_DEBUG("Exit ble cmd thread");
1040+
break;
1041+
}
10311042
gap->stopAdvertising();
10321043
LOCAL_DEBUG("notifyAdvStop in ble cmd thread");
10331044
if (command == BLE_CMD_STOP_ADV_NOTIFY) {
@@ -1036,7 +1047,19 @@ void BleGap::bleCommandThread(void *context) {
10361047
}
10371048
} else if (command == BLE_CMD_START_ADV) {
10381049
LOCAL_DEBUG("startAdvertising in ble cmd thread");
1039-
BleLock lk;
1050+
// FIXME: duplication, but for now works as a workaround
1051+
while (!(locked = s_bleMutex.lock(BLE_WAIT_CMD_THREAD_TRY_LOCK)) && !gap->bleCommandThreadExit_) {
1052+
// Nothing
1053+
}
1054+
SCOPE_GUARD({
1055+
if (locked) {
1056+
s_bleMutex.unlock();
1057+
}
1058+
});
1059+
if (gap->bleCommandThreadExit_) {
1060+
LOCAL_DEBUG("Exit ble cmd thread");
1061+
break;
1062+
}
10401063
gap->startAdvertising();
10411064
} else if (command == BLE_CMD_EXIT_THREAD) {
10421065
LOCAL_DEBUG("Exit ble cmd thread");
@@ -1046,6 +1069,8 @@ void BleGap::bleCommandThread(void *context) {
10461069
os_queue_take(gap->cmdQueue_, &command, 0, nullptr);
10471070
}
10481071
}
1072+
// Just in case clean up the queue on exit
1073+
while (!os_queue_take(gap->cmdQueue_, &command, 0, nullptr));
10491074
os_thread_exit(nullptr);
10501075
}
10511076

@@ -1181,14 +1206,14 @@ int BleGap::stop(bool restore) {
11811206
if (btStackStarted_) {
11821207
// Abort any commands, e.g. the re-adv command after disconnection.
11831208
if (cmdThread_ && !os_thread_is_current(cmdThread_)) {
1184-
if (isQueueAvailable()) {
1185-
LOCAL_DEBUG(" >>>>>>>>>>>> s_bleMutex.unlock() <<<<<<<<<<<<<<");
1186-
s_bleMutex.unlock();
1187-
}
1188-
if (enqueue(BLE_CMD_EXIT_THREAD) == SYSTEM_ERROR_NONE) {
1189-
os_thread_join(cmdThread_);
1190-
cmdThread_ = nullptr;
1209+
bleCommandThreadExit_ = true;
1210+
// It's fine even if this call below fails, but just in case loop here
1211+
while (enqueue(BLE_CMD_EXIT_THREAD)) {
1212+
// Nothing
11911213
}
1214+
os_thread_join(cmdThread_);
1215+
cmdThread_ = nullptr;
1216+
bleCommandThreadExit_ = false;
11921217
}
11931218
if (cmdQueue_) {
11941219
if (!cmdThread_) {

0 commit comments

Comments
 (0)