2 * HID driver for 3M PCT multitouch panels
4 * Copyright (c) 2009-2010 Stephane Chatty <chatty@enac.fr>
5 * Copyright (c) 2010 Henrik Rydberg <rydberg@euromail.se>
6 * Copyright (c) 2010 Canonical, Ltd.
11 * This program is free software; you can redistribute it and/or modify it
12 * under the terms of the GNU General Public License as published by the Free
13 * Software Foundation; either version 2 of the License, or (at your option)
17 #include <linux/device.h>
18 #include <linux/hid.h>
19 #include <linux/module.h>
20 #include <linux/slab.h>
21 #include <linux/usb.h>
23 MODULE_AUTHOR("Stephane Chatty <chatty@enac.fr>");
24 MODULE_DESCRIPTION("3M PCT multitouch panels");
25 MODULE_LICENSE("GPL");
30 #define MAX_TRKID USHRT_MAX
31 #define MAX_EVENTS 360
33 /* estimated signal-to-noise ratios */
46 struct mmm_finger f
[MAX_SLOTS
];
53 static int mmm_input_mapping(struct hid_device
*hdev
, struct hid_input
*hi
,
54 struct hid_field
*field
, struct hid_usage
*usage
,
55 unsigned long **bit
, int *max
)
57 int f1
= field
->logical_minimum
;
58 int f2
= field
->logical_maximum
;
61 switch (usage
->hid
& HID_USAGE_PAGE
) {
69 hid_map_usage(hi
, usage
, bit
, max
,
70 EV_ABS
, ABS_MT_POSITION_X
);
71 input_set_abs_params(hi
->input
, ABS_MT_POSITION_X
,
72 f1
, f2
, df
/ SN_MOVE
, 0);
73 /* touchscreen emulation */
74 input_set_abs_params(hi
->input
, ABS_X
,
75 f1
, f2
, df
/ SN_MOVE
, 0);
78 hid_map_usage(hi
, usage
, bit
, max
,
79 EV_ABS
, ABS_MT_POSITION_Y
);
80 input_set_abs_params(hi
->input
, ABS_MT_POSITION_Y
,
81 f1
, f2
, df
/ SN_MOVE
, 0);
82 /* touchscreen emulation */
83 input_set_abs_params(hi
->input
, ABS_Y
,
84 f1
, f2
, df
/ SN_MOVE
, 0);
89 case HID_UP_DIGITIZER
:
91 /* we do not want to map these: no input-oriented meaning */
94 case HID_DG_INPUTMODE
:
95 case HID_DG_DEVICEINDEX
:
96 case HID_DG_CONTACTCOUNT
:
97 case HID_DG_CONTACTMAX
:
99 case HID_DG_CONFIDENCE
:
101 case HID_DG_TIPSWITCH
:
102 /* touchscreen emulation */
103 hid_map_usage(hi
, usage
, bit
, max
, EV_KEY
, BTN_TOUCH
);
104 input_set_capability(hi
->input
, EV_KEY
, BTN_TOUCH
);
107 hid_map_usage(hi
, usage
, bit
, max
,
108 EV_ABS
, ABS_MT_TOUCH_MAJOR
);
109 input_set_abs_params(hi
->input
, ABS_MT_TOUCH_MAJOR
,
110 f1
, f2
, df
/ SN_WIDTH
, 0);
113 hid_map_usage(hi
, usage
, bit
, max
,
114 EV_ABS
, ABS_MT_TOUCH_MINOR
);
115 input_set_abs_params(hi
->input
, ABS_MT_TOUCH_MINOR
,
116 f1
, f2
, df
/ SN_WIDTH
, 0);
117 input_set_abs_params(hi
->input
, ABS_MT_ORIENTATION
,
120 case HID_DG_CONTACTID
:
121 field
->logical_maximum
= MAX_TRKID
;
122 hid_map_usage(hi
, usage
, bit
, max
,
123 EV_ABS
, ABS_MT_TRACKING_ID
);
124 input_set_abs_params(hi
->input
, ABS_MT_TRACKING_ID
,
127 input_mt_create_slots(hi
->input
, MAX_SLOTS
);
128 input_set_events_per_packet(hi
->input
, MAX_EVENTS
);
131 /* let hid-input decide for the others */
135 /* we do not want to map these: no input-oriented meaning */
142 static int mmm_input_mapped(struct hid_device
*hdev
, struct hid_input
*hi
,
143 struct hid_field
*field
, struct hid_usage
*usage
,
144 unsigned long **bit
, int *max
)
146 /* tell hid-input to skip setup of these event types */
147 if (usage
->type
== EV_KEY
|| usage
->type
== EV_ABS
)
148 set_bit(usage
->type
, hi
->input
->evbit
);
153 * this function is called when a whole packet has been received and processed,
154 * so that it can decide what to send to the input layer.
156 static void mmm_filter_event(struct mmm_data
*md
, struct input_dev
*input
)
158 struct mmm_finger
*oldest
= 0;
159 bool pressed
= false, released
= false;
163 * we need to iterate on all fingers to decide if we have a press
164 * or a release event in our touchscreen emulation.
166 for (i
= 0; i
< MAX_SLOTS
; ++i
) {
167 struct mmm_finger
*f
= &md
->f
[i
];
169 /* this finger is just placeholder data, ignore */
172 input_mt_slot(input
, i
);
174 /* this finger is on the screen */
175 int wide
= (f
->w
> f
->h
);
178 input_event(input
, EV_ABS
, ABS_MT_TRACKING_ID
, f
->id
);
179 input_event(input
, EV_ABS
, ABS_MT_POSITION_X
, f
->x
);
180 input_event(input
, EV_ABS
, ABS_MT_POSITION_Y
, f
->y
);
181 input_event(input
, EV_ABS
, ABS_MT_ORIENTATION
, wide
);
182 input_event(input
, EV_ABS
, ABS_MT_TOUCH_MAJOR
,
184 input_event(input
, EV_ABS
, ABS_MT_TOUCH_MINOR
,
187 * touchscreen emulation: maintain the age rank
188 * of this finger, decide if we have a press
191 f
->rank
= ++(md
->num
);
198 /* this finger took off the screen */
199 /* touchscreen emulation: maintain age rank of others */
202 for (j
= 0; j
< 10; ++j
) {
203 struct mmm_finger
*g
= &md
->f
[j
];
204 if (g
->rank
> f
->rank
) {
214 input_event(input
, EV_ABS
, ABS_MT_TRACKING_ID
, -1);
216 f
->prev_touch
= f
->touch
;
220 /* touchscreen emulation */
223 input_event(input
, EV_KEY
, BTN_TOUCH
, 1);
224 input_event(input
, EV_ABS
, ABS_X
, oldest
->x
);
225 input_event(input
, EV_ABS
, ABS_Y
, oldest
->y
);
226 } else if (released
) {
227 input_event(input
, EV_KEY
, BTN_TOUCH
, 0);
233 * this function is called upon all reports
234 * so that we can accumulate contact point information,
235 * and call input_mt_sync after each point.
237 static int mmm_event(struct hid_device
*hid
, struct hid_field
*field
,
238 struct hid_usage
*usage
, __s32 value
)
240 struct mmm_data
*md
= hid_get_drvdata(hid
);
242 * strangely, this function can be called before
243 * field->hidinput is initialized!
245 if (hid
->claimed
& HID_CLAIMED_INPUT
) {
246 struct input_dev
*input
= field
->hidinput
->input
;
247 switch (usage
->hid
) {
248 case HID_DG_TIPSWITCH
:
251 case HID_DG_CONFIDENCE
:
256 md
->f
[md
->curid
].w
= value
;
260 md
->f
[md
->curid
].h
= value
;
262 case HID_DG_CONTACTID
:
263 value
= clamp_val(value
, 0, MAX_SLOTS
- 1);
266 md
->f
[value
].touch
= md
->touch
;
267 md
->f
[value
].valid
= 1;
273 md
->f
[md
->curid
].x
= value
;
277 md
->f
[md
->curid
].y
= value
;
279 case HID_DG_CONTACTCOUNT
:
282 if (md
->nreal
>= md
->nexp
) {
283 mmm_filter_event(md
, input
);
290 /* we have handled the hidinput part, now remains hiddev */
291 if (hid
->claimed
& HID_CLAIMED_HIDDEV
&& hid
->hiddev_hid_event
)
292 hid
->hiddev_hid_event(hid
, field
, usage
, value
);
297 static int mmm_probe(struct hid_device
*hdev
, const struct hid_device_id
*id
)
302 hdev
->quirks
|= HID_QUIRK_NO_INPUT_SYNC
;
304 md
= kzalloc(sizeof(struct mmm_data
), GFP_KERNEL
);
306 dev_err(&hdev
->dev
, "cannot allocate 3M data\n");
309 hid_set_drvdata(hdev
, md
);
311 ret
= hid_parse(hdev
);
313 ret
= hid_hw_start(hdev
, HID_CONNECT_DEFAULT
);
320 static void mmm_remove(struct hid_device
*hdev
)
323 kfree(hid_get_drvdata(hdev
));
324 hid_set_drvdata(hdev
, NULL
);
327 static const struct hid_device_id mmm_devices
[] = {
328 { HID_USB_DEVICE(USB_VENDOR_ID_3M
, USB_DEVICE_ID_3M1968
) },
329 { HID_USB_DEVICE(USB_VENDOR_ID_3M
, USB_DEVICE_ID_3M2256
) },
332 MODULE_DEVICE_TABLE(hid
, mmm_devices
);
334 static const struct hid_usage_id mmm_grabbed_usages
[] = {
335 { HID_ANY_ID
, HID_ANY_ID
, HID_ANY_ID
},
336 { HID_ANY_ID
- 1, HID_ANY_ID
- 1, HID_ANY_ID
- 1}
339 static struct hid_driver mmm_driver
= {
341 .id_table
= mmm_devices
,
343 .remove
= mmm_remove
,
344 .input_mapping
= mmm_input_mapping
,
345 .input_mapped
= mmm_input_mapped
,
346 .usage_table
= mmm_grabbed_usages
,
350 static int __init
mmm_init(void)
352 return hid_register_driver(&mmm_driver
);
355 static void __exit
mmm_exit(void)
357 hid_unregister_driver(&mmm_driver
);
360 module_init(mmm_init
);
361 module_exit(mmm_exit
);