summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/modules/bt-rtp.h76
-rw-r--r--src/modules/module-bt-device.c32
2 files changed, 94 insertions, 14 deletions
diff --git a/src/modules/bt-rtp.h b/src/modules/bt-rtp.h
new file mode 100644
index 00000000..690bd43a
--- /dev/null
+++ b/src/modules/bt-rtp.h
@@ -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
diff --git a/src/modules/module-bt-device.c b/src/modules/module-bt-device.c
index e808cfb7..87d6ea60 100644
--- a/src/modules/module-bt-device.c
+++ b/src/modules/module-bt-device.c
@@ -44,11 +44,15 @@
#include "module-bt-device-symdef.h"
#include "bt-ipc.h"
#include "bt-sbc.h"
+#include "bt-rtp.h"
#define DEFAULT_SINK_NAME "bluetooth_sink"
#define BUFFER_SIZE 2048
#define MAX_BITPOOL 64
#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_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) {
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) {
case 48000:
@@ -260,14 +264,14 @@ static int bt_a2dp_init(struct userdata *u) {
cap->frequency = BT_SBC_SAMPLING_FREQ_16000;
break;
default:
- pa_log_error("Rate %d not supported", rate);
+ pa_log_error("Rate %d not supported", u->rate);
return -1;
}
// if (cfg->has_channel_mode)
// cap->channel_mode = cfg->channel_mode;
// else
- if (channels == 2) {
+ if (u->channels == 2) {
if (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)
@@ -364,7 +368,7 @@ static void bt_a2dp_setup(struct bt_a2dp *a2dp) {
if (active_capabilities.channel_mode & BT_A2DP_CHANNEL_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) {
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->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) {
@@ -457,7 +461,9 @@ static int bt_setconf(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];
struct bt_streamstart_req *start_req = (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);
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;
}
// if (u->transport == BT_CAPABILITIES_TRANSPORT_A2DP) {
-// opt_name = SO_SNDTIMEO;
-// if (setsockopt(u->stream_fd, SOL_SOCKET, opt_name, &t, sizeof(t)) < 0) {
-// pa_log_error("failed to set socket options for A2DP");
+// if (setsockopt(u->stream_fd, SOL_SOCKET, SO_SNDTIMEO, &t, sizeof(t)) < 0) {
+// pa_log_error("failed to set socket options for A2DP: %s (%d)",pa_cstrerror(errno), errno);
// return -errno;
// }
// }
// else {
-// opt_name = SCO_TXBUFS;
-// if (setsockopt(u->stream_fd, SOL_SCO, opt_name, &period_count, sizeof(period_count)) == 0)
+// if (setsockopt(u->stream_fd, SOL_SCO, SCO_TXBUFS, &period_count, sizeof(period_count)) == 0)
// return 0;
-// opt_name = SO_SNDBUF;
-// if (setsockopt(u->stream_fd, SOL_SCO, opt_name, &period_count, sizeof(period_count)) == 0)
+// if (setsockopt(u->stream_fd, SOL_SCO, SO_SNDBUF, &period_count, sizeof(period_count)) == 0)
// return 0;
// /* FIXME : handle error codes */
// }
@@ -703,6 +706,7 @@ int pa__init(pa_module* m) {
u->transport = -1;
u->offset = 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->mempool = pa_mempool_new(FALSE);
pa_memchunk_reset(&u->memchunk);