diff options
Diffstat (limited to 'audio')
-rw-r--r-- | audio/a2dp.c | 144 | ||||
-rw-r--r-- | audio/a2dp.h | 13 | ||||
-rw-r--r-- | audio/avdtp.c | 2 | ||||
-rw-r--r-- | audio/avdtp.h | 1 | ||||
-rw-r--r-- | audio/gsta2dpsendersink.c | 37 | ||||
-rw-r--r-- | audio/ipc.h | 20 | ||||
-rw-r--r-- | audio/pcm_bluetooth.c | 39 | ||||
-rw-r--r-- | audio/unix.c | 62 |
8 files changed, 247 insertions, 71 deletions
diff --git a/audio/a2dp.c b/audio/a2dp.c index 1c59374f..b1409f5c 100644 --- a/audio/a2dp.c +++ b/audio/a2dp.c @@ -58,6 +58,7 @@ struct a2dp_sep { uint8_t type; + uint8_t codec; struct avdtp_local_sep *sep; struct avdtp *session; struct avdtp_stream *stream; @@ -280,7 +281,7 @@ static void stream_state_changed(struct avdtp_stream *stream, } -static gboolean setconf_ind(struct avdtp *session, +static gboolean sbc_setconf_ind(struct avdtp *session, struct avdtp_local_sep *sep, struct avdtp_stream *stream, GSList *caps, uint8_t *err, @@ -331,7 +332,7 @@ static gboolean setconf_ind(struct avdtp *session, return TRUE; } -static gboolean getcap_ind(struct avdtp *session, struct avdtp_local_sep *sep, +static gboolean sbc_getcap_ind(struct avdtp *session, struct avdtp_local_sep *sep, GSList **caps, uint8_t *err, void *user_data) { struct a2dp_sep *a2dp_sep = user_data; @@ -386,6 +387,84 @@ static gboolean getcap_ind(struct avdtp *session, struct avdtp_local_sep *sep, return TRUE; } +static gboolean mpeg_setconf_ind(struct avdtp *session, + struct avdtp_local_sep *sep, + struct avdtp_stream *stream, + GSList *caps, uint8_t *err, + uint8_t *category, void *user_data) +{ + struct a2dp_sep *a2dp_sep = user_data; + struct device *dev; + + if (a2dp_sep->type == AVDTP_SEP_TYPE_SINK) + debug("SBC Sink: Set_Configuration_Ind"); + else + debug("SBC Source: Set_Configuration_Ind"); + + dev = a2dp_get_dev(session); + if (!dev) { + *err = AVDTP_UNSUPPORTED_CONFIGURATION; + *category = 0x00; + return FALSE; + } + + avdtp_stream_add_cb(session, stream, stream_state_changed, a2dp_sep); + a2dp_sep->stream = stream; + + if (a2dp_sep->type == AVDTP_SEP_TYPE_SOURCE) + sink_new_stream(dev, session, stream); + + return TRUE; +} + +static gboolean mpeg_getcap_ind(struct avdtp *session, struct avdtp_local_sep *sep, + GSList **caps, uint8_t *err, void *user_data) +{ + struct a2dp_sep *a2dp_sep = user_data; + struct avdtp_service_capability *media_transport, *media_codec; + struct mpeg_codec_cap mpeg_cap; + + if (a2dp_sep->type == AVDTP_SEP_TYPE_SINK) + debug("SBC Sink: Get_Capability_Ind"); + else + debug("SBC Source: Get_Capability_Ind"); + + *caps = NULL; + + media_transport = avdtp_service_cap_new(AVDTP_MEDIA_TRANSPORT, + NULL, 0); + + *caps = g_slist_append(*caps, media_transport); + + memset(&mpeg_cap, 0, sizeof(struct mpeg_codec_cap)); + + mpeg_cap.cap.media_type = AVDTP_MEDIA_TYPE_AUDIO; + mpeg_cap.cap.media_codec_type = A2DP_CODEC_MPEG12; + + mpeg_cap.frequency = ( MPEG_SAMPLING_FREQ_48000 | + MPEG_SAMPLING_FREQ_44100 | + MPEG_SAMPLING_FREQ_32000 | + MPEG_SAMPLING_FREQ_24000 | + MPEG_SAMPLING_FREQ_22050 | + MPEG_SAMPLING_FREQ_16000 ); + + mpeg_cap.channel_mode = ( MPEG_CHANNEL_MODE_JOINT_STEREO | + MPEG_CHANNEL_MODE_STEREO | + MPEG_CHANNEL_MODE_DUAL_CHANNEL | + MPEG_CHANNEL_MODE_MONO ); + + mpeg_cap.layer = ( MPEG_LAYER_MP3 | MPEG_LAYER_MP2 | MPEG_LAYER_MP1 ); + + mpeg_cap.bitrate = 0xFFFF; + + media_codec = avdtp_service_cap_new(AVDTP_MEDIA_CODEC, &mpeg_cap, + sizeof(mpeg_cap)); + + *caps = g_slist_append(*caps, media_codec); + + return TRUE; +} + static void setconf_cfm(struct avdtp *session, struct avdtp_local_sep *sep, struct avdtp_stream *stream, struct avdtp_error *err, void *user_data) @@ -797,9 +876,21 @@ static struct avdtp_sep_cfm cfm = { .reconfigure = reconf_cfm }; -static struct avdtp_sep_ind ind = { - .get_capability = getcap_ind, - .set_configuration = setconf_ind, +static struct avdtp_sep_ind sbc_ind = { + .get_capability = sbc_getcap_ind, + .set_configuration = sbc_setconf_ind, + .get_configuration = getconf_ind, + .open = open_ind, + .start = start_ind, + .suspend = suspend_ind, + .close = close_ind, + .abort = abort_ind, + .reconfigure = reconf_ind +}; + +static struct avdtp_sep_ind mpeg_ind = { + .get_capability = mpeg_getcap_ind, + .set_configuration = mpeg_setconf_ind, .get_configuration = getconf_ind, .open = open_ind, .start = start_ind, @@ -880,23 +971,27 @@ static int a2dp_sink_record(sdp_buf_t *buf) return 0; } -static struct a2dp_sep *a2dp_add_sep(DBusConnection *conn, uint8_t type) +static struct a2dp_sep *a2dp_add_sep(DBusConnection *conn, uint8_t type, + uint8_t codec) { struct a2dp_sep *sep; GSList **l; int (*create_record)(sdp_buf_t *buf); uint32_t *record_id; sdp_buf_t buf; + struct avdtp_sep_ind *ind; sep = g_new0(struct a2dp_sep, 1); - sep->sep = avdtp_register_sep(type, AVDTP_MEDIA_TYPE_AUDIO, - &ind, &cfm, sep); + ind = (codec == A2DP_CODEC_MPEG12) ? &mpeg_ind : &sbc_ind; + sep->sep = avdtp_register_sep(type, AVDTP_MEDIA_TYPE_AUDIO, codec, + ind, &cfm, sep); if (sep->sep == NULL) { g_free(sep); return NULL; } + sep->codec = codec; sep->type = type; if (type == AVDTP_SEP_TYPE_SOURCE) { @@ -945,11 +1040,15 @@ int a2dp_init(DBusConnection *conn, int sources, int sinks) avdtp_init(); - for (i = 0; i < sources; i++) - a2dp_add_sep(conn, AVDTP_SEP_TYPE_SOURCE); + for (i = 0; i < sources; i++) { + a2dp_add_sep(conn, AVDTP_SEP_TYPE_SOURCE, A2DP_CODEC_SBC); + a2dp_add_sep(conn, AVDTP_SEP_TYPE_SOURCE, A2DP_CODEC_MPEG12); + } - for (i = 0; i < sinks; i++) - a2dp_add_sep(conn, AVDTP_SEP_TYPE_SINK); + for (i = 0; i < sinks; i++) { + a2dp_add_sep(conn, AVDTP_SEP_TYPE_SINK, A2DP_CODEC_SBC); + a2dp_add_sep(conn, AVDTP_SEP_TYPE_SINK, A2DP_CODEC_MPEG12); + } return 0; } @@ -1025,14 +1124,32 @@ unsigned int a2dp_source_config(struct avdtp *session, a2dp_config_cb_t cb, struct a2dp_sep *sep = NULL; struct avdtp_local_sep *lsep; struct avdtp_remote_sep *rsep; + struct avdtp_service_capability *cap; + struct avdtp_media_codec_capability *codec_cap = NULL; int posix_err; + for (l = caps; l != NULL; l = l->next) { + cap = l->data; + + if (cap->category != AVDTP_MEDIA_CODEC) + continue; + + codec_cap = (void *) cap->data; + break; + } + + if (!codec_cap) + return 0; + for (l = sources; l != NULL; l = l->next) { struct a2dp_sep *tmp = l->data; if (tmp->locked) continue; + if (tmp->codec != codec_cap->media_codec_type) + continue; + if (!tmp->stream || avdtp_has_stream(session, tmp->stream)) { sep = tmp; break; @@ -1067,7 +1184,8 @@ unsigned int a2dp_source_config(struct avdtp *session, a2dp_config_cb_t cb, switch (avdtp_sep_get_state(sep->sep)) { case AVDTP_STATE_IDLE: if (avdtp_get_seps(session, AVDTP_SEP_TYPE_SINK, - AVDTP_MEDIA_TYPE_AUDIO, A2DP_CODEC_SBC, + codec_cap->media_type, + codec_cap->media_codec_type, &lsep, &rsep) < 0) { error("No matching ACP and INT SEPs found"); goto failed; diff --git a/audio/a2dp.h b/audio/a2dp.h index cfd1c47d..84301bad 100644 --- a/audio/a2dp.h +++ b/audio/a2dp.h @@ -48,6 +48,11 @@ #define SBC_ALLOCATION_SNR (1 << 1) #define SBC_ALLOCATION_LOUDNESS 1 +#define MPEG_CHANNEL_MODE_MONO (1 << 3) +#define MPEG_CHANNEL_MODE_DUAL_CHANNEL (1 << 2) +#define MPEG_CHANNEL_MODE_STEREO (1 << 1) +#define MPEG_CHANNEL_MODE_JOINT_STEREO 1 + #define MPEG_LAYER_MP1 (1 << 2) #define MPEG_LAYER_MP2 (1 << 1) #define MPEG_LAYER_MP3 1 @@ -83,9 +88,7 @@ struct mpeg_codec_cap { uint8_t frequency:6; uint8_t mpf:1; uint8_t rfa:1; - uint8_t bitrate0:7; - uint8_t vbr:1; - uint8_t bitrate1; + uint16_t bitrate; } __attribute__ ((packed)); #elif __BYTE_ORDER == __BIG_ENDIAN @@ -109,9 +112,7 @@ struct mpeg_codec_cap { uint8_t rfa:1; uint8_t mpf:1; uint8_t frequency:6; - uint8_t vbr:1; - uint8_t bitrate0:7; - uint8_t bitrate1; + uint16_t bitrate; } __attribute__ ((packed)); #else diff --git a/audio/avdtp.c b/audio/avdtp.c index d5433452..97868a07 100644 --- a/audio/avdtp.c +++ b/audio/avdtp.c @@ -2696,6 +2696,7 @@ int avdtp_abort(struct avdtp *session, struct avdtp_stream *stream) } struct avdtp_local_sep *avdtp_register_sep(uint8_t type, uint8_t media_type, + uint8_t codec_type, struct avdtp_sep_ind *ind, struct avdtp_sep_cfm *cfm, void *user_data) @@ -2711,6 +2712,7 @@ struct avdtp_local_sep *avdtp_register_sep(uint8_t type, uint8_t media_type, sep->info.seid = free_seid++; sep->info.type = type; sep->info.media_type = media_type; + sep->codec = codec_type; sep->ind = ind; sep->cfm = cfm; sep->user_data = user_data; diff --git a/audio/avdtp.h b/audio/avdtp.h index 241fa713..01ca50c6 100644 --- a/audio/avdtp.h +++ b/audio/avdtp.h @@ -242,6 +242,7 @@ int avdtp_close(struct avdtp *session, struct avdtp_stream *stream); int avdtp_abort(struct avdtp *session, struct avdtp_stream *stream); struct avdtp_local_sep *avdtp_register_sep(uint8_t type, uint8_t media_type, + uint8_t codec_type, struct avdtp_sep_ind *ind, struct avdtp_sep_cfm *cfm, void *user_data); diff --git a/audio/gsta2dpsendersink.c b/audio/gsta2dpsendersink.c index cfb67b87..1f54f29c 100644 --- a/audio/gsta2dpsendersink.c +++ b/audio/gsta2dpsendersink.c @@ -236,13 +236,13 @@ static gboolean gst_a2dp_sender_sink_init_pkt_conf(GstA2dpSenderSink *sink, value = gst_structure_get_value(structure, "rate"); rate = g_value_get_int(value); if (rate == 44100) - cfg->frequency = BT_A2DP_SAMPLING_FREQ_44100; + cfg->frequency = BT_SBC_SAMPLING_FREQ_44100; else if (rate == 48000) - cfg->frequency = BT_A2DP_SAMPLING_FREQ_48000; + cfg->frequency = BT_SBC_SAMPLING_FREQ_48000; else if (rate == 32000) - cfg->frequency = BT_A2DP_SAMPLING_FREQ_32000; + cfg->frequency = BT_SBC_SAMPLING_FREQ_32000; else if (rate == 16000) - cfg->frequency = BT_A2DP_SAMPLING_FREQ_16000; + cfg->frequency = BT_SBC_SAMPLING_FREQ_16000; else { GST_ERROR_OBJECT(sink, "Invalid rate while setting caps"); return FALSE; @@ -396,17 +396,14 @@ static gboolean server_callback(GIOChannel *chan, return TRUE; } -static gboolean gst_a2dp_sender_sink_update_caps(GstA2dpSenderSink *self) +static GstStructure *gst_a2dp_sender_sink_parse_sbc_caps( + GstA2dpSenderSink *self, sbc_capabilities_t *sbc) { - sbc_capabilities_t *sbc = &self->data->caps.sbc_capabilities; GstStructure *structure; GValue *value; GValue *list; - gchar *tmp; gboolean mono, stereo; - GST_LOG_OBJECT(self, "updating device caps"); - structure = gst_structure_empty_new("audio/x-sbc"); value = g_value_init(g_new0(GValue, 1), G_TYPE_STRING); @@ -518,19 +515,19 @@ static gboolean gst_a2dp_sender_sink_update_caps(GstA2dpSenderSink *self) /* rate */ g_value_init(value, G_TYPE_INT); list = g_value_init(g_new0(GValue, 1), GST_TYPE_LIST); - if (sbc->frequency & BT_A2DP_SAMPLING_FREQ_48000) { + if (sbc->frequency & BT_SBC_SAMPLING_FREQ_48000) { g_value_set_int(value, 48000); gst_value_list_prepend_value(list, value); } - if (sbc->frequency & BT_A2DP_SAMPLING_FREQ_44100) { + if (sbc->frequency & BT_SBC_SAMPLING_FREQ_44100) { g_value_set_int(value, 44100); gst_value_list_prepend_value(list, value); } - if (sbc->frequency & BT_A2DP_SAMPLING_FREQ_32000) { + if (sbc->frequency & BT_SBC_SAMPLING_FREQ_32000) { g_value_set_int(value, 32000); gst_value_list_prepend_value(list, value); } - if (sbc->frequency & BT_A2DP_SAMPLING_FREQ_16000) { + if (sbc->frequency & BT_SBC_SAMPLING_FREQ_16000) { g_value_set_int(value, 16000); gst_value_list_prepend_value(list, value); } @@ -584,6 +581,20 @@ static gboolean gst_a2dp_sender_sink_update_caps(GstA2dpSenderSink *self) gst_structure_set_value(structure, "channels", value); g_free(value); + return structure; +} + +static gboolean gst_a2dp_sender_sink_update_caps(GstA2dpSenderSink *self) +{ + sbc_capabilities_t *sbc = &self->data->caps.sbc_capabilities; + mpeg_capabilities_t *mpeg = &self->data->caps.mpeg_capabilities; + GstStructure *structure; + gchar *tmp; + + GST_LOG_OBJECT(self, "updating device caps"); + + structure = gst_a2dp_sender_sink_parse_sbc_caps(self, sbc); + if (self->dev_caps != NULL) gst_caps_unref(self->dev_caps); self->dev_caps = gst_caps_new_full(structure, NULL); diff --git a/audio/ipc.h b/audio/ipc.h index 64ed65a7..3768dcfb 100644 --- a/audio/ipc.h +++ b/audio/ipc.h @@ -129,10 +129,10 @@ struct bt_getcapabilities_req { * SBC Codec parameters as per A2DP profile 1.0 ยง 4.3 */ -#define BT_A2DP_SAMPLING_FREQ_16000 (1 << 3) -#define BT_A2DP_SAMPLING_FREQ_32000 (1 << 2) -#define BT_A2DP_SAMPLING_FREQ_44100 (1 << 1) -#define BT_A2DP_SAMPLING_FREQ_48000 1 +#define BT_SBC_SAMPLING_FREQ_16000 (1 << 3) +#define BT_SBC_SAMPLING_FREQ_32000 (1 << 2) +#define BT_SBC_SAMPLING_FREQ_44100 (1 << 1) +#define BT_SBC_SAMPLING_FREQ_48000 1 #define BT_A2DP_CHANNEL_MODE_MONO (1 << 3) #define BT_A2DP_CHANNEL_MODE_DUAL_CHANNEL (1 << 2) @@ -152,6 +152,17 @@ struct bt_getcapabilities_req { #define BT_A2DP_ALLOCATION_LOUDNESS 1 #define BT_A2DP_ALLOCATION_AUTO 0 +#define BT_MPEG_SAMPLING_FREQ_16000 (1 << 5) +#define BT_MPEG_SAMPLING_FREQ_22050 (1 << 4) +#define BT_MPEG_SAMPLING_FREQ_24000 (1 << 3) +#define BT_MPEG_SAMPLING_FREQ_32000 (1 << 2) +#define BT_MPEG_SAMPLING_FREQ_44100 (1 << 1) +#define BT_MPEG_SAMPLING_FREQ_48000 1 + +#define BT_MPEG_LAYER_1 (1 << 2) +#define BT_MPEG_LAYER_2 (1 << 1) +#define BT_MPEG_LAYER_3 1 + typedef struct { uint8_t channel_mode; uint8_t frequency; @@ -168,7 +179,6 @@ typedef struct { uint8_t layer; uint8_t frequency; uint8_t mpf; - uint8_t vbr; uint16_t bitrate; } __attribute__ ((packed)) mpeg_capabilities_t; diff --git a/audio/pcm_bluetooth.c b/audio/pcm_bluetooth.c index e81bbc16..a04f18c0 100644 --- a/audio/pcm_bluetooth.c +++ b/audio/pcm_bluetooth.c @@ -468,10 +468,10 @@ static int bluetooth_hsp_hw_params(snd_pcm_ioplug_t *io, static uint8_t default_bitpool(uint8_t freq, uint8_t mode) { switch (freq) { - case BT_A2DP_SAMPLING_FREQ_16000: - case BT_A2DP_SAMPLING_FREQ_32000: + case BT_SBC_SAMPLING_FREQ_16000: + case BT_SBC_SAMPLING_FREQ_32000: return 53; - case BT_A2DP_SAMPLING_FREQ_44100: + case BT_SBC_SAMPLING_FREQ_44100: switch (mode) { case BT_A2DP_CHANNEL_MODE_MONO: case BT_A2DP_CHANNEL_MODE_DUAL_CHANNEL: @@ -483,7 +483,7 @@ static uint8_t default_bitpool(uint8_t freq, uint8_t mode) DBG("Invalid channel mode %u", mode); return 53; } - case BT_A2DP_SAMPLING_FREQ_48000: + case BT_SBC_SAMPLING_FREQ_48000: switch (mode) { case BT_A2DP_CHANNEL_MODE_MONO: case BT_A2DP_CHANNEL_MODE_DUAL_CHANNEL: @@ -508,16 +508,16 @@ static int select_sbc_params(sbc_capabilities_t *cap, unsigned int rate, switch (rate) { case 48000: - cap->frequency = BT_A2DP_SAMPLING_FREQ_48000; + cap->frequency = BT_SBC_SAMPLING_FREQ_48000; break; case 44100: - cap->frequency = BT_A2DP_SAMPLING_FREQ_44100; + cap->frequency = BT_SBC_SAMPLING_FREQ_44100; break; case 32000: - cap->frequency = BT_A2DP_SAMPLING_FREQ_32000; + cap->frequency = BT_SBC_SAMPLING_FREQ_32000; break; case 16000: - cap->frequency = BT_A2DP_SAMPLING_FREQ_16000; + cap->frequency = BT_SBC_SAMPLING_FREQ_16000; break; default: DBG("Rate %d not supported", rate); @@ -641,16 +641,16 @@ static int bluetooth_a2dp_hw_params(snd_pcm_ioplug_t *io, sbc_init(&a2dp->sbc, 0); a2dp->sbc_initialized = 1; - if (active_capabilities.frequency & BT_A2DP_SAMPLING_FREQ_16000) + if (active_capabilities.frequency & BT_SBC_SAMPLING_FREQ_16000) a2dp->sbc.rate = 16000; - if (active_capabilities.frequency & BT_A2DP_SAMPLING_FREQ_32000) + if (active_capabilities.frequency & BT_SBC_SAMPLING_FREQ_32000) a2dp->sbc.rate = 32000; - if (active_capabilities.frequency & BT_A2DP_SAMPLING_FREQ_44100) + if (active_capabilities.frequency & BT_SBC_SAMPLING_FREQ_44100) a2dp->sbc.rate = 44100; - if (active_capabilities.frequency & BT_A2DP_SAMPLING_FREQ_48000) + if (active_capabilities.frequency & BT_SBC_SAMPLING_FREQ_48000) a2dp->sbc.rate = 48000; if (active_capabilities.channel_mode & BT_A2DP_CHANNEL_MODE_MONO) @@ -659,7 +659,8 @@ static int bluetooth_a2dp_hw_params(snd_pcm_ioplug_t *io, a2dp->sbc.channels = 2; if (active_capabilities.channel_mode & - (BT_A2DP_CHANNEL_MODE_MONO || BT_A2DP_CHANNEL_MODE_JOINT_STEREO)) + (BT_A2DP_CHANNEL_MODE_MONO || + BT_A2DP_CHANNEL_MODE_JOINT_STEREO)) a2dp->sbc.joint = 1; else a2dp->sbc.joint = 0; @@ -1231,22 +1232,26 @@ static int bluetooth_a2dp_hw_constraint(snd_pcm_ioplug_t *io) /* supported rates */ rate_count = 0; - if (a2dp->sbc_capabilities.frequency & BT_A2DP_SAMPLING_FREQ_16000) { + if (a2dp->sbc_capabilities.frequency & + BT_SBC_SAMPLING_FREQ_16000) { rate_list[rate_count] = 16000; rate_count++; } - if (a2dp->sbc_capabilities.frequency & BT_A2DP_SAMPLING_FREQ_32000) { + if (a2dp->sbc_capabilities.frequency & + BT_SBC_SAMPLING_FREQ_32000) { rate_list[rate_count] = 32000; rate_count++; } - if (a2dp->sbc_capabilities.frequency & BT_A2DP_SAMPLING_FREQ_44100) { + if (a2dp->sbc_capabilities.frequency & + BT_SBC_SAMPLING_FREQ_44100) { rate_list[rate_count] = 44100; rate_count++; } - if (a2dp->sbc_capabilities.frequency & BT_A2DP_SAMPLING_FREQ_48000) { + if (a2dp->sbc_capabilities.frequency & + BT_SBC_SAMPLING_FREQ_48000) { rate_list[rate_count] = 48000; rate_count++; } diff --git a/audio/unix.c b/audio/unix.c index 2226579d..d71c420a 100644 --- a/audio/unix.c +++ b/audio/unix.c @@ -389,9 +389,7 @@ static void a2dp_discovery_complete(struct avdtp *session, GSList *seps, rsp->mpeg_capabilities.layer = mpeg_cap->layer; rsp->mpeg_capabilities.frequency = mpeg_cap->frequency; rsp->mpeg_capabilities.mpf = mpeg_cap->mpf; - rsp->mpeg_capabilities.vbr = mpeg_cap->vbr; - rsp->mpeg_capabilities.bitrate = mpeg_cap->bitrate1 & - mpeg_cap->bitrate0 << 8; + rsp->mpeg_capabilities.bitrate = mpeg_cap->bitrate; } unix_ipc_sendmsg(client, &rsp->rsp_h.msg_h); @@ -794,6 +792,7 @@ static void handle_setconfiguration_req(struct unix_client *client, { struct avdtp_service_capability *media_transport, *media_codec; struct sbc_codec_cap sbc_cap; + struct mpeg_codec_cap mpeg_cap; struct device *dev; bdaddr_t bdaddr; int err = 0; @@ -842,20 +841,49 @@ static void handle_setconfiguration_req(struct unix_client *client, client->caps = g_slist_append(client->caps, media_transport); - memset(&sbc_cap, 0, sizeof(sbc_cap)); - - sbc_cap.cap.media_type = AVDTP_MEDIA_TYPE_AUDIO; - sbc_cap.cap.media_codec_type = A2DP_CODEC_SBC; - sbc_cap.channel_mode = req->sbc_capabilities.channel_mode; - sbc_cap.frequency = req->sbc_capabilities.frequency; - sbc_cap.allocation_method = req->sbc_capabilities.allocation_method; - sbc_cap.subbands = req->sbc_capabilities.subbands; - sbc_cap.block_length = req->sbc_capabilities.block_length ; - sbc_cap.min_bitpool = req->sbc_capabilities.min_bitpool; - sbc_cap.max_bitpool = req->sbc_capabilities.max_bitpool; - - media_codec = avdtp_service_cap_new(AVDTP_MEDIA_CODEC, &sbc_cap, - sizeof(sbc_cap)); + if (req->mpeg_capabilities.frequency) { + memset(&mpeg_cap, 0, sizeof(mpeg_cap)); + + mpeg_cap.cap.media_type = AVDTP_MEDIA_TYPE_AUDIO; + mpeg_cap.cap.media_codec_type = A2DP_CODEC_MPEG12; + mpeg_cap.channel_mode = req->mpeg_capabilities.channel_mode; + mpeg_cap.crc = req->mpeg_capabilities.crc; + mpeg_cap.layer = req->mpeg_capabilities.layer; + mpeg_cap.frequency = req->mpeg_capabilities.frequency; + mpeg_cap.mpf = req->mpeg_capabilities.mpf; + mpeg_cap.bitrate = req->mpeg_capabilities.bitrate; + + media_codec = avdtp_service_cap_new(AVDTP_MEDIA_CODEC, &mpeg_cap, + sizeof(mpeg_cap)); + + info("config mpeg - frequency = %u channel_mode = %u " + "layer = %u crc = %u mpf = %u bitrate = %u", + mpeg_cap.frequency, mpeg_cap.channel_mode, + mpeg_cap.layer, mpeg_cap.crc, mpeg_cap.mpf, + mpeg_cap.bitrate); + } else { + memset(&sbc_cap, 0, sizeof(sbc_cap)); + + sbc_cap.cap.media_type = AVDTP_MEDIA_TYPE_AUDIO; + sbc_cap.cap.media_codec_type = A2DP_CODEC_SBC; + sbc_cap.channel_mode = req->sbc_capabilities.channel_mode; + sbc_cap.frequency = req->sbc_capabilities.frequency; + sbc_cap.allocation_method = req->sbc_capabilities.allocation_method; + sbc_cap.subbands = req->sbc_capabilities.subbands; + sbc_cap.block_length = req->sbc_capabilities.block_length; + sbc_cap.min_bitpool = req->sbc_capabilities.min_bitpool; + sbc_cap.max_bitpool = req->sbc_capabilities.max_bitpool; + + media_codec = avdtp_service_cap_new(AVDTP_MEDIA_CODEC, &sbc_cap, + sizeof(sbc_cap)); + + info("config sbc - frequency = %u channel_mode = %u " + "allocation = %u subbands = %u blocks = %u " + "bitpool = %u", sbc_cap.frequency, + sbc_cap.channel_mode, sbc_cap.allocation_method, + sbc_cap.subbands, sbc_cap.block_length, + sbc_cap.max_bitpool); + } client->caps = g_slist_append(client->caps, media_codec); |