From e64a8f021f63f9e36fec6409241321a2423eb7ac Mon Sep 17 00:00:00 2001 From: Manish Sogi Date: Mon, 20 Apr 2015 17:32:57 +0530 Subject: [PATCH] Enabled TIZEN specific bluetooth changes Change-Id: I135172f01a84f05bbfc22d5e52a5a9bfdb590946 --- packaging/pulseaudio.spec | 2 +- src/modules/bluetooth/a2dp-codecs.h | 9 +- src/modules/bluetooth/bluez4-util.c | 5 +- src/modules/bluetooth/bluez5-util.c | 137 ++++++++++- src/modules/bluetooth/bluez5-util.h | 11 + src/modules/bluetooth/module-bluetooth-discover.c | 72 +++++- src/modules/bluetooth/module-bluez5-device.c | 281 +++++++++++++++++++++- src/modules/bluetooth/module-bluez5-discover.c | 32 ++- 8 files changed, 531 insertions(+), 18 deletions(-) diff --git a/packaging/pulseaudio.spec b/packaging/pulseaudio.spec index 2927978..653be18 100644 --- a/packaging/pulseaudio.spec +++ b/packaging/pulseaudio.spec @@ -207,7 +207,7 @@ echo "%{version}" > .tarball-version cp %{SOURCE1001} . %build -export CFLAGS="%{optflags} -fno-strict-aliasing -D__TIZEN__ -D__TIZEN_BT__ -D__TIZEN_LOG__ -DTIZEN_MICRO" +export CFLAGS="%{optflags} -fno-strict-aliasing -D__TIZEN__ -D__TIZEN_BT__ -D__TIZEN_LOG__ -DTIZEN_MICRO -DBLUETOOTH_APTX_SUPPORT" %if 0%{?sec_build_binary_debug_enable} export CFLAGS+=" -DTIZEN_DEBUG_ENABLE" export CXXFLAGS="$CXXFLAGS –DTIZEN_DEBUG_ENABLE" diff --git a/src/modules/bluetooth/a2dp-codecs.h b/src/modules/bluetooth/a2dp-codecs.h index c94812b..50c2c0a 100644 --- a/src/modules/bluetooth/a2dp-codecs.h +++ b/src/modules/bluetooth/a2dp-codecs.h @@ -26,7 +26,9 @@ #define A2DP_CODEC_MPEG12 0x01 #define A2DP_CODEC_MPEG24 0x02 #define A2DP_CODEC_ATRAC 0x03 - +#ifdef __TIZEN_BT__ +#define A2DP_CODEC_VENDOR 0xFF +#endif #define A2DP_CODEC_NON_A2DP 0xFF #define SBC_SAMPLING_FREQ_16000 (1 << 3) #define SBC_SAMPLING_FREQ_32000 (1 << 2) @@ -65,7 +67,12 @@ #define MPEG_SAMPLING_FREQ_44100 (1 << 1) #define MPEG_SAMPLING_FREQ_48000 1 + +#if defined(__TIZEN_BT__) && defined(ADJUST_ANDROID_BITPOOL) +#define MAX_BITPOOL 35 +#else #define MAX_BITPOOL 64 +#endif #define MIN_BITPOOL 2 /*#define APTX_CHANNEL_MODE_STEREO 2 */ diff --git a/src/modules/bluetooth/bluez4-util.c b/src/modules/bluetooth/bluez4-util.c index 7e7aed0..4fac115 100644 --- a/src/modules/bluetooth/bluez4-util.c +++ b/src/modules/bluetooth/bluez4-util.c @@ -1530,8 +1530,11 @@ static uint8_t a2dp_default_bitpool(uint8_t freq, uint8_t mode) { case SBC_CHANNEL_MODE_STEREO: case SBC_CHANNEL_MODE_JOINT_STEREO: +#if defined(__TIZEN_BT__) && defined(ADJUST_ANDROID_BITPOOL) + return 35; +#else return 53; - +#endif default: pa_log_warn("Invalid channel mode %u", mode); return 53; diff --git a/src/modules/bluetooth/bluez5-util.c b/src/modules/bluetooth/bluez5-util.c index 35c8adf..6ae4807 100644 --- a/src/modules/bluetooth/bluez5-util.c +++ b/src/modules/bluetooth/bluez5-util.c @@ -37,6 +37,9 @@ #include "hfaudioagent.h" #include "bluez5-util.h" +#ifdef BLUETOOTH_APTX_SUPPORT +#include +#endif #define BLUEZ_SERVICE "org.bluez" #define BLUEZ_ADAPTER_INTERFACE BLUEZ_SERVICE ".Adapter1" @@ -92,6 +95,56 @@ struct pa_bluetooth_discovery { PA_LLIST_HEAD(pa_dbus_pending, pending); }; +#ifdef BLUETOOTH_APTX_SUPPORT +static void *aptx_handle = NULL; + +int pa_unload_aptx(void) +{ + if (aptx_handle == NULL) { + pa_log_warn("Unable to unload apt-X library"); + return -1; + } + + dlclose(aptx_handle); + aptx_handle = NULL; + + pa_log_debug("unloaded apt-X library successfully"); + return 0; +} + +int pa_load_aptx(const char *aptx_lib_name) +{ + char* lib_path = NULL ; + + if(aptx_lib_name == NULL) + return -1; + + lib_path = pa_sprintf_malloc("%s/%s", PA_DLSEARCHPATH, aptx_lib_name); + + if (!lib_path) + return -1; + + pa_log_info("aptx_lib_path = [%s]", lib_path); + + aptx_handle = dlopen(lib_path, RTLD_LAZY); + if (aptx_handle == NULL) { + pa_log_warn("Unable to load apt-X library [%s]", dlerror()); + pa_xfree(lib_path); + return -1; + } + + pa_log_debug("loaded apt-X library successfully"); + pa_xfree(lib_path); + + return 0; +} + +void* pa_aptx_get_handle(void) +{ + return aptx_handle; +} +#endif + static pa_dbus_pending* send_and_add_to_pending(pa_bluetooth_discovery *y, DBusMessage *m, DBusPendingCallNotifyFunction func, void *call_data) { pa_dbus_pending *p; @@ -290,6 +343,25 @@ bool pa_bluetooth_device_any_transport_connected(const pa_bluetooth_device *d) { return false; } +#ifdef __TIZEN_BT__ +bool pa_bluetooth_device_sink_transport_connected(const pa_bluetooth_device *d) { + unsigned i; + + pa_assert(d); + + if (d->device_info_valid != 1) + return false; + + for (i = 0; i < PA_BLUETOOTH_PROFILE_COUNT; i++) + if (d->transports[i] && + d->transports[i]->profile == PA_BLUETOOTH_PROFILE_A2DP_SINK && + d->transports[i]->state != PA_BLUETOOTH_TRANSPORT_STATE_DISCONNECTED) + return true; + + return false; +} +#endif + static int transport_state_from_string(const char* value, pa_bluetooth_transport_state_t *state) { pa_assert(value); pa_assert(state); @@ -366,7 +438,12 @@ static pa_bluetooth_device* device_create(pa_bluetooth_discovery *y, const char d = pa_xnew0(pa_bluetooth_device, 1); d->discovery = y; d->path = pa_xstrdup(path); + +#ifdef __TIZEN_BT__ + d->uuids = pa_hashmap_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func); +#else d->uuids = pa_hashmap_new_full(pa_idxset_string_hash_func, pa_idxset_string_compare_func, NULL, pa_xfree); +#endif pa_hashmap_put(y->devices, d->path, d); @@ -733,8 +810,22 @@ static void register_endpoint(pa_bluetooth_discovery *y, const char *path, const pa_dbus_append_basic_variant_dict_entry(&d, "Codec", DBUS_TYPE_BYTE, &codec); if (pa_streq(uuid, PA_BLUETOOTH_UUID_A2DP_SOURCE) || pa_streq(uuid, PA_BLUETOOTH_UUID_A2DP_SINK)) { - a2dp_sbc_t capabilities; - +#ifdef __TIZEN_BT__ + if (codec == A2DP_CODEC_SBC) { + a2dp_sbc_t capabilities; + capabilities.channel_mode = SBC_CHANNEL_MODE_MONO | SBC_CHANNEL_MODE_DUAL_CHANNEL | SBC_CHANNEL_MODE_STEREO | + SBC_CHANNEL_MODE_JOINT_STEREO; + capabilities.frequency = SBC_SAMPLING_FREQ_16000 | SBC_SAMPLING_FREQ_32000 | SBC_SAMPLING_FREQ_44100 | + SBC_SAMPLING_FREQ_48000; + capabilities.allocation_method = SBC_ALLOCATION_SNR | SBC_ALLOCATION_LOUDNESS; + capabilities.subbands = SBC_SUBBANDS_4 | SBC_SUBBANDS_8; + capabilities.block_length = SBC_BLOCK_LENGTH_4 | SBC_BLOCK_LENGTH_8 | SBC_BLOCK_LENGTH_12 | SBC_BLOCK_LENGTH_16; + capabilities.min_bitpool = MIN_BITPOOL; + capabilities.max_bitpool = MAX_BITPOOL; + pa_dbus_append_basic_array_variant_dict_entry(&d, "Capabilities", DBUS_TYPE_BYTE, &capabilities, sizeof(capabilities)); + } +#else + a2dp_sbc_t capabilities; capabilities.channel_mode = SBC_CHANNEL_MODE_MONO | SBC_CHANNEL_MODE_DUAL_CHANNEL | SBC_CHANNEL_MODE_STEREO | SBC_CHANNEL_MODE_JOINT_STEREO; capabilities.frequency = SBC_SAMPLING_FREQ_16000 | SBC_SAMPLING_FREQ_32000 | SBC_SAMPLING_FREQ_44100 | @@ -746,7 +837,8 @@ static void register_endpoint(pa_bluetooth_discovery *y, const char *path, const capabilities.max_bitpool = MAX_BITPOOL; pa_dbus_append_basic_array_variant_dict_entry(&d, "Capabilities", DBUS_TYPE_BYTE, &capabilities, sizeof(capabilities)); - } +#endif /* __TIZEN_BT__ */ + } dbus_message_iter_close_container(&i, &d); @@ -795,8 +887,9 @@ static void parse_interfaces_and_properties(pa_bluetooth_discovery *y, DBusMessa return; register_endpoint(y, path, A2DP_SOURCE_ENDPOINT, PA_BLUETOOTH_UUID_A2DP_SOURCE); +#ifndef __TIZEN_BT__ register_endpoint(y, path, A2DP_SINK_ENDPOINT, PA_BLUETOOTH_UUID_A2DP_SINK); - +#endif } else if (pa_streq(interface, BLUEZ_DEVICE_INTERFACE)) { if ((d = pa_hashmap_get(y->devices, path))) { @@ -935,10 +1028,10 @@ static DBusHandlerResult filter_cb(DBusConnection *bus, DBusMessage *m, void *us return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; } else if (dbus_message_is_signal(m, "org.freedesktop.DBus.ObjectManager", "InterfacesAdded")) { DBusMessageIter arg_i; - +#ifndef __TIZEN_BT__ if (!y->objects_listed) return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; /* No reply received yet from GetManagedObjects */ - +#endif if (!dbus_message_iter_init(m, &arg_i) || !pa_streq(dbus_message_get_signature(m), "oa{sa{sv}}")) { pa_log_error("Invalid signature found in InterfacesAdded"); goto fail; @@ -986,8 +1079,10 @@ static DBusHandlerResult filter_cb(DBusConnection *bus, DBusMessage *m, void *us DBusMessageIter arg_i; const char *iface; +#ifndef __TIZEN_BT__ if (!y->objects_listed) return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; /* No reply received yet from GetManagedObjects */ +#endif if (!dbus_message_iter_init(m, &arg_i) || !pa_streq(dbus_message_get_signature(m), "sa{sv}as")) { pa_log_error("Invalid signature found in PropertiesChanged"); @@ -1063,7 +1158,11 @@ static uint8_t a2dp_default_bitpool(uint8_t freq, uint8_t mode) { case SBC_CHANNEL_MODE_STEREO: case SBC_CHANNEL_MODE_JOINT_STEREO: +#if defined(__TIZEN_BT__) && defined(ADJUST_ANDROID_BITPOOL) + return 35; +#else return 53; +#endif } pa_log_warn("Invalid channel mode %u", mode); @@ -1111,6 +1210,9 @@ static DBusMessage *endpoint_set_configuration(DBusConnection *conn, DBusMessage pa_bluetooth_device *d; pa_bluetooth_transport *t; const char *sender, *path, *endpoint_path, *dev_path = NULL, *uuid = NULL; +#ifdef __TIZEN_BT__ + uint8_t codec = 0; +#endif const uint8_t *config = NULL; int size = 0; pa_bluetooth_profile_t p = PA_BLUETOOTH_PROFILE_OFF; @@ -1170,6 +1272,15 @@ static DBusMessage *endpoint_set_configuration(DBusConnection *conn, DBusMessage pa_log_error("UUID %s of transport %s incompatible with endpoint %s", uuid, path, endpoint_path); goto fail; } +#ifdef __TIZEN_BT__ + } else if (pa_streq(key, "Codec")) { + if (var != DBUS_TYPE_BYTE) { + pa_log_error("Property %s of wrong type %c", key, (char)var); + goto fail; + } + + dbus_message_iter_get_basic(&value, &codec); +#endif } else if (pa_streq(key, "Device")) { if (var != DBUS_TYPE_OBJECT_PATH) { pa_log_error("Property %s of wrong type %c", key, (char)var); @@ -1256,6 +1367,11 @@ static DBusMessage *endpoint_set_configuration(DBusConnection *conn, DBusMessage dbus_message_unref(r); d->transports[p] = t = pa_bluetooth_transport_new(d, sender, path, p, config, size); +#ifdef __TIZEN_BT__ + t->codec = codec; + d->transports[p] = t; +#endif + t->acquire = bluez5_transport_acquire_cb; t->release = bluez5_transport_release_cb; pa_bluetooth_transport_put(t); @@ -1575,8 +1691,11 @@ pa_bluetooth_discovery* pa_bluetooth_discovery_get(pa_core *c) { y->matches_added = true; endpoint_init(y, PA_BLUETOOTH_PROFILE_A2DP_SINK); + +#ifndef __TIZEN_BT__ endpoint_init(y, PA_BLUETOOTH_PROFILE_A2DP_SOURCE); y->hf_audio_agent = hf_audio_agent_init(c); +#endif get_managed_objects(y); @@ -1618,8 +1737,10 @@ void pa_bluetooth_discovery_unref(pa_bluetooth_discovery *y) { pa_hashmap_free(y->transports); } +#ifndef __TIZEN_BT__ if (y->hf_audio_agent) hf_audio_agent_done(y->hf_audio_agent); +#endif if (y->connection) { @@ -1643,8 +1764,10 @@ void pa_bluetooth_discovery_unref(pa_bluetooth_discovery *y) { dbus_connection_remove_filter(pa_dbus_connection_get(y->connection), filter_cb, y); endpoint_done(y, PA_BLUETOOTH_PROFILE_A2DP_SINK); - endpoint_done(y, PA_BLUETOOTH_PROFILE_A2DP_SOURCE); +#ifndef __TIZEN_BT__ + endpoint_done(y, PA_BLUETOOTH_PROFILE_A2DP_SOURCE); +#endif pa_dbus_connection_unref(y->connection); } diff --git a/src/modules/bluetooth/bluez5-util.h b/src/modules/bluetooth/bluez5-util.h index 841c3c6..9d6c4c4 100644 --- a/src/modules/bluetooth/bluez5-util.h +++ b/src/modules/bluetooth/bluez5-util.h @@ -108,6 +108,9 @@ void pa_bluetooth_transport_put(pa_bluetooth_transport *t); void pa_bluetooth_transport_free(pa_bluetooth_transport *t); bool pa_bluetooth_device_any_transport_connected(const pa_bluetooth_device *d); +#ifdef __TIZEN_BT__ +bool pa_bluetooth_device_sink_transport_connected(const pa_bluetooth_device *d); +#endif pa_bluetooth_device* pa_bluetooth_discovery_get_device_by_path(pa_bluetooth_discovery *y, const char *path); pa_bluetooth_device* pa_bluetooth_discovery_get_device_by_address(pa_bluetooth_discovery *y, const char *remote, const char *local); @@ -119,4 +122,12 @@ const char *pa_bluetooth_profile_to_string(pa_bluetooth_profile_t profile); pa_bluetooth_discovery* pa_bluetooth_discovery_get(pa_core *core); pa_bluetooth_discovery* pa_bluetooth_discovery_ref(pa_bluetooth_discovery *y); void pa_bluetooth_discovery_unref(pa_bluetooth_discovery *y); + +/* +#ifdef BLUETOOTH_APTX_SUPPORT +int pa_load_aptx(const char *aptx_lib_name); +int pa_unload_aptx(void); +void* pa_aptx_get_handle(void); +#endif +*/ #endif diff --git a/src/modules/bluetooth/module-bluetooth-discover.c b/src/modules/bluetooth/module-bluetooth-discover.c index e1dbec5..d78a1b1 100644 --- a/src/modules/bluetooth/module-bluetooth-discover.c +++ b/src/modules/bluetooth/module-bluetooth-discover.c @@ -26,6 +26,11 @@ #include #include #include +#ifdef BLUETOOTH_APTX_SUPPORT +#include +//#include "bluez5-util.h" +#include +#endif #include "module-bluetooth-discover-symdef.h" @@ -41,6 +46,9 @@ PA_MODULE_USAGE("aptx_lib_name="); #ifdef BLUETOOTH_APTX_SUPPORT static const char* const valid_modargs[] = { "aptx_lib_name", +#ifdef __TIZEN_BT__ + "enable_scmst", +#endif NULL }; #endif @@ -49,6 +57,61 @@ struct userdata { uint32_t bluez5_module_idx; uint32_t bluez4_module_idx; }; +#ifdef BLUETOOTH_APTX_SUPPORT +int pa_load_aptx(const char *aptx_lib_name); +int pa_unload_aptx(void); +void* pa_aptx_get_handle(void); +#endif + +#ifdef BLUETOOTH_APTX_SUPPORT +static void *aptx_handle = NULL; + +int pa_unload_aptx(void) +{ + if (aptx_handle == NULL) { + pa_log_warn("Unable to unload apt-X library"); + return -1; + } + + dlclose(aptx_handle); + aptx_handle = NULL; + + pa_log_debug("unloaded apt-X library successfully"); + return 0; +} + +int pa_load_aptx(const char *aptx_lib_name) +{ + char* lib_path = NULL ; + + if(aptx_lib_name == NULL) + return -1; + + lib_path = pa_sprintf_malloc("%s/%s", PA_DLSEARCHPATH, aptx_lib_name); + + if (!lib_path) + return -1; + + pa_log_info("aptx_lib_path = [%s]", lib_path); + + aptx_handle = dlopen(lib_path, RTLD_LAZY); + if (aptx_handle == NULL) { + pa_log_warn("Unable to load apt-X library [%s]", dlerror()); + pa_xfree(lib_path); + return -1; + } + + pa_log_debug("loaded apt-X library successfully"); + pa_xfree(lib_path); + + return 0; +} + +void* pa_aptx_get_handle(void) +{ + return aptx_handle; +} +#endif int pa__init(pa_module* m) { struct userdata *u; @@ -64,7 +127,8 @@ int pa__init(pa_module* m) { #ifdef BLUETOOTH_APTX_SUPPORT if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { pa_log("Failed to parse module arguments"); - goto fail; + pa__done(m); + return -1; } if (pa_modargs_get_value(ma, "async", NULL)) @@ -96,8 +160,14 @@ int pa__init(pa_module* m) { if (u->bluez5_module_idx == PA_INVALID_INDEX && u->bluez4_module_idx == PA_INVALID_INDEX) { pa_xfree(u); +#ifdef BLUETOOTH_APTX_SUPPORT + pa_modargs_free(ma); +#endif return -1; } +#ifdef BLUETOOTH_APTX_SUPPORT + pa_modargs_free(ma); +#endif return 0; } diff --git a/src/modules/bluetooth/module-bluez5-device.c b/src/modules/bluetooth/module-bluez5-device.c index 790dcf1..3f329d1 100644 --- a/src/modules/bluetooth/module-bluez5-device.c +++ b/src/modules/bluetooth/module-bluez5-device.c @@ -29,6 +29,10 @@ #include #include +#ifdef BLUETOOTH_APTX_SUPPORT +#include +#endif + #include #include @@ -69,6 +73,10 @@ PA_MODULE_USAGE("path="); static const char* const valid_modargs[] = { "path", +#ifdef __TIZEN_BT__ + "address", + "profile", +#endif NULL }; @@ -92,7 +100,12 @@ typedef struct sbc_info { uint16_t seq_num; /* Cumulative packet sequence */ uint8_t min_bitpool; uint8_t max_bitpool; - +#ifdef __TIZEN_BT__ +#ifdef BLUETOOTH_APTX_SUPPORT + pa_bool_t aptx_initialized; /* Keep track if the encoder is initialized */ + void *aptx; /* aptx Codec data */ +#endif +#endif void* buffer; /* Codec transfer buffer */ size_t buffer_size; /* Size of the buffer */ } sbc_info_t; @@ -109,6 +122,10 @@ struct userdata { pa_bluetooth_transport *transport; bool transport_acquired; +#ifdef __TIZEN_BT__ + bool transport_suspended_by_remote; +#endif + pa_card *card; pa_sink *sink; pa_source *source; @@ -135,6 +152,10 @@ struct userdata { pa_memchunk write_memchunk; pa_sample_spec sample_spec; struct sbc_info sbc_info; + +#ifdef __TIZEN_BT__ + pa_modargs *modargs; +#endif }; typedef enum pa_bluetooth_form_factor { @@ -219,6 +240,44 @@ static const char *form_factor_to_string(pa_bluetooth_form_factor_t ff) { pa_assert_not_reached(); } +#ifdef __TIZEN_BT__ +#ifdef BLUETOOTH_APTX_SUPPORT +void* (*aptx_new)(short endian); +int (*aptx_encode)(void* _state, void* _pcmL, void* _pcmR, void* _buffer); + +const char *aptx_new_name = "NewAptxEnc"; +const char *aptx_encode_name = "aptxbtenc_encodestereo"; + +static pa_bool_t pa_load_aptx_sym(void *handle ) +{ + if (!handle) + return false; + + aptx_new = (void* (*)(short endian))dlsym(handle, aptx_new_name); + + if (aptx_new) { + pa_log_debug("Load Symbol(%s)", aptx_new_name); + } else { + pa_log_debug("Fail to Load Symbol(%s)", aptx_new_name); + return false; + } + + aptx_encode = (int (*)(void* _state, void* _pcmL, void* _pcmR, + void* _buffer)) + dlsym(handle, "aptxbtenc_encodestereo"); + + if (aptx_encode) { + pa_log_debug("Load Symbol(%s)", aptx_encode_name); + } else { + pa_log_debug("Fail to Load Symbol(%s)", aptx_encode_name); + return false; + } + + return true; +} +#endif +#endif + /* Run from main thread */ static void connect_ports(struct userdata *u, void *new_data, pa_direction_t direction) { pa_device_port *port; @@ -544,6 +603,142 @@ static int a2dp_process_render(struct userdata *u) { return ret; } +#ifdef BLUETOOTH_APTX_SUPPORT +/* Run from IO thread */ +static int a2dp_aptx_process_render(struct userdata *u) { + struct sbc_info *a2dp; + size_t nbytes; + void *d; + const void *p; + size_t to_write, to_encode; + int ret = 0; + + int pcmL[4],pcmR[4]; + int i=0; + const short *mybuffer; + + pa_assert(u); + pa_assert(u->profile == PA_BLUETOOTH_PROFILE_A2DP_SINK); + pa_assert(u->sink); + + /* First, render some data */ + if (!u->write_memchunk.memblock) + pa_sink_render_full(u->sink, u->write_block_size, &u->write_memchunk); + + pa_assert(u->write_memchunk.length == u->write_block_size); + + a2dp_prepare_buffer(u); + + a2dp = &u->sbc_info; + + /* Try to create a packet of the full MTU */ + p = (const uint8_t*) pa_memblock_acquire(u->write_memchunk.memblock) + u->write_memchunk.index; + to_encode = u->write_memchunk.length; + + d = (uint8_t*) a2dp->buffer ; + to_write = a2dp->buffer_size; + + while (PA_LIKELY(to_encode > 0 && to_write > 0)) { + size_t written; + ssize_t encoded; + + mybuffer=(uint8_t *)p; + + for (i = 0; i < 4; i += 1) { + pcmL[i] = mybuffer[2*i]; + pcmR[i] = mybuffer[2*i+1]; + } + /*(8 audio samples)16 bytes of audo data encoded to 4 bytes*/ + aptx_encode(a2dp->aptx, pcmL, pcmR, (short*)d); + + encoded=16; + written=4; + + pa_assert_fp((size_t) encoded <= to_encode); + pa_assert_fp((size_t) written <= to_write); + + p = (const uint8_t*) p + encoded; + to_encode -= encoded; + + d = (uint8_t*) d + written; + to_write -= written; + + } + + pa_memblock_release(u->write_memchunk.memblock); + + pa_assert(to_encode == 0); + + PA_ONCE_BEGIN { + pa_log_debug("Using APTX encoder implementation"); + } PA_ONCE_END; + + nbytes = (uint8_t*) d - (uint8_t*) a2dp->buffer; + + for (;;) { + ssize_t l; + + l = pa_write(u->stream_fd, a2dp->buffer, nbytes, &u->stream_write_type); + + pa_assert(l != 0); + + if (l < 0) { + + if (errno == EINTR) + /* Retry right away if we got interrupted */ + continue; + + else if (errno == EAGAIN) + /* Hmm, apparently the socket was not writable, give up for now */ + break; + + pa_log_error("Failed to write data to socket: %s", pa_cstrerror(errno)); + ret = -1; + break; + } + + pa_assert((size_t) l <= nbytes); + + if ((size_t) l != nbytes) { + pa_log_warn("Wrote memory block to socket only partially! %llu written, wanted to write %llu.", + (unsigned long long) l, + (unsigned long long) nbytes); + ret = -1; + break; + } + + u->write_index += (uint64_t) u->write_memchunk.length; + pa_memblock_unref(u->write_memchunk.memblock); + pa_memchunk_reset(&u->write_memchunk); + + ret = 1; + + break; + } + + return ret; +} + +/* Run from IO thread */ +static int a2dp_process_null_render(struct userdata *u) { + pa_assert(u); + pa_assert(u->profile == PA_BLUETOOTH_PROFILE_A2DP_SINK); + pa_assert(u->sink); + + /* First, render some data */ + if (!u->write_memchunk.memblock) + pa_sink_render_full(u->sink, u->write_block_size, &u->write_memchunk); + + pa_assert(u->write_memchunk.length == u->write_block_size); + + u->write_index += (uint64_t) u->write_memchunk.length; + pa_memblock_unref(u->write_memchunk.memblock); + pa_memchunk_reset(&u->write_memchunk); + + return 1; +} +#endif + /* Run from IO thread */ static int a2dp_process_push(struct userdata *u) { int ret = 0; @@ -750,6 +945,10 @@ static int transport_acquire(struct userdata *u, bool optional) { return -1; u->transport_acquired = true; + +#ifdef __TIZEN_BT__ + u->transport_suspended_by_remote = false; +#endif pa_log_info("Transport %s acquired: fd %d", u->transport->path, u->stream_fd); return 0; @@ -768,6 +967,12 @@ static void transport_release(struct userdata *u) { u->transport_acquired = false; +#ifdef __TIZEN_BT__ + /* The below code would be less effect for most of case */ + if (u->transport_suspended_by_remote) + pa_log_info("Released by remote suspend request"); +#endif + if (u->profile == PA_BLUETOOTH_PROFILE_HEADSET_AUDIO_GATEWAY) { u->transport->state = PA_BLUETOOTH_TRANSPORT_STATE_IDLE; pa_asyncmsgq_post(pa_thread_mq_get()->outq, PA_MSGOBJECT(u->msg), BLUETOOTH_MESSAGE_TRANSPORT_STATE_CHANGED, u, 0, @@ -782,7 +987,11 @@ static void transport_config_mtu(struct userdata *u) { if (u->profile == PA_BLUETOOTH_PROFILE_HEADSET_HEAD_UNIT || u->profile == PA_BLUETOOTH_PROFILE_HEADSET_AUDIO_GATEWAY) { u->read_block_size = u->read_link_mtu; u->write_block_size = u->write_link_mtu; +#ifdef __TIZEN_BT__ + } else if(u->sbc_info.sbc_initialized) { +#else } else { +#endif u->read_block_size = (u->read_link_mtu - sizeof(struct rtp_header) - sizeof(struct rtp_payload)) / u->sbc_info.frame_length * u->sbc_info.codesize; @@ -994,7 +1203,15 @@ static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offse case PA_SINK_RUNNING: if (u->sink->thread_info.state != PA_SINK_SUSPENDED) break; - +#ifdef __TIZEN_BT__ + /* Wait until PA_BLUETOOTH_TRANSPORT_IDLE */ + if ((u->transport != NULL) && (u->transport->state == + PA_BLUETOOTH_TRANSPORT_STATE_IDLE)) + pa_log_info("This is good time for(%d)", + (pa_sink_state_t) PA_PTR_TO_UINT(data)); + else + pa_log_info("Wait for PA_BLUETOOTH_TRANSPORT_STATE_IDLE"); +#endif /* Resume the device if the source was suspended as well */ if (!u->source || !PA_SOURCE_IS_OPENED(u->source->thread_info.state)) { if (transport_acquire(u, false) < 0) @@ -1357,10 +1574,29 @@ static void thread_func(void *userdata) { if (u->write_index <= 0) u->started_at = pa_rtclock_now(); - - if (u->profile == PA_BLUETOOTH_PROFILE_A2DP_SINK) { +#ifdef __TIZEN_BT__ + if ((u->profile == PA_BLUETOOTH_PROFILE_A2DP_SINK) && + !u->transport_suspended_by_remote) { + if(u->sbc_info.sbc_initialized) { + if ((n_written = a2dp_process_render(u)) < 0) + goto io_fail; + } +#ifdef BLUETOOTH_APTX_SUPPORT + else { + if ((n_written = a2dp_aptx_process_render(u)) < 0) + goto io_fail; + } +#endif + } else if ((u->profile == PA_BLUETOOTH_PROFILE_A2DP_SINK) && + u->transport_suspended_by_remote) { +#ifdef BLUETOOTH_APTX_SUPPORT + a2dp_process_null_render(u); +#endif +#else + if (u->profile == PA_BLUETOOTH_PROFILE_A2DP_SINK ) { if ((n_written = a2dp_process_render(u)) < 0) goto io_fail; +#endif } else { if ((n_written = sco_process_render(u)) < 0) goto io_fail; @@ -1728,7 +1964,7 @@ static pa_card_profile *create_card_profile(struct userdata *u, const char *uuid if (pa_streq(uuid, PA_BLUETOOTH_UUID_A2DP_SINK)) { /* TODO: Change this profile's name to a2dp_sink, to reflect the remote * device's role and be consistent with the a2dp source profile */ - cp = pa_card_profile_new("a2dp", _("High Fidelity Playback (A2DP Sink)"), sizeof(pa_bluetooth_profile_t)); + cp = pa_card_profile_new("a2dp_sink", _("High Fidelity Playback (A2DP Sink)"), sizeof(pa_bluetooth_profile_t)); cp->priority = 10; cp->n_sinks = 1; cp->n_sources = 0; @@ -1738,6 +1974,7 @@ static pa_card_profile *create_card_profile(struct userdata *u, const char *uuid p = PA_CARD_PROFILE_DATA(cp); *p = PA_BLUETOOTH_PROFILE_A2DP_SINK; +#ifndef __TIZEN_BT__ } else if (pa_streq(uuid, PA_BLUETOOTH_UUID_A2DP_SOURCE)) { cp = pa_card_profile_new("a2dp_source", _("High Fidelity Capture (A2DP Source)"), sizeof(pa_bluetooth_profile_t)); cp->priority = 10; @@ -1777,6 +2014,7 @@ static pa_card_profile *create_card_profile(struct userdata *u, const char *uuid p = PA_CARD_PROFILE_DATA(cp); *p = PA_BLUETOOTH_PROFILE_HEADSET_AUDIO_GATEWAY; +#endif } if (cp && u->device->transports[*p]) @@ -1837,6 +2075,9 @@ static int add_card(struct userdata *u) { pa_bluetooth_profile_t *p; const char *uuid; void *state; +#ifdef __TIZEN_BT__ + const char *default_profile; +#endif pa_assert(u); pa_assert(u->device); @@ -1890,6 +2131,17 @@ static int add_card(struct userdata *u) { pa_hashmap_put(data.profiles, cp->name, cp); pa_card_new_data_set_profile(&data, "off"); +#ifdef __TIZEN_BT__ + if ((default_profile = pa_modargs_get_value(u->modargs, "profile", NULL))) { + pa_log_debug("default_profile: %s", default_profile); + + if (pa_hashmap_get(data.profiles, default_profile)) + pa_card_new_data_set_profile(&data, default_profile); + else + pa_log_warn("Profile '%s' not valid or not supported by device.", default_profile); + } +#endif + u->card = pa_card_new(u->core, &data); pa_card_new_data_done(&data); if (!u->card) { @@ -1948,6 +2200,9 @@ static void handle_transport_state_change(struct userdata *u, struct pa_bluetoot if (u->sink) { pa_log_debug("Resuming sink %s because its transport state changed to playing", u->sink->name); +#ifdef __TIZEN_BT__ + u->transport_suspended_by_remote = false; +#endif /* FIXME: See the previous comment. */ pa_sink_suspend(u->sink, false, PA_SUSPEND_IDLE|PA_SUSPEND_USER); } @@ -1967,7 +2222,13 @@ static void handle_transport_state_change(struct userdata *u, struct pa_bluetoot if (u->sink) { pa_log_debug("Suspending sink %s because the remote end closed the stream", u->sink->name); +#ifdef __TIZEN_BT__ + /* if we change PA state as Suspend, PA client application + * such as music app would face lock-up */ + u->transport_suspended_by_remote = true; +#else pa_sink_suspend(u->sink, true, PA_SUSPEND_USER); +#endif } } } @@ -2037,6 +2298,11 @@ int pa__init(pa_module* m) { goto fail; } +#ifdef __TIZEN_BT__ + u->sample_spec = m->core->default_sample_spec; + u->modargs = ma; +#endif + if (!(path = pa_modargs_get_value(ma, "path", NULL))) { pa_log_error("Failed to get device path from module arguments"); goto fail; @@ -2054,7 +2320,9 @@ int pa__init(pa_module* m) { goto fail; } +#ifndef __TIZEN_BT__ pa_modargs_free(ma); +#endif u->device_connection_changed_slot = pa_hook_connect(pa_bluetooth_discovery_hook(u->discovery, PA_BLUETOOTH_HOOK_DEVICE_CONNECTION_CHANGED), @@ -2067,6 +2335,9 @@ int pa__init(pa_module* m) { if (add_card(u) < 0) goto fail; +#ifdef __TIZEN_BT__ + pa_modargs_free(ma); +#endif if (!(u->msg = pa_msgobject_new(bluetooth_msg))) goto fail; diff --git a/src/modules/bluetooth/module-bluez5-discover.c b/src/modules/bluetooth/module-bluez5-discover.c index 0b7bf49..5930992 100644 --- a/src/modules/bluetooth/module-bluez5-discover.c +++ b/src/modules/bluetooth/module-bluez5-discover.c @@ -28,7 +28,9 @@ #include #include #include - +#ifdef __TIZEN_BT__ +#include +#endif #include "bluez5-util.h" #include "module-bluez5-discover-symdef.h" @@ -36,8 +38,21 @@ PA_MODULE_AUTHOR("João Paulo Rechi Vita"); PA_MODULE_DESCRIPTION("Detect available BlueZ 5 Bluetooth audio devices and load BlueZ 5 Bluetooth audio drivers"); PA_MODULE_VERSION(PACKAGE_VERSION); +#ifdef __TIZEN_BT__ +PA_MODULE_USAGE("sco_sink= " + "sco_source= " +); +#endif PA_MODULE_LOAD_ONCE(true); +#ifdef __TIZEN_BT__ +static const char* const valid_modargs[] = { + "sco_sink", + "sco_source", + NULL +}; +#endif + struct userdata { pa_module *module; pa_core *core; @@ -64,7 +79,20 @@ static pa_hook_result_t device_connection_changed_cb(pa_bluetooth_discovery *y, if (!module_loaded && pa_bluetooth_device_any_transport_connected(d)) { /* a new device has been connected */ pa_module *m; - char *args = pa_sprintf_malloc("path=%s", d->path); + +#ifdef __TIZEN_BT__ + char *args = pa_sprintf_malloc("address=\"%s\" path=\"%s\"", d->address, d->path); +#else + char *args = pa_sprintf_malloc("path=%s", d->path); +#endif + +#ifdef __TIZEN_BT__ + if (pa_bluetooth_device_sink_transport_connected(d) == true) { + char *tmp = pa_sprintf_malloc("%s profile=\"a2dp_sink\"", args); + pa_xfree(args); + args = tmp; + } +#endif pa_log_debug("Loading module-bluez5-device %s", args); m = pa_module_load(u->module->core, "module-bluez5-device", args); -- 2.7.4