Пример #1
0
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;
}
Пример #2
0
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;
}