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

Unit tests for BLE layer class #33359

Merged
merged 9 commits into from
May 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
6 changes: 3 additions & 3 deletions src/ble/BLEEndPoint.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -346,7 +346,7 @@ void BLEEndPoint::DoClose(uint8_t flags, CHIP_ERROR err)
DoCloseCallback(oldState, flags, err);
}

if ((flags & kBleCloseFlag_SuppressCallback) != 0)
if (mBleTransport != nullptr && (flags & kBleCloseFlag_SuppressCallback) != 0)
{
mBleTransport->OnEndPointConnectionClosed(this, err);
}
Expand All @@ -367,7 +367,7 @@ void BLEEndPoint::FinalizeClose(uint8_t oldState, uint8_t flags, CHIP_ERROR err)
DoCloseCallback(oldState, flags, err);
}

if ((flags & kBleCloseFlag_SuppressCallback) != 0)
if (mBleTransport != nullptr && (flags & kBleCloseFlag_SuppressCallback) != 0)
{
mBleTransport->OnEndPointConnectionClosed(this, err);
}
Expand Down Expand Up @@ -1290,7 +1290,7 @@ CHIP_ERROR BLEEndPoint::Receive(PacketBufferHandle && data)
// Take ownership of message buffer
System::PacketBufferHandle full_packet = mBtpEngine.TakeRxPacket();

ChipLogDebugBleEndPoint(Ble, "reassembled whole msg, len = %d", full_packet->DataLength());
ChipLogDebugBleEndPoint(Ble, "reassembled whole msg, len = %u", static_cast<unsigned>(full_packet->DataLength()));

