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