]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/mag/server/src/mag.lua
Update
[l4.git] / l4 / pkg / mag / server / src / mag.lua
1 -------------------------------------------------
2 -- exported functions used by the mag logic
3 -------------------------------------------------
4
5 local Mag = Mag
6 local string = require "string"
7 local table = require "table"
8
9 Mag.user_state = Mag.get_user_state();
10
11 -- handle an incoming event
12 function handle_event(ev)
13   -- print("handle_event", ev[1], ev[2], ev[3], ev[4], ev[5], ev[6]);
14   -- 1: type, 2: code, 3: value, 4: time, 5: device_id, 6: source
15   local l4re_syn_stream_cfg = (ev[1] == 0 and ev[2] == 0x80);
16   local l4re_close_stream = l4re_syn_stream_cfg and ev[3] == 1;
17   local source = ev[6];
18   local stream = ev[5];
19   local ddh = Mag.sources[source];
20   if not ddh then
21     if (l4re_close_stream) then
22       return
23     end
24     Mag.sources[source] = {};
25     ddh =  Mag.sources[source];
26   end
27
28   local dh = ddh[stream];
29   if not dh then
30     if l4re_close_stream then
31       return
32     end
33     dh = Mag.create_input_device(source, stream);
34   end
35
36   -- print ("EV: ", ev[1], ev[2], ev[3], ev[4], ev[5], ev[6]);
37   -- print(string.format("src=[%s:%s]: type=%x code=%x val=%x (time=%d)", tostring(ev[6]), tostring(ev[5]), ev[1], ev[2], ev[3], ev[4]));
38   dh:process_event(ev);
39   if l4re_close_stream then
40     dh:delete();
41   end
42 end
43
44 -- mag requests infos about a specific input event stream
45 function input_source_info(global_id)
46   -- print "input_source_info";
47   local device = Mag.streams[global_id];
48   if not device then
49     return -22;
50   end
51
52   return device.handler.get_stream_info(device);
53 end
54
55 -- mag requests infos about a specific input event stream
56 function input_source_abs_info(global_id, ...)
57   -- print "input_source_abs_info";
58   local device = Mag.streams[global_id];
59   if not device then
60     return -22;
61   end
62
63   return device.handler.get_abs_info(device, ...);
64 end
65
66
67
68 -------------------------------------------------
69 -- The internals of our event handling module
70 -------------------------------------------------
71 Mag.Mag = Mag;
72 Mag._G = _G;
73 local globals = _G;
74 local Mag_mt = getmetatable(Mag);
75 local orig_Mag_index = Mag_mt.__index;
76 local function Mag_index(table, key)
77   local o = orig_Mag_index(table, key);
78   if (not o) then
79     o = globals[key];
80   end
81   return o;
82 end
83 Mag_mt.__index = Mag_index;
84 _ENV = Mag;
85
86 -- mag will initialize the variable 'user_state' to refer to
87 -- mag's user state object.
88
89 Event = {
90   Type   = 1,
91   Code   = 2,
92   Value  = 3,
93   Time   = 4,
94   Device = 5,
95   Stream = 6,
96
97   SYN = 0;
98   KEY = 1;
99   REL = 2;
100   ABS = 3;
101   MSC = 4;
102   SW  = 5;
103
104   Syn = {
105     REPORT    = 0,
106     CONFIG    = 1,
107     MT_REPORT = 2,
108   };
109
110   Key = {
111     RESERVED         = 0,
112     ESC              = 1,
113     KEY_1            = 2,
114     KEY_2            = 3,
115     KEY_3            = 4,
116     KEY_4            = 5,
117     KEY_5            = 6,
118     KEY_6            = 7,
119     KEY_7            = 8,
120     KEY_8            = 9,
121     KEY_9            = 10,
122     KEY_0            = 11,
123     MINUS            = 12,
124     EQUAL            = 13,
125     BACKSPACE        = 14,
126     TAB              = 15,
127     Q                = 16,
128     W                = 17,
129     E                = 18,
130     R                = 19,
131     T                = 20,
132     Y                = 21,
133     U                = 22,
134     I                = 23,
135     O                = 24,
136     P                = 25,
137     LEFTBRACE        = 26,
138     RIGHTBRACE       = 27,
139     ENTER            = 28,
140     LEFTCTRL         = 29,
141     A                = 30,
142     S                = 31,
143     D                = 32,
144     F                = 33,
145     G                = 34,
146     H                = 35,
147     J                = 36,
148     K                = 37,
149     L                = 38,
150     SEMICOLON        = 39,
151     APOSTROPHE       = 40,
152     GRAVE            = 41,
153     LEFTSHIFT        = 42,
154     BACKSLASH        = 43,
155     Z                = 44,
156     X                = 45,
157     C                = 46,
158     V                = 47,
159     B                = 48,
160     N                = 49,
161     M                = 50,
162     COMMA            = 51,
163     DOT              = 52,
164     SLASH            = 53,
165     RIGHTSHIFT       = 54,
166     KPASTERISK       = 55,
167     LEFTALT          = 56,
168     SPACE            = 57,
169     CAPSLOCK         = 58,
170     F1               = 59,
171     F2               = 60,
172     F3               = 61,
173     F4               = 62,
174     F5               = 63,
175     F6               = 64,
176     F7               = 65,
177     F8               = 66,
178     F9               = 67,
179     F10              = 68,
180     NUMLOCK          = 69,
181     SCROLLLOCK       = 70,
182     KP7              = 71,
183     KP8              = 72,
184     KP9              = 73,
185     KPMINUS          = 74,
186     KP4              = 75,
187     KP5              = 76,
188     KP6              = 77,
189     KPPLUS           = 78,
190     KP1              = 79,
191     KP2              = 80,
192     KP3              = 81,
193     KP0              = 82,
194     KPDOT            = 83,
195     ZENKAKUHANKAKU   = 85,
196     KEY_102ND        = 86,
197     F11              = 87,
198     F12              = 88,
199     RO               = 89,
200     KATAKANA         = 90,
201     HIRAGANA         = 91,
202     HENKAN           = 92,
203     KATAKANAHIRAGANA = 93,
204     MUHENKAN         = 94,
205     KPJPCOMMA        = 95,
206     KPENTER          = 96,
207     RIGHTCTRL        = 97,
208     KPSLASH          = 98,
209     SYSRQ            = 99,
210     RIGHTALT         = 100,
211     LINEFEED         = 101,
212     HOME             = 102,
213     UP               = 103,
214     PAGEUP           = 104,
215     LEFT             = 105,
216     RIGHT            = 106,
217     END              = 107,
218     DOWN             = 108,
219     PAGEDOWN         = 109,
220     INSERT           = 110,
221     DELETE           = 111,
222     MACRO            = 112,
223     MUTE             = 113,
224     VOLUMEDOWN       = 114,
225     VOLUMEUP         = 115,
226     POWER            = 116,
227     KPEQUAL          = 117,
228     KPPLUSMINUS      = 118,
229     PAUSE            = 119,
230     KPCOMMA          = 121,
231     HANGEUL          = 122,
232     HANGUEL          = 122,
233     HANJA            = 123,
234     YEN              = 124,
235     LEFTMETA         = 125,
236     RIGHTMETA        = 126,
237     COMPOSE          = 127,
238     STOP             = 128,
239     AGAIN            = 129,
240     PROPS            = 130,
241     UNDO             = 131,
242     FRONT            = 132,
243     COPY             = 133,
244     OPEN             = 134,
245     PASTE            = 135,
246     FIND             = 136,
247     CUT              = 137,
248     HELP             = 138,
249     MENU             = 139,
250     CALC             = 140,
251     SETUP            = 141,
252     SLEEP            = 142,
253     WAKEUP           = 143,
254     FILE             = 144,
255     SENDFILE         = 145,
256     DELETEFILE       = 146,
257     XFER             = 147,
258     PROG1            = 148,
259     PROG2            = 149,
260     WWW              = 150,
261     MSDOS            = 151,
262     COFFEE           = 152,
263     DIRECTION        = 153,
264     CYCLEWINDOWS     = 154,
265     MAIL             = 155,
266     BOOKMARKS        = 156,
267     COMPUTER         = 157,
268     BACK             = 158,
269     FORWARD          = 159,
270     CLOSECD          = 160,
271     EJECTCD          = 161,
272     EJECTCLOSECD     = 162,
273     NEXTSONG         = 163,
274     PLAYPAUSE        = 164,
275     PREVIOUSSONG     = 165,
276     STOPCD           = 166,
277     RECORD           = 167,
278     REWIND           = 168,
279     PHONE            = 169,
280     ISO              = 170,
281     CONFIG           = 171,
282     HOMEPAGE         = 172,
283     REFRESH          = 173,
284     EXIT             = 174,
285     MOVE             = 175,
286     EDIT             = 176,
287     SCROLLUP         = 177,
288     SCROLLDOWN       = 178,
289     KPLEFTPAREN      = 179,
290     KPRIGHTPAREN     = 180,
291     NEW              = 181,
292     REDO             = 182,
293     F13              = 183,
294     F14              = 184,
295     F15              = 185,
296     F16              = 186,
297     F17              = 187,
298     F18              = 188,
299     F19              = 189,
300     F20              = 190,
301     F21              = 191,
302     F22              = 192,
303     F23              = 193,
304     F24              = 194,
305     PLAYCD           = 200,
306     PAUSECD          = 201,
307     PROG3            = 202,
308     PROG4            = 203,
309     SUSPEND          = 205,
310     CLOSE            = 206,
311     PLAY             = 207,
312     FASTFORWARD      = 208,
313     BASSBOOST        = 209,
314     PRINT            = 210,
315     HP               = 211,
316     CAMERA           = 212,
317     SOUND            = 213,
318     QUESTION         = 214,
319     EMAIL            = 215,
320     CHAT             = 216,
321     SEARCH           = 217,
322     CONNECT          = 218,
323     FINANCE          = 219,
324     SPORT            = 220,
325     SHOP             = 221,
326     ALTERASE         = 222,
327     CANCEL           = 223,
328     BRIGHTNESSDOWN   = 224,
329     BRIGHTNESSUP     = 225,
330     MEDIA            = 226,
331     SWITCHVIDEOMODE  = 227,
332     KBDILLUMTOGGLE   = 228,
333     KBDILLUMDOWN     = 229,
334     KBDILLUMUP       = 230,
335     SEND             = 231,
336     REPLY            = 232,
337     FORWARDMAIL      = 233,
338     SAVE             = 234,
339     DOCUMENTS        = 235,
340     UNKNOWN          = 240,
341     OK               = 0x160,
342     SELECT           = 0x161,
343     GOTO             = 0x162,
344     CLEAR            = 0x163,
345     POWER2           = 0x164,
346     OPTION           = 0x165,
347     INFO             = 0x166,
348     TIME             = 0x167,
349     VENDOR           = 0x168,
350     ARCHIVE          = 0x169,
351     PROGRAM          = 0x16a,
352     CHANNEL          = 0x16b,
353     FAVORITES        = 0x16c,
354     EPG              = 0x16d,
355     PVR              = 0x16e,
356     MHP              = 0x16f,
357     LANGUAGE         = 0x170,
358     TITLE            = 0x171,
359     SUBTITLE         = 0x172,
360     ANGLE            = 0x173,
361     ZOOM             = 0x174,
362     MODE             = 0x175,
363     KEYBOARD         = 0x176,
364     SCREEN           = 0x177,
365     PC               = 0x178,
366     TV               = 0x179,
367     TV2              = 0x17a,
368     VCR              = 0x17b,
369     VCR2             = 0x17c,
370     SAT              = 0x17d,
371     SAT2             = 0x17e,
372     CD               = 0x17f,
373     TAPE             = 0x180,
374     RADIO            = 0x181,
375     TUNER            = 0x182,
376     PLAYER           = 0x183,
377     TEXT             = 0x184,
378     DVD              = 0x185,
379     AUX              = 0x186,
380     MP3              = 0x187,
381     AUDIO            = 0x188,
382     VIDEO            = 0x189,
383     DIRECTORY        = 0x18a,
384     LIST             = 0x18b,
385     MEMO             = 0x18c,
386     CALENDAR         = 0x18d,
387     RED              = 0x18e,
388     GREEN            = 0x18f,
389     YELLOW           = 0x190,
390     BLUE             = 0x191,
391     CHANNELUP        = 0x192,
392     CHANNELDOWN      = 0x193,
393     FIRST            = 0x194,
394     LAST             = 0x195,
395     AB               = 0x196,
396     NEXT             = 0x197,
397     RESTART          = 0x198,
398     SLOW             = 0x199,
399     SHUFFLE          = 0x19a,
400     BREAK            = 0x19b,
401     PREVIOUS         = 0x19c,
402     DIGITS           = 0x19d,
403     TEEN             = 0x19e,
404     TWEN             = 0x19f,
405     DEL_EOL          = 0x1c0,
406     DEL_EOS          = 0x1c1,
407     INS_LINE         = 0x1c2,
408     DEL_LINE         = 0x1c3,
409     FN               = 0x1d0,
410     FN_ESC           = 0x1d1,
411     FN_F1            = 0x1d2,
412     FN_F2            = 0x1d3,
413     FN_F3            = 0x1d4,
414     FN_F4            = 0x1d5,
415     FN_F5            = 0x1d6,
416     FN_F6            = 0x1d7,
417     FN_F7            = 0x1d8,
418     FN_F8            = 0x1d9,
419     FN_F9            = 0x1da,
420     FN_F10           = 0x1db,
421     FN_F11           = 0x1dc,
422     FN_F12           = 0x1dd,
423     FN_1             = 0x1de,
424     FN_2             = 0x1df,
425     FN_D             = 0x1e0,
426     FN_E             = 0x1e1,
427     FN_F             = 0x1e2,
428     FN_S             = 0x1e3,
429     FN_B             = 0x1e4,
430     MAX              = 0x1ff,
431   };
432
433   Rel = {
434     X      = 0x00,
435     Y      = 0x01,
436     Z      = 0x02,
437     RX     = 0x03,
438     RY     = 0x04,
439     RZ     = 0x05,
440     HWHEEL = 0x06,
441     DIAL   = 0x07,
442     WHEEL  = 0x08,
443     MISC   = 0x09,
444     MAX    = 0x0f,
445   };
446
447   Abs = {
448     X          = 0x00,
449     Y          = 0x01,
450     Z          = 0x02,
451     RX         = 0x03,
452     RY         = 0x04,
453     RZ         = 0x05,
454     THROTTLE   = 0x06,
455     RUDDER     = 0x07,
456     WHEEL      = 0x08,
457     GAS        = 0x09,
458     BRAKE      = 0x0a,
459     HAT0X      = 0x10,
460     HAT0Y      = 0x11,
461     HAT1X      = 0x12,
462     HAT1Y      = 0x13,
463     HAT2X      = 0x14,
464     HAT2Y      = 0x15,
465     HAT3X      = 0x16,
466     HAT3Y      = 0x17,
467     PRESSURE   = 0x18,
468     DISTANCE   = 0x19,
469     TILT_X     = 0x1a,
470     TILT_Y     = 0x1b,
471     TOOL_WIDTH = 0x1c,
472     VOLUME     = 0x20,
473     MISC       = 0x28,
474     MT_SLOT        = 0x2f,
475     MT_TOUCH_MAJOR = 0x30,
476     MT_TOUCH_MINOR = 0x31,
477     MT_WIDTH_MAJOR = 0x32,
478     MT_WIDTH_MINOR = 0x33,
479     MT_ORIENTATION = 0x34,
480     MT_POSITION_X  = 0x35,
481     MT_POSITION_Y  = 0x36,
482     MT_TOOL_TYPE   = 0x37,
483     MT_BLOB_ID     = 0x38,
484     MT_TRACKING_ID = 0x39,
485     MT_PRESSURE    = 0x3a,
486     MT_DISTANCE    = 0x3b,
487     MAX        = 0x3f,
488   };
489
490   Btn = {
491     MISC           = 0x100,
492     BTN_0          = 0x100,
493     BTN_1          = 0x101,
494     BTN_2          = 0x102,
495     BTN_3          = 0x103,
496     BTN_4          = 0x104,
497     BTN_5          = 0x105,
498     BTN_6          = 0x106,
499     BTN_7          = 0x107,
500     BTN_8          = 0x108,
501     BTN_9          = 0x109,
502     MOUSE          = 0x110,
503     LEFT           = 0x110,
504     RIGHT          = 0x111,
505     MIDDLE         = 0x112,
506     SIDE           = 0x113,
507     EXTRA          = 0x114,
508     FORWARD        = 0x115,
509     BACK           = 0x116,
510     TASK           = 0x117,
511     JOYSTICK       = 0x120,
512     TRIGGER        = 0x120,
513     THUMB          = 0x121,
514     THUMB2         = 0x122,
515     TOP            = 0x123,
516     TOP2           = 0x124,
517     PINKIE         = 0x125,
518     BASE           = 0x126,
519     BASE2          = 0x127,
520     BASE3          = 0x128,
521     BASE4          = 0x129,
522     BASE5          = 0x12a,
523     BASE6          = 0x12b,
524     DEAD           = 0x12f,
525     GAMEPAD        = 0x130,
526     A              = 0x130,
527     B              = 0x131,
528     C              = 0x132,
529     X              = 0x133,
530     Y              = 0x134,
531     Z              = 0x135,
532     TL             = 0x136,
533     TR             = 0x137,
534     TL2            = 0x138,
535     TR2            = 0x139,
536     SELECT         = 0x13a,
537     START          = 0x13b,
538     MODE           = 0x13c,
539     THUMBL         = 0x13d,
540     THUMBR         = 0x13e,
541     DIGI           = 0x140,
542     TOOL_PEN       = 0x140,
543     TOOL_RUBBER    = 0x141,
544     TOOL_BRUSH     = 0x142,
545     TOOL_PENCIL    = 0x143,
546     TOOL_AIRBRUSH  = 0x144,
547     TOOL_FINGER    = 0x145,
548     TOOL_MOUSE     = 0x146,
549     TOOL_LENS      = 0x147,
550     TOUCH          = 0x14a,
551     STYLUS         = 0x14b,
552     STYLUS2        = 0x14c,
553     TOOL_DOUBLETAP = 0x14d,
554     TOOL_TRIPLETAP = 0x14e,
555     WHEEL          = 0x150,
556     GEAR_DOWN      = 0x150,
557     GEAR_UP        = 0x151,
558   };
559 };
560
561 -- stores all kown input devices
562 streams = {};
563 sources = {};
564 Input_device = {
565   Devs = {};
566   quirks = {};
567   Bus = {
568     [0x01] = "pci",
569     [0x02] = "isapnp",
570     [0x03] = "usb",
571     [0x04] = "hil",
572     [0x05] = "bluetooth",
573     [0x06] = "virtual",
574
575     [0x10] = "isa",
576     [0x11] = "i8042",
577     [0x12] = "xtkbd",
578     [0x13] = "rs232",
579     [0x14] = "gameport",
580     [0x15] = "parport",
581     [0x16] = "amiga",
582     [0x17] = "adb",
583     [0x18] = "i2c",
584     [0x19] = "host",
585     [0x1A] = "gsc",
586     [0x1B] = "atari",
587
588     PCI         = 0x01,
589     ISAPNP      = 0x02,
590     USB         = 0x03,
591     HIL         = 0x04,
592     BLUETOOTH   = 0x05,
593     VIRTUAL     = 0x06,
594
595     ISA         = 0x10,
596     I8042       = 0x11,
597     XTKBD       = 0x12,
598     RS232       = 0x13,
599     GAMEPORT    = 0x14,
600     PARPORT     = 0x15,
601     AMIGA       = 0x16,
602     ADB         = 0x17,
603     I2C         = 0x18,
604     HOST        = 0x19,
605     GSC         = 0x1A,
606     ATARI       = 0x1B,
607   };
608 };
609
610 function Input_device:drop_event(e)
611   return true;
612 end
613
614 function Input_device:get_stream_info()
615   return self.source:get_stream_info(self.stream);
616 end
617
618 function Input_device:get_abs_info(...)
619   return self.source:get_abs_info(self.stream, ...);
620 end
621
622
623 function Input_device:init()
624   self.current_report = Hid_report(self.global_id, 0x10, 0x29, 0x8, 0x10, 0x10 );
625 end
626
627 function Input_device:process_event(ev)
628   local r = self.current_report;
629   local t = ev[1];
630   local c = ev[2];
631   if t == 3 then
632     if c < 0x2f then
633       r:set(3, c, ev[3]);
634     else
635       r:mt_set(c, ev[3]);
636     end
637   elseif t == 1 then
638     r:add_key(c, ev[3]);
639   elseif t > 1 and t <=5 then
640     r:set(t, c, ev[3]);
641   elseif t == 0 and c == 2 then -- mt sync
642     r:submit_mt();
643   elseif t == 0 and c == 0 then -- full sync
644     r:sync(ev[4]);
645     self:process(r);
646     r:clear();
647   elseif t == 0 and c == 0x80 then -- l4re syn cfg
648     r:clear();
649     for s in Mag.core_api:sessions() do
650       s:put_event(self.global_id, t, c, ev[3], ev[4]);
651     end
652   end
653 end
654
655 -- ----------------------------------------------------------------------
656 --  Generic pointer device handling.
657 --
658 --  Handles absolute and relative motion events and the buttons
659 --  corresponding to a pointer device, such as a mouse.
660 -- ----------------------------------------------------------------------
661 Input_device.Devs.pointer = {};
662
663 Input_device.Devs.pointer.drag_focus    = View_proxy(user_state);
664
665 function Input_device.new_virt_ctrl(_axes, _core)
666   local ctrl = { axes = _axes, core = _core };
667   for _, a in pairs(_axes) do
668     a.ctrl = ctrl;
669   end
670   return ctrl;
671 end
672
673 local screen_width, screen_height = user_state:screen_size()
674
675 Input_device.core_ctrl = Input_device.new_virt_ctrl(
676   { x = { idx = Event.Abs.X, min = 0, max = screen_width,
677           fuzz = 0, flat = 0, mode = 1, v = 0 },
678     y = { idx = Event.Abs.Y, min = 0, max = screen_height,
679           fuzz = 0, flat = 0, mode = 2, v = 0 } }, true);
680
681 function Input_device.Devs.pointer:init()
682   Input_device.init(self);
683   self.pointed_view  = View_proxy(user_state);
684
685   -- get core pointer control descriptions for x and y axis
686   local core_ctrl = Input_device.core_ctrl;
687
688   self.xfrm_abs_axes = {};
689   
690   local d_info = self.info;
691
692   if d_info:get_absbit(0) and d_info:get_absbit(1) then
693     -- we transfrom the absolute x and y axes of this device to core control
694     -- coordinates
695     self.xfrm_abs_axes[#self.xfrm_abs_axes] =
696       { x = Event.Abs.X, y = Event.Abs.Y,
697         -- we have our abs x and abs y axis controling our core pointer
698         core_x = core_ctrl.axes.x, core_y = core_ctrl.axes.y,
699         xfrm = self:get_pointer_transform_func(Event.Abs.X, Event.Abs.Y) };
700   end
701
702   self.virt_ctrls = { core_ctrl };
703
704   self.vaxes = { [Event.Abs.X] = core_ctrl.axes.x,
705                  [Event.Abs.Y] = core_ctrl.axes.y };
706
707   self.rel_to_abs_axes = { [Event.Rel.X] = { va = core_ctrl.axes.x, ctrl = core_ctrl },
708                            [Event.Rel.Y] = { va = core_ctrl.axes.y, ctrl = core_ctrl } };
709
710   local abs_info = Axis_info_vector(0x40);
711   self.current_report:set_abs_info(abs_info);
712   self.abs_info = abs_info;
713   for a = 0, 0x3f do
714     if d_info:get_absbit(a) then
715       local r, i = self:get_abs_info(a);
716       if r == 0 then
717         abs_info:set(a, i);
718       end
719     end
720   end
721
722   if abs_info[0] then
723     abs_info[0].mode = 1;
724   end
725   if abs_info[1] then
726     abs_info[1].mode = 2;
727   end
728
729   if d_info:get_absbit(0x35) and d_info:get_absbit(0x36) then
730     local mt_ctrl = Input_device.new_virt_ctrl(
731       { x = { idx = 0x35, min = 0, max = screen_width,
732               fuzz = 0, flat = 0, mode = 1, v = 0 },
733         y = { idx = 0x36, min = 0, max = screen_height,
734               fuzz = 0, flat = 0, mode = 2, v = 0 } })
735     self.xfrm_abs_axes[#self.xfrm_abs_axes + 1] =
736       { x = 0x35, y = 0x36, xfrm = self:get_pointer_transform_func(0x35, 0x36) };
737     self.vaxes[0x35] = mt_ctrl.axes.x;
738     self.vaxes[0x36] = mt_ctrl.axes.y;
739     abs_info[0x35].mode = 1;
740     abs_info[0x36].mode = 2;
741   end
742
743   for a, i in pairs(self.vaxes) do
744     if (not abs_info[a]) then
745       local ai = abs_info:create(a);
746       ai.value = i.value or 0;
747       ai.min   = i.min or 0;
748       ai.max   = i.max or 0;
749       ai.fuzz  = i.fuzz or 0;
750       ai.resolution = i.resolution or 0;
751       ai.delta = i.delta or 0;
752       ai.mode  = i.mode or 0;
753     end
754   end
755 end
756
757 function Input_device.Devs.pointer:get_stream_info()
758   local r, info = self:get_stream_info();
759
760   if r < 0 then
761     return r;
762   end
763
764   -- This device is translated to a core pointer
765   -- this means it sends always absolute X,Y axis pairs
766   if self.vaxes then
767     info:set_evbit(Event.ABS, true);
768     for a, _ in pairs(self.vaxes) do
769       info:set_absbit(a, true);
770     end
771   end
772
773   if self.rel_to_abs_axes then
774     for a, _ in pairs(self.rel_to_abs_axes) do
775       info:set_relbit(a, false);
776     end
777   end
778
779   return r, info;
780 end
781
782 function Input_device.Devs.pointer:get_abs_info(...)
783   local axes = {...};
784   local pass = true;
785   local vaxes = self.vaxes;
786   local r = {};
787
788   for _, s in ipairs(axes) do
789     if vaxes[s] then
790       r[_] = vaxes[s];
791     else
792       r[_] = self.abs_info[s];
793       if not r[_] then
794         return -22;
795       end
796     end
797   end
798   return (vaxes ~= nil), table.unpack(r);
799 end
800
801 -- generic transformationof absolute pointer events to screen coordinates
802 function Input_device:get_pointer_transform_func(ax, ay)
803   -- transformation of raw coordinates to screen coordinates
804   local w, h = user_state:screen_size();
805   return function(self, p)
806     if self.abs_info then
807       return (p[1] * w) // self.abs_info[ax].delta,
808              (p[2] * h) // self.abs_info[ay].delta;
809     else
810       return p[1], p[2];
811     end
812   end;
813 end
814
815 -- ----------------------------------------------------------------
816 -- sync a set of events from a pointer device
817 --
818 -- - converts motion events to the core mouse pointer of mag
819 -- - manages dragging and keyboard focus
820
821
822 Input_device.Default = {};
823
824 function Input_device.Default:axis_xfrm(report)
825   local function do_xfrm_axes(xfrm_axes, axes)
826     if not axes then return end
827     for i, cax in pairs(xfrm_axes) do
828       local x = axes[cax.x];
829       local y = axes[cax.y];
830       if x and y then
831         x, y = cax.xfrm(self, {x, y});
832         axes[cax.x] = x;
833         axes[cax.y] = y;
834         local ca = cax.core_x;
835         if ca then
836           ca.v = x;
837           ca.ctrl.update = true;
838         end
839         local ca = cax.core_y;
840         if ca then
841           ca.v = y;
842           ca.ctrl.update = true;
843         end
844       end
845     end
846   end
847
848   -- scale and rotate absolute axes
849   local abs = report[3];
850   do_xfrm_axes(self.xfrm_abs_axes, abs);
851   for id = 0, 10 do
852     do_xfrm_axes(self.xfrm_abs_axes, report:get_mt_vals(id));
853   end
854
855   -- transform relative to absolute axes if needed
856   local rel = report[2];
857   if rel then
858     for a, inf in pairs(self.rel_to_abs_axes) do
859       local v = rel[a];
860       if v then
861         rel:inv(a);
862         local vctrl = inf.ctrl;
863         local va = inf.va;
864         v = va.v + v;
865         if v < va.min then
866           v = va.min;
867         end
868         if v > va.max then
869           v = va.max;
870         end
871         va.v = v;
872         vctrl.dirty = true;
873       end
874     end
875   end
876
877   -- write back virtual controls if they are dirty
878   if abs then
879     for c, vc in pairs(self.virt_ctrls) do
880         for i, va in pairs(vc.axes) do
881           abs:set(va.idx, va.v);
882         end
883       if vc.dirty then
884         vc.update = true; -- if its a core control we need an update
885         vc.dirty = false;
886       end
887     end
888   end
889 end
890
891 function Input_device.Default:foreach_key(report, func)
892   local i = 0;
893   while true do
894     local c, v = report:get_key_event(i);
895     if not c then
896       break;
897     end
898     if func(self, c, v) then
899       return true;
900     end
901     i = i + 1;
902   end
903 end
904
905 function Input_device.Default:do_core_ctrl()
906   local cctrl = Input_device.core_ctrl;
907   if cctrl.update then
908     cctrl.update = false;
909     local x, y = cctrl.axes.x.v, cctrl.axes.y.v;
910     user_state:set_pointer(x, y, self.hide_cursor or false);
911     user_state:find_pointed_view(self.pointed_view); -- should need x and y here
912   end
913 end
914
915 function Input_device.Default:core_keys(report)
916   local toggle_mode = 0;
917   local function xray_key(s, c, v)
918     if v ~= 1 then
919       return false;
920     end
921     return (c == 70) or (c == Event.Key.NEXTSONG);
922   end
923
924   local function kill_key(s, c, v)
925     if v ~= 1 then
926       return false;
927     end
928     return (c == 210) or (c == 99);
929   end
930
931   local fek = Input_device.Default.foreach_key;
932
933   if fek(self, report, xray_key) then
934     toggle_mode = 1;
935   elseif fek(self, report, kill_key) then
936     toggle_mode = 2;
937   end
938   if toggle_mode ~= 0 then
939     user_state:toggle_mode(toggle_mode);
940     return true;
941   end
942   return false;
943 end
944
945 function Input_device.Default:dnd_handling()
946   local ptr = Input_device.Devs.pointer;
947   if ptr.dragging then
948     if ptr.dragging == self and self.stop_drag then
949       ptr.dragging = false;
950     end
951     self.stop_drag = false;
952     return ptr.drag_focus;
953   else
954     return self.pointed_view;
955   end
956 end
957
958 function Input_device.Devs.pointer:hook(report)
959   local n_press = 0;
960   local n_release = 0;
961   local function k(s, c, v)
962     if v == 1 then
963       n_press = n_press + 1;
964     elseif v == 0 then
965       n_release = n_release + 1;
966     end
967   end
968   Input_device.Default.foreach_key(self, report, k);
969
970   local n = self.pressed_keys + n_press - n_release;
971   if n < 0 then
972     n = 0;
973   end
974
975   self.pressed_keys = n;
976
977   local ptr = Input_device.Devs.pointer;
978
979   if (not ptr.dragging) and n_press > 0 and n == n_press then
980     ptr.dragging = self;
981     ptr.drag_focus:set(self.pointed_view);
982     self.set_focus = true;
983   elseif n_release > 0 and n == 0 then
984     self.stop_drag = true;
985   end
986 end
987
988 function Input_device.Devs.pointer:process(report)
989   local update = false;
990   local sink;
991   local dfl = Input_device.Default;
992
993   dfl.axis_xfrm(self, report);
994   dfl.do_core_ctrl(self);
995
996   if self.handler.hook then
997     self.handler.hook(self, report);
998   end
999
1000   sink = dfl.dnd_handling(self);
1001   -- for keyboards: update = dfl.core_keys(self, report);
1002   if self.set_focus then
1003     update = user_state:set_kbd_focus(self.pointed_view) or update;
1004     self.set_focus = false;
1005   end
1006   user_state:post_event(sink, report, update, true);
1007 end
1008
1009
1010 Input_device.Devs.touchscreen = {};
1011 setmetatable(Input_device.Devs.touchscreen, { __index = Input_device.Devs.pointer});
1012
1013 function Input_device.Devs.touchscreen:init()
1014   Input_device.Devs.pointer.init(self);
1015   self.hide_cursor = true;
1016 end
1017
1018 function Input_device.Devs.touchscreen:get_stream_info()
1019   local r, info = Input_device.Devs.pointer.get_stream_info(self);
1020
1021   if r < 0 then
1022     return r;
1023   end
1024
1025   -- additionally we have a left button, but no longer the touch button
1026   --info:set_keybit(Event.Btn.TOUCH, false);
1027   --info:set_keybit(Event.Btn.LEFT, true);
1028   return r, info;
1029 end
1030
1031 function Input_device.Devs.touchscreen:button(e)
1032   local c = e[2];
1033   local v = e[3];
1034   if c == Event.Btn.TOUCH then
1035     e[2] = Event.Btn.LEFT;
1036   end
1037   Input_device.Devs.pointer.button(self, e);
1038 end
1039
1040 -- ----------------------------------------------------------------------
1041 --  Touchpad pointing device handling
1042 --  Inherits from pointer device and adds functionality to:
1043 --  - transform absolute finger positions to relative movements
1044 --  - tapping button emulation (missing)
1045 --  - scroll wheel emulation etc (missing)
1046 -- ----------------------------------------------------------------------
1047 Input_device.Devs.touchpad = {};
1048 setmetatable(Input_device.Devs.touchpad, { __index = Input_device.Devs.pointer});
1049
1050 function Input_device.Devs.touchpad:init()
1051   Input_device.Devs.pointer.init(self);
1052   self.touchdev = {
1053     touch      = false;
1054     release    = false;
1055     touch_drag = false;
1056     tap_time   = 150 * 1000; -- 150 ms
1057     btn_report = Hid_report(self.global_id,0,0,0,0,0);
1058   };
1059   local tdev = self.touchdev;
1060   tdev.p    = { Axis_buf(4), Axis_buf(4) };
1061   tdev.pkts = 0;
1062 end
1063
1064 function Input_device.Devs.touchpad:get_stream_info()
1065   local r, info = Input_device.Devs.pointer.get_stream_info(self);
1066
1067   if r < 0 then
1068     return r;
1069   end
1070
1071   -- additionally we have a left button, but no longer the touch button
1072   info:set_keybit(Event.Btn.LEFT, true);
1073   info:set_keybit(Event.Btn.TOOL_FINGER, false);
1074   info:set_keybit(Event.Btn.TOOL_PEN, true);
1075
1076   -- hm, X does not like to have MT values if we do not send them
1077   info:set_absbit(0x2f, false);
1078   info:set_absbit(0x30, false);
1079   info:set_absbit(0x31, false);
1080   info:set_absbit(0x32, false);
1081   info:set_absbit(0x33, false);
1082   info:set_absbit(0x34, false);
1083   info:set_absbit(0x35, false);
1084   info:set_absbit(0x36, false);
1085   info:set_absbit(0x37, false);
1086   info:set_absbit(0x38, false);
1087   info:set_absbit(0x39, false);
1088   info:set_absbit(0x3a, false);
1089   info:set_absbit(0x3b, false);
1090
1091   return r, info;
1092 end
1093
1094 function Input_device.Devs.touchpad:button(r)
1095   local c, v = r:find_key_event(Event.Btn.TOUCH);
1096   if not v or v == 2 then
1097     return
1098   end
1099
1100   local time = r:time();
1101   local p = self.touchdev;
1102
1103   -- drop the touch event, we convert it to left mouse button
1104   --r[1][Event.Btn.TOUCH] = nil;
1105   r:remove_key_event(Event.Btn.TOOL_FINGER);
1106
1107   if v == 1 then
1108     if p.release and p.release + p.tap_time > time then
1109       p.touch_drag = true;
1110       r:add_key(Event.Btn.LEFT, 1);
1111     end
1112     p.touch = time;
1113     p.release = false;
1114   else
1115     if p.touch_drag then
1116       p.touch_drag = false;
1117       r:add_key(Event.Btn.LEFT, 0);
1118     elseif p.touch and p.touch + p.tap_time > time then
1119       p.release = time;
1120
1121       local dr = p.btn_report;
1122
1123       dr:clear();
1124       dr:sync(time);
1125       dr:add_key(Event.Btn.LEFT, 1);
1126       self:process(dr);
1127
1128       r:add_key(Event.Btn.LEFT, 0);
1129     end
1130     p.pkts = 0;
1131     p.touch = false;
1132   end
1133 end
1134
1135 function Input_device.Devs.touchpad:motion(r)
1136   local p = self.touchdev;
1137   if not p.touch then
1138     -- drop event, if not touched
1139     r[2]:clear();
1140     r[3]:clear();
1141     return
1142   end
1143
1144   local abs = r[3];
1145   for c = 1, 2 do
1146     local v = abs[c-1];
1147     if v then
1148       local cnt = p.pkts;
1149       p.p[c][cnt] = v;
1150       if cnt >= 2 then
1151         local size = self.abs_info[c-1].delta;
1152         r[2]:set(c-1, (v - p.p[c]:get(cnt - 2)) * 256 // size);
1153       end
1154       abs:inv(c-1);
1155     end
1156   end
1157
1158   local nc = p.pkts + 1;
1159   p.pkts = nc;
1160   p.p[1]:copy(nc, nc - 1);
1161   p.p[2]:copy(nc, nc - 1);
1162 end
1163
1164 function Input_device.Devs.touchpad:process(r)
1165   Input_device.Devs.touchpad.button(self, r);
1166   Input_device.Devs.touchpad.motion(self, r);
1167   Input_device.Devs.pointer.process(self, r)
1168 end
1169
1170 -- ----------------------------------------------------------------------
1171 --  Keyboard device handling
1172 -- ----------------------------------------------------------------------
1173 Input_device.Devs.keyboard = {};
1174 setmetatable(Input_device.Devs.keyboard, { __index = Input_device });
1175
1176 function Input_device.Devs.keyboard:get_stream_info()
1177   return self:get_stream_info();
1178 end
1179
1180 function Input_device.Devs.keyboard:get_abs_info(...)
1181   return self:get_abs_info(...);
1182 end
1183
1184 function Input_device.Devs.keyboard:process(report)
1185   local dfl = Input_device.Default;
1186
1187   if self.handler.hook then
1188     self.handler.hook(self, report);
1189   end
1190   local update = dfl.core_keys(self, report);
1191   user_state:post_event(nil, report, update, true);
1192 end
1193
1194 Input_device.Devs.unknown = Input_device;
1195
1196 function Input_device:find_device_type()
1197   local bus, vend, prod, ver = self.info:get_device_id();
1198   self.dev_id = { bus = bus, vendor = vend, product = prod, version = ver };
1199   local id = bus .. "_" .. vend .. "_" .. prod;
1200
1201   self.dev_type = "unknown";
1202
1203   if self.quirks[id] and self.quirks[id](self, id) then
1204     return;
1205   end
1206
1207   id = id .. "_" .. ver;
1208
1209   if self.quirks[id] and self.quirks[id](self, id) then
1210     return;
1211   end
1212
1213   local have_keys = self.info:get_evbit(1);
1214   if (have_keys and self.info:get_evbit(2)) then
1215     -- we have relative axes, can be a mouse
1216     if (self.info:get_relbit(0) and self.info:get_relbit(1)
1217         and self.info:get_keybit(0x110)) then
1218       -- x and y axis and at least the left mouse button found
1219       self.dev_type = "pointer";
1220     end
1221   end
1222   if (have_keys and self.info:get_evbit(3)) then
1223     -- we have absolute axes, can be a mouse
1224     if self.info:get_absbit(0) and self.info:get_absbit(1) then
1225       if self.info:get_keybit(0x110) then
1226         -- x and y axis and at least the left mouse button found
1227         self.dev_type = "pointer";
1228       end
1229       if self.info:get_keybit(Event.Btn.TOUCH)
1230          and not self.info:get_keybit(0x110) then
1231         -- x and y axis and at least touch button found
1232         self.dev_type = "touchscreen";
1233       end
1234     end
1235   end
1236
1237   if self.dev_type == "pointer" then
1238     if self.info:get_keybit(Event.Btn.TOOL_FINGER) then
1239       self.dev_type = "touchpad";
1240     end
1241   end
1242
1243   if (have_keys) then
1244     local k;
1245     for k = 0, 199 do
1246       if (self.info:get_keybit(k)) then
1247         self.dev_type = "keyboard";
1248         return;
1249       end
1250     end
1251   end
1252 end
1253
1254 function Input_device:delete()
1255   streams[self.global_id] = nil;
1256   sources[self.source][self.stream] = nil;
1257   print (string.format([==[Input: remove device (src='%s' stream='%s')]==],
1258                        tostring(self.source), tostring(self.stream)));
1259   self = nil;
1260   collectgarbage();
1261 end
1262
1263
1264 -- -----------------------------------------------------------------------
1265 --  Create a input device (stream) object.
1266 --  A single input stream is managed by a device specific set of
1267 --  methods and data structures.
1268 -- -----------------------------------------------------------------------
1269 local input_device_mt = { __index = Input_device };
1270
1271 function create_input_device(source, stream)
1272   local dh = {
1273     -- the device handle itself
1274     source        = source,
1275     stream        = stream,
1276     global_id     = #streams + 1;
1277
1278     -- number of keys currently pressed on this device
1279     pressed_keys  = 0,
1280
1281     -- data according to the current bundle of events (one comound event)
1282     -- need to set the focus to the pointed view
1283     set_focus     = false,
1284     -- the current events stop dragging mode
1285     stop_drag     = false,
1286     -- the events to pass to the applications
1287     events        = {},
1288     -- event handler for the device
1289     process       = Input_device.drop_event
1290   };
1291
1292   setmetatable(dh, input_device_mt);
1293
1294   local r;
1295   r, dh.info = dh:get_stream_info();
1296
1297   sources[source][stream] = dh;
1298   streams[dh.global_id] = dh;
1299
1300   dh:find_device_type();
1301   dh.handler = Input_device.Devs[dh.dev_type] or {};
1302   dh.process = dh.handler.process or Input_device.drop_event;
1303   if dh.handler.init then dh.handler.init(dh); end
1304
1305   local pdev;
1306   function pdev(dh)
1307     local a, b, c, d = dh.info:get_device_id();
1308     if Input_device.Bus[a] then
1309       return Input_device.Bus[a], b, c, d;
1310     end
1311     return "bus " .. a, b, c, d;
1312   end
1313
1314   print (string.format([==[Input: new %s device (src='%s' stream='%s')
1315                            bus='%s' vendor=0x%x product=0x%x version=%d]==],
1316                        dh.dev_type, tostring(dh.source), tostring(dh.stream),
1317                        pdev(dh)));
1318   return dh;
1319 end