| /* |
| * Copyright (C) 2024 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| #include "topshim/csis/csis_shim.h" |
| |
| #include <bluetooth/log.h> |
| #include <bluetooth/types/uuid.h> |
| #include <hardware/bluetooth.h> |
| |
| #include <string> |
| |
| #include "src/profiles/csis.rs.h" |
| #include "types/raw_address.h" |
| |
| namespace rusty = ::bluetooth::topshim::rust; |
| |
| namespace bluetooth { |
| namespace topshim { |
| namespace rust { |
| namespace internal { |
| |
| static CsisClientIntf* g_csis_if; |
| |
| static BtCsisConnectionState to_rust_btcsis_connection_state(csis::ConnectionState state) { |
| switch (state) { |
| case csis::ConnectionState::DISCONNECTED: |
| return BtCsisConnectionState::Disconnected; |
| case csis::ConnectionState::CONNECTING: |
| return BtCsisConnectionState::Connecting; |
| case csis::ConnectionState::CONNECTED: |
| return BtCsisConnectionState::Connected; |
| case csis::ConnectionState::DISCONNECTING: |
| return BtCsisConnectionState::Disconnecting; |
| default: |
| log::assert_that(false, "Unhandled enum value from C++"); |
| } |
| return BtCsisConnectionState{}; |
| } |
| |
| static BtCsisGroupLockStatus to_rust_btcsis_group_lock_status(csis::CsisGroupLockStatus status) { |
| switch (status) { |
| case csis::CsisGroupLockStatus::SUCCESS: |
| return BtCsisGroupLockStatus::Success; |
| case csis::CsisGroupLockStatus::FAILED_INVALID_GROUP: |
| return BtCsisGroupLockStatus::FailedInvalidGroup; |
| case csis::CsisGroupLockStatus::FAILED_GROUP_EMPTY: |
| return BtCsisGroupLockStatus::FailedGroupEmpty; |
| case csis::CsisGroupLockStatus::FAILED_GROUP_NOT_CONNECTED: |
| return BtCsisGroupLockStatus::FailedGroupNotConnected; |
| case csis::CsisGroupLockStatus::FAILED_LOCKED_BY_OTHER: |
| return BtCsisGroupLockStatus::FailedLockedByOther; |
| case csis::CsisGroupLockStatus::FAILED_OTHER_REASON: |
| return BtCsisGroupLockStatus::FailedOtherReason; |
| case csis::CsisGroupLockStatus::LOCKED_GROUP_MEMBER_LOST: |
| return BtCsisGroupLockStatus::LockedGroupMemberLost; |
| default: |
| log::assert_that(false, "Unhandled enum value from C++"); |
| } |
| return BtCsisGroupLockStatus{}; |
| } |
| |
| static void connection_state_cb(const RawAddress& addr, csis::ConnectionState state) { |
| csis_connection_state_callback(addr, to_rust_btcsis_connection_state(state)); |
| } |
| |
| static void device_available_cb(const RawAddress& addr, int group_id, int group_size, int rank, |
| const bluetooth::Uuid& uuid) { |
| csis_device_available_callback(addr, group_id, group_size, rank, uuid); |
| } |
| |
| static void set_member_available_cb(const RawAddress& addr, int group_id) { |
| csis_set_member_available_callback(addr, group_id); |
| } |
| |
| static void group_lock_changed_cb(int group_id, bool locked, csis::CsisGroupLockStatus status) { |
| csis_group_lock_changed_callback(group_id, locked, to_rust_btcsis_group_lock_status(status)); |
| } |
| } // namespace internal |
| |
| class DBusCsisClientCallbacks : public csis::CsisClientCallbacks { |
| public: |
| static csis::CsisClientCallbacks* GetInstance() { |
| static auto instance = new DBusCsisClientCallbacks(); |
| return instance; |
| } |
| |
| DBusCsisClientCallbacks() {} |
| |
| void OnConnectionState(const RawAddress& addr, csis::ConnectionState state) override { |
| log::info("addr={}, state={}", addr, static_cast<uint8_t>(state)); |
| topshim::rust::internal::connection_state_cb(addr, state); |
| } |
| |
| void OnDeviceAvailable(const RawAddress& addr, int group_id, int group_size, int rank, |
| const bluetooth::Uuid& uuid) override { |
| log::info("addr={}, group_id={}, group_size={}, rank={}", addr, group_id, group_size, rank); |
| topshim::rust::internal::device_available_cb(addr, group_id, group_size, rank, uuid); |
| } |
| |
| void OnSetMemberAvailable(const RawAddress& addr, int group_id) { |
| log::info("addr={}, group_id={}", addr, group_id); |
| topshim::rust::internal::set_member_available_cb(addr, group_id); |
| } |
| |
| void OnGroupLockChanged(int group_id, bool locked, csis::CsisGroupLockStatus status) { |
| topshim::rust::internal::group_lock_changed_cb(group_id, locked, status); |
| } |
| }; |
| |
| std::unique_ptr<CsisClientIntf> GetCsisClientProfile(const unsigned char* btif) { |
| if (internal::g_csis_if) { |
| std::abort(); |
| } |
| |
| const bt_interface_t* btif_ = reinterpret_cast<const bt_interface_t*>(btif); |
| |
| auto csis_if = std::make_unique<CsisClientIntf>( |
| const_cast<csis::CsisClientInterface*>(reinterpret_cast<const csis::CsisClientInterface*>( |
| btif_->get_profile_interface("csis_client")))); |
| |
| internal::g_csis_if = csis_if.get(); |
| |
| return csis_if; |
| } |
| |
| void CsisClientIntf::init(/*CsisClientCallbacks* callbacks*/) { |
| return intf_->Init(DBusCsisClientCallbacks::GetInstance()); |
| } |
| |
| void CsisClientIntf::connect(RawAddress addr) { return intf_->Connect(addr); } |
| |
| void CsisClientIntf::disconnect(RawAddress addr) { return intf_->Disconnect(addr); } |
| |
| void CsisClientIntf::lock_group(int group_id, bool lock) { |
| return intf_->LockGroup(group_id, lock); |
| } |
| |
| void CsisClientIntf::remove_device(RawAddress addr) { return intf_->RemoveDevice(addr); } |
| |
| void CsisClientIntf::cleanup() { return intf_->Cleanup(); } |
| } // namespace rust |
| } // namespace topshim |
| } // namespace bluetooth |