/drivers/hid/hid-quanta.c
C | 261 lines | 192 code | 38 blank | 31 comment | 20 complexity | 00d4c512255be795718b599813c2f0ea MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.0, AGPL-1.0
1/* 2 * HID driver for Quanta Optical Touch dual-touch panels 3 * 4 * Copyright (c) 2009-2010 Stephane Chatty <chatty@enac.fr> 5 * 6 */ 7 8/* 9 * This program is free software; you can redistribute it and/or modify it 10 * under the terms of the GNU General Public License as published by the Free 11 * Software Foundation; either version 2 of the License, or (at your option) 12 * any later version. 13 */ 14 15#include <linux/device.h> 16#include <linux/hid.h> 17#include <linux/module.h> 18#include <linux/slab.h> 19 20MODULE_AUTHOR("Stephane Chatty <chatty@enac.fr>"); 21MODULE_DESCRIPTION("Quanta dual-touch panel"); 22MODULE_LICENSE("GPL"); 23 24#include "hid-ids.h" 25 26struct quanta_data { 27 __u16 x, y; 28 __u8 id; 29 bool valid; /* valid finger data, or just placeholder? */ 30 bool first; /* is this the first finger in this frame? */ 31 bool activity_now; /* at least one active finger in this frame? */ 32 bool activity; /* at least one active finger previously? */ 33}; 34 35static int quanta_input_mapping(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 switch (usage->hid & HID_USAGE_PAGE) { 40 41 case HID_UP_GENDESK: 42 switch (usage->hid) { 43 case HID_GD_X: 44 hid_map_usage(hi, usage, bit, max, 45 EV_ABS, ABS_MT_POSITION_X); 46 /* touchscreen emulation */ 47 input_set_abs_params(hi->input, ABS_X, 48 field->logical_minimum, 49 field->logical_maximum, 0, 0); 50 return 1; 51 case HID_GD_Y: 52 hid_map_usage(hi, usage, bit, max, 53 EV_ABS, ABS_MT_POSITION_Y); 54 /* touchscreen emulation */ 55 input_set_abs_params(hi->input, ABS_Y, 56 field->logical_minimum, 57 field->logical_maximum, 0, 0); 58 return 1; 59 } 60 return 0; 61 62 case HID_UP_DIGITIZER: 63 switch (usage->hid) { 64 case HID_DG_CONFIDENCE: 65 case HID_DG_TIPSWITCH: 66 case HID_DG_INPUTMODE: 67 case HID_DG_DEVICEINDEX: 68 case HID_DG_CONTACTCOUNT: 69 case HID_DG_CONTACTMAX: 70 case HID_DG_TIPPRESSURE: 71 case HID_DG_WIDTH: 72 case HID_DG_HEIGHT: 73 return -1; 74 case HID_DG_INRANGE: 75 /* touchscreen emulation */ 76 hid_map_usage(hi, usage, bit, max, EV_KEY, BTN_TOUCH); 77 return 1; 78 case HID_DG_CONTACTID: 79 hid_map_usage(hi, usage, bit, max, 80 EV_ABS, ABS_MT_TRACKING_ID); 81 return 1; 82 } 83 return 0; 84 85 case 0xff000000: 86 /* ignore vendor-specific features */ 87 return -1; 88 } 89 90 return 0; 91} 92 93static int quanta_input_mapped(struct hid_device *hdev, struct hid_input *hi, 94 struct hid_field *field, struct hid_usage *usage, 95 unsigned long **bit, int *max) 96{ 97 if (usage->type == EV_KEY || usage->type == EV_ABS) 98 clear_bit(usage->code, *bit); 99 100 return 0; 101} 102 103/* 104 * this function is called when a whole finger has been parsed, 105 * so that it can decide what to send to the input layer. 106 */ 107static void quanta_filter_event(struct quanta_data *td, struct input_dev *input) 108{ 109 110 td->first = !td->first; /* touchscreen emulation */ 111 112 if (!td->valid) { 113 /* 114 * touchscreen emulation: if no finger in this frame is valid 115 * and there previously was finger activity, this is a release 116 */ 117 if (!td->first && !td->activity_now && td->activity) { 118 input_event(input, EV_KEY, BTN_TOUCH, 0); 119 td->activity = false; 120 } 121 return; 122 } 123 124 input_event(input, EV_ABS, ABS_MT_TRACKING_ID, td->id); 125 input_event(input, EV_ABS, ABS_MT_POSITION_X, td->x); 126 input_event(input, EV_ABS, ABS_MT_POSITION_Y, td->y); 127 128 input_mt_sync(input); 129 td->valid = false; 130 131 /* touchscreen emulation: if first active finger in this frame... */ 132 if (!td->activity_now) { 133 /* if there was no previous activity, emit touch event */ 134 if (!td->activity) { 135 input_event(input, EV_KEY, BTN_TOUCH, 1); 136 td->activity = true; 137 } 138 td->activity_now = true; 139 /* and in any case this is our preferred finger */ 140 input_event(input, EV_ABS, ABS_X, td->x); 141 input_event(input, EV_ABS, ABS_Y, td->y); 142 } 143} 144 145 146static int quanta_event(struct hid_device *hid, struct hid_field *field, 147 struct hid_usage *usage, __s32 value) 148{ 149 struct quanta_data *td = hid_get_drvdata(hid); 150 151 if (hid->claimed & HID_CLAIMED_INPUT) { 152 struct input_dev *input = field->hidinput->input; 153 154 switch (usage->hid) { 155 case HID_DG_INRANGE: 156 td->valid = !!value; 157 break; 158 case HID_GD_X: 159 td->x = value; 160 break; 161 case HID_GD_Y: 162 td->y = value; 163 quanta_filter_event(td, input); 164 break; 165 case HID_DG_CONTACTID: 166 td->id = value; 167 break; 168 case HID_DG_CONTACTCOUNT: 169 /* touch emulation: this is the last field in a frame */ 170 td->first = false; 171 td->activity_now = false; 172 break; 173 case HID_DG_CONFIDENCE: 174 case HID_DG_TIPSWITCH: 175 /* avoid interference from generic hidinput handling */ 176 break; 177 178 default: 179 /* fallback to the generic hidinput handling */ 180 return 0; 181 } 182 } 183 184 /* we have handled the hidinput part, now remains hiddev */ 185 if (hid->claimed & HID_CLAIMED_HIDDEV && hid->hiddev_hid_event) 186 hid->hiddev_hid_event(hid, field, usage, value); 187 188 return 1; 189} 190 191static int quanta_probe(struct hid_device *hdev, const struct hid_device_id *id) 192{ 193 int ret; 194 struct quanta_data *td; 195 196 td = kmalloc(sizeof(struct quanta_data), GFP_KERNEL); 197 if (!td) { 198 hid_err(hdev, "cannot allocate Quanta Touch data\n"); 199 return -ENOMEM; 200 } 201 td->valid = false; 202 td->activity = false; 203 td->activity_now = false; 204 td->first = false; 205 hid_set_drvdata(hdev, td); 206 207 ret = hid_parse(hdev); 208 if (!ret) 209 ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT); 210 211 if (ret) 212 kfree(td); 213 214 return ret; 215} 216 217static void quanta_remove(struct hid_device *hdev) 218{ 219 hid_hw_stop(hdev); 220 kfree(hid_get_drvdata(hdev)); 221 hid_set_drvdata(hdev, NULL); 222} 223 224static const struct hid_device_id quanta_devices[] = { 225 { HID_USB_DEVICE(USB_VENDOR_ID_QUANTA, 226 USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH) }, 227 { HID_USB_DEVICE(USB_VENDOR_ID_QUANTA, 228 USB_DEVICE_ID_PIXART_IMAGING_INC_OPTICAL_TOUCH_SCREEN) }, 229 { } 230}; 231MODULE_DEVICE_TABLE(hid, quanta_devices); 232 233static const struct hid_usage_id quanta_grabbed_usages[] = { 234 { HID_ANY_ID, HID_ANY_ID, HID_ANY_ID }, 235 { HID_ANY_ID - 1, HID_ANY_ID - 1, HID_ANY_ID - 1} 236}; 237 238static struct hid_driver quanta_driver = { 239 .name = "quanta-touch", 240 .id_table = quanta_devices, 241 .probe = quanta_probe, 242 .remove = quanta_remove, 243 .input_mapping = quanta_input_mapping, 244 .input_mapped = quanta_input_mapped, 245 .usage_table = quanta_grabbed_usages, 246 .event = quanta_event, 247}; 248 249static int __init quanta_init(void) 250{ 251 return hid_register_driver(&quanta_driver); 252} 253 254static void __exit quanta_exit(void) 255{ 256 hid_unregister_driver(&quanta_driver); 257} 258 259module_init(quanta_init); 260module_exit(quanta_exit); 261