Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

RTL872x-based platforms: supports BLE GATT client, BLE central role and pairing APIs #2542

Merged
merged 21 commits into from
Sep 29, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
2958a65
[rtl872x] hal: makes BLE connections extendable.
XuGuohui Aug 24, 2022
34b7832
[rtl872x] hal: implement APIs for getting/setting BLE PPCP.
XuGuohui Aug 25, 2022
344ea64
[rtl872x] hal: implements connection related APIs.
XuGuohui Aug 25, 2022
cec451f
[rtl872x] hal: implement GATT client related APIs.
XuGuohui Sep 1, 2022
ab300c1
[rtl872x] hal: fix the issue that BLE GATT server indication may lose…
XuGuohui Sep 3, 2022
fd8748b
[rtl872x] hal: implement BLE pairing APIs
XuGuohui Sep 7, 2022
161e0eb
[rtl872x] hal: give BLE connection semaphore only when MTU is updated
XuGuohui Sep 8, 2022
2be8a0a
[rtl872x] ble: add comments
XuGuohui Sep 8, 2022
70da17c
[rtl872x] hal: BLE peripheral and broadcaster concurrent roles.
XuGuohui Sep 19, 2022
7393c8d
[rtl872x] BLE: fixes some race conditions and makes some improvements.
XuGuohui Sep 23, 2022
38d50f3
[rtl872x] ble: coexistence workaround, minor LESC stuff
avtolstoy Sep 27, 2022
12957a9
[rtl872x] ble: minor LESC_ONLY fix
avtolstoy Sep 27, 2022
d6c7949
[rtl872x] fix BLE race conditions.
XuGuohui Sep 28, 2022
2e55fed
[test] enable tests of setting BLE address for P2.
XuGuohui Sep 28, 2022
cacabb3
[rtl872x] timer thread should have max priority otherwise its queue w…
avtolstoy Sep 28, 2022
4466bd8
[rtl872x] ble: fix race condition with GAP_MSG_LE_CONN_STATE_CHANGE g…
avtolstoy Sep 28, 2022
2472a56
[rtl872x] ble: thread safety for connections_ array
avtolstoy Sep 28, 2022
7bc980d
[test] wiring/ble_central_peripheral/ble_central: delay when switchin…
avtolstoy Sep 29, 2022
0b37089
[rtl872x] introduce a new SDK API to get pairing procedure type.
XuGuohui Sep 29, 2022
2fb6d65
Set size to get ppcp params
keeramis Sep 29, 2022
a002f91
[rtl872x] ble: workaround for a BT stack race condition
avtolstoy Sep 29, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions hal/inc/hal_platform.h
Original file line number Diff line number Diff line change
Expand Up @@ -526,4 +526,8 @@
#define HAL_PLATFORM_CELLULAR_MODEM_VOLTAGE_TRANSLATOR (1)
#endif // HAL_PLATFORM_CELLULAR_MODEM_VOLTAGE_TRANSLATOR

#ifndef HAL_PLATFORM_BLE_ACTIVE_EVENT
#define HAL_PLATFORM_BLE_ACTIVE_EVENT (0)
#endif // HAL_PLATFORM_BLE_ACTIVE_EVENT

