static bluetooth::shim::legacy::L2cap shim_l2cap;
+// Classic Dynamic Channel Shim Helper
+
+uint16_t classic_cid_token_counter_ = 1;
+
+struct ClassicDynamicChannelInfo {
+ uint16_t psm;
+ RawAddress remote;
+};
+std::unordered_map<uint16_t, ClassicDynamicChannelInfo>
+ classic_cid_token_to_channel_map_;
+
+uint16_t add_classic_cid_token_entry(uint16_t psm, RawAddress remote) {
+ uint16_t new_token = classic_cid_token_counter_;
+ classic_cid_token_to_channel_map_[new_token] = {psm, remote};
+ classic_cid_token_counter_++;
+ if (classic_cid_token_counter_ == 0) classic_cid_token_counter_++;
+ return new_token;
+}
+
+void remove_classic_cid_token_entry(uint16_t cid_token) {
+ classic_cid_token_to_channel_map_.erase(cid_token);
+}
+
+uint16_t find_classic_cid_token_by_psm_address(uint16_t psm,
+ RawAddress remote) {
+ for (const auto& entry : classic_cid_token_to_channel_map_) {
+ if (entry.second.psm == psm && entry.second.remote == remote) {
+ return entry.first;
+ }
+ }
+ LOG(ERROR) << __func__ << "Can't find channel";
+ return 0;
+}
+
+struct ClassicDynamicChannelHelper {
+ ClassicDynamicChannelHelper(uint16_t psm, tL2CAP_APPL_INFO appl_info)
+ : psm_(psm), appl_info_(appl_info) {}
+
+ uint16_t psm_;
+ tL2CAP_APPL_INFO appl_info_;
+
+ void Register() {
+ bluetooth::shim::GetL2capClassicModule()
+ ->GetDynamicChannelManager()
+ ->RegisterService(
+ psm_, {}, {},
+ bluetooth::shim::GetGdShimHandler()->BindOnceOn(
+ this, &ClassicDynamicChannelHelper::on_registration_complete),
+ bluetooth::shim::GetGdShimHandler()->BindOn(
+ this, &ClassicDynamicChannelHelper::on_channel_open));
+ }
+
+ void on_registration_complete(
+ classic::DynamicChannelManager::RegistrationResult result,
+ std::unique_ptr<classic::DynamicChannelService> service) {
+ if (result != classic::DynamicChannelManager::RegistrationResult::SUCCESS) {
+ LOG(ERROR) << "Channel is not registered. psm=" << +psm_ << (int)result;
+ return;
+ }
+ channel_service_ = std::move(service);
+ }
+
+ std::unique_ptr<classic::DynamicChannelService> channel_service_ = nullptr;
+
+ void Connect(bluetooth::hci::AddressWithType device) {
+ if (channel_service_ == nullptr) {
+ return;
+ }
+ initiated_by_us_[device] = true;
+ bluetooth::shim::GetL2capClassicModule()
+ ->GetDynamicChannelManager()
+ ->ConnectChannel(
+ device.GetAddress(), {}, psm_,
+ bluetooth::shim::GetGdShimHandler()->BindOn(
+ this, &ClassicDynamicChannelHelper::on_channel_open),
+ bluetooth::shim::GetGdShimHandler()->BindOnceOn(
+ this,
+ &ClassicDynamicChannelHelper::on_outgoing_connection_fail));
+ }
+
+ void Disconnect(bluetooth::hci::AddressWithType device) {
+ if (channel_service_ == nullptr) {
+ return;
+ }
+ if (channels_.count(device) == 0) {
+ return;
+ }
+ channels_[device]->Close();
+ disconnected_by_us_[device] = true;
+ }
+
+ void Unregister() {
+ if (channel_service_ != nullptr) {
+ channel_service_->Unregister(
+ bluetooth::shim::GetGdShimHandler()->BindOnceOn(
+ this, &ClassicDynamicChannelHelper::on_unregistered));
+ channel_service_ = nullptr;
+ }
+ }
+
+ void on_unregistered() {
+ for (const auto& device : channels_) {
+ device.second->Close();
+ }
+ }
+
+ void on_channel_close(bluetooth::hci::AddressWithType device,
+ bluetooth::hci::ErrorCode error_code) {
+ channel_enqueue_buffer_[device] = nullptr;
+ channels_[device]->GetQueueUpEnd()->UnregisterDequeue();
+ channels_.erase(device);
+ auto address = bluetooth::ToRawAddress(device.GetAddress());
+ auto cid_token = find_classic_cid_token_by_psm_address(psm_, address);
+ (appl_info_.pL2CA_DisconnectInd_Cb)(cid_token, false);
+ remove_classic_cid_token_entry(cid_token);
+ initiated_by_us_.erase(device);
+
+ if (channel_service_ == nullptr && channels_.empty()) {
+ // Try again
+ bluetooth::shim::L2CA_Deregister(psm_);
+ }
+ }
+
+ void on_channel_open(std::unique_ptr<classic::DynamicChannel> channel) {
+ auto device = channel->GetDevice();
+ channel->RegisterOnCloseCallback(
+ bluetooth::shim::GetGdShimHandler()->BindOnceOn(
+ this, &ClassicDynamicChannelHelper::on_channel_close, device));
+ channel_enqueue_buffer_[device] = std::make_unique<
+ bluetooth::os::EnqueueBuffer<bluetooth::packet::BasePacketBuilder>>(
+ channel->GetQueueUpEnd());
+ channel->GetQueueUpEnd()->RegisterDequeue(
+ bluetooth::shim::GetGdShimHandler(),
+ bluetooth::common::Bind(&ClassicDynamicChannelHelper::on_incoming_data,
+ bluetooth::common::Unretained(this), device));
+ channels_[device] = std::move(channel);
+
+ auto address = bluetooth::ToRawAddress(device.GetAddress());
+ if (initiated_by_us_[device]) {
+ auto cid_token = find_classic_cid_token_by_psm_address(psm_, address);
+ appl_info_.pL2CA_ConnectCfm_Cb(cid_token, 0);
+ } else {
+ if (appl_info_.pL2CA_ConnectInd_Cb == nullptr) {
+ Disconnect(device);
+ return;
+ }
+ auto cid_token = add_classic_cid_token_entry(psm_, address);
+ appl_info_.pL2CA_ConnectInd_Cb(address, cid_token, psm_, 0);
+ }
+ }
+
+ void on_incoming_data(bluetooth::hci::AddressWithType remote) {
+ auto channel = channels_.find(remote);
+ if (channel == channels_.end()) {
+ LOG_ERROR("Channel is not open");
+ return;
+ }
+ auto packet = channel->second->GetQueueUpEnd()->TryDequeue();
+ std::vector<uint8_t> packet_vector(packet->begin(), packet->end());
+ BT_HDR* buffer =
+ static_cast<BT_HDR*>(osi_calloc(packet_vector.size() + sizeof(BT_HDR)));
+ std::copy(packet_vector.begin(), packet_vector.end(), buffer->data);
+ buffer->len = packet_vector.size();
+ auto address = bluetooth::ToRawAddress(remote.GetAddress());
+ auto cid_token = find_classic_cid_token_by_psm_address(psm_, address);
+ appl_info_.pL2CA_DataInd_Cb(cid_token, buffer);
+ }
+
+ void on_outgoing_connection_fail(
+ classic::DynamicChannelManager::ConnectionResult result) {
+ LOG(ERROR) << "Outgoing connection failed";
+ }
+
+ bool send(AddressWithType remote,
+ std::unique_ptr<bluetooth::packet::BasePacketBuilder> packet) {
+ auto buffer = channel_enqueue_buffer_.find(remote);
+ if (buffer == channel_enqueue_buffer_.end() || buffer->second == nullptr) {
+ LOG(ERROR) << "Channel is not open";
+ return false;
+ }
+ buffer->second->Enqueue(std::move(packet),
+ bluetooth::shim::GetGdShimHandler());
+ return true;
+ }
+
+ std::unordered_map<AddressWithType, std::unique_ptr<classic::DynamicChannel>>
+ channels_;
+ std::unordered_map<AddressWithType,
+ std::unique_ptr<bluetooth::os::EnqueueBuffer<
+ bluetooth::packet::BasePacketBuilder>>>
+ channel_enqueue_buffer_;
+ std::unordered_map<AddressWithType, uint16_t> cid_map_;
+ std::unordered_map<AddressWithType, bool> initiated_by_us_;
+ std::unordered_map<AddressWithType, bool> disconnected_by_us_;
+};
+
+std::unordered_map<uint16_t, std::unique_ptr<ClassicDynamicChannelHelper>>
+ classic_dynamic_channel_helper_map_;
+
// Helper: L2cap security enforcement shim
std::unordered_map<intptr_t,
// LE COC Shim Helper
-uint16_t cid_token_counter_ = 1;
+uint16_t le_cid_token_counter_ = 1;
struct LeCocChannelInfo {
uint16_t psm;
RawAddress remote;
};
-std::unordered_map<uint16_t, LeCocChannelInfo> cid_token_to_channel_map_;
+std::unordered_map<uint16_t, LeCocChannelInfo> le_cid_token_to_channel_map_;
-uint16_t add_cid_token_entry(uint16_t psm, RawAddress remote) {
- uint16_t new_token = cid_token_counter_;
- cid_token_to_channel_map_[new_token] = {psm, remote};
- cid_token_counter_++;
- if (cid_token_counter_ == 0) cid_token_counter_++;
+uint16_t add_le_cid_token_entry(uint16_t psm, RawAddress remote) {
+ uint16_t new_token = le_cid_token_counter_;
+ le_cid_token_to_channel_map_[new_token] = {psm, remote};
+ le_cid_token_counter_++;
+ if (le_cid_token_counter_ == 0) le_cid_token_counter_++;
return new_token;
}
-void remove_cid_token_entry(uint16_t cid_token) {
- cid_token_to_channel_map_.erase(cid_token);
+void remove_le_cid_token_entry(uint16_t cid_token) {
+ le_cid_token_to_channel_map_.erase(cid_token);
}
-uint16_t find_cid_token_by_psm_address(uint16_t psm, RawAddress remote) {
- for (const auto& entry : cid_token_to_channel_map_) {
+uint16_t find_le_cid_token_by_psm_address(uint16_t psm, RawAddress remote) {
+ for (const auto& entry : le_cid_token_to_channel_map_) {
if (entry.second.psm == psm && entry.second.remote == remote) {
return entry.first;
}
channels_[device]->GetQueueUpEnd()->UnregisterDequeue();
channels_.erase(device);
auto address = bluetooth::ToRawAddress(device.GetAddress());
- auto cid_token = find_cid_token_by_psm_address(psm_, address);
+ auto cid_token = find_le_cid_token_by_psm_address(psm_, address);
(appl_info_.pL2CA_DisconnectInd_Cb)(cid_token, false);
- remove_cid_token_entry(cid_token);
+ remove_le_cid_token_entry(cid_token);
initiated_by_us_.erase(device);
if (channel_service_ == nullptr && channels_.empty()) {
auto address = bluetooth::ToRawAddress(device.GetAddress());
if (initiated_by_us_[device]) {
- auto cid_token = find_cid_token_by_psm_address(psm_, address);
+ auto cid_token = find_le_cid_token_by_psm_address(psm_, address);
appl_info_.pL2CA_ConnectCfm_Cb(cid_token, 0);
} else {
if (appl_info_.pL2CA_ConnectInd_Cb == nullptr) {
Disconnect(device);
return;
}
- auto cid_token = add_cid_token_entry(psm_, address);
+ auto cid_token = add_le_cid_token_entry(psm_, address);
appl_info_.pL2CA_ConnectInd_Cb(address, cid_token, psm_, 0);
}
}
std::copy(packet_vector.begin(), packet_vector.end(), buffer->data);
buffer->len = packet_vector.size();
auto address = bluetooth::ToRawAddress(remote.GetAddress());
- auto cid_token = find_cid_token_by_psm_address(psm_, address);
+ auto cid_token = find_le_cid_token_by_psm_address(psm_, address);
appl_info_.pL2CA_DataInd_Cb(cid_token, buffer);
}
}
le_dynamic_channel_helper_map_[psm]->Connect(
ToAddressWithType(p_bd_addr, Btm::GetAddressType(p_bd_addr)));
- return add_cid_token_entry(psm, p_bd_addr);
+ return add_le_cid_token_entry(psm, p_bd_addr);
}
bool bluetooth::shim::L2CA_GetPeerLECocConfig(uint16_t cid,
tL2CAP_LE_CFG_INFO* peer_cfg) {
- if (cid_token_to_channel_map_.count(cid) == 0) {
+ if (le_cid_token_to_channel_map_.count(cid) == 0) {
LOG(ERROR) << __func__ << "Invalid cid: " << cid;
return false;
}
- auto psm = cid_token_to_channel_map_[cid].psm;
- auto remote = cid_token_to_channel_map_[cid].remote;
+ auto psm = le_cid_token_to_channel_map_[cid].psm;
+ auto remote = le_cid_token_to_channel_map_[cid].remote;
if (le_dynamic_channel_helper_map_.count(psm) == 0) {
LOG(ERROR) << __func__ << "Not registered psm: " << psm;
return false;
}
bool bluetooth::shim::L2CA_DisconnectLECocReq(uint16_t cid) {
- if (cid_token_to_channel_map_.count(cid) == 0) {
+ if (le_cid_token_to_channel_map_.count(cid) == 0) {
LOG(ERROR) << __func__ << "Invalid cid: " << cid;
return false;
}
- auto psm = cid_token_to_channel_map_[cid].psm;
- auto remote = cid_token_to_channel_map_[cid].remote;
+ auto psm = le_cid_token_to_channel_map_[cid].psm;
+ auto remote = le_cid_token_to_channel_map_[cid].remote;
if (le_dynamic_channel_helper_map_.count(psm) == 0) {
LOG(ERROR) << __func__ << "Not registered psm: " << psm;
return false;
}
uint8_t bluetooth::shim::L2CA_LECocDataWrite(uint16_t cid, BT_HDR* p_data) {
- if (cid_token_to_channel_map_.count(cid) == 0) {
+ if (le_cid_token_to_channel_map_.count(cid) == 0) {
LOG(ERROR) << __func__ << "Invalid cid: " << cid;
return 0;
}
- auto psm = cid_token_to_channel_map_[cid].psm;
- auto remote = cid_token_to_channel_map_[cid].remote;
+ auto psm = le_cid_token_to_channel_map_[cid].psm;
+ auto remote = le_cid_token_to_channel_map_[cid].remote;
if (le_dynamic_channel_helper_map_.count(psm) == 0) {
LOG(ERROR) << __func__ << "Not registered psm: " << psm;
return 0;