diff options
Diffstat (limited to 'cras/src/server/cras_bt_device.c')
-rw-r--r-- | cras/src/server/cras_bt_device.c | 98 |
1 files changed, 56 insertions, 42 deletions
diff --git a/cras/src/server/cras_bt_device.c b/cras/src/server/cras_bt_device.c index 0607ac8e..70c87479 100644 --- a/cras/src/server/cras_bt_device.c +++ b/cras/src/server/cras_bt_device.c @@ -61,9 +61,7 @@ static const unsigned int CONN_WATCH_MAX_RETRIES = 30; static const unsigned int SCO_SUSPEND_DELAY_MS = 5000; static const unsigned int CRAS_SUPPORTED_PROFILES = - CRAS_BT_DEVICE_PROFILE_A2DP_SINK | - CRAS_BT_DEVICE_PROFILE_HFP_HANDSFREE | - CRAS_BT_DEVICE_PROFILE_HSP_AUDIOGATEWAY; + CRAS_BT_DEVICE_PROFILE_A2DP_SINK | CRAS_BT_DEVICE_PROFILE_HFP_HANDSFREE; /* Object to represent a general bluetooth device, and used to * associate with some CRAS modules if it supports audio. @@ -79,6 +77,8 @@ static const unsigned int CRAS_SUPPORTED_PROFILES = * connected - If this devices is connected. * connected_profiles - OR'ed all connected audio profiles. * profiles - OR'ed by all audio profiles this device supports. + * hidden_profiles - OR'ed by all audio profiles this device actually + * supports but is not scanned by BlueZ. * bt_iodevs - The pointer to the cras_iodevs of this device. * active_profile - The flag to indicate the active audio profile this * device is currently using. @@ -102,8 +102,9 @@ struct cras_bt_device { int paired; int trusted; int connected; - enum cras_bt_device_profile connected_profiles; - enum cras_bt_device_profile profiles; + unsigned int connected_profiles; + unsigned int profiles; + unsigned int hidden_profiles; struct cras_iodev *bt_iodevs[CRAS_NUM_DIRECTIONS]; unsigned int active_profile; int use_hardware_volume; @@ -512,14 +513,18 @@ int cras_bt_device_audio_gateway_initialized(struct cras_bt_device *device) * behavior on qualification test software. */ if (!cras_bt_device_supports_profile( device, CRAS_BT_DEVICE_PROFILE_HFP_HANDSFREE)) { - cras_bt_device_add_supported_profiles(device, HFP_HF_UUID); + unsigned int profiles = + device->profiles | CRAS_BT_DEVICE_PROFILE_HFP_HANDSFREE; + cras_bt_device_set_supported_profiles(device, profiles); + device->hidden_profiles |= CRAS_BT_DEVICE_PROFILE_HFP_HANDSFREE; bt_device_conn_watch_cb(NULL, (void *)device); } return 0; } -int cras_bt_device_get_active_profile(const struct cras_bt_device *device) +unsigned int +cras_bt_device_get_active_profile(const struct cras_bt_device *device) { return device->active_profile; } @@ -569,6 +574,19 @@ static void cras_bt_device_log_profile(const struct cras_bt_device *device, } } +static void cras_bt_device_log_profiles(const struct cras_bt_device *device, + unsigned int profiles) +{ + unsigned int profile; + + while (profiles) { + /* Get the LSB of profiles */ + profile = profiles & -profiles; + cras_bt_device_log_profile(device, profile); + profiles ^= profile; + } +} + static int cras_bt_device_is_profile_connected(const struct cras_bt_device *device, enum cras_bt_device_profile profile) @@ -708,7 +726,7 @@ void cras_bt_device_set_connected(struct cras_bt_device *device, int value) void cras_bt_device_notify_profile_dropped(struct cras_bt_device *device, enum cras_bt_device_profile profile) { - device->connected_profiles &= !profile; + device->connected_profiles &= ~profile; /* Do nothing if device already disconnected. */ if (!device->connected) @@ -723,37 +741,33 @@ void cras_bt_device_notify_profile_dropped(struct cras_bt_device *device, UNEXPECTED_PROFILE_DROP); } -/* - * Check if the uuid is of a new audio profile that isn't listed - * as supported by device. +/* Refresh the list of known supported profiles. * Args: - * device - The BT device holding supported profiles bitmap. - * uuid - UUID string from the device properties notified by BlueZ. + * device - The BT device holding scanned profiles bitmap. + * profiles - The OR'ed profiles the device claims to support as is notified + * by BlueZ. * Returns: - * True if uuid is a new audio profiles not already supported by device. + * The OR'ed profiles that are both supported by Cras and isn't previously + * supported by the device. */ -int cras_bt_device_add_supported_profiles(struct cras_bt_device *device, - const char *uuid) +int cras_bt_device_set_supported_profiles(struct cras_bt_device *device, + unsigned int profiles) { - enum cras_bt_device_profile profile = - cras_bt_device_profile_from_uuid(uuid); - - if (profile == 0) + /* Do nothing if no new profiles. */ + if ((device->profiles & profiles) == profiles) return 0; - /* Do nothing if this profile is not new. */ - if (device->profiles & profile) - return 0; + unsigned int new_profiles = profiles & ~device->profiles; /* Log this event as we might need to re-intialize the BT audio nodes * if new audio profile is reported for already connected device. */ - if (device->connected && (profile & CRAS_SUPPORTED_PROFILES)) + if (device->connected && (new_profiles & CRAS_SUPPORTED_PROFILES)) BTLOG(btlog, BT_NEW_AUDIO_PROFILE_AFTER_CONNECT, - device->profiles, profile); - device->profiles |= profile; - cras_bt_device_log_profile(device, profile); + device->profiles, new_profiles); + cras_bt_device_log_profiles(device, new_profiles); + device->profiles = profiles | device->hidden_profiles; - return (profile & CRAS_SUPPORTED_PROFILES); + return (new_profiles & CRAS_SUPPORTED_PROFILES); } void cras_bt_device_update_properties(struct cras_bt_device *device, @@ -821,6 +835,7 @@ void cras_bt_device_update_properties(struct cras_bt_device *device, "as") == 0 && strcmp(key, "UUIDs") == 0) { DBusMessageIter uuid_array_iter; + unsigned int profiles = 0; dbus_message_iter_recurse(&variant_iter, &uuid_array_iter); @@ -830,22 +845,21 @@ void cras_bt_device_update_properties(struct cras_bt_device *device, dbus_message_iter_get_basic(&uuid_array_iter, &uuid); - - /* - * If updated properties includes new audio - * profile, and device is connected, we need - * to start connection watcher. This is needed - * because on some bluetooth device, supported - * profiles do not present when device - * interface is added and they are updated - * later. - */ - if (cras_bt_device_add_supported_profiles( - device, uuid)) - watch_needed = device->connected; + profiles |= + cras_bt_device_profile_from_uuid(uuid); dbus_message_iter_next(&uuid_array_iter); } + + /* If updated properties includes new audio profile and + * device is connected, we need to start connection + * watcher. This is needed because on some bluetooth + * devices, supported profiles do not present when + * device interface is added and they are updated later. + */ + if (cras_bt_device_set_supported_profiles(device, + profiles)) + watch_needed = device->connected; } dbus_message_iter_next(properties_array_iter); @@ -876,7 +890,7 @@ void cras_bt_device_update_properties(struct cras_bt_device *device, } else if (strcmp(key, "Connected") == 0) { device->connected = 0; } else if (strcmp(key, "UUIDs") == 0) { - device->profiles = 0; + device->profiles = device->hidden_profiles; } dbus_message_iter_next(invalidated_array_iter); |