Jack He | fcb2bbf | 2019-07-31 15:44:05 -0700 | [diff] [blame] | 1 | /* |
| 2 | * Copyright 2019 The Android Open Source Project |
| 3 | * |
| 4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
| 5 | * you may not use this file except in compliance with the License. |
| 6 | * You may obtain a copy of the License at |
| 7 | * |
| 8 | * http://www.apache.org/licenses/LICENSE-2.0 |
| 9 | * |
| 10 | * Unless required by applicable law or agreed to in writing, software |
| 11 | * distributed under the License is distributed on an "AS IS" BASIS, |
| 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 13 | * See the License for the specific language governing permissions and |
| 14 | * limitations under the License. |
| 15 | */ |
| 16 | #include <cstdint> |
| 17 | #include <unordered_map> |
| 18 | |
Hansong Zhang | 7092a1f | 2019-08-29 14:28:40 -0700 | [diff] [blame] | 19 | #include "common/bidi_queue.h" |
Jack He | fcb2bbf | 2019-07-31 15:44:05 -0700 | [diff] [blame] | 20 | #include "common/bind.h" |
| 21 | #include "grpc/grpc_event_stream.h" |
Martin Brabham | 94db40c | 2019-03-29 10:24:52 -0700 | [diff] [blame] | 22 | #include "hci/address.h" |
Hansong Zhang | 7092a1f | 2019-08-29 14:28:40 -0700 | [diff] [blame] | 23 | #include "hci/facade.h" |
Jack He | ff38d89 | 2019-10-03 17:11:07 -0700 | [diff] [blame] | 24 | #include "l2cap/classic/facade.grpc.pb.h" |
| 25 | #include "l2cap/classic/facade.h" |
| 26 | #include "l2cap/classic/l2cap_classic_module.h" |
Jack He | fcb2bbf | 2019-07-31 15:44:05 -0700 | [diff] [blame] | 27 | #include "l2cap/l2cap_packets.h" |
| 28 | #include "os/log.h" |
| 29 | #include "packet/raw_builder.h" |
| 30 | |
| 31 | using ::grpc::ServerAsyncResponseWriter; |
| 32 | using ::grpc::ServerAsyncWriter; |
| 33 | using ::grpc::ServerContext; |
| 34 | |
| 35 | using ::bluetooth::facade::EventStreamRequest; |
| 36 | using ::bluetooth::packet::RawBuilder; |
| 37 | |
| 38 | namespace bluetooth { |
| 39 | namespace l2cap { |
Jack He | ff38d89 | 2019-10-03 17:11:07 -0700 | [diff] [blame] | 40 | namespace classic { |
Jack He | fcb2bbf | 2019-07-31 15:44:05 -0700 | [diff] [blame] | 41 | |
| 42 | class L2capModuleFacadeService : public L2capModuleFacade::Service { |
| 43 | public: |
Jack He | ff38d89 | 2019-10-03 17:11:07 -0700 | [diff] [blame] | 44 | L2capModuleFacadeService(L2capClassicModule* l2cap_layer, os::Handler* facade_handler) |
Jack He | fcb2bbf | 2019-07-31 15:44:05 -0700 | [diff] [blame] | 45 | : l2cap_layer_(l2cap_layer), facade_handler_(facade_handler) { |
| 46 | ASSERT(l2cap_layer_ != nullptr); |
| 47 | ASSERT(facade_handler_ != nullptr); |
| 48 | } |
| 49 | |
Hansong Zhang | 7092a1f | 2019-08-29 14:28:40 -0700 | [diff] [blame] | 50 | class ConnectionCompleteCallback |
| 51 | : public grpc::GrpcEventStreamCallback<ConnectionCompleteEvent, ConnectionCompleteEvent> { |
| 52 | public: |
| 53 | void OnWriteResponse(ConnectionCompleteEvent* response, const ConnectionCompleteEvent& event) override { |
| 54 | response->CopyFrom(event); |
| 55 | } |
| 56 | |
| 57 | } connection_complete_callback_; |
| 58 | ::bluetooth::grpc::GrpcEventStream<ConnectionCompleteEvent, ConnectionCompleteEvent> connection_complete_stream_{ |
| 59 | &connection_complete_callback_}; |
| 60 | |
Hansong Zhang | cd0c319 | 2019-09-20 15:50:42 -0700 | [diff] [blame] | 61 | ::grpc::Status FetchConnectionComplete(::grpc::ServerContext* context, |
| 62 | const ::bluetooth::facade::EventStreamRequest* request, |
| 63 | ::grpc::ServerWriter<classic::ConnectionCompleteEvent>* writer) override { |
Hansong Zhang | 7092a1f | 2019-08-29 14:28:40 -0700 | [diff] [blame] | 64 | return connection_complete_stream_.HandleRequest(context, request, writer); |
| 65 | } |
| 66 | |
| 67 | ::grpc::Status Connect(::grpc::ServerContext* context, const facade::BluetoothAddress* request, |
| 68 | ::google::protobuf::Empty* response) override { |
Jack He | ff38d89 | 2019-10-03 17:11:07 -0700 | [diff] [blame] | 69 | auto fixed_channel_manager = l2cap_layer_->GetFixedChannelManager(); |
Hansong Zhang | 7092a1f | 2019-08-29 14:28:40 -0700 | [diff] [blame] | 70 | hci::Address peer; |
| 71 | ASSERT(hci::Address::FromString(request->address(), peer)); |
Jack He | ff38d89 | 2019-10-03 17:11:07 -0700 | [diff] [blame] | 72 | fixed_channel_manager->ConnectServices(peer, common::BindOnce([](FixedChannelManager::ConnectionResult) {}), |
Hansong Zhang | 7092a1f | 2019-08-29 14:28:40 -0700 | [diff] [blame] | 73 | facade_handler_); |
Jack He | fcb2bbf | 2019-07-31 15:44:05 -0700 | [diff] [blame] | 74 | return ::grpc::Status::OK; |
| 75 | } |
| 76 | |
Hansong Zhang | cd0c319 | 2019-09-20 15:50:42 -0700 | [diff] [blame] | 77 | ::grpc::Status SendL2capPacket(::grpc::ServerContext* context, const classic::L2capPacket* request, |
| 78 | SendL2capPacketResult* response) override { |
| 79 | if (fixed_channel_helper_map_.find(request->channel()) == fixed_channel_helper_map_.end()) { |
Hansong Zhang | 7092a1f | 2019-08-29 14:28:40 -0700 | [diff] [blame] | 80 | return ::grpc::Status(::grpc::StatusCode::FAILED_PRECONDITION, "Channel not registered"); |
| 81 | } |
| 82 | std::vector<uint8_t> packet(request->payload().begin(), request->payload().end()); |
Hansong Zhang | cd0c319 | 2019-09-20 15:50:42 -0700 | [diff] [blame] | 83 | fixed_channel_helper_map_[request->channel()]->SendPacket(packet); |
| 84 | response->set_result_type(SendL2capPacketResultType::OK); |
| 85 | return ::grpc::Status::OK; |
| 86 | } |
| 87 | |
| 88 | ::grpc::Status SendDynamicChannelPacket(::grpc::ServerContext* context, const DynamicChannelPacket* request, |
| 89 | ::google::protobuf::Empty* response) override { |
| 90 | if (dynamic_channel_helper_map_.find(request->psm()) == dynamic_channel_helper_map_.end()) { |
| 91 | return ::grpc::Status(::grpc::StatusCode::FAILED_PRECONDITION, "Psm not registered"); |
| 92 | } |
| 93 | std::vector<uint8_t> packet(request->payload().begin(), request->payload().end()); |
| 94 | dynamic_channel_helper_map_[request->psm()]->SendPacket(packet); |
Hansong Zhang | 7092a1f | 2019-08-29 14:28:40 -0700 | [diff] [blame] | 95 | return ::grpc::Status::OK; |
| 96 | } |
| 97 | |
Hansong Zhang | d1b6c9b | 2019-10-22 16:11:53 -0700 | [diff] [blame] | 98 | ::grpc::Status OpenChannel(::grpc::ServerContext* context, |
| 99 | const ::bluetooth::l2cap::classic::OpenChannelRequest* request, |
| 100 | ::google::protobuf::Empty* response) override { |
| 101 | auto psm = request->psm(); |
Hansong Zhang | a631253 | 2019-11-19 14:01:36 -0800 | [diff] [blame] | 102 | auto mode = request->mode(); |
Hansong Zhang | d1b6c9b | 2019-10-22 16:11:53 -0700 | [diff] [blame] | 103 | dynamic_channel_helper_map_.emplace( |
Hansong Zhang | a631253 | 2019-11-19 14:01:36 -0800 | [diff] [blame] | 104 | psm, std::make_unique<L2capDynamicChannelHelper>(this, l2cap_layer_, facade_handler_, psm, mode)); |
Hansong Zhang | d1b6c9b | 2019-10-22 16:11:53 -0700 | [diff] [blame] | 105 | hci::Address peer; |
| 106 | ASSERT(hci::Address::FromString(request->remote().address(), peer)); |
| 107 | dynamic_channel_helper_map_[psm]->Connect(peer); |
| 108 | return ::grpc::Status::OK; |
| 109 | } |
| 110 | |
Hansong Zhang | 7092a1f | 2019-08-29 14:28:40 -0700 | [diff] [blame] | 111 | ::grpc::Status FetchL2capData(::grpc::ServerContext* context, const ::bluetooth::facade::EventStreamRequest* request, |
Hansong Zhang | cd0c319 | 2019-09-20 15:50:42 -0700 | [diff] [blame] | 112 | ::grpc::ServerWriter<classic::L2capPacket>* writer) override { |
Hansong Zhang | 7092a1f | 2019-08-29 14:28:40 -0700 | [diff] [blame] | 113 | return l2cap_stream_.HandleRequest(context, request, writer); |
| 114 | } |
| 115 | |
Hansong Zhang | cd0c319 | 2019-09-20 15:50:42 -0700 | [diff] [blame] | 116 | ::grpc::Status RegisterChannel(::grpc::ServerContext* context, const classic::RegisterChannelRequest* request, |
Hansong Zhang | 7092a1f | 2019-08-29 14:28:40 -0700 | [diff] [blame] | 117 | ::google::protobuf::Empty* response) override { |
Hansong Zhang | cd0c319 | 2019-09-20 15:50:42 -0700 | [diff] [blame] | 118 | if (fixed_channel_helper_map_.find(request->channel()) != fixed_channel_helper_map_.end()) { |
Hansong Zhang | 7092a1f | 2019-08-29 14:28:40 -0700 | [diff] [blame] | 119 | return ::grpc::Status(::grpc::StatusCode::FAILED_PRECONDITION, "Already registered"); |
| 120 | } |
Hansong Zhang | cd0c319 | 2019-09-20 15:50:42 -0700 | [diff] [blame] | 121 | fixed_channel_helper_map_.emplace(request->channel(), std::make_unique<L2capFixedChannelHelper>( |
| 122 | this, l2cap_layer_, facade_handler_, request->channel())); |
Hansong Zhang | 7092a1f | 2019-08-29 14:28:40 -0700 | [diff] [blame] | 123 | |
| 124 | return ::grpc::Status::OK; |
| 125 | } |
| 126 | |
| 127 | class L2capFixedChannelHelper { |
| 128 | public: |
Jack He | ff38d89 | 2019-10-03 17:11:07 -0700 | [diff] [blame] | 129 | L2capFixedChannelHelper(L2capModuleFacadeService* service, L2capClassicModule* l2cap_layer, os::Handler* handler, |
| 130 | Cid cid) |
Hansong Zhang | 7092a1f | 2019-08-29 14:28:40 -0700 | [diff] [blame] | 131 | : facade_service_(service), l2cap_layer_(l2cap_layer), handler_(handler), cid_(cid) { |
Jack He | ff38d89 | 2019-10-03 17:11:07 -0700 | [diff] [blame] | 132 | fixed_channel_manager_ = l2cap_layer_->GetFixedChannelManager(); |
Hansong Zhang | 7092a1f | 2019-08-29 14:28:40 -0700 | [diff] [blame] | 133 | fixed_channel_manager_->RegisterService( |
| 134 | cid, {}, |
| 135 | common::BindOnce(&L2capFixedChannelHelper::on_l2cap_service_registration_complete, common::Unretained(this)), |
| 136 | common::Bind(&L2capFixedChannelHelper::on_connection_open, common::Unretained(this)), handler_); |
| 137 | } |
| 138 | |
Jack He | ff38d89 | 2019-10-03 17:11:07 -0700 | [diff] [blame] | 139 | void on_l2cap_service_registration_complete(FixedChannelManager::RegistrationResult registration_result, |
| 140 | std::unique_ptr<FixedChannelService> service) { |
Hansong Zhang | 7092a1f | 2019-08-29 14:28:40 -0700 | [diff] [blame] | 141 | service_ = std::move(service); |
| 142 | } |
| 143 | |
Jack He | ff38d89 | 2019-10-03 17:11:07 -0700 | [diff] [blame] | 144 | void on_connection_open(std::unique_ptr<FixedChannel> channel) { |
Hansong Zhang | 7092a1f | 2019-08-29 14:28:40 -0700 | [diff] [blame] | 145 | ConnectionCompleteEvent event; |
| 146 | event.mutable_remote()->set_address(channel->GetDevice().ToString()); |
| 147 | facade_service_->connection_complete_stream_.OnIncomingEvent(event); |
| 148 | channel_ = std::move(channel); |
| 149 | } |
| 150 | |
| 151 | void SendPacket(std::vector<uint8_t> packet) { |
| 152 | if (channel_ == nullptr) { |
| 153 | LOG_WARN("Channel is not open"); |
| 154 | return; |
| 155 | } |
| 156 | channel_->GetQueueUpEnd()->RegisterEnqueue( |
| 157 | handler_, common::Bind(&L2capFixedChannelHelper::enqueue_callback, common::Unretained(this), packet)); |
| 158 | } |
| 159 | |
| 160 | void on_incoming_packet() { |
| 161 | auto packet = channel_->GetQueueUpEnd()->TryDequeue(); |
| 162 | std::string data = std::string(packet->begin(), packet->end()); |
| 163 | L2capPacket l2cap_data; |
| 164 | l2cap_data.set_channel(cid_); |
| 165 | l2cap_data.set_payload(data); |
| 166 | facade_service_->l2cap_stream_.OnIncomingEvent(l2cap_data); |
| 167 | } |
| 168 | |
| 169 | std::unique_ptr<packet::BasePacketBuilder> enqueue_callback(std::vector<uint8_t> packet) { |
| 170 | auto packet_one = std::make_unique<packet::RawBuilder>(); |
| 171 | packet_one->AddOctets(packet); |
| 172 | channel_->GetQueueUpEnd()->UnregisterEnqueue(); |
| 173 | return packet_one; |
| 174 | }; |
| 175 | |
| 176 | L2capModuleFacadeService* facade_service_; |
Jack He | ff38d89 | 2019-10-03 17:11:07 -0700 | [diff] [blame] | 177 | L2capClassicModule* l2cap_layer_; |
Hansong Zhang | 7092a1f | 2019-08-29 14:28:40 -0700 | [diff] [blame] | 178 | os::Handler* handler_; |
Jack He | ff38d89 | 2019-10-03 17:11:07 -0700 | [diff] [blame] | 179 | std::unique_ptr<FixedChannelManager> fixed_channel_manager_; |
| 180 | std::unique_ptr<FixedChannelService> service_; |
| 181 | std::unique_ptr<FixedChannel> channel_ = nullptr; |
Hansong Zhang | 7092a1f | 2019-08-29 14:28:40 -0700 | [diff] [blame] | 182 | Cid cid_; |
| 183 | }; |
| 184 | |
Hansong Zhang | cd0c319 | 2019-09-20 15:50:42 -0700 | [diff] [blame] | 185 | ::grpc::Status SetDynamicChannel(::grpc::ServerContext* context, const SetEnableDynamicChannelRequest* request, |
| 186 | google::protobuf::Empty* response) override { |
Hansong Zhang | a631253 | 2019-11-19 14:01:36 -0800 | [diff] [blame] | 187 | dynamic_channel_helper_map_.emplace( |
| 188 | request->psm(), std::make_unique<L2capDynamicChannelHelper>(this, l2cap_layer_, facade_handler_, request->psm(), |
| 189 | request->retransmission_mode())); |
Hansong Zhang | cd0c319 | 2019-09-20 15:50:42 -0700 | [diff] [blame] | 190 | return ::grpc::Status::OK; |
| 191 | } |
| 192 | |
| 193 | class L2capDynamicChannelHelper { |
| 194 | public: |
| 195 | L2capDynamicChannelHelper(L2capModuleFacadeService* service, L2capClassicModule* l2cap_layer, os::Handler* handler, |
Hansong Zhang | a631253 | 2019-11-19 14:01:36 -0800 | [diff] [blame] | 196 | Psm psm, RetransmissionFlowControlMode mode) |
Hansong Zhang | cd0c319 | 2019-09-20 15:50:42 -0700 | [diff] [blame] | 197 | : facade_service_(service), l2cap_layer_(l2cap_layer), handler_(handler), psm_(psm) { |
| 198 | dynamic_channel_manager_ = l2cap_layer_->GetDynamicChannelManager(); |
Hansong Zhang | a631253 | 2019-11-19 14:01:36 -0800 | [diff] [blame] | 199 | DynamicChannelConfigurationOption configuration_option; |
| 200 | if (mode == RetransmissionFlowControlMode::BASIC) { |
| 201 | configuration_option.channel_mode = |
| 202 | DynamicChannelConfigurationOption::RetransmissionAndFlowControlMode::L2CAP_BASIC; |
| 203 | } else if (mode == RetransmissionFlowControlMode::ERTM) { |
| 204 | configuration_option.channel_mode = |
| 205 | DynamicChannelConfigurationOption::RetransmissionAndFlowControlMode::ENHANCED_RETRANSMISSION; |
| 206 | } |
Hansong Zhang | cd0c319 | 2019-09-20 15:50:42 -0700 | [diff] [blame] | 207 | dynamic_channel_manager_->RegisterService( |
Hansong Zhang | a631253 | 2019-11-19 14:01:36 -0800 | [diff] [blame] | 208 | psm, configuration_option, {}, |
Hansong Zhang | cd0c319 | 2019-09-20 15:50:42 -0700 | [diff] [blame] | 209 | common::BindOnce(&L2capDynamicChannelHelper::on_l2cap_service_registration_complete, |
| 210 | common::Unretained(this)), |
| 211 | common::Bind(&L2capDynamicChannelHelper::on_connection_open, common::Unretained(this)), handler_); |
| 212 | } |
| 213 | |
Hansong Zhang | d1b6c9b | 2019-10-22 16:11:53 -0700 | [diff] [blame] | 214 | void Connect(hci::Address address) { |
Hansong Zhang | a631253 | 2019-11-19 14:01:36 -0800 | [diff] [blame] | 215 | // TODO: specify channel mode |
Hansong Zhang | d1b6c9b | 2019-10-22 16:11:53 -0700 | [diff] [blame] | 216 | dynamic_channel_manager_->ConnectChannel( |
Hansong Zhang | a631253 | 2019-11-19 14:01:36 -0800 | [diff] [blame] | 217 | address, {}, psm_, common::Bind(&L2capDynamicChannelHelper::on_connection_open, common::Unretained(this)), |
Hansong Zhang | d1b6c9b | 2019-10-22 16:11:53 -0700 | [diff] [blame] | 218 | common::Bind(&L2capDynamicChannelHelper::on_connect_fail, common::Unretained(this)), handler_); |
| 219 | } |
| 220 | |
Hansong Zhang | cd0c319 | 2019-09-20 15:50:42 -0700 | [diff] [blame] | 221 | void on_l2cap_service_registration_complete(DynamicChannelManager::RegistrationResult registration_result, |
| 222 | std::unique_ptr<DynamicChannelService> service) {} |
| 223 | |
| 224 | void on_connection_open(std::unique_ptr<DynamicChannel> channel) { |
| 225 | ConnectionCompleteEvent event; |
| 226 | event.mutable_remote()->set_address(channel->GetDevice().ToString()); |
| 227 | facade_service_->connection_complete_stream_.OnIncomingEvent(event); |
| 228 | channel_ = std::move(channel); |
| 229 | } |
| 230 | |
Hansong Zhang | d1b6c9b | 2019-10-22 16:11:53 -0700 | [diff] [blame] | 231 | void on_connect_fail(DynamicChannelManager::ConnectionResult result) {} |
| 232 | |
Hansong Zhang | cd0c319 | 2019-09-20 15:50:42 -0700 | [diff] [blame] | 233 | void on_incoming_packet() { |
| 234 | auto packet = channel_->GetQueueUpEnd()->TryDequeue(); |
| 235 | std::string data = std::string(packet->begin(), packet->end()); |
| 236 | L2capPacket l2cap_data; |
| 237 | // l2cap_data.set_channel(cid_); |
| 238 | l2cap_data.set_payload(data); |
| 239 | facade_service_->l2cap_stream_.OnIncomingEvent(l2cap_data); |
| 240 | } |
| 241 | |
| 242 | void SendPacket(std::vector<uint8_t> packet) { |
| 243 | if (channel_ == nullptr) { |
| 244 | LOG_WARN("Channel is not open"); |
| 245 | return; |
| 246 | } |
| 247 | channel_->GetQueueUpEnd()->RegisterEnqueue( |
| 248 | handler_, common::Bind(&L2capDynamicChannelHelper::enqueue_callback, common::Unretained(this), packet)); |
| 249 | } |
| 250 | |
| 251 | std::unique_ptr<packet::BasePacketBuilder> enqueue_callback(std::vector<uint8_t> packet) { |
Hansong Zhang | a631253 | 2019-11-19 14:01:36 -0800 | [diff] [blame] | 252 | auto packet_one = std::make_unique<packet::RawBuilder>(2000); |
Hansong Zhang | cd0c319 | 2019-09-20 15:50:42 -0700 | [diff] [blame] | 253 | packet_one->AddOctets(packet); |
| 254 | channel_->GetQueueUpEnd()->UnregisterEnqueue(); |
| 255 | return packet_one; |
| 256 | }; |
| 257 | |
| 258 | L2capModuleFacadeService* facade_service_; |
| 259 | L2capClassicModule* l2cap_layer_; |
| 260 | os::Handler* handler_; |
| 261 | std::unique_ptr<DynamicChannelManager> dynamic_channel_manager_; |
| 262 | std::unique_ptr<DynamicChannelService> service_; |
| 263 | std::unique_ptr<DynamicChannel> channel_ = nullptr; |
| 264 | Psm psm_; |
| 265 | }; |
| 266 | |
| 267 | L2capClassicModule* l2cap_layer_; |
Jack He | fcb2bbf | 2019-07-31 15:44:05 -0700 | [diff] [blame] | 268 | ::bluetooth::os::Handler* facade_handler_; |
Hansong Zhang | cd0c319 | 2019-09-20 15:50:42 -0700 | [diff] [blame] | 269 | std::map<Cid, std::unique_ptr<L2capFixedChannelHelper>> fixed_channel_helper_map_; |
| 270 | std::map<Psm, std::unique_ptr<L2capDynamicChannelHelper>> dynamic_channel_helper_map_; |
Hansong Zhang | 7092a1f | 2019-08-29 14:28:40 -0700 | [diff] [blame] | 271 | |
| 272 | class L2capStreamCallback : public ::bluetooth::grpc::GrpcEventStreamCallback<L2capPacket, L2capPacket> { |
| 273 | public: |
| 274 | L2capStreamCallback(L2capModuleFacadeService* service) : service_(service) {} |
| 275 | |
| 276 | ~L2capStreamCallback() { |
Hansong Zhang | cd0c319 | 2019-09-20 15:50:42 -0700 | [diff] [blame] | 277 | for (const auto& connection : service_->fixed_channel_helper_map_) { |
| 278 | if (subscribed_fixed_channel_[connection.first] && connection.second->channel_ != nullptr) { |
Hansong Zhang | 7092a1f | 2019-08-29 14:28:40 -0700 | [diff] [blame] | 279 | connection.second->channel_->GetQueueUpEnd()->UnregisterDequeue(); |
Hansong Zhang | cd0c319 | 2019-09-20 15:50:42 -0700 | [diff] [blame] | 280 | subscribed_fixed_channel_[connection.first] = false; |
| 281 | } |
| 282 | } |
| 283 | |
| 284 | for (const auto& connection : service_->dynamic_channel_helper_map_) { |
| 285 | if (subscribed_dynamic_channel_[connection.first] && connection.second->channel_ != nullptr) { |
| 286 | connection.second->channel_->GetQueueUpEnd()->UnregisterDequeue(); |
| 287 | subscribed_dynamic_channel_[connection.first] = false; |
Hansong Zhang | 7092a1f | 2019-08-29 14:28:40 -0700 | [diff] [blame] | 288 | } |
| 289 | } |
| 290 | } |
| 291 | |
| 292 | void OnSubscribe() override { |
Hansong Zhang | cd0c319 | 2019-09-20 15:50:42 -0700 | [diff] [blame] | 293 | for (auto& connection : service_->fixed_channel_helper_map_) { |
| 294 | if (!subscribed_fixed_channel_[connection.first] && connection.second->channel_ != nullptr) { |
Hansong Zhang | 7092a1f | 2019-08-29 14:28:40 -0700 | [diff] [blame] | 295 | connection.second->channel_->GetQueueUpEnd()->RegisterDequeue( |
| 296 | service_->facade_handler_, |
| 297 | common::Bind(&L2capFixedChannelHelper::on_incoming_packet, common::Unretained(connection.second.get()))); |
Hansong Zhang | cd0c319 | 2019-09-20 15:50:42 -0700 | [diff] [blame] | 298 | subscribed_fixed_channel_[connection.first] = true; |
| 299 | } |
| 300 | } |
| 301 | |
| 302 | for (auto& connection : service_->dynamic_channel_helper_map_) { |
| 303 | if (!subscribed_dynamic_channel_[connection.first] && connection.second->channel_ != nullptr) { |
| 304 | connection.second->channel_->GetQueueUpEnd()->RegisterDequeue( |
| 305 | service_->facade_handler_, common::Bind(&L2capDynamicChannelHelper::on_incoming_packet, |
| 306 | common::Unretained(connection.second.get()))); |
| 307 | subscribed_dynamic_channel_[connection.first] = true; |
Hansong Zhang | 7092a1f | 2019-08-29 14:28:40 -0700 | [diff] [blame] | 308 | } |
| 309 | } |
| 310 | } |
| 311 | |
| 312 | void OnUnsubscribe() override { |
Hansong Zhang | cd0c319 | 2019-09-20 15:50:42 -0700 | [diff] [blame] | 313 | for (const auto& connection : service_->fixed_channel_helper_map_) { |
| 314 | if (subscribed_fixed_channel_[connection.first] && connection.second->channel_ != nullptr) { |
Hansong Zhang | 7092a1f | 2019-08-29 14:28:40 -0700 | [diff] [blame] | 315 | connection.second->channel_->GetQueueUpEnd()->UnregisterDequeue(); |
Hansong Zhang | cd0c319 | 2019-09-20 15:50:42 -0700 | [diff] [blame] | 316 | subscribed_fixed_channel_[connection.first] = false; |
| 317 | } |
| 318 | } |
| 319 | |
| 320 | for (const auto& connection : service_->dynamic_channel_helper_map_) { |
| 321 | if (subscribed_dynamic_channel_[connection.first] && connection.second->channel_ != nullptr) { |
| 322 | connection.second->channel_->GetQueueUpEnd()->UnregisterDequeue(); |
| 323 | subscribed_dynamic_channel_[connection.first] = false; |
Hansong Zhang | 7092a1f | 2019-08-29 14:28:40 -0700 | [diff] [blame] | 324 | } |
| 325 | } |
| 326 | } |
| 327 | |
| 328 | void OnWriteResponse(L2capPacket* response, const L2capPacket& event) override { |
| 329 | response->CopyFrom(event); |
| 330 | } |
| 331 | |
| 332 | L2capModuleFacadeService* service_; |
Hansong Zhang | cd0c319 | 2019-09-20 15:50:42 -0700 | [diff] [blame] | 333 | std::map<Cid, bool> subscribed_fixed_channel_; |
| 334 | std::map<Psm, bool> subscribed_dynamic_channel_; |
Hansong Zhang | 7092a1f | 2019-08-29 14:28:40 -0700 | [diff] [blame] | 335 | |
| 336 | } l2cap_stream_callback_{this}; |
| 337 | ::bluetooth::grpc::GrpcEventStream<L2capPacket, L2capPacket> l2cap_stream_{&l2cap_stream_callback_}; |
| 338 | |
Jack He | fcb2bbf | 2019-07-31 15:44:05 -0700 | [diff] [blame] | 339 | std::mutex mutex_; |
| 340 | }; |
| 341 | |
| 342 | void L2capModuleFacadeModule::ListDependencies(ModuleList* list) { |
| 343 | ::bluetooth::grpc::GrpcFacadeModule::ListDependencies(list); |
Jack He | ff38d89 | 2019-10-03 17:11:07 -0700 | [diff] [blame] | 344 | list->add<l2cap::classic::L2capClassicModule>(); |
Hansong Zhang | 7092a1f | 2019-08-29 14:28:40 -0700 | [diff] [blame] | 345 | list->add<hci::HciLayer>(); |
Jack He | fcb2bbf | 2019-07-31 15:44:05 -0700 | [diff] [blame] | 346 | } |
| 347 | |
| 348 | void L2capModuleFacadeModule::Start() { |
| 349 | ::bluetooth::grpc::GrpcFacadeModule::Start(); |
Hansong Zhang | 7092a1f | 2019-08-29 14:28:40 -0700 | [diff] [blame] | 350 | GetDependency<hci::HciLayer>()->EnqueueCommand(hci::WriteScanEnableBuilder::Create(hci::ScanEnable::PAGE_SCAN_ONLY), |
| 351 | common::BindOnce([](hci::CommandCompleteView) {}), GetHandler()); |
Jack He | ff38d89 | 2019-10-03 17:11:07 -0700 | [diff] [blame] | 352 | service_ = new L2capModuleFacadeService(GetDependency<l2cap::classic::L2capClassicModule>(), GetHandler()); |
Jack He | fcb2bbf | 2019-07-31 15:44:05 -0700 | [diff] [blame] | 353 | } |
| 354 | |
| 355 | void L2capModuleFacadeModule::Stop() { |
| 356 | delete service_; |
| 357 | ::bluetooth::grpc::GrpcFacadeModule::Stop(); |
| 358 | } |
| 359 | |
| 360 | ::grpc::Service* L2capModuleFacadeModule::GetService() const { |
| 361 | return service_; |
| 362 | } |
| 363 | |
| 364 | const ModuleFactory L2capModuleFacadeModule::Factory = |
| 365 | ::bluetooth::ModuleFactory([]() { return new L2capModuleFacadeModule(); }); |
| 366 | |
Jack He | ff38d89 | 2019-10-03 17:11:07 -0700 | [diff] [blame] | 367 | } // namespace classic |
Jack He | fcb2bbf | 2019-07-31 15:44:05 -0700 | [diff] [blame] | 368 | } // namespace l2cap |
| 369 | } // namespace bluetooth |