1717#include <linux/errno.h>
1818#include <linux/module.h>
1919#include <linux/input.h>
20+ #include <linux/input/mt.h>
2021#include <linux/slab.h>
2122
2223#include <asm/xen/hypervisor.h>
3435struct xenkbd_info {
3536 struct input_dev * kbd ;
3637 struct input_dev * ptr ;
38+ struct input_dev * mtouch ;
3739 struct xenkbd_page * page ;
3840 int gref ;
3941 int irq ;
4042 struct xenbus_device * xbdev ;
4143 char phys [32 ];
44+ /* current MT slot/contact ID we are injecting events in */
45+ int mtouch_cur_contact_id ;
4246};
4347
4448enum { KPARAM_X , KPARAM_Y , KPARAM_CNT };
@@ -56,6 +60,112 @@ static void xenkbd_disconnect_backend(struct xenkbd_info *);
5660 * to do that.
5761 */
5862
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+
59169static irqreturn_t input_handler (int rq , void * dev_id )
60170{
61171 struct xenkbd_info * info = dev_id ;
@@ -66,44 +176,8 @@ static irqreturn_t input_handler(int rq, void *dev_id)
66176 if (prod == page -> in_cons )
67177 return IRQ_HANDLED ;
68178 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 ));
107181 mb (); /* ensure we got ring contents */
108182 page -> in_cons = cons ;
109183 notify_remote_via_irq (info -> irq );
@@ -115,9 +189,9 @@ static int xenkbd_probe(struct xenbus_device *dev,
115189 const struct xenbus_device_id * id )
116190{
117191 int ret , i ;
118- unsigned int abs ;
192+ unsigned int abs , touch ;
119193 struct xenkbd_info * info ;
120- struct input_dev * kbd , * ptr ;
194+ struct input_dev * kbd , * ptr , * mtouch ;
121195
122196 info = kzalloc (sizeof (* info ), GFP_KERNEL );
123197 if (!info ) {
@@ -152,6 +226,17 @@ static int xenkbd_probe(struct xenbus_device *dev,
152226 }
153227 }
154228
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+
155240 /* keyboard */
156241 kbd = input_allocate_device ();
157242 if (!kbd )
@@ -208,6 +293,58 @@ static int xenkbd_probe(struct xenbus_device *dev,
208293 }
209294 info -> ptr = ptr ;
210295
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+
211348 ret = xenkbd_connect_backend (dev , info );
212349 if (ret < 0 )
213350 goto error ;
@@ -240,6 +377,8 @@ static int xenkbd_remove(struct xenbus_device *dev)
240377 input_unregister_device (info -> kbd );
241378 if (info -> ptr )
242379 input_unregister_device (info -> ptr );
380+ if (info -> mtouch )
381+ input_unregister_device (info -> mtouch );
243382 free_page ((unsigned long )info -> page );
244383 kfree (info );
245384 return 0 ;
0 commit comments