Linux bluetooth development
 help / color / mirror / Atom feed
* Re: [PATCH 8/9] android/hal-audio: Read fd from Output Stream response
From: Luiz Augusto von Dentz @ 2014-01-17 19:57 UTC (permalink / raw)
  To: Szymon Janc; +Cc: Andrzej Kaczmarek, linux-bluetooth@vger.kernel.org
In-Reply-To: <1772554.HcRPMI1tWs@athlon>

Hi Szymon,

On Fri, Jan 17, 2014 at 8:13 PM, Szymon Janc <szymon.janc@gmail.com> wrote:
> Hi Andrzej,
>
> On Friday 17 January 2014 16:40:12 Andrzej Kaczmarek wrote:
>> ---
>>  android/hal-audio.c | 11 +++++++----
>>  1 file changed, 7 insertions(+), 4 deletions(-)
>>
>> diff --git a/android/hal-audio.c b/android/hal-audio.c
>> index f2cb12a..d8438f7 100644
>> --- a/android/hal-audio.c
>> +++ b/android/hal-audio.c
>> @@ -575,7 +575,7 @@ static int ipc_close_cmd(uint8_t endpoint_id)
>>       return result;
>>  }
>>
>> -static int ipc_open_stream_cmd(uint8_t endpoint_id, uint16_t *mtu,
>> +static int ipc_open_stream_cmd(uint8_t endpoint_id, uint16_t *mtu, int *fd,
>> struct audio_preset **caps)
>>  {
>>       char buf[BLUEZ_AUDIO_MTU];
>> @@ -593,7 +593,7 @@ static int ipc_open_stream_cmd(uint8_t endpoint_id,
>> uint16_t *mtu, cmd.id = endpoint_id;
>>
>>       result = audio_ipc_cmd(AUDIO_SERVICE_ID, AUDIO_OP_OPEN_STREAM,
>> -                             sizeof(cmd), &cmd, &rsp_len, rsp, NULL);
>> +                             sizeof(cmd), &cmd, &rsp_len, rsp, fd);
>>
>>       if (result == AUDIO_STATUS_SUCCESS) {
>>               size_t buf_len = sizeof(struct audio_preset) +
>> @@ -990,6 +990,7 @@ static int audio_open_output_stream(struct
>> audio_hw_device *dev, struct audio_preset *preset;
>>       const struct audio_codec *codec;
>>       uint16_t mtu;
>> +     int fd;
>>
>>       out = calloc(1, sizeof(struct a2dp_stream_out));
>>       if (!out)
>> @@ -1017,13 +1018,15 @@ static int audio_open_output_stream(struct
>> audio_hw_device *dev, /* TODO: for now we always use endpoint 0 */
>>       out->ep = &audio_endpoints[0];
>>
>> -     if (ipc_open_stream_cmd(out->ep->id, &mtu, &preset) !=
>> +     if (ipc_open_stream_cmd(out->ep->id, &mtu, &fd, &preset) !=
>>                       AUDIO_STATUS_SUCCESS)
>>               goto fail;
>>
>> -     if (!preset)
>> +     if (!preset || fd < 0)
>>               goto fail;
>
> For sanity, code under fail label should be updated to handle that either
> preset or fd might be valid here.
>
>>
>> +     out->ep->fd = fd;
>> +
>
> I might be missing something but fd is never closed. Should this be done in
> audio_close_output_stream() ?

Yep, the fd should be closed every time we suspend as we will get
another fd on open so we will end up with duplicated fds.


-- 
Luiz Augusto von Dentz

^ permalink raw reply

* Re: [RFC v2 1/6] android: Add sample init.bluetooth.rc file
From: Szymon Janc @ 2014-01-17 19:47 UTC (permalink / raw)
  To: Szymon Janc; +Cc: linux-bluetooth
In-Reply-To: <1389972646-3761-1-git-send-email-szymon.janc@tieto.com>

Hi,

On Friday 17 January 2014 16:30:41 Szymon Janc wrote:
> This file is intended to be included from device init.rc.
> ---
>  android/Android.mk        | 16 +++++++++++++++-
>  android/Makefile.am       |  1 +
>  android/init.bluetooth.rc | 37 +++++++++++++++++++++++++++++++++++++
>  3 files changed, 53 insertions(+), 1 deletion(-)
>  create mode 100644 android/init.bluetooth.rc
> 
> diff --git a/android/Android.mk b/android/Android.mk
> index 7e97ec8..afa3a51 100644
> --- a/android/Android.mk
> +++ b/android/Android.mk
> @@ -109,7 +109,7 @@ LOCAL_MODULE := bluetooth.default
>  LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw
>  LOCAL_MODULE_TAGS := optional
>  LOCAL_MODULE_CLASS := SHARED_LIBRARIES
> -LOCAL_REQUIRED_MODULES := bluetoothd bluetoothd-snoop
> +LOCAL_REQUIRED_MODULES := bluetoothd bluetoothd-snoop init.bluetooth.rc
> 
>  include $(BUILD_SHARED_LIBRARY)
> 
> @@ -282,3 +282,17 @@ LOCAL_MODULE_TAGS := optional
>  LOCAL_MODULE := bluetoothd-snoop
> 
>  include $(BUILD_EXECUTABLE)
> +
> +#
> +# init.bluetooth.rc
> +#
> +
> +include $(CLEAR_VARS)
> +
> +LOCAL_MODULE := init.bluetooth.rc
> +LOCAL_MODULE_CLASS := ETC
> +LOCAL_SRC_FILES := $(LOCAL_MODULE)
> +LOCAL_MODULE_TAGS := optional
> +LOCAL_MODULE_PATH := $(TARGET_ROOT_OUT)
> +
> +include $(BUILD_PREBUILT)
> diff --git a/android/Makefile.am b/android/Makefile.am
> index 8d2714d..5aa3995 100644
> --- a/android/Makefile.am
> +++ b/android/Makefile.am
> @@ -136,6 +136,7 @@ android_audio_a2dp_default_la_LDFLAGS = $(AM_LDFLAGS)
> -module -avoid-version \ endif
> 
>  EXTRA_DIST += android/Android.mk android/hal-ipc-api.txt android/README \
> +		android/init.bluetooth.rc \
>  		android/pics-gap.txt android/pics-hid.txt \
>  		android/pics-pan.txt android/pics-did.txt \
>  		android/pics-opp.txt android/pics-pbap.txt \
> diff --git a/android/init.bluetooth.rc b/android/init.bluetooth.rc
> new file mode 100644
> index 0000000..9f9aa84
> --- /dev/null
> +++ b/android/init.bluetooth.rc
> @@ -0,0 +1,37 @@
> +# required permissions
> +on boot
> +    chown bluetooth bluetooth /data/misc/bluetooth
> +    chown bluetooth bluetooth /dev/uhid
> +
> +# services
> +on property:bluetooth.start=daemon
> +    setprop bluetooth.start none
> +    start bluetoothd
> +
> +on property:bluetooth.stop=daemon
> +    setprop bluetooth.stop none
> +    stop bluetoothd
> +
> +on property:bluetooth.start=snoop
> +    setprop bluetooth.start none
> +    start bluetoothd-snoop
> +
> +on property:bluetooth.stop=snoop
> +    setprop bluetooth.stop none
> +    stop bluetoothd-snoop
> +
> +service bluetoothd /system/bin/logwrapper /system/bin/bluetoothd
> +    class main
> +    # init does not yet support setting capabilities so run as root,
> +    # bluetoothd drop uid to bluetooth with the right linux capabilities
> +    group bluetooth
> +    disabled
> +    oneshot
> +
> +service bluetoothd-snoop /system/bin/logwrapper
> /system/bin/bluetoothd-snoop +    class main
> +    # init does not yet support setting capabilities so run as root,
> +    # bluetoothd-snoop drops unneeded linux capabilities
> +    group nobody
> +    disabled
> +    oneshot

This is now upstream.

-- 
Szymon K. Janc
szymon.janc@gmail.com

^ permalink raw reply

* Re: [PATCH 5/9] android/hal-audio: Calculate SBC stream parameters
From: Luiz Augusto von Dentz @ 2014-01-17 19:42 UTC (permalink / raw)
  To: Andrzej Kaczmarek
  Cc: Marcel Holtmann, linux-bluetooth@vger.kernel.org development
In-Reply-To: <CAF3PWx0KN9mtfy=czsmjYPEZj_c6X_buPBOAtbirdyQm01QqJw@mail.gmail.com>

Hi Andrzej,

On Fri, Jan 17, 2014 at 9:17 PM, Andrzej Kaczmarek
<andrzej.kaczmarek@tieto.com> wrote:
> Hi Marcel,
>
> On 17 January 2014 19:25, Marcel Holtmann <marcel@holtmann.org> wrote:
>> Hi Andrzej,
>>
>>> This patch adds necessary calculations for SBC stream parameters.
>>>
>>> Both input and output buffers are expected to have exact amount of
>>> data to fill single media packet (based on transport channel MTU).
>>>
>>> Frame duration will be used to synchronize input and output streams.
>>> ---
>>> android/hal-audio.c | 50 ++++++++++++++++++++++++++++++-----
>>> android/rtp.h       | 76 +++++++++++++++++++++++++++++++++++++++++++++++++++++
>>> 2 files changed, 120 insertions(+), 6 deletions(-)
>>> create mode 100644 android/rtp.h
>>>
>>> diff --git a/android/hal-audio.c b/android/hal-audio.c
>>> index e5c646c..3f53295 100644
>>> --- a/android/hal-audio.c
>>> +++ b/android/hal-audio.c
>>> @@ -33,6 +33,7 @@
>>> #include "hal-msg.h"
>>> #include "../profiles/audio/a2dp-codecs.h"
>>> #include <sbc/sbc.h>
>>> +#include "rtp.h"
>>>
>>> static const uint8_t a2dp_src_uuid[] = {
>>>               0x00, 0x00, 0x11, 0x0a, 0x00, 0x00, 0x10, 0x00,
>>> @@ -46,6 +47,12 @@ static pthread_t ipc_th = 0;
>>> static pthread_mutex_t close_mutex = PTHREAD_MUTEX_INITIALIZER;
>>> static pthread_mutex_t sk_mutex = PTHREAD_MUTEX_INITIALIZER;
>>>
>>> +struct media_packet {
>>> +     struct rtp_header hdr;
>>> +     struct rtp_payload payload;
>>> +     uint8_t data[0];
>>> +};
>>> +
>>> struct audio_input_config {
>>>       uint32_t rate;
>>>       uint32_t channels;
>>> @@ -56,10 +63,19 @@ struct sbc_data {
>>>       a2dp_sbc_t sbc;
>>>
>>>       sbc_t enc;
>>> +
>>> +     size_t in_frame_len;
>>> +     size_t in_buf_size;
>>> +
>>> +     size_t out_buf_size;
>>> +     uint8_t *out_buf;
>>> +
>>> +     unsigned frame_duration;
>>> };
>>>
>>> static int sbc_get_presets(struct audio_preset *preset, size_t *len);
>>> -static int sbc_codec_init(struct audio_preset *preset, void **codec_data);
>>> +static int sbc_codec_init(struct audio_preset *preset, uint16_t mtu,
>>> +                             void **codec_data);
>>> static int sbc_cleanup(void *codec_data);
>>> static int sbc_get_config(void *codec_data,
>>>                                       struct audio_input_config *config);
>>> @@ -69,7 +85,8 @@ struct audio_codec {
>>>
>>>       int (*get_presets) (struct audio_preset *preset, size_t *len);
>>>
>>> -     int (*init) (struct audio_preset *preset, void **codec_data);
>>> +     int (*init) (struct audio_preset *preset, uint16_t mtu,
>>> +                             void **codec_data);
>>>       int (*cleanup) (void *codec_data);
>>>       int (*get_config) (void *codec_data,
>>>                                       struct audio_input_config *config);
>>> @@ -251,9 +268,14 @@ static void sbc_init_encoder(struct sbc_data *sbc_data)
>>>       }
>>> }
>>>
>>> -static int sbc_codec_init(struct audio_preset *preset, void **codec_data)
>>> +static int sbc_codec_init(struct audio_preset *preset, uint16_t mtu,
>>> +                             void **codec_data)
>>> {
>>>       struct sbc_data *sbc_data;
>>> +     size_t hdr_len = sizeof(struct media_packet);
>>> +     size_t in_frame_len;
>>> +     size_t out_frame_len;
>>> +     size_t num_frames;
>>>
>>>       DBG("");
>>>
>>> @@ -268,6 +290,18 @@ static int sbc_codec_init(struct audio_preset *preset, void **codec_data)
>>>
>>>       sbc_init_encoder(sbc_data);
>>>
>>> +     in_frame_len = sbc_get_codesize(&sbc_data->enc);
>>> +     out_frame_len = sbc_get_frame_length(&sbc_data->enc);
>>> +     num_frames = (mtu - hdr_len) / out_frame_len;
>>> +
>>> +     sbc_data->in_frame_len = in_frame_len;
>>> +     sbc_data->in_buf_size = num_frames * in_frame_len;
>>> +
>>> +     sbc_data->out_buf_size = hdr_len + num_frames * out_frame_len;
>>> +     sbc_data->out_buf = calloc(1, sbc_data->out_buf_size);
>>> +
>>> +     sbc_data->frame_duration = sbc_get_frame_duration(&sbc_data->enc);
>>> +
>>>       *codec_data = sbc_data;
>>>
>>>       return AUDIO_STATUS_SUCCESS;
>>> @@ -280,6 +314,7 @@ static int sbc_cleanup(void *codec_data)
>>>       DBG("");
>>>
>>>       sbc_finish(&sbc_data->enc);
>>> +     free(sbc_data->out_buf);
>>>       free(codec_data);
>>>
>>>       return AUDIO_STATUS_SUCCESS;
>>> @@ -511,7 +546,7 @@ static int ipc_close_cmd(uint8_t endpoint_id)
>>>       return result;
>>> }
>>>
>>> -static int ipc_open_stream_cmd(uint8_t endpoint_id,
>>> +static int ipc_open_stream_cmd(uint8_t endpoint_id, uint16_t *mtu,
>>>                                       struct audio_preset **caps)
>>> {
>>>       char buf[BLUEZ_AUDIO_MTU];
>>> @@ -534,6 +569,7 @@ static int ipc_open_stream_cmd(uint8_t endpoint_id,
>>>       if (result == AUDIO_STATUS_SUCCESS) {
>>>               size_t buf_len = sizeof(struct audio_preset) +
>>>                                       rsp->preset[0].len;
>>> +             *mtu = rsp->mtu;
>>>               *caps = malloc(buf_len);
>>>               memcpy(*caps, &rsp->preset, buf_len);
>>>       } else {
>>> @@ -919,6 +955,7 @@ static int audio_open_output_stream(struct audio_hw_device *dev,
>>>       struct a2dp_stream_out *out;
>>>       struct audio_preset *preset;
>>>       const struct audio_codec *codec;
>>> +     uint16_t mtu;
>>>
>>>       out = calloc(1, sizeof(struct a2dp_stream_out));
>>>       if (!out)
>>> @@ -946,7 +983,8 @@ static int audio_open_output_stream(struct audio_hw_device *dev,
>>>       /* TODO: for now we always use endpoint 0 */
>>>       out->ep = &audio_endpoints[0];
>>>
>>> -     if (ipc_open_stream_cmd(out->ep->id, &preset) != AUDIO_STATUS_SUCCESS)
>>> +     if (ipc_open_stream_cmd(out->ep->id, &mtu, &preset) !=
>>> +                     AUDIO_STATUS_SUCCESS)
>>>               goto fail;
>>>
>>>       if (!preset)
>>> @@ -954,7 +992,7 @@ static int audio_open_output_stream(struct audio_hw_device *dev,
>>>
>>>       codec = out->ep->codec;
>>>
>>> -     codec->init(preset, &out->ep->codec_data);
>>> +     codec->init(preset, mtu, &out->ep->codec_data);
>>>       codec->get_config(out->ep->codec_data, &out->cfg);
>>>
>>>       DBG("rate=%d channels=%d format=%d", out->cfg.rate,
>>> diff --git a/android/rtp.h b/android/rtp.h
>>> new file mode 100644
>>> index 0000000..45fddcf
>>> --- /dev/null
>>> +++ b/android/rtp.h
>>> @@ -0,0 +1,76 @@
>>> +/*
>>> + *
>>> + *  BlueZ - Bluetooth protocol stack for Linux
>>> + *
>>> + *  Copyright (C) 2004-2010  Marcel Holtmann <marcel@holtmann.org>
>>> + *
>>> + *
>>> + *  This library is free software; you can redistribute it and/or
>>> + *  modify it under the terms of the GNU Lesser General Public
>>> + *  License as published by the Free Software Foundation; either
>>> + *  version 2.1 of the License, or (at your option) any later version.
>>> + *
>>> + *  This library is distributed in the hope that it will be useful,
>>> + *  but WITHOUT ANY WARRANTY; without even the implied warranty of
>>> + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
>>> + *  Lesser General Public License for more details.
>>> + *
>>> + *  You should have received a copy of the GNU Lesser General Public
>>> + *  License along with this library; if not, write to the Free Software
>>> + *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
>>> + *
>>> + */
>>
>> where is this file coming from? Why do we need a copy of it?
>
> From BlueZ but it was removed (was used in pcm_bluetooth.c) so I just
> added it again since we need RTP header structures. Or should these
> just be added inline to hal-audio.c?

I would just add these to hal-audio.c, nothing else should need it.


-- 
Luiz Augusto von Dentz

^ permalink raw reply

* Re: [PATCH 4/9] android/hal-audio: Initialize SBC encoder
From: Luiz Augusto von Dentz @ 2014-01-17 19:38 UTC (permalink / raw)
  To: Marcel Holtmann
  Cc: Andrzej Kaczmarek, linux-bluetooth@vger.kernel.org development
In-Reply-To: <127C43B2-4418-44A2-9F44-27908E587B11@holtmann.org>

Hi Marcel,

On Fri, Jan 17, 2014 at 9:28 PM, Marcel Holtmann <marcel@holtmann.org> wrot=
e:
> Hi Andrezj,
>
>>>> ---
>>>> android/hal-audio.c | 72 +++++++++++++++++++++++++++++++++++++++++++++=
++++++++
>>>> 1 file changed, 72 insertions(+)
>>>>
>>>> diff --git a/android/hal-audio.c b/android/hal-audio.c
>>>> index f53dba0..e5c646c 100644
>>>> --- a/android/hal-audio.c
>>>> +++ b/android/hal-audio.c
>>>> @@ -32,6 +32,7 @@
>>>> #include "hal-log.h"
>>>> #include "hal-msg.h"
>>>> #include "../profiles/audio/a2dp-codecs.h"
>>>> +#include <sbc/sbc.h>
>>>>
>>>> static const uint8_t a2dp_src_uuid[] =3D {
>>>>              0x00, 0x00, 0x11, 0x0a, 0x00, 0x00, 0x10, 0x00,
>>>> @@ -53,6 +54,8 @@ struct audio_input_config {
>>>>
>>>> struct sbc_data {
>>>>      a2dp_sbc_t sbc;
>>>> +
>>>> +     sbc_t enc;
>>>> };
>>>>
>>>> static int sbc_get_presets(struct audio_preset *preset, size_t *len);
>>>> @@ -184,6 +187,70 @@ static int sbc_get_presets(struct audio_preset *p=
reset, size_t *len)
>>>>      return i;
>>>> }
>>>>
>>>> +static void sbc_init_encoder(struct sbc_data *sbc_data)
>>>> +{
>>>> +     a2dp_sbc_t *in =3D &sbc_data->sbc;
>>>> +     sbc_t *out =3D &sbc_data->enc;
>>>> +
>>>> +     DBG("");
>>>> +
>>>> +     sbc_init(out, 0L);
>>>> +
>>>> +     switch (in->frequency) {
>>>> +     case SBC_SAMPLING_FREQ_16000:
>>>> +             out->frequency =3D SBC_FREQ_16000;
>>>> +             break;
>>>> +     case SBC_SAMPLING_FREQ_32000:
>>>> +             out->frequency =3D SBC_FREQ_32000;
>>>> +             break;
>>>> +     case SBC_SAMPLING_FREQ_44100:
>>>> +             out->frequency =3D SBC_FREQ_44100;
>>>> +             break;
>>>> +     case SBC_SAMPLING_FREQ_48000:
>>>> +             out->frequency =3D SBC_FREQ_48000;
>>>> +             break;
>>>> +     }
>>>> +
>>>> +     out->subbands =3D in->subbands =3D=3D SBC_SUBBANDS_4 ? SBC_SB_4 =
: SBC_SB_8;
>>>> +
>>>> +     switch (in->channel_mode) {
>>>> +     case SBC_CHANNEL_MODE_MONO:
>>>> +             out->mode =3D SBC_MODE_MONO;
>>>> +             break;
>>>> +     case SBC_CHANNEL_MODE_DUAL_CHANNEL:
>>>> +             out->mode =3D SBC_MODE_DUAL_CHANNEL;
>>>> +             break;
>>>> +     case SBC_CHANNEL_MODE_JOINT_STEREO:
>>>> +             out->mode =3D SBC_MODE_JOINT_STEREO;
>>>> +             break;
>>>> +     case SBC_CHANNEL_MODE_STEREO:
>>>> +             out->mode =3D SBC_MODE_STEREO;
>>>> +             break;
>>>> +     }
>>>> +
>>>> +     out->endian =3D SBC_LE;
>>>> +
>>>> +     out->bitpool =3D in->max_bitpool;
>>>> +
>>>> +     out->allocation =3D in->allocation_method =3D=3D SBC_ALLOCATION_=
SNR ?
>>>> +                             SBC_AM_SNR : SBC_AM_LOUDNESS;
>>>> +
>>>> +     switch (in->block_length) {
>>>> +     case SBC_BLOCK_LENGTH_4:
>>>> +             out->blocks =3D SBC_BLK_4;
>>>> +             break;
>>>> +     case SBC_BLOCK_LENGTH_8:
>>>> +             out->blocks =3D SBC_BLK_8;
>>>> +             break;
>>>> +     case SBC_BLOCK_LENGTH_12:
>>>> +             out->blocks =3D SBC_BLK_12;
>>>> +             break;
>>>> +     case SBC_BLOCK_LENGTH_16:
>>>> +             out->blocks =3D SBC_BLK_16;
>>>> +             break;
>>>> +     }
>>>
>>> aren=92t the values all the same? This looks pretty complicated for som=
ething that should be dead simple. Does Android really had to duplicate eve=
ry single definition with the same prefix?
>>
>> Actually symbols for 'in' come from a2dp-codecs.h and 'out' from sbc.h
>> ;-) And they have different values since A2DP uses shifted-bit values
>> while sbc.h are just ordinal values so cannot assign them directly.
>
> so this a problem we created by ourselves. Yeah. Seems no cookie for me t=
onight ;)
>
> We need to start fixing a2dp-codecs.h then and prefix it with A2DP. This =
current situation is bad. Luiz?

Looks like it, what about a helper function inside sbc that takes care
of this conversion?


--=20
Luiz Augusto von Dentz

^ permalink raw reply

* Re: [PATCH 4/9] android/hal-audio: Initialize SBC encoder
From: Luiz Augusto von Dentz @ 2014-01-17 19:36 UTC (permalink / raw)
  To: Andrzej Kaczmarek
  Cc: Marcel Holtmann, linux-bluetooth@vger.kernel.org development
In-Reply-To: <CAF3PWx3PZuAaJWacG77GSD7PRAaFuXi_o6LMe1zTWMrW1qYKaA@mail.gmail.com>

Hi Andrzej,

On Fri, Jan 17, 2014 at 9:26 PM, Andrzej Kaczmarek
<andrzej.kaczmarek@tieto.com> wrote:
> Hi Marcel,
>
> On 17 January 2014 19:24, Marcel Holtmann <marcel@holtmann.org> wrote:
>> Hi Andrzej,
>>
>>> ---
>>> android/hal-audio.c | 72 ++++++++++++++++++++++++++++++++++++++++++++++=
+++++++
>>> 1 file changed, 72 insertions(+)
>>>
>>> diff --git a/android/hal-audio.c b/android/hal-audio.c
>>> index f53dba0..e5c646c 100644
>>> --- a/android/hal-audio.c
>>> +++ b/android/hal-audio.c
>>> @@ -32,6 +32,7 @@
>>> #include "hal-log.h"
>>> #include "hal-msg.h"
>>> #include "../profiles/audio/a2dp-codecs.h"
>>> +#include <sbc/sbc.h>
>>>
>>> static const uint8_t a2dp_src_uuid[] =3D {
>>>               0x00, 0x00, 0x11, 0x0a, 0x00, 0x00, 0x10, 0x00,
>>> @@ -53,6 +54,8 @@ struct audio_input_config {
>>>
>>> struct sbc_data {
>>>       a2dp_sbc_t sbc;
>>> +
>>> +     sbc_t enc;
>>> };
>>>
>>> static int sbc_get_presets(struct audio_preset *preset, size_t *len);
>>> @@ -184,6 +187,70 @@ static int sbc_get_presets(struct audio_preset *pr=
eset, size_t *len)
>>>       return i;
>>> }
>>>
>>> +static void sbc_init_encoder(struct sbc_data *sbc_data)
>>> +{
>>> +     a2dp_sbc_t *in =3D &sbc_data->sbc;
>>> +     sbc_t *out =3D &sbc_data->enc;
>>> +
>>> +     DBG("");
>>> +
>>> +     sbc_init(out, 0L);
>>> +
>>> +     switch (in->frequency) {
>>> +     case SBC_SAMPLING_FREQ_16000:
>>> +             out->frequency =3D SBC_FREQ_16000;
>>> +             break;
>>> +     case SBC_SAMPLING_FREQ_32000:
>>> +             out->frequency =3D SBC_FREQ_32000;
>>> +             break;
>>> +     case SBC_SAMPLING_FREQ_44100:
>>> +             out->frequency =3D SBC_FREQ_44100;
>>> +             break;
>>> +     case SBC_SAMPLING_FREQ_48000:
>>> +             out->frequency =3D SBC_FREQ_48000;
>>> +             break;
>>> +     }
>>> +
>>> +     out->subbands =3D in->subbands =3D=3D SBC_SUBBANDS_4 ? SBC_SB_4 :=
 SBC_SB_8;
>>> +
>>> +     switch (in->channel_mode) {
>>> +     case SBC_CHANNEL_MODE_MONO:
>>> +             out->mode =3D SBC_MODE_MONO;
>>> +             break;
>>> +     case SBC_CHANNEL_MODE_DUAL_CHANNEL:
>>> +             out->mode =3D SBC_MODE_DUAL_CHANNEL;
>>> +             break;
>>> +     case SBC_CHANNEL_MODE_JOINT_STEREO:
>>> +             out->mode =3D SBC_MODE_JOINT_STEREO;
>>> +             break;
>>> +     case SBC_CHANNEL_MODE_STEREO:
>>> +             out->mode =3D SBC_MODE_STEREO;
>>> +             break;
>>> +     }
>>> +
>>> +     out->endian =3D SBC_LE;
>>> +
>>> +     out->bitpool =3D in->max_bitpool;
>>> +
>>> +     out->allocation =3D in->allocation_method =3D=3D SBC_ALLOCATION_S=
NR ?
>>> +                             SBC_AM_SNR : SBC_AM_LOUDNESS;
>>> +
>>> +     switch (in->block_length) {
>>> +     case SBC_BLOCK_LENGTH_4:
>>> +             out->blocks =3D SBC_BLK_4;
>>> +             break;
>>> +     case SBC_BLOCK_LENGTH_8:
>>> +             out->blocks =3D SBC_BLK_8;
>>> +             break;
>>> +     case SBC_BLOCK_LENGTH_12:
>>> +             out->blocks =3D SBC_BLK_12;
>>> +             break;
>>> +     case SBC_BLOCK_LENGTH_16:
>>> +             out->blocks =3D SBC_BLK_16;
>>> +             break;
>>> +     }
>>
>> aren=92t the values all the same? This looks pretty complicated for some=
thing that should be dead simple. Does Android really had to duplicate ever=
y single definition with the same prefix?
>
> Actually symbols for 'in' come from a2dp-codecs.h and 'out' from sbc.h
> ;-) And they have different values since A2DP uses shifted-bit values
> while sbc.h are just ordinal values so cannot assign them directly.

Perhaps we should create some helper function in sbc code to do that
translation for us, I was even considering stuff the rtp packing there
as well.


--=20
Luiz Augusto von Dentz

^ permalink raw reply

* Re: [PATCH 4/9] android/hal-audio: Initialize SBC encoder
From: Luiz Augusto von Dentz @ 2014-01-17 19:33 UTC (permalink / raw)
  To: Marcel Holtmann
  Cc: Andrzej Kaczmarek, linux-bluetooth@vger.kernel.org development
In-Reply-To: <D34DEF28-690B-4697-B88F-B224F7583782@holtmann.org>

Hi Marcel,

On Fri, Jan 17, 2014 at 8:24 PM, Marcel Holtmann <marcel@holtmann.org> wrot=
e:
> Hi Andrzej,
>
>> ---
>> android/hal-audio.c | 72 +++++++++++++++++++++++++++++++++++++++++++++++=
++++++
>> 1 file changed, 72 insertions(+)
>>
>> diff --git a/android/hal-audio.c b/android/hal-audio.c
>> index f53dba0..e5c646c 100644
>> --- a/android/hal-audio.c
>> +++ b/android/hal-audio.c
>> @@ -32,6 +32,7 @@
>> #include "hal-log.h"
>> #include "hal-msg.h"
>> #include "../profiles/audio/a2dp-codecs.h"
>> +#include <sbc/sbc.h>
>>
>> static const uint8_t a2dp_src_uuid[] =3D {
>>               0x00, 0x00, 0x11, 0x0a, 0x00, 0x00, 0x10, 0x00,
>> @@ -53,6 +54,8 @@ struct audio_input_config {
>>
>> struct sbc_data {
>>       a2dp_sbc_t sbc;
>> +
>> +     sbc_t enc;
>> };
>>
>> static int sbc_get_presets(struct audio_preset *preset, size_t *len);
>> @@ -184,6 +187,70 @@ static int sbc_get_presets(struct audio_preset *pre=
set, size_t *len)
>>       return i;
>> }
>>
>> +static void sbc_init_encoder(struct sbc_data *sbc_data)
>> +{
>> +     a2dp_sbc_t *in =3D &sbc_data->sbc;
>> +     sbc_t *out =3D &sbc_data->enc;
>> +
>> +     DBG("");
>> +
>> +     sbc_init(out, 0L);
>> +
>> +     switch (in->frequency) {
>> +     case SBC_SAMPLING_FREQ_16000:
>> +             out->frequency =3D SBC_FREQ_16000;
>> +             break;
>> +     case SBC_SAMPLING_FREQ_32000:
>> +             out->frequency =3D SBC_FREQ_32000;
>> +             break;
>> +     case SBC_SAMPLING_FREQ_44100:
>> +             out->frequency =3D SBC_FREQ_44100;
>> +             break;
>> +     case SBC_SAMPLING_FREQ_48000:
>> +             out->frequency =3D SBC_FREQ_48000;
>> +             break;
>> +     }
>> +
>> +     out->subbands =3D in->subbands =3D=3D SBC_SUBBANDS_4 ? SBC_SB_4 : =
SBC_SB_8;
>> +
>> +     switch (in->channel_mode) {
>> +     case SBC_CHANNEL_MODE_MONO:
>> +             out->mode =3D SBC_MODE_MONO;
>> +             break;
>> +     case SBC_CHANNEL_MODE_DUAL_CHANNEL:
>> +             out->mode =3D SBC_MODE_DUAL_CHANNEL;
>> +             break;
>> +     case SBC_CHANNEL_MODE_JOINT_STEREO:
>> +             out->mode =3D SBC_MODE_JOINT_STEREO;
>> +             break;
>> +     case SBC_CHANNEL_MODE_STEREO:
>> +             out->mode =3D SBC_MODE_STEREO;
>> +             break;
>> +     }
>> +
>> +     out->endian =3D SBC_LE;
>> +
>> +     out->bitpool =3D in->max_bitpool;
>> +
>> +     out->allocation =3D in->allocation_method =3D=3D SBC_ALLOCATION_SN=
R ?
>> +                             SBC_AM_SNR : SBC_AM_LOUDNESS;
>> +
>> +     switch (in->block_length) {
>> +     case SBC_BLOCK_LENGTH_4:
>> +             out->blocks =3D SBC_BLK_4;
>> +             break;
>> +     case SBC_BLOCK_LENGTH_8:
>> +             out->blocks =3D SBC_BLK_8;
>> +             break;
>> +     case SBC_BLOCK_LENGTH_12:
>> +             out->blocks =3D SBC_BLK_12;
>> +             break;
>> +     case SBC_BLOCK_LENGTH_16:
>> +             out->blocks =3D SBC_BLK_16;
>> +             break;
>> +     }
>
> aren=92t the values all the same? This looks pretty complicated for somet=
hing that should be dead simple. Does Android really had to duplicate every=
 single definition with the same prefix?

This is the conversion from A2DP configuration to libsbc
representation but I believe we don't really need to do the switch
statement, which anyway are done with defines from sbc.h instead of
a2dp-codecs.h.

^ permalink raw reply

* Re: [PATCH 4/9] android/hal-audio: Initialize SBC encoder
From: Marcel Holtmann @ 2014-01-17 19:28 UTC (permalink / raw)
  To: Andrzej Kaczmarek; +Cc: linux-bluetooth@vger.kernel.org development
In-Reply-To: <CAF3PWx3PZuAaJWacG77GSD7PRAaFuXi_o6LMe1zTWMrW1qYKaA@mail.gmail.com>

Hi Andrezj,

>>> ---
>>> android/hal-audio.c | 72 +++++++++++++++++++++++++++++++++++++++++++++++++++++
>>> 1 file changed, 72 insertions(+)
>>> 
>>> diff --git a/android/hal-audio.c b/android/hal-audio.c
>>> index f53dba0..e5c646c 100644
>>> --- a/android/hal-audio.c
>>> +++ b/android/hal-audio.c
>>> @@ -32,6 +32,7 @@
>>> #include "hal-log.h"
>>> #include "hal-msg.h"
>>> #include "../profiles/audio/a2dp-codecs.h"
>>> +#include <sbc/sbc.h>
>>> 
>>> static const uint8_t a2dp_src_uuid[] = {
>>>              0x00, 0x00, 0x11, 0x0a, 0x00, 0x00, 0x10, 0x00,
>>> @@ -53,6 +54,8 @@ struct audio_input_config {
>>> 
>>> struct sbc_data {
>>>      a2dp_sbc_t sbc;
>>> +
>>> +     sbc_t enc;
>>> };
>>> 
>>> static int sbc_get_presets(struct audio_preset *preset, size_t *len);
>>> @@ -184,6 +187,70 @@ static int sbc_get_presets(struct audio_preset *preset, size_t *len)
>>>      return i;
>>> }
>>> 
>>> +static void sbc_init_encoder(struct sbc_data *sbc_data)
>>> +{
>>> +     a2dp_sbc_t *in = &sbc_data->sbc;
>>> +     sbc_t *out = &sbc_data->enc;
>>> +
>>> +     DBG("");
>>> +
>>> +     sbc_init(out, 0L);
>>> +
>>> +     switch (in->frequency) {
>>> +     case SBC_SAMPLING_FREQ_16000:
>>> +             out->frequency = SBC_FREQ_16000;
>>> +             break;
>>> +     case SBC_SAMPLING_FREQ_32000:
>>> +             out->frequency = SBC_FREQ_32000;
>>> +             break;
>>> +     case SBC_SAMPLING_FREQ_44100:
>>> +             out->frequency = SBC_FREQ_44100;
>>> +             break;
>>> +     case SBC_SAMPLING_FREQ_48000:
>>> +             out->frequency = SBC_FREQ_48000;
>>> +             break;
>>> +     }
>>> +
>>> +     out->subbands = in->subbands == SBC_SUBBANDS_4 ? SBC_SB_4 : SBC_SB_8;
>>> +
>>> +     switch (in->channel_mode) {
>>> +     case SBC_CHANNEL_MODE_MONO:
>>> +             out->mode = SBC_MODE_MONO;
>>> +             break;
>>> +     case SBC_CHANNEL_MODE_DUAL_CHANNEL:
>>> +             out->mode = SBC_MODE_DUAL_CHANNEL;
>>> +             break;
>>> +     case SBC_CHANNEL_MODE_JOINT_STEREO:
>>> +             out->mode = SBC_MODE_JOINT_STEREO;
>>> +             break;
>>> +     case SBC_CHANNEL_MODE_STEREO:
>>> +             out->mode = SBC_MODE_STEREO;
>>> +             break;
>>> +     }
>>> +
>>> +     out->endian = SBC_LE;
>>> +
>>> +     out->bitpool = in->max_bitpool;
>>> +
>>> +     out->allocation = in->allocation_method == SBC_ALLOCATION_SNR ?
>>> +                             SBC_AM_SNR : SBC_AM_LOUDNESS;
>>> +
>>> +     switch (in->block_length) {
>>> +     case SBC_BLOCK_LENGTH_4:
>>> +             out->blocks = SBC_BLK_4;
>>> +             break;
>>> +     case SBC_BLOCK_LENGTH_8:
>>> +             out->blocks = SBC_BLK_8;
>>> +             break;
>>> +     case SBC_BLOCK_LENGTH_12:
>>> +             out->blocks = SBC_BLK_12;
>>> +             break;
>>> +     case SBC_BLOCK_LENGTH_16:
>>> +             out->blocks = SBC_BLK_16;
>>> +             break;
>>> +     }
>> 
>> aren’t the values all the same? This looks pretty complicated for something that should be dead simple. Does Android really had to duplicate every single definition with the same prefix?
> 
> Actually symbols for 'in' come from a2dp-codecs.h and 'out' from sbc.h
> ;-) And they have different values since A2DP uses shifted-bit values
> while sbc.h are just ordinal values so cannot assign them directly.

so this a problem we created by ourselves. Yeah. Seems no cookie for me tonight ;)

We need to start fixing a2dp-codecs.h then and prefix it with A2DP. This current situation is bad. Luiz?

Regards

Marcel



^ permalink raw reply

* Re: [PATCH 4/9] android/hal-audio: Initialize SBC encoder
From: Andrzej Kaczmarek @ 2014-01-17 19:26 UTC (permalink / raw)
  To: Marcel Holtmann; +Cc: linux-bluetooth@vger.kernel.org development
In-Reply-To: <D34DEF28-690B-4697-B88F-B224F7583782@holtmann.org>

Hi Marcel,

On 17 January 2014 19:24, Marcel Holtmann <marcel@holtmann.org> wrote:
> Hi Andrzej,
>
>> ---
>> android/hal-audio.c | 72 +++++++++++++++++++++++++++++++++++++++++++++++=
++++++
>> 1 file changed, 72 insertions(+)
>>
>> diff --git a/android/hal-audio.c b/android/hal-audio.c
>> index f53dba0..e5c646c 100644
>> --- a/android/hal-audio.c
>> +++ b/android/hal-audio.c
>> @@ -32,6 +32,7 @@
>> #include "hal-log.h"
>> #include "hal-msg.h"
>> #include "../profiles/audio/a2dp-codecs.h"
>> +#include <sbc/sbc.h>
>>
>> static const uint8_t a2dp_src_uuid[] =3D {
>>               0x00, 0x00, 0x11, 0x0a, 0x00, 0x00, 0x10, 0x00,
>> @@ -53,6 +54,8 @@ struct audio_input_config {
>>
>> struct sbc_data {
>>       a2dp_sbc_t sbc;
>> +
>> +     sbc_t enc;
>> };
>>
>> static int sbc_get_presets(struct audio_preset *preset, size_t *len);
>> @@ -184,6 +187,70 @@ static int sbc_get_presets(struct audio_preset *pre=
set, size_t *len)
>>       return i;
>> }
>>
>> +static void sbc_init_encoder(struct sbc_data *sbc_data)
>> +{
>> +     a2dp_sbc_t *in =3D &sbc_data->sbc;
>> +     sbc_t *out =3D &sbc_data->enc;
>> +
>> +     DBG("");
>> +
>> +     sbc_init(out, 0L);
>> +
>> +     switch (in->frequency) {
>> +     case SBC_SAMPLING_FREQ_16000:
>> +             out->frequency =3D SBC_FREQ_16000;
>> +             break;
>> +     case SBC_SAMPLING_FREQ_32000:
>> +             out->frequency =3D SBC_FREQ_32000;
>> +             break;
>> +     case SBC_SAMPLING_FREQ_44100:
>> +             out->frequency =3D SBC_FREQ_44100;
>> +             break;
>> +     case SBC_SAMPLING_FREQ_48000:
>> +             out->frequency =3D SBC_FREQ_48000;
>> +             break;
>> +     }
>> +
>> +     out->subbands =3D in->subbands =3D=3D SBC_SUBBANDS_4 ? SBC_SB_4 : =
SBC_SB_8;
>> +
>> +     switch (in->channel_mode) {
>> +     case SBC_CHANNEL_MODE_MONO:
>> +             out->mode =3D SBC_MODE_MONO;
>> +             break;
>> +     case SBC_CHANNEL_MODE_DUAL_CHANNEL:
>> +             out->mode =3D SBC_MODE_DUAL_CHANNEL;
>> +             break;
>> +     case SBC_CHANNEL_MODE_JOINT_STEREO:
>> +             out->mode =3D SBC_MODE_JOINT_STEREO;
>> +             break;
>> +     case SBC_CHANNEL_MODE_STEREO:
>> +             out->mode =3D SBC_MODE_STEREO;
>> +             break;
>> +     }
>> +
>> +     out->endian =3D SBC_LE;
>> +
>> +     out->bitpool =3D in->max_bitpool;
>> +
>> +     out->allocation =3D in->allocation_method =3D=3D SBC_ALLOCATION_SN=
R ?
>> +                             SBC_AM_SNR : SBC_AM_LOUDNESS;
>> +
>> +     switch (in->block_length) {
>> +     case SBC_BLOCK_LENGTH_4:
>> +             out->blocks =3D SBC_BLK_4;
>> +             break;
>> +     case SBC_BLOCK_LENGTH_8:
>> +             out->blocks =3D SBC_BLK_8;
>> +             break;
>> +     case SBC_BLOCK_LENGTH_12:
>> +             out->blocks =3D SBC_BLK_12;
>> +             break;
>> +     case SBC_BLOCK_LENGTH_16:
>> +             out->blocks =3D SBC_BLK_16;
>> +             break;
>> +     }
>
> aren=92t the values all the same? This looks pretty complicated for somet=
hing that should be dead simple. Does Android really had to duplicate every=
 single definition with the same prefix?

Actually symbols for 'in' come from a2dp-codecs.h and 'out' from sbc.h
;-) And they have different values since A2DP uses shifted-bit values
while sbc.h are just ordinal values so cannot assign them directly.


BR,
Andrzej

^ permalink raw reply

* Re: [PATCH 2/9] android: Build Audio HAL with SBC
From: Marcel Holtmann @ 2014-01-17 19:22 UTC (permalink / raw)
  To: Andrzej Kaczmarek; +Cc: linux-bluetooth@vger.kernel.org development
In-Reply-To: <CAF3PWx2XmgedAh3owiGN3JQzQZo8gNNRcph7kx=252Uo1yFyuw@mail.gmail.com>

Hi Andrzej,

>>> Build for Android requires libsbc sources to be available in
>>> external/bluetooth/sbc. Build for host requires libsbc package to be
>>> installed.
>>> ---
>>> android/Android.mk  | 14 +++++++++++---
>>> android/Makefile.am |  2 ++
>>> configure.ac        |  7 +++++++
>>> 3 files changed, 20 insertions(+), 3 deletions(-)
>>> 
>>> diff --git a/android/Android.mk b/android/Android.mk
>>> index 7e97ec8..63a4a24 100644
>>> --- a/android/Android.mk
>>> +++ b/android/Android.mk
>>> @@ -3,8 +3,9 @@ LOCAL_PATH := $(call my-dir)
>>> # Retrieve BlueZ version from configure.ac file
>>> BLUEZ_VERSION := $(shell grep ^AC_INIT $(LOCAL_PATH)/../configure.ac | cpp -P -D'AC_INIT(_,v)=v')
>>> 
>>> -# Specify pathmap for glib
>>> -pathmap_INCL += glib:external/bluetooth/glib
>>> +# Specify pathmap for glib and sbc
>>> +pathmap_INCL += glib:external/bluetooth/glib \
>>> +     sbc:external/bluetooth/sbc
>>> 
>>> # Specify common compiler flags
>>> BLUEZ_COMMON_CFLAGS := -DVERSION=\"$(BLUEZ_VERSION)\" \
>>> @@ -220,11 +221,18 @@ include $(BUILD_EXECUTABLE)
>>> 
>>> include $(CLEAR_VARS)
>>> 
>>> -LOCAL_SRC_FILES := hal-audio.c
>>> +LOCAL_SRC_FILES := hal-audio.c \
>>> +     ../../sbc/sbc/sbc.c \
>>> +     ../../sbc/sbc/sbc_primitives.c \
>>> +     ../../sbc/sbc/sbc_primitives_armv6.c \
>>> +     ../../sbc/sbc/sbc_primitives_iwmmxt.c \
>>> +     ../../sbc/sbc/sbc_primitives_mmx.c \
>>> +     ../../sbc/sbc/sbc_primitives_neon.c \
>> 
>> why? Can we not just build libsbc for Android?
> 
> This way we can use upstream sbc git without forking it to add Android.mk.

okay. Seems fine for now to get this started, but eventually we need to sort this out.

>> I rather install an extra library and not have to make this builtin.
> 
> Sure, this can be changed. Static or dynamic library?

I would build it at least as dynamic library. Even you build that from android/Android.mk file from bluez tree. If you make it static or include it then you have to worry about LGPL obligations. They are different for a shared library compared to a static library/include.

Regards

Marcel


^ permalink raw reply

* Re: [PATCH 5/9] android/hal-audio: Calculate SBC stream parameters
From: Andrzej Kaczmarek @ 2014-01-17 19:17 UTC (permalink / raw)
  To: Marcel Holtmann; +Cc: linux-bluetooth@vger.kernel.org development
In-Reply-To: <816CDF1A-CF41-445B-9CAF-CE5A1E06C940@holtmann.org>

Hi Marcel,

On 17 January 2014 19:25, Marcel Holtmann <marcel@holtmann.org> wrote:
> Hi Andrzej,
>
>> This patch adds necessary calculations for SBC stream parameters.
>>
>> Both input and output buffers are expected to have exact amount of
>> data to fill single media packet (based on transport channel MTU).
>>
>> Frame duration will be used to synchronize input and output streams.
>> ---
>> android/hal-audio.c | 50 ++++++++++++++++++++++++++++++-----
>> android/rtp.h       | 76 +++++++++++++++++++++++++++++++++++++++++++++++++++++
>> 2 files changed, 120 insertions(+), 6 deletions(-)
>> create mode 100644 android/rtp.h
>>
>> diff --git a/android/hal-audio.c b/android/hal-audio.c
>> index e5c646c..3f53295 100644
>> --- a/android/hal-audio.c
>> +++ b/android/hal-audio.c
>> @@ -33,6 +33,7 @@
>> #include "hal-msg.h"
>> #include "../profiles/audio/a2dp-codecs.h"
>> #include <sbc/sbc.h>
>> +#include "rtp.h"
>>
>> static const uint8_t a2dp_src_uuid[] = {
>>               0x00, 0x00, 0x11, 0x0a, 0x00, 0x00, 0x10, 0x00,
>> @@ -46,6 +47,12 @@ static pthread_t ipc_th = 0;
>> static pthread_mutex_t close_mutex = PTHREAD_MUTEX_INITIALIZER;
>> static pthread_mutex_t sk_mutex = PTHREAD_MUTEX_INITIALIZER;
>>
>> +struct media_packet {
>> +     struct rtp_header hdr;
>> +     struct rtp_payload payload;
>> +     uint8_t data[0];
>> +};
>> +
>> struct audio_input_config {
>>       uint32_t rate;
>>       uint32_t channels;
>> @@ -56,10 +63,19 @@ struct sbc_data {
>>       a2dp_sbc_t sbc;
>>
>>       sbc_t enc;
>> +
>> +     size_t in_frame_len;
>> +     size_t in_buf_size;
>> +
>> +     size_t out_buf_size;
>> +     uint8_t *out_buf;
>> +
>> +     unsigned frame_duration;
>> };
>>
>> static int sbc_get_presets(struct audio_preset *preset, size_t *len);
>> -static int sbc_codec_init(struct audio_preset *preset, void **codec_data);
>> +static int sbc_codec_init(struct audio_preset *preset, uint16_t mtu,
>> +                             void **codec_data);
>> static int sbc_cleanup(void *codec_data);
>> static int sbc_get_config(void *codec_data,
>>                                       struct audio_input_config *config);
>> @@ -69,7 +85,8 @@ struct audio_codec {
>>
>>       int (*get_presets) (struct audio_preset *preset, size_t *len);
>>
>> -     int (*init) (struct audio_preset *preset, void **codec_data);
>> +     int (*init) (struct audio_preset *preset, uint16_t mtu,
>> +                             void **codec_data);
>>       int (*cleanup) (void *codec_data);
>>       int (*get_config) (void *codec_data,
>>                                       struct audio_input_config *config);
>> @@ -251,9 +268,14 @@ static void sbc_init_encoder(struct sbc_data *sbc_data)
>>       }
>> }
>>
>> -static int sbc_codec_init(struct audio_preset *preset, void **codec_data)
>> +static int sbc_codec_init(struct audio_preset *preset, uint16_t mtu,
>> +                             void **codec_data)
>> {
>>       struct sbc_data *sbc_data;
>> +     size_t hdr_len = sizeof(struct media_packet);
>> +     size_t in_frame_len;
>> +     size_t out_frame_len;
>> +     size_t num_frames;
>>
>>       DBG("");
>>
>> @@ -268,6 +290,18 @@ static int sbc_codec_init(struct audio_preset *preset, void **codec_data)
>>
>>       sbc_init_encoder(sbc_data);
>>
>> +     in_frame_len = sbc_get_codesize(&sbc_data->enc);
>> +     out_frame_len = sbc_get_frame_length(&sbc_data->enc);
>> +     num_frames = (mtu - hdr_len) / out_frame_len;
>> +
>> +     sbc_data->in_frame_len = in_frame_len;
>> +     sbc_data->in_buf_size = num_frames * in_frame_len;
>> +
>> +     sbc_data->out_buf_size = hdr_len + num_frames * out_frame_len;
>> +     sbc_data->out_buf = calloc(1, sbc_data->out_buf_size);
>> +
>> +     sbc_data->frame_duration = sbc_get_frame_duration(&sbc_data->enc);
>> +
>>       *codec_data = sbc_data;
>>
>>       return AUDIO_STATUS_SUCCESS;
>> @@ -280,6 +314,7 @@ static int sbc_cleanup(void *codec_data)
>>       DBG("");
>>
>>       sbc_finish(&sbc_data->enc);
>> +     free(sbc_data->out_buf);
>>       free(codec_data);
>>
>>       return AUDIO_STATUS_SUCCESS;
>> @@ -511,7 +546,7 @@ static int ipc_close_cmd(uint8_t endpoint_id)
>>       return result;
>> }
>>
>> -static int ipc_open_stream_cmd(uint8_t endpoint_id,
>> +static int ipc_open_stream_cmd(uint8_t endpoint_id, uint16_t *mtu,
>>                                       struct audio_preset **caps)
>> {
>>       char buf[BLUEZ_AUDIO_MTU];
>> @@ -534,6 +569,7 @@ static int ipc_open_stream_cmd(uint8_t endpoint_id,
>>       if (result == AUDIO_STATUS_SUCCESS) {
>>               size_t buf_len = sizeof(struct audio_preset) +
>>                                       rsp->preset[0].len;
>> +             *mtu = rsp->mtu;
>>               *caps = malloc(buf_len);
>>               memcpy(*caps, &rsp->preset, buf_len);
>>       } else {
>> @@ -919,6 +955,7 @@ static int audio_open_output_stream(struct audio_hw_device *dev,
>>       struct a2dp_stream_out *out;
>>       struct audio_preset *preset;
>>       const struct audio_codec *codec;
>> +     uint16_t mtu;
>>
>>       out = calloc(1, sizeof(struct a2dp_stream_out));
>>       if (!out)
>> @@ -946,7 +983,8 @@ static int audio_open_output_stream(struct audio_hw_device *dev,
>>       /* TODO: for now we always use endpoint 0 */
>>       out->ep = &audio_endpoints[0];
>>
>> -     if (ipc_open_stream_cmd(out->ep->id, &preset) != AUDIO_STATUS_SUCCESS)
>> +     if (ipc_open_stream_cmd(out->ep->id, &mtu, &preset) !=
>> +                     AUDIO_STATUS_SUCCESS)
>>               goto fail;
>>
>>       if (!preset)
>> @@ -954,7 +992,7 @@ static int audio_open_output_stream(struct audio_hw_device *dev,
>>
>>       codec = out->ep->codec;
>>
>> -     codec->init(preset, &out->ep->codec_data);
>> +     codec->init(preset, mtu, &out->ep->codec_data);
>>       codec->get_config(out->ep->codec_data, &out->cfg);
>>
>>       DBG("rate=%d channels=%d format=%d", out->cfg.rate,
>> diff --git a/android/rtp.h b/android/rtp.h
>> new file mode 100644
>> index 0000000..45fddcf
>> --- /dev/null
>> +++ b/android/rtp.h
>> @@ -0,0 +1,76 @@
>> +/*
>> + *
>> + *  BlueZ - Bluetooth protocol stack for Linux
>> + *
>> + *  Copyright (C) 2004-2010  Marcel Holtmann <marcel@holtmann.org>
>> + *
>> + *
>> + *  This library is free software; you can redistribute it and/or
>> + *  modify it under the terms of the GNU Lesser General Public
>> + *  License as published by the Free Software Foundation; either
>> + *  version 2.1 of the License, or (at your option) any later version.
>> + *
>> + *  This library is distributed in the hope that it will be useful,
>> + *  but WITHOUT ANY WARRANTY; without even the implied warranty of
>> + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
>> + *  Lesser General Public License for more details.
>> + *
>> + *  You should have received a copy of the GNU Lesser General Public
>> + *  License along with this library; if not, write to the Free Software
>> + *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
>> + *
>> + */
>
> where is this file coming from? Why do we need a copy of it?

>From BlueZ but it was removed (was used in pcm_bluetooth.c) so I just
added it again since we need RTP header structures. Or should these
just be added inline to hal-audio.c?


BR,
Andrzej

^ permalink raw reply

* Re: [PATCH 2/9] android: Build Audio HAL with SBC
From: Andrzej Kaczmarek @ 2014-01-17 19:09 UTC (permalink / raw)
  To: Marcel Holtmann; +Cc: linux-bluetooth@vger.kernel.org development
In-Reply-To: <04524385-0757-4DFE-B503-352781B4B9BA@holtmann.org>

Hi Marcel,

On 17 January 2014 19:27, Marcel Holtmann <marcel@holtmann.org> wrote:
> Hi Andrzej,
>
>> Build for Android requires libsbc sources to be available in
>> external/bluetooth/sbc. Build for host requires libsbc package to be
>> installed.
>> ---
>> android/Android.mk  | 14 +++++++++++---
>> android/Makefile.am |  2 ++
>> configure.ac        |  7 +++++++
>> 3 files changed, 20 insertions(+), 3 deletions(-)
>>
>> diff --git a/android/Android.mk b/android/Android.mk
>> index 7e97ec8..63a4a24 100644
>> --- a/android/Android.mk
>> +++ b/android/Android.mk
>> @@ -3,8 +3,9 @@ LOCAL_PATH := $(call my-dir)
>> # Retrieve BlueZ version from configure.ac file
>> BLUEZ_VERSION := $(shell grep ^AC_INIT $(LOCAL_PATH)/../configure.ac | cpp -P -D'AC_INIT(_,v)=v')
>>
>> -# Specify pathmap for glib
>> -pathmap_INCL += glib:external/bluetooth/glib
>> +# Specify pathmap for glib and sbc
>> +pathmap_INCL += glib:external/bluetooth/glib \
>> +     sbc:external/bluetooth/sbc
>>
>> # Specify common compiler flags
>> BLUEZ_COMMON_CFLAGS := -DVERSION=\"$(BLUEZ_VERSION)\" \
>> @@ -220,11 +221,18 @@ include $(BUILD_EXECUTABLE)
>>
>> include $(CLEAR_VARS)
>>
>> -LOCAL_SRC_FILES := hal-audio.c
>> +LOCAL_SRC_FILES := hal-audio.c \
>> +     ../../sbc/sbc/sbc.c \
>> +     ../../sbc/sbc/sbc_primitives.c \
>> +     ../../sbc/sbc/sbc_primitives_armv6.c \
>> +     ../../sbc/sbc/sbc_primitives_iwmmxt.c \
>> +     ../../sbc/sbc/sbc_primitives_mmx.c \
>> +     ../../sbc/sbc/sbc_primitives_neon.c \
>
> why? Can we not just build libsbc for Android?

This way we can use upstream sbc git without forking it to add Android.mk.

> I rather install an extra library and not have to make this builtin.

Sure, this can be changed. Static or dynamic library?


BR,
Andrzej

^ permalink raw reply

* Re: [PATCH v4 2/2] Bluetooth: Queue incoming ACL data until BT_CONNECTED state is reached
From: Marcel Holtmann @ 2014-01-17 19:06 UTC (permalink / raw)
  To: Johan Hedberg; +Cc: linux-bluetooth@vger.kernel.org development
In-Reply-To: <1389984311-10482-2-git-send-email-johan.hedberg@gmail.com>

Hi Johan,

> This patch adds a queue for incoming L2CAP data that's received before
> l2cap_connect_cfm is called and processes the data once
> l2cap_connect_cfm is called. This way we ensure that we have e.g. all
> remote features before processing L2CAP signaling data (which is very
> important for making the correct security decisions).
> 
> The processing of the pending rx data needs to be done through
> queue_work since unlike l2cap_recv_acldata, l2cap_connect_cfm is called
> with the hci_dev lock held which could cause potential deadlocks.
> 
> Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
> ---
> include/net/bluetooth/l2cap.h |  3 +++
> net/bluetooth/l2cap_core.c    | 27 +++++++++++++++++++++++++++
> 2 files changed, 30 insertions(+)

both patches have been applied to bluetooth-next tree.

Regards

Marcel


^ permalink raw reply

* [PATCH v4 2/2] Bluetooth: Queue incoming ACL data until BT_CONNECTED state is reached
From: johan.hedberg @ 2014-01-17 18:45 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1389984311-10482-1-git-send-email-johan.hedberg@gmail.com>

From: Johan Hedberg <johan.hedberg@intel.com>

This patch adds a queue for incoming L2CAP data that's received before
l2cap_connect_cfm is called and processes the data once
l2cap_connect_cfm is called. This way we ensure that we have e.g. all
remote features before processing L2CAP signaling data (which is very
important for making the correct security decisions).

The processing of the pending rx data needs to be done through
queue_work since unlike l2cap_recv_acldata, l2cap_connect_cfm is called
with the hci_dev lock held which could cause potential deadlocks.

Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
---
 include/net/bluetooth/l2cap.h |  3 +++
 net/bluetooth/l2cap_core.c    | 27 +++++++++++++++++++++++++++
 2 files changed, 30 insertions(+)

diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h
index c695083eee2b..85cf40acc47e 100644
--- a/include/net/bluetooth/l2cap.h
+++ b/include/net/bluetooth/l2cap.h
@@ -624,6 +624,9 @@ struct l2cap_conn {
 	__u32			rx_len;
 	__u8			tx_ident;
 
+	struct sk_buff_head	pending_rx;
+	struct work_struct	pending_rx_work;
+
 	__u8			disc_reason;
 
 	struct delayed_work	security_timer;
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index 317a5737daf6..cd534599fbfa 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -1550,6 +1550,8 @@ static void l2cap_conn_ready(struct l2cap_conn *conn)
 	}
 
 	mutex_unlock(&conn->chan_lock);
+
+	queue_work(hcon->hdev->workqueue, &conn->pending_rx_work);
 }
 
 /* Notify sockets that we cannot guaranty reliability anymore */
@@ -1675,6 +1677,9 @@ static void l2cap_conn_del(struct hci_conn *hcon, int err)
 
 	kfree_skb(conn->rx_skb);
 
+	skb_queue_purge(&conn->pending_rx);
+	flush_work(&conn->pending_rx_work);
+
 	l2cap_unregister_all_users(conn);
 
 	mutex_lock(&conn->chan_lock);
@@ -6880,9 +6885,16 @@ drop:
 static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb)
 {
 	struct l2cap_hdr *lh = (void *) skb->data;
+	struct hci_conn *hcon = conn->hcon;
 	u16 cid, len;
 	__le16 psm;
 
+	if (hcon->state != BT_CONNECTED) {
+		BT_DBG("queueing pending rx skb");
+		skb_queue_tail(&conn->pending_rx, skb);
+		return;
+	}
+
 	skb_pull(skb, L2CAP_HDR_SIZE);
 	cid = __le16_to_cpu(lh->cid);
 	len = __le16_to_cpu(lh->len);
@@ -6928,6 +6940,18 @@ static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb)
 	}
 }
 
+static void process_pending_rx(struct work_struct *work)
+{
+	struct l2cap_conn *conn = container_of(work, struct l2cap_conn,
+					       pending_rx_work);
+	struct sk_buff *skb;
+
+	BT_DBG("");
+
+	while ((skb = skb_dequeue(&conn->pending_rx)))
+		l2cap_recv_frame(conn, skb);
+}
+
 static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon)
 {
 	struct l2cap_conn *conn = hcon->l2cap_data;
@@ -6983,6 +7007,9 @@ static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon)
 	else
 		INIT_DELAYED_WORK(&conn->info_timer, l2cap_info_timeout);
 
+	skb_queue_head_init(&conn->pending_rx);
+	INIT_WORK(&conn->pending_rx_work, process_pending_rx);
+
 	conn->disc_reason = HCI_ERROR_REMOTE_USER_TERM;
 
 	return conn;
-- 
1.8.4.2


^ permalink raw reply related

* [PATCH v4 1/2] Bluetooth: Reorder L2CAP functions to avoid forward declarations
From: johan.hedberg @ 2014-01-17 18:45 UTC (permalink / raw)
  To: linux-bluetooth

From: Johan Hedberg <johan.hedberg@intel.com>

This patch moves the l2cap_conn_add, is_valid_psm and l2cap_chan_connect
functions further down in l2cap_core.c. The patch doesn't contain
anything else except the relocation of these functions. By moving the
functions further down the patch enables a subsequent patch that adds a
pending RX queue to be implemented without a forward declaration of a
function.

Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
---
 net/bluetooth/l2cap_core.c | 415 ++++++++++++++++++++++-----------------------
 1 file changed, 207 insertions(+), 208 deletions(-)

diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index 3f0dd552cb2b..317a5737daf6 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -1722,66 +1722,6 @@ static void security_timeout(struct work_struct *work)
 	}
 }
 
-static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon)
-{
-	struct l2cap_conn *conn = hcon->l2cap_data;
-	struct hci_chan *hchan;
-
-	if (conn)
-		return conn;
-
-	hchan = hci_chan_create(hcon);
-	if (!hchan)
-		return NULL;
-
-	conn = kzalloc(sizeof(struct l2cap_conn), GFP_KERNEL);
-	if (!conn) {
-		hci_chan_del(hchan);
-		return NULL;
-	}
-
-	kref_init(&conn->ref);
-	hcon->l2cap_data = conn;
-	conn->hcon = hcon;
-	hci_conn_get(conn->hcon);
-	conn->hchan = hchan;
-
-	BT_DBG("hcon %p conn %p hchan %p", hcon, conn, hchan);
-
-	switch (hcon->type) {
-	case LE_LINK:
-		if (hcon->hdev->le_mtu) {
-			conn->mtu = hcon->hdev->le_mtu;
-			break;
-		}
-		/* fall through */
-	default:
-		conn->mtu = hcon->hdev->acl_mtu;
-		break;
-	}
-
-	conn->feat_mask = 0;
-
-	if (hcon->type == ACL_LINK)
-		conn->hs_enabled = test_bit(HCI_HS_ENABLED,
-					    &hcon->hdev->dev_flags);
-
-	spin_lock_init(&conn->lock);
-	mutex_init(&conn->chan_lock);
-
-	INIT_LIST_HEAD(&conn->chan_l);
-	INIT_LIST_HEAD(&conn->users);
-
-	if (hcon->type == LE_LINK)
-		INIT_DELAYED_WORK(&conn->security_timer, security_timeout);
-	else
-		INIT_DELAYED_WORK(&conn->info_timer, l2cap_info_timeout);
-
-	conn->disc_reason = HCI_ERROR_REMOTE_USER_TERM;
-
-	return conn;
-}
-
 static void l2cap_conn_free(struct kref *ref)
 {
 	struct l2cap_conn *conn = container_of(ref, struct l2cap_conn, ref);
@@ -1852,154 +1792,6 @@ static struct l2cap_chan *l2cap_global_chan_by_psm(int state, __le16 psm,
 	return c1;
 }
 
-static bool is_valid_psm(u16 psm, u8 dst_type)
-{
-	if (!psm)
-		return false;
-
-	if (bdaddr_type_is_le(dst_type))
-		return (psm <= 0x00ff);
-
-	/* PSM must be odd and lsb of upper byte must be 0 */
-	return ((psm & 0x0101) == 0x0001);
-}
-
-int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid,
-		       bdaddr_t *dst, u8 dst_type)
-{
-	struct l2cap_conn *conn;
-	struct hci_conn *hcon;
-	struct hci_dev *hdev;
-	__u8 auth_type;
-	int err;
-
-	BT_DBG("%pMR -> %pMR (type %u) psm 0x%2.2x", &chan->src, dst,
-	       dst_type, __le16_to_cpu(psm));
-
-	hdev = hci_get_route(dst, &chan->src);
-	if (!hdev)
-		return -EHOSTUNREACH;
-
-	hci_dev_lock(hdev);
-
-	l2cap_chan_lock(chan);
-
-	if (!is_valid_psm(__le16_to_cpu(psm), dst_type) && !cid &&
-	    chan->chan_type != L2CAP_CHAN_RAW) {
-		err = -EINVAL;
-		goto done;
-	}
-
-	if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED && !(psm || cid)) {
-		err = -EINVAL;
-		goto done;
-	}
-
-	switch (chan->mode) {
-	case L2CAP_MODE_BASIC:
-		break;
-	case L2CAP_MODE_LE_FLOWCTL:
-		l2cap_le_flowctl_init(chan);
-		break;
-	case L2CAP_MODE_ERTM:
-	case L2CAP_MODE_STREAMING:
-		if (!disable_ertm)
-			break;
-		/* fall through */
-	default:
-		err = -ENOTSUPP;
-		goto done;
-	}
-
-	switch (chan->state) {
-	case BT_CONNECT:
-	case BT_CONNECT2:
-	case BT_CONFIG:
-		/* Already connecting */
-		err = 0;
-		goto done;
-
-	case BT_CONNECTED:
-		/* Already connected */
-		err = -EISCONN;
-		goto done;
-
-	case BT_OPEN:
-	case BT_BOUND:
-		/* Can connect */
-		break;
-
-	default:
-		err = -EBADFD;
-		goto done;
-	}
-
-	/* Set destination address and psm */
-	bacpy(&chan->dst, dst);
-	chan->dst_type = dst_type;
-
-	chan->psm = psm;
-	chan->dcid = cid;
-
-	auth_type = l2cap_get_auth_type(chan);
-
-	if (bdaddr_type_is_le(dst_type))
-		hcon = hci_connect(hdev, LE_LINK, dst, dst_type,
-				   chan->sec_level, auth_type);
-	else
-		hcon = hci_connect(hdev, ACL_LINK, dst, dst_type,
-				   chan->sec_level, auth_type);
-
-	if (IS_ERR(hcon)) {
-		err = PTR_ERR(hcon);
-		goto done;
-	}
-
-	conn = l2cap_conn_add(hcon);
-	if (!conn) {
-		hci_conn_drop(hcon);
-		err = -ENOMEM;
-		goto done;
-	}
-
-	if (cid && __l2cap_get_chan_by_dcid(conn, cid)) {
-		hci_conn_drop(hcon);
-		err = -EBUSY;
-		goto done;
-	}
-
-	/* Update source addr of the socket */
-	bacpy(&chan->src, &hcon->src);
-	chan->src_type = bdaddr_type(hcon, hcon->src_type);
-
-	l2cap_chan_unlock(chan);
-	l2cap_chan_add(conn, chan);
-	l2cap_chan_lock(chan);
-
-	/* l2cap_chan_add takes its own ref so we can drop this one */
-	hci_conn_drop(hcon);
-
-	l2cap_state_change(chan, BT_CONNECT);
-	__set_chan_timer(chan, chan->ops->get_sndtimeo(chan));
-
-	if (hcon->state == BT_CONNECTED) {
-		if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
-			__clear_chan_timer(chan);
-			if (l2cap_chan_check_security(chan))
-				l2cap_state_change(chan, BT_CONNECTED);
-		} else
-			l2cap_do_start(chan);
-	}
-
-	err = 0;
-
-done:
-	l2cap_chan_unlock(chan);
-	hci_dev_unlock(hdev);
-	hci_dev_put(hdev);
-	return err;
-}
-
 static void l2cap_monitor_timeout(struct work_struct *work)
 {
 	struct l2cap_chan *chan = container_of(work, struct l2cap_chan,
@@ -7136,6 +6928,213 @@ static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb)
 	}
 }
 
+static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon)
+{
+	struct l2cap_conn *conn = hcon->l2cap_data;
+	struct hci_chan *hchan;
+
+	if (conn)
+		return conn;
+
+	hchan = hci_chan_create(hcon);
+	if (!hchan)
+		return NULL;
+
+	conn = kzalloc(sizeof(struct l2cap_conn), GFP_KERNEL);
+	if (!conn) {
+		hci_chan_del(hchan);
+		return NULL;
+	}
+
+	kref_init(&conn->ref);
+	hcon->l2cap_data = conn;
+	conn->hcon = hcon;
+	hci_conn_get(conn->hcon);
+	conn->hchan = hchan;
+
+	BT_DBG("hcon %p conn %p hchan %p", hcon, conn, hchan);
+
+	switch (hcon->type) {
+	case LE_LINK:
+		if (hcon->hdev->le_mtu) {
+			conn->mtu = hcon->hdev->le_mtu;
+			break;
+		}
+		/* fall through */
+	default:
+		conn->mtu = hcon->hdev->acl_mtu;
+		break;
+	}
+
+	conn->feat_mask = 0;
+
+	if (hcon->type == ACL_LINK)
+		conn->hs_enabled = test_bit(HCI_HS_ENABLED,
+					    &hcon->hdev->dev_flags);
+
+	spin_lock_init(&conn->lock);
+	mutex_init(&conn->chan_lock);
+
+	INIT_LIST_HEAD(&conn->chan_l);
+	INIT_LIST_HEAD(&conn->users);
+
+	if (hcon->type == LE_LINK)
+		INIT_DELAYED_WORK(&conn->security_timer, security_timeout);
+	else
+		INIT_DELAYED_WORK(&conn->info_timer, l2cap_info_timeout);
+
+	conn->disc_reason = HCI_ERROR_REMOTE_USER_TERM;
+
+	return conn;
+}
+
+static bool is_valid_psm(u16 psm, u8 dst_type) {
+	if (!psm)
+		return false;
+
+	if (bdaddr_type_is_le(dst_type))
+		return (psm <= 0x00ff);
+
+	/* PSM must be odd and lsb of upper byte must be 0 */
+	return ((psm & 0x0101) == 0x0001);
+}
+
+int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid,
+		       bdaddr_t *dst, u8 dst_type)
+{
+	struct l2cap_conn *conn;
+	struct hci_conn *hcon;
+	struct hci_dev *hdev;
+	__u8 auth_type;
+	int err;
+
+	BT_DBG("%pMR -> %pMR (type %u) psm 0x%2.2x", &chan->src, dst,
+	       dst_type, __le16_to_cpu(psm));
+
+	hdev = hci_get_route(dst, &chan->src);
+	if (!hdev)
+		return -EHOSTUNREACH;
+
+	hci_dev_lock(hdev);
+
+	l2cap_chan_lock(chan);
+
+	if (!is_valid_psm(__le16_to_cpu(psm), dst_type) && !cid &&
+	    chan->chan_type != L2CAP_CHAN_RAW) {
+		err = -EINVAL;
+		goto done;
+	}
+
+	if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED && !(psm || cid)) {
+		err = -EINVAL;
+		goto done;
+	}
+
+	switch (chan->mode) {
+	case L2CAP_MODE_BASIC:
+		break;
+	case L2CAP_MODE_LE_FLOWCTL:
+		l2cap_le_flowctl_init(chan);
+		break;
+	case L2CAP_MODE_ERTM:
+	case L2CAP_MODE_STREAMING:
+		if (!disable_ertm)
+			break;
+		/* fall through */
+	default:
+		err = -ENOTSUPP;
+		goto done;
+	}
+
+	switch (chan->state) {
+	case BT_CONNECT:
+	case BT_CONNECT2:
+	case BT_CONFIG:
+		/* Already connecting */
+		err = 0;
+		goto done;
+
+	case BT_CONNECTED:
+		/* Already connected */
+		err = -EISCONN;
+		goto done;
+
+	case BT_OPEN:
+	case BT_BOUND:
+		/* Can connect */
+		break;
+
+	default:
+		err = -EBADFD;
+		goto done;
+	}
+
+	/* Set destination address and psm */
+	bacpy(&chan->dst, dst);
+	chan->dst_type = dst_type;
+
+	chan->psm = psm;
+	chan->dcid = cid;
+
+	auth_type = l2cap_get_auth_type(chan);
+
+	if (bdaddr_type_is_le(dst_type))
+		hcon = hci_connect(hdev, LE_LINK, dst, dst_type,
+				   chan->sec_level, auth_type);
+	else
+		hcon = hci_connect(hdev, ACL_LINK, dst, dst_type,
+				   chan->sec_level, auth_type);
+
+	if (IS_ERR(hcon)) {
+		err = PTR_ERR(hcon);
+		goto done;
+	}
+
+	conn = l2cap_conn_add(hcon);
+	if (!conn) {
+		hci_conn_drop(hcon);
+		err = -ENOMEM;
+		goto done;
+	}
+
+	if (cid && __l2cap_get_chan_by_dcid(conn, cid)) {
+		hci_conn_drop(hcon);
+		err = -EBUSY;
+		goto done;
+	}
+
+	/* Update source addr of the socket */
+	bacpy(&chan->src, &hcon->src);
+	chan->src_type = bdaddr_type(hcon, hcon->src_type);
+
+	l2cap_chan_unlock(chan);
+	l2cap_chan_add(conn, chan);
+	l2cap_chan_lock(chan);
+
+	/* l2cap_chan_add takes its own ref so we can drop this one */
+	hci_conn_drop(hcon);
+
+	l2cap_state_change(chan, BT_CONNECT);
+	__set_chan_timer(chan, chan->ops->get_sndtimeo(chan));
+
+	if (hcon->state == BT_CONNECTED) {
+		if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
+			__clear_chan_timer(chan);
+			if (l2cap_chan_check_security(chan))
+				l2cap_state_change(chan, BT_CONNECTED);
+		} else
+			l2cap_do_start(chan);
+	}
+
+	err = 0;
+
+done:
+	l2cap_chan_unlock(chan);
+	hci_dev_unlock(hdev);
+	hci_dev_put(hdev);
+	return err;
+}
+
 /* ---- L2CAP interface with lower layer (HCI) ---- */
 
 int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr)
-- 
1.8.4.2


^ permalink raw reply related

* Re: [PATCH 2/9] android: Build Audio HAL with SBC
From: Marcel Holtmann @ 2014-01-17 18:27 UTC (permalink / raw)
  To: Andrzej Kaczmarek; +Cc: linux-bluetooth@vger.kernel.org development
In-Reply-To: <1389973213-30251-3-git-send-email-andrzej.kaczmarek@tieto.com>

Hi Andrzej,

> Build for Android requires libsbc sources to be available in
> external/bluetooth/sbc. Build for host requires libsbc package to be
> installed.
> ---
> android/Android.mk  | 14 +++++++++++---
> android/Makefile.am |  2 ++
> configure.ac        |  7 +++++++
> 3 files changed, 20 insertions(+), 3 deletions(-)
> 
> diff --git a/android/Android.mk b/android/Android.mk
> index 7e97ec8..63a4a24 100644
> --- a/android/Android.mk
> +++ b/android/Android.mk
> @@ -3,8 +3,9 @@ LOCAL_PATH := $(call my-dir)
> # Retrieve BlueZ version from configure.ac file
> BLUEZ_VERSION := $(shell grep ^AC_INIT $(LOCAL_PATH)/../configure.ac | cpp -P -D'AC_INIT(_,v)=v')
> 
> -# Specify pathmap for glib
> -pathmap_INCL += glib:external/bluetooth/glib
> +# Specify pathmap for glib and sbc
> +pathmap_INCL += glib:external/bluetooth/glib \
> +	sbc:external/bluetooth/sbc
> 
> # Specify common compiler flags
> BLUEZ_COMMON_CFLAGS := -DVERSION=\"$(BLUEZ_VERSION)\" \
> @@ -220,11 +221,18 @@ include $(BUILD_EXECUTABLE)
> 
> include $(CLEAR_VARS)
> 
> -LOCAL_SRC_FILES := hal-audio.c
> +LOCAL_SRC_FILES := hal-audio.c \
> +	../../sbc/sbc/sbc.c \
> +	../../sbc/sbc/sbc_primitives.c \
> +	../../sbc/sbc/sbc_primitives_armv6.c \
> +	../../sbc/sbc/sbc_primitives_iwmmxt.c \
> +	../../sbc/sbc/sbc_primitives_mmx.c \
> +	../../sbc/sbc/sbc_primitives_neon.c \

why? Can we not just build libsbc for Android?

I rather install an extra library and not have to make this builtin.

> 
> LOCAL_C_INCLUDES = \
> 	$(call include-path-for, system-core) \
> 	$(call include-path-for, libhardware) \
> +	$(call include-path-for, sbc) \
> 
> LOCAL_SHARED_LIBRARIES := \
> 	libcutils \
> diff --git a/android/Makefile.am b/android/Makefile.am
> index 8d2714d..01d8996 100644
> --- a/android/Makefile.am
> +++ b/android/Makefile.am
> @@ -130,6 +130,8 @@ android_audio_a2dp_default_la_SOURCES = android/audio-msg.h \
> 
> android_audio_a2dp_default_la_CFLAGS = $(AM_CFLAGS) -I$(srcdir)/android
> 
> +android_audio_a2dp_default_la_LIBADD = @SBC_LIBS@
> +
> android_audio_a2dp_default_la_LDFLAGS = $(AM_LDFLAGS) -module -avoid-version \
> 					-no-undefined -pthread
> 
> diff --git a/configure.ac b/configure.ac
> index c85f208..79c3705 100644
> --- a/configure.ac
> +++ b/configure.ac
> @@ -252,6 +252,13 @@ AC_ARG_ENABLE(android, AC_HELP_STRING([--enable-android],
> 					[enable_android=${enableval}])
> AM_CONDITIONAL(ANDROID, test "${enable_android}" = "yes")
> 
> +if (test "${enable_android}" = "yes"); then
> +	PKG_CHECK_MODULES(SBC, sbc >= 1.0, dummy=yes,
> +					AC_MSG_ERROR(libsbc1 >= 1.0 is required))

This should not read libsbc1. There is no such thing as libsbc1. It should read SBC library.

> +	AC_SUBST(SBC_CFLAGS)
> +	AC_SUBST(SBC_LIBS)
> +fi
> +
> AC_DEFINE_UNQUOTED(ANDROID_STORAGEDIR, "${storagedir}/android",
> 			[Directory for the Android daemon storage files])

Regards

Marcel


^ permalink raw reply

* Re: [PATCH 5/9] android/hal-audio: Calculate SBC stream parameters
From: Marcel Holtmann @ 2014-01-17 18:25 UTC (permalink / raw)
  To: Andrzej Kaczmarek; +Cc: linux-bluetooth@vger.kernel.org development
In-Reply-To: <1389973213-30251-6-git-send-email-andrzej.kaczmarek@tieto.com>

Hi Andrzej,

> This patch adds necessary calculations for SBC stream parameters.
> 
> Both input and output buffers are expected to have exact amount of
> data to fill single media packet (based on transport channel MTU).
> 
> Frame duration will be used to synchronize input and output streams.
> ---
> android/hal-audio.c | 50 ++++++++++++++++++++++++++++++-----
> android/rtp.h       | 76 +++++++++++++++++++++++++++++++++++++++++++++++++++++
> 2 files changed, 120 insertions(+), 6 deletions(-)
> create mode 100644 android/rtp.h
> 
> diff --git a/android/hal-audio.c b/android/hal-audio.c
> index e5c646c..3f53295 100644
> --- a/android/hal-audio.c
> +++ b/android/hal-audio.c
> @@ -33,6 +33,7 @@
> #include "hal-msg.h"
> #include "../profiles/audio/a2dp-codecs.h"
> #include <sbc/sbc.h>
> +#include "rtp.h"
> 
> static const uint8_t a2dp_src_uuid[] = {
> 		0x00, 0x00, 0x11, 0x0a, 0x00, 0x00, 0x10, 0x00,
> @@ -46,6 +47,12 @@ static pthread_t ipc_th = 0;
> static pthread_mutex_t close_mutex = PTHREAD_MUTEX_INITIALIZER;
> static pthread_mutex_t sk_mutex = PTHREAD_MUTEX_INITIALIZER;
> 
> +struct media_packet {
> +	struct rtp_header hdr;
> +	struct rtp_payload payload;
> +	uint8_t data[0];
> +};
> +
> struct audio_input_config {
> 	uint32_t rate;
> 	uint32_t channels;
> @@ -56,10 +63,19 @@ struct sbc_data {
> 	a2dp_sbc_t sbc;
> 
> 	sbc_t enc;
> +
> +	size_t in_frame_len;
> +	size_t in_buf_size;
> +
> +	size_t out_buf_size;
> +	uint8_t *out_buf;
> +
> +	unsigned frame_duration;
> };
> 
> static int sbc_get_presets(struct audio_preset *preset, size_t *len);
> -static int sbc_codec_init(struct audio_preset *preset, void **codec_data);
> +static int sbc_codec_init(struct audio_preset *preset, uint16_t mtu,
> +				void **codec_data);
> static int sbc_cleanup(void *codec_data);
> static int sbc_get_config(void *codec_data,
> 					struct audio_input_config *config);
> @@ -69,7 +85,8 @@ struct audio_codec {
> 
> 	int (*get_presets) (struct audio_preset *preset, size_t *len);
> 
> -	int (*init) (struct audio_preset *preset, void **codec_data);
> +	int (*init) (struct audio_preset *preset, uint16_t mtu,
> +				void **codec_data);
> 	int (*cleanup) (void *codec_data);
> 	int (*get_config) (void *codec_data,
> 					struct audio_input_config *config);
> @@ -251,9 +268,14 @@ static void sbc_init_encoder(struct sbc_data *sbc_data)
> 	}
> }
> 
> -static int sbc_codec_init(struct audio_preset *preset, void **codec_data)
> +static int sbc_codec_init(struct audio_preset *preset, uint16_t mtu,
> +				void **codec_data)
> {
> 	struct sbc_data *sbc_data;
> +	size_t hdr_len = sizeof(struct media_packet);
> +	size_t in_frame_len;
> +	size_t out_frame_len;
> +	size_t num_frames;
> 
> 	DBG("");
> 
> @@ -268,6 +290,18 @@ static int sbc_codec_init(struct audio_preset *preset, void **codec_data)
> 
> 	sbc_init_encoder(sbc_data);
> 
> +	in_frame_len = sbc_get_codesize(&sbc_data->enc);
> +	out_frame_len = sbc_get_frame_length(&sbc_data->enc);
> +	num_frames = (mtu - hdr_len) / out_frame_len;
> +
> +	sbc_data->in_frame_len = in_frame_len;
> +	sbc_data->in_buf_size = num_frames * in_frame_len;
> +
> +	sbc_data->out_buf_size = hdr_len + num_frames * out_frame_len;
> +	sbc_data->out_buf = calloc(1, sbc_data->out_buf_size);
> +
> +	sbc_data->frame_duration = sbc_get_frame_duration(&sbc_data->enc);
> +
> 	*codec_data = sbc_data;
> 
> 	return AUDIO_STATUS_SUCCESS;
> @@ -280,6 +314,7 @@ static int sbc_cleanup(void *codec_data)
> 	DBG("");
> 
> 	sbc_finish(&sbc_data->enc);
> +	free(sbc_data->out_buf);
> 	free(codec_data);
> 
> 	return AUDIO_STATUS_SUCCESS;
> @@ -511,7 +546,7 @@ static int ipc_close_cmd(uint8_t endpoint_id)
> 	return result;
> }
> 
> -static int ipc_open_stream_cmd(uint8_t endpoint_id,
> +static int ipc_open_stream_cmd(uint8_t endpoint_id, uint16_t *mtu,
> 					struct audio_preset **caps)
> {
> 	char buf[BLUEZ_AUDIO_MTU];
> @@ -534,6 +569,7 @@ static int ipc_open_stream_cmd(uint8_t endpoint_id,
> 	if (result == AUDIO_STATUS_SUCCESS) {
> 		size_t buf_len = sizeof(struct audio_preset) +
> 					rsp->preset[0].len;
> +		*mtu = rsp->mtu;
> 		*caps = malloc(buf_len);
> 		memcpy(*caps, &rsp->preset, buf_len);
> 	} else {
> @@ -919,6 +955,7 @@ static int audio_open_output_stream(struct audio_hw_device *dev,
> 	struct a2dp_stream_out *out;
> 	struct audio_preset *preset;
> 	const struct audio_codec *codec;
> +	uint16_t mtu;
> 
> 	out = calloc(1, sizeof(struct a2dp_stream_out));
> 	if (!out)
> @@ -946,7 +983,8 @@ static int audio_open_output_stream(struct audio_hw_device *dev,
> 	/* TODO: for now we always use endpoint 0 */
> 	out->ep = &audio_endpoints[0];
> 
> -	if (ipc_open_stream_cmd(out->ep->id, &preset) != AUDIO_STATUS_SUCCESS)
> +	if (ipc_open_stream_cmd(out->ep->id, &mtu, &preset) !=
> +			AUDIO_STATUS_SUCCESS)
> 		goto fail;
> 
> 	if (!preset)
> @@ -954,7 +992,7 @@ static int audio_open_output_stream(struct audio_hw_device *dev,
> 
> 	codec = out->ep->codec;
> 
> -	codec->init(preset, &out->ep->codec_data);
> +	codec->init(preset, mtu, &out->ep->codec_data);
> 	codec->get_config(out->ep->codec_data, &out->cfg);
> 
> 	DBG("rate=%d channels=%d format=%d", out->cfg.rate,
> diff --git a/android/rtp.h b/android/rtp.h
> new file mode 100644
> index 0000000..45fddcf
> --- /dev/null
> +++ b/android/rtp.h
> @@ -0,0 +1,76 @@
> +/*
> + *
> + *  BlueZ - Bluetooth protocol stack for Linux
> + *
> + *  Copyright (C) 2004-2010  Marcel Holtmann <marcel@holtmann.org>
> + *
> + *
> + *  This library is free software; you can redistribute it and/or
> + *  modify it under the terms of the GNU Lesser General Public
> + *  License as published by the Free Software Foundation; either
> + *  version 2.1 of the License, or (at your option) any later version.
> + *
> + *  This library is distributed in the hope that it will be useful,
> + *  but WITHOUT ANY WARRANTY; without even the implied warranty of
> + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> + *  Lesser General Public License for more details.
> + *
> + *  You should have received a copy of the GNU Lesser General Public
> + *  License along with this library; if not, write to the Free Software
> + *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
> + *
> + */

where is this file coming from? Why do we need a copy of it?

Regards

Marcel


^ permalink raw reply

* Re: [PATCH 4/9] android/hal-audio: Initialize SBC encoder
From: Marcel Holtmann @ 2014-01-17 18:24 UTC (permalink / raw)
  To: Andrzej Kaczmarek; +Cc: linux-bluetooth@vger.kernel.org development
In-Reply-To: <1389973213-30251-5-git-send-email-andrzej.kaczmarek@tieto.com>

Hi Andrzej,

> ---
> android/hal-audio.c | 72 +++++++++++++++++++++++++++++++++++++++++++++++++++++
> 1 file changed, 72 insertions(+)
> 
> diff --git a/android/hal-audio.c b/android/hal-audio.c
> index f53dba0..e5c646c 100644
> --- a/android/hal-audio.c
> +++ b/android/hal-audio.c
> @@ -32,6 +32,7 @@
> #include "hal-log.h"
> #include "hal-msg.h"
> #include "../profiles/audio/a2dp-codecs.h"
> +#include <sbc/sbc.h>
> 
> static const uint8_t a2dp_src_uuid[] = {
> 		0x00, 0x00, 0x11, 0x0a, 0x00, 0x00, 0x10, 0x00,
> @@ -53,6 +54,8 @@ struct audio_input_config {
> 
> struct sbc_data {
> 	a2dp_sbc_t sbc;
> +
> +	sbc_t enc;
> };
> 
> static int sbc_get_presets(struct audio_preset *preset, size_t *len);
> @@ -184,6 +187,70 @@ static int sbc_get_presets(struct audio_preset *preset, size_t *len)
> 	return i;
> }
> 
> +static void sbc_init_encoder(struct sbc_data *sbc_data)
> +{
> +	a2dp_sbc_t *in = &sbc_data->sbc;
> +	sbc_t *out = &sbc_data->enc;
> +
> +	DBG("");
> +
> +	sbc_init(out, 0L);
> +
> +	switch (in->frequency) {
> +	case SBC_SAMPLING_FREQ_16000:
> +		out->frequency = SBC_FREQ_16000;
> +		break;
> +	case SBC_SAMPLING_FREQ_32000:
> +		out->frequency = SBC_FREQ_32000;
> +		break;
> +	case SBC_SAMPLING_FREQ_44100:
> +		out->frequency = SBC_FREQ_44100;
> +		break;
> +	case SBC_SAMPLING_FREQ_48000:
> +		out->frequency = SBC_FREQ_48000;
> +		break;
> +	}
> +
> +	out->subbands = in->subbands == SBC_SUBBANDS_4 ? SBC_SB_4 : SBC_SB_8;
> +
> +	switch (in->channel_mode) {
> +	case SBC_CHANNEL_MODE_MONO:
> +		out->mode = SBC_MODE_MONO;
> +		break;
> +	case SBC_CHANNEL_MODE_DUAL_CHANNEL:
> +		out->mode = SBC_MODE_DUAL_CHANNEL;
> +		break;
> +	case SBC_CHANNEL_MODE_JOINT_STEREO:
> +		out->mode = SBC_MODE_JOINT_STEREO;
> +		break;
> +	case SBC_CHANNEL_MODE_STEREO:
> +		out->mode = SBC_MODE_STEREO;
> +		break;
> +	}
> +
> +	out->endian = SBC_LE;
> +
> +	out->bitpool = in->max_bitpool;
> +
> +	out->allocation = in->allocation_method == SBC_ALLOCATION_SNR ?
> +				SBC_AM_SNR : SBC_AM_LOUDNESS;
> +
> +	switch (in->block_length) {
> +	case SBC_BLOCK_LENGTH_4:
> +		out->blocks = SBC_BLK_4;
> +		break;
> +	case SBC_BLOCK_LENGTH_8:
> +		out->blocks = SBC_BLK_8;
> +		break;
> +	case SBC_BLOCK_LENGTH_12:
> +		out->blocks = SBC_BLK_12;
> +		break;
> +	case SBC_BLOCK_LENGTH_16:
> +		out->blocks = SBC_BLK_16;
> +		break;
> +	}

aren’t the values all the same? This looks pretty complicated for something that should be dead simple. Does Android really had to duplicate every single definition with the same prefix?

> +}
> +
> static int sbc_codec_init(struct audio_preset *preset, void **codec_data)
> {
> 	struct sbc_data *sbc_data;
> @@ -199,6 +266,8 @@ static int sbc_codec_init(struct audio_preset *preset, void **codec_data)
> 
> 	memcpy(&sbc_data->sbc, preset->data, preset->len);
> 
> +	sbc_init_encoder(sbc_data);
> +
> 	*codec_data = sbc_data;
> 
> 	return AUDIO_STATUS_SUCCESS;
> @@ -206,8 +275,11 @@ static int sbc_codec_init(struct audio_preset *preset, void **codec_data)
> 
> static int sbc_cleanup(void *codec_data)
> {
> +	struct sbc_data *sbc_data = (struct sbc_data *) codec_data;
> +
> 	DBG("");
> 
> +	sbc_finish(&sbc_data->enc);
> 	free(codec_data);
> 
> 	return AUDIO_STATUS_SUCCESS;

Regards

Marcel


^ permalink raw reply

* Re: [PATCH 8/9] android/hal-audio: Read fd from Output Stream response
From: Szymon Janc @ 2014-01-17 18:13 UTC (permalink / raw)
  To: Andrzej Kaczmarek; +Cc: linux-bluetooth
In-Reply-To: <1389973213-30251-9-git-send-email-andrzej.kaczmarek@tieto.com>

Hi Andrzej,

On Friday 17 January 2014 16:40:12 Andrzej Kaczmarek wrote:
> ---
>  android/hal-audio.c | 11 +++++++----
>  1 file changed, 7 insertions(+), 4 deletions(-)
> 
> diff --git a/android/hal-audio.c b/android/hal-audio.c
> index f2cb12a..d8438f7 100644
> --- a/android/hal-audio.c
> +++ b/android/hal-audio.c
> @@ -575,7 +575,7 @@ static int ipc_close_cmd(uint8_t endpoint_id)
>  	return result;
>  }
> 
> -static int ipc_open_stream_cmd(uint8_t endpoint_id, uint16_t *mtu,
> +static int ipc_open_stream_cmd(uint8_t endpoint_id, uint16_t *mtu, int *fd,
> struct audio_preset **caps)
>  {
>  	char buf[BLUEZ_AUDIO_MTU];
> @@ -593,7 +593,7 @@ static int ipc_open_stream_cmd(uint8_t endpoint_id,
> uint16_t *mtu, cmd.id = endpoint_id;
> 
>  	result = audio_ipc_cmd(AUDIO_SERVICE_ID, AUDIO_OP_OPEN_STREAM,
> -				sizeof(cmd), &cmd, &rsp_len, rsp, NULL);
> +				sizeof(cmd), &cmd, &rsp_len, rsp, fd);
> 
>  	if (result == AUDIO_STATUS_SUCCESS) {
>  		size_t buf_len = sizeof(struct audio_preset) +
> @@ -990,6 +990,7 @@ static int audio_open_output_stream(struct
> audio_hw_device *dev, struct audio_preset *preset;
>  	const struct audio_codec *codec;
>  	uint16_t mtu;
> +	int fd;
> 
>  	out = calloc(1, sizeof(struct a2dp_stream_out));
>  	if (!out)
> @@ -1017,13 +1018,15 @@ static int audio_open_output_stream(struct
> audio_hw_device *dev, /* TODO: for now we always use endpoint 0 */
>  	out->ep = &audio_endpoints[0];
> 
> -	if (ipc_open_stream_cmd(out->ep->id, &mtu, &preset) !=
> +	if (ipc_open_stream_cmd(out->ep->id, &mtu, &fd, &preset) !=
>  			AUDIO_STATUS_SUCCESS)
>  		goto fail;
> 
> -	if (!preset)
> +	if (!preset || fd < 0)
>  		goto fail;

For sanity, code under fail label should be updated to handle that either 
preset or fd might be valid here.

> 
> +	out->ep->fd = fd;
> +

I might be missing something but fd is never closed. Should this be done in 
audio_close_output_stream() ?

>  	codec = out->ep->codec;
> 
>  	codec->init(preset, mtu, &out->ep->codec_data);

-- 
Szymon K. Janc
szymon.janc@gmail.com

^ permalink raw reply

* [PATCH 9/9] android/hal-audio: Add proper SBC encoding
From: Andrzej Kaczmarek @ 2014-01-17 15:40 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Andrzej Kaczmarek
In-Reply-To: <1389973213-30251-1-git-send-email-andrzej.kaczmarek@tieto.com>

Input and output stream is configured in a way that each input buffer
can be encoded to exactly one output buffer.

Reading from AudioFlinger is synchronized based on amounts of frames
which were expected to be sent since stream was resumed, i.e. as long
as we sent enough data we can wait for period of single media packet
before we need another buffer from input. Without synchronization
we'd receive next input buffer as soon as we process current one.
---
 android/hal-audio.c | 96 +++++++++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 93 insertions(+), 3 deletions(-)

diff --git a/android/hal-audio.c b/android/hal-audio.c
index d8438f7..86ef97b 100644
--- a/android/hal-audio.c
+++ b/android/hal-audio.c
@@ -24,6 +24,7 @@
 #include <sys/socket.h>
 #include <sys/un.h>
 #include <unistd.h>
+#include <arpa/inet.h>
 
 #include <hardware/audio.h>
 #include <hardware/hardware.h>
@@ -74,8 +75,22 @@ struct sbc_data {
 
 	struct timespec start;
 	unsigned frames_sent;
+
+	uint16_t seq;
 };
 
+static inline void timespec_diff(struct timespec *a, struct timespec *b,
+					struct timespec *res)
+{
+	res->tv_sec = a->tv_sec - b->tv_sec;
+	res->tv_nsec = a->tv_nsec - b->tv_nsec;
+
+	if (res->tv_nsec < 0) {
+		res->tv_sec--;
+		res->tv_nsec += 1000000000; /* 1sec */
+	}
+}
+
 static int sbc_get_presets(struct audio_preset *preset, size_t *len);
 static int sbc_codec_init(struct audio_preset *preset, uint16_t mtu,
 				void **codec_data);
@@ -84,6 +99,8 @@ static int sbc_get_config(void *codec_data,
 					struct audio_input_config *config);
 static size_t sbc_get_buffer_size(void *codec_data);
 static void sbc_resume(void *codec_data);
+static ssize_t sbc_write_data(void *codec_data, const void *buffer,
+					size_t bytes, int fd);
 
 struct audio_codec {
 	uint8_t type;
@@ -98,7 +115,7 @@ struct audio_codec {
 	size_t (*get_buffer_size) (void *codec_data);
 	void (*resume) (void *codec_data);
 	ssize_t (*write_data) (void *codec_data, const void *buffer,
-				size_t bytes);
+				size_t bytes, int fd);
 };
 
 static const struct audio_codec audio_codecs[] = {
@@ -112,6 +129,7 @@ static const struct audio_codec audio_codecs[] = {
 		.get_config = sbc_get_config,
 		.get_buffer_size = sbc_get_buffer_size,
 		.resume = sbc_resume,
+		.write_data = sbc_write_data,
 	}
 };
 
@@ -378,6 +396,74 @@ static void sbc_resume(void *codec_data)
 	sbc_data->frames_sent = 0;
 }
 
+static ssize_t sbc_write_data(void *codec_data, const void *buffer,
+				size_t bytes, int fd)
+{
+	struct sbc_data *sbc_data = (struct sbc_data *) codec_data;
+	size_t consumed = 0;
+	size_t encoded = 0;
+	struct media_packet *mp = (struct media_packet *) sbc_data->out_buf;
+	size_t free_space = sbc_data->out_buf_size - sizeof(*mp);
+	struct timespec cur;
+	struct timespec diff;
+	unsigned expected_frames;
+	int ret;
+
+	mp->hdr.v = 2;
+	mp->hdr.pt = 1;
+	mp->hdr.sequence_number = htons(sbc_data->seq++);
+	mp->hdr.ssrc = htonl(1);
+	mp->payload.frame_count = 0;
+
+	while (bytes - consumed >= sbc_data->in_frame_len) {
+		ssize_t written = 0;
+
+		ret = sbc_encode(&sbc_data->enc, buffer + consumed,
+					sbc_data->in_frame_len,
+					mp->data + encoded, free_space,
+					&written);
+
+		if (ret < 0) {
+			DBG("failed to encode block");
+			break;
+		}
+
+		mp->payload.frame_count++;
+
+		consumed += ret;
+		encoded += written;
+		free_space -= written;
+	}
+
+	ret = write(fd, mp, sizeof(*mp) + encoded);
+	if (ret < 0) {
+		int err = errno;
+		DBG("error writing data: %d (%s)", err, strerror(err));
+	}
+
+	if (consumed != bytes || free_space != 0) {
+		/*
+		 * we should encode all input data and fill output buffer
+		 * if we did not, something went wrong but we can't really
+		 * handle this so this is just sanity check
+		 */
+		DBG("some data were not encoded");
+	}
+
+	sbc_data->frames_sent += mp->payload.frame_count;
+
+	clock_gettime(CLOCK_MONOTONIC, &cur);
+	timespec_diff(&cur, &sbc_data->start, &diff);
+	expected_frames = (diff.tv_sec * 1000000 + diff.tv_nsec / 1000) /
+				sbc_data->frame_duration;
+
+	if (sbc_data->frames_sent >= expected_frames)
+		usleep(sbc_data->frame_duration * mp->payload.frame_count);
+
+	/* we always assume that all data was processed and sent */
+	return bytes;
+}
+
 static void audio_ipc_cleanup(void)
 {
 	if (audio_sk >= 0) {
@@ -710,9 +796,13 @@ static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
 		return -1;
 	}
 
-	/* TODO: encode data using codec */
+	if (out->ep->fd < 0) {
+		DBG("no transport");
+		return -1;
+	}
 
-	return bytes;
+	return out->ep->codec->write_data(out->ep->codec_data, buffer,
+						bytes, out->ep->fd);
 }
 
 static uint32_t out_get_sample_rate(const struct audio_stream *stream)
-- 
1.8.5.2


^ permalink raw reply related

* [PATCH 8/9] android/hal-audio: Read fd from Output Stream response
From: Andrzej Kaczmarek @ 2014-01-17 15:40 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Andrzej Kaczmarek
In-Reply-To: <1389973213-30251-1-git-send-email-andrzej.kaczmarek@tieto.com>

---
 android/hal-audio.c | 11 +++++++----
 1 file changed, 7 insertions(+), 4 deletions(-)

diff --git a/android/hal-audio.c b/android/hal-audio.c
index f2cb12a..d8438f7 100644
--- a/android/hal-audio.c
+++ b/android/hal-audio.c
@@ -575,7 +575,7 @@ static int ipc_close_cmd(uint8_t endpoint_id)
 	return result;
 }
 
-static int ipc_open_stream_cmd(uint8_t endpoint_id, uint16_t *mtu,
+static int ipc_open_stream_cmd(uint8_t endpoint_id, uint16_t *mtu, int *fd,
 					struct audio_preset **caps)
 {
 	char buf[BLUEZ_AUDIO_MTU];
@@ -593,7 +593,7 @@ static int ipc_open_stream_cmd(uint8_t endpoint_id, uint16_t *mtu,
 	cmd.id = endpoint_id;
 
 	result = audio_ipc_cmd(AUDIO_SERVICE_ID, AUDIO_OP_OPEN_STREAM,
-				sizeof(cmd), &cmd, &rsp_len, rsp, NULL);
+				sizeof(cmd), &cmd, &rsp_len, rsp, fd);
 
 	if (result == AUDIO_STATUS_SUCCESS) {
 		size_t buf_len = sizeof(struct audio_preset) +
@@ -990,6 +990,7 @@ static int audio_open_output_stream(struct audio_hw_device *dev,
 	struct audio_preset *preset;
 	const struct audio_codec *codec;
 	uint16_t mtu;
+	int fd;
 
 	out = calloc(1, sizeof(struct a2dp_stream_out));
 	if (!out)
@@ -1017,13 +1018,15 @@ static int audio_open_output_stream(struct audio_hw_device *dev,
 	/* TODO: for now we always use endpoint 0 */
 	out->ep = &audio_endpoints[0];
 
-	if (ipc_open_stream_cmd(out->ep->id, &mtu, &preset) !=
+	if (ipc_open_stream_cmd(out->ep->id, &mtu, &fd, &preset) !=
 			AUDIO_STATUS_SUCCESS)
 		goto fail;
 
-	if (!preset)
+	if (!preset || fd < 0)
 		goto fail;
 
+	out->ep->fd = fd;
+
 	codec = out->ep->codec;
 
 	codec->init(preset, mtu, &out->ep->codec_data);
-- 
1.8.5.2


^ permalink raw reply related

* [PATCH 7/9] android/hal-audio: Return proper buffer size to AudioFlinger
From: Andrzej Kaczmarek @ 2014-01-17 15:40 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Andrzej Kaczmarek
In-Reply-To: <1389973213-30251-1-git-send-email-andrzej.kaczmarek@tieto.com>

---
 android/hal-audio.c | 17 ++++++++++++++++-
 1 file changed, 16 insertions(+), 1 deletion(-)

diff --git a/android/hal-audio.c b/android/hal-audio.c
index aeb6ea4..f2cb12a 100644
--- a/android/hal-audio.c
+++ b/android/hal-audio.c
@@ -82,6 +82,7 @@ static int sbc_codec_init(struct audio_preset *preset, uint16_t mtu,
 static int sbc_cleanup(void *codec_data);
 static int sbc_get_config(void *codec_data,
 					struct audio_input_config *config);
+static size_t sbc_get_buffer_size(void *codec_data);
 static void sbc_resume(void *codec_data);
 
 struct audio_codec {
@@ -94,6 +95,7 @@ struct audio_codec {
 	int (*cleanup) (void *codec_data);
 	int (*get_config) (void *codec_data,
 					struct audio_input_config *config);
+	size_t (*get_buffer_size) (void *codec_data);
 	void (*resume) (void *codec_data);
 	ssize_t (*write_data) (void *codec_data, const void *buffer,
 				size_t bytes);
@@ -108,6 +110,7 @@ static const struct audio_codec audio_codecs[] = {
 		.init = sbc_codec_init,
 		.cleanup = sbc_cleanup,
 		.get_config = sbc_get_config,
+		.get_buffer_size = sbc_get_buffer_size,
 		.resume = sbc_resume,
 	}
 };
@@ -355,6 +358,15 @@ static int sbc_get_config(void *codec_data,
 	return AUDIO_STATUS_SUCCESS;
 }
 
+static size_t sbc_get_buffer_size(void *codec_data)
+{
+	struct sbc_data *sbc_data = (struct sbc_data *) codec_data;
+
+	DBG("");
+
+	return sbc_data->in_buf_size;
+}
+
 static void sbc_resume(void *codec_data)
 {
 	struct sbc_data *sbc_data = (struct sbc_data *) codec_data;
@@ -728,8 +740,11 @@ static int out_set_sample_rate(struct audio_stream *stream, uint32_t rate)
 
 static size_t out_get_buffer_size(const struct audio_stream *stream)
 {
+	struct a2dp_stream_out *out = (struct a2dp_stream_out *) stream;
+
 	DBG("");
-	return 20 * 512;
+
+	return out->ep->codec->get_buffer_size(out->ep->codec_data);
 }
 
 static uint32_t out_get_channels(const struct audio_stream *stream)
-- 
1.8.5.2


^ permalink raw reply related

* [PATCH 6/9] android/hal-audio: Add resume to codec callbacks
From: Andrzej Kaczmarek @ 2014-01-17 15:40 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Andrzej Kaczmarek
In-Reply-To: <1389973213-30251-1-git-send-email-andrzej.kaczmarek@tieto.com>

Once stream is resumed it may be required to reset some state of codec,
i.e. in case of SBC we need to reset monotonic clock and frames count
which are used for synchronization.
---
 android/hal-audio.c | 19 +++++++++++++++++++
 1 file changed, 19 insertions(+)

diff --git a/android/hal-audio.c b/android/hal-audio.c
index 3f53295..aeb6ea4 100644
--- a/android/hal-audio.c
+++ b/android/hal-audio.c
@@ -71,6 +71,9 @@ struct sbc_data {
 	uint8_t *out_buf;
 
 	unsigned frame_duration;
+
+	struct timespec start;
+	unsigned frames_sent;
 };
 
 static int sbc_get_presets(struct audio_preset *preset, size_t *len);
@@ -79,6 +82,7 @@ static int sbc_codec_init(struct audio_preset *preset, uint16_t mtu,
 static int sbc_cleanup(void *codec_data);
 static int sbc_get_config(void *codec_data,
 					struct audio_input_config *config);
+static void sbc_resume(void *codec_data);
 
 struct audio_codec {
 	uint8_t type;
@@ -90,6 +94,7 @@ struct audio_codec {
 	int (*cleanup) (void *codec_data);
 	int (*get_config) (void *codec_data,
 					struct audio_input_config *config);
+	void (*resume) (void *codec_data);
 	ssize_t (*write_data) (void *codec_data, const void *buffer,
 				size_t bytes);
 };
@@ -103,6 +108,7 @@ static const struct audio_codec audio_codecs[] = {
 		.init = sbc_codec_init,
 		.cleanup = sbc_cleanup,
 		.get_config = sbc_get_config,
+		.resume = sbc_resume,
 	}
 };
 
@@ -349,6 +355,17 @@ static int sbc_get_config(void *codec_data,
 	return AUDIO_STATUS_SUCCESS;
 }
 
+static void sbc_resume(void *codec_data)
+{
+	struct sbc_data *sbc_data = (struct sbc_data *) codec_data;
+
+	DBG("");
+
+	clock_gettime(CLOCK_MONOTONIC, &sbc_data->start);
+
+	sbc_data->frames_sent = 0;
+}
+
 static void audio_ipc_cleanup(void)
 {
 	if (audio_sk >= 0) {
@@ -671,6 +688,8 @@ static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
 		if (ipc_resume_stream_cmd(out->ep->id) != AUDIO_STATUS_SUCCESS)
 			return -1;
 
+		out->ep->codec->resume(out->ep->codec_data);
+
 		out->audio_state = AUDIO_A2DP_STATE_STARTED;
 	}
 
-- 
1.8.5.2


^ permalink raw reply related

* [PATCH 5/9] android/hal-audio: Calculate SBC stream parameters
From: Andrzej Kaczmarek @ 2014-01-17 15:40 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Andrzej Kaczmarek
In-Reply-To: <1389973213-30251-1-git-send-email-andrzej.kaczmarek@tieto.com>

This patch adds necessary calculations for SBC stream parameters.

Both input and output buffers are expected to have exact amount of
data to fill single media packet (based on transport channel MTU).

Frame duration will be used to synchronize input and output streams.
---
 android/hal-audio.c | 50 ++++++++++++++++++++++++++++++-----
 android/rtp.h       | 76 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 120 insertions(+), 6 deletions(-)
 create mode 100644 android/rtp.h

diff --git a/android/hal-audio.c b/android/hal-audio.c
index e5c646c..3f53295 100644
--- a/android/hal-audio.c
+++ b/android/hal-audio.c
@@ -33,6 +33,7 @@
 #include "hal-msg.h"
 #include "../profiles/audio/a2dp-codecs.h"
 #include <sbc/sbc.h>
+#include "rtp.h"
 
 static const uint8_t a2dp_src_uuid[] = {
 		0x00, 0x00, 0x11, 0x0a, 0x00, 0x00, 0x10, 0x00,
@@ -46,6 +47,12 @@ static pthread_t ipc_th = 0;
 static pthread_mutex_t close_mutex = PTHREAD_MUTEX_INITIALIZER;
 static pthread_mutex_t sk_mutex = PTHREAD_MUTEX_INITIALIZER;
 
+struct media_packet {
+	struct rtp_header hdr;
+	struct rtp_payload payload;
+	uint8_t data[0];
+};
+
 struct audio_input_config {
 	uint32_t rate;
 	uint32_t channels;
@@ -56,10 +63,19 @@ struct sbc_data {
 	a2dp_sbc_t sbc;
 
 	sbc_t enc;
+
+	size_t in_frame_len;
+	size_t in_buf_size;
+
+	size_t out_buf_size;
+	uint8_t *out_buf;
+
+	unsigned frame_duration;
 };
 
 static int sbc_get_presets(struct audio_preset *preset, size_t *len);
-static int sbc_codec_init(struct audio_preset *preset, void **codec_data);
+static int sbc_codec_init(struct audio_preset *preset, uint16_t mtu,
+				void **codec_data);
 static int sbc_cleanup(void *codec_data);
 static int sbc_get_config(void *codec_data,
 					struct audio_input_config *config);
@@ -69,7 +85,8 @@ struct audio_codec {
 
 	int (*get_presets) (struct audio_preset *preset, size_t *len);
 
-	int (*init) (struct audio_preset *preset, void **codec_data);
+	int (*init) (struct audio_preset *preset, uint16_t mtu,
+				void **codec_data);
 	int (*cleanup) (void *codec_data);
 	int (*get_config) (void *codec_data,
 					struct audio_input_config *config);
@@ -251,9 +268,14 @@ static void sbc_init_encoder(struct sbc_data *sbc_data)
 	}
 }
 
-static int sbc_codec_init(struct audio_preset *preset, void **codec_data)
+static int sbc_codec_init(struct audio_preset *preset, uint16_t mtu,
+				void **codec_data)
 {
 	struct sbc_data *sbc_data;
+	size_t hdr_len = sizeof(struct media_packet);
+	size_t in_frame_len;
+	size_t out_frame_len;
+	size_t num_frames;
 
 	DBG("");
 
@@ -268,6 +290,18 @@ static int sbc_codec_init(struct audio_preset *preset, void **codec_data)
 
 	sbc_init_encoder(sbc_data);
 
+	in_frame_len = sbc_get_codesize(&sbc_data->enc);
+	out_frame_len = sbc_get_frame_length(&sbc_data->enc);
+	num_frames = (mtu - hdr_len) / out_frame_len;
+
+	sbc_data->in_frame_len = in_frame_len;
+	sbc_data->in_buf_size = num_frames * in_frame_len;
+
+	sbc_data->out_buf_size = hdr_len + num_frames * out_frame_len;
+	sbc_data->out_buf = calloc(1, sbc_data->out_buf_size);
+
+	sbc_data->frame_duration = sbc_get_frame_duration(&sbc_data->enc);
+
 	*codec_data = sbc_data;
 
 	return AUDIO_STATUS_SUCCESS;
@@ -280,6 +314,7 @@ static int sbc_cleanup(void *codec_data)
 	DBG("");
 
 	sbc_finish(&sbc_data->enc);
+	free(sbc_data->out_buf);
 	free(codec_data);
 
 	return AUDIO_STATUS_SUCCESS;
@@ -511,7 +546,7 @@ static int ipc_close_cmd(uint8_t endpoint_id)
 	return result;
 }
 
-static int ipc_open_stream_cmd(uint8_t endpoint_id,
+static int ipc_open_stream_cmd(uint8_t endpoint_id, uint16_t *mtu,
 					struct audio_preset **caps)
 {
 	char buf[BLUEZ_AUDIO_MTU];
@@ -534,6 +569,7 @@ static int ipc_open_stream_cmd(uint8_t endpoint_id,
 	if (result == AUDIO_STATUS_SUCCESS) {
 		size_t buf_len = sizeof(struct audio_preset) +
 					rsp->preset[0].len;
+		*mtu = rsp->mtu;
 		*caps = malloc(buf_len);
 		memcpy(*caps, &rsp->preset, buf_len);
 	} else {
@@ -919,6 +955,7 @@ static int audio_open_output_stream(struct audio_hw_device *dev,
 	struct a2dp_stream_out *out;
 	struct audio_preset *preset;
 	const struct audio_codec *codec;
+	uint16_t mtu;
 
 	out = calloc(1, sizeof(struct a2dp_stream_out));
 	if (!out)
@@ -946,7 +983,8 @@ static int audio_open_output_stream(struct audio_hw_device *dev,
 	/* TODO: for now we always use endpoint 0 */
 	out->ep = &audio_endpoints[0];
 
-	if (ipc_open_stream_cmd(out->ep->id, &preset) != AUDIO_STATUS_SUCCESS)
+	if (ipc_open_stream_cmd(out->ep->id, &mtu, &preset) !=
+			AUDIO_STATUS_SUCCESS)
 		goto fail;
 
 	if (!preset)
@@ -954,7 +992,7 @@ static int audio_open_output_stream(struct audio_hw_device *dev,
 
 	codec = out->ep->codec;
 
-	codec->init(preset, &out->ep->codec_data);
+	codec->init(preset, mtu, &out->ep->codec_data);
 	codec->get_config(out->ep->codec_data, &out->cfg);
 
 	DBG("rate=%d channels=%d format=%d", out->cfg.rate,
diff --git a/android/rtp.h b/android/rtp.h
new file mode 100644
index 0000000..45fddcf
--- /dev/null
+++ b/android/rtp.h
@@ -0,0 +1,76 @@
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2004-2010  Marcel Holtmann <marcel@holtmann.org>
+ *
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+
+struct rtp_header {
+	unsigned cc:4;
+	unsigned x:1;
+	unsigned p:1;
+	unsigned v:2;
+
+	unsigned pt:7;
+	unsigned m:1;
+
+	uint16_t sequence_number;
+	uint32_t timestamp;
+	uint32_t ssrc;
+	uint32_t csrc[0];
+} __attribute__ ((packed));
+
+struct rtp_payload {
+	unsigned frame_count:4;
+	unsigned rfa0:1;
+	unsigned is_last_fragment:1;
+	unsigned is_first_fragment:1;
+	unsigned is_fragmented:1;
+} __attribute__ ((packed));
+
+#elif __BYTE_ORDER == __BIG_ENDIAN
+
+struct rtp_header {
+	unsigned v:2;
+	unsigned p:1;
+	unsigned x:1;
+	unsigned cc:4;
+
+	unsigned m:1;
+	unsigned pt:7;
+
+	uint16_t sequence_number;
+	uint32_t timestamp;
+	uint32_t ssrc;
+	uint32_t csrc[0];
+} __attribute__ ((packed));
+
+struct rtp_payload {
+	unsigned is_fragmented:1;
+	unsigned is_first_fragment:1;
+	unsigned is_last_fragment:1;
+	unsigned rfa0:1;
+	unsigned frame_count:4;
+} __attribute__ ((packed));
+
+#else
+#error "Unknown byte order"
+#endif
-- 
1.8.5.2


^ permalink raw reply related

* [PATCH 4/9] android/hal-audio: Initialize SBC encoder
From: Andrzej Kaczmarek @ 2014-01-17 15:40 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Andrzej Kaczmarek
In-Reply-To: <1389973213-30251-1-git-send-email-andrzej.kaczmarek@tieto.com>

---
 android/hal-audio.c | 72 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 72 insertions(+)

diff --git a/android/hal-audio.c b/android/hal-audio.c
index f53dba0..e5c646c 100644
--- a/android/hal-audio.c
+++ b/android/hal-audio.c
@@ -32,6 +32,7 @@
 #include "hal-log.h"
 #include "hal-msg.h"
 #include "../profiles/audio/a2dp-codecs.h"
+#include <sbc/sbc.h>
 
 static const uint8_t a2dp_src_uuid[] = {
 		0x00, 0x00, 0x11, 0x0a, 0x00, 0x00, 0x10, 0x00,
@@ -53,6 +54,8 @@ struct audio_input_config {
 
 struct sbc_data {
 	a2dp_sbc_t sbc;
+
+	sbc_t enc;
 };
 
 static int sbc_get_presets(struct audio_preset *preset, size_t *len);
@@ -184,6 +187,70 @@ static int sbc_get_presets(struct audio_preset *preset, size_t *len)
 	return i;
 }
 
+static void sbc_init_encoder(struct sbc_data *sbc_data)
+{
+	a2dp_sbc_t *in = &sbc_data->sbc;
+	sbc_t *out = &sbc_data->enc;
+
+	DBG("");
+
+	sbc_init(out, 0L);
+
+	switch (in->frequency) {
+	case SBC_SAMPLING_FREQ_16000:
+		out->frequency = SBC_FREQ_16000;
+		break;
+	case SBC_SAMPLING_FREQ_32000:
+		out->frequency = SBC_FREQ_32000;
+		break;
+	case SBC_SAMPLING_FREQ_44100:
+		out->frequency = SBC_FREQ_44100;
+		break;
+	case SBC_SAMPLING_FREQ_48000:
+		out->frequency = SBC_FREQ_48000;
+		break;
+	}
+
+	out->subbands = in->subbands == SBC_SUBBANDS_4 ? SBC_SB_4 : SBC_SB_8;
+
+	switch (in->channel_mode) {
+	case SBC_CHANNEL_MODE_MONO:
+		out->mode = SBC_MODE_MONO;
+		break;
+	case SBC_CHANNEL_MODE_DUAL_CHANNEL:
+		out->mode = SBC_MODE_DUAL_CHANNEL;
+		break;
+	case SBC_CHANNEL_MODE_JOINT_STEREO:
+		out->mode = SBC_MODE_JOINT_STEREO;
+		break;
+	case SBC_CHANNEL_MODE_STEREO:
+		out->mode = SBC_MODE_STEREO;
+		break;
+	}
+
+	out->endian = SBC_LE;
+
+	out->bitpool = in->max_bitpool;
+
+	out->allocation = in->allocation_method == SBC_ALLOCATION_SNR ?
+				SBC_AM_SNR : SBC_AM_LOUDNESS;
+
+	switch (in->block_length) {
+	case SBC_BLOCK_LENGTH_4:
+		out->blocks = SBC_BLK_4;
+		break;
+	case SBC_BLOCK_LENGTH_8:
+		out->blocks = SBC_BLK_8;
+		break;
+	case SBC_BLOCK_LENGTH_12:
+		out->blocks = SBC_BLK_12;
+		break;
+	case SBC_BLOCK_LENGTH_16:
+		out->blocks = SBC_BLK_16;
+		break;
+	}
+}
+
 static int sbc_codec_init(struct audio_preset *preset, void **codec_data)
 {
 	struct sbc_data *sbc_data;
@@ -199,6 +266,8 @@ static int sbc_codec_init(struct audio_preset *preset, void **codec_data)
 
 	memcpy(&sbc_data->sbc, preset->data, preset->len);
 
+	sbc_init_encoder(sbc_data);
+
 	*codec_data = sbc_data;
 
 	return AUDIO_STATUS_SUCCESS;
@@ -206,8 +275,11 @@ static int sbc_codec_init(struct audio_preset *preset, void **codec_data)
 
 static int sbc_cleanup(void *codec_data)
 {
+	struct sbc_data *sbc_data = (struct sbc_data *) codec_data;
+
 	DBG("");
 
+	sbc_finish(&sbc_data->enc);
 	free(codec_data);
 
 	return AUDIO_STATUS_SUCCESS;
-- 
1.8.5.2


^ permalink raw reply related

* [PATCH 3/9] android/hal-audio: Rename sbc_init to avoid collision with libsbc
From: Andrzej Kaczmarek @ 2014-01-17 15:40 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Andrzej Kaczmarek
In-Reply-To: <1389973213-30251-1-git-send-email-andrzej.kaczmarek@tieto.com>

---
 android/hal-audio.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/android/hal-audio.c b/android/hal-audio.c
index 2f6f8c2..f53dba0 100644
--- a/android/hal-audio.c
+++ b/android/hal-audio.c
@@ -56,7 +56,7 @@ struct sbc_data {
 };
 
 static int sbc_get_presets(struct audio_preset *preset, size_t *len);
-static int sbc_init(struct audio_preset *preset, void **codec_data);
+static int sbc_codec_init(struct audio_preset *preset, void **codec_data);
 static int sbc_cleanup(void *codec_data);
 static int sbc_get_config(void *codec_data,
 					struct audio_input_config *config);
@@ -80,7 +80,7 @@ static const struct audio_codec audio_codecs[] = {
 
 		.get_presets = sbc_get_presets,
 
-		.init = sbc_init,
+		.init = sbc_codec_init,
 		.cleanup = sbc_cleanup,
 		.get_config = sbc_get_config,
 	}
@@ -184,7 +184,7 @@ static int sbc_get_presets(struct audio_preset *preset, size_t *len)
 	return i;
 }
 
-static int sbc_init(struct audio_preset *preset, void **codec_data)
+static int sbc_codec_init(struct audio_preset *preset, void **codec_data)
 {
 	struct sbc_data *sbc_data;
 
-- 
1.8.5.2


^ permalink raw reply related


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox