Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
at v2.6.16 223 lines 5.6 kB view raw
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#include <linux/usb_input.h> 8#include <asm/unaligned.h> 9#include <asm/byteorder.h> 10 11/* 12 * Version Information 13 * v0.0.1 - Original, extremely basic version, 2.4.xx only 14 * v0.0.2 - Updated, works with 2.5.62 and 2.4.20; 15 * - added pressure-threshold modules param code from 16 * Alex Perry <alex.perry@ieee.org> 17 */ 18 19#define DRIVER_VERSION "v0.0.2" 20#define DRIVER_AUTHOR "Josh Myer <josh@joshisanerd.com>" 21#define DRIVER_DESC "USB KB Gear JamStudio Tablet driver" 22#define DRIVER_LICENSE "GPL" 23 24MODULE_AUTHOR(DRIVER_AUTHOR); 25MODULE_DESCRIPTION(DRIVER_DESC); 26MODULE_LICENSE(DRIVER_LICENSE); 27 28#define USB_VENDOR_ID_KBGEAR 0x084e 29 30static int kb_pressure_click = 0x10; 31module_param(kb_pressure_click, int, 0); 32MODULE_PARM_DESC(kb_pressure_click, "pressure threshold for clicks"); 33 34struct kbtab { 35 signed char *data; 36 dma_addr_t data_dma; 37 struct input_dev *dev; 38 struct usb_device *usbdev; 39 struct urb *irq; 40 int x, y; 41 int button; 42 int pressure; 43 __u32 serial[2]; 44 char phys[32]; 45}; 46 47static void kbtab_irq(struct urb *urb, struct pt_regs *regs) 48{ 49 struct kbtab *kbtab = urb->context; 50 unsigned char *data = kbtab->data; 51 struct input_dev *dev = kbtab->dev; 52 int retval; 53 54 switch (urb->status) { 55 case 0: 56 /* success */ 57 break; 58 case -ECONNRESET: 59 case -ENOENT: 60 case -ESHUTDOWN: 61 /* this urb is terminated, clean up */ 62 dbg("%s - urb shutting down with status: %d", __FUNCTION__, urb->status); 63 return; 64 default: 65 dbg("%s - nonzero urb status received: %d", __FUNCTION__, urb->status); 66 goto exit; 67 } 68 69 kbtab->x = le16_to_cpu(get_unaligned((__le16 *) &data[1])); 70 kbtab->y = le16_to_cpu(get_unaligned((__le16 *) &data[3])); 71 72 kbtab->pressure = (data[5]); 73 74 input_report_key(dev, BTN_TOOL_PEN, 1); 75 76 input_report_abs(dev, ABS_X, kbtab->x); 77 input_report_abs(dev, ABS_Y, kbtab->y); 78 79 /*input_report_key(dev, BTN_TOUCH , data[0] & 0x01);*/ 80 input_report_key(dev, BTN_RIGHT, data[0] & 0x02); 81 82 if (-1 == kb_pressure_click) { 83 input_report_abs(dev, ABS_PRESSURE, kbtab->pressure); 84 } else { 85 input_report_key(dev, BTN_LEFT, (kbtab->pressure > kb_pressure_click) ? 1 : 0); 86 }; 87 88 input_sync(dev); 89 90 exit: 91 retval = usb_submit_urb (urb, GFP_ATOMIC); 92 if (retval) 93 err ("%s - usb_submit_urb failed with result %d", 94 __FUNCTION__, retval); 95} 96 97static struct usb_device_id kbtab_ids[] = { 98 { USB_DEVICE(USB_VENDOR_ID_KBGEAR, 0x1001), .driver_info = 0 }, 99 { } 100}; 101 102MODULE_DEVICE_TABLE(usb, kbtab_ids); 103 104static int kbtab_open(struct input_dev *dev) 105{ 106 struct kbtab *kbtab = dev->private; 107 108 kbtab->irq->dev = kbtab->usbdev; 109 if (usb_submit_urb(kbtab->irq, GFP_KERNEL)) 110 return -EIO; 111 112 return 0; 113} 114 115static void kbtab_close(struct input_dev *dev) 116{ 117 struct kbtab *kbtab = dev->private; 118 119 usb_kill_urb(kbtab->irq); 120} 121 122static int kbtab_probe(struct usb_interface *intf, const struct usb_device_id *id) 123{ 124 struct usb_device *dev = interface_to_usbdev(intf); 125 struct usb_endpoint_descriptor *endpoint; 126 struct kbtab *kbtab; 127 struct input_dev *input_dev; 128 129 kbtab = kzalloc(sizeof(struct kbtab), GFP_KERNEL); 130 input_dev = input_allocate_device(); 131 if (!kbtab || !input_dev) 132 goto fail1; 133 134 kbtab->data = usb_buffer_alloc(dev, 8, GFP_KERNEL, &kbtab->data_dma); 135 if (!kbtab->data) 136 goto fail1; 137 138 kbtab->irq = usb_alloc_urb(0, GFP_KERNEL); 139 if (!kbtab->irq) 140 goto fail2; 141 142 kbtab->usbdev = dev; 143 kbtab->dev = input_dev; 144 145 usb_make_path(dev, kbtab->phys, sizeof(kbtab->phys)); 146 strlcat(kbtab->phys, "/input0", sizeof(kbtab->phys)); 147 148 input_dev->name = "KB Gear Tablet"; 149 input_dev->phys = kbtab->phys; 150 usb_to_input_id(dev, &input_dev->id); 151 input_dev->cdev.dev = &intf->dev; 152 input_dev->private = kbtab; 153 154 input_dev->open = kbtab_open; 155 input_dev->close = kbtab_close; 156 157 input_dev->evbit[0] |= BIT(EV_KEY) | BIT(EV_ABS) | BIT(EV_MSC); 158 input_dev->keybit[LONG(BTN_LEFT)] |= BIT(BTN_LEFT) | BIT(BTN_RIGHT) | BIT(BTN_MIDDLE); 159 input_dev->keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_PEN) | BIT(BTN_TOUCH); 160 input_dev->mscbit[0] |= BIT(MSC_SERIAL); 161 input_set_abs_params(input_dev, ABS_X, 0, 0x2000, 4, 0); 162 input_set_abs_params(input_dev, ABS_Y, 0, 0x1750, 4, 0); 163 input_set_abs_params(input_dev, ABS_PRESSURE, 0, 0xff, 0, 0); 164 165 endpoint = &intf->cur_altsetting->endpoint[0].desc; 166 167 usb_fill_int_urb(kbtab->irq, dev, 168 usb_rcvintpipe(dev, endpoint->bEndpointAddress), 169 kbtab->data, 8, 170 kbtab_irq, kbtab, endpoint->bInterval); 171 kbtab->irq->transfer_dma = kbtab->data_dma; 172 kbtab->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; 173 174 input_register_device(kbtab->dev); 175 176 usb_set_intfdata(intf, kbtab); 177 return 0; 178 179fail2: usb_buffer_free(dev, 10, kbtab->data, kbtab->data_dma); 180fail1: input_free_device(input_dev); 181 kfree(kbtab); 182 return -ENOMEM; 183} 184 185static void kbtab_disconnect(struct usb_interface *intf) 186{ 187 struct kbtab *kbtab = usb_get_intfdata(intf); 188 189 usb_set_intfdata(intf, NULL); 190 if (kbtab) { 191 usb_kill_urb(kbtab->irq); 192 input_unregister_device(kbtab->dev); 193 usb_free_urb(kbtab->irq); 194 usb_buffer_free(interface_to_usbdev(intf), 10, kbtab->data, kbtab->data_dma); 195 kfree(kbtab); 196 } 197} 198 199static struct usb_driver kbtab_driver = { 200 .name = "kbtab", 201 .probe = kbtab_probe, 202 .disconnect = kbtab_disconnect, 203 .id_table = kbtab_ids, 204}; 205 206static int __init kbtab_init(void) 207{ 208 int retval; 209 retval = usb_register(&kbtab_driver); 210 if (retval) 211 goto out; 212 info(DRIVER_VERSION ":" DRIVER_DESC); 213out: 214 return retval; 215} 216 217static void __exit kbtab_exit(void) 218{ 219 usb_deregister(&kbtab_driver); 220} 221 222module_init(kbtab_init); 223module_exit(kbtab_exit);