static int hidp_add_connection(const struct input_device *idev, const 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]; int err; 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); sdp_record_free(rec); read_device_id(src_addr, dst_addr, NULL, &req->vendor, &req->product, &req->version); fake_hid = get_fake_hid(req->vendor, req->product); if (fake_hid) { fake = g_new0(struct fake_input, 1); fake->connect = fake_hid_connect; fake->disconnect = fake_hid_disconnect; fake->priv = fake_hid; err = fake_hid_connadd(fake, iconn->intr_io, fake_hid); goto cleanup; } if (idev->name) strncpy(req->name, idev->name, sizeof(req->name) - 1); /* Encryption is mandatory for keyboards */ if (req->subclass & 0x40) { err = bt_acl_encrypt(&idev->src, &idev->dst, encrypt_completed, req); if (err == 0) { /* Waiting async encryption */ return 0; } else if (err != -EALREADY) { error("bt_acl_encrypt(): %s(%d)", strerror(-err), -err); goto cleanup; } } err = ioctl_connadd(req); cleanup: free(req->rd_data); g_free(req); return err; }
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; }