1 /* 2 * HID driver for some a4tech "special" devices 3 * 4 * Copyright (c) 1999 Andreas Gal 5 * Copyright (c) 2000-2005 Vojtech Pavlik <vojtech@suse.cz> 6 * Copyright (c) 2005 Michael Haboustak <mike-@cinci.rr.com> for Concept2, Inc 7 * Copyright (c) 2006-2007 Jiri Kosina 8 * Copyright (c) 2008 Jiri Slaby 9 */ 10 11 /* 12 * This program is free software; you can redistribute it and/or modify it 13 * under the terms of the GNU General Public License as published by the Free 14 * Software Foundation; either version 2 of the License, or (at your option) 15 * any later version. 16 */ 17 18 #include <linux/device.h> 19 #include <linux/input.h> 20 #include <linux/hid.h> 21 #include <linux/module.h> 22 #include <linux/slab.h> 23 24 #include "hid-ids.h" 25 26 #define A4_2WHEEL_MOUSE_HACK_7 0x01 27 #define A4_2WHEEL_MOUSE_HACK_B8 0x02 28 29 struct a4tech_sc { 30 unsigned long quirks; 31 unsigned int hw_wheel; 32 __s32 delayed_value; 33 }; 34 35 static int a4_input_mapped(struct hid_device *hdev, struct hid_input *hi, 36 struct hid_field *field, struct hid_usage *usage, 37 unsigned long **bit, int *max) 38 { 39 struct a4tech_sc *a4 = hid_get_drvdata(hdev); 40 41 if (usage->type == EV_REL && usage->code == REL_WHEEL) 42 set_bit(REL_HWHEEL, *bit); 43 44 if ((a4->quirks & A4_2WHEEL_MOUSE_HACK_7) && usage->hid == 0x00090007) 45 return -1; 46 47 return 0; 48 } 49 50 static int a4_event(struct hid_device *hdev, struct hid_field *field, 51 struct hid_usage *usage, __s32 value) 52 { 53 struct a4tech_sc *a4 = hid_get_drvdata(hdev); 54 struct input_dev *input; 55 56 if (!(hdev->claimed & HID_CLAIMED_INPUT) || !field->hidinput || 57 !usage->type) 58 return 0; 59 60 input = field->hidinput->input; 61 62 if (a4->quirks & A4_2WHEEL_MOUSE_HACK_B8) { 63 if (usage->type == EV_REL && usage->code == REL_WHEEL) { 64 a4->delayed_value = value; 65 return 1; 66 } 67 68 if (usage->hid == 0x000100b8) { 69 input_event(input, EV_REL, value ? REL_HWHEEL : 70 REL_WHEEL, a4->delayed_value); 71 return 1; 72 } 73 } 74 75 if ((a4->quirks & A4_2WHEEL_MOUSE_HACK_7) && usage->hid == 0x00090007) { 76 a4->hw_wheel = !!value; 77 return 1; 78 } 79 80 if (usage->code == REL_WHEEL && a4->hw_wheel) { 81 input_event(input, usage->type, REL_HWHEEL, value); 82 return 1; 83 } 84 85 return 0; 86 } 87 88 static int a4_probe(struct hid_device *hdev, const struct hid_device_id *id) 89 { 90 struct a4tech_sc *a4; 91 int ret; 92 93 a4 = kzalloc(sizeof(*a4), GFP_KERNEL); 94 if (a4 == NULL) { 95 hid_err(hdev, "can't alloc device descriptor\n"); 96 ret = -ENOMEM; 97 goto err_free; 98 } 99 100 a4->quirks = id->driver_data; 101 102 hid_set_drvdata(hdev, a4); 103 104 ret = hid_parse(hdev); 105 if (ret) { 106 hid_err(hdev, "parse failed\n"); 107 goto err_free; 108 } 109 110 ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT); 111 if (ret) { 112 hid_err(hdev, "hw start failed\n"); 113 goto err_free; 114 } 115 116 return 0; 117 err_free: 118 kfree(a4); 119 return ret; 120 } 121 122 static void a4_remove(struct hid_device *hdev) 123 { 124 struct a4tech_sc *a4 = hid_get_drvdata(hdev); 125 126 hid_hw_stop(hdev); 127 kfree(a4); 128 } 129 130 static const struct hid_device_id a4_devices[] = { 131 { HID_USB_DEVICE(USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_WCP32PU), 132 .driver_data = A4_2WHEEL_MOUSE_HACK_7 }, 133 { HID_USB_DEVICE(USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_X5_005D), 134 .driver_data = A4_2WHEEL_MOUSE_HACK_B8 }, 135 { HID_USB_DEVICE(USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_RP_649), 136 .driver_data = A4_2WHEEL_MOUSE_HACK_B8 }, 137 { } 138 }; 139 MODULE_DEVICE_TABLE(hid, a4_devices); 140 141 static struct hid_driver a4_driver = { 142 .name = "a4tech", 143 .id_table = a4_devices, 144 .input_mapped = a4_input_mapped, 145 .event = a4_event, 146 .probe = a4_probe, 147 .remove = a4_remove, 148 }; 149 module_hid_driver(a4_driver); 150 151 MODULE_LICENSE("GPL"); 152