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/vc/vc_shim.h"
18
19 #include <aics/api.h>
20 #include <bluetooth/log.h>
21 #include <hardware/bluetooth.h>
22
23 #include <string>
24
25 #include "src/profiles/vc.rs.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 VolumeControlIntf* g_vc_if;
36
to_rust_btvc_connection_state(vc::ConnectionState state)37 static BtVcConnectionState to_rust_btvc_connection_state(vc::ConnectionState state) {
38 switch (state) {
39 case vc::ConnectionState::DISCONNECTED:
40 return BtVcConnectionState::Disconnected;
41 case vc::ConnectionState::CONNECTING:
42 return BtVcConnectionState::Connecting;
43 case vc::ConnectionState::CONNECTED:
44 return BtVcConnectionState::Connected;
45 case vc::ConnectionState::DISCONNECTING:
46 return BtVcConnectionState::Disconnecting;
47 default:
48 log::assert_that(false, "Unhandled enum value from C++");
49 }
50 return BtVcConnectionState{};
51 }
52
connection_state_cb(vc::ConnectionState state,const RawAddress & address)53 static void connection_state_cb(vc::ConnectionState state, const RawAddress& address) {
54 vc_connection_state_callback(to_rust_btvc_connection_state(state), address);
55 }
56
volume_state_cb(const RawAddress & address,uint8_t volume,bool mute,bool is_autonomous)57 static void volume_state_cb(const RawAddress& address, uint8_t volume, bool mute,
58 bool is_autonomous) {
59 vc_volume_state_callback(address, volume, mute, is_autonomous);
60 }
61
group_volume_state_cb(int group_id,uint8_t volume,bool mute,bool is_autonomous)62 static void group_volume_state_cb(int group_id, uint8_t volume, bool mute, bool is_autonomous) {
63 vc_group_volume_state_callback(group_id, volume, mute, is_autonomous);
64 }
65
device_available_cb(const RawAddress & address,uint8_t num_offset)66 static void device_available_cb(const RawAddress& address, uint8_t num_offset) {
67 vc_device_available_callback(address, num_offset);
68 }
69
ext_audio_out_volume_offset_cb(const RawAddress & address,uint8_t ext_output_id,int16_t offset)70 static void ext_audio_out_volume_offset_cb(const RawAddress& address, uint8_t ext_output_id,
71 int16_t offset) {
72 vc_ext_audio_out_volume_offset_callback(address, ext_output_id, offset);
73 }
74
ext_audio_out_location_cb(const RawAddress & address,uint8_t ext_output_id,uint32_t location)75 static void ext_audio_out_location_cb(const RawAddress& address, uint8_t ext_output_id,
76 uint32_t location) {
77 vc_ext_audio_out_location_callback(address, ext_output_id, location);
78 }
79
ext_audio_out_description_cb(const RawAddress & address,uint8_t ext_output_id,std::string descr)80 static void ext_audio_out_description_cb(const RawAddress& address, uint8_t ext_output_id,
81 std::string descr) {
82 vc_ext_audio_out_description_callback(address, ext_output_id, descr);
83 }
84
85 } // namespace internal
86
87 class DBusVolumeControlCallbacks : public vc::VolumeControlCallbacks {
88 public:
GetInstance()89 static vc::VolumeControlCallbacks* GetInstance() {
90 static auto instance = new DBusVolumeControlCallbacks();
91 return instance;
92 }
93
DBusVolumeControlCallbacks()94 DBusVolumeControlCallbacks() {}
95
OnConnectionState(vc::ConnectionState state,const RawAddress & address)96 void OnConnectionState(vc::ConnectionState state, const RawAddress& address) override {
97 log::info("state={}, address={}", static_cast<int>(state), address);
98 topshim::rust::internal::connection_state_cb(state, address);
99 }
100
OnVolumeStateChanged(const RawAddress & address,uint8_t volume,bool mute,uint8_t flags,bool is_autonomous)101 void OnVolumeStateChanged(const RawAddress& address, uint8_t volume, bool mute, uint8_t flags,
102 bool is_autonomous) override {
103 log::info("address={}, volume={}, mute={}, flags={}, is_autonomous={}", address, volume, mute,
104 flags, is_autonomous);
105 topshim::rust::internal::volume_state_cb(address, volume, mute, is_autonomous);
106 }
107
OnGroupVolumeStateChanged(int group_id,uint8_t volume,bool mute,bool is_autonomous)108 void OnGroupVolumeStateChanged(int group_id, uint8_t volume, bool mute,
109 bool is_autonomous) override {
110 log::info("group_id={}, volume={}, mute={}, is_autonomous={}", group_id, volume, mute,
111 is_autonomous);
112 topshim::rust::internal::group_volume_state_cb(group_id, volume, mute, is_autonomous);
113 }
114
OnDeviceAvailable(const RawAddress & address,uint8_t num_offset,uint8_t num_inputs)115 void OnDeviceAvailable(const RawAddress& address, uint8_t num_offset,
116 uint8_t num_inputs) override {
117 log::info("address={}, num_offset={} num_inputs={}", address, num_offset, num_inputs);
118 topshim::rust::internal::device_available_cb(address, num_offset);
119 }
120
OnExtAudioOutVolumeOffsetChanged(const RawAddress & address,uint8_t ext_output_id,int16_t offset)121 void OnExtAudioOutVolumeOffsetChanged(const RawAddress& address, uint8_t ext_output_id,
122 int16_t offset) override {
123 log::info("address={}, ext_output_id={}, offset={}", address, ext_output_id, offset);
124 topshim::rust::internal::ext_audio_out_volume_offset_cb(address, ext_output_id, offset);
125 }
126
OnExtAudioOutLocationChanged(const RawAddress & address,uint8_t ext_output_id,uint32_t location)127 void OnExtAudioOutLocationChanged(const RawAddress& address, uint8_t ext_output_id,
128 uint32_t location) override {
129 log::info("address={}, ext_output_id, location={}", address, ext_output_id, location);
130 topshim::rust::internal::ext_audio_out_location_cb(address, ext_output_id, location);
131 }
132
OnExtAudioOutDescriptionChanged(const RawAddress & address,uint8_t ext_output_id,std::string descr)133 void OnExtAudioOutDescriptionChanged(const RawAddress& address, uint8_t ext_output_id,
134 std::string descr) override {
135 log::info("address={}, ext_output_id={}, descr={}", address, ext_output_id, descr.c_str());
136 topshim::rust::internal::ext_audio_out_description_cb(address, ext_output_id, descr);
137 }
138
OnExtAudioInStateChanged(const RawAddress & address,uint8_t ext_input_id,int8_t gain_setting,bluetooth::aics::Mute mute,bluetooth::aics::GainMode gain_mode)139 void OnExtAudioInStateChanged(const RawAddress& address, uint8_t ext_input_id,
140 int8_t gain_setting, bluetooth::aics::Mute mute,
141 bluetooth::aics::GainMode gain_mode) {
142 log::info("address={}, ext_input_id={}, gain_setting={}, mute={:#x}, gain_mode={:#x}", address,
143 ext_input_id, gain_setting, mute, gain_mode);
144 log::info("Not implemented");
145 }
146
OnExtAudioInSetGainSettingFailed(const RawAddress & address,uint8_t ext_input_id)147 void OnExtAudioInSetGainSettingFailed(const RawAddress& address, uint8_t ext_input_id) {
148 log::info("address={}, ext_input_id={}", address, ext_input_id);
149 log::info("Not implemented");
150 }
151
OnExtAudioInSetMuteFailed(const RawAddress & address,uint8_t ext_input_id)152 void OnExtAudioInSetMuteFailed(const RawAddress& address, uint8_t ext_input_id) {
153 log::info("address={}, ext_input_id={}", address, ext_input_id);
154 log::info("Not implemented");
155 }
156
OnExtAudioInSetGainModeFailed(const RawAddress & address,uint8_t ext_input_id)157 void OnExtAudioInSetGainModeFailed(const RawAddress& address, uint8_t ext_input_id) {
158 log::info("address={}, ext_input_id={}", address, ext_input_id);
159 log::info("Not implemented");
160 }
161
OnExtAudioInStatusChanged(const RawAddress & address,uint8_t ext_input_id,bluetooth::vc::VolumeInputStatus status)162 void OnExtAudioInStatusChanged(const RawAddress& address, uint8_t ext_input_id,
163 bluetooth::vc::VolumeInputStatus status) {
164 log::info("address={}, ext_input_id={}, status={}", address, ext_input_id, status);
165 log::info("Not implemented");
166 }
OnExtAudioInTypeChanged(const RawAddress & address,uint8_t ext_input_id,bluetooth::vc::VolumeInputType type)167 void OnExtAudioInTypeChanged(const RawAddress& address, uint8_t ext_input_id,
168 bluetooth::vc::VolumeInputType type) {
169 log::info("address={}, ext_input_id={}, type={}", address, ext_input_id, type);
170 log::info("Not implemented");
171 }
172
OnExtAudioInGainSettingPropertiesChanged(const RawAddress & address,uint8_t ext_input_id,uint8_t unit,int8_t min,int8_t max)173 void OnExtAudioInGainSettingPropertiesChanged(const RawAddress& address, uint8_t ext_input_id,
174 uint8_t unit, int8_t min, int8_t max) {
175 log::info("address={}, ext_input_id={}, unit={}, min={}, max={}", address, ext_input_id, unit,
176 min, max);
177 log::info("Not implemented");
178 }
179
OnExtAudioInDescriptionChanged(const RawAddress & address,uint8_t ext_input_id,std::string description,bool is_writable)180 void OnExtAudioInDescriptionChanged(const RawAddress& address, uint8_t ext_input_id,
181 std::string description, bool is_writable) {
182 log::info("address={}, ext_input_id={}, description={}, is_writable={}", address, ext_input_id,
183 description, is_writable);
184 log::info("Not implemented");
185 }
186 };
187
GetVolumeControlProfile(const unsigned char * btif)188 std::unique_ptr<VolumeControlIntf> GetVolumeControlProfile(const unsigned char* btif) {
189 if (internal::g_vc_if) {
190 std::abort();
191 }
192
193 const bt_interface_t* btif_ = reinterpret_cast<const bt_interface_t*>(btif);
194
195 auto vc_if = std::make_unique<VolumeControlIntf>(const_cast<vc::VolumeControlInterface*>(
196 reinterpret_cast<const vc::VolumeControlInterface*>(
197 btif_->get_profile_interface("volume_control"))));
198
199 internal::g_vc_if = vc_if.get();
200
201 return vc_if;
202 }
203
init()204 void VolumeControlIntf::init(/*VolumeControlCallbacks* callbacks*/) {
205 return intf_->Init(DBusVolumeControlCallbacks::GetInstance());
206 }
207
cleanup()208 void VolumeControlIntf::cleanup() { return intf_->Cleanup(); }
209
connect(RawAddress addr)210 void VolumeControlIntf::connect(RawAddress addr) { return intf_->Connect(addr); }
211
disconnect(RawAddress addr)212 void VolumeControlIntf::disconnect(RawAddress addr) { return intf_->Disconnect(addr); }
213
remove_device(RawAddress addr)214 void VolumeControlIntf::remove_device(RawAddress addr) { return intf_->RemoveDevice(addr); }
215
set_volume(int group_id,uint8_t volume)216 void VolumeControlIntf::set_volume(int group_id, uint8_t volume) {
217 return intf_->SetVolume(group_id, volume);
218 }
219
mute(RawAddress addr)220 void VolumeControlIntf::mute(RawAddress addr) { return intf_->Mute(addr); }
221
unmute(RawAddress addr)222 void VolumeControlIntf::unmute(RawAddress addr) { return intf_->Unmute(addr); }
223
get_ext_audio_out_volume_offset(RawAddress addr,uint8_t ext_output_id)224 void VolumeControlIntf::get_ext_audio_out_volume_offset(RawAddress addr, uint8_t ext_output_id) {
225 return intf_->GetExtAudioOutVolumeOffset(addr, ext_output_id);
226 }
227
set_ext_audio_out_volume_offset(RawAddress addr,uint8_t ext_output_id,int16_t offset_val)228 void VolumeControlIntf::set_ext_audio_out_volume_offset(RawAddress addr, uint8_t ext_output_id,
229 int16_t offset_val) {
230 return intf_->SetExtAudioOutVolumeOffset(addr, ext_output_id, offset_val);
231 }
232
get_ext_audio_out_location(RawAddress addr,uint8_t ext_output_id)233 void VolumeControlIntf::get_ext_audio_out_location(RawAddress addr, uint8_t ext_output_id) {
234 return intf_->GetExtAudioOutLocation(addr, ext_output_id);
235 }
236
set_ext_audio_out_location(RawAddress addr,uint8_t ext_output_id,uint32_t location)237 void VolumeControlIntf::set_ext_audio_out_location(RawAddress addr, uint8_t ext_output_id,
238 uint32_t location) {
239 return intf_->SetExtAudioOutLocation(addr, ext_output_id, location);
240 }
241
get_ext_audio_out_description(RawAddress addr,uint8_t ext_output_id)242 void VolumeControlIntf::get_ext_audio_out_description(RawAddress addr, uint8_t ext_output_id) {
243 return intf_->GetExtAudioOutDescription(addr, ext_output_id);
244 }
245
set_ext_audio_out_description(RawAddress addr,uint8_t ext_output_id,const char * descr)246 void VolumeControlIntf::set_ext_audio_out_description(RawAddress addr, uint8_t ext_output_id,
247 const char* descr) {
248 return intf_->SetExtAudioOutDescription(addr, ext_output_id, std::string(descr));
249 }
250 } // namespace rust
251 } // namespace topshim
252 } // namespace bluetooth
253