summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohan Hedberg <johan.hedberg@nokia.com>2009-02-19 22:22:20 +0200
committerJohan Hedberg <johan.hedberg@nokia.com>2009-02-19 22:22:20 +0200
commite03af126e1b79d4096dc9147859f74f256af28bb (patch)
tree6fcbaa90b74db1ff49c349102197aba3902adfd1
parent10d6858927cb3db0a06c42f41cdb5f3175082df3 (diff)
Convert control.c to use btio confirm_cb
-rw-r--r--audio/control.c189
1 files changed, 81 insertions, 108 deletions
diff --git a/audio/control.c b/audio/control.c
index efe9f987..74879656 100644
--- a/audio/control.c
+++ b/audio/control.c
@@ -165,9 +165,8 @@ struct avctp {
int uinput;
- int sock;
-
- guint io;
+ GIOChannel *io;
+ guint io_id;
uint16_t mtu;
};
@@ -332,7 +331,6 @@ static struct avctp *avctp_get(const bdaddr_t *src, const bdaddr_t *dst)
session = g_new0(struct avctp, 1);
session->uinput = -1;
- session->sock = -1;
bacpy(&session->src, src);
bacpy(&session->dst, dst);
@@ -429,10 +427,12 @@ static void avctp_unref(struct avctp *session)
DBUS_TYPE_BOOLEAN, &value);
}
- if (session->sock >= 0)
- close(session->sock);
- if (session->io)
- g_source_remove(session->io);
+ if (session->io) {
+ g_io_channel_shutdown(session->io, TRUE, NULL);
+ g_io_channel_unref(session->io);
+ }
+ if (session->io_id)
+ g_source_remove(session->io_id);
if (session->dev)
session->dev->control->session = NULL;
@@ -452,12 +452,14 @@ static gboolean session_cb(GIOChannel *chan, GIOCondition cond,
unsigned char buf[1024], *operands;
struct avctp_header *avctp;
struct avrcp_header *avrcp;
- int ret, packet_size, operand_count;
+ int ret, packet_size, operand_count, sock;
if (!(cond | G_IO_IN))
goto failed;
- ret = read(session->sock, buf, sizeof(buf));
+ sock = g_io_channel_unix_get_fd(session->io);
+
+ ret = read(sock, buf, sizeof(buf));
if (ret <= 0)
goto failed;
@@ -505,7 +507,7 @@ static gboolean session_cb(GIOChannel *chan, GIOCondition cond,
handle_panel_passthrough(session, operands, operand_count);
avctp->cr = AVCTP_RESPONSE;
avrcp->code = CTYPE_ACCEPTED;
- ret = write(session->sock, buf, packet_size);
+ ret = write(sock, buf, packet_size);
}
if (avctp->packet_type == AVCTP_PACKET_SINGLE &&
@@ -518,7 +520,7 @@ static gboolean session_cb(GIOChannel *chan, GIOCondition cond,
avrcp->code = CTYPE_STABLE;
debug("reply to %s", avrcp->opcode == OP_UNITINFO ?
"OP_UNITINFO" : "OP_SUBUNITINFO");
- ret = write(session->sock, buf, packet_size);
+ ret = write(sock, buf, packet_size);
}
return TRUE;
@@ -603,20 +605,46 @@ static void init_uinput(struct avctp *session)
debug("AVRCP: uinput initialized for %s", address);
}
-static gboolean avctp_connect_session(struct avctp *session)
+static void avctp_connect_cb(GIOChannel *chan, GError *err, gpointer data)
{
- GIOChannel *io;
+ struct control *control = data;
+ struct avctp *session = control->session;
+ char address[18];
+ uint16_t imtu;
+ GError *gerr = NULL;
gboolean value;
- session->dev = manager_find_device(&session->dst, NULL, FALSE);
- if (!session->dev) {
- error("Connecting audio device not known (SDP not completed)");
- return FALSE;
+ if (!session) {
+ debug("avctp_connect_cb: session removed while connecting");
+ g_io_channel_shutdown(chan, TRUE, NULL);
+ g_io_channel_unref(chan);
+ return;
}
- session->state = AVCTP_STATE_CONNECTED;
+ if (err) {
+ avctp_unref(session);
+ error("%s", err->message);
+ return;
+ }
- session->dev->control->session = session;
+ bt_io_get(chan, BT_IO_L2CAP, &gerr,
+ BT_IO_OPT_DEST, &address,
+ BT_IO_OPT_IMTU, &imtu,
+ BT_IO_OPT_INVALID);
+ if (gerr) {
+ avctp_unref(session);
+ error("%s", gerr->message);
+ g_error_free(gerr);
+ g_io_channel_shutdown(chan, TRUE, NULL);
+ return;
+ }
+
+ debug("AVCTP: connected to %s", address);
+
+ g_io_channel_set_close_on_unref(chan, FALSE);
+
+ if (!session->io)
+ session->io = g_io_channel_ref(chan);
init_uinput(session);
@@ -628,57 +656,51 @@ static gboolean avctp_connect_session(struct avctp *session)
AUDIO_CONTROL_INTERFACE, "Connected",
DBUS_TYPE_BOOLEAN, &value);
- if (session->io)
- g_source_remove(session->io);
-
- io = g_io_channel_unix_new(session->sock);
- session->io = g_io_add_watch(io,
- G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL,
- (GIOFunc) session_cb, session);
- g_io_channel_unref(io);
-
- return TRUE;
+ session->state = AVCTP_STATE_CONNECTED;
+ session->mtu = imtu;
+ session->io_id = g_io_add_watch(chan,
+ G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL,
+ (GIOFunc) session_cb, session);
}
static void auth_cb(DBusError *derr, void *user_data)
{
- struct avctp *session = user_data;
+ struct control *control = user_data;
+ struct avctp *session = control->session;
+ GError *err = NULL;
if (derr && dbus_error_is_set(derr)) {
error("Access denied: %s", derr->message);
-
avctp_unref(session);
return;
}
- avctp_connect_session(session);
+ if (!bt_io_accept(session->io, avctp_connect_cb, control,
+ NULL, &err)) {
+ error("bt_io_accept: %s", err->message);
+ g_error_free(err);
+ avctp_unref(session);
+ }
}
-static void avctp_server_cb(GIOChannel *chan, GError *err, gpointer data)
+static void avctp_confirm_cb(GIOChannel *chan, gpointer data)
{
struct avctp *session;
GIOCondition flags = G_IO_ERR | G_IO_HUP | G_IO_NVAL;
struct audio_device *dev;
char address[18];
bdaddr_t src, dst;
- uint16_t imtu;
int perr;
- GError *gerr = NULL;
-
- if (err) {
- error("%s", err->message);
- return;
- }
+ GError *err = NULL;
- bt_io_get(chan, BT_IO_L2CAP, &gerr,
+ bt_io_get(chan, BT_IO_L2CAP, &err,
BT_IO_OPT_SOURCE_BDADDR, &src,
BT_IO_OPT_DEST_BDADDR, &dst,
BT_IO_OPT_DEST, address,
- BT_IO_OPT_IMTU, &imtu,
BT_IO_OPT_INVALID);
- if (gerr) {
- error("%s", gerr->message);
- g_error_free(gerr);
+ if (err) {
+ error("%s", err->message);
+ g_error_free(err);
g_io_channel_shutdown(chan, TRUE, NULL);
return;
}
@@ -690,7 +712,7 @@ static void avctp_server_cb(GIOChannel *chan, GError *err, gpointer data)
goto drop;
}
- if (session->sock >= 0) {
+ if (session->io) {
error("Refusing unexpected connect from %s", address);
goto drop;
}
@@ -704,28 +726,32 @@ static void avctp_server_cb(GIOChannel *chan, GError *err, gpointer data)
if (!dev->control)
dev->control = control_init(dev);
+ if (!dev->control->session)
+ dev->control->session = session;
+
+ if (!session->dev)
+ session->dev = dev;
+
device_remove_control_timer(dev);
session->state = AVCTP_STATE_CONNECTING;
- session->sock = g_io_channel_unix_get_fd(chan);
-
- session->mtu = imtu;
+ session->io = g_io_channel_ref(chan);
- session->io = g_io_add_watch(chan, flags, (GIOFunc) session_cb,
- session);
+ session->io_id = g_io_add_watch(chan, flags, (GIOFunc) session_cb,
+ session);
if (avdtp_is_connected(&src, &dst))
goto proceed;
perr = btd_request_authorization(&src, &dst, AVRCP_TARGET_UUID,
- auth_cb, session);
+ auth_cb, dev->control);
if (perr < 0)
goto drop;
return;
proceed:
- if (!avctp_connect_session(session))
+ if (!bt_io_accept(chan, avctp_connect_cb, dev->control, NULL, NULL))
goto drop;
return;
@@ -740,7 +766,7 @@ static GIOChannel *avctp_server_socket(const bdaddr_t *src, gboolean master)
GError *err = NULL;
GIOChannel *io;
- io = bt_io_listen(BT_IO_L2CAP, avctp_server_cb, NULL, NULL,
+ io = bt_io_listen(BT_IO_L2CAP, NULL, avctp_confirm_cb, NULL,
NULL, &err,
BT_IO_OPT_SOURCE_BDADDR, src,
BT_IO_OPT_PSM, AVCTP_PSM,
@@ -755,59 +781,6 @@ static GIOChannel *avctp_server_socket(const bdaddr_t *src, gboolean master)
return io;
}
-static void avctp_connect_cb(GIOChannel *chan, GError *err, gpointer data)
-{
- struct control *control = data;
- struct avctp *session = control->session;
- int sk;
- char address[18];
- uint16_t imtu;
- GError *gerr = NULL;
-
- if (!session) {
- debug("avctp_connect_cb: session removed while connecting");
- g_io_channel_shutdown(chan, TRUE, NULL);
- g_io_channel_unref(chan);
- return;
- }
-
- if (err) {
- avctp_unref(session);
- error("%s", err->message);
- return;
- }
-
- bt_io_get(chan, BT_IO_L2CAP, &gerr,
- BT_IO_OPT_DEST, &address,
- BT_IO_OPT_IMTU, &imtu,
- BT_IO_OPT_INVALID);
- if (gerr) {
- avctp_unref(session);
- error("%s", gerr->message);
- g_error_free(gerr);
- g_io_channel_shutdown(chan, TRUE, NULL);
- return;
- }
-
- debug("AVCTP: connected to %s", address);
-
- g_io_channel_set_close_on_unref(chan, FALSE);
- sk = g_io_channel_unix_get_fd(chan);
- session->sock = sk;
-
- init_uinput(session);
-
- g_dbus_emit_signal(session->dev->conn, session->dev->path,
- AUDIO_CONTROL_INTERFACE, "Connected",
- DBUS_TYPE_INVALID);
-
- session->state = AVCTP_STATE_CONNECTED;
- session->mtu = imtu;
- session->io = g_io_add_watch(chan,
- G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL,
- (GIOFunc) session_cb, session);
-}
-
gboolean avrcp_connect(struct audio_device *dev)
{
struct control *control = dev->control;