• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #ifndef foobluez5utilhfoo
2 #define foobluez5utilhfoo
3 
4 /***
5   This file is part of PulseAudio.
6 
7   Copyright 2008-2013 João Paulo Rechi Vita
8   Copyrigth 2018-2019 Pali Rohár <pali.rohar@gmail.com>
9 
10   PulseAudio is free software; you can redistribute it and/or modify
11   it under the terms of the GNU Lesser General Public License as
12   published by the Free Software Foundation; either version 2.1 of the
13   License, or (at your option) any later version.
14 
15   PulseAudio is distributed in the hope that it will be useful, but
16   WITHOUT ANY WARRANTY; without even the implied warranty of
17   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18   General Public License for more details.
19 
20   You should have received a copy of the GNU Lesser General Public
21   License along with PulseAudio; if not, see <http://www.gnu.org/licenses/>.
22 ***/
23 
24 #include <pulsecore/core.h>
25 
26 #include "a2dp-codec-util.h"
27 
28 #define BLUEZ_SERVICE "org.bluez"
29 #define BLUEZ_ADAPTER_INTERFACE BLUEZ_SERVICE ".Adapter1"
30 #define BLUEZ_BATTERY_PROVIDER_INTERFACE BLUEZ_SERVICE ".BatteryProvider1"
31 #define BLUEZ_BATTERY_PROVIDER_MANAGER_INTERFACE BLUEZ_SERVICE ".BatteryProviderManager1"
32 #define BLUEZ_DEVICE_INTERFACE BLUEZ_SERVICE ".Device1"
33 #define BLUEZ_MEDIA_ENDPOINT_INTERFACE BLUEZ_SERVICE ".MediaEndpoint1"
34 #define BLUEZ_MEDIA_INTERFACE BLUEZ_SERVICE ".Media1"
35 #define BLUEZ_MEDIA_TRANSPORT_INTERFACE BLUEZ_SERVICE ".MediaTransport1"
36 #define BLUEZ_PROFILE_INTERFACE BLUEZ_SERVICE ".Profile1"
37 #define BLUEZ_PROFILE_MANAGER_INTERFACE BLUEZ_SERVICE ".ProfileManager1"
38 
39 #define BLUEZ_ERROR_INVALID_ARGUMENTS BLUEZ_SERVICE ".Error.InvalidArguments"
40 #define BLUEZ_ERROR_NOT_AVAILABLE BLUEZ_SERVICE ".Error.NotAvailable"
41 #define BLUEZ_ERROR_NOT_SUPPORTED BLUEZ_SERVICE ".Error.NotSupported"
42 
43 #define PA_BLUETOOTH_UUID_A2DP_SOURCE "0000110a-0000-1000-8000-00805f9b34fb"
44 #define PA_BLUETOOTH_UUID_A2DP_SINK   "0000110b-0000-1000-8000-00805f9b34fb"
45 
46 /* There are two HSP HS UUIDs. The first one (older?) is used both as the HSP
47  * profile identifier and as the HS role identifier, while the second one is
48  * only used to identify the role. As far as PulseAudio is concerned, the two
49  * UUIDs mean exactly the same thing. */
50 #define PA_BLUETOOTH_UUID_HSP_HS      "00001108-0000-1000-8000-00805f9b34fb"
51 #define PA_BLUETOOTH_UUID_HSP_HS_ALT  "00001131-0000-1000-8000-00805f9b34fb"
52 
53 #define PA_BLUETOOTH_UUID_HSP_AG      "00001112-0000-1000-8000-00805f9b34fb"
54 #define PA_BLUETOOTH_UUID_HFP_HF      "0000111e-0000-1000-8000-00805f9b34fb"
55 #define PA_BLUETOOTH_UUID_HFP_AG      "0000111f-0000-1000-8000-00805f9b34fb"
56 
57 #define A2DP_MAX_GAIN 127
58 #define HSP_MAX_GAIN 15
59 
60 typedef struct pa_bluetooth_transport pa_bluetooth_transport;
61 typedef struct pa_bluetooth_device pa_bluetooth_device;
62 typedef struct pa_bluetooth_adapter pa_bluetooth_adapter;
63 typedef struct pa_bluetooth_discovery pa_bluetooth_discovery;
64 typedef struct pa_bluetooth_backend pa_bluetooth_backend;
65 typedef struct pa_upower_backend pa_upower_backend;
66 
67 typedef enum pa_bluetooth_hook {
68     PA_BLUETOOTH_HOOK_ADAPTER_UUIDS_CHANGED,            /* Call data: pa_bluetooth_adapter */
69     PA_BLUETOOTH_HOOK_DEVICE_CONNECTION_CHANGED,        /* Call data: pa_bluetooth_device */
70     PA_BLUETOOTH_HOOK_DEVICE_UNLINK,                    /* Call data: pa_bluetooth_device */
71     PA_BLUETOOTH_HOOK_DEVICE_BATTERY_LEVEL_CHANGED,     /* Call data: pa_bluetooth_device */
72     PA_BLUETOOTH_HOOK_HOST_BATTERY_LEVEL_CHANGED,       /* Call data: pa_upower_backend */
73     PA_BLUETOOTH_HOOK_TRANSPORT_STATE_CHANGED,          /* Call data: pa_bluetooth_transport */
74     PA_BLUETOOTH_HOOK_TRANSPORT_SOURCE_VOLUME_CHANGED,  /* Call data: pa_bluetooth_transport */
75     PA_BLUETOOTH_HOOK_TRANSPORT_SINK_VOLUME_CHANGED,    /* Call data: pa_bluetooth_transport */
76     PA_BLUETOOTH_HOOK_MAX
77 } pa_bluetooth_hook_t;
78 
79 typedef enum profile {
80     PA_BLUETOOTH_PROFILE_A2DP_SINK,
81     PA_BLUETOOTH_PROFILE_A2DP_SOURCE,
82     PA_BLUETOOTH_PROFILE_HSP_HS,
83     PA_BLUETOOTH_PROFILE_HSP_AG,
84     PA_BLUETOOTH_PROFILE_HFP_HF,
85     PA_BLUETOOTH_PROFILE_HFP_AG,
86     PA_BLUETOOTH_PROFILE_OFF
87 } pa_bluetooth_profile_t;
88 #define PA_BLUETOOTH_PROFILE_COUNT PA_BLUETOOTH_PROFILE_OFF
89 
90 typedef enum pa_bluetooth_profile_status {
91   PA_BLUETOOTH_PROFILE_STATUS_INACTIVE,
92   PA_BLUETOOTH_PROFILE_STATUS_ACTIVE,
93   PA_BLUETOOTH_PROFILE_STATUS_REGISTERING,
94   PA_BLUETOOTH_PROFILE_STATUS_REGISTERED
95 } pa_bluetooth_profile_status_t;
96 
97 typedef enum pa_bluetooth_transport_state {
98     PA_BLUETOOTH_TRANSPORT_STATE_DISCONNECTED,
99     PA_BLUETOOTH_TRANSPORT_STATE_IDLE,
100     PA_BLUETOOTH_TRANSPORT_STATE_PLAYING
101 } pa_bluetooth_transport_state_t;
102 
103 typedef int (*pa_bluetooth_transport_acquire_cb)(pa_bluetooth_transport *t, bool optional, size_t *imtu, size_t *omtu);
104 typedef void (*pa_bluetooth_transport_release_cb)(pa_bluetooth_transport *t);
105 typedef void (*pa_bluetooth_transport_destroy_cb)(pa_bluetooth_transport *t);
106 typedef pa_volume_t (*pa_bluetooth_transport_set_volume_cb)(pa_bluetooth_transport *t, pa_volume_t volume);
107 typedef ssize_t (*pa_bluetooth_transport_write_cb)(pa_bluetooth_transport *t, int fd, const void* buffer, size_t size, size_t write_mtu);
108 typedef int (*pa_bluetooth_transport_setsockopt_cb)(pa_bluetooth_transport *t, int fd);
109 
110 struct pa_bluetooth_transport {
111     pa_bluetooth_device *device;
112 
113     char *owner;
114     char *path;
115     pa_bluetooth_profile_t profile;
116 
117     void *config;
118     size_t config_size;
119 
120     const pa_bt_codec *bt_codec;
121     int stream_write_type;
122     size_t last_read_size;
123 
124     pa_volume_t source_volume;
125     pa_volume_t sink_volume;
126 
127     pa_bluetooth_transport_state_t state;
128 
129     pa_bluetooth_transport_acquire_cb acquire;
130     pa_bluetooth_transport_release_cb release;
131     pa_bluetooth_transport_write_cb write;
132     pa_bluetooth_transport_setsockopt_cb setsockopt;
133     pa_bluetooth_transport_destroy_cb destroy;
134     pa_bluetooth_transport_set_volume_cb set_sink_volume;
135     pa_bluetooth_transport_set_volume_cb set_source_volume;
136     void *userdata;
137 };
138 
139 struct pa_bluetooth_device {
140     pa_bluetooth_discovery *discovery;
141     pa_bluetooth_adapter *adapter;
142 
143     bool enable_hfp_hf;
144     bool properties_received;
145     bool tried_to_link_with_adapter;
146     bool valid;
147     bool autodetect_mtu;
148     bool codec_switching_in_progress;
149     bool avrcp_absolute_volume;
150     uint32_t output_rate_refresh_interval_ms;
151 
152     /* Device information */
153     char *path;
154     char *adapter_path;
155     char *alias;
156     char *address;
157     uint32_t class_of_device;
158     pa_hashmap *uuids; /* char* -> char* (hashmap-as-a-set) */
159     /* pa_a2dp_codec_id* -> pa_hashmap ( char* (remote endpoint) -> struct a2dp_codec_capabilities* ) */
160     pa_hashmap *a2dp_sink_endpoints;
161     pa_hashmap *a2dp_source_endpoints;
162 
163     pa_bluetooth_transport *transports[PA_BLUETOOTH_PROFILE_COUNT];
164 
165     pa_time_event *wait_for_profiles_timer;
166 
167     bool has_battery_level;
168     uint8_t battery_level;
169     const char *battery_source;
170 };
171 
172 struct pa_bluetooth_adapter {
173     pa_bluetooth_discovery *discovery;
174     char *path;
175     char *address;
176     pa_hashmap *uuids; /* char* -> char* (hashmap-as-a-set) */
177 
178     bool valid;
179     bool application_registered;
180     bool battery_provider_registered;
181 };
182 
183 #ifdef HAVE_BLUEZ_5_OFONO_HEADSET
184 pa_bluetooth_backend *pa_bluetooth_ofono_backend_new(pa_core *c, pa_bluetooth_discovery *y);
185 void pa_bluetooth_ofono_backend_free(pa_bluetooth_backend *b);
186 #else
pa_bluetooth_ofono_backend_new(pa_core * c,pa_bluetooth_discovery * y)187 static inline pa_bluetooth_backend *pa_bluetooth_ofono_backend_new(pa_core *c, pa_bluetooth_discovery *y) {
188     return NULL;
189 }
pa_bluetooth_ofono_backend_free(pa_bluetooth_backend * b)190 static inline void pa_bluetooth_ofono_backend_free(pa_bluetooth_backend *b) {}
191 #endif
192 
193 #ifdef HAVE_BLUEZ_5_NATIVE_HEADSET
194 pa_bluetooth_backend *pa_bluetooth_native_backend_new(pa_core *c, pa_bluetooth_discovery *y, bool enable_shared_profiles);
195 void pa_bluetooth_native_backend_free(pa_bluetooth_backend *b);
196 void pa_bluetooth_native_backend_enable_shared_profiles(pa_bluetooth_backend *b, bool enable);
197 #else
pa_bluetooth_native_backend_new(pa_core * c,pa_bluetooth_discovery * y,bool enable_shared_profiles)198 static inline pa_bluetooth_backend *pa_bluetooth_native_backend_new(pa_core *c, pa_bluetooth_discovery *y, bool enable_shared_profiles) {
199     return NULL;
200 }
pa_bluetooth_native_backend_free(pa_bluetooth_backend * b)201 static inline void pa_bluetooth_native_backend_free(pa_bluetooth_backend *b) {}
pa_bluetooth_native_backend_enable_shared_profiles(pa_bluetooth_backend * b,bool enable)202 static inline void pa_bluetooth_native_backend_enable_shared_profiles(pa_bluetooth_backend *b, bool enable) {}
203 #endif
204 
205 pa_bluetooth_profile_status_t profile_status_get(pa_bluetooth_discovery *y, pa_bluetooth_profile_t profile);
206 void profile_status_set(pa_bluetooth_discovery *y, pa_bluetooth_profile_t profile, pa_bluetooth_profile_status_t status);
207 
208 pa_bluetooth_transport *pa_bluetooth_transport_new(pa_bluetooth_device *d, const char *owner, const char *path,
209                                                    pa_bluetooth_profile_t p, const uint8_t *config, size_t size);
210 
211 void pa_bluetooth_transport_reconfigure(pa_bluetooth_transport *t, const pa_bt_codec *bt_codec,
212                                         pa_bluetooth_transport_write_cb write_cb, pa_bluetooth_transport_setsockopt_cb setsockopt_cb);
213 
214 void pa_bluetooth_transport_set_state(pa_bluetooth_transport *t, pa_bluetooth_transport_state_t state);
215 void pa_bluetooth_transport_put(pa_bluetooth_transport *t);
216 void pa_bluetooth_transport_unlink(pa_bluetooth_transport *t);
217 void pa_bluetooth_transport_free(pa_bluetooth_transport *t);
218 void pa_bluetooth_transport_load_a2dp_sink_volume(pa_bluetooth_transport *t);
219 
220 bool pa_bluetooth_device_supports_profile(const pa_bluetooth_device *device, pa_bluetooth_profile_t profile);
221 bool pa_bluetooth_device_any_transport_connected(const pa_bluetooth_device *d);
222 bool pa_bluetooth_device_switch_codec(pa_bluetooth_device *device, pa_bluetooth_profile_t profile, pa_hashmap *capabilities_hashmap, const pa_a2dp_endpoint_conf *endpoint_conf, void (*codec_switch_cb)(bool, pa_bluetooth_profile_t profile, void *), void *userdata);
223 void pa_bluetooth_device_report_battery_level(pa_bluetooth_device *d, uint8_t level, const char *reporting_source);
224 void pa_bluetooth_device_deregister_battery(pa_bluetooth_device *d);
225 
226 pa_bluetooth_device* pa_bluetooth_discovery_get_device_by_path(pa_bluetooth_discovery *y, const char *path);
227 pa_bluetooth_device* pa_bluetooth_discovery_get_device_by_address(pa_bluetooth_discovery *y, const char *remote, const char *local);
228 
229 pa_hook* pa_bluetooth_discovery_hook(pa_bluetooth_discovery *y, pa_bluetooth_hook_t hook);
230 
231 const char *pa_bluetooth_profile_to_string(pa_bluetooth_profile_t profile);
232 bool pa_bluetooth_profile_should_attenuate_volume(pa_bluetooth_profile_t profile);
233 bool pa_bluetooth_profile_is_a2dp(pa_bluetooth_profile_t profile);
234 
pa_bluetooth_uuid_is_hsp_hs(const char * uuid)235 static inline bool pa_bluetooth_uuid_is_hsp_hs(const char *uuid) {
236     return pa_streq(uuid, PA_BLUETOOTH_UUID_HSP_HS) || pa_streq(uuid, PA_BLUETOOTH_UUID_HSP_HS_ALT);
237 }
238 
239 #define HEADSET_BACKEND_OFONO 0
240 #define HEADSET_BACKEND_NATIVE 1
241 #define HEADSET_BACKEND_AUTO 2
242 
243 pa_bluetooth_discovery* pa_bluetooth_discovery_get(pa_core *core, int headset_backend, bool enable_native_hsp_hs, bool enable_native_hfp_hf, bool enable_msbc);
244 pa_bluetooth_discovery* pa_bluetooth_discovery_ref(pa_bluetooth_discovery *y);
245 void pa_bluetooth_discovery_unref(pa_bluetooth_discovery *y);
246 void pa_bluetooth_discovery_set_ofono_running(pa_bluetooth_discovery *y, bool is_running);
247 bool pa_bluetooth_discovery_get_enable_native_hsp_hs(pa_bluetooth_discovery *y);
248 bool pa_bluetooth_discovery_get_enable_native_hfp_hf(pa_bluetooth_discovery *y);
249 bool pa_bluetooth_discovery_get_enable_msbc(pa_bluetooth_discovery *y);
250 pa_hashmap* pa_bluetooth_discovery_get_transports(pa_bluetooth_discovery *y);
251 #endif
252