diff --git a/examples/common/blemesh_platform/platform/ESP32_custom/BUILD.gn b/examples/common/blemesh_platform/platform/ESP32_custom/BUILD.gn index fcd3cf48a4..b6f4254b0c 100644 --- a/examples/common/blemesh_platform/platform/ESP32_custom/BUILD.gn +++ b/examples/common/blemesh_platform/platform/ESP32_custom/BUILD.gn @@ -114,7 +114,10 @@ static_library("ESP32_custom") { "${chip_root}/src/setup_payload", ] - public = [ "${chip_root}/src/credentials/DeviceAttestationCredsProvider.h" ] + public = [ + "${chip_root}/src/credentials/CHIPCert.h", + "${chip_root}/src/credentials/DeviceAttestationCredsProvider.h", + ] public_deps = [ "${chip_root}/src/crypto", @@ -132,19 +135,31 @@ static_library("ESP32_custom") { if (chip_enable_chipoble) { sources += [ "BLEManagerImpl.h", + "ChipDeviceScanner.h", ] } + if (chip_enable_ble_controller) { + sources += [ "ChipDeviceScanner.h" ] + } + if (chip_bt_nimble_enabled) { - sources += [ - "nimble/BLEManagerImpl.cpp", - ] + sources += [ "nimble/BLEManagerImpl.cpp" ] + if (chip_enable_ble_controller) { + sources += [ + "nimble/ChipDeviceScanner.cpp", + "nimble/blecent.h", + "nimble/misc.c", + "nimble/peer.c", + ] + } } if (chip_bt_bluedroid_enabled) { - sources += [ - "bluedroid/BLEManagerImpl.cpp", - ] + sources += [ "bluedroid/BLEManagerImpl.cpp" ] + if (chip_enable_ble_controller) { + sources += [ "bluedroid/ChipDeviceScanner.cpp" ] + } } if (chip_enable_wifi) { @@ -159,6 +174,9 @@ static_library("ESP32_custom") { "WiFiDnssdImpl.h", ] } + if (chip_mdns == "minimal") { + sources += [ "ESP32EndpointQueueFilter.h" ] + } if (chip_enable_route_hook) { sources += [ "route_hook/ESP32RouteHook.c", @@ -169,6 +187,10 @@ static_library("ESP32_custom") { } } + if (chip_mdns == "platform") { + sources += [ "DnssdImpl.cpp" ] + } + if (chip_enable_ethernet) { sources += [ "ConnectivityManagerImpl_Ethernet.cpp", @@ -176,8 +198,23 @@ static_library("ESP32_custom") { ] } - if (chip_mdns == "platform") { - sources += [ "DnssdImpl.cpp" ] + if (chip_enable_openthread) { + sources += [ + "${chip_root}/src/platform/OpenThread/GenericNetworkCommissioningThreadDriver.cpp", + "${chip_root}/src/platform/OpenThread/GenericNetworkCommissioningThreadDriver.h", + "${chip_root}/src/platform/OpenThread/OpenThreadUtils.cpp", + "OpenthreadLauncher.cpp", + "OpenthreadLauncher.h", + "ThreadStackManagerImpl.cpp", + "ThreadStackManagerImpl.h", + ] + if (chip_mdns == "platform") { + sources += [ + "${chip_root}/src/platform/OpenThread/OpenThreadDnssdImpl.cpp", + "${chip_root}/src/platform/OpenThread/OpenThreadDnssdImpl.h", + ] + } + configs -= [ "${chip_root}/build/config/compiler:warnings_default" ] } if (chip_use_factory_data_provider) { @@ -193,4 +230,20 @@ static_library("ESP32_custom") { "ESP32DeviceInfoProvider.h", ] } + + if (chip_use_secure_cert_dac_provider) { + sources += [ + "ESP32SecureCertDACProvider.cpp", + "ESP32SecureCertDACProvider.h", + ] + } + + if (chip_use_esp32_ecdsa_peripheral) { + sources += [ + "ESP32CHIPCryptoPAL.cpp", + "ESP32CHIPCryptoPAL.h", + ] + } + + cflags = [ "-Wconversion" ] } diff --git a/examples/common/blemesh_platform/platform/ESP32_custom/ESP32EndpointQueueFilter.h b/examples/common/blemesh_platform/platform/ESP32_custom/ESP32EndpointQueueFilter.h new file mode 120000 index 0000000000..fc4f861782 --- /dev/null +++ b/examples/common/blemesh_platform/platform/ESP32_custom/ESP32EndpointQueueFilter.h @@ -0,0 +1 @@ +../../../../../connectedhomeip/connectedhomeip/src/platform/ESP32/ESP32EndpointQueueFilter.h \ No newline at end of file diff --git a/examples/common/blemesh_platform/platform/ESP32_custom/nimble/BLEManagerImpl.cpp b/examples/common/blemesh_platform/platform/ESP32_custom/nimble/BLEManagerImpl.cpp index 41ee92d3a5..ad37a33a45 100644 --- a/examples/common/blemesh_platform/platform/ESP32_custom/nimble/BLEManagerImpl.cpp +++ b/examples/common/blemesh_platform/platform/ESP32_custom/nimble/BLEManagerImpl.cpp @@ -30,11 +30,17 @@ #if CONFIG_BT_NIMBLE_ENABLED +#if CONFIG_ENABLE_ESP32_BLE_CONTROLLER +#include +#endif #include #include #include #include #include +#if CONFIG_ENABLE_ESP32_BLE_CONTROLLER +#include +#endif #include #include #include @@ -44,6 +50,9 @@ #if ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 0, 0) #include "esp_nimble_hci.h" #endif +#if CONFIG_ENABLE_ESP32_BLE_CONTROLLER +#include "blecent.h" +#endif #include "host/ble_hs.h" #include "host/ble_hs_pvcy.h" #include "host/ble_uuid.h" @@ -83,6 +92,11 @@ namespace Internal { namespace { +#if CONFIG_ENABLE_ESP32_BLE_CONTROLLER +static constexpr uint16_t kNewConnectionScanTimeout = 60; +static constexpr uint16_t kConnectTimeout = 20; +#endif + struct ESP32ChipServiceData { uint8_t ServiceUUID[2]; @@ -91,6 +105,10 @@ struct ESP32ChipServiceData const ble_uuid16_t ShortUUID_CHIPoBLEService = { BLE_UUID_TYPE_16, 0xFFF6 }; +#if CONFIG_ENABLE_ESP32_BLE_CONTROLLER +const ble_uuid16_t ShortUUID_CHIPoBLE_CharTx_Desc = { BLE_UUID_TYPE_16, 0x2902 }; +#endif + const ble_uuid128_t UUID128_CHIPoBLEChar_RX = { BLE_UUID_TYPE_128, { 0x11, 0x9D, 0x9F, 0x42, 0x9C, 0x4F, 0x9F, 0x95, 0x59, 0x45, 0x3D, 0x26, 0xF5, 0x2E, 0xEE, 0x18 } }; @@ -117,6 +135,9 @@ uint8_t own_addr_type = BLE_OWN_ADDR_RANDOM; } // unnamed namespace +#if CONFIG_ENABLE_ESP32_BLE_CONTROLLER +ChipDeviceScanner & mDeviceScanner = Internal::ChipDeviceScanner::GetInstance(); +#endif BLEManagerImpl BLEManagerImpl::sInstance; constexpr System::Clock::Timeout BLEManagerImpl::kFastAdvertiseTimeout; @@ -155,27 +176,65 @@ const struct ble_gatt_svc_def BLEManagerImpl::CHIPoBLEGATTAttrs[] = { }, }; -CHIP_ERROR BLEManagerImpl::_Init() +#if CONFIG_ENABLE_ESP32_BLE_CONTROLLER +void BLEManagerImpl::HandleConnectFailed(CHIP_ERROR error) { -#if CONFIG_USE_BLE_ONLY_FOR_COMMISSIONING -#if CHIP_DEVICE_CONFIG_ENABLE_THREAD - if (ConnectivityMgr().IsThreadProvisioned()) + if (sInstance.mIsCentral) { - ESP_LOGI(TAG, "Thread credentials already provisioned, not initializing BLE"); -#else - if (ConnectivityMgr().IsWiFiStationProvisioned()) + ChipDeviceEvent event; + event.Type = DeviceEventType::kPlatformESP32BLECentralConnectFailed; + event.Platform.BLECentralConnectFailed.mError = error; + PlatformMgr().PostEventOrDie(&event); + } +} + +void BLEManagerImpl::CancelConnect(void) +{ + int rc = ble_gap_conn_cancel(); + VerifyOrReturn(rc == 0, ChipLogError(Ble, "Failed to cancel connection rc=%d", rc)); +} + +void BLEManagerImpl::HandleConnectTimeout(chip::System::Layer *, void * context) +{ + CancelConnect(); + BLEManagerImpl::HandleConnectFailed(CHIP_ERROR_TIMEOUT); +} + +void BLEManagerImpl::ConnectDevice(const ble_addr_t & addr, uint16_t timeout) +{ + int rc; + uint8_t ownAddrType; + + rc = ble_hs_id_infer_auto(0, &ownAddrType); + if (rc != 0) { - ESP_LOGI(TAG, "WiFi station already provisioned, not initializing BLE"); -#endif /* CHIP_DEVICE_CONFIG_ENABLE_THREAD */ - esp_bt_mem_release(ESP_BT_MODE_BTDM); - return CHIP_NO_ERROR; + ChipLogError(Ble, "Failed to infer own address type rc=%d", rc); + return; } -#endif /* CONFIG_USE_BLE_ONLY_FOR_COMMISSIONING */ + rc = ble_gap_connect(ownAddrType, &addr, (timeout * 1000), NULL, ble_svr_gap_event, NULL); + if (rc != 0) + { + ChipLogError(Ble, "Failed to connect to rc=%d", rc); + } +} + +void HandleIncomingBleConnection(BLEEndPoint * bleEP) +{ + ChipLogProgress(DeviceLayer, "CHIPoBLE connection received"); +} +#endif + +CHIP_ERROR BLEManagerImpl::_Init() +{ CHIP_ERROR err; // Initialize the Chip BleLayer. +#if CONFIG_ENABLE_ESP32_BLE_CONTROLLER + err = BleLayer::Init(this, this, this, &DeviceLayer::SystemLayer()); +#else err = BleLayer::Init(this, this, &DeviceLayer::SystemLayer()); +#endif SuccessOrExit(err); mRXCharAttrHandle = 0; @@ -183,8 +242,15 @@ CHIP_ERROR BLEManagerImpl::_Init() mC3CharAttrHandle = 0; #endif mTXCharCCCDAttrHandle = 0; +#if CONFIG_ENABLE_ESP32_BLE_CONTROLLER + mFlags.ClearAll().Set(Flags::kAdvertisingEnabled, CHIP_DEVICE_CONFIG_CHIPOBLE_ENABLE_ADVERTISING_AUTOSTART && !mIsCentral); + mFlags.Set(Flags::kFastAdvertisingEnabled, !mIsCentral); + OnChipBleConnectReceived = HandleIncomingBleConnection; +#else mFlags.ClearAll().Set(Flags::kAdvertisingEnabled, CHIP_DEVICE_CONFIG_CHIPOBLE_ENABLE_ADVERTISING_AUTOSTART); mFlags.Set(Flags::kFastAdvertisingEnabled, true); + +#endif mNumGAPCons = 0; memset(reinterpret_cast(mCons), 0, sizeof(mCons)); mServiceMode = ConnectivityManager::kCHIPoBLEServiceMode_Enabled; @@ -327,20 +393,164 @@ void BLEManagerImpl::_OnPlatformEvent(const ChipDeviceEvent * event) break; default: +#if CONFIG_ENABLE_ESP32_BLE_CONTROLLER + HandlePlatformSpecificBLEEvent(event); +#endif + break; + } +} + +#if CONFIG_ENABLE_ESP32_BLE_CONTROLLER +void BLEManagerImpl::HandlePlatformSpecificBLEEvent(const ChipDeviceEvent * apEvent) +{ + CHIP_ERROR err = CHIP_NO_ERROR; + ChipLogProgress(DeviceLayer, "HandlePlatformSpecificBLEEvent %d", apEvent->Type); + + switch (apEvent->Type) + { + case DeviceEventType::kPlatformESP32BLECentralConnected: + if (BLEManagerImpl::mBLEScanConfig.mBleScanState == BleScanState::kConnecting) + { + BleConnectionDelegate::OnConnectionComplete(mBLEScanConfig.mAppState, + apEvent->Platform.BLECentralConnected.mConnection); + CleanScanConfig(); + } break; + + case DeviceEventType::kPlatformESP32BLECentralConnectFailed: + if (BLEManagerImpl::mBLEScanConfig.mBleScanState == BleScanState::kConnecting) + { + BleConnectionDelegate::OnConnectionError(mBLEScanConfig.mAppState, apEvent->Platform.BLECentralConnectFailed.mError); + CleanScanConfig(); + } + break; + + case DeviceEventType::kPlatformESP32BLEWriteComplete: + HandleWriteConfirmation(apEvent->Platform.BLEWriteComplete.mConnection, &CHIP_BLE_SVC_ID, &chipUUID_CHIPoBLEChar_RX); + break; + + case DeviceEventType::kPlatformESP32BLESubscribeOpComplete: + if (apEvent->Platform.BLESubscribeOpComplete.mIsSubscribed) + HandleSubscribeComplete(apEvent->Platform.BLESubscribeOpComplete.mConnection, &CHIP_BLE_SVC_ID, + &chipUUID_CHIPoBLEChar_TX); + else + HandleUnsubscribeComplete(apEvent->Platform.BLESubscribeOpComplete.mConnection, &CHIP_BLE_SVC_ID, + &chipUUID_CHIPoBLEChar_TX); + break; + + case DeviceEventType::kPlatformESP32BLEIndicationReceived: + HandleIndicationReceived(apEvent->Platform.BLEIndicationReceived.mConnection, &CHIP_BLE_SVC_ID, &chipUUID_CHIPoBLEChar_TX, + PacketBufferHandle::Adopt(apEvent->Platform.BLEIndicationReceived.mData)); + break; + + default: + break; + } + + if (err != CHIP_NO_ERROR) + { + ChipLogError(DeviceLayer, "Disabling CHIPoBLE service due to error: %s", ErrorStr(err)); + mServiceMode = ConnectivityManager::kCHIPoBLEServiceMode_Disabled; } } +static int OnUnsubscribeCharComplete(uint16_t conn_handle, const struct ble_gatt_error * error, struct ble_gatt_attr * attr, + void * arg) +{ + ChipLogProgress(DeviceLayer, "Subscribe complete: conn_handle=%d, error=%d, attr_handle=%d", conn_handle, error->status, + attr->handle); + + ChipDeviceEvent event; + event.Type = DeviceEventType::kPlatformESP32BLESubscribeOpComplete; + event.Platform.BLESubscribeOpComplete.mConnection = conn_handle; + event.Platform.BLESubscribeOpComplete.mIsSubscribed = false; + PlatformMgr().PostEventOrDie(&event); + + return 0; +} + +static int OnSubscribeCharComplete(uint16_t conn_handle, const struct ble_gatt_error * error, struct ble_gatt_attr * attr, + void * arg) +{ + ChipLogProgress(DeviceLayer, "Subscribe complete: conn_handle=%d, error=%d, attr_handle=%d", conn_handle, error->status, + attr->handle); + + ChipDeviceEvent event; + event.Type = DeviceEventType::kPlatformESP32BLESubscribeOpComplete; + event.Platform.BLESubscribeOpComplete.mConnection = conn_handle; + event.Platform.BLESubscribeOpComplete.mIsSubscribed = true; + PlatformMgr().PostEventOrDie(&event); + + return 0; +} +#endif + bool BLEManagerImpl::SubscribeCharacteristic(BLE_CONNECTION_OBJECT conId, const ChipBleUUID * svcId, const ChipBleUUID * charId) { - ChipLogProgress(DeviceLayer, "BLEManagerImpl::SubscribeCharacteristic() not supported"); +#if CONFIG_ENABLE_ESP32_BLE_CONTROLLER + const struct peer_dsc * dsc; + uint8_t value[2]; + int rc; + struct peer * peer = peer_find(conId); + + dsc = peer_dsc_find_uuid(peer, (ble_uuid_t *) (&ShortUUID_CHIPoBLEService), (ble_uuid_t *) (&UUID_CHIPoBLEChar_TX), + (ble_uuid_t *) (&ShortUUID_CHIPoBLE_CharTx_Desc)); + + if (dsc == nullptr) + { + ChipLogError(Ble, "Peer does not have CCCD"); + ble_gap_terminate(peer->conn_handle, BLE_ERR_REM_USER_CONN_TERM); + return false; + } + + value[0] = 0x02; + value[1] = 0x00; + + rc = ble_gattc_write_flat(peer->conn_handle, dsc->dsc.handle, value, sizeof(value), OnSubscribeCharComplete, NULL); + if (rc != 0) + { + ChipLogError(Ble, "ble_gattc_write_flat failed: %d", rc); + ble_gap_terminate(peer->conn_handle, BLE_ERR_REM_USER_CONN_TERM); + return false; + } + return true; +#else return false; +#endif } bool BLEManagerImpl::UnsubscribeCharacteristic(BLE_CONNECTION_OBJECT conId, const ChipBleUUID * svcId, const ChipBleUUID * charId) { - ChipLogProgress(DeviceLayer, "BLEManagerImpl::UnsubscribeCharacteristic() not supported"); +#if CONFIG_ENABLE_ESP32_BLE_CONTROLLER + const struct peer_dsc * dsc; + uint8_t value[2]; + int rc; + struct peer * peer = peer_find(conId); + + dsc = peer_dsc_find_uuid(peer, (ble_uuid_t *) (&ShortUUID_CHIPoBLEService), (ble_uuid_t *) (&UUID_CHIPoBLEChar_TX), + (ble_uuid_t *) (&ShortUUID_CHIPoBLE_CharTx_Desc)); + + if (dsc == nullptr) + { + ChipLogError(Ble, "Peer does not have CCCD"); + ble_gap_terminate(peer->conn_handle, BLE_ERR_REM_USER_CONN_TERM); + return false; + } + + value[0] = 0x00; + value[1] = 0x00; + + rc = ble_gattc_write_flat(peer->conn_handle, dsc->dsc.handle, value, sizeof(value), OnUnsubscribeCharComplete, NULL); + if (rc != 0) + { + ChipLogError(Ble, "ble_gattc_write_flat failed: %d", rc); + ble_gap_terminate(peer->conn_handle, BLE_ERR_REM_USER_CONN_TERM); + return false; + } + return true; +#else return false; +#endif } bool BLEManagerImpl::CloseConnection(BLE_CONNECTION_OBJECT conId) @@ -356,10 +566,12 @@ bool BLEManagerImpl::CloseConnection(BLE_CONNECTION_OBJECT conId) ChipLogError(DeviceLayer, "ble_gap_terminate() failed: %s", ErrorStr(err)); } +#if !CONFIG_ENABLE_ESP32_BLE_CONTROLLER // Force a refresh of the advertising state. mFlags.Set(Flags::kAdvertisingRefreshNeeded); mFlags.Clear(Flags::kAdvertisingConfigured); PlatformMgr().ScheduleWork(DriveBLEState, 0); +#endif return (err == CHIP_NO_ERROR); } @@ -370,7 +582,7 @@ uint16_t BLEManagerImpl::GetMTU(BLE_CONNECTION_OBJECT conId) const } bool BLEManagerImpl::SendIndication(BLE_CONNECTION_OBJECT conId, const ChipBleUUID * svcId, const ChipBleUUID * charId, - PacketBufferHandle data) + chip::System::PacketBufferHandle data) { CHIP_ERROR err = CHIP_NO_ERROR; struct os_mbuf * om; @@ -403,15 +615,54 @@ bool BLEManagerImpl::SendIndication(BLE_CONNECTION_OBJECT conId, const ChipBleUU return true; } +#if CONFIG_ENABLE_ESP32_BLE_CONTROLLER +static int OnWriteComplete(uint16_t conn_handle, const struct ble_gatt_error * error, struct ble_gatt_attr * attr, void * arg) +{ + ChipLogDetail(Ble, "Write complete; status:%d conn_handle:%d attr_handle:%d", error->status, conn_handle, attr->handle); + ChipDeviceEvent event; + event.Type = DeviceEventType::kPlatformESP32BLEWriteComplete; + event.Platform.BLEWriteComplete.mConnection = conn_handle; + CHIP_ERROR err = PlatformMgr().PostEvent(&event); + if (err != CHIP_NO_ERROR) + { + return 1; + } + + return 0; +} +#endif + bool BLEManagerImpl::SendWriteRequest(BLE_CONNECTION_OBJECT conId, const ChipBleUUID * svcId, const ChipBleUUID * charId, - PacketBufferHandle pBuf) + chip::System::PacketBufferHandle pBuf) { - ChipLogError(DeviceLayer, "BLEManagerImpl::SendWriteRequest() not supported"); +#if CONFIG_ENABLE_ESP32_BLE_CONTROLLER + const struct peer_chr * chr; + int rc; + const struct peer * peer = peer_find(conId); + + chr = peer_chr_find_uuid(peer, (ble_uuid_t *) (&ShortUUID_CHIPoBLEService), (ble_uuid_t *) (&UUID128_CHIPoBLEChar_RX)); + if (chr == nullptr) + { + ChipLogError(Ble, "Peer does not have RX characteristic"); + ble_gap_terminate(peer->conn_handle, BLE_ERR_REM_USER_CONN_TERM); + return false; + } + + rc = ble_gattc_write_flat(conId, chr->chr.val_handle, pBuf->Start(), pBuf->DataLength(), OnWriteComplete, this); + if (rc != 0) + { + ChipLogError(Ble, "ble_gattc_write_flat failed: %d", rc); + ble_gap_terminate(peer->conn_handle, BLE_ERR_REM_USER_CONN_TERM); + return false; + } + return true; +#else return false; +#endif } bool BLEManagerImpl::SendReadRequest(BLE_CONNECTION_OBJECT conId, const ChipBleUUID * svcId, const ChipBleUUID * charId, - PacketBufferHandle pBuf) + chip::System::PacketBufferHandle pBuf) { ChipLogError(DeviceLayer, "BLEManagerImpl::SendReadRequest() not supported"); return false; @@ -433,7 +684,7 @@ CHIP_ERROR BLEManagerImpl::MapBLEError(int bleErr) case ESP_OK: return CHIP_NO_ERROR; case BLE_HS_EMSGSIZE: - return CHIP_ERROR_INVALID_MESSAGE_LENGTH; + return CHIP_ERROR_BUFFER_TOO_SMALL; case BLE_HS_ENOMEM: case ESP_ERR_NO_MEM: return CHIP_ERROR_NO_MEMORY; @@ -442,7 +693,7 @@ CHIP_ERROR BLEManagerImpl::MapBLEError(int bleErr) case BLE_HS_ENOTSUP: return CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE; case BLE_HS_EAPP: - return CHIP_ERROR_READ_FAILED; + return CHIP_ERROR_INCORRECT_STATE; case BLE_HS_EBADDATA: return CHIP_ERROR_DATA_NOT_ALIGNED; case BLE_HS_ETIMEOUT: @@ -812,6 +1063,25 @@ CHIP_ERROR BLEManagerImpl::ConfigureAdvertisingData(void) return err; } +CHIP_ERROR BLEManagerImpl::ConfigureScanResponseData(ByteSpan data) +{ + if (data.empty() || data.size() > MAX_SCAN_RSP_DATA_LEN) + { + ChipLogError(DeviceLayer, "scan response data is invalid"); + return CHIP_ERROR_INVALID_ARGUMENT; + } + memcpy(scanResponseBuffer, data.data(), data.size()); + ByteSpan scanResponseSpan(scanResponseBuffer); + mScanResponse = chip::Optional(scanResponseSpan); + return CHIP_NO_ERROR; +} + +void BLEManagerImpl::ClearScanResponseData(void) +{ + mScanResponse.ClearValue(); + ChipLogDetail(DeviceLayer, "scan response data is cleared"); +} + void BLEManagerImpl::HandleRXCharWrite(struct ble_gatt_char_context * param) { CHIP_ERROR err = CHIP_NO_ERROR; @@ -950,7 +1220,76 @@ uint16_t BLEManagerImpl::_NumConnections(void) return numCons; } -CHIP_ERROR BLEManagerImpl::HandleGAPConnect(struct ble_gap_event * gapEvent) +#if CONFIG_ENABLE_ESP32_BLE_CONTROLLER +void BLEManagerImpl::HandleGAPConnectionFailed(struct ble_gap_event * gapEvent, CHIP_ERROR error) +{ + ChipLogError(Ble, "BLE GAP connection failed; status:%d", gapEvent->connect.status); + if (sInstance.mIsCentral) + { + ChipDeviceEvent event; + event.Type = DeviceEventType::kPlatformESP32BLECentralConnectFailed; + event.Platform.BLECentralConnectFailed.mError = error; + PlatformMgr().PostEventOrDie(&event); + } +} + +void BLEManagerImpl::OnGattDiscComplete(const struct peer * peer, int status, void * arg) +{ + if (status != 0) + { + ChipLogError(Ble, "GATT discovery failed; status:%d", status); + ble_gap_terminate(peer->conn_handle, BLE_ERR_REM_USER_CONN_TERM); + return; + } + + ChipLogProgress(Ble, "GATT discovery complete status:%d conn_handle:%d", status, peer->conn_handle); + + ChipDeviceEvent event; + event.Type = DeviceEventType::kPlatformESP32BLECentralConnected; + event.Platform.BLECentralConnected.mConnection = peer->conn_handle; + PlatformMgr().PostEventOrDie(&event); +} + +CHIP_ERROR BLEManagerImpl::HandleGAPCentralConnect(struct ble_gap_event * gapEvent) +{ + if (BLEManagerImpl::mBLEScanConfig.mBleScanState == BleScanState::kConnecting) + { + if (gapEvent->connect.status == 0) + { + // Track the number of active GAP connections. + mNumGAPCons++; + + ChipLogProgress(DeviceLayer, "BLE GAP connection established (con %u)", gapEvent->connect.conn_handle); + + // remember the peer + int rc = peer_add(gapEvent->connect.conn_handle); + if (rc != 0) + { + HandleGAPConnectionFailed(gapEvent, CHIP_ERROR_INTERNAL); + ChipLogError(DeviceLayer, "peer_add failed: %d", rc); + return CHIP_ERROR_INTERNAL; + } + + // Start the GATT discovery process + rc = peer_disc_all(gapEvent->connect.conn_handle, OnGattDiscComplete, NULL); + if (rc != 0) + { + HandleGAPConnectionFailed(gapEvent, CHIP_ERROR_INTERNAL); + ChipLogError(DeviceLayer, "peer_disc_al failed: %d", rc); + return CHIP_ERROR_INTERNAL; + } + } + else + { + HandleGAPConnectionFailed(gapEvent, CHIP_ERROR_INTERNAL); + return CHIP_ERROR_INTERNAL; + } + } + return CHIP_NO_ERROR; +} +#endif + +CHIP_ERROR BLEManagerImpl::HandleGAPPeripheralConnect(struct ble_gap_event * gapEvent) { CHIP_ERROR err = CHIP_NO_ERROR; ChipLogProgress(DeviceLayer, "BLE GAP connection established (con %u)", gapEvent->connect.conn_handle); @@ -968,6 +1307,23 @@ CHIP_ERROR BLEManagerImpl::HandleGAPConnect(struct ble_gap_event * gapEvent) return err; } +CHIP_ERROR BLEManagerImpl::HandleGAPConnect(struct ble_gap_event * gapEvent) +{ +#if CONFIG_ENABLE_ESP32_BLE_CONTROLLER + int rc; + + rc = ble_gattc_exchange_mtu(gapEvent->connect.conn_handle, NULL, NULL); + if (rc != 0) + { + return CHIP_ERROR_INTERNAL; + } + + return HandleGAPCentralConnect(gapEvent); +#else + return HandleGAPPeripheralConnect(gapEvent); +#endif +} + CHIP_ERROR BLEManagerImpl::HandleGAPDisconnect(struct ble_gap_event * gapEvent) { ChipLogProgress(DeviceLayer, "BLE GAP connection terminated (con %u reason 0x%02x)", gapEvent->disconnect.conn.conn_handle, @@ -979,6 +1335,12 @@ CHIP_ERROR BLEManagerImpl::HandleGAPDisconnect(struct ble_gap_event * gapEvent) mNumGAPCons--; } +#if CONFIG_ENABLE_ESP32_BLE_CONTROLLER + peer_delete(gapEvent->disconnect.conn.conn_handle); +#endif + + // There can be a case where the BLE central disconnects without unsubscribing from the BLE characteristic. + // In such situations, it is necessary to clear the subscription and post a connection error event. if (UnsetSubscribed(gapEvent->disconnect.conn.conn_handle)) { CHIP_ERROR disconReason; @@ -994,7 +1356,12 @@ CHIP_ERROR BLEManagerImpl::HandleGAPDisconnect(struct ble_gap_event * gapEvent) disconReason = BLE_ERROR_CHIPOBLE_PROTOCOL_ABORT; break; } - HandleConnectionError(gapEvent->disconnect.conn.conn_handle, disconReason); + + ChipDeviceEvent connectionErrorEvent; + connectionErrorEvent.Type = DeviceEventType::kCHIPoBLEConnectionError; + connectionErrorEvent.CHIPoBLEConnectionError.ConId = gapEvent->disconnect.conn.conn_handle; + connectionErrorEvent.CHIPoBLEConnectionError.Reason = disconReason; + ReturnErrorOnFailure(PlatformMgr().PostEvent(&connectionErrorEvent)); } ChipDeviceEvent disconnectEvent; @@ -1096,8 +1463,8 @@ int BLEManagerImpl::ble_svr_gap_event(struct ble_gap_event * event, void * arg) case BLE_GAP_EVENT_NOTIFY_TX: if (event->notify_tx.status != 0) { - err = sInstance.HandleTXComplete(event); - SuccessOrExit(err); + err = sInstance.HandleTXComplete(event); + SuccessOrExit(err); } break; @@ -1105,6 +1472,15 @@ int BLEManagerImpl::ble_svr_gap_event(struct ble_gap_event * event, void * arg) ESP_LOGD(TAG, "BLE_GAP_EVENT_MTU = %d channel id = %d", event->mtu.value, event->mtu.channel_id); break; +#if CONFIG_ENABLE_ESP32_BLE_CONTROLLER + case BLE_GAP_EVENT_NOTIFY_RX: + ESP_LOGD(TAG, "BLE_GAP_EVENT_NOTIFY_RX received %s conn_handle:%d attr_handle:%d attr_len:%d", + event->notify_rx.indication ? "indication" : "notification", event->notify_rx.conn_handle, + event->notify_rx.attr_handle, OS_MBUF_PKTLEN(event->notify_rx.om)); + err = sInstance.HandleRXNotify(event); + SuccessOrExit(err); + break; +#endif default: break; } @@ -1299,6 +1675,15 @@ CHIP_ERROR BLEManagerImpl::StartAdvertising(void) } } #endif + if (mScanResponse.HasValue()) + { + err = MapBLEError(ble_gap_adv_rsp_set_data(mScanResponse.Value().data(), mScanResponse.Value().size())); + if (err != CHIP_NO_ERROR) + { + ChipLogError(DeviceLayer, "ble_gap_adv_rsp_set_data failed: %s", ErrorStr(err)); + return err; + } + } #if CONFIG_BLE_MESH esp_ble_mesh_ble_adv_param_t chipoble_adv_param = { @@ -1344,6 +1729,156 @@ void BLEManagerImpl::DriveBLEState(intptr_t arg) sInstance.DriveBLEState(); } +#if CONFIG_ENABLE_ESP32_BLE_CONTROLLER +CHIP_ERROR BLEManagerImpl::HandleRXNotify(struct ble_gap_event * ble_event) +{ + uint8_t * data = OS_MBUF_DATA(ble_event->notify_rx.om, uint8_t *); + size_t dataLen = OS_MBUF_PKTLEN(ble_event->notify_rx.om); + System::PacketBufferHandle buf = System::PacketBufferHandle::NewWithData(data, dataLen); + VerifyOrReturnError(!buf.IsNull(), CHIP_ERROR_NO_MEMORY); + + ChipLogDetail(DeviceLayer, "Indication received, conn = %d", ble_event->notify_rx.conn_handle); + + ChipDeviceEvent event; + event.Type = DeviceEventType::kPlatformESP32BLEIndicationReceived; + event.Platform.BLEIndicationReceived.mConnection = ble_event->notify_rx.conn_handle; + event.Platform.BLEIndicationReceived.mData = std::move(buf).UnsafeRelease(); + PlatformMgr().PostEventOrDie(&event); + + return CHIP_NO_ERROR; +} + +CHIP_ERROR BLEManagerImpl::ConfigureBle(uint32_t aAdapterId, bool aIsCentral) +{ + mBLEAdvConfig.mpBleName = mDeviceName; + mBLEAdvConfig.mAdapterId = aAdapterId; + mBLEAdvConfig.mMajor = 1; + mBLEAdvConfig.mMinor = 1; + mBLEAdvConfig.mVendorId = 1; + mBLEAdvConfig.mProductId = 1; + mBLEAdvConfig.mDeviceId = 1; + mBLEAdvConfig.mDuration = 2; + mBLEAdvConfig.mPairingStatus = 0; + mBLEAdvConfig.mType = 1; + mBLEAdvConfig.mpAdvertisingUUID = "0xFFF6"; + + mIsCentral = aIsCentral; + if (mIsCentral) + { + int rc = peer_init(MYNEWT_VAL(BLE_MAX_CONNECTIONS), 64, 64, 64); + assert(rc == 0); + } + + return CHIP_NO_ERROR; +} + +void BLEManagerImpl::OnDeviceScanned(const struct ble_hs_adv_fields & fields, const ble_addr_t & addr, + const chip::Ble::ChipBLEDeviceIdentificationInfo & info) +{ + + if (mBLEScanConfig.mBleScanState == BleScanState::kScanForDiscriminator) + { + if (!mBLEScanConfig.mDiscriminator.MatchesLongDiscriminator(info.GetDeviceDiscriminator())) + { + printf("Discriminator didi not match \n"); + return; + } + ChipLogProgress(Ble, "Device Discriminator match. Attempting to connect"); + } + else if (mBLEScanConfig.mBleScanState == BleScanState::kScanForAddress) + { + ChipLogProgress(Ble, "Device Address match. Attempting to connect"); + } + else + { + ChipLogProgress(Ble, "Unknown discovery type. Ignoring"); + } + + mBLEScanConfig.mBleScanState = BleScanState::kConnecting; + chip::DeviceLayer::PlatformMgr().LockChipStack(); + DeviceLayer::SystemLayer().StartTimer(System::Clock::Seconds16(kConnectTimeout), HandleConnectTimeout, nullptr); + chip::DeviceLayer::PlatformMgr().UnlockChipStack(); + + mDeviceScanner.StopScan(); + + ConnectDevice(addr, kConnectTimeout); +} + +void BLEManagerImpl::OnScanComplete() +{ + if (mBLEScanConfig.mBleScanState != BleScanState::kScanForDiscriminator && + mBLEScanConfig.mBleScanState != BleScanState::kScanForAddress) + { + ChipLogProgress(Ble, "Scan complete notification without an active scan"); + return; + } + + BleConnectionDelegate::OnConnectionError(mBLEScanConfig.mAppState, CHIP_ERROR_TIMEOUT); + mBLEScanConfig.mBleScanState = BleScanState::kNotScanning; +} + +void BLEManagerImpl::InitiateScan(BleScanState scanType) +{ + DriveBLEState(); + + // Check for a valid scan type + if (scanType == BleScanState::kNotScanning) + { + BleConnectionDelegate::OnConnectionError(mBLEScanConfig.mAppState, CHIP_ERROR_INCORRECT_STATE); + ChipLogError(Ble, "Invalid scan type requested"); + return; + } + + // Initialize the device scanner + CHIP_ERROR err = mDeviceScanner.Init(this); + if (err != CHIP_NO_ERROR) + { + BleConnectionDelegate::OnConnectionError(mBLEScanConfig.mAppState, err); + ChipLogError(Ble, "Failed to initialize device scanner: %s", ErrorStr(err)); + return; + } + + // Start scanning + mBLEScanConfig.mBleScanState = scanType; + err = mDeviceScanner.StartScan(kNewConnectionScanTimeout); + if (err != CHIP_NO_ERROR) + { + mBLEScanConfig.mBleScanState = BleScanState::kNotScanning; + ChipLogError(Ble, "Failed to start a BLE scan: %s", chip::ErrorStr(err)); + BleConnectionDelegate::OnConnectionError(mBLEScanConfig.mAppState, err); + return; + } +} + +void BLEManagerImpl::CleanScanConfig() +{ + if (BLEManagerImpl::mBLEScanConfig.mBleScanState == BleScanState::kConnecting) + { + DeviceLayer::SystemLayer().CancelTimer(HandleConnectTimeout, nullptr); + } + mBLEScanConfig.mBleScanState = BleScanState::kNotScanning; +} + +void BLEManagerImpl::InitiateScan(intptr_t arg) +{ + sInstance.InitiateScan(static_cast(arg)); +} + +void BLEManagerImpl::NewConnection(BleLayer * bleLayer, void * appState, const SetupDiscriminator & connDiscriminator) +{ + mBLEScanConfig.mDiscriminator = connDiscriminator; + mBLEScanConfig.mAppState = appState; + + // Initiate async scan + PlatformMgr().ScheduleWork(InitiateScan, static_cast(BleScanState::kScanForDiscriminator)); +} + +CHIP_ERROR BLEManagerImpl::CancelConnection() +{ + return CHIP_ERROR_NOT_IMPLEMENTED; +} +#endif + } // namespace Internal } // namespace DeviceLayer } // namespace chip