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;
{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"},
_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);
}
}
#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
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
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);
/* 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");
}
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")
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;
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;
--- /dev/null
+/*
+ * Bluetooth-frwk
+ *
+ * Copyright (c) 2020 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: Dohyun Pyun <dh79.pyun@samsung.com>
+ *
+ * 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 <vconf.h>
+
+#include <oal-event.h>
+#include <oal-hardware.h>
+#include <oal-audio-src.h>
+
+#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 */
+
}
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,
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:
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;
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);
BLUETOOTH_EVENT_AVRCP_SETTING_REPEAT_STATUS, /**<AVRCP service player repeat status event*/
BLUETOOTH_EVENT_AVRCP_SETTING_SCAN_STATUS, /**<AVRCP service player scan status event*/
BLUETOOTH_EVENT_AVRCP_DELAY_CHANGED, /**<AVRCP service transport delay changed event*/
+ BLUETOOTH_EVENT_AVRCP_VOLUME_CHANGED, /**<AVRCP service transport volume changed event*/
+ BLUETOOTH_EVENT_AUDIO_AVC_STATUS, /**<Absolute Volume Control status changed event*/
BLUETOOTH_EVENT_HF_CONNECTED,
BLUETOOTH_EVENT_HF_DISCONNECTED,
BLUETOOTH_EVENT_HF_AUDIO_CONNECTED,
*/
int bluetooth_audio_select_role(bluetooth_audio_role_t role);
+/**
+ * @brief The function bluetooth_audio_get_absolute_volume is called to set
+ * the Aboslute volume.
+ *
+ * @param[in] volume Headset's volume
+ * @return int Zero on Success or reason for error if any.
+ *
+ */
+int bluetooth_audio_set_absolute_volume(unsigned int volume);
+
+/**
+ * @brief The function bluetooth_audio_get_absolute_volume is called to get
+ * the Aboslute volume.
+ *
+ * @param[out] volume Headset's volume
+ * @return int Zero on Success or reason for error if any.
+ *
+ */
+int bluetooth_audio_get_absolute_volume(unsigned int *volume);
+
+/**
+ * @brief The function bluetooth_audio_is_avc_activated is called to get
+ * the Aboslute volume Control mode is activated or not
+ *
+ * @param[out] AVC mode is activated or not
+ * @return int Zero on Success or reason for error if any.
+ *
+ */
+int bluetooth_audio_is_avc_activated(bool *activated);
+
+
typedef struct {
int event;
int result;
BT_SET_SPEAKER_GAIN,
BT_SET_CONTENT_PROTECT,
BT_AUDIO_SELECT_ROLE,
+ BT_AUDIO_SET_ABSOLUTE_VOLUME,
+ BT_AUDIO_GET_ABSOLUTE_VOLUME,
+ BT_AUDIO_IS_AVC_ACTIVATED,
BT_OOB_READ_LOCAL_DATA = BT_FUNC_OOB_BASE,
BT_OOB_ADD_REMOTE_DATA,
BT_OOB_REMOVE_REMOTE_DATA,
#define BT_MEDIA_POSITION_STATUS "MediaPositionStatus"
#define BT_MEDIA_TRACK_CHANGE "MediaTrackStatus"
#define BT_MEDIA_DELAY_CHANGE "MediaDelayStatus"
+#define BT_MEDIA_VOLUME_CHANGE "MediaVolumeStatus"
#define BT_NAME_OWNER_CHANGED "NameOwnerChanged"
#ifdef TIZEN_GATT_CLIENT
%define bt_permanent_log DISABLED
%define bt_http_proxy DISABLED
%define bt_factory_mode DISABLED
+%define bt_avc_target ENABLED
BuildRequires: pkgconfig(aul)
%if %{bt_factory_mode} == ENABLED
export CFLAGS="$CFLAGS -DTIZEN_FEATURE_BT_FACTORY_MODE"
%endif
+%if %{bt_avc_target} == ENABLED
+export CFLAGS="$CFLAGS -DTIZEN_FEATURE_BT_AVC_TARGET"
+%endif
+
%ifarch %{ix86} x86_64
export CFLAGS+=" -DTIZEN_TEST_EMUL"
export CXXFLAGS+=" -DTIZEN_TEST_EMUL"