Re: [PATCH v3] input: tablet: add Pegasus Notetaker tablet driver

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Mon, 2016-05-23 at 13:39 +0200, Martin Kepplinger wrote:

> It's *really* fun to use as an input tablet though! So let's support this
> for everybody.

Hi,

I am afraid there are a few issues.

1. Why the kernel thread?
2. This driver has questionable power management.

	Regards
		Oliver

> +static int pegasus_probe(struct usb_interface *intf,
> +			 const struct usb_device_id *id)
> +{
> +	struct usb_device *dev = interface_to_usbdev(intf);
> +	struct usb_endpoint_descriptor *endpoint;
> +	struct pegasus *pegasus;
> +	struct input_dev *input_dev;
> +	int error;
> +	int pipe, maxp;
> +
> +	/* we control interface 0 */
> +	if (intf->cur_altsetting->desc.bInterfaceNumber == 1)
> +		return -ENODEV;
> +
> +	endpoint = &intf->cur_altsetting->endpoint[0].desc;
> +
> +	pegasus = kzalloc(sizeof(*pegasus), GFP_KERNEL);
> +	input_dev = input_allocate_device();
> +	if (!pegasus || !input_dev) {
> +		error = -ENOMEM;
> +		goto err_free_mem;
> +	}
> +
> +	pegasus->usbdev = dev;
> +	pegasus->dev = input_dev;
> +
> +	pegasus->data = usb_alloc_coherent(dev, endpoint->wMaxPacketSize,
> +					   GFP_KERNEL, &pegasus->data_dma);
> +	if (!pegasus->data) {
> +		error = -ENOMEM;
> +		goto err_free_mem;
> +	}
> +
> +	pegasus->irq = usb_alloc_urb(0, GFP_KERNEL);
> +	if (!pegasus->irq) {
> +		error = -ENOMEM;
> +		goto err_free_mem;
> +	}
> +
> +	pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress);
> +	maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe));
> +	pegasus->data_len = maxp;
> +
> +	usb_fill_int_urb(pegasus->irq, dev, pipe, pegasus->data, maxp,
> +			 pegasus_irq, pegasus, endpoint->bInterval);
> +
> +	pegasus->irq->transfer_dma = pegasus->data_dma;
> +	pegasus->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
> +
> +	if (dev->manufacturer)
> +		strlcpy(pegasus->name, dev->manufacturer,
> +			sizeof(pegasus->name));
> +
> +	if (dev->product) {
> +		if (dev->manufacturer)
> +			strlcat(pegasus->name, " ", sizeof(pegasus->name));
> +		strlcat(pegasus->name, dev->product, sizeof(pegasus->name));
> +	}
> +
> +	if (!strlen(pegasus->name))
> +		snprintf(pegasus->name, sizeof(pegasus->name),
> +			 "USB Pegasus Device %04x:%04x",
> +			 le16_to_cpu(dev->descriptor.idVendor),
> +			 le16_to_cpu(dev->descriptor.idProduct));
> +
> +	usb_make_path(dev, pegasus->phys, sizeof(pegasus->phys));
> +	strlcat(pegasus->phys, "/input0", sizeof(pegasus->phys));
> +
> +	usb_set_intfdata(intf, pegasus);
> +
> +	input_dev->name = pegasus->name;
> +	input_dev->phys = pegasus->phys;
> +	usb_to_input_id(dev, &input_dev->id);
> +	input_dev->dev.parent = &intf->dev;
> +
> +	input_set_drvdata(input_dev, pegasus);
> +
> +	input_dev->open = pegasus_open;
> +	input_dev->close = pegasus_close;
> +
> +	__set_bit(EV_ABS, input_dev->evbit);
> +	__set_bit(EV_KEY, input_dev->evbit);
> +
> +	__set_bit(ABS_X, input_dev->absbit);
> +	__set_bit(ABS_Y, input_dev->absbit);
> +
> +	__set_bit(BTN_TOUCH, input_dev->keybit);
> +	__set_bit(BTN_RIGHT, input_dev->keybit);
> +	__set_bit(BTN_TOOL_PEN, input_dev->keybit);
> +
> +	__set_bit(INPUT_PROP_DIRECT, input_dev->propbit);
> +	__set_bit(INPUT_PROP_POINTER, input_dev->propbit);
> +
> +	input_set_abs_params(input_dev, ABS_X, -1500, 1500, 8, 0);
> +	input_set_abs_params(input_dev, ABS_Y, 1600, 3000, 8, 0);
> +
> +	error = input_register_device(pegasus->dev);
> +	if (error)
> +		goto err_free_dma;
> +
> +	pegasus_thread = kthread_run(pegasus_threadf, pegasus,
> +				     "pegasus_notetaker_thread");

Why is that needed?

> +	if (IS_ERR(pegasus_thread)) {
> +		error = -ENOMEM;
> +		goto err_free_dma;
> +	}
> +
> +	return 0;
> +
> +err_free_dma:
> +	usb_free_coherent(dev, pegasus->data_len,
> +			  pegasus->data, pegasus->data_dma);
> +
> +	usb_free_urb(pegasus->irq);
> +err_free_mem:
> +	kfree(pegasus);
> +	usb_set_intfdata(intf, NULL);
> +
> +	return error;
> +}
> +
> +static void pegasus_disconnect(struct usb_interface *intf)
> +{
> +	struct pegasus *pegasus = usb_get_intfdata(intf);
> +
> +	input_unregister_device(pegasus->dev);
> +	if (pegasus_thread) {
> +		if (kthread_stop(pegasus_thread) == -EINTR)
> +			dev_err(&pegasus->usbdev->dev,
> +				"wake_up_proc was never called\n");
> +	}
> +
> +	usb_free_urb(pegasus->irq);
> +	usb_free_coherent(interface_to_usbdev(intf),
> +			  pegasus->data_len, pegasus->data,
> +			  pegasus->data_dma);
> +	kfree(pegasus);
> +	usb_set_intfdata(intf, NULL);
> +}
> +
> +static const struct usb_device_id pegasus_ids[] = {
> +	{ USB_DEVICE(USB_VENDOR_ID_PEGASUSTECH,
> +		     USB_DEVICE_ID_PEGASUS_NOTETAKER_EN100) },
> +	{ }
> +};
> +MODULE_DEVICE_TABLE(usb, pegasus_ids);
> +
> +static struct usb_driver pegasus_driver = {
> +	.name		= "pegasus_notetaker",
> +	.probe		= pegasus_probe,
> +	.disconnect	= pegasus_disconnect,
> +	.id_table	= pegasus_ids,
> +};
> +
> +module_usb_driver(pegasus_driver);
> +
> +MODULE_AUTHOR("Martin Kepplinger <martink@xxxxxxxxx>");
> +MODULE_DESCRIPTION("Pegasus Mobile Notetaker Pen tablet driver");
> +MODULE_LICENSE("GPL");



--
To unsubscribe from this list: send the line "unsubscribe linux-input" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Index of Archives]     [Linux Media Devel]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Linux Wireless Networking]     [Linux Omap]

  Powered by Linux