mirror of
				https://gitlab.freedesktop.org/pulseaudio/pulseaudio.git
				synced 2025-11-03 09:01:50 -05:00 
			
		
		
		
	Update ipc to match new message headers introduced on BlueZ 4.34.
This commit is contained in:
		
							parent
							
								
									b03c545850
								
							
						
					
					
						commit
						071b3e7fc5
					
				
					 3 changed files with 84 additions and 36 deletions
				
			
		| 
						 | 
					@ -35,6 +35,7 @@ static const char *strtypes[] = {
 | 
				
			||||||
/* This table contains the string representation for messages names */
 | 
					/* This table contains the string representation for messages names */
 | 
				
			||||||
static const char *strnames[] = {
 | 
					static const char *strnames[] = {
 | 
				
			||||||
	"BT_GET_CAPABILITIES",
 | 
						"BT_GET_CAPABILITIES",
 | 
				
			||||||
 | 
						"BT_OPEN",
 | 
				
			||||||
	"BT_SET_CONFIGURATION",
 | 
						"BT_SET_CONFIGURATION",
 | 
				
			||||||
	"BT_NEW_STREAM",
 | 
						"BT_NEW_STREAM",
 | 
				
			||||||
	"BT_START_STREAM",
 | 
						"BT_START_STREAM",
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -71,7 +71,7 @@ extern "C" {
 | 
				
			||||||
#include <sys/un.h>
 | 
					#include <sys/un.h>
 | 
				
			||||||
#include <errno.h>
 | 
					#include <errno.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define BT_SUGGESTED_BUFFER_SIZE   128
 | 
					#define BT_SUGGESTED_BUFFER_SIZE   512
 | 
				
			||||||
#define BT_IPC_SOCKET_NAME "\0/org/bluez/audio"
 | 
					#define BT_IPC_SOCKET_NAME "\0/org/bluez/audio"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Generic message header definition, except for RESPONSE messages */
 | 
					/* Generic message header definition, except for RESPONSE messages */
 | 
				
			||||||
| 
						 | 
					@ -94,10 +94,12 @@ typedef struct {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Messages names */
 | 
					/* Messages names */
 | 
				
			||||||
#define BT_GET_CAPABILITIES		0
 | 
					#define BT_GET_CAPABILITIES		0
 | 
				
			||||||
#define BT_SET_CONFIGURATION		1
 | 
					#define BT_OPEN				1
 | 
				
			||||||
#define BT_NEW_STREAM			2
 | 
					#define BT_SET_CONFIGURATION		2
 | 
				
			||||||
#define BT_START_STREAM			3
 | 
					#define BT_NEW_STREAM			3
 | 
				
			||||||
#define BT_STOP_STREAM			4
 | 
					#define BT_START_STREAM			4
 | 
				
			||||||
 | 
					#define BT_STOP_STREAM			5
 | 
				
			||||||
 | 
					#define BT_CLOSE			6
 | 
				
			||||||
#define BT_CONTROL			7
 | 
					#define BT_CONTROL			7
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define BT_CAPABILITIES_TRANSPORT_A2DP	0
 | 
					#define BT_CAPABILITIES_TRANSPORT_A2DP	0
 | 
				
			||||||
| 
						 | 
					@ -112,19 +114,31 @@ typedef struct {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct bt_get_capabilities_req {
 | 
					struct bt_get_capabilities_req {
 | 
				
			||||||
	bt_audio_msg_header_t	h;
 | 
						bt_audio_msg_header_t	h;
 | 
				
			||||||
	char			device[18];	/* Address of the remote Device */
 | 
						char			source[18];	/* Address of the local Device */
 | 
				
			||||||
 | 
						char			destination[18];/* Address of the remote Device */
 | 
				
			||||||
 | 
						char			object[128];	/* DBus object path */
 | 
				
			||||||
	uint8_t			transport;	/* Requested transport */
 | 
						uint8_t			transport;	/* Requested transport */
 | 
				
			||||||
	uint8_t			flags;		/* Requested flags */
 | 
						uint8_t			flags;		/* Requested flags */
 | 
				
			||||||
 | 
						uint8_t			seid;		/* Requested capability configuration */
 | 
				
			||||||
} __attribute__ ((packed));
 | 
					} __attribute__ ((packed));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * SBC Codec parameters as per A2DP profile 1.0 § 4.3
 | 
					 * SBC Codec parameters as per A2DP profile 1.0 § 4.3
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define BT_A2DP_CODEC_SBC			0x00
 | 
					/* A2DP seid are 6 bytes long so HSP/HFP are assigned to 7-8 bits */
 | 
				
			||||||
#define BT_A2DP_CODEC_MPEG12			0x01
 | 
					#define BT_A2DP_SEID_RANGE			(1 << 6) - 1
 | 
				
			||||||
#define BT_A2DP_CODEC_MPEG24			0x02
 | 
					
 | 
				
			||||||
#define BT_A2DP_CODEC_ATRAC			0x03
 | 
					#define BT_A2DP_SBC_SOURCE			0x00
 | 
				
			||||||
 | 
					#define BT_A2DP_SBC_SINK			0x01
 | 
				
			||||||
 | 
					#define BT_A2DP_MPEG12_SOURCE			0x02
 | 
				
			||||||
 | 
					#define BT_A2DP_MPEG12_SINK			0x03
 | 
				
			||||||
 | 
					#define BT_A2DP_MPEG24_SOURCE			0x04
 | 
				
			||||||
 | 
					#define BT_A2DP_MPEG24_SINK			0x05
 | 
				
			||||||
 | 
					#define BT_A2DP_ATRAC_SOURCE			0x06
 | 
				
			||||||
 | 
					#define BT_A2DP_ATRAC_SINK			0x07
 | 
				
			||||||
 | 
					#define BT_A2DP_UNKNOWN_SOURCE			0x08
 | 
				
			||||||
 | 
					#define BT_A2DP_UNKNOWN_SINK			0x09
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define BT_SBC_SAMPLING_FREQ_16000		(1 << 3)
 | 
					#define BT_SBC_SAMPLING_FREQ_16000		(1 << 3)
 | 
				
			||||||
#define BT_SBC_SAMPLING_FREQ_32000		(1 << 2)
 | 
					#define BT_SBC_SAMPLING_FREQ_32000		(1 << 2)
 | 
				
			||||||
| 
						 | 
					@ -163,10 +177,16 @@ struct bt_get_capabilities_req {
 | 
				
			||||||
#define BT_PCM_FLAG_NREC			0x01
 | 
					#define BT_PCM_FLAG_NREC			0x01
 | 
				
			||||||
#define BT_PCM_FLAG_PCM_ROUTING			0x02
 | 
					#define BT_PCM_FLAG_PCM_ROUTING			0x02
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define BT_WRITE_LOCK				(1 << 1)
 | 
				
			||||||
 | 
					#define BT_READ_LOCK				1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
typedef struct {
 | 
					typedef struct {
 | 
				
			||||||
 | 
						uint8_t seid;
 | 
				
			||||||
	uint8_t transport;
 | 
						uint8_t transport;
 | 
				
			||||||
	uint8_t type;
 | 
						uint8_t type;
 | 
				
			||||||
	uint8_t length;
 | 
						uint8_t length;
 | 
				
			||||||
 | 
						uint8_t configured;
 | 
				
			||||||
 | 
						uint8_t lock;
 | 
				
			||||||
	uint8_t data[0];
 | 
						uint8_t data[0];
 | 
				
			||||||
} __attribute__ ((packed)) codec_capabilities_t;
 | 
					} __attribute__ ((packed)) codec_capabilities_t;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -199,20 +219,35 @@ typedef struct {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct bt_get_capabilities_rsp {
 | 
					struct bt_get_capabilities_rsp {
 | 
				
			||||||
	bt_audio_msg_header_t	h;
 | 
						bt_audio_msg_header_t	h;
 | 
				
			||||||
 | 
						char			source[18];	/* Address of the local Device */
 | 
				
			||||||
 | 
						char			destination[18];/* Address of the remote Device */
 | 
				
			||||||
 | 
						char			object[128];	/* DBus object path */
 | 
				
			||||||
	uint8_t			data[0];	/* First codec_capabilities_t */
 | 
						uint8_t			data[0];	/* First codec_capabilities_t */
 | 
				
			||||||
} __attribute__ ((packed));
 | 
					} __attribute__ ((packed));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct bt_open_req {
 | 
				
			||||||
 | 
						bt_audio_msg_header_t	h;
 | 
				
			||||||
 | 
						char			source[18];	/* Address of the local Device */
 | 
				
			||||||
 | 
						char			destination[18];/* Address of the remote Device */
 | 
				
			||||||
 | 
						char			object[128];	/* DBus object path */
 | 
				
			||||||
 | 
						uint8_t			seid;		/* Requested capability configuration to lock */
 | 
				
			||||||
 | 
						uint8_t			lock;		/* Requested lock */
 | 
				
			||||||
 | 
					} __attribute__ ((packed));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct bt_open_rsp {
 | 
				
			||||||
 | 
						bt_audio_msg_header_t	h;
 | 
				
			||||||
 | 
						char			source[18];	/* Address of the local Device */
 | 
				
			||||||
 | 
						char			destination[18];/* Address of the remote Device */
 | 
				
			||||||
 | 
						char			object[128];	/* DBus object path */
 | 
				
			||||||
 | 
					} __attribute__ ((packed));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct bt_set_configuration_req {
 | 
					struct bt_set_configuration_req {
 | 
				
			||||||
	bt_audio_msg_header_t	h;
 | 
						bt_audio_msg_header_t	h;
 | 
				
			||||||
	char			device[18];	/* Address of the remote Device */
 | 
					 | 
				
			||||||
	uint8_t			access_mode;	/* Requested access mode */
 | 
					 | 
				
			||||||
	codec_capabilities_t	codec;		/* Requested codec */
 | 
						codec_capabilities_t	codec;		/* Requested codec */
 | 
				
			||||||
} __attribute__ ((packed));
 | 
					} __attribute__ ((packed));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct bt_set_configuration_rsp {
 | 
					struct bt_set_configuration_rsp {
 | 
				
			||||||
	bt_audio_msg_header_t	h;
 | 
						bt_audio_msg_header_t	h;
 | 
				
			||||||
	uint8_t			transport;	/* Granted transport */
 | 
					 | 
				
			||||||
	uint8_t			access_mode;	/* Granted access mode */
 | 
					 | 
				
			||||||
	uint16_t		link_mtu;	/* Max length that transport supports */
 | 
						uint16_t		link_mtu;	/* Max length that transport supports */
 | 
				
			||||||
} __attribute__ ((packed));
 | 
					} __attribute__ ((packed));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -241,6 +276,14 @@ struct bt_stop_stream_rsp {
 | 
				
			||||||
	bt_audio_msg_header_t	h;
 | 
						bt_audio_msg_header_t	h;
 | 
				
			||||||
} __attribute__ ((packed));
 | 
					} __attribute__ ((packed));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct bt_close_req {
 | 
				
			||||||
 | 
						bt_audio_msg_header_t	h;
 | 
				
			||||||
 | 
					} __attribute__ ((packed));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct bt_close_rsp {
 | 
				
			||||||
 | 
						bt_audio_msg_header_t	h;
 | 
				
			||||||
 | 
					} __attribute__ ((packed));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct bt_suspend_stream_ind {
 | 
					struct bt_suspend_stream_ind {
 | 
				
			||||||
	bt_audio_msg_header_t	h;
 | 
						bt_audio_msg_header_t	h;
 | 
				
			||||||
} __attribute__ ((packed));
 | 
					} __attribute__ ((packed));
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -311,7 +311,7 @@ static int parse_caps(struct userdata *u, const struct bt_get_capabilities_rsp *
 | 
				
			||||||
    } else if (u->profile == PROFILE_A2DP) {
 | 
					    } else if (u->profile == PROFILE_A2DP) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        while (bytes_left > 0) {
 | 
					        while (bytes_left > 0) {
 | 
				
			||||||
            if (codec->type == BT_A2DP_CODEC_SBC)
 | 
					            if ((codec->type == BT_A2DP_SBC_SINK) && !codec->lock)
 | 
				
			||||||
                break;
 | 
					                break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            bytes_left -= codec->length;
 | 
					            bytes_left -= codec->length;
 | 
				
			||||||
| 
						 | 
					@ -321,7 +321,7 @@ static int parse_caps(struct userdata *u, const struct bt_get_capabilities_rsp *
 | 
				
			||||||
        if (bytes_left <= 0 || codec->length != sizeof(u->a2dp.sbc_capabilities))
 | 
					        if (bytes_left <= 0 || codec->length != sizeof(u->a2dp.sbc_capabilities))
 | 
				
			||||||
            return -1;
 | 
					            return -1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        pa_assert(codec->type == BT_A2DP_CODEC_SBC);
 | 
					        pa_assert(codec->type == BT_A2DP_SBC_SINK);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        memcpy(&u->a2dp.sbc_capabilities, codec, sizeof(u->a2dp.sbc_capabilities));
 | 
					        memcpy(&u->a2dp.sbc_capabilities, codec, sizeof(u->a2dp.sbc_capabilities));
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
| 
						 | 
					@ -344,7 +344,7 @@ static int get_caps(struct userdata *u) {
 | 
				
			||||||
    msg.getcaps_req.h.name = BT_GET_CAPABILITIES;
 | 
					    msg.getcaps_req.h.name = BT_GET_CAPABILITIES;
 | 
				
			||||||
    msg.getcaps_req.h.length = sizeof(msg.getcaps_req);
 | 
					    msg.getcaps_req.h.length = sizeof(msg.getcaps_req);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    pa_strlcpy(msg.getcaps_req.device, u->address, sizeof(msg.getcaps_req.device));
 | 
					    pa_strlcpy(msg.getcaps_req.object, u->path, sizeof(msg.getcaps_req.object));
 | 
				
			||||||
    if (u->profile == PROFILE_A2DP)
 | 
					    if (u->profile == PROFILE_A2DP)
 | 
				
			||||||
        msg.getcaps_req.transport = BT_CAPABILITIES_TRANSPORT_A2DP;
 | 
					        msg.getcaps_req.transport = BT_CAPABILITIES_TRANSPORT_A2DP;
 | 
				
			||||||
    else {
 | 
					    else {
 | 
				
			||||||
| 
						 | 
					@ -602,12 +602,29 @@ static void setup_sbc(struct a2dp_info *a2dp) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int set_conf(struct userdata *u) {
 | 
					static int set_conf(struct userdata *u) {
 | 
				
			||||||
    union {
 | 
					    union {
 | 
				
			||||||
 | 
					        struct bt_open_req open_req;
 | 
				
			||||||
 | 
					        struct bt_open_rsp open_rsp;
 | 
				
			||||||
        struct bt_set_configuration_req setconf_req;
 | 
					        struct bt_set_configuration_req setconf_req;
 | 
				
			||||||
        struct bt_set_configuration_rsp setconf_rsp;
 | 
					        struct bt_set_configuration_rsp setconf_rsp;
 | 
				
			||||||
        bt_audio_error_t error;
 | 
					        bt_audio_error_t error;
 | 
				
			||||||
        uint8_t buf[BT_SUGGESTED_BUFFER_SIZE];
 | 
					        uint8_t buf[BT_SUGGESTED_BUFFER_SIZE];
 | 
				
			||||||
    } msg;
 | 
					    } msg;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    memset(&msg, 0, sizeof(msg));
 | 
				
			||||||
 | 
					    msg.open_req.h.type = BT_REQUEST;
 | 
				
			||||||
 | 
					    msg.open_req.h.name = BT_OPEN;
 | 
				
			||||||
 | 
					    msg.open_req.h.length = sizeof(msg.open_req);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    pa_strlcpy(msg.open_req.object, u->path, sizeof(msg.open_req.object));
 | 
				
			||||||
 | 
					    msg.open_req.seid = u->profile == PROFILE_A2DP ? u->a2dp.sbc_capabilities.capability.seid : BT_A2DP_SEID_RANGE + 1;
 | 
				
			||||||
 | 
					    msg.open_req.lock = u->profile == PROFILE_A2DP ? BT_WRITE_LOCK : BT_READ_LOCK | BT_WRITE_LOCK;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (service_send(u, &msg.open_req.h) < 0)
 | 
				
			||||||
 | 
					        return -1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (service_expect(u, &msg.open_rsp.h, sizeof(msg), BT_OPEN, sizeof(msg.open_rsp)) < 0)
 | 
				
			||||||
 | 
					        return -1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (u->profile == PROFILE_A2DP ) {
 | 
					    if (u->profile == PROFILE_A2DP ) {
 | 
				
			||||||
        u->sample_spec.format = PA_SAMPLE_S16LE;
 | 
					        u->sample_spec.format = PA_SAMPLE_S16LE;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -626,15 +643,14 @@ static int set_conf(struct userdata *u) {
 | 
				
			||||||
    msg.setconf_req.h.name = BT_SET_CONFIGURATION;
 | 
					    msg.setconf_req.h.name = BT_SET_CONFIGURATION;
 | 
				
			||||||
    msg.setconf_req.h.length = sizeof(msg.setconf_req);
 | 
					    msg.setconf_req.h.length = sizeof(msg.setconf_req);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    pa_strlcpy(msg.setconf_req.device, u->address, sizeof(msg.setconf_req.device));
 | 
					 | 
				
			||||||
    msg.setconf_req.access_mode = u->profile == PROFILE_A2DP ? BT_CAPABILITIES_ACCESS_MODE_WRITE : BT_CAPABILITIES_ACCESS_MODE_READWRITE;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    msg.setconf_req.codec.transport = u->profile == PROFILE_A2DP ? BT_CAPABILITIES_TRANSPORT_A2DP : BT_CAPABILITIES_TRANSPORT_SCO;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (u->profile == PROFILE_A2DP) {
 | 
					    if (u->profile == PROFILE_A2DP) {
 | 
				
			||||||
        memcpy(&msg.setconf_req.codec, &u->a2dp.sbc_capabilities, sizeof(u->a2dp.sbc_capabilities));
 | 
					        memcpy(&msg.setconf_req.codec, &u->a2dp.sbc_capabilities, sizeof(u->a2dp.sbc_capabilities));
 | 
				
			||||||
        msg.setconf_req.h.length += msg.setconf_req.codec.length - sizeof(msg.setconf_req.codec);
 | 
					    } else {
 | 
				
			||||||
 | 
					        msg.setconf_req.codec.transport = BT_CAPABILITIES_TRANSPORT_SCO;
 | 
				
			||||||
 | 
					        msg.setconf_req.codec.seid = BT_A2DP_SEID_RANGE + 1;
 | 
				
			||||||
 | 
					        msg.setconf_req.codec.length = sizeof(pcm_capabilities_t);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					    msg.setconf_req.h.length += msg.setconf_req.codec.length - sizeof(msg.setconf_req.codec);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (service_send(u, &msg.setconf_req.h) < 0)
 | 
					    if (service_send(u, &msg.setconf_req.h) < 0)
 | 
				
			||||||
        return -1;
 | 
					        return -1;
 | 
				
			||||||
| 
						 | 
					@ -642,18 +658,6 @@ static int set_conf(struct userdata *u) {
 | 
				
			||||||
    if (service_expect(u, &msg.setconf_rsp.h, sizeof(msg), BT_SET_CONFIGURATION, sizeof(msg.setconf_rsp)) < 0)
 | 
					    if (service_expect(u, &msg.setconf_rsp.h, sizeof(msg), BT_SET_CONFIGURATION, sizeof(msg.setconf_rsp)) < 0)
 | 
				
			||||||
        return -1;
 | 
					        return -1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if ((u->profile == PROFILE_A2DP && msg.setconf_rsp.transport != BT_CAPABILITIES_TRANSPORT_A2DP) ||
 | 
					 | 
				
			||||||
        (u->profile == PROFILE_HSP && msg.setconf_rsp.transport != BT_CAPABILITIES_TRANSPORT_SCO)) {
 | 
					 | 
				
			||||||
        pa_log("Transport doesn't match what we requested.");
 | 
					 | 
				
			||||||
        return -1;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if ((u->profile == PROFILE_A2DP && msg.setconf_rsp.access_mode != BT_CAPABILITIES_ACCESS_MODE_WRITE) ||
 | 
					 | 
				
			||||||
        (u->profile == PROFILE_HSP && msg.setconf_rsp.access_mode != BT_CAPABILITIES_ACCESS_MODE_READWRITE)) {
 | 
					 | 
				
			||||||
        pa_log("Access mode doesn't match what we requested.");
 | 
					 | 
				
			||||||
        return -1;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    u->link_mtu = msg.setconf_rsp.link_mtu;
 | 
					    u->link_mtu = msg.setconf_rsp.link_mtu;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* setup SBC encoder now we agree on parameters */
 | 
					    /* setup SBC encoder now we agree on parameters */
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue