예제 #1
0
static int uhid_dev_create(struct uhid_device *uhid,
			   const struct uhid_event *ev)
{
	struct hid_device *hid;
	int ret;

	if (uhid->running)
		return -EALREADY;

	uhid->rd_size = ev->u.create.rd_size;
	if (uhid->rd_size <= 0 || uhid->rd_size > HID_MAX_DESCRIPTOR_SIZE)
		return -EINVAL;

	uhid->rd_data = kmalloc(uhid->rd_size, GFP_KERNEL);
	if (!uhid->rd_data)
		return -ENOMEM;

	if (copy_from_user(uhid->rd_data, ev->u.create.rd_data,
			   uhid->rd_size)) {
		ret = -EFAULT;
		goto err_free;
	}

	hid = hid_allocate_device();
	if (IS_ERR(hid)) {
		ret = PTR_ERR(hid);
		goto err_free;
	}

	strncpy(hid->name, ev->u.create.name, 127);
	hid->name[127] = 0;
	strncpy(hid->phys, ev->u.create.phys, 63);
	hid->phys[63] = 0;
	strncpy(hid->uniq, ev->u.create.uniq, 63);
	hid->uniq[63] = 0;

	hid->ll_driver = &uhid_hid_driver;
	hid->hid_get_raw_report = uhid_hid_get_raw;
	hid->hid_output_raw_report = uhid_hid_output_raw;
	hid->bus = ev->u.create.bus;
	hid->vendor = ev->u.create.vendor;
	hid->product = ev->u.create.product;
	hid->version = ev->u.create.version;
	hid->country = ev->u.create.country;
	hid->driver_data = uhid;
	hid->dev.parent = uhid_misc.this_device;

	uhid->hid = hid;
	uhid->running = true;

	ret = hid_add_device(hid);
	if (ret) {
		hid_err(hid, "Cannot register HID device\n");
		goto err_hid;
	}

	return 0;

err_hid:
	hid_destroy_device(hid);
	uhid->hid = NULL;
	uhid->running = false;
err_free:
	kfree(uhid->rd_data);
	return ret;
}
예제 #2
0
static void logi_dj_recv_add_djhid_device(struct dj_receiver_dev *djrcv_dev,
					  struct dj_report *dj_report)
{
	/* Called in delayed work context */
	struct hid_device *djrcv_hdev = djrcv_dev->hdev;
	struct usb_interface *intf = to_usb_interface(djrcv_hdev->dev.parent);
	struct usb_device *usbdev = interface_to_usbdev(intf);
	struct hid_device *dj_hiddev;
	struct dj_device *dj_dev;

	/* Device index goes from 1 to 6, we need 3 bytes to store the
	 * semicolon, the index, and a null terminator
	 */
	unsigned char tmpstr[3];

	if (dj_report->report_params[DEVICE_PAIRED_PARAM_SPFUNCTION] &
	    SPFUNCTION_DEVICE_LIST_EMPTY) {
		dbg_hid("%s: device list is empty\n", __func__);
		return;
	}

	if (djrcv_dev->paired_dj_devices[dj_report->device_index]) {
		/* The device is already known. No need to reallocate it. */
		dbg_hid("%s: device is already known\n", __func__);
		return;
	}

	dj_hiddev = hid_allocate_device();
	if (IS_ERR(dj_hiddev)) {
		dev_err(&djrcv_hdev->dev, "%s: hid_allocate_device failed\n",
			__func__);
		return;
	}

	dj_hiddev->ll_driver = &logi_dj_ll_driver;
	dj_hiddev->hid_output_raw_report = logi_dj_output_hidraw_report;

	dj_hiddev->dev.parent = &djrcv_hdev->dev;
	dj_hiddev->bus = BUS_USB;
	dj_hiddev->vendor = le16_to_cpu(usbdev->descriptor.idVendor);
	dj_hiddev->product = le16_to_cpu(usbdev->descriptor.idProduct);
	snprintf(dj_hiddev->name, sizeof(dj_hiddev->name),
		"Logitech Unifying Device. Wireless PID:%02x%02x",
		dj_report->report_params[DEVICE_PAIRED_PARAM_EQUAD_ID_MSB],
		dj_report->report_params[DEVICE_PAIRED_PARAM_EQUAD_ID_LSB]);

