Exemplo n.º 1
0
static void connect_cb(GIOChannel *io, GError *err, gpointer user_data)
{
    uint16_t mtu;
    uint16_t cid;
    GError *gerr = NULL;

    DBG("io = %p, err = %p", io, err);
    if (err) {
        DBG("err = %s", err->message);
        set_state(STATE_DISCONNECTED);
        resp_error(err_CONN_FAIL);
        printf("# Connect error: %s\n", err->message);
        return;
    }

    bt_io_get(io, &gerr, BT_IO_OPT_IMTU, &mtu,
                BT_IO_OPT_CID, &cid, BT_IO_OPT_INVALID);

    if (gerr) {
        printf("# Can't detect MTU, using default");
        g_error_free(gerr);
        mtu = ATT_DEFAULT_LE_MTU;
    }
    else if (cid == ATT_CID)
        mtu = ATT_DEFAULT_LE_MTU;

    attrib = g_attrib_new(iochannel, mtu);

    g_attrib_register(attrib, ATT_OP_HANDLE_NOTIFY, GATTRIB_ALL_HANDLES,
                        events_handler, attrib, NULL);
    g_attrib_register(attrib, ATT_OP_HANDLE_IND, GATTRIB_ALL_HANDLES,
                        events_handler, attrib, NULL);
    g_attrib_register(attrib, ATT_OP_FIND_INFO_REQ, GATTRIB_ALL_HANDLES,
                        req_gatts, NULL, NULL);
    g_attrib_register(attrib, ATT_OP_FIND_BY_TYPE_REQ, GATTRIB_ALL_HANDLES,
                        req_gatts, NULL, NULL);
    g_attrib_register(attrib, ATT_OP_READ_BY_TYPE_REQ, GATTRIB_ALL_HANDLES,
                        req_gatts, NULL, NULL);
    g_attrib_register(attrib, ATT_OP_READ_REQ, GATTRIB_ALL_HANDLES,
                        req_gatts, NULL, NULL);
    g_attrib_register(attrib, ATT_OP_READ_BLOB_REQ, GATTRIB_ALL_HANDLES,
                        req_gatts, NULL, NULL);
    g_attrib_register(attrib, ATT_OP_READ_MULTI_REQ, GATTRIB_ALL_HANDLES,
                        req_gatts, NULL, NULL);
    g_attrib_register(attrib, ATT_OP_READ_BY_GROUP_REQ, GATTRIB_ALL_HANDLES,
                        req_gatts, NULL, NULL);
    g_attrib_register(attrib, ATT_OP_WRITE_REQ, GATTRIB_ALL_HANDLES,
                        req_gatts, NULL, NULL);
    g_attrib_register(attrib, ATT_OP_WRITE_CMD, GATTRIB_ALL_HANDLES,
                        req_gatts, NULL, NULL);
    g_attrib_register(attrib, ATT_OP_SIGNED_WRITE_CMD, GATTRIB_ALL_HANDLES,
                        req_gatts, NULL, NULL);
    g_attrib_register(attrib, ATT_OP_PREP_WRITE_REQ, GATTRIB_ALL_HANDLES,
                        req_gatts, NULL, NULL);
    g_attrib_register(attrib, ATT_OP_EXEC_WRITE_REQ, GATTRIB_ALL_HANDLES,
                        req_gatts, NULL, NULL);

    set_state(STATE_CONNECTED);
}
Exemplo n.º 2
0
static void connect_cb(GIOChannel *chan, GError *err, gpointer user_data)
{
	uint16_t imtu, omtu;
	GError *gerr = NULL;
	int fd;

	if (err) {
		printf("%s\n", err->message);
		g_main_loop_quit(mainloop);
		return;
	}

	bt_io_get(chan, &gerr,
			BT_IO_OPT_IMTU, &imtu,
			BT_IO_OPT_OMTU, &omtu,
			BT_IO_OPT_DEST_BDADDR, &dst,
			BT_IO_OPT_INVALID);
	if (gerr) {
		printf("%s\n", gerr->message);
		g_main_loop_quit(mainloop);
		return;
	}

	printf("Connected (imtu=%d omtu=%d)\n", imtu, omtu);

	fd = g_io_channel_unix_get_fd(chan);

	if (avdtp && avdtp_stream) {
		if (!avdtp_stream_set_transport(avdtp_stream, fd, imtu, omtu)) {
			printf("avdtp_stream_set_transport: failed\n");
			g_main_loop_quit(mainloop);
		}

		g_io_channel_set_close_on_unref(chan, FALSE);

		send_command();

		return;
	}

	avdtp = avdtp_new(fd, imtu, omtu, version);
	if (!avdtp) {
		printf("Failed to create avdtp instance\n");
		g_main_loop_quit(mainloop);
		return;
	}

	avdtp_add_disconnect_cb(avdtp, disconnect_cb, NULL);

	if (preconf) {
		int ret;

		ret = avdtp_discover(avdtp, discover_cb, NULL);
		if (ret < 0) {
			printf("avdtp_discover failed: %s", strerror(-ret));
			g_main_loop_quit(mainloop);
		}
	}
}
Exemplo n.º 3
0
static void avctp_connect_browsing_cb(GIOChannel *chan, GError *err,
							gpointer data)
{
	struct avctp *session = data;
	struct avctp_channel *browsing = session->browsing;
	char address[18];
	uint16_t imtu, omtu;
	GError *gerr = NULL;

	if (err) {
		error("Browsing: %s", err->message);
		goto fail;
	}

	bt_io_get(chan, &gerr,
			BT_IO_OPT_DEST, &address,
			BT_IO_OPT_IMTU, &imtu,
			BT_IO_OPT_OMTU, &omtu,
			BT_IO_OPT_INVALID);
	if (gerr) {
		error("%s", gerr->message);
		g_io_channel_shutdown(chan, TRUE, NULL);
		g_io_channel_unref(chan);
		g_error_free(gerr);
		goto fail;
	}

	DBG("AVCTP Browsing: connected to %s", address);

	if (browsing == NULL) {
		browsing = avctp_channel_create(session, chan,
						avctp_destroy_browsing);
		session->browsing = browsing;
	}

	browsing->imtu = imtu;
	browsing->omtu = omtu;
	browsing->buffer = g_malloc0(MAX(imtu, omtu));
	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);

	avctp_set_state(session, AVCTP_STATE_BROWSING_CONNECTED);

	/* Process any request that was pending the connection to complete */
	if (browsing->process_id == 0 && !g_queue_is_empty(browsing->queue))
		browsing->process_id = g_idle_add(process_queue, browsing);

	return;

