ChangeSet 1.1020, 2003/03/05 14:17:51-08:00, josh@joshisanerd.com [PATCH] USB: add KB Gear USB Tablet Driver drivers/usb/Config.in | 1 drivers/usb/Makefile | 1 drivers/usb/hid-core.c | 4 + drivers/usb/kbtab.c | 179 +++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 185 insertions(+) diff -Nru a/drivers/usb/Config.in b/drivers/usb/Config.in --- a/drivers/usb/Config.in Thu Mar 6 14:23:32 2003 +++ b/drivers/usb/Config.in Thu Mar 6 14:23:32 2003 @@ -68,6 +68,7 @@ fi dep_tristate ' Aiptek 6000U/8000U tablet support' CONFIG_USB_AIPTEK $CONFIG_USB $CONFIG_INPUT dep_tristate ' Wacom Intuos/Graphire tablet support' CONFIG_USB_WACOM $CONFIG_USB $CONFIG_INPUT + dep_tristate ' KB Gear JamStudio tablet support' CONFIG_USB_KBTAB $CONFIG_USB $CONFIG_INPUT dep_tristate ' Griffin Technology PowerMate support' CONFIG_USB_POWERMATE $CONFIG_USB $CONFIG_INPUT comment 'USB Imaging devices' diff -Nru a/drivers/usb/Makefile b/drivers/usb/Makefile --- a/drivers/usb/Makefile Thu Mar 6 14:23:32 2003 +++ b/drivers/usb/Makefile Thu Mar 6 14:23:32 2003 @@ -70,6 +70,7 @@ obj-$(CONFIG_USB_KBD) += usbkbd.o obj-$(CONFIG_USB_AIPTEK) += aiptek.o obj-$(CONFIG_USB_WACOM) += wacom.o +obj-$(CONFIG_USB_KBTAB) += kbtab.o obj-$(CONFIG_USB_POWERMATE) += powermate.o obj-$(CONFIG_USB_SCANNER) += scanner.o diff -Nru a/drivers/usb/hid-core.c b/drivers/usb/hid-core.c --- a/drivers/usb/hid-core.c Thu Mar 6 14:23:32 2003 +++ b/drivers/usb/hid-core.c Thu Mar 6 14:23:32 2003 @@ -1080,6 +1080,9 @@ #define USB_DEVICE_ID_WACOM_PL 0x0030 #define USB_DEVICE_ID_WACOM_INTUOS2 0x0041 +#define USB_VENDOR_ID_KBGEAR 0x084e +#define USB_DEVICE_ID_KBGEAR_JAMSTUDIO 0x1001 + #define USB_VENDOR_ID_ATEN 0x0557 #define USB_DEVICE_ID_ATEN_UC100KM 0x2004 #define USB_DEVICE_ID_ATEN_CS124U 0x2202 @@ -1121,6 +1124,7 @@ { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS2 + 2, HID_QUIRK_IGNORE }, { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS2 + 3, HID_QUIRK_IGNORE }, { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS2 + 4, HID_QUIRK_IGNORE }, + { USB_VENDOR_ID_KBGEAR, USB_DEVICE_ID_KBGEAR_JAMSTUDIO, HID_QUIRK_IGNORE }, { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_UC100KM, HID_QUIRK_NOGET }, { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_CS124U, HID_QUIRK_NOGET }, { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_2PORTKVM, HID_QUIRK_NOGET }, diff -Nru a/drivers/usb/kbtab.c b/drivers/usb/kbtab.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/usb/kbtab.c Thu Mar 6 14:23:32 2003 @@ -0,0 +1,179 @@ +#include +#include +#include +#include +#include +#include + +/* + * Version Information + */ +#define DRIVER_VERSION "v0.0.1" +#define DRIVER_AUTHOR "Josh Myer " +#define DRIVER_DESC "KB Gear Jam Studio Tablet Driver" + +MODULE_AUTHOR( DRIVER_AUTHOR ); +MODULE_DESCRIPTION( DRIVER_DESC ); +MODULE_LICENSE("GPL"); + +#define USB_VENDOR_ID_KBTAB 0x84e + +static int kb_pressure_click = 0x10; +MODULE_PARM (kb_pressure_click,"i"); +MODULE_PARM_DESC(kb_pressure_click, + "pressure threshold for clicks"); + +struct kbtab { + signed char data[8]; + struct input_dev dev; + struct usb_device *usbdev; + struct urb irq; + int open; + int x, y; + int button; + int pressure; +}; + +static void kbtab_irq(struct urb *urb) +{ + + struct kbtab *tab = urb->context; + unsigned char *data = tab->data; + struct input_dev *dev = &tab->dev; + + if(urb->status) + return; + + tab->x = (data[2] << 8) + data[1]; + tab->y = (data[4] << 8) + data[3]; + + tab->pressure = (data[5]); + + /* XXX: don't report unless actual change */ + + input_report_abs(dev, ABS_X, tab->x); + input_report_abs(dev, ABS_Y, tab->y); + input_report_abs(dev, ABS_PRESSURE, tab->pressure); + + input_report_key(dev, BTN_STYLUS, (data[0] & 2)); + input_report_key(dev, BTN_TOUCH, (data[0] & 1)); + input_report_key(dev, BTN_LEFT, (tab->pressure > kb_pressure_click) ? 1 : 0); + + input_event(dev, EV_MSC, MSC_SERIAL, 0); +} + +struct usb_device_id kbtab_ids[] = { + { USB_DEVICE(USB_VENDOR_ID_KBTAB, 0x1001), driver_info : 0 }, + { } +}; + +MODULE_DEVICE_TABLE(usb, kbtab_ids); + +static int kbtab_open(struct input_dev *dev) +{ + struct kbtab *kbtab = dev->private; + + if(kbtab->open++) + return 0; + + kbtab->irq.dev = kbtab->usbdev; + if(usb_submit_urb(&kbtab->irq)) + return -EIO; + + return 0; +} + +static void kbtab_close(struct input_dev *dev) +{ + struct kbtab *kbtab = dev->private; + + if(!--kbtab->open) + usb_unlink_urb(&kbtab->irq); +} + +static void *kbtab_probe(struct usb_device *dev, unsigned int ifnum, const struct usb_device_id *id) +{ + struct usb_endpoint_descriptor *endpoint; + struct kbtab *kbtab; + + if(!(kbtab = kmalloc(sizeof(struct kbtab), GFP_KERNEL))) + return NULL; + + memset(kbtab, 0, sizeof(struct kbtab)); + + kbtab->dev.evbit[0] |= BIT(EV_KEY) | BIT(EV_ABS) | BIT(EV_MSC); + kbtab->dev.absbit[0] |= BIT(ABS_X) | BIT(ABS_Y) | BIT(ABS_PRESSURE); + + kbtab->dev.keybit[LONG(BTN_LEFT)] |= BIT(BTN_LEFT) | BIT(BTN_RIGHT) | BIT(BTN_MIDDLE); + kbtab->dev.keybit[LONG(BTN_DIGI)] |= BIT(BTN_STYLUS); + + kbtab->dev.mscbit[0] |= BIT(MSC_SERIAL); + + kbtab->dev.absmax[ABS_X] = 0x2000; + kbtab->dev.absmax[ABS_Y] = 0x1750; + + kbtab->dev.absmax[ABS_PRESSURE] = 0xff; + + kbtab->dev.absfuzz[ABS_X] = 4; + kbtab->dev.absfuzz[ABS_Y] = 4; + + kbtab->dev.private = kbtab; + + kbtab->dev.open = kbtab_open; + kbtab->dev.close = kbtab_close; + + kbtab->dev.name = "KB Gear Tablet"; + kbtab->dev.idbus = BUS_USB; + + kbtab->dev.idvendor = dev->descriptor.idVendor; + kbtab->dev.idproduct = dev->descriptor.idProduct; + kbtab->dev.idversion = dev->descriptor.bcdDevice; + kbtab->usbdev = dev; + + + endpoint = dev->config[0].interface[ifnum].altsetting[0].endpoint + 0; + + usb_set_idle(dev, dev->config[0].interface[ifnum].altsetting[0].bInterfaceNumber, 0, 0); + + FILL_INT_URB(&kbtab->irq, dev, usb_rcvintpipe(dev, endpoint->bEndpointAddress), + kbtab->data, 8, kbtab_irq, kbtab, endpoint->bInterval); + + input_register_device(&kbtab->dev); + + printk(KERN_INFO "input%d: KB Gear Tablet on usb%d:%d.%d\n", + kbtab->dev.number, dev->bus->busnum, dev->devnum, ifnum); + + return kbtab; + +} + +static void kbtab_disconnect(struct usb_device *dev, void *ptr) +{ + struct kbtab *kbtab = ptr; + usb_unlink_urb(&kbtab->irq); + input_unregister_device(&kbtab->dev); + kfree(kbtab); +} + +static struct usb_driver kbtab_driver = { + name: "kbtab", + probe: kbtab_probe, + disconnect: kbtab_disconnect, + id_table: kbtab_ids, +}; + +static int __init kbtab_init(void) +{ + usb_register(&kbtab_driver); + info(DRIVER_VERSION " " DRIVER_AUTHOR); + info(DRIVER_DESC); + return 0; +} + +static void __exit kbtab_exit(void) +{ + usb_deregister(&kbtab_driver); +} + +module_init(kbtab_init); +module_exit(kbtab_exit);