17
17
#include <linux/errno.h>
18
18
#include <linux/module.h>
19
19
#include <linux/input.h>
20
+ #include <linux/input/mt.h>
20
21
#include <linux/slab.h>
21
22
22
23
#include <asm/xen/hypervisor.h>
34
35
struct xenkbd_info {
35
36
struct input_dev * kbd ;
36
37
struct input_dev * ptr ;
38
+ struct input_dev * mtouch ;
37
39
struct xenkbd_page * page ;
38
40
int gref ;
39
41
int irq ;
40
42
struct xenbus_device * xbdev ;
41
43
char phys [32 ];
44
+ /* current MT slot/contact ID we are injecting events in */
45
+ int mtouch_cur_contact_id ;
42
46
};
43
47
44
48
enum { KPARAM_X , KPARAM_Y , KPARAM_CNT };
@@ -56,6 +60,112 @@ static void xenkbd_disconnect_backend(struct xenkbd_info *);
56
60
* to do that.
57
61
*/
58
62
63
+ static void xenkbd_handle_motion_event (struct xenkbd_info * info ,
64
+ struct xenkbd_motion * motion )
65
+ {
66
+ input_report_rel (info -> ptr , REL_X , motion -> rel_x );
67
+ input_report_rel (info -> ptr , REL_Y , motion -> rel_y );
68
+ if (motion -> rel_z )
69
+ input_report_rel (info -> ptr , REL_WHEEL , - motion -> rel_z );
70
+ input_sync (info -> ptr );
71
+ }
72
+
73
+ static void xenkbd_handle_position_event (struct xenkbd_info * info ,
74
+ struct xenkbd_position * pos )
75
+ {
76
+ input_report_abs (info -> ptr , ABS_X , pos -> abs_x );
77
+ input_report_abs (info -> ptr , ABS_Y , pos -> abs_y );
78
+ if (pos -> rel_z )
79
+ input_report_rel (info -> ptr , REL_WHEEL , - pos -> rel_z );
80
+ input_sync (info -> ptr );
81
+ }
82
+
83
+ static void xenkbd_handle_key_event (struct xenkbd_info * info ,
84
+ struct xenkbd_key * key )
85
+ {
86
+ struct input_dev * dev ;
87
+
88
+ if (test_bit (key -> keycode , info -> ptr -> keybit )) {
89
+ dev = info -> ptr ;
90
+ } else if (test_bit (key -> keycode , info -> kbd -> keybit )) {
91
+ dev = info -> kbd ;
92
+ } else {
93
+ pr_warn ("unhandled keycode 0x%x\n" , key -> keycode );
94
+ return ;
95
+ }
96
+
97
+ input_report_key (dev , key -> keycode , key -> pressed );
98
+ input_sync (dev );
99
+ }
100
+
101
+ static void xenkbd_handle_mt_event (struct xenkbd_info * info ,
102
+ struct xenkbd_mtouch * mtouch )
103
+ {
104
+ if (unlikely (!info -> mtouch ))
105
+ return ;
106
+
107
+ if (mtouch -> contact_id != info -> mtouch_cur_contact_id ) {
108
+ info -> mtouch_cur_contact_id = mtouch -> contact_id ;
109
+ input_mt_slot (info -> mtouch , mtouch -> contact_id );
110
+ }
111
+
112
+ switch (mtouch -> event_type ) {
113
+ case XENKBD_MT_EV_DOWN :
114
+ input_mt_report_slot_state (info -> mtouch , MT_TOOL_FINGER , true);
115
+ /* fall through */
116
+
117
+ case XENKBD_MT_EV_MOTION :
118
+ input_report_abs (info -> mtouch , ABS_MT_POSITION_X ,
119
+ mtouch -> u .pos .abs_x );
120
+ input_report_abs (info -> mtouch , ABS_MT_POSITION_Y ,
121
+ mtouch -> u .pos .abs_y );
122
+ break ;
123
+
124
+ case XENKBD_MT_EV_SHAPE :
125
+ input_report_abs (info -> mtouch , ABS_MT_TOUCH_MAJOR ,
126
+ mtouch -> u .shape .major );
127
+ input_report_abs (info -> mtouch , ABS_MT_TOUCH_MINOR ,
128
+ mtouch -> u .shape .minor );
129
+ break ;
130
+
131
+ case XENKBD_MT_EV_ORIENT :
132
+ input_report_abs (info -> mtouch , ABS_MT_ORIENTATION ,
133
+ mtouch -> u .orientation );
134
+ break ;
135
+
136
+ case XENKBD_MT_EV_UP :
137
+ input_mt_report_slot_state (info -> mtouch , MT_TOOL_FINGER , false);
138
+ break ;
139
+
140
+ case XENKBD_MT_EV_SYN :
141
+ input_mt_sync_frame (info -> mtouch );
142
+ input_sync (info -> mtouch );
143
+ break ;
144
+ }
145
+ }
146
+
147
+ static void xenkbd_handle_event (struct xenkbd_info * info ,
148
+ union xenkbd_in_event * event )
149
+ {
150
+ switch (event -> type ) {
151
+ case XENKBD_TYPE_MOTION :
152
+ xenkbd_handle_motion_event (info , & event -> motion );
153
+ break ;
154
+
155
+ case XENKBD_TYPE_KEY :
156
+ xenkbd_handle_key_event (info , & event -> key );
157
+ break ;
158
+
159
+ case XENKBD_TYPE_POS :
160
+ xenkbd_handle_position_event (info , & event -> pos );
161
+ break ;
162
+
163
+ case XENKBD_TYPE_MTOUCH :
164
+ xenkbd_handle_mt_event (info , & event -> mtouch );
165
+ break ;
166
+ }
167
+ }
168
+
59
169
static irqreturn_t input_handler (int rq , void * dev_id )
60
170
{
61
171
struct xenkbd_info * info = dev_id ;
@@ -66,44 +176,8 @@ static irqreturn_t input_handler(int rq, void *dev_id)
66
176
if (prod == page -> in_cons )
67
177
return IRQ_HANDLED ;
68
178
rmb (); /* ensure we see ring contents up to prod */
69
- for (cons = page -> in_cons ; cons != prod ; cons ++ ) {
70
- union xenkbd_in_event * event ;
71
- struct input_dev * dev ;
72
- event = & XENKBD_IN_RING_REF (page , cons );
73
-
74
- dev = info -> ptr ;
75
- switch (event -> type ) {
76
- case XENKBD_TYPE_MOTION :
77
- input_report_rel (dev , REL_X , event -> motion .rel_x );
78
- input_report_rel (dev , REL_Y , event -> motion .rel_y );
79
- if (event -> motion .rel_z )
80
- input_report_rel (dev , REL_WHEEL ,
81
- - event -> motion .rel_z );
82
- break ;
83
- case XENKBD_TYPE_KEY :
84
- dev = NULL ;
85
- if (test_bit (event -> key .keycode , info -> kbd -> keybit ))
86
- dev = info -> kbd ;
87
- if (test_bit (event -> key .keycode , info -> ptr -> keybit ))
88
- dev = info -> ptr ;
89
- if (dev )
90
- input_report_key (dev , event -> key .keycode ,
91
- event -> key .pressed );
92
- else
93
- pr_warn ("unhandled keycode 0x%x\n" ,
94
- event -> key .keycode );
95
- break ;
96
- case XENKBD_TYPE_POS :
97
- input_report_abs (dev , ABS_X , event -> pos .abs_x );
98
- input_report_abs (dev , ABS_Y , event -> pos .abs_y );
99
- if (event -> pos .rel_z )
100
- input_report_rel (dev , REL_WHEEL ,
101
- - event -> pos .rel_z );
102
- break ;
103
- }
104
- if (dev )
105
- input_sync (dev );
106
- }
179
+ for (cons = page -> in_cons ; cons != prod ; cons ++ )
180
+ xenkbd_handle_event (info , & XENKBD_IN_RING_REF (page , cons ));
107
181
mb (); /* ensure we got ring contents */
108
182
page -> in_cons = cons ;
109
183
notify_remote_via_irq (info -> irq );
@@ -115,9 +189,9 @@ static int xenkbd_probe(struct xenbus_device *dev,
115
189
const struct xenbus_device_id * id )
116
190
{
117
191
int ret , i ;
118
- unsigned int abs ;
192
+ unsigned int abs , touch ;
119
193
struct xenkbd_info * info ;
120
- struct input_dev * kbd , * ptr ;
194
+ struct input_dev * kbd , * ptr , * mtouch ;
121
195
122
196
info = kzalloc (sizeof (* info ), GFP_KERNEL );
123
197
if (!info ) {
@@ -152,6 +226,17 @@ static int xenkbd_probe(struct xenbus_device *dev,
152
226
}
153
227
}
154
228
229
+ touch = xenbus_read_unsigned (dev -> nodename ,
230
+ XENKBD_FIELD_FEAT_MTOUCH , 0 );
231
+ if (touch ) {
232
+ ret = xenbus_write (XBT_NIL , dev -> nodename ,
233
+ XENKBD_FIELD_REQ_MTOUCH , "1" );
234
+ if (ret ) {
235
+ pr_warn ("xenkbd: can't request multi-touch" );
236
+ touch = 0 ;
237
+ }
238
+ }
239
+
155
240
/* keyboard */
156
241
kbd = input_allocate_device ();
157
242
if (!kbd )
@@ -208,6 +293,58 @@ static int xenkbd_probe(struct xenbus_device *dev,
208
293
}
209
294
info -> ptr = ptr ;
210
295
296
+ /* multi-touch device */
297
+ if (touch ) {
298
+ int num_cont , width , height ;
299
+
300
+ mtouch = input_allocate_device ();
301
+ if (!mtouch )
302
+ goto error_nomem ;
303
+
304
+ num_cont = xenbus_read_unsigned (info -> xbdev -> nodename ,
305
+ XENKBD_FIELD_MT_NUM_CONTACTS ,
306
+ 1 );
307
+ width = xenbus_read_unsigned (info -> xbdev -> nodename ,
308
+ XENKBD_FIELD_MT_WIDTH ,
309
+ XENFB_WIDTH );
310
+ height = xenbus_read_unsigned (info -> xbdev -> nodename ,
311
+ XENKBD_FIELD_MT_HEIGHT ,
312
+ XENFB_HEIGHT );
313
+
314
+ mtouch -> name = "Xen Virtual Multi-touch" ;
315
+ mtouch -> phys = info -> phys ;
316
+ mtouch -> id .bustype = BUS_PCI ;
317
+ mtouch -> id .vendor = 0x5853 ;
318
+ mtouch -> id .product = 0xfffd ;
319
+
320
+ input_set_abs_params (mtouch , ABS_MT_TOUCH_MAJOR ,
321
+ 0 , 255 , 0 , 0 );
322
+ input_set_abs_params (mtouch , ABS_MT_POSITION_X ,
323
+ 0 , width , 0 , 0 );
324
+ input_set_abs_params (mtouch , ABS_MT_POSITION_Y ,
325
+ 0 , height , 0 , 0 );
326
+ input_set_abs_params (mtouch , ABS_MT_PRESSURE ,
327
+ 0 , 255 , 0 , 0 );
328
+
329
+ ret = input_mt_init_slots (mtouch , num_cont , INPUT_MT_DIRECT );
330
+ if (ret ) {
331
+ input_free_device (mtouch );
332
+ xenbus_dev_fatal (info -> xbdev , ret ,
333
+ "input_mt_init_slots" );
334
+ goto error ;
335
+ }
336
+
337
+ ret = input_register_device (mtouch );
338
+ if (ret ) {
339
+ input_free_device (mtouch );
340
+ xenbus_dev_fatal (info -> xbdev , ret ,
341
+ "input_register_device(mtouch)" );
342
+ goto error ;
343
+ }
344
+ info -> mtouch_cur_contact_id = -1 ;
345
+ info -> mtouch = mtouch ;
346
+ }
347
+
211
348
ret = xenkbd_connect_backend (dev , info );
212
349
if (ret < 0 )
213
350
goto error ;
@@ -240,6 +377,8 @@ static int xenkbd_remove(struct xenbus_device *dev)
240
377
input_unregister_device (info -> kbd );
241
378
if (info -> ptr )
242
379
input_unregister_device (info -> ptr );
380
+ if (info -> mtouch )
381
+ input_unregister_device (info -> mtouch );
243
382
free_page ((unsigned long )info -> page );
244
383
kfree (info );
245
384
return 0 ;
0 commit comments