#endif /* HAL_PLATFORM_H */
10 changes: 2 additions & 8 deletions hal/src/nRF52840/ble_hal.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -647,7 +647,6 @@ class BleObject::GattClient {
hal_ble_char_t* findDiscoveredCharacteristic(hal_ble_attr_handle_t attrHandle);
int addPublisher(hal_ble_conn_handle_t connHandle, hal_ble_attr_handle_t valueHandle, hal_ble_on_char_evt_cb_t callback, void* context);
int removePublisher(hal_ble_conn_handle_t connHandle, hal_ble_attr_handle_t valueHandle);
int configRemoteCharCCCD(const hal_ble_cccd_config_t* config);
static void processGattClientEvents(const ble_evt_t* event, void* context);
static void onAttMtuExchangeTimerExpired(os_timer_t timer);

Expand Down Expand Up @@ -1806,13 +1805,7 @@ bool BleObject::ConnectionsManager::connecting(const hal_ble_addr_t* address) co

bool BleObject::ConnectionsManager::connected(const hal_ble_addr_t* address) {
if (address == nullptr) {
// Check if local device is connected as BLE Peripheral.
for (const auto& connection : connections_) {
if (connection.info.role == BLE_ROLE_PERIPHERAL) {
return true;
}
}
return false;
return connections_.size() > 0;
}
if (fetchConnection(address)) {
return true;
Expand Down Expand Up @@ -3149,6 +3142,7 @@ int BleObject::GattClient::discoverServices(hal_ble_conn_handle_t connHandle, co
int BleObject::GattClient::discoverCharacteristics(hal_ble_conn_handle_t connHandle, const hal_ble_svc_t* service, hal_ble_on_disc_char_cb_t callback, void* context) {
CHECK_TRUE(BleObject::getInstance().connMgr()->valid(connHandle), SYSTEM_ERROR_NOT_FOUND);
CHECK_FALSE(isDiscovering_, SYSTEM_ERROR_INVALID_STATE);
CHECK_TRUE(service, SYSTEM_ERROR_INVALID_ARGUMENT);
SCOPE_GUARD ({
resetDiscoveryState();
});
Expand Down
1,611 changes: 1,449 additions & 162 deletions hal/src/rtl872x/ble_hal.cpp

Large diffs are not rendered by default.

5 changes: 1 addition & 4 deletions hal/src/rtl872x/freertos/FreeRTOSConfig.h
Original file line number Diff line number Diff line change
Expand Up @@ -136,10 +136,7 @@ extern void newlib_impure_ptr_change(struct _reent* r);

/* Software timer definitions. */
#define configUSE_TIMERS 1
#define configTIMER_TASK_PRIORITY 2
// #define configTIMER_QUEUE_LENGTH ( 10 + 32 )
// #define configTIMER_TASK_STACK_DEPTH ( 512 )
// #define configTIMER_TASK_PRIORITY ( configMAX_PRIORITIES - 1 )
#define configTIMER_TASK_PRIORITY ( configMAX_PRIORITIES - 1 )
#define configTIMER_QUEUE_LENGTH ( 64 )
#define configTIMER_TASK_STACK_DEPTH ( ( unsigned short ) (4096 / sizeof( portSTACK_TYPE )) )

Expand Down
2 changes: 2 additions & 0 deletions hal/src/rtl872x/hal_platform_rtl8721x_config.h
Original file line number Diff line number Diff line change
Expand Up @@ -128,3 +128,5 @@
#define HAL_PLATFORM_MODULE_SUFFIX_EXTENSIONS (1)

#define HAL_PLATFORM_POWER_MANAGEMENT_STACK_SIZE (1536)

#define HAL_PLATFORM_BLE_ACTIVE_EVENT (1)
1 change: 1 addition & 0 deletions system/src/ble_provisioning_mode_handler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,7 @@ int BleProvisioningModeHandler::cacheUserConfigurations() {
preAdvParams_.size = sizeof(hal_ble_adv_params_t);
CHECK(hal_ble_gap_get_advertising_parameters(&preAdvParams_, nullptr));
CHECK(hal_ble_gap_get_tx_power(&preTxPower_, nullptr));
prePpcp_.size = sizeof(hal_ble_conn_params_t);
CHECK(hal_ble_gap_get_ppcp(&prePpcp_, nullptr));
CHECK(hal_ble_gap_get_auto_advertise(&preAutoAdv_, nullptr));

Expand Down
1 change: 1 addition & 0 deletions third_party/ambd_sdk/include.mk
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ INCLUDE_DIRS += $(TARGET_AMBD_SDK_COMMON_PATH)/drivers/usb/device_new/core
INCLUDE_DIRS += $(TARGET_AMBD_SDK_COMMON_PATH)/drivers/usb/common_new

# Hack of the century!
LIBS_EXT_END += -Wl,--wrap=bt_coex_handle_specific_evt
LIBS_EXT_END += $(TARGET_AMBD_SDK_PROJECT_LIB_PATH)/lib_wlan.a
LIBS_EXT_END += $(TARGET_AMBD_SDK_PROJECT_LIB_PATH)/lib_wps.a
ifneq ("$(MODULE)", "user-part")
Expand Down
179 changes: 95 additions & 84 deletions user/tests/wiring/ble_central_peripheral/ble_central/central.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -342,100 +342,103 @@ const char* ioCapsStr[5] = {

static void pairingTestRoutine(bool request, BlePairingAlgorithm algorithm,
BlePairingIoCaps ours = BlePairingIoCaps::NONE, BlePairingIoCaps theirs = BlePairingIoCaps::NONE) {
peer = BLE.connect(peerAddr, false);
assertTrue(peer.connected());
{
SCOPE_GUARD ({
delay(500);
assertEqual(BLE.disconnect(peer), (int)SYSTEM_ERROR_NONE);
assertFalse(BLE.connected());
delay(500);
});

pairingStatus = -1;
pairingRequested = false;
BLE.onPairingEvent([&](const BlePairingEvent& event) {
if (event.type == BlePairingEventType::REQUEST_RECEIVED) {
Serial.println("Request received");
pairingRequested = true;
} else if (event.type == BlePairingEventType::STATUS_UPDATED) {
pairingStatus = event.payload.status.status;
lesc = event.payload.status.lesc;
Serial.println("status updated");
} else if (event.type == BlePairingEventType::PASSKEY_DISPLAY || event.type == BlePairingEventType::NUMERIC_COMPARISON) {
Serial.print("Passkey display: ");
for (uint8_t i = 0; i < BLE_PAIRING_PASSKEY_LEN; i++) {
Serial.printf("%c", event.payload.passkey[i]);
}
Serial.println("");
#if !defined(PARTICLE_TEST_RUNNER)
if (event.type == BlePairingEventType::NUMERIC_COMPARISON) {
while (Serial.available()) {
Serial.read();
}
Serial.print("Please confirm if the passkey is identical (y/n): ");
while (!Serial.available());
char c = Serial.read();
Serial.write(c);
Serial.println("");
BLE.setPairingNumericComparison(event.peer, (c == 'y') ? true : false);
}
#else
assertTrue(publishPassKey((const char*)event.payload.passkey, event.payloadLen));
if (event.type == BlePairingEventType::NUMERIC_COMPARISON) {
String peerPassKey;
for (auto t = millis(); millis() - t < 60000;) {
if (getBleTestPasskey(peerPassKey)) {
break;
}
delay(50);
}
assertNotEqual(String(), peerPassKey);
BLE.setPairingNumericComparison(event.peer, peerPassKey == String((const char*)event.payload.passkey, event.payloadLen));
}
#endif // PARTICLE_TEST_RUNNER
} else if (event.type == BlePairingEventType::PASSKEY_INPUT) {
pairingStatus = -1;
pairingRequested = false;
BLE.onPairingEvent([&](const BlePairingEvent& event) {
if (event.type == BlePairingEventType::REQUEST_RECEIVED) {
Serial.println("Request received");
pairingRequested = true;
} else if (event.type == BlePairingEventType::STATUS_UPDATED) {
pairingStatus = event.payload.status.status;
lesc = event.payload.status.lesc;
Serial.printlnf("status updated, %d", event.payload.status.status);
} else if (event.type == BlePairingEventType::PASSKEY_DISPLAY || event.type == BlePairingEventType::NUMERIC_COMPARISON) {
Serial.print("Passkey display: ");
for (uint8_t i = 0; i < BLE_PAIRING_PASSKEY_LEN; i++) {
Serial.printf("%c", event.payload.passkey[i]);
}
Serial.println("");
#if !defined(PARTICLE_TEST_RUNNER)
if (event.type == BlePairingEventType::NUMERIC_COMPARISON) {
while (Serial.available()) {
Serial.read();
}
Serial.print("Passkey input (must be identical to the peer's): ");
uint8_t i = 0;
uint8_t passkey[BLE_PAIRING_PASSKEY_LEN];
while (i < BLE_PAIRING_PASSKEY_LEN) {
if (Serial.available()) {
passkey[i] = Serial.read();
Serial.write(passkey[i++]);
}
}
Serial.print("Please confirm if the passkey is identical (y/n): ");
while (!Serial.available());
char c = Serial.read();
Serial.write(c);
Serial.println("");
BLE.setPairingPasskey(event.peer, passkey);
BLE.setPairingNumericComparison(event.peer, (c == 'y') ? true : false);
}
#else
Serial.printlnf("passkey input");
assertTrue(publishPassKey((const char*)event.payload.passkey, event.payloadLen));
if (event.type == BlePairingEventType::NUMERIC_COMPARISON) {
String peerPassKey;
// Special case where both ends have KEYBOARD_ONLY capabilities:
// Generate random passkey, the side that is the requester will publish it
if (ours == theirs && ours == BlePairingIoCaps::KEYBOARD_ONLY && request) {
Random rand;
char passkey[BLE_PAIRING_PASSKEY_LEN + 1] = {};
const char dict[] = "0123456789";
rand.genAlpha(passkey, BLE_PAIRING_PASSKEY_LEN, dict, sizeof(dict) - 1);
assertTrue(publishPassKey(passkey, BLE_PAIRING_PASSKEY_LEN));
peerPassKey = String(passkey);
} else {
for (auto t = millis(); millis() - t < 60000;) {
if (getBleTestPasskey(peerPassKey)) {
break;
}
delay(50);
for (auto t = millis(); millis() - t < 60000;) {
if (getBleTestPasskey(peerPassKey)) {
break;
}
delay(50);
}
assertNotEqual(String(), peerPassKey);
BLE.setPairingPasskey(event.peer, (const uint8_t*)peerPassKey.c_str());
BLE.setPairingNumericComparison(event.peer, peerPassKey == String((const char*)event.payload.passkey, event.payloadLen));
}
#endif // PARTICLE_TEST_RUNNER
} else if (event.type == BlePairingEventType::PASSKEY_INPUT) {
#if !defined(PARTICLE_TEST_RUNNER)
while (Serial.available()) {
Serial.read();
}
});
Serial.print("Passkey input (must be identical to the peer's): ");
uint8_t i = 0;
uint8_t passkey[BLE_PAIRING_PASSKEY_LEN];
while (i < BLE_PAIRING_PASSKEY_LEN) {
if (Serial.available()) {
passkey[i] = Serial.read();
Serial.write(passkey[i++]);
}
}
Serial.println("");
BLE.setPairingPasskey(event.peer, passkey);
#else
Serial.printlnf("passkey input");
String peerPassKey;
// Special case where both ends have KEYBOARD_ONLY capabilities:
// Generate random passkey, the side that is the requester will publish it
if (ours == theirs && ours == BlePairingIoCaps::KEYBOARD_ONLY && request) {
Random rand;
char passkey[BLE_PAIRING_PASSKEY_LEN + 1] = {};
const char dict[] = "0123456789";
rand.genAlpha(passkey, BLE_PAIRING_PASSKEY_LEN, dict, sizeof(dict) - 1);
assertTrue(publishPassKey(passkey, BLE_PAIRING_PASSKEY_LEN));
peerPassKey = String(passkey);
} else {
for (auto t = millis(); millis() - t < 60000;) {
if (getBleTestPasskey(peerPassKey)) {
break;
}
delay(50);
}
}
assertNotEqual(String(), peerPassKey);
BLE.setPairingPasskey(event.peer, (const uint8_t*)peerPassKey.c_str());
#endif // PARTICLE_TEST_RUNNER
}
});

// Some platforms may have to restart BT stack to set IO caps, which may fail the connection attempt
delay(1s);

peer = BLE.connect(peerAddr, false);
assertTrue(peer.connected());
{
SCOPE_GUARD ({
delay(500);
assertEqual(BLE.disconnect(peer), (int)SYSTEM_ERROR_NONE);
assertFalse(BLE.connected());
assertFalse(peer.connected());
delay(500);
});
if (request) {
assertEqual(BLE.startPairing(peer), (int)SYSTEM_ERROR_NONE);
} else {
Expand Down Expand Up @@ -473,6 +476,12 @@ test(BLE_28_Pairing_Algorithm_Lesc_Only_Reject_Legacy_Prepare) {
}

test(BLE_29_Pairing_Algorithm_Lesc_Only_Reject_Legacy) {
assertEqual(BLE.setPairingIoCaps(BlePairingIoCaps::NONE), (int)SYSTEM_ERROR_NONE);
assertEqual(BLE.setPairingAlgorithm(BlePairingAlgorithm::LESC_ONLY), (int)SYSTEM_ERROR_NONE);

// Some platforms may have to restart BT stack to set IO caps, which may fail the connection attempt
delay(1s);

peer = BLE.connect(peerAddr, false);
assertTrue(peer.connected());
{
Expand All @@ -491,9 +500,6 @@ test(BLE_29_Pairing_Algorithm_Lesc_Only_Reject_Legacy) {
}
});

assertEqual(BLE.setPairingIoCaps(BlePairingIoCaps::NONE), (int)SYSTEM_ERROR_NONE);
assertEqual(BLE.setPairingAlgorithm(BlePairingAlgorithm::LESC_ONLY), (int)SYSTEM_ERROR_NONE);

assertEqual(BLE.startPairing(peer), (int)SYSTEM_ERROR_NONE);
assertTrue(BLE.isPairing(peer));
assertTrue(waitFor([&]{ return !BLE.isPairing(peer); }, 20000));
Expand Down Expand Up @@ -531,6 +537,11 @@ test(BLE_31_Pairing_Receiption_Reject) {
}
});

#if HAL_PLATFORM_RTL872X
// We set it to LESC_ONLY before, it will reject the pairing request automatically without generating any event.
assertEqual(BLE.setPairingAlgorithm(BlePairingAlgorithm::AUTO), (int)SYSTEM_ERROR_NONE);
#endif

peer = BLE.connect(peerAddr, false);
assertTrue(peer.connected());
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -380,7 +380,6 @@ static void pairingTestRoutine(bool request, BlePairingAlgorithm algorithm,
} else {
assertFalse(lesc);
}

}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,6 @@ void onDataReceived(const uint8_t* data, size_t len, const BlePeerDevice& peer,

using namespace particle::test;

// TODO: P2 needs to support BLE central role to perform this test

test(BLE_000_Broacaster_Cloud_Connect) {
subscribeEvents(BLE_ROLE_PERIPHERAL);
Particle.connect();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,6 @@ BleCharacteristic peerCharWriteWoRsp;

using namespace particle::test;

// TODO: P2 needs to support BLE central role to perform this test

test(BLE_000_Scanner_Cloud_Connect) {
subscribeEvents(BLE_ROLE_PERIPHERAL);
Particle.connect();
Expand Down
4 changes: 2 additions & 2 deletions user/tests/wiring/no_fixture_ble/ble.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,12 @@

#if Wiring_BLE == 1

#if !HAL_PLATFORM_RTL872X // P2 doesn't support setting device address
test(BLE_01_Set_BLE_Device_Address) {
int ret;
BleAddress defaultAddr = BLE.address();
BleAddress getAddr;

#if !HAL_PLATFORM_RTL872X // P2 doesn't support setting public device address
// The most two significant bits should be 0b10.
uint8_t mac[6] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x9b};
ret = BLE.setAddress(BleAddress(mac));
Expand Down Expand Up @@ -58,6 +58,7 @@ test(BLE_01_Set_BLE_Device_Address) {
assertEqual(ret, 0);
getAddr = BLE.address();
assertTrue(!strcmp(getAddr.toString().c_str(), "9B:40:33:20:11:00"));
#endif // !HAL_PLATFORM_RTL872X

// The most two significant bits of static address must be 0b11
ret = BLE.setAddress("9b:44:33:22:11:00", BleAddressType::RANDOM_STATIC);
Expand All @@ -74,7 +75,6 @@ test(BLE_01_Set_BLE_Device_Address) {
getAddr = BLE.address();
assertTrue(getAddr == defaultAddr);
}
#endif // !HAL_PLATFORM_RTL872X

test(BLE_02_Set_BLE_Device_Name) {
int ret;
Expand Down
2 changes: 1 addition & 1 deletion wiring/inc/spark_wiring_ble.h
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@ enum class BlePairingIoCaps : uint8_t {
enum class BlePairingAlgorithm : uint8_t {
AUTO = BLE_PAIRING_ALGORITHM_AUTO,
LEGACY_ONLY = BLE_PAIRING_ALGORITHM_LEGACY_ONLY,
LESC_ONLY = BLE_PAIRING_ALGORITHM_LESC_ONLY
LESC_ONLY = BLE_PAIRING_ALGORITHM_LESC_ONLY // nRF52840-based platforms only
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be supported with GAP_AUTHEN_BIT_SC_ONLY_FLAG, right?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've added this in https://github.com/particle-iot/device-os/tree/feature%2Fp2_ble_central-v2, feel free to pull-in if necessary.

};

enum class BlePairingEventType : uint8_t {
Expand Down
Loading