Exemple #1
0
static struct input_device *input_device_new(struct btd_service *service)
{
    struct btd_device *device = btd_service_get_device(service);
    struct btd_profile *p = btd_service_get_profile(service);
    const char *path = device_get_path(device);
    const sdp_record_t *rec = btd_device_get_record(device, p->remote_uuid);
    struct btd_adapter *adapter = device_get_adapter(device);
    struct input_device *idev;
    char name[HCI_MAX_NAME_LENGTH + 1];

    idev = g_new0(struct input_device, 1);
    bacpy(&idev->src, btd_adapter_get_address(adapter));
    bacpy(&idev->dst, device_get_address(device));
    idev->service = btd_service_ref(service);
    idev->device = btd_device_ref(device);
    idev->path = g_strdup(path);
    idev->handle = rec->handle;
    idev->disable_sdp = is_device_sdp_disable(rec);

    device_get_name(device, name, HCI_MAX_NAME_LENGTH);
    if (strlen(name) > 0)
        idev->name = g_strdup(name);

    /* Initialize device properties */
    extract_hid_props(idev, rec);

    return idev;
}
Exemple #2
0
static int hidp_add_connection(struct input_device *idev,
					struct input_conn *iconn)
{
	struct hidp_connadd_req *req;
	struct fake_hid *fake_hid;
	struct fake_input *fake;
	sdp_record_t *rec;
	char src_addr[18], dst_addr[18];
	GError *gerr = NULL;
	int err;

	DBG("idev %p", idev);

	req = g_new0(struct hidp_connadd_req, 1);
	req->ctrl_sock = g_io_channel_unix_get_fd(iconn->ctrl_io);
	req->intr_sock = g_io_channel_unix_get_fd(iconn->intr_io);
	req->flags     = 0;
	req->idle_to   = iconn->timeout;

	ba2str(&idev->src, src_addr);
	ba2str(&idev->dst, dst_addr);

	rec = fetch_record(src_addr, dst_addr, idev->handle);
	if (!rec) {
		error("Rejected connection from unknown device %s", dst_addr);
		err = -EPERM;
		goto cleanup;
	}

	extract_hid_record(rec, req);
	extract_hid_props(idev, rec);
	sdp_record_free(rec);

	req->vendor = btd_device_get_vendor(idev->device);
	req->product = btd_device_get_product(idev->device);
	req->version = btd_device_get_version(idev->device);

	fake_hid = get_fake_hid(req->vendor, req->product);
	if (fake_hid) {
		err = 0;
		fake = g_new0(struct fake_input, 1);
		fake->connect = fake_hid_connect;
		fake->disconnect = fake_hid_disconnect;
		fake->priv = fake_hid;
		fake->idev = idev;
		fake = fake_hid_connadd(fake, iconn->intr_io, fake_hid);
		if (fake == NULL)
			err = -ENOMEM;
		else
			fake->flags |= FI_FLAG_CONNECTED;
		goto cleanup;
	}

	if (idev->name)
		strncpy(req->name, idev->name, sizeof(req->name) - 1);

	/* Encryption is mandatory for keyboards */
	if (req->subclass & 0x40) {
		struct btd_adapter *adapter = device_get_adapter(idev->device);

		err = btd_adapter_encrypt_link(adapter, (bdaddr_t *) &idev->dst,
						encrypt_completed, req);
		if (err == 0) {
			/* Waiting async encryption */
			return 0;
		}

		if (err == -ENOSYS)
			goto nosys;

		if (err != -EALREADY) {
			error("encrypt_link: %s (%d)", strerror(-err), -err);
			goto cleanup;
		}
	}

	err = ioctl_connadd(req);

cleanup:
	free(req->rd_data);
	g_free(req);

	return err;

nosys:
	if (!bt_io_set(iconn->intr_io, BT_IO_L2CAP, &gerr,
				BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_MEDIUM,
				BT_IO_OPT_INVALID)) {
		error("btio: %s", gerr->message);
		g_error_free(gerr);
		goto cleanup;
	}

	iconn->req = req;
	iconn->sec_watch = g_io_add_watch(iconn->intr_io, G_IO_OUT,
							encrypt_notify, iconn);
	return 0;
}