summaryrefslogtreecommitdiffstats
path: root/audio/unix.c
diff options
context:
space:
mode:
Diffstat (limited to 'audio/unix.c')
-rw-r--r--audio/unix.c581
1 files changed, 458 insertions, 123 deletions
diff --git a/audio/unix.c b/audio/unix.c
index ea96bd4f..c321b99b 100644
--- a/audio/unix.c
+++ b/audio/unix.c
@@ -71,7 +71,7 @@ struct headset_data {
struct unix_client {
struct device *dev;
- struct avdtp_service_capability *media_codec;
+ GSList *caps;
service_type_t type;
char *interface;
union {
@@ -83,18 +83,13 @@ struct unix_client {
int data_fd; /* To be deleted once two phase configuration is fully implemented */
unsigned int req_id;
unsigned int cb_id;
- gboolean (*cancel_stream) (struct device *dev, unsigned int id);
+ gboolean (*cancel) (struct device *dev, unsigned int id);
};
static GSList *clients = NULL;
static int unix_sock = -1;
-static void unix_ipc_sendmsg(struct unix_client *client,
- const bt_audio_msg_header_t *msg);
-
-static void send_getcapabilities_rsp_error(struct unix_client *client, int err);
-
static void client_free(struct unix_client *client)
{
struct a2dp_data *a2dp;
@@ -118,8 +113,10 @@ static void client_free(struct unix_client *client)
if (client->sock >= 0)
close(client->sock);
- if (client->media_codec)
- g_free(client->media_codec);
+ if (client->caps) {
+ g_slist_foreach(client->caps, (GFunc) g_free, NULL);
+ g_slist_free(client->caps);
+ }
g_free(client->interface);
g_free(client);
@@ -152,6 +149,27 @@ static int unix_sendmsg_fd(int sock, int fd)
return sendmsg(sock, &msgh, MSG_NOSIGNAL);
}
+static void unix_ipc_sendmsg(struct unix_client *client,
+ const bt_audio_msg_header_t *msg)
+{
+ info("Audio API: sending %s", bt_audio_strmsg(msg->msg_type));
+
+ if (send(client->sock, msg, BT_AUDIO_IPC_PACKET_SIZE, 0) < 0)
+ error("Error %s(%d)", strerror(errno), errno);
+}
+
+static void unix_ipc_error(struct unix_client *client, int type, int err)
+{
+ char buf[BT_AUDIO_IPC_PACKET_SIZE];
+ struct bt_getcapabilities_rsp *rsp = (void *) buf;
+
+ memset(buf, 0, sizeof(buf));
+ rsp->h.msg_type = type;
+ rsp->posix_errno = err;
+
+ unix_ipc_sendmsg(client, &rsp->h);
+}
+
static service_type_t select_service(struct device *dev, const char *interface)
{
if (!interface) {
@@ -198,8 +216,8 @@ static void stream_state_changed(struct avdtp_stream *stream,
break;
}
}
-
-static void headset_setup_complete(struct device *dev, void *user_data)
+/*
+static void headset_discovery_complete(struct device *dev, void *user_data)
{
struct unix_client *client = user_data;
char buf[BT_AUDIO_IPC_PACKET_SIZE];
@@ -209,7 +227,7 @@ static void headset_setup_complete(struct device *dev, void *user_data)
client->req_id = 0;
if (!dev) {
- send_getcapabilities_rsp_error(client, EIO);
+ unix_ipc_error(client, BT_GETCAPABILITIES_RSP, EIO);
client->dev = NULL;
return;
}
@@ -231,7 +249,7 @@ static void headset_setup_complete(struct device *dev, void *user_data)
if (!headset_lock(dev, hs->lock)) {
error("Unable to lock headset");
- send_getcapabilities_rsp_error(client, EIO);
+ unix_ipc_error(client, BT_GETCAPABILITIES_RSP, EIO);
client->dev = NULL;
return;
}
@@ -240,25 +258,131 @@ static void headset_setup_complete(struct device *dev, void *user_data)
rsp->h.msg_type = BT_GETCAPABILITIES_RSP;
rsp->transport = BT_CAPABILITIES_TRANSPORT_SCO;
- rsp->access_mode = client->access_mode;
- rsp->link_mtu = 48;
rsp->sampling_rate = 8000;
client->data_fd = headset_get_sco_fd(dev);
unix_ipc_sendmsg(client, &rsp->h);
}
+*/
+static void headset_setup_complete(struct 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;
+ struct headset_data *hs = &client->d.hs;
-static void a2dp_setup_complete(struct avdtp *session, struct a2dp_sep *sep,
- struct avdtp_stream *stream,
- void *user_data, struct avdtp_error *err)
+ 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;
+ }
+
+ memset(buf, 0, sizeof(buf));
+
+ rsp->h.msg_type = BT_SETCONFIGURATION_RSP;
+ rsp->transport = BT_CAPABILITIES_TRANSPORT_SCO;
+ rsp->access_mode = client->access_mode;
+
+ client->data_fd = headset_get_sco_fd(dev);
+
+ unix_ipc_sendmsg(client, &rsp->h);
+}
+
+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;
- struct avdtp_service_capability *cap;
- struct avdtp_media_codec_capability *codec_cap;
- struct sbc_codec_cap *sbc_cap;
+ struct a2dp_data *a2dp = &client->d.a2dp;
+ struct sbc_codec_cap *sbc_cap = NULL;
+ GSList *l;
+
+ if (err)
+ goto failed;
+
+ memset(buf, 0, sizeof(buf));
+ client->req_id = 0;
+
+ rsp->h.msg_type = BT_GETCAPABILITIES_RSP;
+ rsp->transport = BT_CAPABILITIES_TRANSPORT_A2DP;
+
+ 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;
+
+ }
+
+ /* 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;
+ }
+
+ unix_ipc_sendmsg(client, &rsp->h);
+
+ return;
+
+failed:
+ error("discovery failed");
+ unix_ipc_error(client, BT_GETCAPABILITIES_RSP, EIO);
+
+ avdtp_unref(a2dp->session);
+
+ a2dp->session = NULL;
+ a2dp->stream = NULL;
+}
+
+static void a2dp_config_complete(struct avdtp *session, struct a2dp_sep *sep,
+ struct avdtp_stream *stream,
+ struct avdtp_error *err,
+ void *user_data)
+{
+ struct unix_client *client = user_data;
+ char buf[BT_AUDIO_IPC_PACKET_SIZE];
+ struct bt_setconfiguration_rsp *rsp = (void *) buf;
struct a2dp_data *a2dp = &client->d.a2dp;
uint16_t imtu, omtu;
GSList *caps;
@@ -282,40 +406,13 @@ static void a2dp_setup_complete(struct avdtp *session, struct a2dp_sep *sep,
goto failed;
}
- for (codec_cap = NULL; caps; caps = g_slist_next(caps)) {
- cap = caps->data;
- if (cap->category == AVDTP_MEDIA_CODEC) {
- codec_cap = (void *) cap->data;
- break;
- }
- }
-
- if (codec_cap == NULL ||
- codec_cap->media_codec_type != A2DP_CODEC_SBC) {
- error("Unable to find matching codec capability");
- goto failed;
- }
-
- rsp->h.msg_type = BT_GETCAPABILITIES_RSP;
+ rsp->h.msg_type = BT_SETCONFIGURATION_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;
- sbc_cap = (void *) codec_cap;
-
- /* assignations below are ok as soon as newipc.h and a2dp.h are kept */
- /* in sync. However it is not possible to cast a struct to another */
- /* dues to endianess issues */
- 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;
-
unix_ipc_sendmsg(client, &rsp->h);
client->cb_id = avdtp_stream_add_cb(session, stream,
@@ -324,12 +421,86 @@ static void a2dp_setup_complete(struct avdtp *session, struct a2dp_sep *sep,
return;
failed:
- error("stream setup failed");
+ error("setup failed");
+
+ if (a2dp->sep) {
+ a2dp_sep_unlock(a2dp->sep, a2dp->session);
+ a2dp->sep = NULL;
+ }
+ unix_ipc_error(client, BT_SETCONFIGURATION_RSP, EIO);
+
+ avdtp_unref(a2dp->session);
+
+ a2dp->session = NULL;
+ a2dp->stream = NULL;
+}
+
+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_datafd_ind *ind = (void *) buf;
+ struct a2dp_data *a2dp = &client->d.a2dp;
+
+ memset(buf, 0, sizeof(buf));
+ rsp->h.msg_type = BT_STREAMSTART_RSP;
+ rsp->posix_errno = 0;
+ unix_ipc_sendmsg(client, &rsp->h);
+
+ memset(buf, 0, sizeof(buf));
+ ind->h.msg_type = BT_STREAMFD_IND;
+ unix_ipc_sendmsg(client, &ind->h);
+
+ 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");
+
+ if (a2dp->sep) {
+ a2dp_sep_unlock(a2dp->sep, a2dp->session);
+ a2dp->sep = NULL;
+ }
+ unix_ipc_error(client, BT_STREAMSTART_REQ, EIO);
+
+ avdtp_unref(a2dp->session);
+
+ a2dp->session = NULL;
+ a2dp->stream = NULL;
+}
+
+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;
+ struct a2dp_data *a2dp = &client->d.a2dp;
+
+ if (err)
+ goto failed;
+
+ memset(buf, 0, sizeof(buf));
+ rsp->h.msg_type = BT_STREAMSTOP_RSP;
+ rsp->posix_errno = 0;
+ unix_ipc_sendmsg(client, &rsp->h);
+
+ return;
+
+failed:
+ error("suspend failed");
+
if (a2dp->sep) {
a2dp_sep_unlock(a2dp->sep, a2dp->session);
a2dp->sep = NULL;
}
- send_getcapabilities_rsp_error(client, EIO);
+ unix_ipc_error(client, BT_STREAMSTOP_REQ, EIO);
avdtp_unref(a2dp->session);
@@ -337,10 +508,11 @@ failed:
a2dp->stream = NULL;
}
-static void create_stream(struct device *dev, struct unix_client *client)
+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);
@@ -356,18 +528,55 @@ static void create_stream(struct device *dev, struct unix_client *client)
goto failed;
}
- /* FIXME: The provided media_codec breaks bitpool
- selection. So disable it. This needs fixing */
- id = a2dp_source_request_stream(a2dp->session,
- TRUE, a2dp_setup_complete,
- client,
- NULL/*client->media_codec*/);
- client->cancel_stream = a2dp_source_cancel_stream;
+ err = avdtp_discover(a2dp->session, a2dp_discovery_complete,
+ client);
+ if (err)
+ goto failed;
break;
case TYPE_HEADSET:
id = headset_request_stream(dev, headset_setup_complete, client);
- client->cancel_stream = headset_cancel_stream;
+ client->cancel = headset_cancel_stream;
+ break;
+
+ default:
+ error("No known services for device");
+ goto failed;
+ }
+
+ return;
+
+failed:
+ unix_ipc_error(client, BT_GETCAPABILITIES_RSP, err ? : EIO);
+}
+
+static void start_config(struct device *dev, struct unix_client *client)
+{
+ struct a2dp_data *a2dp;
+ unsigned int id;
+
+ client->type = select_service(dev, client->interface);
+
+ switch (client->type) {
+ case TYPE_SINK:
+ a2dp = &client->d.a2dp;
+
+ if (!a2dp->session)
+ a2dp->session = avdtp_get(&dev->src, &dev->dst);
+
+ if (!a2dp->session) {
+ error("Unable to get a session");
+ goto failed;
+ }
+
+ id = a2dp_source_config(a2dp->session, a2dp_config_complete,
+ client->caps, client);
+ client->cancel = a2dp_source_cancel;
+ break;
+
+ case TYPE_HEADSET:
+ id = headset_request_stream(dev, headset_setup_complete, client);
+ client->cancel = headset_cancel_stream;
break;
default:
@@ -376,7 +585,7 @@ static void create_stream(struct device *dev, struct unix_client *client)
}
if (id == 0) {
- error("request_stream failed");
+ error("config failed");
goto failed;
}
@@ -386,37 +595,117 @@ static void create_stream(struct device *dev, struct unix_client *client)
return;
failed:
- send_getcapabilities_rsp_error(client, EIO);
+ unix_ipc_error(client, BT_SETCONFIGURATION_RSP, EIO);
}
-static void create_cb(struct device *dev, void *user_data)
+static void start_resume(struct device *dev, struct unix_client *client)
{
- struct unix_client *client = user_data;
+ struct a2dp_data *a2dp;
+ unsigned int id;
- if (!dev)
- send_getcapabilities_rsp_error(client, EIO);
- else
- create_stream(dev, client);
+ client->type = select_service(dev, client->interface);
+
+ switch (client->type) {
+ case TYPE_SINK:
+ a2dp = &client->d.a2dp;
+
+ if (!a2dp->session)
+ a2dp->session = avdtp_get(&dev->src, &dev->dst);
+
+ if (!a2dp->session) {
+ error("Unable to get a session");
+ goto failed;
+ }
+
+ if (!a2dp->sep) {
+ error("Unable to get a sep");
+ goto failed;
+ }
+
+ id = a2dp_source_resume(a2dp->session, a2dp->sep,
+ a2dp_resume_complete, client);
+ client->cancel = a2dp_source_cancel;
+ break;
+
+ case TYPE_HEADSET:
+ id = headset_request_stream(dev, headset_setup_complete, client);
+ client->cancel = headset_cancel_stream;
+ break;
+
+ default:
+ error("No known services for device");
+ goto failed;
+ }
+
+ if (id == 0) {
+ error("resume failed");
+ goto failed;
+ }
+
+ return;
+
+failed:
+ unix_ipc_error(client, BT_STREAMSTART_RSP, EIO);
}
-static void unix_ipc_sendmsg(struct unix_client *client,
- const bt_audio_msg_header_t *msg)
+static void start_suspend(struct device *dev, struct unix_client *client)
{
- info("Audio API: sending %s", bt_audio_strmsg(msg->msg_type));
- if (send(client->sock, msg, BT_AUDIO_IPC_PACKET_SIZE, 0) < 0)
- error("Error %s(%d)", strerror(errno), errno);
+ struct a2dp_data *a2dp;
+ unsigned int id;
+
+ client->type = select_service(dev, client->interface);
+
+ switch (client->type) {
+ case TYPE_SINK:
+ a2dp = &client->d.a2dp;
+
+ if (!a2dp->session)
+ a2dp->session = avdtp_get(&dev->src, &dev->dst);
+
+ if (!a2dp->session) {
+ error("Unable to get a session");
+ goto failed;
+ }
+
+ if (!a2dp->sep) {
+ error("Unable to get a sep");
+ goto failed;
+ }
+
+ id = a2dp_source_suspend(a2dp->session, a2dp->sep,
+ a2dp_suspend_complete, client);
+ client->cancel = a2dp_source_cancel;
+ break;
+
+ case TYPE_HEADSET:
+ id = headset_request_stream(dev, headset_setup_complete, client);
+ client->cancel = headset_cancel_stream;
+ break;
+
+ default:
+ error("No known services for device");
+ goto failed;
+ }
+
+ if (id == 0) {
+ error("suspend failed");
+ goto failed;
+ }
+
+ return;
+
+failed:
+ unix_ipc_error(client, BT_STREAMSTOP_RSP, EIO);
}
-static void send_getcapabilities_rsp_error(struct unix_client *client, int err)
+static void create_cb(struct device *dev, void *user_data)
{
- char buf[BT_AUDIO_IPC_PACKET_SIZE];
- struct bt_getcapabilities_rsp *rsp = (void *) buf;
-
- memset(buf, 0, sizeof(buf));
- rsp->h.msg_type = BT_GETCAPABILITIES_RSP;
- rsp->posix_errno = err;
+ struct unix_client *client = user_data;
- unix_ipc_sendmsg(client, &rsp->h);
+ if (!dev)
+ unix_ipc_error(client, BT_GETCAPABILITIES_RSP, EIO);
+ else
+ start_discovery(dev, client);
}
static void handle_getcapabilities_req(struct unix_client *client,
@@ -427,13 +716,6 @@ static void handle_getcapabilities_req(struct unix_client *client,
str2ba(req->device, &bdaddr);
- if (!req->access_mode) {
- send_getcapabilities_rsp_error(client, EINVAL);
- return;
- }
-
- client->access_mode = req->access_mode;
-
if (client->interface) {
g_free(client->interface);
client->interface = NULL;
@@ -444,8 +726,6 @@ static void handle_getcapabilities_req(struct unix_client *client,
else if (req->transport == BT_CAPABILITIES_TRANSPORT_A2DP)
client->interface = g_strdup(AUDIO_SINK_INTERFACE);
- client->media_codec = 0;
-
if (!manager_find_device(&bdaddr, NULL, FALSE)) {
if (!bacmp(&bdaddr, BDADDR_ANY))
goto failed;
@@ -461,63 +741,118 @@ static void handle_getcapabilities_req(struct unix_client *client,
if (!dev)
goto failed;
- create_stream(dev, client);
+ start_discovery(dev, client);
return;
failed:
- send_getcapabilities_rsp_error(client, EIO);
+ unix_ipc_error(client, BT_GETCAPABILITIES_RSP, EIO);
}
static void handle_setconfiguration_req(struct unix_client *client,
struct bt_setconfiguration_req *req)
{
- /* FIXME: for now we just blindly assume that we receive is the
- only valid configuration sent.*/
- char buf[BT_AUDIO_IPC_PACKET_SIZE];
- struct bt_setconfiguration_rsp *rsp = (void *) buf;
+ struct avdtp_service_capability *media_transport, *media_codec;
+ struct sbc_codec_cap sbc_cap;
+ struct device *dev;
+ bdaddr_t bdaddr;
+ int err = 0;
- memset(buf, 0, sizeof(buf));
- rsp->h.msg_type = BT_SETCONFIGURATION_RSP;
- rsp->posix_errno = 0;
+ if (!req->access_mode) {
+ err = EINVAL;
+ goto failed;
+ }
- unix_ipc_sendmsg(client, &rsp->h);
+ str2ba(req->device, &bdaddr);
+
+ if (client->interface) {
+ g_free(client->interface);
+ client->interface = NULL;
+ }
+
+ if (req->transport == BT_CAPABILITIES_TRANSPORT_SCO)
+ client->interface = g_strdup(AUDIO_HEADSET_INTERFACE);
+ else if (req->transport == BT_CAPABILITIES_TRANSPORT_A2DP)
+ client->interface = g_strdup(AUDIO_SINK_INTERFACE);
+
+ if (!manager_find_device(&bdaddr, NULL, FALSE)) {
+ if (!bacmp(&bdaddr, BDADDR_ANY))
+ goto failed;
+ if (!manager_create_device(&bdaddr, create_cb, client))
+ goto failed;
+ return;
+ }
+
+ dev = manager_find_device(&bdaddr, client->interface, TRUE);
+ if (!dev)
+ dev = manager_find_device(&bdaddr, client->interface, FALSE);
+
+ if (!dev)
+ goto failed;
+
+ client->access_mode = req->access_mode;
+
+ if (client->caps) {
+ g_slist_foreach(client->caps, (GFunc) g_free, NULL);
+ g_slist_free(client->caps);
+ }
+
+ media_transport = avdtp_service_cap_new(AVDTP_MEDIA_TRANSPORT,
+ NULL, 0);
+
+ client->caps = g_slist_append(client->caps, media_transport);
+
+ 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;
+
+ media_codec = avdtp_service_cap_new(AVDTP_MEDIA_CODEC, &sbc_cap,
+ sizeof(sbc_cap));
+
+ client->caps = g_slist_append(client->caps, media_codec);
+
+ start_config(dev, client);
+
+ return;
+
+failed:
+ unix_ipc_error(client, BT_SETCONFIGURATION_RSP, err ? : EIO);
}
static void handle_streamstart_req(struct unix_client *client,
struct bt_streamstart_req *req)
{
- /* FIXME : to be really implemented */
- char buf[BT_AUDIO_IPC_PACKET_SIZE];
- struct bt_streamstart_rsp *rsp = (void *) buf;
- struct bt_datafd_ind *ind = (void *) buf;
-
- memset(buf, 0, sizeof(buf));
- rsp->h.msg_type = BT_STREAMSTART_RSP;
- rsp->posix_errno = 0;
- unix_ipc_sendmsg(client, &rsp->h);
+ if (!client->dev)
+ goto failed;
- memset(buf, 0, sizeof(buf));
- ind->h.msg_type = BT_STREAMFD_IND;
- unix_ipc_sendmsg(client, &ind->h);
+ start_resume(client->dev, client);
- if (unix_sendmsg_fd(client->sock, client->data_fd) < 0)
- error("unix_sendmsg_fd: %s(%d)", strerror(errno), errno);
+ return;
+failed:
+ unix_ipc_error(client, BT_STREAMSTART_REQ, EIO);
}
static void handle_streamstop_req(struct unix_client *client,
struct bt_streamstop_req *req)
{
- /* FIXME : to be implemented */
- char buf[BT_AUDIO_IPC_PACKET_SIZE];
- struct bt_streamstop_rsp *rsp = (void *) buf;
+ if (!client->dev)
+ goto failed;
- memset(buf, 0, sizeof(buf));
- rsp->h.msg_type = BT_STREAMSTOP_RSP;
- rsp->posix_errno = 0;
+ start_suspend(client->dev, client);
- unix_ipc_sendmsg(client, &rsp->h);
+ return;
+
+failed:
+ unix_ipc_error(client, BT_STREAMSTOP_REQ, EIO);
}
static void handle_control_req(struct unix_client *client,
@@ -565,8 +900,8 @@ static gboolean client_cb(GIOChannel *chan, GIOCondition cond, gpointer data)
break;
}
- if (client->cancel_stream && client->req_id > 0)
- client->cancel_stream(client->dev, client->req_id);
+ if (client->cancel && client->req_id > 0)
+ client->cancel(client->dev, client->req_id);
goto failed;
}