	usb_make_path(usbdev, dj_hiddev->phys, sizeof(dj_hiddev->phys));
	snprintf(tmpstr, sizeof(tmpstr), ":%d", dj_report->device_index);
	strlcat(dj_hiddev->phys, tmpstr, sizeof(dj_hiddev->phys));

	dj_dev = kzalloc(sizeof(struct dj_device), GFP_KERNEL);

	if (!dj_dev) {
		dev_err(&djrcv_hdev->dev, "%s: failed allocating dj_device\n",
			__func__);
		goto dj_device_allocate_fail;
	}

	dj_dev->reports_supported = le32_to_cpu(
		dj_report->report_params[DEVICE_PAIRED_RF_REPORT_TYPE]);
	dj_dev->hdev = dj_hiddev;
	dj_dev->dj_receiver_dev = djrcv_dev;
	dj_dev->device_index = dj_report->device_index;
	dj_hiddev->driver_data = dj_dev;

	djrcv_dev->paired_dj_devices[dj_report->device_index] = dj_dev;

	if (hid_add_device(dj_hiddev)) {
		dev_err(&djrcv_hdev->dev, "%s: failed adding dj_device\n",
			__func__);
		goto hid_add_device_fail;
	}

	return;

hid_add_device_fail:
	djrcv_dev->paired_dj_devices[dj_report->device_index] = NULL;
	kfree(dj_dev);
dj_device_allocate_fail:
	hid_destroy_device(dj_hiddev);
}
예제 #3
0
static int bthid_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
{
    int ret;
    char *name;
    struct bthid_ctrl *p_ctrl;
    struct bthid_device *p_dev = file->private_data;
    struct bthid_di di;

#ifdef CONFIG_DEBUG_PRINTK
    printk(KERN_INFO "######## bthid_ioctl: cmd = %d ########\n", cmd);
#else
    ;
#endif

    if (p_dev == NULL)
    {
        return -EINVAL;
    }

    if (cmd == BTHID_IOCTL_RPT_NAME) {
        name = kzalloc(BTHID_DEV_NAME_LEN, GFP_KERNEL);

        if (name == NULL)
            return -ENOMEM;

        if (copy_from_user(name, (void __user *)arg, BTHID_DEV_NAME_LEN)) {
            kfree(name);
            return -EFAULT;
        }

#ifdef CONFIG_DEBUG_PRINTK
	printk(KERN_INFO "%s: name=%s\n", __func__, name);
#else
	;
#endif

        if (!p_dev->hid) {
            p_dev->hid = hid_allocate_device();
            if (p_dev->hid == NULL)
            {
#ifdef CONFIG_DEBUG_PRINTK
		printk(KERN_INFO "Oops: Failed to allocation HID device.\n");
#else
		;
#endif
                kfree(name);
                return -ENOMEM;
            }
        }

        strncpy(p_dev->hid->name, name, 128);

        kfree(name);
    } else if (cmd == BTHID_IOCTL_RPT_DI) {
        if (copy_from_user(&di, (void __user *) arg, sizeof(struct bthid_di)) != 0)
        {
            return -EFAULT;
        }

#ifdef CONFIG_DEBUG_PRINTK
	printk(KERN_INFO "%s: vendor=0x%04x, product=0x%04x, version=0x%04x, country=0x%02x\n",
			__func__, di.vendor_id, di.product_id, di.version, di.ctry_code);
#else
	;
#endif
		
        if (!p_dev->hid) {
            p_dev->hid = hid_allocate_device();
            if (p_dev->hid == NULL)
            {
#ifdef CONFIG_DEBUG_PRINTK
		printk(KERN_INFO "Oops: Failed to allocation HID device.\n");
#else
		;
#endif
                return -ENOMEM;
            }
        }
            p_dev->hid->vendor = di.vendor_id;
            p_dev->hid->product = di.product_id;
            p_dev->hid->version = di.version;
            p_dev->hid->country = di.ctry_code;  
    } else if (cmd == BTHID_IOCTL_RPT_DSCP) {
    p_ctrl = kmalloc(sizeof(struct bthid_ctrl), GFP_KERNEL);
    if (p_ctrl == NULL)
    {
        return -ENOMEM;
    }

    if (copy_from_user(p_ctrl, (void __user *) arg, sizeof(struct bthid_ctrl)) != 0)
    {
        kfree(p_ctrl);
        return -EFAULT;
    }

    if (p_ctrl->size <= 0) 
    {
#ifdef CONFIG_DEBUG_PRINTK
	printk(KERN_INFO "Oops: Invalid BT HID report descriptor size %d\n",
			p_ctrl->size);
#else
	;
#endif

        kfree(p_ctrl);
        return -EINVAL;
    }
    
        if (!p_dev->hid) {
    p_dev->hid = hid_allocate_device();
    if (p_dev->hid == NULL)
    {
#ifdef CONFIG_DEBUG_PRINTK
	printk(KERN_INFO "Oops: Failed to allocation HID device.\n");
#else
	;
#endif

        kfree(p_ctrl);
        return -ENOMEM;
    }
        }

	if (p_dev->hid->vendor == 0x04E8 && p_dev->hid->product == 0x7021) {
		strcpy(p_dev->hid->name, "Vendor_04E8_Product_7021");
		p_dev->hid->name[strlen("Vendor_04E8_Product_7021")] =  '\0';
	} else {
		strcpy(p_dev->hid->name, "Broadcom Bluetooth HID");
		p_dev->hid->vendor = 0;
		p_dev->hid->product = 0;
		p_dev->hid->version = 0;
		p_dev->hid->country = 0;
		p_dev->hid->name[strlen("Broadcom Bluetooth HID")] =  '\0';
	}
    
    p_dev->hid->bus         = BUS_BLUETOOTH;
    p_dev->hid->ll_driver   = &bthid_ll_driver;
    p_dev->hid->driver_data = p_ctrl;


    ret = hid_add_device(p_dev->hid);

#ifdef CONFIG_DEBUG_PRINTK
	printk(KERN_INFO "hid_add_device: ret = %d, hid->status = %d\n",
		    ret, p_dev->hid->status);
#else
	;
#endif

    if (ret != 0)
    {
#ifdef CONFIG_DEBUG_PRINTK
	printk(KERN_INFO "Oops: Failed to add HID device");
#else
	;
#endif

        kfree(p_ctrl);
        hid_destroy_device(p_dev->hid);
        p_dev->hid = NULL;
        return -EINVAL;
    }
    p_dev->hid->claimed |= HID_CLAIMED_INPUT;

    if (p_dev->hid->status != (HID_STAT_ADDED | HID_STAT_PARSED))
    {
#ifdef CONFIG_DEBUG_PRINTK
	printk(KERN_INFO "Oops: Failed to process HID report descriptor");
#else
	;
#endif
        return -EINVAL;
    }

    p_dev->dscp_set = 1;
    } else {
#ifdef CONFIG_DEBUG_PRINTK
	printk(KERN_INFO "Invlid ioctl value");
#else
	;
#endif
        return -EINVAL;
    }

#ifdef CONFIG_DEBUG_PRINTK
    printk(KERN_INFO "######## bthid_ioctl: done ########\n");
#else
    ;
#endif
    return 0;
}
static long bthid_unlocked_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
//static int bthid_unlocked_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
    int ret;
    struct bthid_ctrl *p_ctrl;
    struct bthid_device *p_dev = file->private_data;

    printk("######## bthid_unlocked_ioctl: cmd = %d ########\n", cmd);

    if (cmd != BTHID_IOCTL_HID_INFO || p_dev == NULL)
    {
        return -EINVAL;
    }

    p_ctrl = kmalloc(sizeof(struct bthid_ctrl), GFP_KERNEL);
    if (p_ctrl == NULL)
    {
        return -ENOMEM;
    }

    if (copy_from_user(p_ctrl, (void __user *) arg, sizeof(struct bthid_ctrl)) != 0)
    {
        kfree(p_ctrl);
        return -EFAULT;
    }

    printk("bthid: name = [%s], VID/PID = %04x/%04x, version = 0x%04x, country = 0x%02x\n",
           p_ctrl->dev_name, p_ctrl->vendor_id, p_ctrl->product_id,
           p_ctrl->version, p_ctrl->ctry_code);

    if (p_ctrl->dscp_len <= 0) 
    {
        printk("Oops: Invalid BT HID report descriptor size %d\n", p_ctrl->dscp_len); 

        kfree(p_ctrl);
        return -EINVAL;
    }
    
    p_dev->hid = hid_allocate_device();
    if (p_dev->hid == NULL)
    {
        printk("Oops: Failed to allocation HID device.\n");

        kfree(p_ctrl);
        return -ENOMEM;
    }
    
    p_dev->hid->bus         = BUS_BLUETOOTH;
    p_dev->hid->vendor      = p_ctrl->vendor_id;
    p_dev->hid->product     = p_ctrl->product_id;
    p_dev->hid->version     = p_ctrl->version;
    p_dev->hid->country     = p_ctrl->ctry_code;
    p_dev->hid->ll_driver   = &bthid_ll_driver;
    p_dev->hid->driver_data = p_ctrl;

    // strcpy(p_dev->hid->name, "Broadcom Bluetooth HID");
    strncpy(p_dev->hid->name, p_ctrl->dev_name, BTHID_MAX_DEV_NAME_LEN);

    ret = hid_add_device(p_dev->hid);

    printk("hid_add_device: ret = %d, hid->status = %d\n", ret, p_dev->hid->status);

    if (ret != 0)
    {
        printk("Oops: Failed to add HID device");

        kfree(p_ctrl);
        hid_destroy_device(p_dev->hid);
        p_dev->hid = NULL;
        return -EINVAL;
    }
    p_dev->hid->claimed |= HID_CLAIMED_INPUT;

    if (p_dev->hid->status != (HID_STAT_ADDED | HID_STAT_PARSED))
    {
        printk("Oops: Failed to process HID report descriptor");
        return -EINVAL;
    }

    p_dev->dscp_set = 1;

    printk("######## bthid_unlocked_ioctl: done ########\n");
    return 0;
}
예제 #5
0
static int mousevsc_probe(struct hv_device *device,
			const struct hv_vmbus_device_id *dev_id)
{
	int ret;
	struct mousevsc_dev *input_dev;
	struct hid_device *hid_dev;

	input_dev = mousevsc_alloc_device(device);

	if (!input_dev)
		return -ENOMEM;

	ret = vmbus_open(device->channel,
		INPUTVSC_SEND_RING_BUFFER_SIZE,
		INPUTVSC_RECV_RING_BUFFER_SIZE,
		NULL,
		0,
		mousevsc_on_channel_callback,
		device
		);

	if (ret)
		goto probe_err0;

	ret = mousevsc_connect_to_vsp(device);

	if (ret)
		goto probe_err1;

	/* workaround SA-167 */
	if (input_dev->report_desc[14] == 0x25)
		input_dev->report_desc[14] = 0x29;

	hid_dev = hid_allocate_device();
	if (IS_ERR(hid_dev)) {
		ret = PTR_ERR(hid_dev);
		goto probe_err1;
	}

	hid_dev->ll_driver = &mousevsc_ll_driver;
	hid_dev->driver = &mousevsc_hid_driver;
	hid_dev->bus = BUS_VIRTUAL;
	hid_dev->vendor = input_dev->hid_dev_info.vendor;
	hid_dev->product = input_dev->hid_dev_info.product;
	hid_dev->version = input_dev->hid_dev_info.version;
	input_dev->hid_device = hid_dev;

	sprintf(hid_dev->name, "%s", "Microsoft Vmbus HID-compliant Mouse");

	hid_set_drvdata(hid_dev, device);

	ret = hid_add_device(hid_dev);
	if (ret)
		goto probe_err1;


	ret = hid_parse(hid_dev);
	if (ret) {
		hid_err(hid_dev, "parse failed\n");
		goto probe_err2;
	}

	ret = hid_hw_start(hid_dev, HID_CONNECT_HIDINPUT | HID_CONNECT_HIDDEV);

	if (ret) {
		hid_err(hid_dev, "hw start failed\n");
		goto probe_err2;
	}

	input_dev->connected = true;
	input_dev->init_complete = true;

	return ret;

probe_err2:
	hid_destroy_device(hid_dev);

probe_err1:
	vmbus_close(device->channel);

probe_err0:
	mousevsc_free_device(input_dev);

	return ret;
}
예제 #6
0
static int bthid_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
{
    int ret;
    struct bthid_ctrl *p_ctrl;
    struct bthid_device *p_dev = file->private_data;

    printk("######## bthid_ioctl: cmd = %d ########\n", cmd);

    if (cmd != BTHID_IOCTL_RPT_DSCP || p_dev == NULL)
    {
        return -EINVAL;
    }

    p_ctrl = kmalloc(sizeof(struct bthid_ctrl), GFP_KERNEL);
    if (p_ctrl == NULL)
    {
        return -ENOMEM;
    }

    if (copy_from_user(p_ctrl, (void __user *) arg, sizeof(struct bthid_ctrl)) != 0)
    {
        kfree(p_ctrl);
        return -EFAULT;
    }

    if (p_ctrl->size <= 0) 
    {
        printk("Oops: Invalid BT HID report descriptor size %d\n", p_ctrl->size); 

        kfree(p_ctrl);
        return -EINVAL;
    }
    
    p_dev->hid = hid_allocate_device();
    if (p_dev->hid == NULL)
    {
        printk("Oops: Failed to allocation HID device.\n");

        kfree(p_ctrl);
        return -ENOMEM;
    }
    
    p_dev->hid->bus         = BUS_BLUETOOTH;
    p_dev->hid->vendor      = 0;
    p_dev->hid->product     = 0;
    p_dev->hid->version     = 0;
    p_dev->hid->country     = 0;
    p_dev->hid->ll_driver   = &bthid_ll_driver;
    p_dev->hid->driver_data = p_ctrl;

    strcpy(p_dev->hid->name, "Broadcom Bluetooth HID");

    ret = hid_add_device(p_dev->hid);

    printk("hid_add_device: ret = %d, hid->status = %d\n", ret, p_dev->hid->status);

    if (ret != 0)
    {
        printk("Oops: Failed to add HID device");

        kfree(p_ctrl);
        hid_destroy_device(p_dev->hid);
        p_dev->hid = NULL;
        return -EINVAL;
    }
    p_dev->hid->claimed |= HID_CLAIMED_INPUT;

    if (p_dev->hid->status != (HID_STAT_ADDED | HID_STAT_PARSED))
    {
        printk("Oops: Failed to process HID report descriptor");
        return -EINVAL;
    }

    p_dev->dscp_set = 1;

    printk("######## bthid_ioctl: done ########\n");
    return 0;
}
예제 #7
0
static long bthid_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
#endif
{
    struct bthid_ctrl *p_ctrl;
    struct bthid_device *p_dev = file->private_data;

    printk("######## bthid_ioctl: cmd = %d ########\n", cmd);

    if (cmd != BTHID_IOCTL_RPT_DSCP || p_dev == NULL)
    {
        return -EINVAL;
    }

    p_ctrl = kmalloc(sizeof(struct bthid_ctrl), GFP_KERNEL);
    if (p_ctrl == NULL)
    {
        return -ENOMEM;
    }

    if (copy_from_user(p_ctrl, (void __user *) arg, sizeof(struct bthid_ctrl)) != 0)
    {
        kfree(p_ctrl);
        return -EFAULT;
    }

    if (p_ctrl->size <= 0) 
    {
        printk("Oops: Invalid BT HID report descriptor size %d\n", p_ctrl->size); 

        kfree(p_ctrl);
        return -EINVAL;
    }
    
    p_dev->hid = hid_allocate_device();
    if (p_dev->hid == NULL)
    {
        printk("Oops: Failed to allocation HID device.\n");

        kfree(p_ctrl);
        return -ENOMEM;
    }
    
    p_dev->hid->bus         = BUS_BLUETOOTH;
    p_dev->hid->vendor      = 0;
    p_dev->hid->product     = 0;
    p_dev->hid->version     = 0;
    p_dev->hid->country     = 0;
    p_dev->hid->ll_driver   = &bthid_ll_driver;
    p_dev->hid->driver_data = p_ctrl;

    strcpy(p_dev->hid->name, "Broadcom Bluetooth HID");

    if (hid_add_device(p_dev->hid) != 0)
    {
        printk("Oops: Failed to add HID device\n");

        kfree(p_ctrl);
        hid_destroy_device(p_dev->hid);
        p_dev->hid = NULL;
        return -EINVAL;
    }

    // TBD: don't know whether it is required
    if (hidinput_connect(p_dev->hid, 0) == 0) 
    {
        printk("bthid_ioctl: HID Interface Claimed...\n");
        p_dev->hid->claimed |= HID_CLAIMED_INPUT;
    }
    p_dev->dscp_set = 1;

    printk("######## bthid_ioctl: done ########\n");
    return 0;
}