static int hidp_add_connection(struct input_device *idev) { struct hidp_connadd_req *req; sdp_record_t *rec; char src_addr[18], dst_addr[18]; char filename[PATH_MAX + 1]; GKeyFile *key_file; char handle[11], *str; GError *gerr = NULL; int err; req = g_new0(struct hidp_connadd_req, 1); req->ctrl_sock = g_io_channel_unix_get_fd(idev->ctrl_io); req->intr_sock = g_io_channel_unix_get_fd(idev->intr_io); req->flags = 0; req->idle_to = idle_timeout; ba2str(&idev->src, src_addr); ba2str(&idev->dst, dst_addr); snprintf(filename, PATH_MAX, STORAGEDIR "/%s/cache/%s", src_addr, dst_addr); filename[PATH_MAX] = '\0'; sprintf(handle, "0x%8.8X", idev->handle); key_file = g_key_file_new(); g_key_file_load_from_file(key_file, filename, 0, NULL); str = g_key_file_get_string(key_file, "ServiceRecords", handle, NULL); g_key_file_free(key_file); if (!str) { error("Rejected connection from unknown device %s", dst_addr); err = -EPERM; goto cleanup; } rec = record_from_string(str); g_free(str); err = extract_hid_record(rec, req); sdp_record_free(rec); if (err < 0) { error("Could not parse HID SDP record: %s (%d)", strerror(-err), -err); goto cleanup; } req->vendor = btd_device_get_vendor(idev->device); req->product = btd_device_get_product(idev->device); req->version = btd_device_get_version(idev->device); if (idev->name) strncpy(req->name, idev->name, sizeof(req->name) - 1); /* Encryption is mandatory for keyboards */ if (req->subclass & 0x40) { if (!bt_io_set(idev->intr_io, &gerr, BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_MEDIUM, BT_IO_OPT_INVALID)) { error("btio: %s", gerr->message); g_error_free(gerr); err = -EFAULT; goto cleanup; } idev->req = req; idev->sec_watch = g_io_add_watch(idev->intr_io, G_IO_OUT, encrypt_notify, idev); return 0; } err = ioctl_connadd(req); cleanup: g_free(req->rd_data); g_free(req); return err; }
static int handle_device (libusb_device *dev, struct libusb_config_descriptor *cfg, int itfnum, const struct libusb_interface_descriptor *alt) { libusb_device_handle *devh; int res, retval; retval = -1; if (libusb_open (dev, &devh) < 0) { g_warning ("Can't open device"); goto bail; } libusb_detach_kernel_driver (devh, itfnum); res = libusb_claim_interface (devh, itfnum); if (res < 0) { g_warning ("Can't claim interface %d", itfnum); goto bail; } if (option_get_master != FALSE) { if (show_master (devh, itfnum) == FALSE) goto bail; retval = 0; } if (option_master != NULL) { if (strcmp (option_master, "auto") == 0) { g_free (option_master); option_master = get_host_bdaddr (); if (option_master == NULL) { g_warning ("Can't get bdaddr from default device"); retval = -1; goto bail; } } } else { option_master = get_host_bdaddr (); if (option_master == NULL) { g_warning ("Can't get bdaddr from default device"); retval = -1; goto bail; } } if (option_store_info != FALSE) { sdp_record_t *rec; char *device; bdaddr_t dst, src; device = get_bdaddr (devh, itfnum); if (device == NULL) { retval = -1; goto bail; } rec = record_from_string (PS3_PNP_RECORD); store_record(option_master, device, rec); write_trust(option_master, device, "[all]", TRUE); store_device_id(option_master, device, 0xffff, 0x054c, 0x0268, 0); str2ba(option_master, &src); str2ba(device, &dst); write_device_profiles(&src, &dst, ""); write_device_name(&src, &dst, "PLAYSTATION(R)3 Controller"); sdp_record_free(rec); if (set_master_bdaddr (devh, itfnum, option_master) == FALSE) { retval = -1; goto bail; } } bail: libusb_release_interface (devh, itfnum); res = libusb_attach_kernel_driver(devh, itfnum); if (res < 0) { //FIXME sometimes the kernel tells us ENOENT, but succeeds anyway... g_warning ("Reattaching the driver failed: %d", res); } if (devh != NULL) libusb_close (devh); return retval; }