linux-old/drivers/usb/kbtab.c
<<
>>
Prefs
   1#include <linux/kernel.h>
   2#include <linux/slab.h>
   3#include <linux/input.h>
   4#include <linux/module.h>
   5#include <linux/init.h>
   6#include <linux/usb.h>
   7
   8/*
   9 * Version Information
  10 */
  11#define DRIVER_VERSION "v0.0.1"
  12#define DRIVER_AUTHOR "Josh Myer <josh@joshisanerd.com>"
  13#define DRIVER_DESC "KB Gear Jam Studio Tablet Driver"
  14
  15MODULE_AUTHOR( DRIVER_AUTHOR );
  16MODULE_DESCRIPTION( DRIVER_DESC );
  17MODULE_LICENSE("GPL");
  18
  19#define USB_VENDOR_ID_KBTAB 0x84e
  20
  21static int       kb_pressure_click = 0x10;
  22MODULE_PARM     (kb_pressure_click,"i");
  23MODULE_PARM_DESC(kb_pressure_click,
  24                 "pressure threshold for clicks");
  25
  26struct kbtab {
  27        signed char data[8];
  28        struct input_dev dev;
  29        struct usb_device *usbdev;
  30        struct urb irq;
  31        int open;
  32        int x, y;
  33        int button;
  34        int pressure;
  35};
  36
  37static void kbtab_irq(struct urb *urb)
  38{
  39
  40        struct kbtab *tab = urb->context;
  41        unsigned char *data = tab->data;
  42        struct input_dev *dev = &tab->dev;
  43
  44        if(urb->status)
  45                return;
  46
  47        tab->x = (data[2] << 8) + data[1];
  48        tab->y = (data[4] << 8) + data[3];
  49
  50        tab->pressure = (data[5]);
  51
  52        /* XXX: don't report unless actual change */
  53
  54        input_report_abs(dev, ABS_X, tab->x);
  55        input_report_abs(dev, ABS_Y, tab->y);
  56        input_report_abs(dev, ABS_PRESSURE, tab->pressure);
  57
  58        input_report_key(dev, BTN_STYLUS, (data[0] & 2));
  59        input_report_key(dev, BTN_TOUCH, (data[0] & 1));
  60        input_report_key(dev, BTN_LEFT, (tab->pressure > kb_pressure_click) ? 1 : 0);
  61
  62        input_event(dev, EV_MSC, MSC_SERIAL, 0);
  63}
  64
  65struct usb_device_id kbtab_ids[] = {
  66        { USB_DEVICE(USB_VENDOR_ID_KBTAB, 0x1001), driver_info : 0 },
  67        { }
  68};
  69  
  70MODULE_DEVICE_TABLE(usb, kbtab_ids);
  71
  72static int kbtab_open(struct input_dev *dev)
  73{
  74        struct kbtab *kbtab = dev->private;
  75
  76        if(kbtab->open++)
  77                return 0;
  78
  79        kbtab->irq.dev = kbtab->usbdev;
  80        if(usb_submit_urb(&kbtab->irq))
  81                return -EIO;
  82
  83        return 0;
  84}
  85
  86static void kbtab_close(struct input_dev *dev)
  87{
  88        struct kbtab *kbtab = dev->private;
  89
  90        if(!--kbtab->open)
  91                usb_unlink_urb(&kbtab->irq);
  92}
  93
  94static void *kbtab_probe(struct usb_device *dev, unsigned int ifnum, const struct usb_device_id *id)
  95{
  96        struct usb_endpoint_descriptor *endpoint;
  97        struct kbtab *kbtab;
  98
  99        if(!(kbtab = kmalloc(sizeof(struct kbtab), GFP_KERNEL)))
 100                return NULL;
 101
 102        memset(kbtab, 0, sizeof(struct kbtab));
 103
 104        kbtab->dev.evbit[0] |= BIT(EV_KEY) | BIT(EV_ABS) | BIT(EV_MSC);
 105        kbtab->dev.absbit[0] |= BIT(ABS_X) | BIT(ABS_Y) | BIT(ABS_PRESSURE);
 106
 107        kbtab->dev.keybit[LONG(BTN_LEFT)] |= BIT(BTN_LEFT) | BIT(BTN_RIGHT) | BIT(BTN_MIDDLE);
 108        kbtab->dev.keybit[LONG(BTN_DIGI)] |= BIT(BTN_STYLUS);
 109
 110        kbtab->dev.mscbit[0] |= BIT(MSC_SERIAL);
 111
 112        kbtab->dev.absmax[ABS_X] = 0x2000;
 113        kbtab->dev.absmax[ABS_Y] = 0x1750;
 114
 115        kbtab->dev.absmax[ABS_PRESSURE] = 0xff;
 116  
 117        kbtab->dev.absfuzz[ABS_X] = 4;
 118        kbtab->dev.absfuzz[ABS_Y] = 4;
 119  
 120        kbtab->dev.private = kbtab;
 121
 122        kbtab->dev.open = kbtab_open;
 123        kbtab->dev.close = kbtab_close;
 124
 125        kbtab->dev.name = "KB Gear Tablet";
 126        kbtab->dev.idbus = BUS_USB;
 127  
 128        kbtab->dev.idvendor = dev->descriptor.idVendor;
 129        kbtab->dev.idproduct = dev->descriptor.idProduct;
 130        kbtab->dev.idversion = dev->descriptor.bcdDevice;
 131        kbtab->usbdev = dev;
 132
 133
 134        endpoint = dev->config[0].interface[ifnum].altsetting[0].endpoint + 0;
 135
 136        usb_set_idle(dev, dev->config[0].interface[ifnum].altsetting[0].bInterfaceNumber, 0, 0);
 137
 138        FILL_INT_URB(&kbtab->irq, dev, usb_rcvintpipe(dev, endpoint->bEndpointAddress),
 139                     kbtab->data, 8, kbtab_irq, kbtab, endpoint->bInterval);
 140
 141        input_register_device(&kbtab->dev);
 142
 143        printk(KERN_INFO "input%d: KB Gear Tablet on usb%d:%d.%d\n",
 144               kbtab->dev.number, dev->bus->busnum, dev->devnum, ifnum);
 145
 146        return kbtab;
 147
 148}
 149
 150static void kbtab_disconnect(struct usb_device *dev, void *ptr)
 151{
 152        struct kbtab *kbtab = ptr;
 153        usb_unlink_urb(&kbtab->irq);
 154        input_unregister_device(&kbtab->dev);
 155        kfree(kbtab);
 156}
 157
 158static struct usb_driver kbtab_driver = {
 159        name:           "kbtab",
 160        probe:          kbtab_probe,
 161        disconnect:     kbtab_disconnect,
 162        id_table:       kbtab_ids,
 163};
 164
 165static int __init kbtab_init(void)
 166{
 167        usb_register(&kbtab_driver);
 168        info(DRIVER_VERSION " " DRIVER_AUTHOR);
 169        info(DRIVER_DESC);
 170        return 0;
 171}
 172
 173static void __exit kbtab_exit(void)
 174{
 175        usb_deregister(&kbtab_driver);
 176}
 177
 178module_init(kbtab_init);
 179module_exit(kbtab_exit);
 180
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.