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 60typedef struct pa_bluetooth_transport pa_bluetooth_transport; 61typedef struct pa_bluetooth_device pa_bluetooth_device; 62typedef struct pa_bluetooth_adapter pa_bluetooth_adapter; 63typedef struct pa_bluetooth_discovery pa_bluetooth_discovery; 64typedef struct pa_bluetooth_backend pa_bluetooth_backend; 65 66typedef enum pa_bluetooth_hook { 67 PA_BLUETOOTH_HOOK_ADAPTER_UUIDS_CHANGED, /* Call data: pa_bluetooth_adapter */ 68 PA_BLUETOOTH_HOOK_DEVICE_CONNECTION_CHANGED, /* Call data: pa_bluetooth_device */ 69 PA_BLUETOOTH_HOOK_DEVICE_UNLINK, /* Call data: pa_bluetooth_device */ 70 PA_BLUETOOTH_HOOK_DEVICE_BATTERY_LEVEL_CHANGED, /* Call data: pa_bluetooth_device */ 71 PA_BLUETOOTH_HOOK_TRANSPORT_STATE_CHANGED, /* Call data: pa_bluetooth_transport */ 72 PA_BLUETOOTH_HOOK_TRANSPORT_SOURCE_VOLUME_CHANGED, /* Call data: pa_bluetooth_transport */ 73 PA_BLUETOOTH_HOOK_TRANSPORT_SINK_VOLUME_CHANGED, /* Call data: pa_bluetooth_transport */ 74 PA_BLUETOOTH_HOOK_MAX 75} pa_bluetooth_hook_t; 76 77typedef enum profile { 78 PA_BLUETOOTH_PROFILE_A2DP_SINK, 79 PA_BLUETOOTH_PROFILE_A2DP_SOURCE, 80 PA_BLUETOOTH_PROFILE_HSP_HS, 81 PA_BLUETOOTH_PROFILE_HSP_AG, 82 PA_BLUETOOTH_PROFILE_HFP_HF, 83 PA_BLUETOOTH_PROFILE_HFP_AG, 84 PA_BLUETOOTH_PROFILE_OFF 85} pa_bluetooth_profile_t; 86#define PA_BLUETOOTH_PROFILE_COUNT PA_BLUETOOTH_PROFILE_OFF 87 88typedef enum pa_bluetooth_profile_status { 89 PA_BLUETOOTH_PROFILE_STATUS_INACTIVE, 90 PA_BLUETOOTH_PROFILE_STATUS_ACTIVE, 91 PA_BLUETOOTH_PROFILE_STATUS_REGISTERING, 92 PA_BLUETOOTH_PROFILE_STATUS_REGISTERED 93} pa_bluetooth_profile_status_t; 94 95typedef enum pa_bluetooth_transport_state { 96 PA_BLUETOOTH_TRANSPORT_STATE_DISCONNECTED, 97 PA_BLUETOOTH_TRANSPORT_STATE_IDLE, 98 PA_BLUETOOTH_TRANSPORT_STATE_PLAYING 99} pa_bluetooth_transport_state_t; 100 101typedef int (*pa_bluetooth_transport_acquire_cb)(pa_bluetooth_transport *t, bool optional, size_t *imtu, size_t *omtu); 102typedef void (*pa_bluetooth_transport_release_cb)(pa_bluetooth_transport *t); 103typedef void (*pa_bluetooth_transport_destroy_cb)(pa_bluetooth_transport *t); 104typedef pa_volume_t (*pa_bluetooth_transport_set_volume_cb)(pa_bluetooth_transport *t, pa_volume_t volume); 105typedef ssize_t (*pa_bluetooth_transport_write_cb)(pa_bluetooth_transport *t, int fd, const void* buffer, size_t size, size_t write_mtu); 106typedef int (*pa_bluetooth_transport_setsockopt_cb)(pa_bluetooth_transport *t, int fd); 107 108struct pa_bluetooth_transport { 109 pa_bluetooth_device *device; 110 111 char *owner; 112 char *path; 113 pa_bluetooth_profile_t profile; 114 115 void *config; 116 size_t config_size; 117 118 const pa_bt_codec *bt_codec; 119 int stream_write_type; 120 size_t last_read_size; 121 122 pa_volume_t source_volume; 123 pa_volume_t sink_volume; 124 125 pa_bluetooth_transport_state_t state; 126 127 pa_bluetooth_transport_acquire_cb acquire; 128 pa_bluetooth_transport_release_cb release; 129 pa_bluetooth_transport_write_cb write; 130 pa_bluetooth_transport_setsockopt_cb setsockopt; 131 pa_bluetooth_transport_destroy_cb destroy; 132 pa_bluetooth_transport_set_volume_cb set_sink_volume; 133 pa_bluetooth_transport_set_volume_cb set_source_volume; 134 void *userdata; 135}; 136 137struct pa_bluetooth_device { 138 pa_bluetooth_discovery *discovery; 139 pa_bluetooth_adapter *adapter; 140 141 bool enable_hfp_hf; 142 bool properties_received; 143 bool tried_to_link_with_adapter; 144 bool valid; 145 bool autodetect_mtu; 146 bool codec_switching_in_progress; 147 bool avrcp_absolute_volume; 148 uint32_t output_rate_refresh_interval_ms; 149 150 /* Device information */ 151 char *path; 152 char *adapter_path; 153 char *alias; 154 char *address; 155 uint32_t class_of_device; 156 pa_hashmap *uuids; /* char* -> char* (hashmap-as-a-set) */ 157 /* pa_a2dp_codec_id* -> pa_hashmap ( char* (remote endpoint) -> struct a2dp_codec_capabilities* ) */ 158 pa_hashmap *a2dp_sink_endpoints; 159 pa_hashmap *a2dp_source_endpoints; 160 161 pa_bluetooth_transport *transports[PA_BLUETOOTH_PROFILE_COUNT]; 162 163 pa_time_event *wait_for_profiles_timer; 164 165 bool has_battery_level; 166 uint8_t battery_level; 167 const char *battery_source; 168}; 169 170struct pa_bluetooth_adapter { 171 pa_bluetooth_discovery *discovery; 172 char *path; 173 char *address; 174 pa_hashmap *uuids; /* char* -> char* (hashmap-as-a-set) */ 175 176 bool valid; 177 bool application_registered; 178 bool battery_provider_registered; 179}; 180 181#ifdef HAVE_BLUEZ_5_OFONO_HEADSET 182pa_bluetooth_backend *pa_bluetooth_ofono_backend_new(pa_core *c, pa_bluetooth_discovery *y); 183void pa_bluetooth_ofono_backend_free(pa_bluetooth_backend *b); 184#else 185static inline pa_bluetooth_backend *pa_bluetooth_ofono_backend_new(pa_core *c, pa_bluetooth_discovery *y) { 186 return NULL; 187} 188static inline void pa_bluetooth_ofono_backend_free(pa_bluetooth_backend *b) {} 189#endif 190 191#ifdef HAVE_BLUEZ_5_NATIVE_HEADSET 192pa_bluetooth_backend *pa_bluetooth_native_backend_new(pa_core *c, pa_bluetooth_discovery *y, bool enable_shared_profiles); 193void pa_bluetooth_native_backend_free(pa_bluetooth_backend *b); 194void pa_bluetooth_native_backend_enable_shared_profiles(pa_bluetooth_backend *b, bool enable); 195#else 196static inline pa_bluetooth_backend *pa_bluetooth_native_backend_new(pa_core *c, pa_bluetooth_discovery *y, bool enable_shared_profiles) { 197 return NULL; 198} 199static inline void pa_bluetooth_native_backend_free(pa_bluetooth_backend *b) {} 200static inline void pa_bluetooth_native_backend_enable_shared_profiles(pa_bluetooth_backend *b, bool enable) {} 201#endif 202 203pa_bluetooth_profile_status_t profile_status_get(pa_bluetooth_discovery *y, pa_bluetooth_profile_t profile); 204void profile_status_set(pa_bluetooth_discovery *y, pa_bluetooth_profile_t profile, pa_bluetooth_profile_status_t status); 205 206pa_bluetooth_transport *pa_bluetooth_transport_new(pa_bluetooth_device *d, const char *owner, const char *path, 207 pa_bluetooth_profile_t p, const uint8_t *config, size_t size); 208 209void pa_bluetooth_transport_reconfigure(pa_bluetooth_transport *t, const pa_bt_codec *bt_codec, 210 pa_bluetooth_transport_write_cb write_cb, pa_bluetooth_transport_setsockopt_cb setsockopt_cb); 211 212void pa_bluetooth_transport_set_state(pa_bluetooth_transport *t, pa_bluetooth_transport_state_t state); 213void pa_bluetooth_transport_put(pa_bluetooth_transport *t); 214void pa_bluetooth_transport_unlink(pa_bluetooth_transport *t); 215void pa_bluetooth_transport_free(pa_bluetooth_transport *t); 216void pa_bluetooth_transport_load_a2dp_sink_volume(pa_bluetooth_transport *t); 217 218bool pa_bluetooth_device_supports_profile(const pa_bluetooth_device *device, pa_bluetooth_profile_t profile); 219bool pa_bluetooth_device_any_transport_connected(const pa_bluetooth_device *d); 220bool 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); 221void pa_bluetooth_device_report_battery_level(pa_bluetooth_device *d, uint8_t level, const char *reporting_source); 222void pa_bluetooth_device_deregister_battery(pa_bluetooth_device *d); 223 224pa_bluetooth_device* pa_bluetooth_discovery_get_device_by_path(pa_bluetooth_discovery *y, const char *path); 225pa_bluetooth_device* pa_bluetooth_discovery_get_device_by_address(pa_bluetooth_discovery *y, const char *remote, const char *local); 226 227pa_hook* pa_bluetooth_discovery_hook(pa_bluetooth_discovery *y, pa_bluetooth_hook_t hook); 228 229const char *pa_bluetooth_profile_to_string(pa_bluetooth_profile_t profile); 230bool pa_bluetooth_profile_should_attenuate_volume(pa_bluetooth_profile_t profile); 231bool pa_bluetooth_profile_is_a2dp(pa_bluetooth_profile_t profile); 232 233static inline bool pa_bluetooth_uuid_is_hsp_hs(const char *uuid) { 234 return pa_streq(uuid, PA_BLUETOOTH_UUID_HSP_HS) || pa_streq(uuid, PA_BLUETOOTH_UUID_HSP_HS_ALT); 235} 236 237#define HEADSET_BACKEND_OFONO 0 238#define HEADSET_BACKEND_NATIVE 1 239#define HEADSET_BACKEND_AUTO 2 240 241pa_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); 242pa_bluetooth_discovery* pa_bluetooth_discovery_ref(pa_bluetooth_discovery *y); 243void pa_bluetooth_discovery_unref(pa_bluetooth_discovery *y); 244void pa_bluetooth_discovery_set_ofono_running(pa_bluetooth_discovery *y, bool is_running); 245bool pa_bluetooth_discovery_get_enable_native_hsp_hs(pa_bluetooth_discovery *y); 246bool pa_bluetooth_discovery_get_enable_native_hfp_hf(pa_bluetooth_discovery *y); 247bool pa_bluetooth_discovery_get_enable_msbc(pa_bluetooth_discovery *y); 248#endif 249