1 /*
2 * Copyright (C) 2024 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
17 #include "gd/rust/topshim/csis/csis_shim.h"
18
19 #include <bluetooth/log.h>
20 #include <hardware/bluetooth.h>
21
22 #include <string>
23
24 #include "src/profiles/csis.rs.h"
25 #include "types/bluetooth/uuid.h"
26 #include "types/raw_address.h"
27
28 namespace rusty = ::bluetooth::topshim::rust;
29
30 namespace bluetooth {
31 namespace topshim {
32 namespace rust {
33 namespace internal {
34
35 static CsisClientIntf* g_csis_if;
36
to_rust_btcsis_connection_state(csis::ConnectionState state)37 static BtCsisConnectionState to_rust_btcsis_connection_state(csis::ConnectionState state) {
38 switch (state) {
39 case csis::ConnectionState::DISCONNECTED:
40 return BtCsisConnectionState::Disconnected;
41 case csis::ConnectionState::CONNECTING:
42 return BtCsisConnectionState::Connecting;
43 case csis::ConnectionState::CONNECTED:
44 return BtCsisConnectionState::Connected;
45 case csis::ConnectionState::DISCONNECTING:
46 return BtCsisConnectionState::Disconnecting;
47 default:
48 log::assert_that(false, "Unhandled enum value from C++");
49 }
50 return BtCsisConnectionState{};
51 }
52
to_rust_btcsis_group_lock_status(csis::CsisGroupLockStatus status)53 static BtCsisGroupLockStatus to_rust_btcsis_group_lock_status(csis::CsisGroupLockStatus status) {
54 switch (status) {
55 case csis::CsisGroupLockStatus::SUCCESS:
56 return BtCsisGroupLockStatus::Success;
57 case csis::CsisGroupLockStatus::FAILED_INVALID_GROUP:
58 return BtCsisGroupLockStatus::FailedInvalidGroup;
59 case csis::CsisGroupLockStatus::FAILED_GROUP_EMPTY:
60 return BtCsisGroupLockStatus::FailedGroupEmpty;
61 case csis::CsisGroupLockStatus::FAILED_GROUP_NOT_CONNECTED:
62 return BtCsisGroupLockStatus::FailedGroupNotConnected;
63 case csis::CsisGroupLockStatus::FAILED_LOCKED_BY_OTHER:
64 return BtCsisGroupLockStatus::FailedLockedByOther;
65 case csis::CsisGroupLockStatus::FAILED_OTHER_REASON:
66 return BtCsisGroupLockStatus::FailedOtherReason;
67 case csis::CsisGroupLockStatus::LOCKED_GROUP_MEMBER_LOST:
68 return BtCsisGroupLockStatus::LockedGroupMemberLost;
69 default:
70 log::assert_that(false, "Unhandled enum value from C++");
71 }
72 return BtCsisGroupLockStatus{};
73 }
74
connection_state_cb(const RawAddress & addr,csis::ConnectionState state)75 static void connection_state_cb(const RawAddress& addr, csis::ConnectionState state) {
76 csis_connection_state_callback(addr, to_rust_btcsis_connection_state(state));
77 }
78
device_available_cb(const RawAddress & addr,int group_id,int group_size,int rank,const bluetooth::Uuid & uuid)79 static void device_available_cb(const RawAddress& addr, int group_id, int group_size, int rank,
80 const bluetooth::Uuid& uuid) {
81 csis_device_available_callback(addr, group_id, group_size, rank, uuid);
82 }
83
set_member_available_cb(const RawAddress & addr,int group_id)84 static void set_member_available_cb(const RawAddress& addr, int group_id) {
85 csis_set_member_available_callback(addr, group_id);
86 }
87
group_lock_changed_cb(int group_id,bool locked,csis::CsisGroupLockStatus status)88 static void group_lock_changed_cb(int group_id, bool locked, csis::CsisGroupLockStatus status) {
89 csis_group_lock_changed_callback(group_id, locked, to_rust_btcsis_group_lock_status(status));
90 }
91 } // namespace internal
92
93 class DBusCsisClientCallbacks : public csis::CsisClientCallbacks {
94 public:
GetInstance()95 static csis::CsisClientCallbacks* GetInstance() {
96 static auto instance = new DBusCsisClientCallbacks();
97 return instance;
98 }
99
DBusCsisClientCallbacks()100 DBusCsisClientCallbacks() {}
101
OnConnectionState(const RawAddress & addr,csis::ConnectionState state)102 void OnConnectionState(const RawAddress& addr, csis::ConnectionState state) override {
103 log::info("addr={}, state={}", addr, static_cast<uint8_t>(state));
104 topshim::rust::internal::connection_state_cb(addr, state);
105 }
106
OnDeviceAvailable(const RawAddress & addr,int group_id,int group_size,int rank,const bluetooth::Uuid & uuid)107 void OnDeviceAvailable(const RawAddress& addr, int group_id, int group_size, int rank,
108 const bluetooth::Uuid& uuid) override {
109 log::info("addr={}, group_id={}, group_size={}, rank={}", addr, group_id, group_size, rank);
110 topshim::rust::internal::device_available_cb(addr, group_id, group_size, rank, uuid);
111 }
112
OnSetMemberAvailable(const RawAddress & addr,int group_id)113 void OnSetMemberAvailable(const RawAddress& addr, int group_id) {
114 log::info("addr={}, group_id={}", addr, group_id);
115 topshim::rust::internal::set_member_available_cb(addr, group_id);
116 }
117
OnGroupLockChanged(int group_id,bool locked,csis::CsisGroupLockStatus status)118 void OnGroupLockChanged(int group_id, bool locked, csis::CsisGroupLockStatus status) {
119 topshim::rust::internal::group_lock_changed_cb(group_id, locked, status);
120 }
121 };
122
GetCsisClientProfile(const unsigned char * btif)123 std::unique_ptr<CsisClientIntf> GetCsisClientProfile(const unsigned char* btif) {
124 if (internal::g_csis_if) {
125 std::abort();
126 }
127
128 const bt_interface_t* btif_ = reinterpret_cast<const bt_interface_t*>(btif);
129
130 auto csis_if = std::make_unique<CsisClientIntf>(
131 const_cast<csis::CsisClientInterface*>(reinterpret_cast<const csis::CsisClientInterface*>(
132 btif_->get_profile_interface("csis_client"))));
133
134 internal::g_csis_if = csis_if.get();
135
136 return csis_if;
137 }
138
init()139 void CsisClientIntf::init(/*CsisClientCallbacks* callbacks*/) {
140 return intf_->Init(DBusCsisClientCallbacks::GetInstance());
141 }
142
connect(RawAddress addr)143 void CsisClientIntf::connect(RawAddress addr) { return intf_->Connect(addr); }
144
disconnect(RawAddress addr)145 void CsisClientIntf::disconnect(RawAddress addr) { return intf_->Disconnect(addr); }
146
lock_group(int group_id,bool lock)147 void CsisClientIntf::lock_group(int group_id, bool lock) {
148 return intf_->LockGroup(group_id, lock);
149 }
150
remove_device(RawAddress addr)151 void CsisClientIntf::remove_device(RawAddress addr) { return intf_->RemoveDevice(addr); }
152
cleanup()153 void CsisClientIntf::cleanup() { return intf_->Cleanup(); }
154 } // namespace rust
155 } // namespace topshim
156 } // namespace bluetooth
157