Loading system/gd/l2cap/classic/cert/api.proto +2 −1 Original line number Diff line number Diff line Loading @@ -59,5 +59,6 @@ message DisconnectionRequest { message FetchOpenedChannelsRequest {} message FetchOpenedChannelsResponse { repeated uint32 cid = 1; repeated uint32 scid = 1; repeated uint32 dcid = 2; } No newline at end of file system/gd/l2cap/classic/cert/cert.cc +44 −35 Original line number Diff line number Diff line Loading @@ -92,48 +92,52 @@ class L2capModuleCertService : public L2capModuleCert::Service { packet->AddOctets(std::vector<uint8_t>(req_string.begin(), req_string.end())); std::unique_ptr<BasicFrameBuilder> l2cap_builder = BasicFrameBuilder::Create(request->channel(), std::move(packet)); 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))); } send_packet_from_queue(); return ::grpc::Status::OK; } static constexpr Cid kFirstDynamicChannelForIncomingRequest = kFirstDynamicChannel + 0x100; ::grpc::Status SendConnectionRequest(::grpc::ServerContext* context, const cert::ConnectionRequest* request, ::google::protobuf::Empty* response) override { auto builder = ConnectionRequestBuilder::Create(1, 1, request->scid()); auto scid = request->scid(); if (last_connection_request_scid_ != kInvalidCid) { return ::grpc::Status(::grpc::StatusCode::INVALID_ARGUMENT, "Another connection request is pending"); } if (scid >= kFirstDynamicChannelForIncomingRequest) { return ::grpc::Status(::grpc::StatusCode::INVALID_ARGUMENT, "Use scid < kFirstDynamicChannelForIncomingRequest"); } for (const auto& cid_pair : open_channels_scid_dcid_) { if (cid_pair.first == scid) { return ::grpc::Status(::grpc::StatusCode::INVALID_ARGUMENT, "SCID already taken"); } } auto builder = ConnectionRequestBuilder::Create(1, request->psm(), scid); 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))); } send_packet_from_queue(); last_connection_request_scid_ = scid; return ::grpc::Status::OK; } Cid last_connection_request_scid_ = kInvalidCid; Cid next_incoming_request_cid_ = kFirstDynamicChannelForIncomingRequest; ::grpc::Status SendConfigurationRequest( ::grpc::ServerContext* context, const ::bluetooth::l2cap::classic::cert::ConfigurationRequest* request, ::bluetooth::l2cap::classic::cert::SendConfigurationRequestResult* response) override { auto builder = ConfigurationRequestBuilder::Create(1, request->scid(), Continuation::END, {}); auto l2cap_builder = BasicFrameBuilder::Create(1, std::move(builder)); auto l2cap_builder = BasicFrameBuilder::Create(kClassicSignallingCid, 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))); } send_packet_from_queue(); 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)); auto builder = DisconnectionRequestBuilder::Create(3, request->dcid(), request->scid()); auto l2cap_builder = BasicFrameBuilder::Create(kClassicSignallingCid, 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))); } send_packet_from_queue(); return ::grpc::Status::OK; } Loading @@ -141,10 +145,13 @@ class L2capModuleCertService : public L2capModuleCert::Service { ::grpc::Status FetchOpenedChannels( ::grpc::ServerContext* context, const ::bluetooth::l2cap::classic::cert::FetchOpenedChannelsRequest* request, ::bluetooth::l2cap::classic::cert::FetchOpenedChannelsResponse* response) override { response->mutable_cid()->Add(open_channels_.begin(), open_channels_.end()); for (const auto& cid_pair : open_channels_scid_dcid_) { response->mutable_scid()->Add(cid_pair.first); response->mutable_dcid()->Add(cid_pair.second); } return ::grpc::Status::OK; } std::vector<uint16_t> open_channels_; std::vector<std::pair<uint16_t, uint16_t>> open_channels_scid_dcid_; std::unique_ptr<packet::BasePacketBuilder> enqueue_packet_to_acl() { auto basic_frame_builder = std::move(outgoing_packet_queue_.front()); Loading Loading @@ -186,30 +193,35 @@ class L2capModuleCertService : public L2capModuleCert::Service { } } void send_packet_from_queue() { if (outgoing_packet_queue_.size() == 1) { acl_connection_->GetAclQueueEnd()->RegisterEnqueue( handler_, common::Bind(&L2capModuleCertService::enqueue_packet_to_acl, common::Unretained(this))); } } void handle_signalling_packet(ControlView control_view) { auto code = control_view.GetCode(); switch (code) { case CommandCode::CONNECTION_REQUEST: { ConnectionRequestView view = ConnectionRequestView::Create(control_view); ASSERT(view.IsValid()); open_channels_.push_back(view.GetSourceCid()); auto builder = ConnectionResponseBuilder::Create( view.GetIdentifier(), view.GetSourceCid(), view.GetSourceCid(), view.GetIdentifier(), view.GetSourceCid(), next_incoming_request_cid_, accept_incoming_connection_ ? ConnectionResponseResult::SUCCESS : ConnectionResponseResult::INVALID_CID, ConnectionResponseStatus::NO_FURTHER_INFORMATION_AVAILABLE); auto l2cap_builder = BasicFrameBuilder::Create(kClassicSignallingCid, 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))); } send_packet_from_queue(); open_channels_scid_dcid_.emplace_back(next_incoming_request_cid_, view.GetSourceCid()); next_incoming_request_cid_++; break; } case CommandCode::CONNECTION_RESPONSE: { ConnectionResponseView view = ConnectionResponseView::Create(control_view); ASSERT(view.IsValid()); open_channels_.push_back(view.GetSourceCid()); open_channels_scid_dcid_.emplace_back(last_connection_request_scid_, view.GetSourceCid()); last_connection_request_scid_ = kInvalidCid; break; } Loading @@ -221,10 +233,7 @@ class L2capModuleCertService : public L2capModuleCert::Service { ConfigurationResponseResult::SUCCESS, {}); auto l2cap_builder = BasicFrameBuilder::Create(kClassicSignallingCid, 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))); } send_packet_from_queue(); break; } default: Loading system/gd/l2cap/classic/cert/simple_l2cap_test.py +17 −8 Original line number Diff line number Diff line Loading @@ -84,11 +84,11 @@ class SimpleL2capTest(GdBaseTestClass): ) dut_connection_stream.unsubscribe() self.cert_device.l2cap.SendConnectionRequest(l2cap_cert_pb2.ConnectionRequest(scid=0x101)) self.cert_device.l2cap.SendConnectionRequest(l2cap_cert_pb2.ConnectionRequest(scid=0x101, psm=1)) time.sleep(1) open_channels = self.cert_device.l2cap.FetchOpenedChannels(l2cap_cert_pb2.FetchOpenedChannelsRequest()) cid = open_channels.cid[0] cid = open_channels.dcid[0] dut_packet_stream.subscribe() cert_packet_stream.subscribe() Loading @@ -113,28 +113,37 @@ class SimpleL2capTest(GdBaseTestClass): lambda packet: b"abc" in packet.payload ) self.cert_device.l2cap.SendDisconnectionRequest(l2cap_cert_pb2.DisconnectionRequest()) self.cert_device.l2cap.SendDisconnectionRequest(l2cap_cert_pb2.DisconnectionRequest(dcid=0x40, scid=101)) time.sleep(1) dut_packet_stream.unsubscribe() cert_packet_stream.unsubscribe() def test_open_two_channels(self): cert_connection_stream = self.cert_device.l2cap.connection_complete_stream cert_connection_stream.subscribe() self.device_under_test.l2cap.OpenChannel(l2cap_facade_pb2.OpenChannelRequest(remote=self.cert_address, psm=0x01)) self.device_under_test.l2cap.OpenChannel(l2cap_facade_pb2.OpenChannelRequest(remote=self.cert_address, psm=0x03)) cert_connection_stream.assert_event_occurs( lambda device: device.remote == self.dut_address ) cert_connection_stream.unsubscribe() time.sleep(1) open_channels = self.cert_device.l2cap.FetchOpenedChannels(l2cap_cert_pb2.FetchOpenedChannelsRequest()) assert len(open_channels.dcid) == 2 def test_basic_operation_request_connection(self): """ L2CAP/COS/CED/BV-01-C [Request Connection] Verify that the IUT is able to request the connection establishment for an L2CAP data channel and initiate the configuration procedure. """ self.device_under_test.l2cap.RegisterChannel(l2cap_facade_pb2.RegisterChannelRequest(channel=2)) cert_connection_stream = self.cert_device.l2cap.connection_complete_stream cert_connection_stream.subscribe() self.device_under_test.l2cap.Connect(self.cert_address) self.device_under_test.l2cap.OpenChannel(l2cap_facade_pb2.OpenChannelRequest(remote=self.cert_address, psm=0x01)) cert_connection_stream.assert_event_occurs( lambda device: device.remote == self.dut_address ) cert_connection_stream.unsubscribe() self.device_under_test.l2cap.OpenChannel(l2cap_facade_pb2.OpenChannelRequest(remote=self.cert_address, psm=0x01)) time.sleep(1) def test_respond_to_echo_request(self): """ Loading system/gd/l2cap/classic/internal/signalling_manager.cc +63 −24 Original line number Diff line number Diff line Loading @@ -52,8 +52,15 @@ ClassicSignallingManager::~ClassicSignallingManager() { } void ClassicSignallingManager::OnCommandReject(CommandRejectView command_reject_view) { if (pending_commands_.empty()) { LOG_WARN("Unexpected command reject: no pending request"); return; } auto last_sent_command = std::move(pending_commands_.front()); pending_commands_.pop(); SignalId signal_id = command_reject_view.GetIdentifier(); if (last_sent_command_.signal_id_ != signal_id) { if (last_sent_command.signal_id_ != signal_id) { LOG_WARN("Unknown command reject"); return; } Loading Loading @@ -147,20 +154,24 @@ void ClassicSignallingManager::OnConnectionRequest(SignalId signal_id, Psm psm, void ClassicSignallingManager::OnConnectionResponse(SignalId signal_id, Cid cid, Cid remote_cid, ConnectionResponseResult result, ConnectionResponseStatus status) { if (last_sent_command_.signal_id_ != signal_id || last_sent_command_.command_code_ != CommandCode::CONNECTION_REQUEST) { if (pending_commands_.empty()) { LOG_WARN("Unexpected response: no pending request"); return; } auto last_sent_command = std::move(pending_commands_.front()); pending_commands_.pop(); if (last_sent_command.signal_id_ != signal_id || last_sent_command.command_code_ != CommandCode::CONNECTION_REQUEST) { LOG_WARN("Received unexpected connection response"); return; } if (last_sent_command_.source_cid_ != cid) { LOG_WARN("SCID doesn't match: expected %d, received %d", last_sent_command_.source_cid_, cid); if (last_sent_command.source_cid_ != cid) { LOG_WARN("SCID doesn't match: expected %d, received %d", last_sent_command.source_cid_, cid); return; } if (result != ConnectionResponseResult::SUCCESS) { return; } Psm pending_psm = last_sent_command_.psm_; last_sent_command_ = {}; Psm pending_psm = last_sent_command.psm_; auto new_channel = link_->AllocateReservedDynamicChannel(cid, pending_psm, remote_cid, {}); if (new_channel == nullptr) { LOG_WARN("Can't allocate dynamic channel"); Loading Loading @@ -188,7 +199,15 @@ void ClassicSignallingManager::OnConfigurationRequest(SignalId signal_id, Cid ci void ClassicSignallingManager::OnConfigurationResponse(SignalId signal_id, Cid cid, Continuation is_continuation, ConfigurationResponseResult result, std::vector<std::unique_ptr<ConfigurationOption>> option) {} std::vector<std::unique_ptr<ConfigurationOption>> option) { if (pending_commands_.empty()) { LOG_WARN("Unexpected response: no pending request"); return; } auto last_sent_command = std::move(pending_commands_.front()); pending_commands_.pop(); } void ClassicSignallingManager::OnDisconnectionRequest(SignalId signal_id, Cid cid, Cid remote_cid) { // TODO: check cid match Loading @@ -204,8 +223,15 @@ void ClassicSignallingManager::OnDisconnectionRequest(SignalId signal_id, Cid ci } void ClassicSignallingManager::OnDisconnectionResponse(SignalId signal_id, Cid cid, Cid remote_cid) { if (last_sent_command_.signal_id_ != signal_id || last_sent_command_.command_code_ != CommandCode::DISCONNECTION_REQUEST) { if (pending_commands_.empty()) { LOG_WARN("Unexpected response: no pending request"); return; } auto last_sent_command = std::move(pending_commands_.front()); pending_commands_.pop(); if (last_sent_command.signal_id_ != signal_id || last_sent_command.command_code_ != CommandCode::DISCONNECTION_REQUEST) { return; } Loading @@ -228,7 +254,14 @@ void ClassicSignallingManager::OnEchoRequest(SignalId signal_id, const PacketVie } void ClassicSignallingManager::OnEchoResponse(SignalId signal_id, const PacketView<kLittleEndian>& packet) { if (last_sent_command_.signal_id_ != signal_id || last_sent_command_.command_code_ != CommandCode::ECHO_REQUEST) { if (pending_commands_.empty()) { LOG_WARN("Unexpected response: no pending request"); return; } auto last_sent_command = std::move(pending_commands_.front()); pending_commands_.pop(); if (last_sent_command.signal_id_ != signal_id || last_sent_command.command_code_ != CommandCode::ECHO_REQUEST) { return; } LOG_INFO("Echo response received"); Loading Loading @@ -259,8 +292,15 @@ void ClassicSignallingManager::OnInformationRequest(SignalId signal_id, Informat } void ClassicSignallingManager::OnInformationResponse(SignalId signal_id, const InformationResponseView& view) { if (last_sent_command_.signal_id_ != signal_id || last_sent_command_.command_code_ != CommandCode::INFORMATION_REQUEST) { if (pending_commands_.empty()) { LOG_WARN("Unexpected response: no pending request"); return; } auto last_sent_command = std::move(pending_commands_.front()); pending_commands_.pop(); if (last_sent_command.signal_id_ != signal_id || last_sent_command.command_code_ != CommandCode::INFORMATION_REQUEST) { return; } if (view.GetResult() != InformationRequestResult::SUCCESS) { Loading Loading @@ -395,16 +435,15 @@ void ClassicSignallingManager::handle_send_next_command() { if (pending_commands_.empty()) { return; } last_sent_command_ = std::move(pending_commands_.front()); pending_commands_.pop(); auto& last_sent_command = pending_commands_.front(); auto signal_id = last_sent_command_.signal_id_; auto psm = last_sent_command_.psm_; auto source_cid = last_sent_command_.source_cid_; auto destination_cid = last_sent_command_.destination_cid_; auto info_type = last_sent_command_.info_type_; auto config = std::move(last_sent_command_.config_); switch (last_sent_command_.command_code_) { auto signal_id = last_sent_command.signal_id_; auto psm = last_sent_command.psm_; auto source_cid = last_sent_command.source_cid_; auto destination_cid = last_sent_command.destination_cid_; auto info_type = last_sent_command.info_type_; auto config = std::move(last_sent_command.config_); switch (last_sent_command.command_code_) { case CommandCode::CONNECTION_REQUEST: { auto builder = ConnectionRequestBuilder::Create(signal_id.Value(), psm, source_cid); enqueue_buffer_->Enqueue(std::move(builder), handler_); Loading Loading @@ -435,7 +474,7 @@ void ClassicSignallingManager::handle_send_next_command() { break; } default: LOG_WARN("Unsupported command code 0x%x", static_cast<int>(last_sent_command_.command_code_)); LOG_WARN("Unsupported command code 0x%x", static_cast<int>(last_sent_command.command_code_)); } } Loading Loading
system/gd/l2cap/classic/cert/api.proto +2 −1 Original line number Diff line number Diff line Loading @@ -59,5 +59,6 @@ message DisconnectionRequest { message FetchOpenedChannelsRequest {} message FetchOpenedChannelsResponse { repeated uint32 cid = 1; repeated uint32 scid = 1; repeated uint32 dcid = 2; } No newline at end of file
system/gd/l2cap/classic/cert/cert.cc +44 −35 Original line number Diff line number Diff line Loading @@ -92,48 +92,52 @@ class L2capModuleCertService : public L2capModuleCert::Service { packet->AddOctets(std::vector<uint8_t>(req_string.begin(), req_string.end())); std::unique_ptr<BasicFrameBuilder> l2cap_builder = BasicFrameBuilder::Create(request->channel(), std::move(packet)); 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))); } send_packet_from_queue(); return ::grpc::Status::OK; } static constexpr Cid kFirstDynamicChannelForIncomingRequest = kFirstDynamicChannel + 0x100; ::grpc::Status SendConnectionRequest(::grpc::ServerContext* context, const cert::ConnectionRequest* request, ::google::protobuf::Empty* response) override { auto builder = ConnectionRequestBuilder::Create(1, 1, request->scid()); auto scid = request->scid(); if (last_connection_request_scid_ != kInvalidCid) { return ::grpc::Status(::grpc::StatusCode::INVALID_ARGUMENT, "Another connection request is pending"); } if (scid >= kFirstDynamicChannelForIncomingRequest) { return ::grpc::Status(::grpc::StatusCode::INVALID_ARGUMENT, "Use scid < kFirstDynamicChannelForIncomingRequest"); } for (const auto& cid_pair : open_channels_scid_dcid_) { if (cid_pair.first == scid) { return ::grpc::Status(::grpc::StatusCode::INVALID_ARGUMENT, "SCID already taken"); } } auto builder = ConnectionRequestBuilder::Create(1, request->psm(), scid); 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))); } send_packet_from_queue(); last_connection_request_scid_ = scid; return ::grpc::Status::OK; } Cid last_connection_request_scid_ = kInvalidCid; Cid next_incoming_request_cid_ = kFirstDynamicChannelForIncomingRequest; ::grpc::Status SendConfigurationRequest( ::grpc::ServerContext* context, const ::bluetooth::l2cap::classic::cert::ConfigurationRequest* request, ::bluetooth::l2cap::classic::cert::SendConfigurationRequestResult* response) override { auto builder = ConfigurationRequestBuilder::Create(1, request->scid(), Continuation::END, {}); auto l2cap_builder = BasicFrameBuilder::Create(1, std::move(builder)); auto l2cap_builder = BasicFrameBuilder::Create(kClassicSignallingCid, 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))); } send_packet_from_queue(); 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)); auto builder = DisconnectionRequestBuilder::Create(3, request->dcid(), request->scid()); auto l2cap_builder = BasicFrameBuilder::Create(kClassicSignallingCid, 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))); } send_packet_from_queue(); return ::grpc::Status::OK; } Loading @@ -141,10 +145,13 @@ class L2capModuleCertService : public L2capModuleCert::Service { ::grpc::Status FetchOpenedChannels( ::grpc::ServerContext* context, const ::bluetooth::l2cap::classic::cert::FetchOpenedChannelsRequest* request, ::bluetooth::l2cap::classic::cert::FetchOpenedChannelsResponse* response) override { response->mutable_cid()->Add(open_channels_.begin(), open_channels_.end()); for (const auto& cid_pair : open_channels_scid_dcid_) { response->mutable_scid()->Add(cid_pair.first); response->mutable_dcid()->Add(cid_pair.second); } return ::grpc::Status::OK; } std::vector<uint16_t> open_channels_; std::vector<std::pair<uint16_t, uint16_t>> open_channels_scid_dcid_; std::unique_ptr<packet::BasePacketBuilder> enqueue_packet_to_acl() { auto basic_frame_builder = std::move(outgoing_packet_queue_.front()); Loading Loading @@ -186,30 +193,35 @@ class L2capModuleCertService : public L2capModuleCert::Service { } } void send_packet_from_queue() { if (outgoing_packet_queue_.size() == 1) { acl_connection_->GetAclQueueEnd()->RegisterEnqueue( handler_, common::Bind(&L2capModuleCertService::enqueue_packet_to_acl, common::Unretained(this))); } } void handle_signalling_packet(ControlView control_view) { auto code = control_view.GetCode(); switch (code) { case CommandCode::CONNECTION_REQUEST: { ConnectionRequestView view = ConnectionRequestView::Create(control_view); ASSERT(view.IsValid()); open_channels_.push_back(view.GetSourceCid()); auto builder = ConnectionResponseBuilder::Create( view.GetIdentifier(), view.GetSourceCid(), view.GetSourceCid(), view.GetIdentifier(), view.GetSourceCid(), next_incoming_request_cid_, accept_incoming_connection_ ? ConnectionResponseResult::SUCCESS : ConnectionResponseResult::INVALID_CID, ConnectionResponseStatus::NO_FURTHER_INFORMATION_AVAILABLE); auto l2cap_builder = BasicFrameBuilder::Create(kClassicSignallingCid, 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))); } send_packet_from_queue(); open_channels_scid_dcid_.emplace_back(next_incoming_request_cid_, view.GetSourceCid()); next_incoming_request_cid_++; break; } case CommandCode::CONNECTION_RESPONSE: { ConnectionResponseView view = ConnectionResponseView::Create(control_view); ASSERT(view.IsValid()); open_channels_.push_back(view.GetSourceCid()); open_channels_scid_dcid_.emplace_back(last_connection_request_scid_, view.GetSourceCid()); last_connection_request_scid_ = kInvalidCid; break; } Loading @@ -221,10 +233,7 @@ class L2capModuleCertService : public L2capModuleCert::Service { ConfigurationResponseResult::SUCCESS, {}); auto l2cap_builder = BasicFrameBuilder::Create(kClassicSignallingCid, 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))); } send_packet_from_queue(); break; } default: Loading
system/gd/l2cap/classic/cert/simple_l2cap_test.py +17 −8 Original line number Diff line number Diff line Loading @@ -84,11 +84,11 @@ class SimpleL2capTest(GdBaseTestClass): ) dut_connection_stream.unsubscribe() self.cert_device.l2cap.SendConnectionRequest(l2cap_cert_pb2.ConnectionRequest(scid=0x101)) self.cert_device.l2cap.SendConnectionRequest(l2cap_cert_pb2.ConnectionRequest(scid=0x101, psm=1)) time.sleep(1) open_channels = self.cert_device.l2cap.FetchOpenedChannels(l2cap_cert_pb2.FetchOpenedChannelsRequest()) cid = open_channels.cid[0] cid = open_channels.dcid[0] dut_packet_stream.subscribe() cert_packet_stream.subscribe() Loading @@ -113,28 +113,37 @@ class SimpleL2capTest(GdBaseTestClass): lambda packet: b"abc" in packet.payload ) self.cert_device.l2cap.SendDisconnectionRequest(l2cap_cert_pb2.DisconnectionRequest()) self.cert_device.l2cap.SendDisconnectionRequest(l2cap_cert_pb2.DisconnectionRequest(dcid=0x40, scid=101)) time.sleep(1) dut_packet_stream.unsubscribe() cert_packet_stream.unsubscribe() def test_open_two_channels(self): cert_connection_stream = self.cert_device.l2cap.connection_complete_stream cert_connection_stream.subscribe() self.device_under_test.l2cap.OpenChannel(l2cap_facade_pb2.OpenChannelRequest(remote=self.cert_address, psm=0x01)) self.device_under_test.l2cap.OpenChannel(l2cap_facade_pb2.OpenChannelRequest(remote=self.cert_address, psm=0x03)) cert_connection_stream.assert_event_occurs( lambda device: device.remote == self.dut_address ) cert_connection_stream.unsubscribe() time.sleep(1) open_channels = self.cert_device.l2cap.FetchOpenedChannels(l2cap_cert_pb2.FetchOpenedChannelsRequest()) assert len(open_channels.dcid) == 2 def test_basic_operation_request_connection(self): """ L2CAP/COS/CED/BV-01-C [Request Connection] Verify that the IUT is able to request the connection establishment for an L2CAP data channel and initiate the configuration procedure. """ self.device_under_test.l2cap.RegisterChannel(l2cap_facade_pb2.RegisterChannelRequest(channel=2)) cert_connection_stream = self.cert_device.l2cap.connection_complete_stream cert_connection_stream.subscribe() self.device_under_test.l2cap.Connect(self.cert_address) self.device_under_test.l2cap.OpenChannel(l2cap_facade_pb2.OpenChannelRequest(remote=self.cert_address, psm=0x01)) cert_connection_stream.assert_event_occurs( lambda device: device.remote == self.dut_address ) cert_connection_stream.unsubscribe() self.device_under_test.l2cap.OpenChannel(l2cap_facade_pb2.OpenChannelRequest(remote=self.cert_address, psm=0x01)) time.sleep(1) def test_respond_to_echo_request(self): """ Loading
system/gd/l2cap/classic/internal/signalling_manager.cc +63 −24 Original line number Diff line number Diff line Loading @@ -52,8 +52,15 @@ ClassicSignallingManager::~ClassicSignallingManager() { } void ClassicSignallingManager::OnCommandReject(CommandRejectView command_reject_view) { if (pending_commands_.empty()) { LOG_WARN("Unexpected command reject: no pending request"); return; } auto last_sent_command = std::move(pending_commands_.front()); pending_commands_.pop(); SignalId signal_id = command_reject_view.GetIdentifier(); if (last_sent_command_.signal_id_ != signal_id) { if (last_sent_command.signal_id_ != signal_id) { LOG_WARN("Unknown command reject"); return; } Loading Loading @@ -147,20 +154,24 @@ void ClassicSignallingManager::OnConnectionRequest(SignalId signal_id, Psm psm, void ClassicSignallingManager::OnConnectionResponse(SignalId signal_id, Cid cid, Cid remote_cid, ConnectionResponseResult result, ConnectionResponseStatus status) { if (last_sent_command_.signal_id_ != signal_id || last_sent_command_.command_code_ != CommandCode::CONNECTION_REQUEST) { if (pending_commands_.empty()) { LOG_WARN("Unexpected response: no pending request"); return; } auto last_sent_command = std::move(pending_commands_.front()); pending_commands_.pop(); if (last_sent_command.signal_id_ != signal_id || last_sent_command.command_code_ != CommandCode::CONNECTION_REQUEST) { LOG_WARN("Received unexpected connection response"); return; } if (last_sent_command_.source_cid_ != cid) { LOG_WARN("SCID doesn't match: expected %d, received %d", last_sent_command_.source_cid_, cid); if (last_sent_command.source_cid_ != cid) { LOG_WARN("SCID doesn't match: expected %d, received %d", last_sent_command.source_cid_, cid); return; } if (result != ConnectionResponseResult::SUCCESS) { return; } Psm pending_psm = last_sent_command_.psm_; last_sent_command_ = {}; Psm pending_psm = last_sent_command.psm_; auto new_channel = link_->AllocateReservedDynamicChannel(cid, pending_psm, remote_cid, {}); if (new_channel == nullptr) { LOG_WARN("Can't allocate dynamic channel"); Loading Loading @@ -188,7 +199,15 @@ void ClassicSignallingManager::OnConfigurationRequest(SignalId signal_id, Cid ci void ClassicSignallingManager::OnConfigurationResponse(SignalId signal_id, Cid cid, Continuation is_continuation, ConfigurationResponseResult result, std::vector<std::unique_ptr<ConfigurationOption>> option) {} std::vector<std::unique_ptr<ConfigurationOption>> option) { if (pending_commands_.empty()) { LOG_WARN("Unexpected response: no pending request"); return; } auto last_sent_command = std::move(pending_commands_.front()); pending_commands_.pop(); } void ClassicSignallingManager::OnDisconnectionRequest(SignalId signal_id, Cid cid, Cid remote_cid) { // TODO: check cid match Loading @@ -204,8 +223,15 @@ void ClassicSignallingManager::OnDisconnectionRequest(SignalId signal_id, Cid ci } void ClassicSignallingManager::OnDisconnectionResponse(SignalId signal_id, Cid cid, Cid remote_cid) { if (last_sent_command_.signal_id_ != signal_id || last_sent_command_.command_code_ != CommandCode::DISCONNECTION_REQUEST) { if (pending_commands_.empty()) { LOG_WARN("Unexpected response: no pending request"); return; } auto last_sent_command = std::move(pending_commands_.front()); pending_commands_.pop(); if (last_sent_command.signal_id_ != signal_id || last_sent_command.command_code_ != CommandCode::DISCONNECTION_REQUEST) { return; } Loading @@ -228,7 +254,14 @@ void ClassicSignallingManager::OnEchoRequest(SignalId signal_id, const PacketVie } void ClassicSignallingManager::OnEchoResponse(SignalId signal_id, const PacketView<kLittleEndian>& packet) { if (last_sent_command_.signal_id_ != signal_id || last_sent_command_.command_code_ != CommandCode::ECHO_REQUEST) { if (pending_commands_.empty()) { LOG_WARN("Unexpected response: no pending request"); return; } auto last_sent_command = std::move(pending_commands_.front()); pending_commands_.pop(); if (last_sent_command.signal_id_ != signal_id || last_sent_command.command_code_ != CommandCode::ECHO_REQUEST) { return; } LOG_INFO("Echo response received"); Loading Loading @@ -259,8 +292,15 @@ void ClassicSignallingManager::OnInformationRequest(SignalId signal_id, Informat } void ClassicSignallingManager::OnInformationResponse(SignalId signal_id, const InformationResponseView& view) { if (last_sent_command_.signal_id_ != signal_id || last_sent_command_.command_code_ != CommandCode::INFORMATION_REQUEST) { if (pending_commands_.empty()) { LOG_WARN("Unexpected response: no pending request"); return; } auto last_sent_command = std::move(pending_commands_.front()); pending_commands_.pop(); if (last_sent_command.signal_id_ != signal_id || last_sent_command.command_code_ != CommandCode::INFORMATION_REQUEST) { return; } if (view.GetResult() != InformationRequestResult::SUCCESS) { Loading Loading @@ -395,16 +435,15 @@ void ClassicSignallingManager::handle_send_next_command() { if (pending_commands_.empty()) { return; } last_sent_command_ = std::move(pending_commands_.front()); pending_commands_.pop(); auto& last_sent_command = pending_commands_.front(); auto signal_id = last_sent_command_.signal_id_; auto psm = last_sent_command_.psm_; auto source_cid = last_sent_command_.source_cid_; auto destination_cid = last_sent_command_.destination_cid_; auto info_type = last_sent_command_.info_type_; auto config = std::move(last_sent_command_.config_); switch (last_sent_command_.command_code_) { auto signal_id = last_sent_command.signal_id_; auto psm = last_sent_command.psm_; auto source_cid = last_sent_command.source_cid_; auto destination_cid = last_sent_command.destination_cid_; auto info_type = last_sent_command.info_type_; auto config = std::move(last_sent_command.config_); switch (last_sent_command.command_code_) { case CommandCode::CONNECTION_REQUEST: { auto builder = ConnectionRequestBuilder::Create(signal_id.Value(), psm, source_cid); enqueue_buffer_->Enqueue(std::move(builder), handler_); Loading Loading @@ -435,7 +474,7 @@ void ClassicSignallingManager::handle_send_next_command() { break; } default: LOG_WARN("Unsupported command code 0x%x", static_cast<int>(last_sent_command_.command_code_)); LOG_WARN("Unsupported command code 0x%x", static_cast<int>(last_sent_command.command_code_)); } } Loading