Re: [PATCH BlueZ 3/6] audio/A2DP: Add implemention of audio Open Stream command

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi Luiz,

On 11 January 2014 11:13, Luiz Augusto von Dentz <luiz.dentz@xxxxxxxxx> wrote:
> From: Luiz Augusto von Dentz <luiz.von.dentz@xxxxxxxxx>
>
> ---
>  android/a2dp.c | 199 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
>  1 file changed, 197 insertions(+), 2 deletions(-)
>
> diff --git a/android/a2dp.c b/android/a2dp.c
> index 8649cf3..479cb71 100644
> --- a/android/a2dp.c
> +++ b/android/a2dp.c
> @@ -37,6 +37,7 @@
>  #include "lib/bluetooth.h"
>  #include "lib/sdp.h"
>  #include "lib/sdp_lib.h"
> +#include "profiles/audio/a2dp-codecs.h"
>  #include "log.h"
>  #include "a2dp.h"
>  #include "hal-msg.h"
> @@ -53,6 +54,7 @@
>  static GIOChannel *server = NULL;
>  static GSList *devices = NULL;
>  static GSList *endpoints = NULL;
> +static GSList *setups = NULL;
>  static bdaddr_t adapter_addr;
>  static uint32_t record_id = 0;
>
> @@ -67,6 +69,7 @@ struct a2dp_endpoint {
>         struct avdtp_local_sep *sep;
>         struct a2dp_preset *caps;
>         GSList *presets;
> +       struct a2dp_config *config;
>  };
>
>  struct a2dp_device {
> @@ -76,6 +79,13 @@ struct a2dp_device {
>         struct avdtp    *session;
>  };
>
> +struct a2dp_setup {
> +       struct a2dp_device *dev;
> +       struct a2dp_endpoint *endpoint;
> +       struct a2dp_preset *preset;
> +       struct avdtp_stream *stream;
> +};
> +
>  static int device_cmp(gconstpointer s, gconstpointer user_data)
>  {
>         const struct a2dp_device *dev = s;
> @@ -422,8 +432,160 @@ static gboolean sep_getcap_ind(struct avdtp *session,
>         return TRUE;
>  }
>
> +static int sbc_check_config(struct a2dp_endpoint *endpoint,
> +                                               struct a2dp_preset *conf)
> +{
> +       a2dp_sbc_t *caps, *config;
> +
> +       if (conf->len != sizeof(a2dp_sbc_t)) {
> +               error("SBC: Invalid configuration size (%u)", conf->len);
> +               return -EINVAL;
> +       }
> +
> +       caps = endpoint->caps->data;
> +       config = conf->data;
> +
> +       if (!(caps->frequency & config->frequency)) {
> +               error("SBC: Unsupported frequency (%u) by endpoint",
> +                                                       config->frequency);
> +               return -EINVAL;
> +       }
> +
> +       if (!(caps->channel_mode & config->channel_mode)) {
> +               error("SBC: Unsupported channel mode (%u) by endpoint",
> +                                                       config->channel_mode);
> +               return -EINVAL;
> +       }
> +
> +       if (!(caps->block_length & config->block_length)) {
> +               error("SBC: Unsupported block length (%u) by endpoint",
> +                                                       config->block_length);
> +               return -EINVAL;
> +       }
> +
> +       if (!(caps->allocation_method & config->allocation_method)) {
> +               error("SBC: Unsupported allocation method (%u) by endpoint",
> +                                                       config->block_length);
> +               return -EINVAL;
> +       }
> +
> +       return 0;
> +}
> +
> +static int check_config(struct a2dp_endpoint *endpoint,
> +                                               struct a2dp_preset *config)
> +{
> +       GSList *l;
> +
> +       for (l = endpoint->presets; l; l = g_slist_next(l)) {
> +               struct a2dp_preset *preset = l->data;
> +
> +               if (preset->len != config->len)
> +                       continue;
> +
> +               if (memcmp(preset->data, config->data, preset->len) == 0)
> +                       return 0;
> +       }
> +
> +       /* Codec specific */
> +       switch (endpoint->codec) {
> +       case A2DP_CODEC_SBC:
> +               return sbc_check_config(endpoint, config);
> +       default:
> +               return -EINVAL;
> +       }
> +}
> +
> +static struct a2dp_device *find_device_by_session(struct avdtp *session)
> +{
> +       GSList *l;
> +
> +       for (l = devices; l; l = g_slist_next(l)) {
> +               struct a2dp_device *dev = l->data;
> +
> +               if (dev->session == session)
> +                       return dev;
> +       }
> +
> +       return NULL;
> +}
> +
> +static void setup_free(void *data)
> +{
> +       struct a2dp_setup *setup = data;
> +
> +       preset_free(setup->preset);
> +       g_free(setup);
> +}
> +
> +static void setup_add(struct a2dp_device *dev, struct a2dp_endpoint *endpoint,
> +                       struct a2dp_preset *preset, struct avdtp_stream *stream)
> +{
> +       struct a2dp_setup *setup;
> +
> +       setup = g_new0(struct a2dp_setup, 1);
> +       setup->dev = dev;
> +       setup->endpoint = endpoint;
> +       setup->preset = preset;
> +       setup->stream = stream;
> +       setups = g_slist_append(setups, setup);
> +}
> +
> +static gboolean sep_setconf_ind(struct avdtp *session,
> +                                               struct avdtp_local_sep *sep,
> +                                               struct avdtp_stream *stream,
> +                                               GSList *caps,
> +                                               avdtp_set_configuration_cb cb,
> +                                               void *user_data)
> +{
> +       struct a2dp_endpoint *endpoint = user_data;
> +       struct a2dp_device *dev;
> +       struct a2dp_preset *preset = NULL;
> +
> +       DBG("");
> +
> +       dev = find_device_by_session(session);
> +       if (!dev) {
> +               error("Unable to find device for session %p", session);
> +               return FALSE;
> +       }
> +
> +       for (; caps != NULL; caps = g_slist_next(caps)) {
> +               struct avdtp_service_capability *cap = caps->data;
> +               struct avdtp_media_codec_capability *codec;
> +
> +               if (cap->category == AVDTP_DELAY_REPORTING)
> +                       return FALSE;
> +
> +               if (cap->category != AVDTP_MEDIA_CODEC)
> +                       continue;
> +
> +               codec = (struct avdtp_media_codec_capability *) cap->data;
> +
> +               if (codec->media_codec_type != endpoint->codec)
> +                       return FALSE;
> +
> +               preset = g_new0(struct a2dp_preset, 1);
> +               preset->len = cap->length - sizeof(*codec);
> +               preset->data = g_memdup(codec->data, preset->len);
> +
> +               if (check_config(endpoint, preset) < 0) {
> +                       preset_free(preset);
> +                       return FALSE;
> +               }
> +       }
> +
> +       if (!preset)
> +               return FALSE;
> +
> +       setup_add(dev, endpoint, preset, stream);
> +
> +       return TRUE;

I guess there should be call to avdtp_set_configuration_cb somewhere
in this function?


BR,
Andrzej
--
To unsubscribe from this list: send the line "unsubscribe linux-bluetooth" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[Index of Archives]     [Bluez Devel]     [Linux Wireless Networking]     [Linux Wireless Personal Area Networking]     [Linux ATH6KL]     [Linux USB Devel]     [Linux Media Drivers]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Big List of Linux Books]

  Powered by Linux