Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 13479849 authored by Hansong Zhang's avatar Hansong Zhang
Browse files

L2CAP classic signalling handler, data pipeline, and cert test

Supports listening to an incoming L2CAP connection, open the channel and
transfer data.

Test: bluetooth_test_gd and cert/run_cert.sh
Bug: 138260719
Change-Id: I5a1b93dc30b43bb149c32e5f4ef5404f2d091cdb
parent dacad0cd
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -15,6 +15,7 @@ filegroup {
        "classic/internal/fixed_channel_service_manager_impl.cc",
        "classic/internal/link.cc",
        "classic/internal/link_manager.cc",
        "classic/internal/signalling_manager.cc",
        "classic/l2cap_classic_module.cc",
        "internal/scheduler_fifo.cc",
        "le/internal/fixed_channel_impl.cc",
@@ -36,6 +37,7 @@ filegroup {
        "classic/internal/fixed_channel_impl_test.cc",
        "classic/internal/fixed_channel_service_manager_test.cc",
        "classic/internal/link_manager_test.cc",
        "classic/internal/signalling_manager_test.cc",
        "internal/fixed_channel_allocator_test.cc",
        "internal/scheduler_fifo_test.cc",
        "l2cap_packet_test.cc",
+7 −0
Original line number Diff line number Diff line
@@ -11,6 +11,7 @@ service L2capModuleCert {
  rpc FetchConnectionComplete(facade.EventStreamRequest) returns (stream ConnectionCompleteEvent) {}
  rpc DisconnectLink(DisconnectLinkRequest) returns (google.protobuf.Empty) {}
  rpc SendConnectionRequest(ConnectionRequest) returns (google.protobuf.Empty) {}
  rpc SendDisconnectionRequest(DisconnectionRequest) returns (google.protobuf.Empty) {}
}

message L2capPacket {
@@ -32,3 +33,9 @@ message ConnectionRequest {
  uint32 dcid = 2;
  uint32 scid = 3;
}

message DisconnectionRequest {
  facade.BluetoothAddress remote = 1;
  uint32 dcid = 2;
  uint32 scid = 3;
}
 No newline at end of file
+27 −1
Original line number Diff line number Diff line
@@ -88,6 +88,32 @@ class L2capModuleCertService : public L2capModuleCert::Service {
    return ::grpc::Status::OK;
  }

  ::grpc::Status SendConnectionRequest(::grpc::ServerContext* context, const cert::ConnectionRequest* request,
                                       ::google::protobuf::Empty* response) override {
    auto builder = ConnectionRequestBuilder::Create(1, 1, 101);
    auto l2cap_builder = BasicFrameBuilder::Create(1, std::move(builder));
    outgoing_packet_queue_.push(std::move(l2cap_builder));
    if (outgoing_packet_queue_.size() == 1) {
      acl_connection_->GetAclQueueEnd()->RegisterEnqueue(
          handler_, common::Bind(&L2capModuleCertService::enqueue_packet_to_acl, common::Unretained(this)));
    }

    return ::grpc::Status::OK;
  }

  ::grpc::Status SendDisconnectionRequest(::grpc::ServerContext* context, const cert::DisconnectionRequest* request,
                                          ::google::protobuf::Empty* response) override {
    auto builder = DisconnectionRequestBuilder::Create(3, 0x40, 101);
    auto l2cap_builder = BasicFrameBuilder::Create(1, std::move(builder));
    outgoing_packet_queue_.push(std::move(l2cap_builder));
    if (outgoing_packet_queue_.size() == 1) {
      acl_connection_->GetAclQueueEnd()->RegisterEnqueue(
          handler_, common::Bind(&L2capModuleCertService::enqueue_packet_to_acl, common::Unretained(this)));
    }

    return ::grpc::Status::OK;
  }

  std::unique_ptr<packet::BasePacketBuilder> enqueue_packet_to_acl() {
    auto basic_frame_builder = std::move(outgoing_packet_queue_.front());
    outgoing_packet_queue_.pop();
@@ -122,7 +148,7 @@ class L2capModuleCertService : public L2capModuleCert::Service {
    l2cap_stream_.OnIncomingEvent(l2cap_packet);
  }

  std::queue<std::unique_ptr<BasicFrameBuilder>> outgoing_packet_queue_;
  std::queue<std::unique_ptr<BasePacketBuilder>> outgoing_packet_queue_;
  ::bluetooth::os::Handler* handler_;
  hci::AclManager* acl_manager_;
  std::unique_ptr<hci::AclConnection> acl_connection_;
+21 −0
Original line number Diff line number Diff line
@@ -25,6 +25,9 @@ from facade import common_pb2
from facade import rootservice_pb2 as facade_rootservice_pb2
from google.protobuf import empty_pb2
from l2cap.classic import facade_pb2 as l2cap_facade_pb2
from l2cap.classic.cert import api_pb2 as l2cap_cert_pb2

import time

class SimpleL2capTest(GdBaseTestClass):
    def setup_test(self):
@@ -64,6 +67,7 @@ class SimpleL2capTest(GdBaseTestClass):

    def test_connect_and_send_data(self):
        self.device_under_test.l2cap.RegisterChannel(l2cap_facade_pb2.RegisterChannelRequest(channel=2))
        self.device_under_test.l2cap.SetDynamicChannel(l2cap_facade_pb2.SetEnableDynamicChannelRequest(psm=0x01))
        dut_packet_stream = self.device_under_test.l2cap.packet_stream
        cert_packet_stream = self.cert_device.l2cap.packet_stream
        cert_connection_stream = self.cert_device.l2cap.connection_complete_stream
@@ -79,6 +83,10 @@ class SimpleL2capTest(GdBaseTestClass):
            lambda device: device.remote == self.cert_address
        )
        dut_connection_stream.unsubscribe()

        self.cert_device.l2cap.SendConnectionRequest(l2cap_cert_pb2.ConnectionRequest())
        time.sleep(1)

        dut_packet_stream.subscribe()
        cert_packet_stream.subscribe()
        self.cert_device.l2cap.SendL2capPacket(l2cap_facade_pb2.L2capPacket(channel=2, payload=b"abc"))
@@ -89,5 +97,18 @@ class SimpleL2capTest(GdBaseTestClass):
        cert_packet_stream.assert_event_occurs(
            lambda packet: b"123" in packet.payload
        )

        self.cert_device.l2cap.SendL2capPacket(l2cap_facade_pb2.L2capPacket(channel=64, payload=b"123"))
        dut_packet_stream.assert_event_occurs(
            lambda packet: b"123" in packet.payload
        )

        self.device_under_test.l2cap.SendDynamicChannelPacket(l2cap_facade_pb2.DynamicChannelPacket(psm=1, payload=b'abc'))
        cert_packet_stream.assert_event_occurs(
            lambda packet: b"abc" in packet.payload
        )

        self.cert_device.l2cap.SendDisconnectionRequest(l2cap_cert_pb2.DisconnectionRequest())
        time.sleep(1)
        dut_packet_stream.unsubscribe()
        cert_packet_stream.unsubscribe()
+9 −2
Original line number Diff line number Diff line
@@ -25,8 +25,15 @@ namespace classic {

bool DynamicChannelManager::ConnectChannel(hci::Address device, Psm psm, OnConnectionOpenCallback on_connection_open,
                                           OnConnectionFailureCallback on_fail_callback, os::Handler* handler) {
  // TODO impl me when there is no link, and when there is link
  return false;
  internal::LinkManager::PendingDynamicChannelConnection pending_dynamic_channel_connection{
      .on_open_callback_ = std::move(on_connection_open),
      .on_fail_callback_ = std::move(on_fail_callback),
      .handler_ = handler};
  l2cap_layer_handler_->Post(common::BindOnce(&internal::LinkManager::ConnectDynamicChannelServices,
                                              common::Unretained(link_manager_), device,
                                              std::move(pending_dynamic_channel_connection), psm));

  return true;
}

bool DynamicChannelManager::RegisterService(Psm psm, const SecurityPolicy& security_policy,
Loading