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