Пример #1
0
int source_connect(struct btd_service *service)
{
	struct source *source = btd_service_get_user_data(service);

	if (!source->session)
		source->session = a2dp_avdtp_get(btd_service_get_device(service));

	if (!source->session) {
		DBG("Unable to get a session");
		return -EIO;
	}

	if (source->connect_id > 0 || source->disconnect_id > 0)
		return -EBUSY;

	if (source->state == SOURCE_STATE_CONNECTING)
		return -EBUSY;

	if (source->stream_state >= AVDTP_STATE_OPEN)
		return -EALREADY;

	if (!source_setup_stream(service, NULL)) {
		DBG("Failed to create a stream");
		return -EIO;
	}

	DBG("stream creation in progress");

	return 0;
}
Пример #2
0
int source_disconnect(struct btd_service *service)
{
	struct source *source = btd_service_get_user_data(service);

	if (!source->session)
		return -ENOTCONN;

	/* cancel pending connect */
	if (source->connect_id > 0) {
		a2dp_cancel(source->connect_id);
		source->connect_id = 0;
		btd_service_connecting_complete(source->service, -ECANCELED);

		avdtp_unref(source->session);
		source->session = NULL;

		return 0;
	}

	/* disconnect already ongoing */
	if (source->disconnect_id > 0)
		return -EBUSY;

	if (!source->stream)
		return -ENOTCONN;

	return avdtp_close(source->session, source->stream, FALSE);
}
Пример #3
0
static int gap_accept(struct btd_service *service)
{
	struct btd_device *device = btd_service_get_device(service);
	struct gatt_db *db = btd_device_get_gatt_db(device);
	struct bt_gatt_client *client = btd_device_get_gatt_client(device);
	struct gas *gas = btd_service_get_user_data(service);
	char addr[18];
	bt_uuid_t gap_uuid;

	ba2str(device_get_address(device), addr);
	DBG("GAP profile accept (%s)", addr);

	if (!gas) {
		error("GAP service not handled by profile");
		return -1;
	}

	gas->db = gatt_db_ref(db);
	gas->client = bt_gatt_client_ref(client);

	/* Handle the GAP services */
	bt_uuid16_create(&gap_uuid, GAP_UUID16);
	gatt_db_foreach_service(db, &gap_uuid, foreach_gap_service, gas);

	if (!gas->attr) {
		error("GAP attribute not found");
		gas_reset(gas);
		return -1;
	}

	btd_service_connecting_complete(service, 0);

	return 0;
}
Пример #4
0
static void source_free(struct btd_service *service)
{
	struct source *source = btd_service_get_user_data(service);

	if (source->cb_id)
		avdtp_stream_remove_cb(source->session, source->stream,
					source->cb_id);

	if (source->session)
		avdtp_unref(source->session);

	if (source->connect_id > 0) {
		btd_service_connecting_complete(source->service, -ECANCELED);
		a2dp_cancel(source->connect_id);
		source->connect_id = 0;
	}

	if (source->disconnect_id > 0) {
		btd_service_disconnecting_complete(source->service, -ECANCELED);
		a2dp_cancel(source->disconnect_id);
		source->disconnect_id = 0;
	}

	avdtp_remove_state_cb(source->avdtp_callback_id);
	btd_service_unref(source->service);

	g_free(source);
}
Пример #5
0
/* Connect and initiate BNEP session */
int connection_connect(struct btd_service *service)
{
	struct network_conn *nc = btd_service_get_user_data(service);
	struct network_peer *peer = nc->peer;
	uint16_t id = get_service_id(service);
	GError *err = NULL;
	const bdaddr_t *src;
	const bdaddr_t *dst;

	DBG("id %u", id);

	if (nc->state != DISCONNECTED)
		return -EALREADY;

	src = btd_adapter_get_address(device_get_adapter(peer->device));
	dst = device_get_address(peer->device);

	nc->io = bt_io_connect(connect_cb, nc,
				NULL, &err,
				BT_IO_OPT_SOURCE_BDADDR, src,
				BT_IO_OPT_DEST_BDADDR, dst,
				BT_IO_OPT_PSM, BNEP_PSM,
				BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_MEDIUM,
				BT_IO_OPT_OMTU, BNEP_MTU,
				BT_IO_OPT_IMTU, BNEP_MTU,
				BT_IO_OPT_INVALID);
	if (!nc->io)
		return -EIO;

	nc->state = CONNECTING;

	return 0;
}
Пример #6
0
gboolean control_is_active(struct btd_service *service)
{
	struct control *control = btd_service_get_user_data(service);

	if (control && control->session)
		return TRUE;

	return FALSE;
}
Пример #7
0
gboolean sink_is_active(struct btd_service *service)
{
	struct sink *sink = btd_service_get_user_data(service);

	if (sink->session)
		return TRUE;

	return FALSE;
}
Пример #8
0
static int gap_disconnect(struct btd_service *service)
{
	struct gas *gas = btd_service_get_user_data(service);

	gas_reset(gas);

	btd_service_disconnecting_complete(service, 0);

	return 0;
}
static void hog_remove(struct btd_service *service)
{
    struct hog_device *dev = btd_service_get_user_data(service);
    struct btd_device *device = btd_service_get_device(service);
    const char *path = device_get_path(device);

    DBG("path %s", path);

    hog_device_free(dev);
}
Пример #10
0
int control_disconnect(struct btd_service *service)
{
	struct control *control = btd_service_get_user_data(service);

	if (!control->session)
		return -ENOTCONN;

	avctp_disconnect(control->session);

	return 0;
}
Пример #11
0
int connection_disconnect(struct btd_service *service)
{
	struct network_conn *nc = btd_service_get_user_data(service);

	if (nc->state == DISCONNECTED)
		return 0;

	connection_destroy(NULL, nc);

	return 0;
}
Пример #12
0
static void scan_param_remove(struct btd_service *service)
{
	struct scan *scan = btd_service_get_user_data(service);

	if (scan->attrib != NULL && scan->refresh_cb_id > 0)
		g_attrib_unregister(scan->attrib, scan->refresh_cb_id);

	btd_device_remove_attio_callback(scan->device, scan->attioid);
	btd_device_unref(scan->device);
	g_attrib_unref(scan->attrib);
	g_free(scan);
}
Пример #13
0
int control_connect(struct btd_service *service)
{
	struct control *control = btd_service_get_user_data(service);

	if (control->session)
		return -EALREADY;

	control->session = avctp_connect(control->dev);
	if (!control->session)
		return -EIO;

	return 0;
}
Пример #14
0
void input_device_unregister(struct btd_service *service)
{
    struct btd_device *device = btd_service_get_device(service);
    const char *path = device_get_path(device);
    struct input_device *idev = btd_service_get_user_data(service);

    DBG("%s", path);

    g_dbus_unregister_interface(btd_get_dbus_connection(),
                                idev->path, INPUT_INTERFACE);

    input_device_free(idev);
}
Пример #15
0
int input_device_connect(struct btd_service *service)
{
	struct input_device *idev;

	idev = btd_service_get_user_data(service);

	if (idev->ctrl_io)
		return -EBUSY;

	if (is_connected(idev))
		return -EALREADY;

	return dev_connect(idev);
}
Пример #16
0
int input_device_disconnect(struct btd_service *service)
{
    struct input_device *idev;
    int err;

    DBG("");

    idev = btd_service_get_user_data(service);

    err = connection_disconnect(idev, 0);
    if (err < 0)
        return err;

    return 0;
}
Пример #17
0
static struct input_device *find_device(const bdaddr_t *src,
                                        const bdaddr_t *dst)
{
    struct btd_device *device;
    struct btd_service *service;

    device = btd_adapter_find_device(adapter_find(src), dst);
    if (device == NULL)
        return NULL;

    service = btd_device_get_service(device, HID_UUID);
    if (service == NULL)
        return NULL;

    return btd_service_get_user_data(service);
}
Пример #18
0
static void deviceinfo_driver_remove(struct btd_service *service)
{
	struct deviceinfo *d = btd_service_get_user_data(service);

	if (d->attioid > 0)
		btd_device_remove_attio_callback(d->dev, d->attioid);

	if (d->attrib != NULL)
		g_attrib_unref(d->attrib);

	g_slist_free_full(d->chars, g_free);

	btd_device_unref(d->dev);
	g_free(d->svc_range);
	g_free(d);
}
Пример #19
0
static void gap_remove(struct btd_service *service)
{
	struct btd_device *device = btd_service_get_device(service);
	struct gas *gas;
	char addr[18];

	ba2str(device_get_address(device), addr);
	DBG("GAP profile remove (%s)", addr);

	gas = btd_service_get_user_data(service);
	if (!gas) {
		error("GAP service not handled by profile");
		return;
	}

	gas_free(gas);
}
Пример #20
0
gboolean source_new_stream(struct btd_service *service, struct avdtp *session,
				struct avdtp_stream *stream)
{
	struct source *source = btd_service_get_user_data(service);

