From 071b3e7fc5a89ddc1c7d51ca5854aa661e4cc33b Mon Sep 17 00:00:00 2001 From: Luiz Augusto von Dentz Date: Wed, 25 Mar 2009 17:57:19 -0300 Subject: Update ipc to match new message headers introduced on BlueZ 4.34. --- src/modules/bluetooth/ipc.c | 1 + src/modules/bluetooth/ipc.h | 73 ++++++++++++++++++++----- 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 #include -#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 */ -- cgit