// If we have a message received callback, and end point is not closing...
if (mBleTransport != nullptr && mState != kState_Closing)
Expand Down
256 changes: 70 additions & 186 deletions src/ble/BleLayer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
* a platform's Bluetooth Low Energy (BLE) implementation and the CHIP
* stack.
*
* The BleLayer obect accepts BLE data and control input from the
* The BleLayer object accepts BLE data and control input from the
* application via a functional interface. It performs the fragmentation
* and reassembly required to transmit CHIP message via a BLE GATT
* characteristic interface, and drives incoming messages up the CHIP
Expand Down Expand Up @@ -485,43 +485,24 @@ CHIP_ERROR BleLayer::HandleBleTransportConnectionInitiated(BLE_CONNECTION_OBJECT
bool BleLayer::HandleWriteReceived(BLE_CONNECTION_OBJECT connObj, const ChipBleUUID * svcId, const ChipBleUUID * charId,
PacketBufferHandle && pBuf)
{
if (!UUIDsMatch(&CHIP_BLE_SVC_ID, svcId))
{
ChipLogError(Ble, "ble write rcvd on unknown svc id");
return true;
}
VerifyOrReturnError(UUIDsMatch(&CHIP_BLE_SVC_ID, svcId), false, ChipLogError(Ble, "Write received on unknown svc"));
VerifyOrReturnError(UUIDsMatch(&CHIP_BLE_CHAR_1_ID, charId), false, ChipLogError(Ble, "Write received on unknown char"));
VerifyOrReturnError(!pBuf.IsNull(), false, ChipLogError(Ble, "Write received null buffer"));

if (UUIDsMatch(&CHIP_BLE_CHAR_1_ID, charId))
{
if (pBuf.IsNull())
{
ChipLogError(Ble, "rcvd null ble write");
return true;
}

// Find matching connection end point.
BLEEndPoint * endPoint = sBLEEndPointPool.Find(connObj);
// Find matching connection end point.
BLEEndPoint * endPoint = sBLEEndPointPool.Find(connObj);

if (endPoint != nullptr)
{
CHIP_ERROR status = endPoint->Receive(std::move(pBuf));
if (status != CHIP_NO_ERROR)
{
ChipLogError(Ble, "BLEEndPoint rcv failed, err = %" CHIP_ERROR_FORMAT, status.Format());
}
}
else
{
CHIP_ERROR status = HandleBleTransportConnectionInitiated(connObj, std::move(pBuf));
if (status != CHIP_NO_ERROR)
{
ChipLogError(Ble, "failed handle new chip BLE connection, status = %" CHIP_ERROR_FORMAT, status.Format());
}
}
if (endPoint != nullptr)
{
CHIP_ERROR err = endPoint->Receive(std::move(pBuf));
VerifyOrReturnError(err == CHIP_NO_ERROR, false,
ChipLogError(Ble, "Receive failed, err = %" CHIP_ERROR_FORMAT, err.Format()));
}
else
{
ChipLogError(Ble, "ble write rcvd on unknown char");
CHIP_ERROR err = HandleBleTransportConnectionInitiated(connObj, std::move(pBuf));
VerifyOrReturnError(err == CHIP_NO_ERROR, false,
ChipLogError(Ble, "Handle new BLE connection failed, err = %" CHIP_ERROR_FORMAT, err.Format()));
}

return true;
Expand All @@ -530,217 +511,120 @@ bool BleLayer::HandleWriteReceived(BLE_CONNECTION_OBJECT connObj, const ChipBleU
bool BleLayer::HandleIndicationReceived(BLE_CONNECTION_OBJECT connObj, const ChipBleUUID * svcId, const ChipBleUUID * charId,
PacketBufferHandle && pBuf)
{
if (!UUIDsMatch(&CHIP_BLE_SVC_ID, svcId))
{
return false;
}
VerifyOrReturnError(UUIDsMatch(&CHIP_BLE_SVC_ID, svcId), false, ChipLogError(Ble, "Indication received on unknown svc"));
VerifyOrReturnError(UUIDsMatch(&CHIP_BLE_CHAR_2_ID, charId), false, ChipLogError(Ble, "Indication received on unknown char"));
VerifyOrReturnError(!pBuf.IsNull(), false, ChipLogError(Ble, "Indication received null buffer"));

if (UUIDsMatch(&CHIP_BLE_CHAR_2_ID, charId))
{
if (pBuf.IsNull())
{
ChipLogError(Ble, "rcvd null ble indication");
return true;
}

// find matching connection end point.
BLEEndPoint * endPoint = sBLEEndPointPool.Find(connObj);
// Find matching connection end point.
BLEEndPoint * endPoint = sBLEEndPointPool.Find(connObj);
VerifyOrReturnError(endPoint != nullptr, false, ChipLogDetail(Ble, "No endpoint for received indication"));

if (endPoint != nullptr)
{
CHIP_ERROR status = endPoint->Receive(std::move(pBuf));
if (status != CHIP_NO_ERROR)
{
ChipLogError(Ble, "BLEEndPoint rcv failed, err = %" CHIP_ERROR_FORMAT, status.Format());
}
}
else
{
ChipLogDetail(Ble, "no endpoint for rcvd indication");
}
}
else
{
ChipLogError(Ble, "ble ind rcvd on unknown char");
}
CHIP_ERROR err = endPoint->Receive(std::move(pBuf));
VerifyOrReturnError(err == CHIP_NO_ERROR, false, ChipLogError(Ble, "Receive failed, err = %" CHIP_ERROR_FORMAT, err.Format()));

return true;
}

bool BleLayer::HandleWriteConfirmation(BLE_CONNECTION_OBJECT connObj, const ChipBleUUID * svcId, const ChipBleUUID * charId)
{
if (!UUIDsMatch(&CHIP_BLE_SVC_ID, svcId))
{
return false;
}

if (UUIDsMatch(&CHIP_BLE_CHAR_1_ID, charId))
{
HandleAckReceived(connObj);
}
else
{
ChipLogError(Ble, "ble write con rcvd on unknown char");
}
VerifyOrReturnError(UUIDsMatch(&CHIP_BLE_SVC_ID, svcId), false, ChipLogError(Ble, "Write confirmation on unknown svc"));
VerifyOrReturnError(UUIDsMatch(&CHIP_BLE_CHAR_1_ID, charId), false, ChipLogError(Ble, "Write confirmation on unknown char"));

HandleAckReceived(connObj);
return true;
}

bool BleLayer::HandleIndicationConfirmation(BLE_CONNECTION_OBJECT connObj, const ChipBleUUID * svcId, const ChipBleUUID * charId)
{
if (!UUIDsMatch(&CHIP_BLE_SVC_ID, svcId))
{
return false;
}

if (UUIDsMatch(&CHIP_BLE_CHAR_2_ID, charId))
{
HandleAckReceived(connObj);
}
else
{
ChipLogError(Ble, "ble ind con rcvd on unknown char");
}
VerifyOrReturnError(UUIDsMatch(&CHIP_BLE_SVC_ID, svcId), false, ChipLogError(Ble, "Indication confirmation on unknown svc"));
VerifyOrReturnError(UUIDsMatch(&CHIP_BLE_CHAR_2_ID, charId), false,
ChipLogError(Ble, "Indication confirmation on unknown char"));

HandleAckReceived(connObj);
return true;
}

void BleLayer::HandleAckReceived(BLE_CONNECTION_OBJECT connObj)
{
// find matching connection end point.
// Find matching connection end point.
BLEEndPoint * endPoint = sBLEEndPointPool.Find(connObj);
VerifyOrReturn(endPoint != nullptr, ChipLogDetail(Ble, "No endpoint for received ack"));

if (endPoint != nullptr)
{
CHIP_ERROR status = endPoint->HandleGattSendConfirmationReceived();

if (status != CHIP_NO_ERROR)
{
ChipLogError(Ble, "endpoint conf recvd failed, err = %" CHIP_ERROR_FORMAT, status.Format());
}
}
else
{
ChipLogError(Ble, "no endpoint for BLE sent data ack");
}
CHIP_ERROR err = endPoint->HandleGattSendConfirmationReceived();
VerifyOrReturn(err == CHIP_NO_ERROR,
ChipLogError(Ble, "Send ack confirmation failed, err = %" CHIP_ERROR_FORMAT, err.Format()));
}

bool BleLayer::HandleSubscribeReceived(BLE_CONNECTION_OBJECT connObj, const ChipBleUUID * svcId, const ChipBleUUID * charId)
{
if (!UUIDsMatch(&CHIP_BLE_SVC_ID, svcId))
{
return false;
}
VerifyOrReturnError(UUIDsMatch(&CHIP_BLE_SVC_ID, svcId), false, ChipLogError(Ble, "Subscribe received on unknown svc"));
VerifyOrReturnError(UUIDsMatch(&CHIP_BLE_CHAR_2_ID, charId) || UUIDsMatch(&CHIP_BLE_CHAR_3_ID, charId), false,
ChipLogError(Ble, "Subscribe received on unknown char"));

if (UUIDsMatch(&CHIP_BLE_CHAR_2_ID, charId) || UUIDsMatch(&CHIP_BLE_CHAR_3_ID, charId))
{
// Find end point already associated with BLE connection, if any.
BLEEndPoint * endPoint = sBLEEndPointPool.Find(connObj);

if (endPoint != nullptr)
{
endPoint->HandleSubscribeReceived();
}
else
{
ChipLogError(Ble, "no endpoint for sub recvd");
}
}
// Find end point already associated with BLE connection, if any.
BLEEndPoint * endPoint = sBLEEndPointPool.Find(connObj);
VerifyOrReturnError(endPoint != nullptr, false, ChipLogDetail(Ble, "No endpoint for received subscribe"));

endPoint->HandleSubscribeReceived();
return true;
}

bool BleLayer::HandleSubscribeComplete(BLE_CONNECTION_OBJECT connObj, const ChipBleUUID * svcId, const ChipBleUUID * charId)
{
if (!UUIDsMatch(&CHIP_BLE_SVC_ID, svcId))
{
return false;
}
VerifyOrReturnError(UUIDsMatch(&CHIP_BLE_SVC_ID, svcId), false, ChipLogError(Ble, "Subscribe complete on unknown svc"));
VerifyOrReturnError(UUIDsMatch(&CHIP_BLE_CHAR_2_ID, charId) || UUIDsMatch(&CHIP_BLE_CHAR_3_ID, charId), false,
ChipLogError(Ble, "Subscribe complete on unknown char"));

if (UUIDsMatch(&CHIP_BLE_CHAR_2_ID, charId) || UUIDsMatch(&CHIP_BLE_CHAR_3_ID, charId))
{
BLEEndPoint * endPoint = sBLEEndPointPool.Find(connObj);

if (endPoint != nullptr)
{
endPoint->HandleSubscribeComplete();
}
else
{
ChipLogError(Ble, "no endpoint for sub complete");
}
}
BLEEndPoint * endPoint = sBLEEndPointPool.Find(connObj);
VerifyOrReturnError(endPoint != nullptr, false, ChipLogDetail(Ble, "No endpoint for subscribe complete"));

endPoint->HandleSubscribeComplete();
return true;
}

bool BleLayer::HandleUnsubscribeReceived(BLE_CONNECTION_OBJECT connObj, const ChipBleUUID * svcId, const ChipBleUUID * charId)
{
if (!UUIDsMatch(&CHIP_BLE_SVC_ID, svcId))
{
return false;
}
VerifyOrReturnError(UUIDsMatch(&CHIP_BLE_SVC_ID, svcId), false, ChipLogError(Ble, "Unsubscribe received on unknown svc"));
VerifyOrReturnError(UUIDsMatch(&CHIP_BLE_CHAR_2_ID, charId) || UUIDsMatch(&CHIP_BLE_CHAR_3_ID, charId), false,
ChipLogError(Ble, "Unsubscribe received on unknown char"));

if (UUIDsMatch(&CHIP_BLE_CHAR_2_ID, charId) || UUIDsMatch(&CHIP_BLE_CHAR_3_ID, charId))
{
// Find end point already associated with BLE connection, if any.
BLEEndPoint * endPoint = sBLEEndPointPool.Find(connObj);

if (endPoint != nullptr)
{
endPoint->DoClose(kBleCloseFlag_AbortTransmission, BLE_ERROR_CENTRAL_UNSUBSCRIBED);
}
else
{
ChipLogError(Ble, "no endpoint for unsub recvd");
}
}
// Find end point already associated with BLE connection, if any.
BLEEndPoint * endPoint = sBLEEndPointPool.Find(connObj);
VerifyOrReturnError(endPoint != nullptr, false, ChipLogDetail(Ble, "No endpoint for unsubscribe received"));

endPoint->DoClose(kBleCloseFlag_AbortTransmission, BLE_ERROR_CENTRAL_UNSUBSCRIBED);
return true;
}

bool BleLayer::HandleUnsubscribeComplete(BLE_CONNECTION_OBJECT connObj, const ChipBleUUID * svcId, const ChipBleUUID * charId)
{
if (!UUIDsMatch(&CHIP_BLE_SVC_ID, svcId))
{
return false;
}
VerifyOrReturnError(UUIDsMatch(&CHIP_BLE_SVC_ID, svcId), false, ChipLogError(Ble, "Unsubscribe complete on unknown svc"));
VerifyOrReturnError(UUIDsMatch(&CHIP_BLE_CHAR_2_ID, charId) || UUIDsMatch(&CHIP_BLE_CHAR_3_ID, charId), false,
ChipLogError(Ble, "Unsubscribe complete on unknown char"));

if (UUIDsMatch(&CHIP_BLE_CHAR_2_ID, charId) || UUIDsMatch(&CHIP_BLE_CHAR_3_ID, charId))
{
// Find end point already associated with BLE connection, if any.
BLEEndPoint * endPoint = sBLEEndPointPool.Find(connObj);

if (endPoint != nullptr)
{
endPoint->HandleUnsubscribeComplete();
}
else
{
ChipLogError(Ble, "no endpoint for unsub complete");
}
}
// Find end point already associated with BLE connection, if any.
BLEEndPoint * endPoint = sBLEEndPointPool.Find(connObj);
VerifyOrReturnError(endPoint != nullptr, false, ChipLogDetail(Ble, "No endpoint for unsubscribe complete"));

endPoint->HandleUnsubscribeComplete();
return true;
}

void BleLayer::HandleConnectionError(BLE_CONNECTION_OBJECT connObj, CHIP_ERROR err)
{
// BLE connection has failed somehow, we must find and abort matching connection end point.
BLEEndPoint * endPoint = sBLEEndPointPool.Find(connObj);
VerifyOrReturn(endPoint != nullptr, ChipLogDetail(Ble, "No endpoint for connection error"));

if (endPoint != nullptr)
if (err == BLE_ERROR_GATT_UNSUBSCRIBE_FAILED && endPoint->IsUnsubscribePending())
{
if (err == BLE_ERROR_GATT_UNSUBSCRIBE_FAILED && endPoint->IsUnsubscribePending())
{
// If end point was already closed and just waiting for unsubscribe to complete, free it. Call to Free()
// stops unsubscribe timer.
endPoint->Free();
}
else
{
endPoint->DoClose(kBleCloseFlag_AbortTransmission, err);
}
// If end point was already closed and just waiting for unsubscribe to complete, free it. Call to Free()
// stops unsubscribe timer.
endPoint->Free();
}
else
{
endPoint->DoClose(kBleCloseFlag_AbortTransmission, err);
}
}

Expand Down
1 change: 0 additions & 1 deletion src/ble/BleLayer.h
Original file line number Diff line number Diff line change
Expand Up @@ -327,7 +327,6 @@ class DLL_EXPORT BleLayer

// Private functions:
void HandleAckReceived(BLE_CONNECTION_OBJECT connObj);
void DriveSending();
CHIP_ERROR HandleBleTransportConnectionInitiated(BLE_CONNECTION_OBJECT connObj, System::PacketBufferHandle && pBuf);

static BleTransportProtocolVersion GetHighestSupportedProtocolVersion(const BleTransportCapabilitiesRequestMessage & reqMsg);
Expand Down
6 changes: 5 additions & 1 deletion src/ble/tests/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,15 @@ chip_test_suite("tests") {

test_sources = [
"TestBleErrorStr.cpp",
"TestBleLayer.cpp",
"TestBleUUID.cpp",
"TestBtpEngine.cpp",
]

cflags = [ "-Wconversion" ]

public_deps = [ "${chip_root}/src/ble" ]
public_deps = [
"${chip_root}/src/ble",
"${chip_root}/src/platform",
]
}
Loading
Loading