From a345f36e203bc044909329c8bfd789ed520a6b73 Mon Sep 17 00:00:00 2001 From: DoHyun Pyun Date: Fri, 14 Feb 2020 15:08:53 +0900 Subject: [PATCH] Add interfaces for BT AVC feature (AVRCP Target) Change-Id: Id45c2c61b4ec917edd9ca5f53e46e81d34756e6e Signed-off-by: DoHyun Pyun --- bt-api/bt-audio.c | 69 ++++++++++++++++++ bt-api/bt-common.c | 3 + bt-api/bt-event-handler.c | 7 ++ bt-oal/bluez_hal/inc/bt-hal-msg.h | 6 ++ bt-oal/bluez_hal/src/bt-hal-avrcp-tg.c | 8 +++ bt-oal/bluez_hal/src/bt-hal-event-receiver.c | 13 ++++ bt-service-adaptation/CMakeLists.txt | 3 + .../services/audio/avrcp/bt-service-avrcp-tg.c | 24 ++++++- .../services/audio/bt-service-absolute-volume.c | 82 ++++++++++++++++++++++ .../services/bt-request-handler.c | 31 ++++++++ .../services/bt-service-event-sender.c | 3 + .../services/include/bt-service-audio-common.h | 14 ++++ include/bluetooth-api.h | 2 + include/bluetooth-audio-api.h | 31 ++++++++ include/bt-internal-types.h | 4 ++ packaging/bluetooth-frwk.spec | 5 ++ 16 files changed, 304 insertions(+), 1 deletion(-) create mode 100644 bt-service-adaptation/services/audio/bt-service-absolute-volume.c diff --git a/bt-api/bt-audio.c b/bt-api/bt-audio.c index 46c29fc..eb1523d 100644 --- a/bt-api/bt-audio.c +++ b/bt-api/bt-audio.c @@ -451,6 +451,75 @@ BT_EXPORT_API int bluetooth_audio_select_role(bluetooth_audio_role_t role) return result; } +BT_EXPORT_API int bluetooth_audio_set_absolute_volume(unsigned int volume) +{ + int result; + + BT_CHECK_ENABLED(return); + + BT_INIT_PARAMS(); + BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + + g_array_append_vals(in_param1, &volume, sizeof(unsigned int)); + + result = _bt_send_request(BT_BLUEZ_SERVICE, BT_AUDIO_SET_ABSOLUTE_VOLUME, + in_param1, in_param2, in_param3, in_param4, &out_param); + + BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + return result; +} + +BT_EXPORT_API int bluetooth_audio_get_absolute_volume(unsigned int *volume) +{ + int result; + + BT_CHECK_PARAMETER(volume, return); + BT_CHECK_ENABLED(return); + + BT_INIT_PARAMS(); + BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + + result = _bt_send_request(BT_BLUEZ_SERVICE, BT_AUDIO_GET_ABSOLUTE_VOLUME, + in_param1, in_param2, in_param3, in_param4, &out_param); + + if (result == BLUETOOTH_ERROR_NONE) { + *volume = g_array_index(out_param, + unsigned int, 0); + } + + BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + + return result; +} + +BT_EXPORT_API int bluetooth_audio_is_avc_activated(bool *activated) +{ + int result; + + BT_CHECK_PARAMETER(activated, return); + + if (bluetooth_check_adapter() == BLUETOOTH_ADAPTER_DISABLED) { + BT_DBG("BT is not enabled. So activated value is false"); + *activated = false; + return BLUETOOTH_ERROR_NONE; + } + + BT_INIT_PARAMS(); + BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + + result = _bt_send_request(BT_BLUEZ_SERVICE, BT_AUDIO_IS_AVC_ACTIVATED, + in_param1, in_param2, in_param3, in_param4, &out_param); + + if (result == BLUETOOTH_ERROR_NONE) { + *activated = g_array_index(out_param, + bool, 0); + } + + BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param); + + return result; +} + BT_EXPORT_API int bluetooth_ag_get_headset_volume(unsigned int *speaker_gain) { int result; diff --git a/bt-api/bt-common.c b/bt-api/bt-common.c index a4dbd38..496d94b 100644 --- a/bt-api/bt-common.c +++ b/bt-api/bt-common.c @@ -590,6 +590,9 @@ const char *_bt_convert_service_function_to_string(int function) {BT_SET_SPEAKER_GAIN, "BT_SET_SPEAKER_GAIN"}, {BT_SET_CONTENT_PROTECT, "BT_SET_CONTENT_PROTECT"}, {BT_AUDIO_SELECT_ROLE, "BT_AUDIO_SELECT_ROLE"}, + {BT_AUDIO_SET_ABSOLUTE_VOLUME, "BT_AUDIO_SET_ABSOLUTE_VOLUME"}, + {BT_AUDIO_GET_ABSOLUTE_VOLUME, "BT_AUDIO_GET_ABSOLUTE_VOLUME"}, + {BT_AUDIO_IS_AVC_ACTIVATED, "BT_AUDIO_IS_AVC_ACTIVATED"}, {BT_OOB_READ_LOCAL_DATA, "BT_OOB_READ_LOCAL_DATA"}, {BT_OOB_ADD_REMOTE_DATA, "BT_OOB_ADD_REMOTE_DATA"}, {BT_OOB_REMOVE_REMOTE_DATA, "BT_OOB_REMOVE_REMOTE_DATA"}, diff --git a/bt-api/bt-event-handler.c b/bt-api/bt-event-handler.c index ea3d35e..c45e644 100644 --- a/bt-api/bt-event-handler.c +++ b/bt-api/bt-event-handler.c @@ -1653,6 +1653,13 @@ void __bt_avrcp_event_filter(GDBusConnection *connection, _bt_avrcp_event_cb(BLUETOOTH_EVENT_AVRCP_DELAY_CHANGED, result, &delay, event_info->cb, event_info->user_data); + } else if (strcasecmp(signal_name, BT_MEDIA_VOLUME_CHANGE) == 0) { + unsigned int volume; + + g_variant_get(parameters, "(u)", &volume); + _bt_avrcp_event_cb(BLUETOOTH_EVENT_AVRCP_VOLUME_CHANGED, + result, &volume, + event_info->cb, event_info->user_data); } } diff --git a/bt-oal/bluez_hal/inc/bt-hal-msg.h b/bt-oal/bluez_hal/inc/bt-hal-msg.h index 2c46056..af9675b 100644 --- a/bt-oal/bluez_hal/inc/bt-hal-msg.h +++ b/bt-oal/bluez_hal/inc/bt-hal-msg.h @@ -436,6 +436,7 @@ struct hal_ev_play_status_changed { #ifdef TIZEN_BT_HAL #define HAL_EV_AVRCP_TG_CONN_STATE 0xA2 #define HAL_EV_AVRCP_TG_DELAY_CHANGE 0xF1 +#define HAL_EV_AVRCP_TG_VOLUME_CHANGE 0xF2 #define HAL_AVRCP_TG_STATE_DISCONNECTED 0x00 #define HAL_AVRCP_TG_STATE_CONNECTED 0x01 @@ -449,6 +450,11 @@ struct hal_ev_avrcp_tg_delay_changed{ uint16_t value; } __attribute__((packed)); +struct hal_ev_avrcp_tg_volume_changed{ + uint8_t bdaddr[6]; + uint16_t volume; +} __attribute__((packed)); + #endif /* TIZEN_BT_HAL */ #define HAL_EV_AVRCP_TG_SET_PLAYER_PROPERTY 0xA3 diff --git a/bt-oal/bluez_hal/src/bt-hal-avrcp-tg.c b/bt-oal/bluez_hal/src/bt-hal-avrcp-tg.c index a6a6673..ce19459 100644 --- a/bt-oal/bluez_hal/src/bt-hal-avrcp-tg.c +++ b/bt-oal/bluez_hal/src/bt-hal-avrcp-tg.c @@ -276,6 +276,14 @@ static void __bt_hal_handle_avrcp_tg_events(int message, void *buf, uint16_t len ev->value, (bt_bdaddr_t *)ev->bdaddr); break; } + case HAL_EV_AVRCP_TG_VOLUME_CHANGE: + { + DBG("avrcp tg volume change"); + struct hal_ev_avrcp_tg_volume_changed *ev = buf; + bt_hal_avrcp_tg_cbacks->volume_change_cb( + ev->volume, 0, (bt_bdaddr_t *)ev->bdaddr); + break; + } #endif case HAL_EV_AVRCP_TG_SET_PLAYER_PROPERTY: __handle_player_property(buf, len); diff --git a/bt-oal/bluez_hal/src/bt-hal-event-receiver.c b/bt-oal/bluez_hal/src/bt-hal-event-receiver.c index 46a172b..29caf36 100644 --- a/bt-oal/bluez_hal/src/bt-hal-event-receiver.c +++ b/bt-oal/bluez_hal/src/bt-hal-event-receiver.c @@ -2500,6 +2500,19 @@ static void __bt_hal_handle_avrcp_transport_events(GVariant *msg, const char *me /* Send event to application */ avrcp_tg_event_cb(HAL_EV_AVRCP_TG_DELAY_CHANGE, &ev, sizeof(ev)); + } else if ((strcasecmp(property, "Volume") == 0)) { + struct hal_ev_avrcp_tg_volume_changed ev; + uint16_t val; + + memset(&ev, 0, sizeof(ev)); + _bt_hal_convert_addr_string_to_type(ev.bdaddr, address); + + val = g_variant_get_uint16(value); + DBG("Value : %d", val); + ev.volume = val; + + /* Send event to application */ + avrcp_tg_event_cb(HAL_EV_AVRCP_TG_VOLUME_CHANGE, &ev, sizeof(ev)); } else { DBG("Property not handled"); } diff --git a/bt-service-adaptation/CMakeLists.txt b/bt-service-adaptation/CMakeLists.txt index 73c5603..5e6d30a 100644 --- a/bt-service-adaptation/CMakeLists.txt +++ b/bt-service-adaptation/CMakeLists.txt @@ -52,6 +52,9 @@ LIST(APPEND SRCS ./services/ipsp/bt-service-ipsp.c) LIST(APPEND SRCS ./services/ipsp/bt-service-ipsp-event-receiver.c) ENDIF() +IF("$ENV{CFLAGS}" MATCHES "-DTIZEN_FEATURE_BT_AVC_TARGET") +LIST(APPEND SRCS ./services/audio/bt-service-absolute-volume.c) +ENDIF() IF("${CMAKE_BUILD_TYPE}" STREQUAL "") SET(CMAKE_BUILD_TYPE "Release") diff --git a/bt-service-adaptation/services/audio/avrcp/bt-service-avrcp-tg.c b/bt-service-adaptation/services/audio/avrcp/bt-service-avrcp-tg.c index 5023648..5e2c064 100644 --- a/bt-service-adaptation/services/audio/avrcp/bt-service-avrcp-tg.c +++ b/bt-service-adaptation/services/audio/avrcp/bt-service-avrcp-tg.c @@ -497,6 +497,23 @@ static void __handle_transport_property_delay(unsigned int *value) BT_DBG("-"); } +static void __handle_transport_property_volume(unsigned int avrcp_volume) +{ +#ifdef TIZEN_FEATURE_BT_AVC_TARGET + unsigned int system_volume = 0; + + BT_DBG("+"); + + /* Need to add the logic for platform */ + + _bt_send_event(BT_AVRCP_EVENT, + BLUETOOTH_EVENT_AVRCP_VOLUME_CHANGED, + g_variant_new("(u)", system_volume)); + + BT_DBG("-"); +#endif +} + static void __handle_avrcp_connection_event(int event, bt_address_t *bdaddr) { int result = BLUETOOTH_ERROR_NONE; @@ -582,8 +599,13 @@ static void __handle_avrcp_target_events(int event_type, gpointer event_data) break; case OAL_EVENT_AVRCP_REMOTE_FEATURES: break; - case OAL_EVENT_AVRCP_VOLUME_MUTE_CHANGED: + case OAL_EVENT_AVRCP_VOLUME_MUTE_CHANGED: { + oal_avrcp_volume_mute_t *volume_mute = (oal_avrcp_volume_mute_t *)event_data; + + if (volume_mute) + __handle_transport_property_volume(volume_mute->volume); break; + } case OAL_EVENT_AVRCP_DELAY_CHANGED: __handle_transport_property_delay((unsigned int *)event_data); break; diff --git a/bt-service-adaptation/services/audio/bt-service-absolute-volume.c b/bt-service-adaptation/services/audio/bt-service-absolute-volume.c new file mode 100644 index 0000000..753162b --- /dev/null +++ b/bt-service-adaptation/services/audio/bt-service-absolute-volume.c @@ -0,0 +1,82 @@ +/* + * Bluetooth-frwk + * + * Copyright (c) 2020 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Dohyun Pyun + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include + +#include +#include +#include + +#include "bt-service-common.h" +#include "bt-service-audio-common.h" + +static unsigned int absolute_volume = 0; +static unsigned int bt_volume = 0; +static int avc_mode = BT_AVC_OFF; + +int _bt_audio_set_absolute_volume(unsigned int volume) +{ + int result = BLUETOOTH_ERROR_NONE; + + /* 1. Translate the absolute volume to bt volume */ + + /* Convert system gain to BT + BT volume range : 0 ~ 127 + system volume range : 0 ~ 150 */ + + bt_volume = 127 * volume / 150; + + /* volume table + system volume : 0 10 20 30 40 50 60 70 80 90 100 110 120 130 140 150 + avrcp_ volume : 0 9 17 26 34 43 51 60 68 77 85 94 102 111 119 127 */ + + if (bt_volume > 0 && bt_volume < 127) + bt_volume++; + + /* 2. Notify the bt_volume to transport (BT Headset) */ + + /* 3. Notify the avc mode to the pulseaudio if it is needed */ + + return result; +} + +/* Just return the absolute_volume value */ +int _bt_audio_get_absolute_volume(unsigned int *volume) +{ + int result = BLUETOOTH_ERROR_NONE; + + *volume = absolute_volume; + + return result; +} + +int _bt_audio_is_avc_activated(bool *activated) +{ + *activated = (avc_mode == BT_AVC_OFF) ? false : true; + + return BLUETOOTH_ERROR_NONE; +} + +/* 1. When a2dp headset is connected, we should set 'AVC' mode into pulseaudio */ +/* 2. If the avc mode is changed, we should inform 'AVC' mode to pulseaudio */ +/* 3. If BT is off, we should send 'AVC' off mode event for application */ +/* 4. If BT A2DP is disconnected, we should send 'AVC' off mode event for application */ + diff --git a/bt-service-adaptation/services/bt-request-handler.c b/bt-service-adaptation/services/bt-request-handler.c index a24c73c..ef3bfd8 100644 --- a/bt-service-adaptation/services/bt-request-handler.c +++ b/bt-service-adaptation/services/bt-request-handler.c @@ -1527,6 +1527,31 @@ int __bt_bluez_request(int function_name, } break; } +#ifdef TIZEN_FEATURE_BT_AVC_TARGET + case BT_AUDIO_SET_ABSOLUTE_VOLUME: { + unsigned int volume = 0; + + __bt_service_get_parameters(in_param1, + &volume, sizeof(unsigned int)); + + result = _bt_audio_set_absolute_volume(volume); + break; + } + case BT_AUDIO_GET_ABSOLUTE_VOLUME: { + unsigned int volume = 0; + + result = _bt_audio_get_absolute_volume(&volume); + g_array_append_vals(*out_param1, &volume, sizeof(unsigned int)); + break; + } + case BT_AUDIO_IS_AVC_ACTIVATED: { + bool activated = 0; + + result = _bt_audio_is_avc_activated(&activated); + g_array_append_vals(*out_param1, &activated, sizeof(bool)); + break; + } +#endif case BT_AV_CONNECT: { bluetooth_device_address_t address = { {0} }; __bt_service_get_parameters(in_param1, @@ -3921,6 +3946,12 @@ gboolean __bt_service_check_privilege(int function_name, case BT_AVRCP_SET_PROPERTIES: case BT_AVRCP_CONTROL_SET_PROPERTY: +#ifdef TIZEN_FEATURE_BT_AVC_TARGET + case BT_AUDIO_SET_ABSOLUTE_VOLUME: + case BT_AUDIO_GET_ABSOLUTE_VOLUME: + case BT_AUDIO_IS_AVC_ACTIVATED: +#endif + case BT_HF_CONNECT: case BT_HF_DISCONNECT: diff --git a/bt-service-adaptation/services/bt-service-event-sender.c b/bt-service-adaptation/services/bt-service-event-sender.c index f4083b9..9919c50 100644 --- a/bt-service-adaptation/services/bt-service-event-sender.c +++ b/bt-service-adaptation/services/bt-service-event-sender.c @@ -447,6 +447,9 @@ int _bt_send_event(int event_type, int event, GVariant *param) case BLUETOOTH_EVENT_AVRCP_DELAY_CHANGED: signal = BT_MEDIA_DELAY_CHANGE; break; + case BLUETOOTH_EVENT_AVRCP_VOLUME_CHANGED: + signal = BT_MEDIA_VOLUME_CHANGE; + break; #ifdef TIZEN_GATT_CLIENT case BLUETOOTH_EVENT_GATT_SERVER_CONNECTED: /* GATT Server and Client */ signal = BT_GATT_SERVER_CONNECTED; diff --git a/bt-service-adaptation/services/include/bt-service-audio-common.h b/bt-service-adaptation/services/include/bt-service-audio-common.h index 99b44f5..bb39cca 100644 --- a/bt-service-adaptation/services/include/bt-service-audio-common.h +++ b/bt-service-adaptation/services/include/bt-service-audio-common.h @@ -130,6 +130,20 @@ int _bt_audio_select_role(bluetooth_audio_role_t role); void _bt_audio_set_current_role(bluetooth_audio_role_t role); +#ifdef TIZEN_FEATURE_BT_AVC_TARGET +typedef enum { + BT_AVC_OFF = 0x00, + BT_AVC_NULL, + BT_AVC_MAX +} bt_avc_mode_t; + +int _bt_audio_set_absolute_volume(unsigned int volume); + +int _bt_audio_get_absolute_volume(unsigned int *volume); + +int _bt_audio_is_avc_activated(bool *activated); +#endif + int _bt_hf_connect(bluetooth_device_address_t *device_address); int _bt_hf_disconnect(bluetooth_device_address_t *device_address); diff --git a/include/bluetooth-api.h b/include/bluetooth-api.h index 9fef6cc..8e2ba9a 100644 --- a/include/bluetooth-api.h +++ b/include/bluetooth-api.h @@ -868,6 +868,8 @@ typedef enum { BLUETOOTH_EVENT_AVRCP_SETTING_REPEAT_STATUS, /**