fail:
	avctp_set_state(session, AVCTP_STATE_CONNECTED);

	if (session->browsing) {
		avctp_channel_destroy(session->browsing);
		session->browsing = NULL;
	}
}
Exemplo n.º 4
0
static void connect_confirm_cb(GIOChannel *io, gpointer data)
{
	struct sap_server *server = data;
	struct sap_connection *conn = server->conn;
	GError *gerr = NULL;
	bdaddr_t src, dst;
	char dstaddr[18];
	int err;

	DBG("conn %p io %p", conn, io);

	if (!io)
		return;

	if (conn) {
		DBG("Another SAP connection already exists.");
		g_io_channel_shutdown(io, TRUE, NULL);
		return;
	}

	conn = g_try_new0(struct sap_connection, 1);
	if (!conn) {
		error("Can't allocate memory for incoming SAP connection.");
		g_io_channel_shutdown(io, TRUE, NULL);
		return;
	}

	g_io_channel_set_encoding(io, NULL, NULL);
	g_io_channel_set_buffered(io, FALSE);

	server->conn = conn;
	conn->io = g_io_channel_ref(io);
	conn->state = SAP_STATE_DISCONNECTED;

	bt_io_get(io, BT_IO_RFCOMM, &gerr,
			BT_IO_OPT_SOURCE_BDADDR, &src,
			BT_IO_OPT_DEST_BDADDR, &dst,
			BT_IO_OPT_INVALID);
	if (gerr) {
		error("%s", gerr->message);
		g_error_free(gerr);
		sap_server_remove_conn(server);
		return;
	}

	ba2str(&dst, dstaddr);

	err = btd_request_authorization(&src, &dst, SAP_UUID, connect_auth_cb,
								server);
	if (err < 0) {
		error("Authorization failure (err %d)", err);
		sap_server_remove_conn(server);
		return;
	}

	DBG("Authorizing incoming SAP connection from %s", dstaddr);
}
Exemplo n.º 5
0
static void hf_io_cb(GIOChannel *chan, gpointer data)
{
	bdaddr_t src, dst;
	GError *err = NULL;
	uint8_t ch;
	const char *server_uuid, *remote_uuid;
	struct audio_device *device;
	int perr;

	bt_io_get(chan, BT_IO_RFCOMM, &err,
			BT_IO_OPT_SOURCE_BDADDR, &src,
			BT_IO_OPT_DEST_BDADDR, &dst,
			BT_IO_OPT_CHANNEL, &ch,
			BT_IO_OPT_INVALID);

	if (err) {
		error("%s", err->message);
		g_error_free(err);
		return;
	}

	server_uuid = HFP_AG_UUID;
	remote_uuid = HFP_HS_UUID;

	device = manager_get_device(&src, &dst, TRUE);
	if (!device)
		goto drop;

	if (!device->gateway) {
		btd_device_add_uuid(device->btd_dev, remote_uuid);
		if (!device->gateway)
			goto drop;
	}

	if (gateway_is_connected(device)) {
		DBG("Refusing new connection since one already exists");
		goto drop;
	}

	if (gateway_connect_rfcomm(device, chan) < 0) {
		error("Allocating new GIOChannel failed!");
		goto drop;
	}

	perr = audio_device_request_authorization(device, server_uuid,
						gateway_auth_cb, device);
	if (perr < 0) {
		DBG("Authorization denied!");
		goto drop;
	}

	return;

drop:
	g_io_channel_shutdown(chan, TRUE, NULL);
}
Exemplo n.º 6
0
static void avctp_confirm_cb(GIOChannel *chan, gpointer data)
{
	struct control *control = NULL;
	struct audio_device *dev;
	char address[18];
	bdaddr_t src, dst;
	GError *err = NULL;

	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_INVALID);
	if (err) {
		error("%s", err->message);
		g_error_free(err);
		g_io_channel_shutdown(chan, TRUE, NULL);
		return;
	}

	dev = manager_get_device(&src, &dst, TRUE);
	if (!dev) {
		error("Unable to get audio device object for %s", address);
		goto drop;
	}

	if (!dev->control) {
		btd_device_add_uuid(dev->btd_dev, AVRCP_REMOTE_UUID);
		if (!dev->control)
			goto drop;
	}

	control = dev->control;

	if (control->io) {
		error("Refusing unexpected connect from %s", address);
		goto drop;
	}

	avctp_set_state(control, AVCTP_STATE_CONNECTING);
	control->io = g_io_channel_ref(chan);

	if (audio_device_request_authorization(dev, AVRCP_TARGET_UUID,
						auth_cb, dev->control) < 0)
		goto drop;

	control->io_id = g_io_add_watch(chan, G_IO_ERR | G_IO_HUP | G_IO_NVAL,
							control_cb, control);
	return;

