diff options
author | Johan Hedberg <johan.hedberg@nokia.com> | 2009-02-19 22:22:20 +0200 |
---|---|---|
committer | Johan Hedberg <johan.hedberg@nokia.com> | 2009-02-19 22:22:20 +0200 |
commit | e03af126e1b79d4096dc9147859f74f256af28bb (patch) | |
tree | 6fcbaa90b74db1ff49c349102197aba3902adfd1 | |
parent | 10d6858927cb3db0a06c42f41cdb5f3175082df3 (diff) |
Convert control.c to use btio confirm_cb
-rw-r--r-- | audio/control.c | 189 |
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; |