Configure bt connection for a2dp

This commit is contained in:
João Paulo Rechi Vita 2008-08-16 16:03:20 -03:00 committed by Lennart Poettering
parent 85a931f333
commit b5c4d2e5f1
2 changed files with 94 additions and 14 deletions

76
src/modules/bt-rtp.h Normal file
View file

@ -0,0 +1,76 @@
/*
*
* BlueZ - Bluetooth protocol stack for Linux
*
* Copyright (C) 2004-2008 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 {
uint8_t cc:4;
uint8_t x:1;
uint8_t p:1;
uint8_t v:2;
uint8_t pt:7;
uint8_t m:1;
uint16_t sequence_number;
uint32_t timestamp;
uint32_t ssrc;
uint32_t csrc[0];
} __attribute__ ((packed));
struct rtp_payload {
uint8_t frame_count:4;
uint8_t rfa0:1;
uint8_t is_last_fragment:1;
uint8_t is_first_fragment:1;
uint8_t is_fragmented:1;
} __attribute__ ((packed));
#elif __BYTE_ORDER == __BIG_ENDIAN
struct rtp_header {
uint8_t v:2;
uint8_t p:1;
uint8_t x:1;
uint8_t cc:4;
uint8_t m:1;
uint8_t pt:7;
uint16_t sequence_number;
uint32_t timestamp;
uint32_t ssrc;
uint32_t csrc[0];
} __attribute__ ((packed));
struct rtp_payload {
uint8_t is_fragmented:1;
uint8_t is_first_fragment:1;
uint8_t is_last_fragment:1;
uint8_t rfa0:1;
uint8_t frame_count:4;
} __attribute__ ((packed));
#else
#error "Unknown byte order"
#endif

View file

@ -44,11 +44,15 @@
#include "module-bt-device-symdef.h" #include "module-bt-device-symdef.h"
#include "bt-ipc.h" #include "bt-ipc.h"
#include "bt-sbc.h" #include "bt-sbc.h"
#include "bt-rtp.h"
#define DEFAULT_SINK_NAME "bluetooth_sink" #define DEFAULT_SINK_NAME "bluetooth_sink"
#define BUFFER_SIZE 2048 #define BUFFER_SIZE 2048
#define MAX_BITPOOL 64 #define MAX_BITPOOL 64
#define MIN_BITPOOL 2 #define MIN_BITPOOL 2
#define SOL_SCO 17
#define SCO_TXBUFS 0x03
#define SCO_RXBUFS 0x04
PA_MODULE_AUTHOR("Joao Paulo Rechi Vita"); PA_MODULE_AUTHOR("Joao Paulo Rechi Vita");
PA_MODULE_DESCRIPTION("Bluetooth audio sink and source"); PA_MODULE_DESCRIPTION("Bluetooth audio sink and source");
@ -244,7 +248,7 @@ static uint8_t default_bitpool(uint8_t freq, uint8_t mode) {
static int bt_a2dp_init(struct userdata *u) { static int bt_a2dp_init(struct userdata *u) {
sbc_capabilities_t *cap = &u->a2dp.sbc_capabilities; sbc_capabilities_t *cap = &u->a2dp.sbc_capabilities;
unsigned int max_bitpool, min_bitpool, rate, channels; unsigned int max_bitpool, min_bitpool;
switch (u->rate) { switch (u->rate) {
case 48000: case 48000:
@ -260,14 +264,14 @@ static int bt_a2dp_init(struct userdata *u) {
cap->frequency = BT_SBC_SAMPLING_FREQ_16000; cap->frequency = BT_SBC_SAMPLING_FREQ_16000;
break; break;
default: default:
pa_log_error("Rate %d not supported", rate); pa_log_error("Rate %d not supported", u->rate);
return -1; return -1;
} }
// if (cfg->has_channel_mode) // if (cfg->has_channel_mode)
// cap->channel_mode = cfg->channel_mode; // cap->channel_mode = cfg->channel_mode;
// else // else
if (channels == 2) { if (u->channels == 2) {
if (cap->channel_mode & BT_A2DP_CHANNEL_MODE_JOINT_STEREO) if (cap->channel_mode & BT_A2DP_CHANNEL_MODE_JOINT_STEREO)
cap->channel_mode = BT_A2DP_CHANNEL_MODE_JOINT_STEREO; cap->channel_mode = BT_A2DP_CHANNEL_MODE_JOINT_STEREO;
else if (cap->channel_mode & BT_A2DP_CHANNEL_MODE_STEREO) else if (cap->channel_mode & BT_A2DP_CHANNEL_MODE_STEREO)
@ -364,7 +368,7 @@ static void bt_a2dp_setup(struct bt_a2dp *a2dp) {
if (active_capabilities.channel_mode & BT_A2DP_CHANNEL_MODE_JOINT_STEREO) if (active_capabilities.channel_mode & BT_A2DP_CHANNEL_MODE_JOINT_STEREO)
a2dp->sbc.mode = SBC_MODE_JOINT_STEREO; a2dp->sbc.mode = SBC_MODE_JOINT_STEREO;
a2dp->sbc.allocation = active_capabilities.allocation_method == BT_A2DP_ALLOCATION_SNR ? SBC_AM_SNR : SBC_AM_LOUDNESS; a2dp->sbc.allocation = (active_capabilities.allocation_method == BT_A2DP_ALLOCATION_SNR ? SBC_AM_SNR : SBC_AM_LOUDNESS);
switch (active_capabilities.subbands) { switch (active_capabilities.subbands) {
case BT_A2DP_SUBBANDS_4: case BT_A2DP_SUBBANDS_4:
@ -392,7 +396,7 @@ static void bt_a2dp_setup(struct bt_a2dp *a2dp) {
a2dp->sbc.bitpool = active_capabilities.max_bitpool; a2dp->sbc.bitpool = active_capabilities.max_bitpool;
a2dp->codesize = sbc_get_codesize(&a2dp->sbc); a2dp->codesize = sbc_get_codesize(&a2dp->sbc);
// a2dp->count = sizeof(struct rtp_header) + sizeof(struct rtp_payload); a2dp->count = sizeof(struct rtp_header) + sizeof(struct rtp_payload);
} }
static int bt_setconf(struct userdata *u) { static int bt_setconf(struct userdata *u) {
@ -457,7 +461,9 @@ static int bt_setconf(struct userdata *u) {
} }
static int bt_getstreamfd(struct userdata *u) { static int bt_getstreamfd(struct userdata *u) {
int e/*, opt_name*/; int e;
// uint32_t period_count = io->buffer_size / io->period_size;
// struct timeval t = { 0, period_count };
char buf[BT_AUDIO_IPC_PACKET_SIZE]; char buf[BT_AUDIO_IPC_PACKET_SIZE];
struct bt_streamstart_req *start_req = (void*) buf; struct bt_streamstart_req *start_req = (void*) buf;
bt_audio_rsp_msg_header_t *rsp_hdr = (void*) buf; bt_audio_rsp_msg_header_t *rsp_hdr = (void*) buf;
@ -494,23 +500,20 @@ static int bt_getstreamfd(struct userdata *u) {
u->stream_fd = bt_audio_service_get_data_fd(u->audioservice_fd); u->stream_fd = bt_audio_service_get_data_fd(u->audioservice_fd);
if (u->stream_fd < 0) { if (u->stream_fd < 0) {
pa_log_error("failed to get data fd"); pa_log_error("failed to get data fd: %s (%d)",pa_cstrerror(errno), errno);
return -errno; return -errno;
} }
// if (u->transport == BT_CAPABILITIES_TRANSPORT_A2DP) { // if (u->transport == BT_CAPABILITIES_TRANSPORT_A2DP) {
// opt_name = SO_SNDTIMEO; // if (setsockopt(u->stream_fd, SOL_SOCKET, SO_SNDTIMEO, &t, sizeof(t)) < 0) {
// if (setsockopt(u->stream_fd, SOL_SOCKET, opt_name, &t, sizeof(t)) < 0) { // pa_log_error("failed to set socket options for A2DP: %s (%d)",pa_cstrerror(errno), errno);
// pa_log_error("failed to set socket options for A2DP");
// return -errno; // return -errno;
// } // }
// } // }
// else { // else {
// opt_name = SCO_TXBUFS; // if (setsockopt(u->stream_fd, SOL_SCO, SCO_TXBUFS, &period_count, sizeof(period_count)) == 0)
// if (setsockopt(u->stream_fd, SOL_SCO, opt_name, &period_count, sizeof(period_count)) == 0)
// return 0; // return 0;
// opt_name = SO_SNDBUF; // if (setsockopt(u->stream_fd, SOL_SCO, SO_SNDBUF, &period_count, sizeof(period_count)) == 0)
// if (setsockopt(u->stream_fd, SOL_SCO, opt_name, &period_count, sizeof(period_count)) == 0)
// return 0; // return 0;
// /* FIXME : handle error codes */ // /* FIXME : handle error codes */
// } // }
@ -703,6 +706,7 @@ int pa__init(pa_module* m) {
u->transport = -1; u->transport = -1;
u->offset = 0; u->offset = 0;
u->latency = 0; u->latency = 0;
u->a2dp.sbc_initialized = 0;
u->smoother = pa_smoother_new(PA_USEC_PER_SEC, PA_USEC_PER_SEC*2, TRUE, 10); u->smoother = pa_smoother_new(PA_USEC_PER_SEC, PA_USEC_PER_SEC*2, TRUE, 10);
u->mempool = pa_mempool_new(FALSE); u->mempool = pa_mempool_new(FALSE);
pa_memchunk_reset(&u->memchunk); pa_memchunk_reset(&u->memchunk);