cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

acecad.c (6805B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3 *  Copyright (c) 2001-2005 Edouard TISSERANT   <edouard.tisserant@wanadoo.fr>
      4 *  Copyright (c) 2004-2005 Stephane VOLTZ      <svoltz@numericable.fr>
      5 *
      6 *  USB Acecad "Acecad Flair" tablet support
      7 *
      8 *  Changelog:
      9 *      v3.2 - Added sysfs support
     10 */
     11
     12/*
     13 */
     14
     15#include <linux/kernel.h>
     16#include <linux/slab.h>
     17#include <linux/module.h>
     18#include <linux/usb/input.h>
     19
     20MODULE_AUTHOR("Edouard TISSERANT <edouard.tisserant@wanadoo.fr>");
     21MODULE_DESCRIPTION("USB Acecad Flair tablet driver");
     22MODULE_LICENSE("GPL");
     23
     24#define USB_VENDOR_ID_ACECAD	0x0460
     25#define USB_DEVICE_ID_FLAIR	0x0004
     26#define USB_DEVICE_ID_302	0x0008
     27
     28struct usb_acecad {
     29	char name[128];
     30	char phys[64];
     31	struct usb_interface *intf;
     32	struct input_dev *input;
     33	struct urb *irq;
     34
     35	unsigned char *data;
     36	dma_addr_t data_dma;
     37};
     38
     39static void usb_acecad_irq(struct urb *urb)
     40{
     41	struct usb_acecad *acecad = urb->context;
     42	unsigned char *data = acecad->data;
     43	struct input_dev *dev = acecad->input;
     44	struct usb_interface *intf = acecad->intf;
     45	struct usb_device *udev = interface_to_usbdev(intf);
     46	int prox, status;
     47
     48	switch (urb->status) {
     49	case 0:
     50		/* success */
     51		break;
     52	case -ECONNRESET:
     53	case -ENOENT:
     54	case -ESHUTDOWN:
     55		/* this urb is terminated, clean up */
     56		dev_dbg(&intf->dev, "%s - urb shutting down with status: %d\n",
     57			__func__, urb->status);
     58		return;
     59	default:
     60		dev_dbg(&intf->dev, "%s - nonzero urb status received: %d\n",
     61			__func__, urb->status);
     62		goto resubmit;
     63	}
     64
     65	prox = (data[0] & 0x04) >> 2;
     66	input_report_key(dev, BTN_TOOL_PEN, prox);
     67
     68	if (prox) {
     69		int x = data[1] | (data[2] << 8);
     70		int y = data[3] | (data[4] << 8);
     71		/* Pressure should compute the same way for flair and 302 */
     72		int pressure = data[5] | (data[6] << 8);
     73		int touch = data[0] & 0x01;
     74		int stylus = (data[0] & 0x10) >> 4;
     75		int stylus2 = (data[0] & 0x20) >> 5;
     76		input_report_abs(dev, ABS_X, x);
     77		input_report_abs(dev, ABS_Y, y);
     78		input_report_abs(dev, ABS_PRESSURE, pressure);
     79		input_report_key(dev, BTN_TOUCH, touch);
     80		input_report_key(dev, BTN_STYLUS, stylus);
     81		input_report_key(dev, BTN_STYLUS2, stylus2);
     82	}
     83
     84	/* event termination */
     85	input_sync(dev);
     86
     87resubmit:
     88	status = usb_submit_urb(urb, GFP_ATOMIC);
     89	if (status)
     90		dev_err(&intf->dev,
     91			"can't resubmit intr, %s-%s/input0, status %d\n",
     92			udev->bus->bus_name,
     93			udev->devpath, status);
     94}
     95
     96static int usb_acecad_open(struct input_dev *dev)
     97{
     98	struct usb_acecad *acecad = input_get_drvdata(dev);
     99
    100	acecad->irq->dev = interface_to_usbdev(acecad->intf);
    101	if (usb_submit_urb(acecad->irq, GFP_KERNEL))
    102		return -EIO;
    103
    104	return 0;
    105}
    106
    107static void usb_acecad_close(struct input_dev *dev)
    108{
    109	struct usb_acecad *acecad = input_get_drvdata(dev);
    110
    111	usb_kill_urb(acecad->irq);
    112}
    113
    114static int usb_acecad_probe(struct usb_interface *intf, const struct usb_device_id *id)
    115{
    116	struct usb_device *dev = interface_to_usbdev(intf);
    117	struct usb_host_interface *interface = intf->cur_altsetting;
    118	struct usb_endpoint_descriptor *endpoint;
    119	struct usb_acecad *acecad;
    120	struct input_dev *input_dev;
    121	int pipe, maxp;
    122	int err;
    123
    124	if (interface->desc.bNumEndpoints != 1)
    125		return -ENODEV;
    126
    127	endpoint = &interface->endpoint[0].desc;
    128
    129	if (!usb_endpoint_is_int_in(endpoint))
    130		return -ENODEV;
    131
    132	pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress);
    133	maxp = usb_maxpacket(dev, pipe);
    134
    135	acecad = kzalloc(sizeof(struct usb_acecad), GFP_KERNEL);
    136	input_dev = input_allocate_device();
    137	if (!acecad || !input_dev) {
    138		err = -ENOMEM;
    139		goto fail1;
    140	}
    141
    142	acecad->data = usb_alloc_coherent(dev, 8, GFP_KERNEL, &acecad->data_dma);
    143	if (!acecad->data) {
    144		err= -ENOMEM;
    145		goto fail1;
    146	}
    147
    148	acecad->irq = usb_alloc_urb(0, GFP_KERNEL);
    149	if (!acecad->irq) {
    150		err = -ENOMEM;
    151		goto fail2;
    152	}
    153
    154	acecad->intf = intf;
    155	acecad->input = input_dev;
    156
    157	if (dev->manufacturer)
    158		strlcpy(acecad->name, dev->manufacturer, sizeof(acecad->name));
    159
    160	if (dev->product) {
    161		if (dev->manufacturer)
    162			strlcat(acecad->name, " ", sizeof(acecad->name));
    163		strlcat(acecad->name, dev->product, sizeof(acecad->name));
    164	}
    165
    166	usb_make_path(dev, acecad->phys, sizeof(acecad->phys));
    167	strlcat(acecad->phys, "/input0", sizeof(acecad->phys));
    168
    169	input_dev->name = acecad->name;
    170	input_dev->phys = acecad->phys;
    171	usb_to_input_id(dev, &input_dev->id);
    172	input_dev->dev.parent = &intf->dev;
    173
    174	input_set_drvdata(input_dev, acecad);
    175
    176	input_dev->open = usb_acecad_open;
    177	input_dev->close = usb_acecad_close;
    178
    179	input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
    180	input_dev->keybit[BIT_WORD(BTN_DIGI)] = BIT_MASK(BTN_TOOL_PEN) |
    181		BIT_MASK(BTN_TOUCH) | BIT_MASK(BTN_STYLUS) |
    182		BIT_MASK(BTN_STYLUS2);
    183
    184	switch (id->driver_info) {
    185	case 0:
    186		input_set_abs_params(input_dev, ABS_X, 0, 5000, 4, 0);
    187		input_set_abs_params(input_dev, ABS_Y, 0, 3750, 4, 0);
    188		input_set_abs_params(input_dev, ABS_PRESSURE, 0, 512, 0, 0);
    189		if (!strlen(acecad->name))
    190			snprintf(acecad->name, sizeof(acecad->name),
    191				"USB Acecad Flair Tablet %04x:%04x",
    192				le16_to_cpu(dev->descriptor.idVendor),
    193				le16_to_cpu(dev->descriptor.idProduct));
    194		break;
    195
    196	case 1:
    197		input_set_abs_params(input_dev, ABS_X, 0, 53000, 4, 0);
    198		input_set_abs_params(input_dev, ABS_Y, 0, 2250, 4, 0);
    199		input_set_abs_params(input_dev, ABS_PRESSURE, 0, 1024, 0, 0);
    200		if (!strlen(acecad->name))
    201			snprintf(acecad->name, sizeof(acecad->name),
    202				"USB Acecad 302 Tablet %04x:%04x",
    203				le16_to_cpu(dev->descriptor.idVendor),
    204				le16_to_cpu(dev->descriptor.idProduct));
    205		break;
    206	}
    207
    208	usb_fill_int_urb(acecad->irq, dev, pipe,
    209			acecad->data, maxp > 8 ? 8 : maxp,
    210			usb_acecad_irq, acecad, endpoint->bInterval);
    211	acecad->irq->transfer_dma = acecad->data_dma;
    212	acecad->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
    213
    214	err = input_register_device(acecad->input);
    215	if (err)
    216		goto fail3;
    217
    218	usb_set_intfdata(intf, acecad);
    219
    220	return 0;
    221
    222 fail3:	usb_free_urb(acecad->irq);
    223 fail2:	usb_free_coherent(dev, 8, acecad->data, acecad->data_dma);
    224 fail1: input_free_device(input_dev);
    225	kfree(acecad);
    226	return err;
    227}
    228
    229static void usb_acecad_disconnect(struct usb_interface *intf)
    230{
    231	struct usb_acecad *acecad = usb_get_intfdata(intf);
    232	struct usb_device *udev = interface_to_usbdev(intf);
    233
    234	usb_set_intfdata(intf, NULL);
    235
    236	input_unregister_device(acecad->input);
    237	usb_free_urb(acecad->irq);
    238	usb_free_coherent(udev, 8, acecad->data, acecad->data_dma);
    239	kfree(acecad);
    240}
    241
    242static const struct usb_device_id usb_acecad_id_table[] = {
    243	{ USB_DEVICE(USB_VENDOR_ID_ACECAD, USB_DEVICE_ID_FLAIR), .driver_info = 0 },
    244	{ USB_DEVICE(USB_VENDOR_ID_ACECAD, USB_DEVICE_ID_302),	 .driver_info = 1 },
    245	{ }
    246};
    247
    248MODULE_DEVICE_TABLE(usb, usb_acecad_id_table);
    249
    250static struct usb_driver usb_acecad_driver = {
    251	.name =		"usb_acecad",
    252	.probe =	usb_acecad_probe,
    253	.disconnect =	usb_acecad_disconnect,
    254	.id_table =	usb_acecad_id_table,
    255};
    256
    257module_usb_driver(usb_acecad_driver);