	if (source->stream)
		return FALSE;

	if (!source->session)
		source->session = avdtp_ref(session);

	source->stream = stream;

	source->cb_id = avdtp_stream_add_cb(session, stream,
						stream_state_changed, service);

	return TRUE;
}
Пример #21
0
gboolean sink_setup_stream(struct btd_service *service, struct avdtp *session)
{
	struct sink *sink = btd_service_get_user_data(service);

	if (sink->connect_id > 0 || sink->disconnect_id > 0)
		return FALSE;

	if (session && !sink->session)
		sink->session = avdtp_ref(session);

	if (!sink->session)
		return FALSE;

	if (avdtp_discover(sink->session, discovery_complete, sink) < 0)
		return FALSE;

	return TRUE;
}
Пример #22
0
int input_device_disconnect(struct btd_service *service)
{
	struct input_device *idev;
	int err, flags;

	DBG("");

	idev = btd_service_get_user_data(service);

	flags = device_is_temporary(idev->device) ?
					(1 << HIDP_VIRTUAL_CABLE_UNPLUG) : 0;

	err = connection_disconnect(idev, flags);
	if (err < 0)
		return err;

	return 0;
}
Пример #23
0
static void stream_state_changed(struct avdtp_stream *stream,
					avdtp_state_t old_state,
					avdtp_state_t new_state,
					struct avdtp_error *err,
					void *user_data)
{
	struct btd_service *service = user_data;
	struct source *source = btd_service_get_user_data(service);

	if (err)
		return;

	switch (new_state) {
	case AVDTP_STATE_IDLE:
		btd_service_disconnecting_complete(source->service, 0);

		if (source->disconnect_id > 0) {
			a2dp_cancel(source->disconnect_id);
			source->disconnect_id = 0;
		}

		if (source->session) {
			avdtp_unref(source->session);
			source->session = NULL;
		}
		source->stream = NULL;
		source->cb_id = 0;
		break;
	case AVDTP_STATE_OPEN:
		btd_service_connecting_complete(source->service, 0);
		source_set_state(source, SOURCE_STATE_CONNECTED);
		break;
	case AVDTP_STATE_STREAMING:
		source_set_state(source, SOURCE_STATE_PLAYING);
		break;
	case AVDTP_STATE_CONFIGURED:
	case AVDTP_STATE_CLOSING:
	case AVDTP_STATE_ABORTING:
	default:
		break;
	}

	source->stream_state = new_state;
}
Пример #24
0
void connection_unregister(struct btd_service *service)
{
	struct btd_device *device = btd_service_get_device(service);
	struct network_conn *conn = btd_service_get_user_data(service);
	struct network_peer *peer = conn->peer;
	uint16_t id = get_service_id(service);

	DBG("%s id %u", device_get_path(device), id);

	peer->connections = g_slist_remove(peer->connections, conn);
	connection_free(conn);

	if (peer->connections != NULL)
		return;

	g_dbus_unregister_interface(btd_get_dbus_connection(),
						device_get_path(device),
						NETWORK_PEER_INTERFACE);
}
Пример #25
0
static DBusMessage *local_connect(DBusConnection *conn,
						DBusMessage *msg, void *data)
{
	struct network_peer *peer = data;
	struct btd_service *service;
	struct network_conn *nc;
	const char *svc;
	const char *uuid;
	uint16_t id;
	int err;

	if (dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &svc,
						DBUS_TYPE_INVALID) == FALSE)
		return btd_error_invalid_args(msg);

	id = bnep_service_id(svc);
	uuid = bnep_uuid(id);

	if (uuid == NULL)
		return btd_error_invalid_args(msg);

	service = btd_device_get_service(peer->device, uuid);
	if (service == NULL)
		return btd_error_not_supported(msg);

	nc = btd_service_get_user_data(service);

	if (nc->connect != NULL)
		return btd_error_busy(msg);

	err = connection_connect(nc->service);
	if (err < 0)
		return btd_error_failed(msg, strerror(-err));

	nc->connect = dbus_message_ref(msg);

	return NULL;
}
Пример #26
0
static int gap_probe(struct btd_service *service)
{
	struct btd_device *device = btd_service_get_device(service);
	struct gas *gas = btd_service_get_user_data(service);
	char addr[18];

	ba2str(device_get_address(device), addr);
	DBG("GAP profile probe (%s)", addr);

	/* Ignore, if we were probed for this device already */
	if (gas) {
		error("Profile probed twice for the same device!");
		return -1;
	}

	gas = g_new0(struct gas, 1);
	if (!gas)
		return -1;

	gas->device = btd_device_ref(device);
	btd_service_set_user_data(service, gas);

	return 0;
}