diff options
-rw-r--r-- | audio/ipc.c | 49 | ||||
-rw-r--r-- | audio/ipc.h | 190 | ||||
-rw-r--r-- | audio/unix.c | 361 |
3 files changed, 345 insertions, 255 deletions
diff --git a/audio/ipc.c b/audio/ipc.c index a4561f47..67785309 100644 --- a/audio/ipc.c +++ b/audio/ipc.c @@ -22,22 +22,26 @@ #include "ipc.h" -/* This table contains the string representation for messages */ -static const char *strmsg[] = { - "BT_GETCAPABILITIES_REQ", - "BT_GETCAPABILITIES_RSP", - "BT_SETCONFIGURATION_REQ", - "BT_SETCONFIGURATION_RSP", - "BT_STREAMSTART_REQ", - "BT_STREAMSTART_RSP", - "BT_STREAMSTOP_REQ", - "BT_STREAMSTOP_RSP", - "BT_STREAMSUSPEND_IND", - "BT_STREAMRESUME_IND", - "BT_CONTROL_REQ", - "BT_CONTROL_RSP", - "BT_CONTROL_IND", - "BT_STREAMFD_IND", +#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) + +/* This table contains the string representation for messages types */ +static const char *strtypes[] = { + "BT_REQUEST", + "BT_RESPONSE", + "BT_INDICATION", + "BT_ERROR", +}; + +/* This table contains the string representation for messages names */ +static const char *strnames[] = { + "BT_GET_CAPABILITIES", + "BT_SET_CONFIGURATION", + "BT_NEW_STREAM", + "BT_START_STREAM", + "BT_STOP_STREAM", + "BT_SUSPEND_STREAM", + "BT_RESUME_STREAM", + "BT_CONTROL", }; int bt_audio_service_open(void) @@ -109,11 +113,18 @@ int bt_audio_service_get_data_fd(int sk) return -1; } -const char *bt_audio_strmsg(int type) +const char *bt_audio_strtype(uint8_t type) { - if (type < 0 || type > (sizeof(strmsg) / sizeof(strmsg[0]))) + if (type >= ARRAY_SIZE(strtypes)) return NULL; - return strmsg[type]; + return strtypes[type]; } +const char *bt_audio_strname(uint8_t name) +{ + if (name >= ARRAY_SIZE(strnames)) + return NULL; + + return strnames[name]; +} diff --git a/audio/ipc.h b/audio/ipc.h index ae85e727..0e985c3a 100644 --- a/audio/ipc.h +++ b/audio/ipc.h @@ -23,36 +23,36 @@ /* Message sequence chart of streaming sequence for A2DP transport - Audio daemon User - on snd_pcm_open - <--BT_GETCAPABILITIES_REQ + Audio daemon User + on snd_pcm_open + <--BT_GET_CAPABILITIES_REQ - BT_GETCAPABILITIES_RSP--> + BT_GET_CAPABILITIES_RSP--> - on snd_pcm_hw_params - <--BT_SETCONFIGURATION_REQ + on snd_pcm_hw_params + <--BT_SETCONFIGURATION_REQ - BT_SETCONFIGURATION_RSP--> + BT_SET_CONFIGURATION_RSP--> - on snd_pcm_prepare - <--BT_STREAMSTART_REQ + on snd_pcm_prepare + <--BT_START_STREAM_REQ <Moves to streaming state> - BT_STREAMSTART_RSP--> + BT_START_STREAM_RSP--> - BT_STREAMFD_IND --> + BT_NEW_STREAM_IND --> - < streams data > - .......... + < streams data > + .......... - on snd_pcm_drop/snd_pcm_drain + on snd_pcm_drop/snd_pcm_drain - <--BT_STREAMSTOP_REQ + <--BT_STOP_STREAM_REQ <Moves to open state> - BT_STREAMSTOP_RSP--> + BT_STOP_STREAM_RSP--> - on IPC close or appl crash + on IPC close or appl crash <Moves to idle> */ @@ -71,43 +71,36 @@ extern "C" { #include <sys/un.h> #include <errno.h> -#define BT_AUDIO_IPC_PACKET_SIZE 128 +#define BT_SUGGESTED_BUFFER_SIZE 128 #define BT_IPC_SOCKET_NAME "\0/org/bluez/audio" -/* Generic message header definition, except for RSP messages */ +/* Generic message header definition, except for RESPONSE messages */ typedef struct { - uint8_t msg_type; + uint8_t type; + uint8_t name; + uint16_t length; } __attribute__ ((packed)) bt_audio_msg_header_t; -/* Generic message header definition, for all RSP messages */ typedef struct { - bt_audio_msg_header_t msg_h; - uint8_t posix_errno; -} __attribute__ ((packed)) bt_audio_rsp_msg_header_t; - -/* Messages list */ -#define BT_GETCAPABILITIES_REQ 0 -#define BT_GETCAPABILITIES_RSP 1 - -#define BT_SETCONFIGURATION_REQ 2 -#define BT_SETCONFIGURATION_RSP 3 - -#define BT_STREAMSTART_REQ 4 -#define BT_STREAMSTART_RSP 5 - -#define BT_STREAMSTOP_REQ 6 -#define BT_STREAMSTOP_RSP 7 - -#define BT_STREAMSUSPEND_IND 8 -#define BT_STREAMRESUME_IND 9 - -#define BT_CONTROL_REQ 10 -#define BT_CONTROL_RSP 11 -#define BT_CONTROL_IND 12 - -#define BT_STREAMFD_IND 13 - -/* BT_GETCAPABILITIES_REQ */ + bt_audio_msg_header_t h; + uint8_t posix_errno; +} __attribute__ ((packed)) bt_audio_error_t; + +/* Message types */ +#define BT_REQUEST 0 +#define BT_RESPONSE 1 +#define BT_INDICATION 2 +#define BT_ERROR 3 + +/* 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_SUSPEND_STREAM 5 +#define BT_RESUME_STREAM 6 +#define BT_CONTROL 7 #define BT_CAPABILITIES_TRANSPORT_A2DP 0 #define BT_CAPABILITIES_TRANSPORT_SCO 1 @@ -119,19 +112,22 @@ typedef struct { #define BT_FLAG_AUTOCONNECT 1 -struct bt_getcapabilities_req { +struct bt_get_capabilities_req { bt_audio_msg_header_t h; char device[18]; /* Address of the remote Device */ uint8_t transport; /* Requested transport */ uint8_t flags; /* Requested flags */ } __attribute__ ((packed)); -/* BT_GETCAPABILITIES_RSP */ - /** * 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 + #define BT_SBC_SAMPLING_FREQ_16000 (1 << 3) #define BT_SBC_SAMPLING_FREQ_32000 (1 << 2) #define BT_SBC_SAMPLING_FREQ_44100 (1 << 1) @@ -164,7 +160,19 @@ struct bt_getcapabilities_req { #define BT_MPEG_LAYER_2 (1 << 1) #define BT_MPEG_LAYER_3 1 +#define BT_HFP_CODEC_PCM 0x00 + +#define BT_PCM_FLAG_NREC 1 + +typedef struct { + uint8_t transport; + uint8_t type; + uint8_t length; + uint8_t data[0]; +} __attribute__ ((packed)) codec_capabilities_t; + typedef struct { + codec_capabilities_t capability; uint8_t channel_mode; uint8_t frequency; uint8_t allocation_method; @@ -175,6 +183,7 @@ typedef struct { } __attribute__ ((packed)) sbc_capabilities_t; typedef struct { + codec_capabilities_t capability; uint8_t channel_mode; uint8_t crc; uint8_t layer; @@ -183,75 +192,65 @@ typedef struct { uint16_t bitrate; } __attribute__ ((packed)) mpeg_capabilities_t; -struct bt_getcapabilities_rsp { - bt_audio_rsp_msg_header_t rsp_h; - uint8_t transport; /* Granted transport */ - sbc_capabilities_t sbc_capabilities; /* A2DP only */ - mpeg_capabilities_t mpeg_capabilities; /* A2DP only */ - uint16_t sampling_rate; /* SCO only */ +typedef struct { + codec_capabilities_t capability; + uint8_t flags; + uint16_t sampling_rate; +} __attribute__ ((packed)) pcm_capabilities_t; + + +struct bt_get_capabilities_rsp { + bt_audio_msg_header_t h; + uint8_t data[0]; /* First codec_capabilities_t */ } __attribute__ ((packed)); -/* BT_SETCONFIGURATION_REQ */ -struct bt_setconfiguration_req { +struct bt_set_configuration_req { bt_audio_msg_header_t h; - char device[18]; /* Address of the remote Device */ - uint8_t transport; /* Requested transport */ - uint8_t access_mode; /* Requested access mode */ - sbc_capabilities_t sbc_capabilities; /* A2DP only - only one of this field - and next one must be filled */ - mpeg_capabilities_t mpeg_capabilities; /* A2DP only */ + char device[18]; /* Address of the remote Device */ + uint8_t access_mode; /* Requested access mode */ + codec_capabilities_t codec; /* Requested codec */ } __attribute__ ((packed)); -/* BT_SETCONFIGURATION_RSP */ -struct bt_setconfiguration_rsp { - bt_audio_rsp_msg_header_t rsp_h; - uint8_t transport; /* Granted transport */ - uint8_t access_mode; /* Granted access mode */ - uint16_t link_mtu; /* Max length that transport supports */ +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)); -/* BT_STREAMSTART_REQ */ #define BT_STREAM_ACCESS_READ 0 #define BT_STREAM_ACCESS_WRITE 1 #define BT_STREAM_ACCESS_READWRITE 2 -struct bt_streamstart_req { +struct bt_start_stream_req { bt_audio_msg_header_t h; } __attribute__ ((packed)); -/* BT_STREAMSTART_RSP */ -struct bt_streamstart_rsp { - bt_audio_rsp_msg_header_t rsp_h; +struct bt_start_stream_rsp { + bt_audio_msg_header_t h; } __attribute__ ((packed)); -/* BT_STREAMFD_IND */ /* This message is followed by one byte of data containing the stream data fd as ancilliary data */ -struct bt_streamfd_ind { +struct bt_new_stream_ind { bt_audio_msg_header_t h; } __attribute__ ((packed)); -/* BT_STREAMSTOP_REQ */ -struct bt_streamstop_req { +struct bt_stop_stream_req { bt_audio_msg_header_t h; } __attribute__ ((packed)); -/* BT_STREAMSTOP_RSP */ -struct bt_streamstop_rsp { - bt_audio_rsp_msg_header_t rsp_h; +struct bt_stop_stream_rsp { + bt_audio_msg_header_t h; } __attribute__ ((packed)); -/* BT_STREAMSUSPEND_IND */ -struct bt_streamsuspend_ind { +struct bt_suspend_stream_ind { bt_audio_msg_header_t h; } __attribute__ ((packed)); -/* BT_STREAMRESUME_IND */ -struct bt_streamresume_ind { +struct bt_resume_stream_ind { bt_audio_msg_header_t h; } __attribute__ ((packed)); -/* BT_CONTROL_REQ */ - #define BT_CONTROL_KEY_POWER 0x40 #define BT_CONTROL_KEY_VOL_UP 0x41 #define BT_CONTROL_KEY_VOL_DOWN 0x42 @@ -272,14 +271,12 @@ struct bt_control_req { uint8_t key; /* Control Key */ } __attribute__ ((packed)); -/* BT_CONTROL_RSP */ struct bt_control_rsp { - bt_audio_rsp_msg_header_t rsp_h; - uint8_t mode; /* Control Mode */ - uint8_t key; /* Control Key */ + bt_audio_msg_header_t h; + uint8_t mode; /* Control Mode */ + uint8_t key; /* Control Key */ } __attribute__ ((packed)); -/* BT_CONTROL_IND */ struct bt_control_ind { bt_audio_msg_header_t h; uint8_t mode; /* Control Mode */ @@ -299,7 +296,10 @@ BT_STREAMFD_IND message is returned */ int bt_audio_service_get_data_fd(int sk); /* Human readable message type string */ -const char *bt_audio_strmsg(int type); +const char *bt_audio_strtype(uint8_t type); + +/* Human readable message name string */ +const char *bt_audio_strname(uint8_t name); #ifdef __cplusplus } diff --git a/audio/unix.c b/audio/unix.c index 921e15ef..bf0dad47 100644 --- a/audio/unix.c +++ b/audio/unix.c @@ -152,25 +152,31 @@ static int unix_sendmsg_fd(int sock, int fd) static void unix_ipc_sendmsg(struct unix_client *client, const bt_audio_msg_header_t *msg) { - debug("Audio API: sending %s", bt_audio_strmsg(msg->msg_type)); + const char *type = bt_audio_strtype(msg->type); + const char *name = bt_audio_strname(msg->name); - if (send(client->sock, msg, BT_AUDIO_IPC_PACKET_SIZE, 0) < 0) + debug("Audio API: %s -> %s", type, name); + + if (send(client->sock, msg, msg->length, 0) < 0) error("Error %s(%d)", strerror(errno), errno); } -static void unix_ipc_error(struct unix_client *client, int type, int err) +static void unix_ipc_error(struct unix_client *client, uint8_t name, int err) { - char buf[BT_AUDIO_IPC_PACKET_SIZE]; - bt_audio_rsp_msg_header_t *rsp_hdr = (void *) buf; + char buf[BT_SUGGESTED_BUFFER_SIZE]; + bt_audio_error_t *rsp = (void *) buf; if (!g_slist_find(clients, client)) return; memset(buf, 0, sizeof(buf)); - rsp_hdr->msg_h.msg_type = type; - rsp_hdr->posix_errno = err; + rsp->h.type = BT_ERROR; + rsp->h.name = name; + rsp->h.length = sizeof(*rsp); + + rsp->posix_errno = err; - unix_ipc_sendmsg(client, &rsp_hdr->msg_h); + unix_ipc_sendmsg(client, &rsp->h); } static service_type_t select_service(struct audio_device *dev, const char *interface) @@ -223,8 +229,10 @@ static void stream_state_changed(struct avdtp_stream *stream, static void headset_discovery_complete(struct audio_device *dev, void *user_data) { struct unix_client *client = user_data; - char buf[BT_AUDIO_IPC_PACKET_SIZE]; - struct bt_getcapabilities_rsp *rsp = (void *) buf; + char buf[BT_SUGGESTED_BUFFER_SIZE]; + struct bt_get_capabilities_rsp *rsp = (void *) buf; + codec_capabilities_t *codec; + pcm_capabilities_t *pcm; client->req_id = 0; @@ -233,24 +241,34 @@ static void headset_discovery_complete(struct audio_device *dev, void *user_data memset(buf, 0, sizeof(buf)); - rsp->rsp_h.msg_h.msg_type = BT_GETCAPABILITIES_RSP; - rsp->transport = BT_CAPABILITIES_TRANSPORT_SCO; - rsp->sampling_rate = 8000; + codec = (void *) rsp->data; + codec->transport = BT_CAPABILITIES_TRANSPORT_SCO; + codec->type = BT_HFP_CODEC_PCM; + codec->length = sizeof(*pcm); + + pcm = (void *) codec; + pcm->sampling_rate = 8000; + if (headset_get_nrec(dev)) + pcm->flags |= BT_PCM_FLAG_NREC; + + rsp->h.type = BT_RESPONSE; + rsp->h.name = BT_GET_CAPABILITIES; + rsp->h.length = sizeof(*rsp) + codec->length; - unix_ipc_sendmsg(client, &rsp->rsp_h.msg_h); + unix_ipc_sendmsg(client, &rsp->h); return; failed: error("discovery failed"); - unix_ipc_error(client, BT_SETCONFIGURATION_RSP, EIO); + unix_ipc_error(client, BT_SET_CONFIGURATION, EIO); } static void headset_setup_complete(struct audio_device *dev, void *user_data) { struct unix_client *client = user_data; - char buf[BT_AUDIO_IPC_PACKET_SIZE]; - struct bt_setconfiguration_rsp *rsp = (void *) buf; + char buf[BT_SUGGESTED_BUFFER_SIZE]; + struct bt_set_configuration_rsp *rsp = (void *) buf; client->req_id = 0; @@ -259,28 +277,31 @@ static void headset_setup_complete(struct audio_device *dev, void *user_data) memset(buf, 0, sizeof(buf)); - rsp->rsp_h.msg_h.msg_type = BT_SETCONFIGURATION_RSP; + rsp->h.type = BT_RESPONSE; + rsp->h.name = BT_SET_CONFIGURATION; + rsp->h.length = sizeof(*rsp); + rsp->transport = BT_CAPABILITIES_TRANSPORT_SCO; rsp->access_mode = client->access_mode; rsp->link_mtu = 48; client->data_fd = headset_get_sco_fd(dev); - unix_ipc_sendmsg(client, &rsp->rsp_h.msg_h); + unix_ipc_sendmsg(client, &rsp->h); return; failed: error("config failed"); - unix_ipc_error(client, BT_SETCONFIGURATION_RSP, EIO); + unix_ipc_error(client, BT_SET_CONFIGURATION, EIO); } static void headset_resume_complete(struct audio_device *dev, void *user_data) { struct unix_client *client = user_data; - char buf[BT_AUDIO_IPC_PACKET_SIZE]; - struct bt_streamstart_rsp *rsp = (void *) buf; - struct bt_streamfd_ind *ind = (void *) buf; + char buf[BT_SUGGESTED_BUFFER_SIZE]; + struct bt_start_stream_rsp *rsp = (void *) buf; + struct bt_new_stream_ind *ind = (void *) buf; struct headset_data *hs = &client->d.hs; client->req_id = 0; @@ -294,13 +315,17 @@ static void headset_resume_complete(struct audio_device *dev, void *user_data) } memset(buf, 0, sizeof(buf)); + rsp->h.type = BT_RESPONSE; + rsp->h.name = BT_START_STREAM; + rsp->h.length = sizeof(*rsp); - rsp->rsp_h.msg_h.msg_type = BT_STREAMSTART_RSP; - - unix_ipc_sendmsg(client, &rsp->rsp_h.msg_h); + unix_ipc_sendmsg(client, &rsp->h); memset(buf, 0, sizeof(buf)); - ind->h.msg_type = BT_STREAMFD_IND; + ind->h.type = BT_INDICATION; + ind->h.name = BT_NEW_STREAM; + ind->h.length = sizeof(*ind); + unix_ipc_sendmsg(client, &ind->h); client->data_fd = headset_get_sco_fd(dev); @@ -315,41 +340,105 @@ static void headset_resume_complete(struct audio_device *dev, void *user_data) failed: error("headset_resume_complete: resume failed"); - unix_ipc_error(client, BT_STREAMSTART_RSP, EIO); + unix_ipc_error(client, BT_START_STREAM, EIO); } static void headset_suspend_complete(struct audio_device *dev, void *user_data) { struct unix_client *client = user_data; - char buf[BT_AUDIO_IPC_PACKET_SIZE]; - struct bt_streamstart_rsp *rsp = (void *) buf; + char buf[BT_SUGGESTED_BUFFER_SIZE]; + struct bt_start_stream_rsp *rsp = (void *) buf; if (!dev) goto failed; memset(buf, 0, sizeof(buf)); - rsp->rsp_h.msg_h.msg_type = BT_STREAMSTOP_RSP; - rsp->rsp_h.posix_errno = 0; - unix_ipc_sendmsg(client, &rsp->rsp_h.msg_h); + rsp->h.type = BT_RESPONSE; + rsp->h.name = BT_STOP_STREAM; + rsp->h.length = sizeof(*rsp); + + unix_ipc_sendmsg(client, &rsp->h); return; failed: error("suspend failed"); - unix_ipc_error(client, BT_STREAMSTOP_RSP, EIO); + unix_ipc_error(client, BT_STOP_STREAM, EIO); client->dev = NULL; } +static int a2dp_append_codec(struct bt_get_capabilities_rsp *rsp, + struct avdtp_service_capability *cap) +{ + struct avdtp_media_codec_capability *codec_cap = (void *) cap->data; + codec_capabilities_t *codec = (void *) rsp + rsp->h.length; + int space_left = BT_SUGGESTED_BUFFER_SIZE - rsp->h.length; + + if (space_left <= 0) + return -ENOMEM; + + /* endianess prevent direct cast */ + if (codec_cap->media_codec_type == A2DP_CODEC_SBC) { + struct sbc_codec_cap *sbc_cap = (void *) codec_cap; + sbc_capabilities_t *sbc = (void *) codec; + + if (space_left - sizeof(sbc_capabilities_t) < 0) + return -ENOMEM; + + codec->length = sizeof(sbc_capabilities_t); + + sbc->channel_mode = sbc_cap->channel_mode; + sbc->frequency = sbc_cap->frequency; + sbc->allocation_method = sbc_cap->allocation_method; + sbc->subbands = sbc_cap->subbands; + sbc->block_length = sbc_cap->block_length; + sbc->min_bitpool = sbc_cap->min_bitpool; + sbc->max_bitpool = sbc_cap->max_bitpool; + } else if (codec_cap->media_codec_type == A2DP_CODEC_MPEG12) { + struct mpeg_codec_cap *mpeg_cap = (void *) codec_cap; + mpeg_capabilities_t *mpeg = (void *) codec; + + if (space_left - sizeof(mpeg_capabilities_t) < 0) + return -ENOMEM; + + codec->length = sizeof(mpeg_capabilities_t); + + mpeg->channel_mode = mpeg_cap->channel_mode; + mpeg->crc = mpeg_cap->crc; + mpeg->layer = mpeg_cap->layer; + mpeg->frequency = mpeg_cap->frequency; + mpeg->mpf = mpeg_cap->mpf; + mpeg->bitrate = mpeg_cap->bitrate; + } else { + int codec_length; + + codec_length = cap->length - (sizeof(struct avdtp_service_capability) + + sizeof(struct avdtp_media_codec_capability)); + + if (space_left - (codec_length + sizeof(codec_capabilities_t)) < 0) + return -ENOMEM; + + codec->length = codec_length + sizeof(codec_capabilities_t); + memcpy(codec->data, codec_cap->data, codec_length); + } + + codec->type = codec_cap->media_codec_type; + rsp->h.length += codec->length; + + debug("Append codec %d - length %d - total %d", codec->type, + codec->length, rsp->h.length); + + return 0; +} + static void a2dp_discovery_complete(struct avdtp *session, GSList *seps, struct avdtp_error *err, void *user_data) { struct unix_client *client = user_data; - char buf[BT_AUDIO_IPC_PACKET_SIZE]; - struct bt_getcapabilities_rsp *rsp = (void *) buf; + char buf[BT_SUGGESTED_BUFFER_SIZE]; + struct bt_get_capabilities_rsp *rsp = (void *) buf; struct a2dp_data *a2dp = &client->d.a2dp; - struct sbc_codec_cap *sbc_cap = NULL; - struct mpeg_codec_cap *mpeg_cap = NULL; GSList *l; if (!g_slist_find(clients, client)) { @@ -363,55 +452,29 @@ static void a2dp_discovery_complete(struct avdtp *session, GSList *seps, memset(buf, 0, sizeof(buf)); client->req_id = 0; - rsp->rsp_h.msg_h.msg_type = BT_GETCAPABILITIES_RSP; - rsp->transport = BT_CAPABILITIES_TRANSPORT_A2DP; + rsp->h.type = BT_RESPONSE; + rsp->h.name = BT_GET_CAPABILITIES; + rsp->h.length = sizeof(*rsp); for (l = seps; l; l = g_slist_next(l)) { struct avdtp_remote_sep *rsep = l->data; struct avdtp_service_capability *cap; - struct avdtp_media_codec_capability *codec_cap; cap = avdtp_get_codec(rsep); if (cap->category != AVDTP_MEDIA_CODEC) continue; - codec_cap = (void *) cap->data; - - if (codec_cap->media_codec_type == A2DP_CODEC_SBC && !sbc_cap) - sbc_cap = (void *) codec_cap; - - if (codec_cap->media_codec_type == A2DP_CODEC_MPEG12 && !mpeg_cap) - mpeg_cap = (void *) codec_cap; + a2dp_append_codec(rsp, cap); } - /* endianess prevent direct cast */ - if (sbc_cap) { - rsp->sbc_capabilities.channel_mode = sbc_cap->channel_mode; - rsp->sbc_capabilities.frequency = sbc_cap->frequency; - rsp->sbc_capabilities.allocation_method = sbc_cap->allocation_method; - rsp->sbc_capabilities.subbands = sbc_cap->subbands; - rsp->sbc_capabilities.block_length = sbc_cap->block_length; - rsp->sbc_capabilities.min_bitpool = sbc_cap->min_bitpool; - rsp->sbc_capabilities.max_bitpool = sbc_cap->max_bitpool; - } - - if (mpeg_cap) { - rsp->mpeg_capabilities.channel_mode = mpeg_cap->channel_mode; - rsp->mpeg_capabilities.crc = mpeg_cap->crc; - rsp->mpeg_capabilities.layer = mpeg_cap->layer; - rsp->mpeg_capabilities.frequency = mpeg_cap->frequency; - rsp->mpeg_capabilities.mpf = mpeg_cap->mpf; - rsp->mpeg_capabilities.bitrate = mpeg_cap->bitrate; - } - - unix_ipc_sendmsg(client, &rsp->rsp_h.msg_h); + unix_ipc_sendmsg(client, &rsp->h); return; failed: error("discovery failed"); - unix_ipc_error(client, BT_GETCAPABILITIES_RSP, EIO); + unix_ipc_error(client, BT_GET_CAPABILITIES, EIO); avdtp_unref(a2dp->session); @@ -425,8 +488,8 @@ static void a2dp_config_complete(struct avdtp *session, struct a2dp_sep *sep, void *user_data) { struct unix_client *client = user_data; - char buf[BT_AUDIO_IPC_PACKET_SIZE]; - struct bt_setconfiguration_rsp *rsp = (void *) buf; + char buf[BT_SUGGESTED_BUFFER_SIZE]; + struct bt_set_configuration_rsp *rsp = (void *) buf; struct a2dp_data *a2dp = &client->d.a2dp; uint16_t imtu, omtu; GSList *caps; @@ -454,14 +517,17 @@ static void a2dp_config_complete(struct avdtp *session, struct a2dp_sep *sep, goto failed; } - rsp->rsp_h.msg_h.msg_type = BT_SETCONFIGURATION_RSP; + rsp->h.type = BT_RESPONSE; + rsp->h.name = BT_SET_CONFIGURATION; + rsp->h.length = sizeof(*rsp); + rsp->transport = BT_CAPABILITIES_TRANSPORT_A2DP; client->access_mode = BT_CAPABILITIES_ACCESS_MODE_WRITE; rsp->access_mode = client->access_mode; /* FIXME: Use imtu when fd_opt is CFG_FD_OPT_READ */ rsp->link_mtu = omtu; - unix_ipc_sendmsg(client, &rsp->rsp_h.msg_h); + unix_ipc_sendmsg(client, &rsp->h); client->cb_id = avdtp_stream_add_cb(session, stream, stream_state_changed, client); @@ -475,7 +541,7 @@ failed: a2dp_sep_unlock(a2dp->sep, a2dp->session); a2dp->sep = NULL; } - unix_ipc_error(client, BT_SETCONFIGURATION_RSP, EIO); + unix_ipc_error(client, BT_SET_CONFIGURATION, EIO); avdtp_unref(a2dp->session); @@ -487,21 +553,26 @@ static void a2dp_resume_complete(struct avdtp *session, struct avdtp_error *err, void *user_data) { struct unix_client *client = user_data; - char buf[BT_AUDIO_IPC_PACKET_SIZE]; - struct bt_streamstart_rsp *rsp = (void *) buf; - struct bt_streamfd_ind *ind = (void *) buf; + char buf[BT_SUGGESTED_BUFFER_SIZE]; + struct bt_start_stream_rsp *rsp = (void *) buf; + struct bt_new_stream_ind *ind = (void *) buf; struct a2dp_data *a2dp = &client->d.a2dp; if (err) goto failed; memset(buf, 0, sizeof(buf)); - rsp->rsp_h.msg_h.msg_type = BT_STREAMSTART_RSP; - rsp->rsp_h.posix_errno = 0; - unix_ipc_sendmsg(client, &rsp->rsp_h.msg_h); + rsp->h.type = BT_RESPONSE; + rsp->h.name = BT_START_STREAM; + rsp->h.length = sizeof(*rsp); + + unix_ipc_sendmsg(client, &rsp->h); memset(buf, 0, sizeof(buf)); - ind->h.msg_type = BT_STREAMFD_IND; + ind->h.type = BT_RESPONSE; + ind->h.name = BT_NEW_STREAM; + rsp->h.length = sizeof(*ind); + unix_ipc_sendmsg(client, &ind->h); if (unix_sendmsg_fd(client->sock, client->data_fd) < 0) { @@ -518,7 +589,7 @@ failed: a2dp_sep_unlock(a2dp->sep, a2dp->session); a2dp->sep = NULL; } - unix_ipc_error(client, BT_STREAMSTART_RSP, EIO); + unix_ipc_error(client, BT_START_STREAM, EIO); if (client->cb_id > 0) { avdtp_stream_remove_cb(a2dp->session, a2dp->stream, @@ -536,17 +607,19 @@ static void a2dp_suspend_complete(struct avdtp *session, struct avdtp_error *err, void *user_data) { struct unix_client *client = user_data; - char buf[BT_AUDIO_IPC_PACKET_SIZE]; - struct bt_streamstart_rsp *rsp = (void *) buf; + char buf[BT_SUGGESTED_BUFFER_SIZE]; + struct bt_start_stream_rsp *rsp = (void *) buf; struct a2dp_data *a2dp = &client->d.a2dp; if (err) goto failed; memset(buf, 0, sizeof(buf)); - rsp->rsp_h.msg_h.msg_type = BT_STREAMSTOP_RSP; - rsp->rsp_h.posix_errno = 0; - unix_ipc_sendmsg(client, &rsp->rsp_h.msg_h); + rsp->h.type = BT_RESPONSE; + rsp->h.name = BT_STOP_STREAM; + rsp->h.length = sizeof(*rsp); + + unix_ipc_sendmsg(client, &rsp->h); return; @@ -557,7 +630,7 @@ failed: a2dp_sep_unlock(a2dp->sep, a2dp->session); a2dp->sep = NULL; } - unix_ipc_error(client, BT_STREAMSTOP_RSP, EIO); + unix_ipc_error(client, BT_STOP_STREAM, EIO); avdtp_unref(a2dp->session); @@ -604,7 +677,7 @@ static void start_discovery(struct audio_device *dev, struct unix_client *client return; failed: - unix_ipc_error(client, BT_GETCAPABILITIES_RSP, err ? : EIO); + unix_ipc_error(client, BT_GET_CAPABILITIES, err ? : EIO); } static void start_config(struct audio_device *dev, struct unix_client *client) @@ -671,7 +744,7 @@ static void start_config(struct audio_device *dev, struct unix_client *client) return; failed: - unix_ipc_error(client, BT_SETCONFIGURATION_RSP, EIO); + unix_ipc_error(client, BT_SET_CONFIGURATION, EIO); } static void start_resume(struct audio_device *dev, struct unix_client *client) @@ -726,7 +799,7 @@ static void start_resume(struct audio_device *dev, struct unix_client *client) return; failed: - unix_ipc_error(client, BT_STREAMSTART_RSP, EIO); + unix_ipc_error(client, BT_START_STREAM, EIO); } static void start_suspend(struct audio_device *dev, struct unix_client *client) @@ -780,11 +853,11 @@ static void start_suspend(struct audio_device *dev, struct unix_client *client) return; failed: - unix_ipc_error(client, BT_STREAMSTOP_RSP, EIO); + unix_ipc_error(client, BT_STOP_STREAM, EIO); } static void handle_getcapabilities_req(struct unix_client *client, - struct bt_getcapabilities_req *req) + struct bt_get_capabilities_req *req) { struct audio_device *dev; bdaddr_t bdaddr; @@ -820,11 +893,11 @@ static void handle_getcapabilities_req(struct unix_client *client, return; failed: - unix_ipc_error(client, BT_GETCAPABILITIES_RSP, EIO); + unix_ipc_error(client, BT_GET_CAPABILITIES, EIO); } static int handle_sco_transport(struct unix_client *client, - struct bt_setconfiguration_req *req) + struct bt_set_configuration_req *req) { client->interface = g_strdup(AUDIO_HEADSET_INTERFACE); @@ -835,7 +908,7 @@ static int handle_sco_transport(struct unix_client *client, } static int handle_a2dp_transport(struct unix_client *client, - struct bt_setconfiguration_req *req) + struct bt_set_configuration_req *req) { struct avdtp_service_capability *media_transport, *media_codec; struct sbc_codec_cap sbc_cap; @@ -856,18 +929,19 @@ static int handle_a2dp_transport(struct unix_client *client, debug("config a2dp - device = %s access_mode = %u", req->device, req->access_mode); - if (req->mpeg_capabilities.frequency) { + if (req->codec.type == BT_A2DP_CODEC_MPEG12) { + mpeg_capabilities_t *mpeg = (void *) &req->codec; memset(&mpeg_cap, 0, sizeof(mpeg_cap)); mpeg_cap.cap.media_type = AVDTP_MEDIA_TYPE_AUDIO; mpeg_cap.cap.media_codec_type = A2DP_CODEC_MPEG12; - mpeg_cap.channel_mode = req->mpeg_capabilities.channel_mode; - mpeg_cap.crc = req->mpeg_capabilities.crc; - mpeg_cap.layer = req->mpeg_capabilities.layer; - mpeg_cap.frequency = req->mpeg_capabilities.frequency; - mpeg_cap.mpf = req->mpeg_capabilities.mpf; - mpeg_cap.bitrate = req->mpeg_capabilities.bitrate; + mpeg_cap.channel_mode = mpeg->channel_mode; + mpeg_cap.crc = mpeg->crc; + mpeg_cap.layer = mpeg->layer; + mpeg_cap.frequency = mpeg->frequency; + mpeg_cap.mpf = mpeg->mpf; + mpeg_cap.bitrate = mpeg->bitrate; media_codec = avdtp_service_cap_new(AVDTP_MEDIA_CODEC, &mpeg_cap, sizeof(mpeg_cap)); @@ -877,18 +951,20 @@ static int handle_a2dp_transport(struct unix_client *client, mpeg_cap.frequency, mpeg_cap.channel_mode, mpeg_cap.layer, mpeg_cap.crc, mpeg_cap.mpf, mpeg_cap.bitrate); - } else if (req->sbc_capabilities.frequency) { + } else if (req->codec.type == BT_A2DP_CODEC_SBC) { + sbc_capabilities_t *sbc = (void *) &req->codec; + memset(&sbc_cap, 0, sizeof(sbc_cap)); sbc_cap.cap.media_type = AVDTP_MEDIA_TYPE_AUDIO; sbc_cap.cap.media_codec_type = A2DP_CODEC_SBC; - sbc_cap.channel_mode = req->sbc_capabilities.channel_mode; - sbc_cap.frequency = req->sbc_capabilities.frequency; - sbc_cap.allocation_method = req->sbc_capabilities.allocation_method; - sbc_cap.subbands = req->sbc_capabilities.subbands; - sbc_cap.block_length = req->sbc_capabilities.block_length; - sbc_cap.min_bitpool = req->sbc_capabilities.min_bitpool; - sbc_cap.max_bitpool = req->sbc_capabilities.max_bitpool; + sbc_cap.channel_mode = sbc->channel_mode; + sbc_cap.frequency = sbc->frequency; + sbc_cap.allocation_method = sbc->allocation_method; + sbc_cap.subbands = sbc->subbands; + sbc_cap.block_length = sbc->block_length; + sbc_cap.min_bitpool = sbc->min_bitpool; + sbc_cap.max_bitpool = sbc->max_bitpool; media_codec = avdtp_service_cap_new(AVDTP_MEDIA_CODEC, &sbc_cap, sizeof(sbc_cap)); @@ -908,7 +984,7 @@ static int handle_a2dp_transport(struct unix_client *client, } static void handle_setconfiguration_req(struct unix_client *client, - struct bt_setconfiguration_req *req) + struct bt_set_configuration_req *req) { struct audio_device *dev; bdaddr_t bdaddr; @@ -926,13 +1002,13 @@ static void handle_setconfiguration_req(struct unix_client *client, client->interface = NULL; } - if (req->transport == BT_CAPABILITIES_TRANSPORT_SCO) { + if (req->codec.transport == BT_CAPABILITIES_TRANSPORT_SCO) { err = handle_sco_transport(client, req); if (err < 0) { err = -err; goto failed; } - } else if (req->transport == BT_CAPABILITIES_TRANSPORT_A2DP) { + } else if (req->codec.transport == BT_CAPABILITIES_TRANSPORT_A2DP) { err = handle_a2dp_transport(client, req); if (err < 0) { err = -err; @@ -957,11 +1033,11 @@ static void handle_setconfiguration_req(struct unix_client *client, return; failed: - unix_ipc_error(client, BT_SETCONFIGURATION_RSP, err ? : EIO); + unix_ipc_error(client, BT_SET_CONFIGURATION, err ? : EIO); } static void handle_streamstart_req(struct unix_client *client, - struct bt_streamstart_req *req) + struct bt_start_stream_req *req) { if (!client->dev) goto failed; @@ -971,11 +1047,11 @@ static void handle_streamstart_req(struct unix_client *client, return; failed: - unix_ipc_error(client, BT_STREAMSTART_REQ, EIO); + unix_ipc_error(client, BT_START_STREAM, EIO); } static void handle_streamstop_req(struct unix_client *client, - struct bt_streamstop_req *req) + struct bt_stop_stream_req *req) { if (!client->dev) goto failed; @@ -985,32 +1061,33 @@ static void handle_streamstop_req(struct unix_client *client, return; failed: - unix_ipc_error(client, BT_STREAMSTOP_REQ, EIO); + unix_ipc_error(client, BT_STOP_STREAM, EIO); } static void handle_control_req(struct unix_client *client, struct bt_control_req *req) { /* FIXME: really implement that */ - char buf[BT_AUDIO_IPC_PACKET_SIZE]; - struct bt_setconfiguration_rsp *rsp = (void *) buf; + char buf[BT_SUGGESTED_BUFFER_SIZE]; + struct bt_set_configuration_rsp *rsp = (void *) buf; memset(buf, 0, sizeof(buf)); - rsp->rsp_h.msg_h.msg_type = BT_CONTROL_RSP; - rsp->rsp_h.posix_errno = 0; + rsp->h.type = BT_RESPONSE; + rsp->h.name = BT_CONTROL; + rsp->h.length = sizeof(*rsp); - unix_ipc_sendmsg(client, &rsp->rsp_h.msg_h); + unix_ipc_sendmsg(client, &rsp->h); } static gboolean client_cb(GIOChannel *chan, GIOCondition cond, gpointer data) { - char buf[BT_AUDIO_IPC_PACKET_SIZE]; + char buf[BT_SUGGESTED_BUFFER_SIZE]; bt_audio_msg_header_t *msghdr = (void *) buf; struct unix_client *client = data; int len; struct a2dp_data *a2dp = &client->d.a2dp; struct headset_data *hs = &client->d.hs; - const char *type; + const char *type, *name; if (cond & G_IO_NVAL) return FALSE; @@ -1046,33 +1123,35 @@ static gboolean client_cb(GIOChannel *chan, GIOCondition cond, gpointer data) goto failed; } - if ((type = bt_audio_strmsg(msghdr->msg_type))) - debug("Audio API: received %s", type); + type = bt_audio_strtype(msghdr->type); + name = bt_audio_strname(msghdr->name); + + debug("Audio API: %s <- %s", type, name); - switch (msghdr->msg_type) { - case BT_GETCAPABILITIES_REQ: + switch (msghdr->name) { + case BT_GET_CAPABILITIES: handle_getcapabilities_req(client, - (struct bt_getcapabilities_req *) msghdr); + (struct bt_get_capabilities_req *) msghdr); break; - case BT_SETCONFIGURATION_REQ: + case BT_SET_CONFIGURATION: handle_setconfiguration_req(client, - (struct bt_setconfiguration_req *) msghdr); + (struct bt_set_configuration_req *) msghdr); break; - case BT_STREAMSTART_REQ: + case BT_START_STREAM: handle_streamstart_req(client, - (struct bt_streamstart_req *) msghdr); + (struct bt_start_stream_req *) msghdr); break; - case BT_STREAMSTOP_REQ: + case BT_STOP_STREAM: handle_streamstop_req(client, - (struct bt_streamstop_req *) msghdr); + (struct bt_stop_stream_req *) msghdr); break; - case BT_CONTROL_REQ: + case BT_CONTROL: handle_control_req(client, (struct bt_control_req *) msghdr); break; default: - error("Audio API: received unexpected packet type %d", - msghdr->msg_type); + error("Audio API: received unexpected message name %d", + msghdr->name); } return TRUE; |