drop:
	if (!control || !control->io)
		g_io_channel_shutdown(chan, TRUE, NULL);
	if (control)
		avctp_set_state(control, AVCTP_STATE_DISCONNECTED);
}
Exemplo n.º 7
0
static void confirm_event(GIOChannel *chan, gpointer user_data)
{
	struct network_adapter *na = user_data;
	struct network_server *ns;
	int perr;
	bdaddr_t src, dst;
	char address[18];
	GError *err = NULL;

	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_INVALID);
	if (err) {
		error("%s", err->message);
		g_error_free(err);
		goto drop;
	}

	DBG("BNEP: incoming connect from %s", address);

	if (na->setup) {
		error("Refusing connect from %s: setup in progress", address);
		goto drop;
	}

	ns = find_server(na->servers, BNEP_SVC_NAP);
	if (!ns)
		goto drop;

	if (!ns->record_id)
		goto drop;

	if (!ns->bridge)
		goto drop;

	na->setup = g_new0(struct network_session, 1);
	bacpy(&na->setup->dst, &dst);
	na->setup->io = g_io_channel_ref(chan);

	perr = btd_request_authorization(&src, &dst, BNEP_SVC_UUID,
					auth_cb, na);
	if (perr < 0) {
		error("Refusing connect from %s: %s (%d)", address,
				strerror(-perr), -perr);
		setup_destroy(na);
		goto drop;
	}

	return;

drop:
	g_io_channel_shutdown(chan, TRUE, NULL);
}
Exemplo n.º 8
0
static void signaling_connect_cb(GIOChannel *chan, GError *err,
							gpointer user_data)
{
	struct a2dp_device *dev = user_data;
	uint16_t imtu, omtu;
	GError *gerr = NULL;
	int fd;

	if (err) {
		bt_a2dp_notify_state(dev, HAL_A2DP_STATE_DISCONNECTED);
		error("%s", err->message);
		return;
	}

	bt_io_get(chan, &gerr,
			BT_IO_OPT_IMTU, &imtu,
			BT_IO_OPT_OMTU, &omtu,
			BT_IO_OPT_INVALID);
	if (gerr) {
		error("%s", gerr->message);
		g_error_free(gerr);
		goto failed;
	}

	fd = g_io_channel_unix_get_fd(chan);

	/* FIXME: Add proper version */
	dev->session = avdtp_new(fd, imtu, omtu, 0x0100);
	if (!dev->session)
		goto failed;

	avdtp_add_disconnect_cb(dev->session, disconnect_cb, dev);

	/* Proceed to stream setup if initiator */
	if (dev->io) {
		int perr;

		g_io_channel_unref(dev->io);
		dev->io = NULL;

		perr = avdtp_discover(dev->session, discover_cb, dev);
		if (perr < 0) {
			error("avdtp_discover: %s", strerror(-perr));
			goto failed;
		}
		bt_avrcp_connect(&dev->dst);
	} else /* Init idle timeout to discover */
		dev->idle_id = g_timeout_add_seconds(IDLE_TIMEOUT, idle_timeout,
									dev);

	return;

failed:
	bt_a2dp_notify_state(dev, HAL_A2DP_STATE_DISCONNECTED);
}
Exemplo n.º 9
0
static DBusMessage *proxy_enable(DBusConnection *conn,
                                 DBusMessage *msg, void *data)
{
    struct serial_proxy *prx = data;
    sdp_record_t *record;
    GError *err = NULL;
    DBusMessage *reply;

    if (prx->io)
        return failed(msg, "Already enabled");

    /* Listen */
    prx->io = bt_io_listen(BT_IO_RFCOMM, NULL, confirm_event_cb, prx,
                           NULL, &err,
                           BT_IO_OPT_SOURCE_BDADDR, &prx->src,
                           BT_IO_OPT_INVALID);
    if (!prx->io)
        goto failed;

    bt_io_get(prx->io, BT_IO_RFCOMM, &err,
              BT_IO_OPT_CHANNEL, &prx->channel,
              BT_IO_OPT_INVALID);
    if (err) {
        g_io_channel_unref(prx->io);
        prx->io = NULL;
        goto failed;
    }

    debug("Allocated channel %d", prx->channel);

    g_io_channel_set_close_on_unref(prx->io, TRUE);

    record = proxy_record_new(prx->uuid128, prx->channel);
    if (!record) {
        g_io_channel_unref(prx->io);
        return failed(msg, "Unable to allocate new service record");
    }

    if (add_record_to_server(&prx->src, record) < 0) {
        sdp_record_free(record);
        g_io_channel_unref(prx->io);
        return failed(msg, "Service registration failed");
    }

    prx->record_id = record->handle;

    return dbus_message_new_method_return(msg);

failed:
    error("%s", err->message);
    reply = failed(msg, err->message);
    g_error_free(err);
    return reply;
}
Exemplo n.º 10
0
static void ctrl_confirm_event_cb(GIOChannel *chan, gpointer user_data)
{
	struct input_server *server = user_data;
	bdaddr_t src, dst;
	GError *err = NULL;
	struct btd_device *device = NULL;

	DBG("");

	bt_io_get(chan, BT_IO_L2CAP, &err,
			BT_IO_OPT_SOURCE_BDADDR, &src,
			BT_IO_OPT_DEST_BDADDR, &dst,
			BT_IO_OPT_INVALID);
	if (err) {
		error("%s", err->message);
		g_error_free(err);
		goto drop;
	}

	device = device_for_connection(&src, &dst);
	if (!device) {
		DBG("No device.");
		goto drop;
	}

	if (device_has_service_records(device)) {
		DBG("Device has service records");
		server->pending_accept.chan = chan;
		if (server_accept(server))
			return;

		DBG("Accept failed");
		goto drop;
	}

	if (server->pending_accept.timer) {
		DBG("Accept already pending.");
		goto drop;
	}

	DBG("Device has no service records, pending accept.");
	server->pending_accept.chan = chan;
	g_io_channel_ref(server->pending_accept.chan);
	server->pending_accept.retries = 0;
	server->pending_accept.src = src;
	server->pending_accept.dst = dst;
	server->pending_accept.timer = g_timeout_add_seconds(1,
							retry_server_accept,
							server);
	return;

drop:
	g_io_channel_shutdown(chan, TRUE, NULL);
}
Exemplo n.º 11
0
static void avctp_connect_cb(GIOChannel *chan, GError *err, gpointer data)
{
	struct avctp *session = data;
	char address[18];
	uint16_t imtu, omtu;
	GError *gerr = NULL;

	if (err) {
		avctp_set_state(session, AVCTP_STATE_DISCONNECTED);
		error("%s", err->message);
		return;
	}

	bt_io_get(chan, &gerr,
			BT_IO_OPT_DEST, &address,
			BT_IO_OPT_IMTU, &imtu,
			BT_IO_OPT_IMTU, &omtu,
			BT_IO_OPT_INVALID);
	if (gerr) {
		avctp_set_state(session, AVCTP_STATE_DISCONNECTED);
		error("%s", gerr->message);
		g_error_free(gerr);
		return;
	}

	DBG("AVCTP: connected to %s", address);

	if (session->control == NULL)
		session->control = avctp_channel_create(session, chan, NULL);

	session->control->imtu = imtu;
	session->control->omtu = omtu;
	session->control->buffer = g_malloc0(MAX(imtu, omtu));
	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);

	session->passthrough_id = avctp_register_pdu_handler(session,
						AVC_OP_PASSTHROUGH,
						handle_panel_passthrough,
						NULL);
	session->unit_id = avctp_register_pdu_handler(session,
						AVC_OP_UNITINFO,
						handle_unit_info,
						NULL);
	session->subunit_id = avctp_register_pdu_handler(session,
						AVC_OP_SUBUNITINFO,
						handle_subunit_info,
						NULL);

	init_uinput(session);

	avctp_set_state(session, AVCTP_STATE_CONNECTED);
}
Exemplo n.º 12
0
gboolean g_attrib_is_encrypted(GAttrib *attrib)
{
	BtIOSecLevel sec_level;

	if (!bt_io_get(attrib->io, BT_IO_L2CAP, NULL,
			BT_IO_OPT_SEC_LEVEL, &sec_level,
			BT_IO_OPT_INVALID))
		return FALSE;

	return sec_level > BT_IO_SEC_LOW;
}
Exemplo n.º 13
0
static int enable_proxy(struct serial_proxy *prx)
{
	sdp_record_t *record;
	GError *gerr = NULL;
	int err;

	if (prx->io)
		return -EALREADY;

	/* Listen */
	prx->io = bt_io_listen(BT_IO_RFCOMM, NULL, confirm_event_cb, prx,
				NULL, &gerr,
				BT_IO_OPT_SOURCE_BDADDR, &prx->src,
				BT_IO_OPT_INVALID);
	if (!prx->io)
		goto failed;

	bt_io_get(prx->io, BT_IO_RFCOMM, &gerr,
			BT_IO_OPT_CHANNEL, &prx->channel,
			BT_IO_OPT_INVALID);
	if (gerr) {
		g_io_channel_unref(prx->io);
		prx->io = NULL;
		goto failed;
	}

	debug("Allocated channel %d", prx->channel);

	g_io_channel_set_close_on_unref(prx->io, TRUE);

	record = proxy_record_new(prx->uuid128, prx->channel);
	if (!record) {
		g_io_channel_unref(prx->io);
		return -ENOMEM;
	}

	err = add_record_to_server(&prx->src, record);
	if (err < 0) {
		sdp_record_free(record);
		g_io_channel_unref(prx->io);
		return err;
	}

	prx->record_id = record->handle;

	return 0;

failed:
	error("%s", gerr->message);
	g_error_free(gerr);
	return -EIO;

}
Exemplo n.º 14
0
static void rfcomm_listen(const char *src, uint8_t ch, gboolean defer,
				gint reject, gint disconn, gint accept,
				gint sec, gboolean master)
{
	struct io_data *data;
	BtIOConnect conn;
	BtIOConfirm cfm;
	GIOChannel *rc_srv;
	GError *err = NULL;

	if (defer) {
		conn = NULL;
		cfm = confirm_cb;
	} else {
		conn = connect_cb;
		cfm = NULL;
	}

	data = io_data_new(NULL, BT_IO_RFCOMM, reject, disconn, accept);

	if (src)
		rc_srv = bt_io_listen(BT_IO_RFCOMM, conn, cfm,
					data, (GDestroyNotify) io_data_unref,
					&err,
					BT_IO_OPT_SOURCE, src,
					BT_IO_OPT_CHANNEL, ch,
					BT_IO_OPT_SEC_LEVEL, sec,
					BT_IO_OPT_MASTER, master,
					BT_IO_OPT_INVALID);
	else
		rc_srv = bt_io_listen(BT_IO_RFCOMM, conn, cfm,
					data, (GDestroyNotify) io_data_unref,
					&err,
					BT_IO_OPT_CHANNEL, ch,
					BT_IO_OPT_SEC_LEVEL, sec,
					BT_IO_OPT_MASTER, master,
					BT_IO_OPT_INVALID);

	if (!rc_srv) {
		printf("Listening failed: %s\n", err->message);
		g_error_free(err);
		exit(EXIT_FAILURE);
	}

	bt_io_get(rc_srv, BT_IO_RFCOMM, &err,
			BT_IO_OPT_CHANNEL, &ch,
			BT_IO_OPT_INVALID);

	printf("Listening on RFCOMM channel %u\n", ch);

	g_io_channel_unref(rc_srv);
}
Exemplo n.º 15
0
static void avctp_confirm_cb(GIOChannel *chan, gpointer data)
{
	struct avctp *session;
	char address[18];
	bdaddr_t src, dst;
	GError *err = NULL;
	uint16_t psm;
	struct btd_device *device;

	bt_io_get(chan, &err,
			BT_IO_OPT_SOURCE_BDADDR, &src,
			BT_IO_OPT_DEST_BDADDR, &dst,
			BT_IO_OPT_DEST, address,
			BT_IO_OPT_PSM, &psm,
			BT_IO_OPT_INVALID);
	if (err) {
		error("%s", err->message);
		g_error_free(err);
		g_io_channel_shutdown(chan, TRUE, NULL);
		return;
	}

	DBG("AVCTP: incoming connect from %s", address);

	device = btd_adapter_find_device(adapter_find(&src), &dst,
								BDADDR_BREDR);
	if (!device)
		return;

	session = avctp_get_internal(device);
	if (session == NULL)
		return;

	if (btd_device_get_service(device, AVRCP_REMOTE_UUID) == NULL)
		btd_device_add_uuid(device, AVRCP_REMOTE_UUID);

	if (btd_device_get_service(device, AVRCP_TARGET_UUID) == NULL)
		btd_device_add_uuid(device, AVRCP_TARGET_UUID);

	switch (psm) {
	case AVCTP_CONTROL_PSM:
		avctp_control_confirm(session, chan, device);
		break;
	case AVCTP_BROWSING_PSM:
		avctp_browsing_confirm(session, chan, device);
		break;
	}

	return;
}
Exemplo n.º 16
0
static void confirm_cb(GIOChannel *io, gpointer user_data)
{
	char addr[18];
	struct io_data *data = user_data;
	GError *err = NULL;

	if (!bt_io_get(io, &err, BT_IO_OPT_DEST, addr, BT_IO_OPT_INVALID)) {
		printf("bt_io_get(OPT_DEST): %s\n", err->message);
		g_clear_error(&err);
	} else
		printf("Got confirmation request for %s\n", addr);

	if (data->accept < 0 && data->reject < 0)
		return;

	if (data->reject == 0) {
		printf("Rejecting connection\n");
		g_io_channel_shutdown(io, TRUE, NULL);
		return;
	}

	if (data->voice) {
		if (!bt_io_set(io, &err, BT_IO_OPT_VOICE, data->voice,
							BT_IO_OPT_INVALID)) {
			printf("bt_io_set(OPT_VOICE): %s\n", err->message);
			g_clear_error(&err);
		}
	}

	data->io = g_io_channel_ref(io);
	io_data_ref(data);

	if (data->accept == 0) {
		if (!bt_io_accept(io, connect_cb, data,
					(GDestroyNotify) io_data_unref,
					&err)) {
			printf("bt_io_accept() failed: %s\n", err->message);
			g_clear_error(&err);
			io_data_unref(data);
			return;
		}
	} else {
		int seconds = (data->reject > 0) ?
						data->reject : data->accept;
		g_timeout_add_seconds_full(G_PRIORITY_DEFAULT, seconds,
					confirm_timeout, data,
					(GDestroyNotify) io_data_unref);
	}
}
Exemplo n.º 17
0
static void connect_event_cb(GIOChannel *chan, GError *err, gpointer data)
{
	uint16_t psm;
	bdaddr_t src, dst;
	char address[18];
	GError *gerr = NULL;
	int ret;

	if (err) {
		error("%s", err->message);
		return;
	}

	bt_io_get(chan, &gerr,
			BT_IO_OPT_SOURCE_BDADDR, &src,
			BT_IO_OPT_DEST_BDADDR, &dst,
			BT_IO_OPT_PSM, &psm,
			BT_IO_OPT_INVALID);
	if (gerr) {
		error("%s", gerr->message);
		g_error_free(gerr);
		g_io_channel_shutdown(chan, TRUE, NULL);
		return;
	}

	ba2str(&dst, address);
	DBG("Incoming connection from %s on PSM %d", address, psm);

	ret = input_device_set_channel(&src, &dst, psm, chan);
	if (ret == 0)
		return;

	if (ret == -ENOENT && dev_is_sixaxis(&src, &dst)) {
		sixaxis_browse_sdp(&src, &dst, chan, psm);
		return;
	}

	error("Refusing input device connect: %s (%d)", strerror(-ret), -ret);

	/* Send unplug virtual cable to unknown devices */
	if (ret == -ENOENT && psm == L2CAP_PSM_HIDP_CTRL) {
		unsigned char unplug = 0x15;
		int sk = g_io_channel_unix_get_fd(chan);
		if (write(sk, &unplug, sizeof(unplug)) < 0)
			error("Unable to send virtual cable unplug");
	}

	g_io_channel_shutdown(chan, TRUE, NULL);
}
Exemplo n.º 18
0
static void confirm_event_cb(GIOChannel *chan, gpointer user_data)
{
	struct input_server *server = user_data;
	bdaddr_t src, dst;
	GError *err = NULL;
	char addr[18];
	guint ret;

	DBG("");

	bt_io_get(chan, &err,
			BT_IO_OPT_SOURCE_BDADDR, &src,
			BT_IO_OPT_DEST_BDADDR, &dst,
			BT_IO_OPT_INVALID);
	if (err) {
		error("%s", err->message);
		g_error_free(err);
		goto drop;
	}

	ba2str(&dst, addr);

	if (server->confirm) {
		error("Refusing connection from %s: setup in progress", addr);
		goto drop;
	}

	if (!input_device_exists(&src, &dst) && !dev_is_sixaxis(&src, &dst)) {
		error("Refusing connection from %s: unknown device", addr);
		goto drop;
	}

	server->confirm = g_io_channel_ref(chan);

	ret = btd_request_authorization(&src, &dst, HID_UUID,
					auth_callback, server);
	if (ret != 0)
		return;

	error("input: authorization for device %s failed", addr);

	g_io_channel_unref(server->confirm);
	server->confirm = NULL;

drop:
	input_device_close_channels(&src, &dst);
	g_io_channel_shutdown(chan, TRUE, NULL);
}
Exemplo n.º 19
0
static int bluetooth_getpeername(GIOChannel *io, char **name)
{
	GError *gerr = NULL;
	char address[18];

	bt_io_get(io, &gerr, BT_IO_OPT_DEST, address, BT_IO_OPT_INVALID);

	if (gerr) {
		error("%s", gerr->message);
		g_error_free(gerr);
		return -EINVAL;
	}

	*name = g_strdup(address);

	return 0;
}
Exemplo n.º 20
0
static void transport_connect_cb(GIOChannel *chan, GError *err,
							gpointer user_data)
{
	struct a2dp_device *dev = user_data;
	struct a2dp_setup *setup;
	uint16_t imtu, omtu;
	GError *gerr = NULL;
	int fd;

	if (err) {
		error("%s", err->message);
		return;
	}

	setup = find_setup_by_device(dev);
	if (!setup) {
		error("Unable to find stream setup");
		return;
	}

	bt_io_get(chan, &gerr,
			BT_IO_OPT_IMTU, &imtu,
			BT_IO_OPT_OMTU, &omtu,
			BT_IO_OPT_INVALID);
	if (gerr) {
		error("%s", gerr->message);
		g_error_free(gerr);
		return;
	}

	fd = g_io_channel_unix_get_fd(chan);

	if (!avdtp_stream_set_transport(setup->stream, fd, imtu, omtu)) {
		error("avdtp_stream_set_transport: failed");
		return;
	}

	g_io_channel_set_close_on_unref(chan, FALSE);

	if (dev->io) {
		g_io_channel_unref(dev->io);
		dev->io = NULL;
	}

	bt_a2dp_notify_state(dev, HAL_A2DP_STATE_CONNECTED);
}
Exemplo n.º 21
0
static void confirm_event_cb(GIOChannel *chan, gpointer user_data)
{
	struct input_server *server = user_data;
	bdaddr_t src, dst;
	GError *err = NULL;
	char addr[18];
	int ret;

	bt_io_get(chan, BT_IO_L2CAP, &err,
			BT_IO_OPT_SOURCE_BDADDR, &src,
			BT_IO_OPT_DEST_BDADDR, &dst,
			BT_IO_OPT_INVALID);
	if (err) {
		error("%s", err->message);
		g_error_free(err);
		goto drop;
	}

	if (server->confirm) {
		char address[18];

		ba2str(&dst, address);
		error("Refusing connection from %s: setup in progress",
								address);
		goto drop;
	}

	server->confirm = g_io_channel_ref(chan);

	ret = btd_request_authorization(&src, &dst, HID_UUID,
					auth_callback, server);
	if (ret == 0)
		return;

	ba2str(&src, addr);
	error("input: authorization for %s failed: %s (%d)",
						addr, strerror(-ret), ret);

	g_io_channel_unref(server->confirm);
	server->confirm = NULL;

drop:
	input_device_close_channels(&src, &dst);
	g_io_channel_shutdown(chan, TRUE, NULL);
}
Exemplo n.º 22
0
bool bt_sco_get_fd_and_mtu(struct bt_sco *sco, int *fd, uint16_t *mtu)
{
	GError *err;

	if (!sco->io || !fd || !mtu)
		return false;

	err = NULL;
	if (!bt_io_get(sco->io, &err, BT_IO_OPT_MTU, mtu, BT_IO_OPT_INVALID)) {
			error("Unable to get MTU: %s\n", err->message);
			g_clear_error(&err);
			return false;
		}

	*fd = g_io_channel_unix_get_fd(sco->io);

	return true;
}
Exemplo n.º 23
0
static void nap_confirm_cb(GIOChannel *chan, gpointer data)
{
    struct pan_device *dev;
    bdaddr_t dst;
    char address[18];
    GError *err = NULL;

    DBG("");

    bt_io_get(chan, &err, BT_IO_OPT_DEST_BDADDR, &dst,
              BT_IO_OPT_DEST, address, BT_IO_OPT_INVALID);
    if (err) {
        error("%s", err->message);
        g_error_free(err);
        return;
    }

    DBG("incoming connect request from %s", address);
    dev = g_new0(struct pan_device, 1);
    bacpy(&dev->dst, &dst);
    local_role = HAL_PAN_ROLE_NAP;
    dev->role = HAL_PAN_ROLE_PANU;

    strncpy(dev->iface, BNEP_NAP_INTERFACE, 16);
    dev->iface[15] = '\0';

    dev->io = g_io_channel_ref(chan);
    g_io_channel_set_close_on_unref(dev->io, TRUE);

    if (!bt_io_accept(dev->io, nap_connect_cb, dev, NULL, &err)) {
        error("bt_io_accept: %s", err->message);
        g_error_free(err);
        goto failed;
    }

    devices = g_slist_append(devices, dev);
    bt_pan_notify_conn_state(dev, HAL_PAN_STATE_CONNECTING);

    return;

failed:
    bt_pan_notify_conn_state(dev, HAL_PAN_STATE_DISCONNECTED);
}
Exemplo n.º 24
0
static void ext_connect(GIOChannel *io, GError *err, gpointer user_data)
{
	struct ext_io *conn = user_data;
	struct ext_profile *ext = conn->ext;
	struct btd_device *device;
	bdaddr_t src;
	char addr[18];

	if (!bt_io_get(io, NULL,
				BT_IO_OPT_SOURCE_BDADDR, &src,
				BT_IO_OPT_DEST, addr,
				BT_IO_OPT_INVALID)) {
		error("Unable to get connect data for %s", ext->name);
		goto drop;
	}

	if (err != NULL) {
		error("%s failed to connect to %s: %s", ext->name, addr,
								err->message);
		goto drop;
	}

	DBG("%s connected to %s", ext->name, addr);

	device = get_btd_dev(&src, addr);
	if (!device) {
		error("%s: Unable to get dev object for %s", ext->name, addr);
		goto drop;
	}

	if (conn->io_id == 0) {
		GIOCondition cond = G_IO_HUP | G_IO_ERR | G_IO_NVAL;
		conn->io_id = g_io_add_watch(io, cond, ext_io_disconnected,
									conn);
	}

	if (send_new_connection(ext, conn, device))
		return;

drop:
	ext->conns = g_slist_remove(ext->conns, conn);
	ext_io_destroy(conn);
}
Exemplo n.º 25
0
static void update_char_desc(guint8 status, const guint8 *pdu, guint16 len,
							gpointer user_data)
{
	struct query_data *current = user_data;
	struct gatt_service *gatt = current->gatt;
	struct characteristic *chr = current->chr;
	INFO("%s",chr->path);

	if (status == 0) {

		g_free(chr->desc);

		chr->desc = g_malloc(len);
		memcpy(chr->desc, pdu + 1, len - 1);
		chr->desc[len - 1] = '\0';

		store_attribute(gatt, current->handle,
				GATT_CHARAC_USER_DESC_UUID,
				(void *) chr->desc, len);
	} else if (status == ATT_ECODE_INSUFF_ENC) {
		GIOChannel *io = g_attrib_get_channel(gatt->attrib);
		BtIOSecLevel level = BT_IO_SEC_HIGH;

		bt_io_get(io, BT_IO_L2CAP, NULL,
				BT_IO_OPT_SEC_LEVEL, &level,
				BT_IO_OPT_INVALID);

		if (level < BT_IO_SEC_HIGH)
			level++;

		if (bt_io_set(io, BT_IO_L2CAP, NULL,
				BT_IO_OPT_SEC_LEVEL, level,
				BT_IO_OPT_INVALID)) {
			gatt_read_char(gatt->attrib, current->handle, 0,
					update_char_desc, current);
			return;
		}
	}

	add_characteristic_descriptor(current, GATT_CHARAC_USER_DESC_UUID);
	query_list_remove(gatt, current);
	g_free(current);
}
Exemplo n.º 26
0
static void auth_callback(DBusError *derr, void *user_data)
{
	struct input_server *server = user_data;
	bdaddr_t src, dst;
	GError *err = NULL;

	bt_io_get(server->confirm, &err,
			BT_IO_OPT_SOURCE_BDADDR, &src,
			BT_IO_OPT_DEST_BDADDR, &dst,
			BT_IO_OPT_INVALID);
	if (err) {
		error("%s", err->message);
		g_error_free(err);
		goto reject;
	}

	if (derr) {
		error("Access denied: %s", derr->message);
		goto reject;
	}

	if (!input_device_exists(&src, &dst) && !dev_is_sixaxis(&src, &dst))
		return;

	if (!bt_io_accept(server->confirm, connect_event_cb, server,
				NULL, &err)) {
		error("bt_io_accept: %s", err->message);
		g_error_free(err);
		goto reject;
	}

	g_io_channel_unref(server->confirm);
	server->confirm = NULL;

	return;

reject:
	g_io_channel_shutdown(server->confirm, TRUE, NULL);
	g_io_channel_unref(server->confirm);
	server->confirm = NULL;
	input_device_close_channels(&src, &dst);
}
Exemplo n.º 27
0
static void confirm_event_cb(GIOChannel *chan, gpointer user_data)
{
    struct serial_proxy *prx = user_data;
    int perr;
    char address[18];
    GError *err = NULL;

    bt_io_get(chan, BT_IO_RFCOMM, &err,
              BT_IO_OPT_DEST_BDADDR, &prx->dst,
              BT_IO_OPT_DEST, address,
              BT_IO_OPT_INVALID);
    if (err) {
        error("%s", err->message);
        g_error_free(err);
        goto drop;
    }

    if (prx->rfcomm) {
        error("Refusing connect from %s: Proxy already in use",
              address);
        goto drop;
    }

    debug("Serial Proxy: incoming connect from %s", address);

    prx->rfcomm = g_io_channel_ref(chan);

    perr = btd_request_authorization(&prx->src, &prx->dst,
                                     prx->uuid128, auth_cb, prx);
    if (perr < 0) {
        error("Refusing connect from %s: %s (%d)", address,
              strerror(-perr), -perr);
        g_io_channel_unref(prx->rfcomm);
        prx->rfcomm = NULL;
        goto drop;
    }

    return;

drop:
    g_io_channel_shutdown(chan, TRUE, NULL);
}
Exemplo n.º 28
0
GAttrib *g_attrib_new(GIOChannel *io)
{
	struct _GAttrib *attrib;
	uint16_t imtu;
	uint16_t att_mtu;
	uint16_t cid;
	GError *gerr = NULL;

	g_io_channel_set_encoding(io, NULL, NULL);
	g_io_channel_set_buffered(io, FALSE);

	bt_io_get(io, BT_IO_L2CAP, &gerr,
			BT_IO_OPT_IMTU, &imtu,
			BT_IO_OPT_CID, &cid,
			BT_IO_OPT_INVALID);

	if (gerr) {
		error("%s", gerr->message);
		g_error_free(gerr);
		return NULL;
	}

	attrib = g_try_new0(struct _GAttrib, 1);
	if (attrib == NULL)
		return NULL;

	att_mtu = (cid == ATT_CID) ? ATT_DEFAULT_LE_MTU : imtu;

	attrib->buf = g_malloc0(att_mtu);
	attrib->buflen = att_mtu;

	attrib->io = g_io_channel_ref(io);
	attrib->requests = g_queue_new();
	attrib->responses = g_queue_new();

	attrib->read_watch = g_io_add_watch(attrib->io,
			G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
			received_data, attrib);

	return g_attrib_ref(attrib);
}
Exemplo n.º 29
0
static void connect_cb(GIOChannel *chan, GError *err, gpointer user_data)
{
	struct avrcp_device *dev = user_data;
	uint16_t imtu, omtu;
	char address[18];
	GError *gerr = NULL;
	int fd;

	if (err) {
		error("%s", err->message);
		return;
	}

	bt_io_get(chan, &gerr,
			BT_IO_OPT_DEST, address,
			BT_IO_OPT_IMTU, &imtu,
			BT_IO_OPT_OMTU, &omtu,
			BT_IO_OPT_INVALID);
	if (gerr) {
		error("%s", gerr->message);
		g_error_free(gerr);
		g_io_channel_shutdown(chan, TRUE, NULL);
		return;
	}

	fd = g_io_channel_unix_get_fd(chan);
	if (avrcp_device_add_session(dev, fd, imtu, omtu) < 0) {
		avrcp_device_free(dev);
		return;
	}

	g_io_channel_set_close_on_unref(chan, FALSE);

	if (dev->io) {
		g_io_channel_unref(dev->io);
		dev->io = NULL;
	}

	DBG("%s connected", address);
}
Exemplo n.º 30
0
static void connect_event_cb(GIOChannel *chan, GError *err, gpointer data)
{
	uint16_t psm;
	bdaddr_t src, dst;
	GError *gerr = NULL;
	int ret;

	if (err) {
		error("%s", err->message);
		return;
	}

	bt_io_get(chan, BT_IO_L2CAP, &gerr,
			BT_IO_OPT_SOURCE_BDADDR, &src,
			BT_IO_OPT_DEST_BDADDR, &dst,
			BT_IO_OPT_PSM, &psm,
			BT_IO_OPT_INVALID);
	if (gerr) {
		error("%s", gerr->message);
		g_error_free(gerr);
		g_io_channel_shutdown(chan, TRUE, NULL);
		return;
	}

	DBG("Incoming connection on PSM %d", psm);

	ret = input_device_set_channel(&src, &dst, psm, chan);
	if (ret == 0)
		return;

	/* Send unplug virtual cable to unknown devices */
	if (ret == -ENOENT && psm == L2CAP_PSM_HIDP_CTRL) {
		unsigned char unplug = 0x15;
		int err, sk = g_io_channel_unix_get_fd(chan);
		err = write(sk, &unplug, sizeof(unplug));
	}

	g_io_channel_shutdown(chan, TRUE, NULL);
}