mirror of
				https://gitlab.freedesktop.org/pulseaudio/pulseaudio.git
				synced 2025-11-03 09:01:50 -05:00 
			
		
		
		
	Configure bt connection for a2dp
This commit is contained in:
		
							parent
							
								
									85a931f333
								
							
						
					
					
						commit
						b5c4d2e5f1
					
				
					 2 changed files with 94 additions and 14 deletions
				
			
		
							
								
								
									
										76
									
								
								src/modules/bt-rtp.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										76
									
								
								src/modules/bt-rtp.h
									
										
									
									
									
										Normal 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
 | 
				
			||||||
| 
						 | 
					@ -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);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue