diff --git a/audio/avctp.c b/audio/avctp.c
index 53c28ec..092a5e2 100644
--- a/audio/avctp.c
+++ b/audio/avctp.c
void *user_data;
};
+struct avctp_channel {
+ GIOChannel *io;
+ guint watch;
+ uint16_t mtu;
+};
+
struct avctp {
struct avctp_server *server;
bdaddr_t dst;
int uinput;
- GIOChannel *control_io;
- GIOChannel *browsing_io;
- guint control_io_id;
- guint browsing_io_id;
guint auth_id;
- uint16_t control_mtu;
- uint16_t browsing_mtu;
+ struct avctp_channel *control;
+ struct avctp_channel *browsing;
uint8_t key_quirks[256];
GSList *handlers;
return NULL;
}
+static void avctp_channel_destroy(struct avctp_channel *chan)
+{
+ g_io_channel_shutdown(chan->io, TRUE, NULL);
+ g_io_channel_unref(chan->io);
+
+ if (chan->watch)
+ g_source_remove(chan->watch);
+
+ g_free(chan);
+}
+
static void avctp_disconnected(struct avctp *session)
{
struct avctp_server *server;
if (!session)
return;
- if (session->browsing_io) {
- g_io_channel_shutdown(session->browsing_io, TRUE, NULL);
- g_io_channel_unref(session->browsing_io);
- session->browsing_io = NULL;
- }
-
- if (session->browsing_io_id) {
- g_source_remove(session->browsing_io_id);
- session->browsing_io_id = 0;
- }
-
- if (session->control_io) {
- g_io_channel_shutdown(session->control_io, TRUE, NULL);
- g_io_channel_unref(session->control_io);
- session->control_io = NULL;
- }
+ if (session->browsing)
+ avctp_channel_destroy(session->browsing);
- if (session->control_io_id) {
- g_source_remove(session->control_io_id);
- session->control_io_id = 0;
+ if (session->control)
+ avctp_channel_destroy(session->control);
- if (session->auth_id != 0) {
- btd_cancel_authorization(session->auth_id);
- session->auth_id = 0;
- }
+ if (session->auth_id != 0) {
+ btd_cancel_authorization(session->auth_id);
+ session->auth_id = 0;
}
if (session->uinput >= 0) {
}
}
-static void handle_response(struct avctp *session, struct avctp_header *avctp,
+static void control_response(struct avctp *session, struct avctp_header *avctp,
struct avc_header *avc, uint8_t *operands,
size_t operand_count)
{
if (cond & (G_IO_ERR | G_IO_HUP | G_IO_NVAL))
goto failed;
- sock = g_io_channel_unix_get_fd(session->browsing_io);
+ sock = g_io_channel_unix_get_fd(chan);
ret = read(sock, buf, sizeof(buf));
if (ret <= 0)
if (cond & (G_IO_ERR | G_IO_HUP | G_IO_NVAL))
goto failed;
- sock = g_io_channel_unix_get_fd(session->control_io);
+ sock = g_io_channel_unix_get_fd(chan);
ret = read(sock, buf, sizeof(buf));
if (ret <= 0)
avc->opcode, operand_count);
if (avctp->cr == AVCTP_RESPONSE) {
- handle_response(session, avctp, avc, operands, operand_count);
+ control_response(session, avctp, avc, operands, operand_count);
return TRUE;
}
DBG("AVRCP: uinput initialized for %s", address);
}
+static struct avctp_channel *avctp_channel_create(GIOChannel *io)
+{
+ struct avctp_channel *chan;
+
+ chan = g_new0(struct avctp_channel, 1);
+ chan->io = g_io_channel_ref(io);
+
+ return chan;
+}
+
static void avctp_connect_browsing_cb(GIOChannel *chan, GError *err,
gpointer data)
{
if (err) {
error("Browsing: %s", err->message);
- g_io_channel_shutdown(chan, TRUE, NULL);
- g_io_channel_unref(chan);
- session->browsing_io = NULL;
- return;
+ goto fail;
}
bt_io_get(chan, &gerr,
error("%s", gerr->message);
g_io_channel_shutdown(chan, TRUE, NULL);
g_io_channel_unref(chan);
- session->browsing_io = NULL;
g_error_free(gerr);
- return;
+ goto fail;
}
DBG("AVCTP Browsing: connected to %s", address);
- if (!session->browsing_io)
- session->browsing_io = g_io_channel_ref(chan);
+ if (session->browsing == NULL)
+ session->browsing = avctp_channel_create(chan);
- session->browsing_mtu = imtu;
- session->browsing_io_id = g_io_add_watch(chan,
+ session->browsing->mtu = imtu;
+ session->browsing->watch = g_io_add_watch(session->browsing->io,
G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL,
- (GIOFunc) session_browsing_cb, session); }
+ (GIOFunc) session_browsing_cb, session);
+
+ return;
+
+fail:
+ if (session->browsing) {
+ avctp_channel_destroy(session->browsing);
+ session->browsing = NULL;
+ }
+}
static void avctp_connect_cb(GIOChannel *chan, GError *err, gpointer data)
{
DBG("AVCTP: connected to %s", address);
- if (!session->control_io)
- session->control_io = g_io_channel_ref(chan);
+ if (session->control == NULL)
+ session->control = avctp_channel_create(chan);
+
+ session->control->mtu = imtu;
+ session->control->watch = g_io_add_watch(session->control->io,
+ G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL,
+ (GIOFunc) session_cb, session);
init_uinput(session);
avctp_set_state(session, AVCTP_STATE_CONNECTED);
- session->control_mtu = imtu;
- session->control_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)
session->auth_id = 0;
- if (session->control_io_id) {
- g_source_remove(session->control_io_id);
- session->control_io_id = 0;
+ if (session->control->watch > 0) {
+ g_source_remove(session->control->watch);
+ session->control->watch = 0;
}
if (derr && dbus_error_is_set(derr)) {
return;
}
- if (!bt_io_accept(session->control_io, avctp_connect_cb, session,
+ if (!bt_io_accept(session->control->io, avctp_connect_cb, session,
NULL, &err)) {
error("bt_io_accept: %s", err->message);
g_error_free(err);
static void avctp_control_confirm(struct avctp *session, GIOChannel *chan,
struct audio_device *dev)
{
- if (session->control_io) {
+ if (session->control != NULL) {
error("Control: Refusing unexpected connect");
g_io_channel_shutdown(chan, TRUE, NULL);
return;
}
avctp_set_state(session, AVCTP_STATE_CONNECTING);
- session->control_io = g_io_channel_ref(chan);
+ session->control = avctp_channel_create(chan);
session->auth_id = btd_request_authorization(&dev->src, &dev->dst,
AVRCP_TARGET_UUID,
if (session->auth_id == 0)
goto drop;
- session->control_io_id = g_io_add_watch(chan, G_IO_ERR | G_IO_HUP |
+ session->control->watch = g_io_add_watch(chan, G_IO_ERR | G_IO_HUP |
G_IO_NVAL, session_cb, session);
return;
{
GError *err = NULL;
- if (session->control_io == NULL || session->browsing_io) {
+ if (session->control == NULL || session->browsing != NULL) {
error("Browsing: Refusing unexpected connect");
g_io_channel_shutdown(chan, TRUE, NULL);
return;
DBG("AVCTP: incoming connect from %s", address);
session = avctp_get_internal(&src, &dst);
- if (!session)
- goto drop;
+ if (session == NULL)
+ return;
dev = manager_get_device(&src, &dst, FALSE);
if (!dev) {
return;
drop:
- if (session && session->browsing_io)
- g_io_channel_unref(session->browsing_io);
-
- if (session && session->control_io)
- g_io_channel_unref(session->control_io);
-
- if (session && psm == AVCTP_CONTROL_PSM)
+ if (psm == AVCTP_CONTROL_PSM)
avctp_set_state(session, AVCTP_STATE_DISCONNECTED);
}
operands[0] = op & 0x7f;
operands[1] = 0;
- sk = g_io_channel_unix_get_fd(session->control_io);
+ sk = g_io_channel_unix_get_fd(session->control->io);
if (write(sk, buf, sizeof(buf)) < 0)
return -errno;
if (session->state != AVCTP_STATE_CONNECTED)
return -ENOTCONN;
- sk = g_io_channel_unix_get_fd(session->control_io);
+ sk = g_io_channel_unix_get_fd(session->control->io);
memset(buf, 0, sizeof(buf));
return NULL;
}
- session->control_io = io;
+ session->control = avctp_channel_create(io);
+ g_io_channel_unref(io);
return session;
}
if (session->state != AVCTP_STATE_CONNECTED)
return -ENOTCONN;
- if (session->browsing_io != NULL)
+ if (session->browsing != NULL)
return 0;
io = bt_io_connect(avctp_connect_browsing_cb, session, NULL, &err,
return -EIO;
}
- session->browsing_io = io;
+ session->browsing = avctp_channel_create(io);
+ g_io_channel_unref(io);
return 0;
}
void avctp_disconnect(struct avctp *session)
{
- if (!session->control_io)
+ if (session->state == AVCTP_STATE_DISCONNECTED)
return;
avctp_set_state(session, AVCTP_STATE_DISCONNECTED);