From 57f0f512b273f60d52568b8c6b77e17f5636edc0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Fabian=20Silva=20Delgado?= Date: Wed, 5 Aug 2015 17:04:01 -0300 Subject: Initial import --- drivers/hid/huiontablet.c | 285 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 285 insertions(+) create mode 100644 drivers/hid/huiontablet.c (limited to 'drivers/hid/huiontablet.c') diff --git a/drivers/hid/huiontablet.c b/drivers/hid/huiontablet.c new file mode 100644 index 000000000..9996032e1 --- /dev/null +++ b/drivers/hid/huiontablet.c @@ -0,0 +1,285 @@ +/* + * Copyright (c) 2013 Tan Huang,Shenzhen Huion + * + * USB HID Tablet support + */ + + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#define DEVICE_NAME "huiontablet" + +/* for apple IDs */ +#ifdef CONFIG_USB_HID_MODULE +#include "./hid-ids.h" +#endif + +/* + * Version Information + */ +#define DRIVER_VERSION "v1.0" +#define DRIVER_AUTHOR "Tan Huang " +#define DRIVER_DESC "USB HID Boot Protocol tablet driver" +#define DRIVER_LICENSE "GPL" + +MODULE_AUTHOR(DRIVER_AUTHOR); +MODULE_DESCRIPTION(DRIVER_DESC); +MODULE_LICENSE(DRIVER_LICENSE); + +struct usb_mouse { + char name[128]; + char phys[64]; + struct usb_device *usbdev; + struct input_dev *dev; + struct urb *irq; + + signed char *data; + dma_addr_t data_dma; +}; + + + +unsigned short int pos_x=0,pos_y=0,pos_z=0; + +//static struct miscdevice misc = { +// .minor = MISC_DYNAMIC_MINOR, +// .name = DEVICE_NAME, +// .fops = &dev_fops, +//}; + + +static void usb_mouse_irq(struct urb *urb) +{ + struct usb_mouse *mouse = urb->context; + signed char *data = mouse->data; + struct input_dev *dev = mouse->dev; + int status; + //unsigned short int pos_x=0,pos_y=0,pos_z=0; + // printk(KERN_NOTICE "enter usb_mouse_irq function\n"); + switch (urb->status) { + case 0: /* success */ + break; + case -ECONNRESET: /* unlink */ + case -ENOENT: + case -ESHUTDOWN: + return; + /* -EPIPE: should clear the halt */ + default: /* error */ + goto resubmit; + } + + pos_x =(data[3] & 0x0FF)<<8; + pos_x |=(data[2] & 0x0FF); + pos_y =(data[5] & 0x0FF)<<8; + pos_y |=(data[4] & 0x0FF); + pos_z =(data[7] & 0x0FF)<<8; + pos_z |=(data[6] & 0x0FF); + printk(KERN_NOTICE "pos_x=%x,pos_y=%x,pos_z=%x,button=%x\n",pos_x,pos_y,pos_z,(data[1] & 0x0F)); + input_report_abs(dev, ABS_X, pos_x); + input_report_abs(dev, ABS_Y, pos_y); + input_report_key(dev, BTN_TOOL_PEN,1); + input_report_abs(dev, ABS_PRESSURE,pos_z); + input_report_key(dev, BTN_LEFT,data[1] & 0x01); + input_report_key(dev, BTN_TOUCH,data[1] & 0x01); + input_report_key(dev, BTN_MIDDLE,data[1] & 0x02); + input_report_key(dev, BTN_RIGHT,data[1] & 0x04); + + input_sync(dev); +resubmit: + status = usb_submit_urb (urb, GFP_ATOMIC); + /* Not sure what the function 'err' would have been, but holy shit this code is UGLY. + Do people really still use the goto statement? + if (status) + err ("can't resubmit intr, %s-%s/input0, status %d", + mouse->usbdev->bus->bus_name, + mouse->usbdev->devpath, status); + // printk(KERN_NOTICE "quit usb_mouse_irq function\n"); + */ +} + +static int usb_mouse_open(struct input_dev *dev) +{ + struct usb_mouse *mouse = input_get_drvdata(dev); + // printk(KERN_NOTICE "enter usinput_report_key(dev, BTN_TOUCH,(pos_z>0)?1:0); b_mouse_open function\n"); + mouse->irq->dev = mouse->usbdev; + if (usb_submit_urb(mouse->irq, GFP_KERNEL)) + return -EIO; + // printk(KERN_NOTICE "quit usb_mouse_open function\n"); + return 0; +} + +static void usb_mouse_close(struct input_dev *dev) +{ + struct usb_mouse *mouse = input_get_drvdata(dev); + // printk(KERN_NOTICE "enter usb_mouse_close function\n"); + usb_kill_urb(mouse->irq); + // printk(KERN_NOTICE "quit usb_mouse_close function\n"); +} + +static int usb_mouse_probe(struct usb_interface *intf, const struct usb_device_id *id) +{ + struct usb_device *dev = interface_to_usbdev(intf); + struct usb_host_interface *interface; + struct usb_endpoint_descriptor *endpoint; + struct usb_mouse *mouse; + struct input_dev *input_dev; + int pipe, maxp; + int error = -ENOMEM; + // printk(KERN_NOTICE "enter usb_mouse_probe function\n"); + interface = intf->cur_altsetting; + + if (interface->desc.bNumEndpoints != 1) + return -ENODEV; + + endpoint = &interface->endpoint[0].desc; + if (!usb_endpoint_is_int_in(endpoint)) + return -ENODEV; + + pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress); + maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe)); + + mouse = kzalloc(sizeof(struct usb_mouse), GFP_KERNEL); + input_dev = input_allocate_device(); + if (!mouse || !input_dev) + goto fail1; + + mouse->data = usb_alloc_coherent(dev, 8, GFP_ATOMIC, &mouse->data_dma); + if (!mouse->data) + goto fail1; + + mouse->irq = usb_alloc_urb(0, GFP_KERNEL); + if (!mouse->irq) + goto fail2; + + mouse->usbdev = dev; + mouse->dev = input_dev; + + if (dev->manufacturer) + strlcpy(mouse->name, dev->manufacturer, sizeof(mouse->name)); + + if (dev->product) { + if (dev->manufacturer) + strlcat(mouse->name, " ", sizeof(mouse->name)); + strlcat(mouse->name, dev->product, sizeof(mouse->name)); + } + + if (!strlen(mouse->name)) + snprintf(mouse->name, sizeof(mouse->name), + "USB HIDBP Mouse %04x:%04x", + le16_to_cpu(dev->descriptor.idVendor), + le16_to_cpu(dev->descriptor.idProduct)); + + usb_make_path(dev, mouse->phys, sizeof(mouse->phys)); + strlcat(mouse->phys, "/input0", sizeof(mouse->phys)); + + input_dev->name = mouse->name; + input_dev->phys = mouse->phys; + usb_to_input_id(dev, &input_dev->id); + input_dev->dev.parent = &intf->dev; + + set_bit(EV_MSC, input_dev->evbit); + set_bit(EV_KEY, input_dev->evbit); + set_bit(EV_ABS, input_dev->evbit); + set_bit(ABS_X, input_dev->absbit); + set_bit(ABS_Y, input_dev->absbit); + set_bit(ABS_PRESSURE, input_dev->absbit); + set_bit(BTN_TOUCH, input_dev->keybit); + set_bit(BTN_TOOL_PEN, input_dev->keybit); + set_bit(BTN_LEFT, input_dev->keybit); + set_bit(BTN_MIDDLE, input_dev->keybit); + set_bit(BTN_RIGHT, input_dev->keybit); + set_bit(MSC_SERIAL, input_dev->mscbit); + + input_set_drvdata(input_dev, mouse); + + input_set_abs_params(input_dev, ABS_X, 0, 0x7ff, 0, 0); + input_set_abs_params(input_dev, ABS_Y, 0, 0x7ff, 0, 0); + input_set_abs_params(input_dev, ABS_PRESSURE, 0, 1024, 0, 0); + + input_dev->open = usb_mouse_open; + input_dev->close = usb_mouse_close; + + usb_fill_int_urb(mouse->irq, dev, pipe, mouse->data, + (maxp > 8 ? 8 : maxp), + usb_mouse_irq, mouse, endpoint->bInterval); + mouse->irq->transfer_dma = mouse->data_dma; + mouse->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; + + error = input_register_device(mouse->dev); + if (error) + goto fail3; + + usb_set_intfdata(intf, mouse); + return 0; + +fail3: + usb_free_urb(mouse->irq); +fail2: + usb_free_coherent(dev, 8, mouse->data, mouse->data_dma); +fail1: + input_free_device(input_dev); + kfree(mouse); + // printk(KERN_NOTICE "quit usb_mouse_probe function\n"); + return error; +} + +static void usb_mouse_disconnect(struct usb_interface *intf) +{ + struct usb_mouse *mouse = usb_get_intfdata (intf); + //printk(KERN_NOTICE "enter usb_mouse_disconnect function\n"); + usb_set_intfdata(intf, NULL); + if (mouse) { + usb_kill_urb(mouse->irq); + input_unregister_device(mouse->dev); + usb_free_urb(mouse->irq); + usb_free_coherent(interface_to_usbdev(intf), 8, mouse->data, mouse->data_dma); + kfree(mouse); + } + // misc_deregister(&misc); + // printk(KERN_NOTICE "quit usb_mouse_disconnect function\n"); +} + +static struct usb_device_id usb_mouse_id_table [] = { + //{ USB_INTERFACE_INFO(USB_INTERFACE_CLASS_HID, USB_INTERFACE_SUBCLASS_BOOT,USB_INTERFACE_PROTOCOL_MOUSE) }, + { USB_DEVICE(0x256C, 0x0005) }, + { USB_DEVICE(0x256C, 0x006E) }, + { USB_DEVICE(0x5543, 0x0005) }, + { USB_DEVICE(0x5543, 0x006E) }, + { } /* Terminating entry */ +}; + +MODULE_DEVICE_TABLE (usb, usb_mouse_id_table); + + +static struct usb_driver usb_mouse_driver = { + .name = "usbmouse", + .probe = usb_mouse_probe, + .disconnect = usb_mouse_disconnect, + .id_table = usb_mouse_id_table, +}; + +static int __init usb_mouse_init(void) +{ + int retval = usb_register(&usb_mouse_driver); + if (retval == 0) + printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" + DRIVER_DESC "\n"); + return retval; +} + +static void __exit usb_mouse_exit(void) +{ + usb_deregister(&usb_mouse_driver); +} + +module_init(usb_mouse_init); +module_exit(usb_mouse_exit); -- cgit v1.2.3