diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/modules/bluetooth/ipc.c | 1 | ||||
| -rw-r--r-- | src/modules/bluetooth/ipc.h | 73 | ||||
| -rw-r--r-- | src/modules/bluetooth/module-bluetooth-device.c | 46 | 
3 files changed, 84 insertions, 36 deletions
| diff --git a/src/modules/bluetooth/ipc.c b/src/modules/bluetooth/ipc.c index f14c92c4..dcecad8a 100644 --- a/src/modules/bluetooth/ipc.c +++ b/src/modules/bluetooth/ipc.c @@ -35,6 +35,7 @@ static const char *strtypes[] = {  /* This table contains the string representation for messages names */  static const char *strnames[] = {  	"BT_GET_CAPABILITIES", +	"BT_OPEN",  	"BT_SET_CONFIGURATION",  	"BT_NEW_STREAM",  	"BT_START_STREAM", diff --git a/src/modules/bluetooth/ipc.h b/src/modules/bluetooth/ipc.h index f030acfa..2e170f50 100644 --- a/src/modules/bluetooth/ipc.h +++ b/src/modules/bluetooth/ipc.h @@ -71,7 +71,7 @@ extern "C" {  #include <sys/un.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"  /* Generic message header definition, except for RESPONSE messages */ @@ -94,10 +94,12 @@ typedef struct {  /* Messages names */  #define BT_GET_CAPABILITIES		0 -#define BT_SET_CONFIGURATION		1 -#define BT_NEW_STREAM			2 -#define BT_START_STREAM			3 -#define BT_STOP_STREAM			4 +#define BT_OPEN				1 +#define BT_SET_CONFIGURATION		2 +#define BT_NEW_STREAM			3 +#define BT_START_STREAM			4 +#define BT_STOP_STREAM			5 +#define BT_CLOSE			6  #define BT_CONTROL			7  #define BT_CAPABILITIES_TRANSPORT_A2DP	0 @@ -112,19 +114,31 @@ typedef struct {  struct bt_get_capabilities_req {  	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			flags;		/* Requested flags */ +	uint8_t			seid;		/* Requested capability configuration */  } __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 -#define BT_A2DP_CODEC_MPEG12			0x01 -#define BT_A2DP_CODEC_MPEG24			0x02 -#define BT_A2DP_CODEC_ATRAC			0x03 +/* A2DP seid are 6 bytes long so HSP/HFP are assigned to 7-8 bits */ +#define BT_A2DP_SEID_RANGE			(1 << 6) - 1 + +#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_32000		(1 << 2) @@ -163,10 +177,16 @@ struct bt_get_capabilities_req {  #define BT_PCM_FLAG_NREC			0x01  #define BT_PCM_FLAG_PCM_ROUTING			0x02 +#define BT_WRITE_LOCK				(1 << 1) +#define BT_READ_LOCK				1 +  typedef struct { +	uint8_t seid;  	uint8_t transport;  	uint8_t type;  	uint8_t length; +	uint8_t configured; +	uint8_t lock;  	uint8_t data[0];  } __attribute__ ((packed)) codec_capabilities_t; @@ -199,20 +219,35 @@ typedef struct {  struct bt_get_capabilities_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 */  	uint8_t			data[0];	/* First codec_capabilities_t */  } __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 {  	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 */  } __attribute__ ((packed));  struct bt_set_configuration_rsp {  	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 */  } __attribute__ ((packed)); @@ -241,6 +276,14 @@ struct bt_stop_stream_rsp {  	bt_audio_msg_header_t	h;  } __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 {  	bt_audio_msg_header_t	h;  } __attribute__ ((packed)); diff --git a/src/modules/bluetooth/module-bluetooth-device.c b/src/modules/bluetooth/module-bluetooth-device.c index 2500fb09..d09dc2c9 100644 --- a/src/modules/bluetooth/module-bluetooth-device.c +++ b/src/modules/bluetooth/module-bluetooth-device.c @@ -311,7 +311,7 @@ static int parse_caps(struct userdata *u, const struct bt_get_capabilities_rsp *      } else if (u->profile == PROFILE_A2DP) {          while (bytes_left > 0) { -            if (codec->type == BT_A2DP_CODEC_SBC) +            if ((codec->type == BT_A2DP_SBC_SINK) && !codec->lock)                  break;              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))              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));      } @@ -344,7 +344,7 @@ static int get_caps(struct userdata *u) {      msg.getcaps_req.h.name = BT_GET_CAPABILITIES;      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)          msg.getcaps_req.transport = BT_CAPABILITIES_TRANSPORT_A2DP;      else { @@ -602,12 +602,29 @@ static void setup_sbc(struct a2dp_info *a2dp) {  static int set_conf(struct userdata *u) {      union { +        struct bt_open_req open_req; +        struct bt_open_rsp open_rsp;          struct bt_set_configuration_req setconf_req;          struct bt_set_configuration_rsp setconf_rsp;          bt_audio_error_t error;          uint8_t buf[BT_SUGGESTED_BUFFER_SIZE];      } 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 ) {          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.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) {          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)          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)          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;      /* setup SBC encoder now we agree on parameters */ | 
