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>
22 #include <linux/input/mt.h>
24 MODULE_AUTHOR("Stephane Chatty <chatty@enac.fr>");
25 MODULE_DESCRIPTION("3M PCT multitouch panels");
26 MODULE_LICENSE("GPL");
31 #define MAX_TRKID USHRT_MAX
32 #define MAX_EVENTS 360
34 /* 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;
160 for (i
= 0; i
< MAX_SLOTS
; ++i
) {
161 struct mmm_finger
*f
= &md
->f
[i
];
163 /* this finger is just placeholder data, ignore */
166 input_mt_slot(input
, i
);
168 /* this finger is on the screen */
169 int wide
= (f
->w
> f
->h
);
170 /* divided by two to match visual scale of touch */
171 int major
= max(f
->w
, f
->h
) >> 1;
172 int minor
= min(f
->w
, f
->h
) >> 1;
176 input_event(input
, EV_ABS
, ABS_MT_TRACKING_ID
, f
->id
);
177 input_event(input
, EV_ABS
, ABS_MT_POSITION_X
, f
->x
);
178 input_event(input
, EV_ABS
, ABS_MT_POSITION_Y
, f
->y
);
179 input_event(input
, EV_ABS
, ABS_MT_ORIENTATION
, wide
);
180 input_event(input
, EV_ABS
, ABS_MT_TOUCH_MAJOR
, major
);
181 input_event(input
, EV_ABS
, ABS_MT_TOUCH_MINOR
, minor
);
182 /* touchscreen emulation: pick the oldest contact */
183 if (!oldest
|| ((f
->id
- oldest
->id
) & (SHRT_MAX
+ 1)))
186 /* this finger took off the screen */
187 input_event(input
, EV_ABS
, ABS_MT_TRACKING_ID
, -1);
189 f
->prev_touch
= f
->touch
;
193 /* touchscreen emulation */
195 input_event(input
, EV_KEY
, BTN_TOUCH
, 1);
196 input_event(input
, EV_ABS
, ABS_X
, oldest
->x
);
197 input_event(input
, EV_ABS
, ABS_Y
, oldest
->y
);
199 input_event(input
, EV_KEY
, BTN_TOUCH
, 0);
205 * this function is called upon all reports
206 * so that we can accumulate contact point information,
207 * and call input_mt_sync after each point.
209 static int mmm_event(struct hid_device
*hid
, struct hid_field
*field
,
210 struct hid_usage
*usage
, __s32 value
)
212 struct mmm_data
*md
= hid_get_drvdata(hid
);
214 * strangely, this function can be called before
215 * field->hidinput is initialized!
217 if (hid
->claimed
& HID_CLAIMED_INPUT
) {
218 struct input_dev
*input
= field
->hidinput
->input
;
219 switch (usage
->hid
) {
220 case HID_DG_TIPSWITCH
:
223 case HID_DG_CONFIDENCE
:
228 md
->f
[md
->curid
].w
= value
;
232 md
->f
[md
->curid
].h
= value
;
234 case HID_DG_CONTACTID
:
235 value
= clamp_val(value
, 0, MAX_SLOTS
- 1);
238 md
->f
[value
].touch
= md
->touch
;
239 md
->f
[value
].valid
= 1;
245 md
->f
[md
->curid
].x
= value
;
249 md
->f
[md
->curid
].y
= value
;
251 case HID_DG_CONTACTCOUNT
:
254 if (md
->nreal
>= md
->nexp
) {
255 mmm_filter_event(md
, input
);
262 /* we have handled the hidinput part, now remains hiddev */
263 if (hid
->claimed
& HID_CLAIMED_HIDDEV
&& hid
->hiddev_hid_event
)
264 hid
->hiddev_hid_event(hid
, field
, usage
, value
);
269 static int mmm_probe(struct hid_device
*hdev
, const struct hid_device_id
*id
)
274 hdev
->quirks
|= HID_QUIRK_NO_INPUT_SYNC
;
276 md
= kzalloc(sizeof(struct mmm_data
), GFP_KERNEL
);
278 dev_err(&hdev
->dev
, "cannot allocate 3M data\n");
281 hid_set_drvdata(hdev
, md
);
283 ret
= hid_parse(hdev
);
285 ret
= hid_hw_start(hdev
, HID_CONNECT_DEFAULT
);
292 static void mmm_remove(struct hid_device
*hdev
)
295 kfree(hid_get_drvdata(hdev
));
296 hid_set_drvdata(hdev
, NULL
);
299 static const struct hid_device_id mmm_devices
[] = {
300 { HID_USB_DEVICE(USB_VENDOR_ID_3M
, USB_DEVICE_ID_3M1968
) },
301 { HID_USB_DEVICE(USB_VENDOR_ID_3M
, USB_DEVICE_ID_3M2256
) },
304 MODULE_DEVICE_TABLE(hid
, mmm_devices
);
306 static const struct hid_usage_id mmm_grabbed_usages
[] = {
307 { HID_ANY_ID
, HID_ANY_ID
, HID_ANY_ID
},
308 { HID_ANY_ID
- 1, HID_ANY_ID
- 1, HID_ANY_ID
- 1}
311 static struct hid_driver mmm_driver
= {
313 .id_table
= mmm_devices
,
315 .remove
= mmm_remove
,
316 .input_mapping
= mmm_input_mapping
,
317 .input_mapped
= mmm_input_mapped
,
318 .usage_table
= mmm_grabbed_usages
,
322 static int __init
mmm_init(void)
324 return hid_register_driver(&mmm_driver
);
327 static void __exit
mmm_exit(void)
329 hid_unregister_driver(&mmm_driver
);
332 module_init(mmm_init
);
333 module_exit(mmm_exit
);