From 721d249e314b0591274436594be56805bf5a2822 Mon Sep 17 00:00:00 2001 From: Luiz Augusto von Dentz Date: Thu, 6 Dec 2007 14:42:41 +0000 Subject: Fixes for hsp. --- audio/pcm_bluetooth.c | 59 ++++++++++++++++++++---- audio/unix.c | 123 +++++++++++++++++++++++++++++--------------------- 2 files changed, 121 insertions(+), 61 deletions(-) diff --git a/audio/pcm_bluetooth.c b/audio/pcm_bluetooth.c index 6f67ca57..b0e3838b 100644 --- a/audio/pcm_bluetooth.c +++ b/audio/pcm_bluetooth.c @@ -422,6 +422,49 @@ static int bluetooth_prepare(snd_pcm_ioplug_t *io) return write(data->pipefd[1], &c, 1); } +static int bluetooth_hsp_hw_params(snd_pcm_ioplug_t *io, + snd_pcm_hw_params_t *params) +{ + struct bluetooth_data *data = io->private_data; + char buf[BT_AUDIO_IPC_PACKET_SIZE]; + bt_audio_rsp_msg_header_t *rsp_hdr = (void*) buf; + struct bt_setconfiguration_req *setconf_req = (void*) buf; + struct bt_setconfiguration_rsp *setconf_rsp = (void*) buf; + int err; + + DBG("Preparing with io->period_size=%lu io->buffer_size=%lu", + io->period_size, io->buffer_size); + + memset(setconf_req, 0, BT_AUDIO_IPC_PACKET_SIZE); + setconf_req->h.msg_type = BT_SETCONFIGURATION_REQ; + strncpy(setconf_req->device, data->alsa_config.device, 18); + setconf_req->transport = BT_CAPABILITIES_TRANSPORT_SCO; + setconf_req->access_mode = (io->stream == SND_PCM_STREAM_PLAYBACK ? + BT_CAPABILITIES_ACCESS_MODE_WRITE : + BT_CAPABILITIES_ACCESS_MODE_READ); + + err = audioservice_send(data->server.fd, &setconf_req->h); + if (err < 0) + return err; + + err = audioservice_expect(data->server.fd, &rsp_hdr->msg_h, + BT_SETCONFIGURATION_RSP); + if (err < 0) + return err; + + if (rsp_hdr->posix_errno != 0) { + SNDERR("BT_SETCONFIGURATION failed : %s(%d)", + strerror(rsp_hdr->posix_errno), + rsp_hdr->posix_errno); + return -rsp_hdr->posix_errno; + } + + data->transport = setconf_rsp->transport; + data->link_mtu = setconf_rsp->link_mtu; + + return 0; +} + static uint8_t default_bitpool(uint8_t freq, uint8_t mode) { switch (freq) { @@ -565,6 +608,8 @@ static int bluetooth_a2dp_hw_params(snd_pcm_ioplug_t *io, memset(setconf_req, 0, BT_AUDIO_IPC_PACKET_SIZE); setconf_req->h.msg_type = BT_SETCONFIGURATION_REQ; + strncpy(setconf_req->device, data->alsa_config.device, 18); + setconf_req->transport = BT_CAPABILITIES_TRANSPORT_A2DP; setconf_req->sbc_capabilities = active_capabilities; setconf_req->access_mode = (io->stream == SND_PCM_STREAM_PLAYBACK ? BT_CAPABILITIES_ACCESS_MODE_WRITE : @@ -762,7 +807,7 @@ static snd_pcm_sframes_t bluetooth_hsp_read(snd_pcm_ioplug_t *io, /* Increment hardware transmition pointer */ data->hw_ptr = (data->hw_ptr + data->link_mtu / frame_size) % - io->buffer_size; + io->buffer_size; proceed: buff = (unsigned char *) areas->addr + @@ -1020,6 +1065,7 @@ static snd_pcm_ioplug_callback_t bluetooth_hsp_playback = { .stop = bluetooth_playback_stop, .pointer = bluetooth_pointer, .close = bluetooth_close, + .hw_params = bluetooth_hsp_hw_params, .prepare = bluetooth_prepare, .transfer = bluetooth_hsp_write, .poll_descriptors = bluetooth_playback_poll_descriptors, @@ -1032,6 +1078,7 @@ static snd_pcm_ioplug_callback_t bluetooth_hsp_capture = { .stop = bluetooth_stop, .pointer = bluetooth_pointer, .close = bluetooth_close, + .hw_params = bluetooth_hsp_hw_params, .prepare = bluetooth_prepare, .transfer = bluetooth_hsp_read, .poll_descriptors = bluetooth_poll_descriptors, @@ -1467,11 +1514,7 @@ static int bluetooth_init(struct bluetooth_data *data, snd_pcm_stream_t stream, getcaps_req->transport = alsa_conf->transport; else getcaps_req->transport = BT_CAPABILITIES_TRANSPORT_ANY; -/* - getcaps_req->access_mode = (stream == SND_PCM_STREAM_PLAYBACK ? - BT_CAPABILITIES_ACCESS_MODE_WRITE : - BT_CAPABILITIES_ACCESS_MODE_READ); -*/ + err = audioservice_send(data->server.fd, &getcaps_req->h); if (err < 0) goto failed; @@ -1488,9 +1531,7 @@ static int bluetooth_init(struct bluetooth_data *data, snd_pcm_stream_t stream, } data->transport = getcaps_rsp->transport; -/* - data->link_mtu = getcaps_rsp->link_mtu; -*/ + if (getcaps_rsp->transport == BT_CAPABILITIES_TRANSPORT_A2DP) data->a2dp.sbc_capabilities = getcaps_rsp->sbc_capabilities; diff --git a/audio/unix.c b/audio/unix.c index 8267e895..442dca79 100644 --- a/audio/unix.c +++ b/audio/unix.c @@ -216,55 +216,34 @@ static void stream_state_changed(struct avdtp_stream *stream, break; } } -/* + static void headset_discovery_complete(struct 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; - struct headset_data *hs = &client->d.hs; client->req_id = 0; - if (!dev) { - unix_ipc_error(client, BT_GETCAPABILITIES_RSP, EIO); - client->dev = NULL; - return; - } - - switch (client->access_mode) { - case BT_CAPABILITIES_ACCESS_MODE_READ: - hs->lock = HEADSET_LOCK_READ; - break; - case BT_CAPABILITIES_ACCESS_MODE_WRITE: - hs->lock = HEADSET_LOCK_WRITE; - break; - case BT_CAPABILITIES_ACCESS_MODE_READWRITE: - hs->lock = HEADSET_LOCK_READ | HEADSET_LOCK_WRITE; - break; - default: - hs->lock = 0; - break; - } - - if (!headset_lock(dev, hs->lock)) { - error("Unable to lock headset"); - unix_ipc_error(client, BT_GETCAPABILITIES_RSP, EIO); - client->dev = NULL; - return; - } + if (!dev) + goto failed; memset(buf, 0, sizeof(buf)); - rsp->h.msg_type = BT_GETCAPABILITIES_RSP; + rsp->rsp_h.msg_h.msg_type = BT_GETCAPABILITIES_RSP; rsp->transport = BT_CAPABILITIES_TRANSPORT_SCO; rsp->sampling_rate = 8000; - 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("discovery failed"); + unix_ipc_error(client, BT_SETCONFIGURATION_RSP, EIO); + client->dev = NULL; } -*/ + static void headset_setup_complete(struct device *dev, void *user_data) { struct unix_client *client = user_data; @@ -274,11 +253,8 @@ static void headset_setup_complete(struct device *dev, void *user_data) client->req_id = 0; - if (!dev) { - unix_ipc_error(client, BT_GETCAPABILITIES_RSP, EIO); - client->dev = NULL; - return; - } + if (!dev) + goto failed; switch (client->access_mode) { case BT_CAPABILITIES_ACCESS_MODE_READ: @@ -297,9 +273,7 @@ static void headset_setup_complete(struct device *dev, void *user_data) if (!headset_lock(dev, hs->lock)) { error("Unable to lock headset"); - unix_ipc_error(client, BT_GETCAPABILITIES_RSP, EIO); - client->dev = NULL; - return; + goto failed; } memset(buf, 0, sizeof(buf)); @@ -307,10 +281,55 @@ static void headset_setup_complete(struct device *dev, void *user_data) rsp->rsp_h.msg_h.msg_type = BT_SETCONFIGURATION_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); + + return; + +failed: + error("config failed"); + unix_ipc_error(client, BT_SETCONFIGURATION_RSP, EIO); + client->dev = NULL; +} + +static void headset_resume_complete(struct 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; + + client->req_id = 0; + + if (!dev) + goto failed; + + memset(buf, 0, sizeof(buf)); + + rsp->rsp_h.msg_h.msg_type = BT_STREAMSTART_RSP; + + unix_ipc_sendmsg(client, &rsp->rsp_h.msg_h); + + memset(buf, 0, sizeof(buf)); + ind->h.msg_type = BT_STREAMFD_IND; + unix_ipc_sendmsg(client, &ind->h); + + client->data_fd = headset_get_sco_fd(dev); + + if (unix_sendmsg_fd(client->sock, client->data_fd) < 0) { + error("unix_sendmsg_fd: %s(%d)", strerror(errno), errno); + goto failed; + } + + return; + +failed: + error("resume failed"); + unix_ipc_error(client, BT_STREAMSTART_RSP, EIO); + client->dev = NULL; } static void a2dp_discovery_complete(struct avdtp *session, GSList *seps, @@ -421,7 +440,7 @@ static void a2dp_config_complete(struct avdtp *session, struct a2dp_sep *sep, return; failed: - error("setup failed"); + error("config failed"); if (a2dp->sep) { a2dp_sep_unlock(a2dp->sep, a2dp->session); @@ -511,7 +530,6 @@ failed: static void start_discovery(struct device *dev, struct unix_client *client) { struct a2dp_data *a2dp; - unsigned int id; int err = 0; client->type = select_service(dev, client->interface); @@ -535,8 +553,7 @@ static void start_discovery(struct device *dev, struct unix_client *client) break; case TYPE_HEADSET: - id = headset_request_stream(dev, headset_setup_complete, client); - client->cancel = headset_cancel_stream; + headset_discovery_complete(dev, client); break; default: @@ -544,6 +561,8 @@ static void start_discovery(struct device *dev, struct unix_client *client) goto failed; } + client->dev = dev; + return; failed: @@ -625,11 +644,16 @@ static void start_resume(struct device *dev, struct unix_client *client) id = a2dp_source_resume(a2dp->session, a2dp->sep, a2dp_resume_complete, client); client->cancel = a2dp_source_cancel; + + if (id == 0) { + error("resume failed"); + goto failed; + } + break; case TYPE_HEADSET: - id = headset_request_stream(dev, headset_setup_complete, client); - client->cancel = headset_cancel_stream; + headset_resume_complete(dev, client); break; default: @@ -637,11 +661,6 @@ static void start_resume(struct device *dev, struct unix_client *client) goto failed; } - if (id == 0) { - error("resume failed"); - goto failed; - } - return; failed: -- cgit