Moje HTPC i nie tylko

Takie tam…

Pilot Elmak Maxter Plus pod linuxem

with 5 comments

Pilot Maxter Plus jako urządzenie HID jest obsługiwany przez Linuksa bez specjalnych driverów. Jednakże nie wszystkie klawisze pilota działają zgodnie z naszymi życzeniami. (Dla niecierpliwych lekarstwo na końcu wpisu)

Zdarzenia generowane przez przyciski pilota

Na początek test – jakie zdarzenia powstają w wyniku naciśnięcia poszczególnych klawiszy pilota. Do tego celu używam programu evtest, który wymaga podania nazwy urządzenia. Aby ją znaleźć wykonuję:

dg@htpc:~$ uname -a
Linux htpc 2.6.32-34-generic #77-Ubuntu SMP Tue Sep 13 19:40:53 UTC 2011 i686 GNU/Linux

dg@htpc:~$ ls -l /dev/input/by-id/
razem 0
lrwxrwxrwx 1 root root 9 2011-11-10 23:49 usb-ELMAK.pl_irMAKbd_pl-event-mouse -> ../event5
lrwxrwxrwx 1 root root 9 2011-11-10 23:49 usb-ELMAK.pl_irMAKbd_pl-mouse -> ../mouse2

I potem mogę zrobić:

dg@htpc:~$ sudo evtest /dev/input/event5
Input driver version is 1.0.0
Input device ID: bus 0x3 vendor 0x18b1 product 0x37 version 0x100
Input device name: „ELMAK.pl irMAKbd pl”
Supported events:
Event type 0 (Sync)
Event type 1 (Key)
Event code 1 (Esc)
Event code 2 (1)
Event code 3 (2)
Event code 4 (3)
Event code 5 (4)
Event code 6 (5)
Event code 7 (6)
Event code 8 (7)
Event code 9 (8)
Event code 10 (9)
Event code 11 (0)
Event code 12 (Minus)
Event code 13 (Equal)
Event code 14 (Backspace)
Event code 15 (Tab)
Event code 16 (Q)
Event code 17 (W)
Event code 18 (E)
Event code 19 (R)
Event code 20 (T)
Event code 21 (Y)
Event code 22 (U)
Event code 23 (I)
Event code 24 (O)
Event code 25 (P)
Event code 26 (LeftBrace)
Event code 27 (RightBrace)
Event code 28 (Enter)
Event code 29 (LeftControl)
Event code 30 (A)
Event code 31 (S)
Event code 32 (D)
Event code 33 (F)
Event code 34 (G)
Event code 35 (H)
Event code 36 (J)
Event code 37 (K)
Event code 38 (L)
Event code 39 (Semicolon)
Event code 40 (Apostrophe)
Event code 41 (Grave)
Event code 42 (LeftShift)
Event code 43 (BackSlash)
Event code 44 (Z)
Event code 45 (X)
Event code 46 (C)
Event code 47 (V)
Event code 48 (B)
Event code 49 (N)
Event code 50 (M)
Event code 51 (Comma)
Event code 52 (Dot)
Event code 53 (Slash)
Event code 54 (RightShift)
Event code 55 (KPAsterisk)
Event code 56 (LeftAlt)
Event code 57 (Space)
Event code 58 (CapsLock)
Event code 59 (F1)
Event code 60 (F2)
Event code 61 (F3)
Event code 62 (F4)
Event code 63 (F5)
Event code 64 (F6)
Event code 65 (F7)
Event code 66 (F8)
Event code 67 (F9)
Event code 68 (F10)
Event code 69 (NumLock)
Event code 70 (ScrollLock)
Event code 71 (KP7)
Event code 72 (KP8)
Event code 73 (KP9)
Event code 74 (KPMinus)
Event code 75 (KP4)
Event code 76 (KP5)
Event code 77 (KP6)
Event code 78 (KPPlus)
Event code 79 (KP1)
Event code 80 (KP2)
Event code 81 (KP3)
Event code 82 (KP0)
Event code 83 (KPDot)
Event code 85 (Zenkaku/Hankaku)
Event code 86 (102nd)
Event code 87 (F11)
Event code 88 (F12)
Event code 89 (RO)
Event code 90 (Katakana)
Event code 91 (HIRAGANA)
Event code 92 (Henkan)
Event code 93 (Katakana/Hiragana)
Event code 94 (Muhenkan)
Event code 95 (KPJpComma)
Event code 96 (KPEnter)
Event code 97 (RightCtrl)
Event code 98 (KPSlash)
Event code 99 (SysRq)
Event code 100 (RightAlt)
Event code 102 (Home)
Event code 103 (Up)
Event code 104 (PageUp)
Event code 105 (Left)
Event code 106 (Right)
Event code 107 (End)
Event code 108 (Down)
Event code 109 (PageDown)
Event code 110 (Insert)
Event code 111 (Delete)
Event code 113 (Mute)
Event code 114 (VolumeDown)
Event code 115 (VolumeUp)
Event code 116 (Power)
Event code 117 (KPEqual)
Event code 119 (Pause)
Event code 121 (KPComma)
Event code 122 (Hanguel)
Event code 123 (Hanja)
Event code 124 (Yen)
Event code 125 (LeftMeta)
Event code 126 (RightMeta)
Event code 127 (Compose)
Event code 128 (Stop)
Event code 129 (Again)
Event code 130 (Props)
Event code 131 (Undo)
Event code 132 (Front)
Event code 133 (Copy)
Event code 134 (Open)
Event code 135 (Paste)
Event code 136 (Find)
Event code 137 (Cut)
Event code 138 (Help)
Event code 139 (Menu)
Event code 140 (Calc)
Event code 142 (Sleep)
Event code 143 (WakeUp)
Event code 150 (WWW)
Event code 152 (Coffee)
Event code 158 (Back)
Event code 159 (Forward)
Event code 161 (EjectCD)
Event code 163 (NextSong)
Event code 164 (PlayPause)
Event code 165 (PreviousSong)
Event code 166 (StopCD)
Event code 167 (Record)
Event code 168 (Rewind)
Event code 169 (Phone)
Event code 173 (Refresh)
Event code 174 (Exit)
Event code 176 (Edit)
Event code 177 (ScrollUp)
Event code 178 (ScrollDown)
Event code 179 (KPLeftParenthesis)
Event code 180 (KPRightParenthesis)
Event code 183 (F13)
Event code 184 (F14)
Event code 185 (F15)
Event code 186 (F16)
Event code 187 (F17)
Event code 188 (F18)
Event code 189 (F19)
Event code 190 (F20)
Event code 191 (F21)
Event code 192 (F22)
Event code 193 (F23)
Event code 194 (F24)
Event code 207 (Play)
Event code 208 (Fast Forward)
Event code 209 (Bass Boost)
Event code 240 (Unknown)
Event code 256 (Btn0)
Event code 272 (LeftBtn)
Event code 273 (RightBtn)
Event code 274 (MiddleBtn)
Event code 362 (Program)
Event code 366 (PVR)
Event code 376 (PC)
Event code 377 (TV)
Event code 378 (TV2)
Event code 379 (VCR)
Event code 380 (VCR2)
Event code 381 (Sat)
Event code 383 (CD)
Event code 384 (Tape)
Event code 385 (Radio)
Event code 386 (Tuner)
Event code 388 (Text)
Event code 389 (DVD)
Event code 396 (Memo)
Event code 398 (Red)
Event code 399 (Green)
Event code 400 (Yellow)
Event code 401 (Blue)
Event code 402 (ChannelUp)
Event code 403 (ChannelDown)
Event code 405 (Last)
Event code 407 (Next)
Event code 416 (?)
Event code 417 (?)
Event code 418 (?)
Event code 419 (?)
Event code 439 (?)
Event type 2 (Relative)
Event code 0 (X)
Event code 1 (Y)
Event code 8 (Wheel)
Event type 3 (Absolute)
Event code 32 (Volume)
Value      0
Min        0
Max      250
Event code 40 (Misc)
Value      1
Min        0
Max      255
Event code 41 (?)
Value     22
Min        0
Max      255
Event code 42 (?)
Value      0
Min        0
Max      255
Event code 43 (?)
Value      0
Min        0
Max      255
Event type 4 (Misc)
Event code 4 (ScanCode)
Event type 17 (LED)
Event code 0 (NumLock)
Event code 1 (CapsLock)
Event code 2 (ScrollLock)
Event code 3 (Compose)
Event code 4 (Kana)
Event type 20 (Repeat)
Testing … (interrupt to exit)

Teraz program czeka na zdarzenia. Poniżej wyniki – naciskałem po kolei klawisze od góry – komentarze (#) określają jaki klawisz został naciśnięty:

#RECTV
Event: time 1321196723.117724, type 3 (Absolute), code 41 (?), value 168
Event: time 1321196723.117768, ————– Report Sync ————
#GUIDE
Event: time 1321196723.797860, type 4 (Misc), code 4 (ScanCode), value c008d
Event: time 1321196723.797894, type 1 (Key), code 362 (Program), value 1
Event: time 1321196723.797902, ————– Report Sync ————
Event: time 1321196723.805857, type 3 (Absolute), code 41 (?), value 38
Event: time 1321196723.805891, ————– Report Sync ————
Event: time 1321196724.021914, type 4 (Misc), code 4 (ScanCode), value c008d
Event: time 1321196724.021955, type 1 (Key), code 362 (Program), value 0
Event: time 1321196724.021968, ————– Report Sync ————
#LIVETV
Event: time 1321196724.421947, type 3 (Absolute), code 41 (?), value 165
Event: time 1321196724.421989, ————– Report Sync ————

#1
Event: time 1321196766.117179, type 4 (Misc), code 4 (ScanCode), value 70059
Event: time 1321196766.117218, type 1 (Key), code 79 (KP1), value 1
Event: time 1321196766.117227, ————– Report Sync ————
Event: time 1321196766.125143, type 3 (Absolute), code 41 (?), value 1
Event: time 1321196766.125177, ————– Report Sync ————
Event: time 1321196766.349223, type 4 (Misc), code 4 (ScanCode), value 70059
Event: time 1321196766.349256, type 1 (Key), code 79 (KP1), value 0
#2
Event: time 1321196766.349263, ————– Report Sync ————
Event: time 1321196766.781323, type 4 (Misc), code 4 (ScanCode), value 7005a
Event: time 1321196766.781379, type 1 (Key), code 80 (KP2), value 1
Event: time 1321196766.781388, ————– Report Sync ————
Event: time 1321196766.789275, type 3 (Absolute), code 41 (?), value 130
Event: time 1321196766.789319, ————– Report Sync ————
Event: time 1321196767.005329, type 4 (Misc), code 4 (ScanCode), value 7005a
Event: time 1321196767.005365, type 1 (Key), code 80 (KP2), value 0
#3
Event: time 1321196767.005375, ————– Report Sync ————
Event: time 1321196767.293387, type 4 (Misc), code 4 (ScanCode), value 7005b
Event: time 1321196767.293429, type 1 (Key), code 81 (KP3), value 1
Event: time 1321196767.293440, ————– Report Sync ————
Event: time 1321196767.301348, type 3 (Absolute), code 41 (?), value 3
Event: time 1321196767.301398, ————– Report Sync ————
Event: time 1321196767.525450, type 4 (Misc), code 4 (ScanCode), value 7005b
Event: time 1321196767.525494, type 1 (Key), code 81 (KP3), value 0
Event: time 1321196767.525500, ————– Report Sync ————

#4
Event: time 1321196773.998542, type 4 (Misc), code 4 (ScanCode), value 7005c
Event: time 1321196773.998582, type 1 (Key), code 75 (KP4), value 1
Event: time 1321196773.998592, ————– Report Sync ————
Event: time 1321196774.006539, type 3 (Absolute), code 41 (?), value 132
Event: time 1321196774.006584, ————– Report Sync ————
Event: time 1321196774.230579, type 4 (Misc), code 4 (ScanCode), value 7005c
Event: time 1321196774.230619, type 1 (Key), code 75 (KP4), value 0
Event: time 1321196774.230628, ————– Report Sync ————
#5
Event: time 1321196774.662660, type 4 (Misc), code 4 (ScanCode), value 7005d
Event: time 1321196774.662709, type 1 (Key), code 76 (KP5), value 1
Event: time 1321196774.662722, ————– Report Sync ————
Event: time 1321196774.670633, type 3 (Absolute), code 41 (?), value 5
Event: time 1321196774.670680, ————– Report Sync ————
Event: time 1321196774.894694, type 4 (Misc), code 4 (ScanCode), value 7005d
Event: time 1321196774.894735, type 1 (Key), code 76 (KP5), value 0
Event: time 1321196774.894743, ————– Report Sync ————
#6
Event: time 1321196775.246790, type 4 (Misc), code 4 (ScanCode), value 7005e
Event: time 1321196775.246833, type 1 (Key), code 77 (KP6), value 1
Event: time 1321196775.246845, ————– Report Sync ————
Event: time 1321196775.254739, type 3 (Absolute), code 41 (?), value 134
Event: time 1321196775.254787, ————– Report Sync ————
Event: time 1321196775.478796, type 4 (Misc), code 4 (ScanCode), value 7005e
Event: time 1321196775.478839, type 1 (Key), code 77 (KP6), value 0
Event: time 1321196775.478848, ————– Report Sync ————

#7
Event: time 1321196778.159266, type 4 (Misc), code 4 (ScanCode), value 7005f
Event: time 1321196778.159311, type 1 (Key), code 71 (KP7), value 1
Event: time 1321196778.159322, ————– Report Sync ————
Event: time 1321196778.167253, type 3 (Absolute), code 41 (?), value 7
Event: time 1321196778.167302, ————– Report Sync ————
Event: time 1321196778.383302, type 4 (Misc), code 4 (ScanCode), value 7005f
Event: time 1321196778.383350, type 1 (Key), code 71 (KP7), value 0
Event: time 1321196778.383360, ————– Report Sync ————
#8
Event: time 1321196778.823377, type 4 (Misc), code 4 (ScanCode), value 70060
Event: time 1321196778.823420, type 1 (Key), code 72 (KP8), value 1
Event: time 1321196778.823443, ————– Report Sync ————
Event: time 1321196778.831358, type 3 (Absolute), code 41 (?), value 136
Event: time 1321196778.831406, ————– Report Sync ————
Event: time 1321196779.055420, type 4 (Misc), code 4 (ScanCode), value 70060
Event: time 1321196779.055465, type 1 (Key), code 72 (KP8), value 0
Event: time 1321196779.055474, ————– Report Sync ————
#9
Event: time 1321196779.439487, type 4 (Misc), code 4 (ScanCode), value 70061
Event: time 1321196779.439533, type 1 (Key), code 73 (KP9), value 1
Event: time 1321196779.439545, ————– Report Sync ————
Event: time 1321196779.447466, type 3 (Absolute), code 41 (?), value 9
Event: time 1321196779.447515, ————– Report Sync ————
Event: time 1321196779.663520, type 4 (Misc), code 4 (ScanCode), value 70061
Event: time 1321196779.663567, type 1 (Key), code 73 (KP9), value 0
Event: time 1321196779.663580, ————– Report Sync ————

#BACK
Event: time 1321196782.023906, type 4 (Misc), code 4 (ScanCode), value c00fa
Event: time 1321196782.023956, type 1 (Key), code 158 (Back), value 1
Event: time 1321196782.023967, ————– Report Sync ————
Event: time 1321196782.031903, type 3 (Absolute), code 41 (?), value 163
Event: time 1321196782.031942, ————– Report Sync ————
Event: time 1321196782.255933, type 4 (Misc), code 4 (ScanCode), value c00fa
Event: time 1321196782.255975, type 1 (Key), code 158 (Back), value 0
Event: time 1321196782.255989, ————– Report Sync ————
#0
Event: time 1321196782.720043, type 4 (Misc), code 4 (ScanCode), value 70062
Event: time 1321196782.720088, type 1 (Key), code 82 (KP0), value 1
Event: time 1321196782.720100, ————– Report Sync ————
Event: time 1321196782.728024, type 3 (Absolute), code 41 (?), value 63
Event: time 1321196782.728070, ————– Report Sync ————
Event: time 1321196782.952093, type 4 (Misc), code 4 (ScanCode), value 70062
Event: time 1321196782.952137, type 1 (Key), code 82 (KP0), value 0
Event: time 1321196782.952146, ————– Report Sync ————
#More
Event: time 1321196783.288115, type 4 (Misc), code 4 (ScanCode), value c00f6
Event: time 1321196783.288153, type 1 (Key), code 407 (Next), value 1
Event: time 1321196783.288168, ————– Report Sync ————
Event: time 1321196783.296143, type 3 (Absolute), code 41 (?), value 143
Event: time 1321196783.296199, ————– Report Sync ————
Event: time 1321196783.512151, type 4 (Misc), code 4 (ScanCode), value c00f6
Event: time 1321196783.512192, type 1 (Key), code 407 (Next), value 0
Event: time 1321196783.512210, ————– Report Sync ————

#Up
Event: time 1321196788.353029, type 4 (Misc), code 4 (ScanCode), value 70052
Event: time 1321196788.353081, type 1 (Key), code 103 (Up), value 1
Event: time 1321196788.353095, ————– Report Sync ————
Event: time 1321196788.361005, type 3 (Absolute), code 41 (?), value 30
Event: time 1321196788.361044, ————– Report Sync ————
Event: time 1321196788.585072, type 4 (Misc), code 4 (ScanCode), value 70052
Event: time 1321196788.585126, type 1 (Key), code 103 (Up), value 0
Event: time 1321196788.585136, ————– Report Sync ————
#Left
Event: time 1321196789.129158, type 4 (Misc), code 4 (ScanCode), value 70050
Event: time 1321196789.129209, type 1 (Key), code 105 (Left), value 1
Event: time 1321196789.129224, ————– Report Sync ————
Event: time 1321196789.137138, type 3 (Absolute), code 41 (?), value 160
Event: time 1321196789.137182, ————– Report Sync ————
Event: time 1321196789.353193, type 4 (Misc), code 4 (ScanCode), value 70050
Event: time 1321196789.353245, type 1 (Key), code 105 (Left), value 0
Event: time 1321196789.353256, ————– Report Sync ————
#Right
Event: time 1321196789.801283, type 4 (Misc), code 4 (ScanCode), value 7004f
Event: time 1321196789.801331, type 1 (Key), code 106 (Right), value 1
Event: time 1321196789.801343, ————– Report Sync ————
Event: time 1321196789.809260, type 3 (Absolute), code 41 (?), value 33
Event: time 1321196789.809316, ————– Report Sync ————
Event: time 1321196790.033310, type 4 (Misc), code 4 (ScanCode), value 7004f
Event: time 1321196790.033361, type 1 (Key), code 106 (Right), value 0
Event: time 1321196790.033373, ————– Report Sync ————
#Down
Event: time 1321196790.449401, type 4 (Misc), code 4 (ScanCode), value 70051
Event: time 1321196790.449458, type 1 (Key), code 108 (Down), value 1
Event: time 1321196790.449471, ————– Report Sync ————
Event: time 1321196790.457368, type 3 (Absolute), code 41 (?), value 159
Event: time 1321196790.457415, ————– Report Sync ————
Event: time 1321196790.673428, type 4 (Misc), code 4 (ScanCode), value 70051
Event: time 1321196790.673480, type 1 (Key), code 108 (Down), value 0
Event: time 1321196790.673493, ————– Report Sync ————
#OK
Event: time 1321196791.185530, type 4 (Misc), code 4 (ScanCode), value 70028
Event: time 1321196791.185590, type 1 (Key), code 28 (Enter), value 1
Event: time 1321196791.185598, ————– Report Sync ————
Event: time 1321196791.193485, type 3 (Absolute), code 41 (?), value 34
Event: time 1321196791.193529, ————– Report Sync ————
Event: time 1321196791.417539, type 4 (Misc), code 4 (ScanCode), value 70028
Event: time 1321196791.417579, type 1 (Key), code 28 (Enter), value 0
Event: time 1321196791.417585, ————– Report Sync ————

#VOL-
Event: time 1321196794.113987, type 4 (Misc), code 4 (ScanCode), value c00ea
Event: time 1321196794.114024, type 1 (Key), code 114 (VolumeDown), value 1
Event: time 1321196794.114035, ————– Report Sync ————
Event: time 1321196794.121986, type 3 (Absolute), code 41 (?), value 145
Event: time 1321196794.122028, ————– Report Sync ————
Event: time 1321196794.346021, type 4 (Misc), code 4 (ScanCode), value c00ea
Event: time 1321196794.346055, type 1 (Key), code 114 (VolumeDown), value 0
Event: time 1321196794.346064, ————– Report Sync ————
#VOL+
Event: time 1321196795.138164, type 4 (Misc), code 4 (ScanCode), value c00e9
Event: time 1321196795.138203, type 1 (Key), code 115 (VolumeUp), value 1
Event: time 1321196795.138210, ————– Report Sync ————
Event: time 1321196795.146169, type 3 (Absolute), code 41 (?), value 16
Event: time 1321196795.146215, ————– Report Sync ————
Event: time 1321196795.370196, type 4 (Misc), code 4 (ScanCode), value c00e9
Event: time 1321196795.370235, type 1 (Key), code 115 (VolumeUp), value 0
Event: time 1321196795.370248, ————– Report Sync ————
#CH-
Event: time 1321196796.138358, type 4 (Misc), code 4 (ScanCode), value 7004e
Event: time 1321196796.138403, type 1 (Key), code 109 (PageDown), value 1
Event: time 1321196796.138410, ————– Report Sync ————
Event: time 1321196796.146352, type 3 (Absolute), code 41 (?), value 147
Event: time 1321196796.146405, ————– Report Sync ————
Event: time 1321196796.362399, type 4 (Misc), code 4 (ScanCode), value 7004e
Event: time 1321196796.362443, type 1 (Key), code 109 (PageDown), value 0
Event: time 1321196796.362449, ————– Report Sync ————
#CH+
Event: time 1321196796.754484, type 4 (Misc), code 4 (ScanCode), value 7004b
Event: time 1321196796.754523, type 1 (Key), code 104 (PageUp), value 1
Event: time 1321196796.754530, ————– Report Sync ————
Event: time 1321196796.762444, type 3 (Absolute), code 41 (?), value 18
Event: time 1321196796.762478, ————– Report Sync ————
Event: time 1321196796.978508, type 4 (Misc), code 4 (ScanCode), value 7004b
Event: time 1321196796.978539, type 1 (Key), code 104 (PageUp), value 0
Event: time 1321196796.978545, ————– Report Sync ————

#Red/Record
Event: time 1321196799.650938, type 4 (Misc), code 4 (ScanCode), value c00b2
Event: time 1321196799.650980, type 1 (Key), code 167 (Record), value 1
Event: time 1321196799.650989, ————– Report Sync ————
Event: time 1321196799.658937, type 3 (Absolute), code 41 (?), value 151
Event: time 1321196799.658982, ————– Report Sync ————
Event: time 1321196799.882975, type 4 (Misc), code 4 (ScanCode), value c00b2
Event: time 1321196799.883018, type 1 (Key), code 167 (Record), value 0
Event: time 1321196799.883033, ————– Report Sync ————
#Green/MCE
Event: time 1321196800.291033, type 3 (Absolute), code 41 (?), value 13
Event: time 1321196800.291083, ————– Report Sync ————
#Yellow/Stop
Event: time 1321196800.891157, type 4 (Misc), code 4 (ScanCode), value c00b7
Event: time 1321196800.891205, type 1 (Key), code 166 (StopCD), value 1
Event: time 1321196800.891215, ————– Report Sync ————
Event: time 1321196800.899155, type 3 (Absolute), code 41 (?), value 153
Event: time 1321196800.899201, ————– Report Sync ————
Event: time 1321196801.115184, type 4 (Misc), code 4 (ScanCode), value c00b7
Event: time 1321196801.115227, type 1 (Key), code 166 (StopCD), value 0
Event: time 1321196801.115236, ————– Report Sync ————
#Blue/Menu
Event: time 1321196801.475259, type 4 (Misc), code 4 (ScanCode), value 700e2
Event: time 1321196801.475297, type 1 (Key), code 56 (LeftAlt), value 1
Event: time 1321196801.475306, type 4 (Misc), code 4 (ScanCode), value 700e3
Event: time 1321196801.475313, type 1 (Key), code 125 (LeftMeta), value 1
Event: time 1321196801.475335, type 4 (Misc), code 4 (ScanCode), value 70028
Event: time 1321196801.475339, type 1 (Key), code 28 (Enter), value 1
Event: time 1321196801.475344, ————– Report Sync ————
Event: time 1321196801.483255, type 3 (Absolute), code 41 (?), value 11
Event: time 1321196801.483304, ————– Report Sync ————
Event: time 1321196801.707297, type 4 (Misc), code 4 (ScanCode), value 700e2
Event: time 1321196801.707328, type 1 (Key), code 56 (LeftAlt), value 0
Event: time 1321196801.707336, type 4 (Misc), code 4 (ScanCode), value 700e3
Event: time 1321196801.707342, type 1 (Key), code 125 (LeftMeta), value 0
Event: time 1321196801.707363, type 4 (Misc), code 4 (ScanCode), value 70028
Event: time 1321196801.707368, type 1 (Key), code 28 (Enter), value 0
Event: time 1321196801.707372, ————– Report Sync ————

#Rewind
Event: time 1321196804.451767, type 4 (Misc), code 4 (ScanCode), value c00b4
Event: time 1321196804.451804, type 1 (Key), code 168 (Rewind), value 1
Event: time 1321196804.451811, ————– Report Sync ————
Event: time 1321196804.459771, type 3 (Absolute), code 41 (?), value 149
Event: time 1321196804.459821, ————– Report Sync ————
Event: time 1321196804.683800, type 4 (Misc), code 4 (ScanCode), value c00b4
Event: time 1321196804.683827, type 1 (Key), code 168 (Rewind), value 0
Event: time 1321196804.683835, ————– Report Sync ————
#Pause
Event: time 1321196805.067873, type 4 (Misc), code 4 (ScanCode), value c00b1
Event: time 1321196805.067901, type 1 (Key), code 119 (Pause), value 1
Event: time 1321196805.067906, ————– Report Sync ————
Event: time 1321196805.075881, type 3 (Absolute), code 41 (?), value 24
Event: time 1321196805.075923, ————– Report Sync ————
Event: time 1321196805.299908, type 4 (Misc), code 4 (ScanCode), value c00b1
Event: time 1321196805.299936, type 1 (Key), code 119 (Pause), value 0
Event: time 1321196805.299945, ————– Report Sync ————
#Fast Forward
Event: time 1321196805.683975, type 4 (Misc), code 4 (ScanCode), value c00b3
Event: time 1321196805.684008, type 1 (Key), code 208 (Fast Forward), value 1
Event: time 1321196805.684016, ————– Report Sync ————
Event: time 1321196805.691980, type 3 (Absolute), code 41 (?), value 148
Event: time 1321196805.692018, ————– Report Sync ————
Event: time 1321196805.908018, type 4 (Misc), code 4 (ScanCode), value c00b3
Event: time 1321196805.908053, type 1 (Key), code 208 (Fast Forward), value 0
Event: time 1321196805.908066, ————– Report Sync ————
#Esc
Event: time 1321196806.252104, type 4 (Misc), code 4 (ScanCode), value 70029
Event: time 1321196806.252144, type 1 (Key), code 1 (Esc), value 1
Event: time 1321196806.252151, ————– Report Sync ————
Event: time 1321196806.260098, type 3 (Absolute), code 41 (?), value 10
Event: time 1321196806.260150, ————– Report Sync ————
Event: time 1321196806.484179, type 4 (Misc), code 4 (ScanCode), value 70029
Event: time 1321196806.484237, type 1 (Key), code 1 (Esc), value 0
Event: time 1321196806.484248, ————– Report Sync ————

#Previous
Event: time 1321196808.732554, type 4 (Misc), code 4 (ScanCode), value c00b6
Event: time 1321196808.732612, type 1 (Key), code 165 (PreviousSong), value 1
Event: time 1321196808.732621, ————– Report Sync ————
Event: time 1321196808.740534, type 3 (Absolute), code 41 (?), value 155
Event: time 1321196808.740601, ————– Report Sync ————
Event: time 1321196808.956584, type 4 (Misc), code 4 (ScanCode), value c00b6
Event: time 1321196808.956660, type 1 (Key), code 165 (PreviousSong), value 0
Event: time 1321196808.956675, ————– Report Sync ————
#Play
Event: time 1321196809.284612, type 4 (Misc), code 4 (ScanCode), value c00cd
Event: time 1321196809.284670, type 1 (Key), code 164 (PlayPause), value 1
Event: time 1321196809.284680, ————– Report Sync ————
Event: time 1321196809.292619, type 3 (Absolute), code 41 (?), value 22
Event: time 1321196809.292671, ————– Report Sync ————
Event: time 1321196809.516650, type 4 (Misc), code 4 (ScanCode), value c00cd
Event: time 1321196809.516700, type 1 (Key), code 164 (PlayPause), value 0
Event: time 1321196809.516713, ————– Report Sync ————
#Next
Event: time 1321196809.860713, type 4 (Misc), code 4 (ScanCode), value c00b5
Event: time 1321196809.860757, type 1 (Key), code 163 (NextSong), value 1
Event: time 1321196809.860764, ————– Report Sync ————
Event: time 1321196809.868722, type 3 (Absolute), code 41 (?), value 154
Event: time 1321196809.868780, ————– Report Sync ————
Event: time 1321196809.980714, type 4 (Misc), code 4 (ScanCode), value c00b5
Event: time 1321196809.980755, type 1 (Key), code 163 (NextSong), value 0
Event: time 1321196809.980771, ————– Report Sync ————
#Mute
Event: time 1321196810.404815, type 4 (Misc), code 4 (ScanCode), value c00e2
Event: time 1321196810.404863, type 1 (Key), code 113 (Mute), value 1
Event: time 1321196810.404871, ————– Report Sync ————
Event: time 1321196810.412809, type 3 (Absolute), code 41 (?), value 14
Event: time 1321196810.412859, ————– Report Sync ————
Event: time 1321196810.636850, type 4 (Misc), code 4 (ScanCode), value c00e2
Event: time 1321196810.636900, type 1 (Key), code 113 (Mute), value 0
Event: time 1321196810.636916, ————– Report Sync ————

### Klawisze z Shiftem czyli zielonym przyciskiem

# *
Event: time 1321196818.118158, type 4 (Misc), code 4 (ScanCode), value 70055
Event: time 1321196818.118207, type 1 (Key), code 55 (KPAsterisk), value 1
Event: time 1321196818.118218, ————– Report Sync ————
Event: time 1321196818.134149, type 3 (Absolute), code 41 (?), value 221
Event: time 1321196818.134213, ————– Report Sync ————
Event: time 1321196818.368066, type 1 (Key), code 55 (KPAsterisk), value 2
Event: time 1321196818.368098, ————– Report Sync ————
Event: time 1321196818.404050, type 1 (Key), code 55 (KPAsterisk), value 2
Event: time 1321196818.404078, ————– Report Sync ————
Event: time 1321196818.440042, type 1 (Key), code 55 (KPAsterisk), value 2
Event: time 1321196818.440075, ————– Report Sync ————
Event: time 1321196818.476047, type 1 (Key), code 55 (KPAsterisk), value 2
Event: time 1321196818.476092, ————– Report Sync ————
Event: time 1321196818.494222, type 4 (Misc), code 4 (ScanCode), value 70055
Event: time 1321196818.494271, type 1 (Key), code 55 (KPAsterisk), value 0
Event: time 1321196818.494279, ————– Report Sync ————
#Clear
Event: time 1321196818.942320, type 4 (Misc), code 4 (ScanCode), value 7002a
Event: time 1321196818.942382, type 1 (Key), code 14 (Backspace), value 1
Event: time 1321196818.942394, ————– Report Sync ————
Event: time 1321196818.950278, type 3 (Absolute), code 41 (?), value 74
Event: time 1321196818.950333, ————– Report Sync ————
Event: time 1321196819.196076, type 1 (Key), code 14 (Backspace), value 2
Event: time 1321196819.196117, ————– Report Sync ————
Event: time 1321196819.236070, type 1 (Key), code 14 (Backspace), value 2
Event: time 1321196819.236111, ————– Report Sync ————
Event: time 1321196819.254374, type 4 (Misc), code 4 (ScanCode), value 7002a
Event: time 1321196819.254428, type 1 (Key), code 14 (Backspace), value 0
Event: time 1321196819.254439, ————– Report Sync ————
# # (hash)
Event: time 1321196819.606393, type 4 (Misc), code 4 (ScanCode), value 700e1
Event: time 1321196819.606438, type 1 (Key), code 42 (LeftShift), value 1
Event: time 1321196819.606477, type 4 (Misc), code 4 (ScanCode), value 70020
Event: time 1321196819.606482, type 1 (Key), code 4 (3), value 1
Event: time 1321196819.606487, ————– Report Sync ————
Event: time 1321196819.622394, type 3 (Absolute), code 41 (?), value 220
Event: time 1321196819.622445, ————– Report Sync ————
Event: time 1321196819.860041, type 1 (Key), code 4 (3), value 2
Event: time 1321196819.860070, ————– Report Sync ————
Event: time 1321196819.896060, type 1 (Key), code 4 (3), value 2
Event: time 1321196819.896090, ————– Report Sync ————
Event: time 1321196819.918447, type 4 (Misc), code 4 (ScanCode), value 700e1
Event: time 1321196819.918494, type 1 (Key), code 42 (LeftShift), value 0
Event: time 1321196819.918536, type 4 (Misc), code 4 (ScanCode), value 70020
Event: time 1321196819.918543, type 1 (Key), code 4 (3), value 0
Event: time 1321196819.918560, ————– Report Sync ————

#Help
Event: time 1321196832.200599, type 4 (Misc), code 4 (ScanCode), value 7003a
Event: time 1321196832.200654, type 1 (Key), code 59 (F1), value 1
Event: time 1321196832.200667, ————– Report Sync ————
Event: time 1321196832.216598, type 3 (Absolute), code 41 (?), value 100
Event: time 1321196832.216662, ————– Report Sync ————
Event: time 1321196832.452033, type 1 (Key), code 59 (F1), value 2
Event: time 1321196832.452061, ————– Report Sync ————
Event: time 1321196832.488064, type 1 (Key), code 59 (F1), value 2
Event: time 1321196832.488095, ————– Report Sync ————
Event: time 1321196832.488629, type 4 (Misc), code 4 (ScanCode), value 7003a
Event: time 1321196832.488662, type 1 (Key), code 59 (F1), value 0
Event: time 1321196832.488671, ————– Report Sync ————
#DVD Menu
Event: time 1321196832.880695, type 3 (Absolute), code 41 (?), value 164
Event: time 1321196832.880748, ————– Report Sync ————
#Resize
Event: time 1321196833.416786, type 4 (Misc), code 4 (ScanCode), value 700e2
Event: time 1321196833.416847, type 1 (Key), code 56 (LeftAlt), value 1
Event: time 1321196833.416891, type 4 (Misc), code 4 (ScanCode), value 70028
Event: time 1321196833.416898, type 1 (Key), code 28 (Enter), value 1
Event: time 1321196833.416904, ————– Report Sync ————
Event: time 1321196833.424780, type 3 (Absolute), code 41 (?), value 99
Event: time 1321196833.424831, ————– Report Sync ————
Event: time 1321196833.672069, type 1 (Key), code 28 (Enter), value 2
Event: time 1321196833.672103, ————– Report Sync ————
Event: time 1321196833.688805, type 4 (Misc), code 4 (ScanCode), value 700e2
Event: time 1321196833.688850, type 1 (Key), code 56 (LeftAlt), value 0
Event: time 1321196833.688886, type 4 (Misc), code 4 (ScanCode), value 70028
Event: time 1321196833.688901, type 1 (Key), code 28 (Enter), value 0
Event: time 1321196833.688909, ————– Report Sync ————
#Enter
Event: time 1321196833.944887, type 4 (Misc), code 4 (ScanCode), value 70028
Event: time 1321196833.944943, type 1 (Key), code 28 (Enter), value 1
Event: time 1321196833.944955, ————– Report Sync ————
Event: time 1321196833.952873, type 3 (Absolute), code 41 (?), value 234
Event: time 1321196833.952943, ————– Report Sync ————
Event: time 1321196834.196054, type 1 (Key), code 28 (Enter), value 2
Event: time 1321196834.196090, ————– Report Sync ————
Event: time 1321196834.232088, type 1 (Key), code 28 (Enter), value 2
Event: time 1321196834.232125, ————– Report Sync ————
Event: time 1321196834.240961, type 4 (Misc), code 4 (ScanCode), value 70028
Event: time 1321196834.241017, type 1 (Key), code 28 (Enter), value 0
Event: time 1321196834.241025, ————– Report Sync ————
^C

Typy przycisków

Jak widać przyciski można podzielić na dwie grupy.

Pierwsza grupa, to takie przyciski, które generują normalne kody naciśnięcia klawisza:

Event: time 1321196766.117179, type 4 (Misc), code 4 (ScanCode), value 70059
Event: time 1321196766.117218, type 1 (Key), code 79 (KP1), value 1
Event: time 1321196766.117227, ————– Report Sync ————
Event: time 1321196766.125143, type 3 (Absolute), code 41 (?), value 1
Event: time 1321196766.125177, ————– Report Sync ————
Event: time 1321196766.349223, type 4 (Misc), code 4 (ScanCode), value 70059
Event: time 1321196766.349256, type 1 (Key), code 79 (KP1), value 0

Jest sekwencja:

type 1 (Key), code .. (…), value 1 # naciśnięcie klawisza

type 1 (Key), code .. (…), value 0 # puszczenie klawisza

Te przyciski działają od razu – tak jak każda inna klawiatura. Niestety, niektóre z przycisków (zwłaszcza te multimedialne) generują kody klawiszy większe od 255, co jest i długo jeszcze będzie problemem pod X11 – patrz: http://www.mythtv.org/wiki/Remapping_remote_control_key_codes_greater_than_255 oraz http://www.thenautilus.net/SW/xf86-input-evdev/en

Druga grupa przycisków nie generuje zdarzeń naciśnięcia i puszczenia klawisza – tylko zdarzenia absolute z kodem 41 i różnymi wartościami np:

type 3 (Absolute), code 41 (?), value 168

Z tego co rozumiem to jakaś emulacja joysticka(?).

Aby poradzić sobie z obydwoma problemami w prymitywny sposób zmieniłem kod xserver-xorg-input-evdev, a konkretnie plik evdev.c

Modyfikacja drivera evdev

1. Należy pobrać źródła xserver-xorg-input-evdev np. ze strony https://launchpad.net/ubuntu/lucid/+source/xserver-xorg-input-evdev/1:2.3.2-5ubuntu1 i zmodyfikować plik evdev.c – dla wersji 2.3.2 można pobrać zmodyfikowany driver:

$ git clone git://github.com/dgolda/maxter-plus-linux.git

$ cd maxter-plus-linux

$ cd xserver-xorg-input-evdev-2.3.2

3. skompilować

$ ./configure
$ make

4. wyłączyć X11 np. sudo service gdm stop lub kill

5. zainstalować:

$ sudo make install

Driver powinien się skopiować do: /usr/local/lib/xorg/modules/input/evdev_drv.so

Następnie należy ustawić X by używamy zmodyfikowanego drivera – w pliku xorg.conf należy dodać ModulePath:

 Section „Files”

ModulePath „/usr/local/lib/xorg/modules,/usr/lib/xorg/extra-modules,/usr/lib/xorg/modules”

EndSection

Teraz należy zrestartować X lub cały komputer i sprawdzić czy zmieniony driver est używany:

grep evdev_drv /var/log/Xorg.0.log

Powinno się pojawić coś takiego:

(II) Loading /usr/local/lib/xorg/modules/input/evdev_drv.so

Co oznacza, że evdev driver jest ładowany z /usr/local/lib, a nie z /usr/lib.

Written by Admin

13 Listopad 2011 @ 17:47

Napisane w Uncategorized

Odpowiedzi: 5

Subscribe to comments with RSS.

  1. Witaj,
    Bardzo dziękuję za rozwiązanie problemu niektórych klawiszy pilota MAXTER.
    Mam pytanie, do którego przycisku w pilocie przypisany jest klawisz TAB? A jeśli nie to czy może być przypisany do np. Shift+FullScreen lub do GUIDE. Teraz GUIDE jak i LIVE TV prowadzą w to samo miejsce, tzn. do Listy kanałów PVR.
    A tak na marginesie, to może byś krótko napisał jak przyporządkować przyciski i klawisze do naszego pilota w pliku keyboard.xml.
    Z góry dziękuję za odpowiedź.
    MM

    Marcin

    23 Listopad 2011 at 23:26

  2. Mam problem z przerobieniem evdev.c dla wersji 2.6.0. Jest tam troszkę inny kod czy mogę prosić o pomoc?

    maniek

    29 Maj 2012 at 12:58

    • Nie mam pod ręką tej wersji. Jaki to kod, w czym problem?

      Admin

      29 Maj 2012 at 13:00

      • /* * Copyright © 2004-2008 Red Hat, Inc. * * Permission to use, copy, modify, distribute, and sell this software * and its documentation for any purpose is hereby granted without * fee, provided that the above copyright notice appear in all copies * and that both that copyright notice and this permission notice * appear in supporting documentation, and that the name of Red Hat * not be used in advertising or publicity pertaining to distribution * of the software without specific, written prior permission. Red * Hat makes no representations about the suitability of this software * for any purpose. It is provided „as is” without express or implied * warranty. * * THE AUTHORS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN * NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * * Authors: * Kristian Høgsberg (krh@redhat.com) * Adam Jackson (ajax@redhat.com) * Peter Hutterer (peter.hutterer@redhat.com) * Oliver McFadden (oliver.mcfadden@nokia.com) */ #ifdef HAVE_CONFIG_H #include „config.h” #endif #include „evdev.h” #include #include #include #include #include #include #include #include #include #include #include #include #ifdef HAVE_PROPERTIES #include #include #include /* 1.6 has properties, but no labels */ #ifdef AXIS_LABEL_PROP #define HAVE_LABELS #else #undef HAVE_LABELS #endif #endif #if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 12 /* removed from server, purge when dropping support for server 1.10 */ #define XI86_SEND_DRAG_EVENTS 0x08 #endif #ifndef MAXDEVICES #include /* for MAX_DEVICES */ #define MAXDEVICES MAX_DEVICES #endif #define ArrayLength(a) (sizeof(a) / (sizeof((a)[0]))) #define MIN_KEYCODE 8 #define GLYPHS_PER_KEY 2 #define AltMask Mod1Mask #define NumLockMask Mod2Mask #define AltLangMask Mod3Mask #define KanaMask Mod4Mask #define ScrollLockMask Mod5Mask #define CAPSFLAG 1 #define NUMFLAG 2 #define SCROLLFLAG 4 #define MODEFLAG 8 #define COMPOSEFLAG 16 static char *evdevDefaults[] = { „XkbRules”, „evdev”, „XkbModel”, „evdev”, „XkbLayout”, „us”, NULL }; /* Any of those triggers a proximity event */ static int proximity_bits[] = { BTN_TOOL_PEN, BTN_TOOL_RUBBER, BTN_TOOL_BRUSH, BTN_TOOL_PENCIL, BTN_TOOL_AIRBRUSH, BTN_TOOL_FINGER, BTN_TOOL_MOUSE, BTN_TOOL_LENS, }; static int EvdevOn(DeviceIntPtr); static int EvdevCache(InputInfoPtr pInfo); static void EvdevKbdCtrl(DeviceIntPtr device, KeybdCtrl *ctrl); static int EvdevSwitchMode(ClientPtr client, DeviceIntPtr device, int mode); static BOOL EvdevGrabDevice(InputInfoPtr pInfo, int grab, int ungrab); static void EvdevSetCalibration(InputInfoPtr pInfo, int num_calibration, int calibration[4]); static int EvdevOpenDevice(InputInfoPtr pInfo); #ifdef HAVE_PROPERTIES static void EvdevInitAxesLabels(EvdevPtr pEvdev, int natoms, Atom *atoms); static void EvdevInitButtonLabels(EvdevPtr pEvdev, int natoms, Atom *atoms); static void EvdevInitProperty(DeviceIntPtr dev); static int EvdevSetProperty(DeviceIntPtr dev, Atom atom, XIPropertyValuePtr val, BOOL checkonly); static Atom prop_invert = 0; static Atom prop_calibration = 0; static Atom prop_swap = 0; static Atom prop_axis_label = 0; static Atom prop_btn_label = 0; #endif /* All devices the evdev driver has allocated and knows about. * MAXDEVICES is safe as null-terminated array, as two devices (VCP and VCK) * cannot be used by evdev, leaving us with a space of 2 at the end. */ static EvdevPtr evdev_devices[MAXDEVICES] = {NULL}; static int EvdevSwitchMode(ClientPtr client, DeviceIntPtr device, int mode) { InputInfoPtr pInfo; EvdevPtr pEvdev; pInfo = device->public.devicePrivate; pEvdev = pInfo->private; if (pEvdev->flags & EVDEV_RELATIVE_EVENTS) { if (mode == Relative) return Success; else return XI_BadMode; } switch (mode) { case Absolute: pEvdev->flags &= ~EVDEV_RELATIVE_MODE; break; case Relative: pEvdev->flags |= EVDEV_RELATIVE_MODE; break; default: return XI_BadMode; } return Success; } static size_t EvdevCountBits(unsigned long *array, size_t nlongs) { unsigned int i; size_t count = 0; for (i = 0; i 0) { count += (x & 0x1); x >>= 1; } } return count; } static int EvdevGetMajorMinor(InputInfoPtr pInfo) { struct stat st; if (fstat(pInfo->fd, &st) == -1) { xf86Msg(X_ERROR, „%s: stat failed (%s). cannot check for duplicates.n”, pInfo->name, strerror(errno)); return 0; } return st.st_rdev; } /** * Return TRUE if one of the devices we know about has the same min/maj * number. */ static BOOL EvdevIsDuplicate(InputInfoPtr pInfo) { EvdevPtr pEvdev = pInfo->private; EvdevPtr* dev = evdev_devices; if (pEvdev->min_maj) { while(*dev) { if ((*dev) != pEvdev && (*dev)->min_maj && (*dev)->min_maj == pEvdev->min_maj) return TRUE; dev++; } } return FALSE; } /** * Add to internal device list. */ static void EvdevAddDevice(InputInfoPtr pInfo) { EvdevPtr pEvdev = pInfo->private; EvdevPtr* dev = evdev_devices; while(*dev) dev++; *dev = pEvdev; } /** * Remove from internal device list. */ static void EvdevRemoveDevice(InputInfoPtr pInfo) { EvdevPtr pEvdev = pInfo->private; EvdevPtr *dev = evdev_devices; int count = 0; while(*dev) { count++; if (*dev == pEvdev) { memmove(dev, dev + 1, sizeof(evdev_devices) – (count * sizeof(EvdevPtr))); break; } dev++; } } static void SetXkbOption(InputInfoPtr pInfo, char *name, char **option) { char *s; if ((s = xf86SetStrOption(pInfo->options, name, NULL))) { if (!s[0]) { free(s); *option = NULL; } else { *option = s; } } } static int wheel_up_button = 4; static int wheel_down_button = 5; static int wheel_left_button = 6; static int wheel_right_button = 7; static EventQueuePtr EvdevNextInQueue(InputInfoPtr pInfo) { EvdevPtr pEvdev = pInfo->private; if (pEvdev->num_queue >= EVDEV_MAXQUEUE) { xf86Msg(X_NONE, „%s: dropping event due to full queue!n”, pInfo->name); return NULL; } pEvdev->num_queue++; return &pEvdev->queue[pEvdev->num_queue – 1]; } void EvdevQueueKbdEvent(InputInfoPtr pInfo, struct input_event *ev, int value) { int code = ev->code + MIN_KEYCODE; EventQueuePtr pQueue; /* Filter all repeated events from device. We’ll do softrepeat in the server, but only since 1.6 */ if (value == 2 #if GET_ABI_MAJOR(ABI_XINPUT_VERSION) code == KEY_LEFTCTRL || ev->code == KEY_RIGHTCTRL || ev->code == KEY_LEFTSHIFT || ev->code == KEY_RIGHTSHIFT || ev->code == KEY_LEFTALT || ev->code == KEY_RIGHTALT || ev->code == KEY_LEFTMETA || ev->code == KEY_RIGHTMETA || ev->code == KEY_CAPSLOCK || ev->code == KEY_NUMLOCK || ev->code == KEY_SCROLLLOCK) /* XXX windows keys? */ #endif ) return; if ((pQueue = EvdevNextInQueue(pInfo))) { pQueue->type = EV_QUEUE_KEY; pQueue->key = code; pQueue->val = value; } } void EvdevQueueButtonEvent(InputInfoPtr pInfo, int button, int value) { EventQueuePtr pQueue; if ((pQueue = EvdevNextInQueue(pInfo))) { pQueue->type = EV_QUEUE_BTN; pQueue->key = button; pQueue->val = value; } } void EvdevQueueProximityEvent(InputInfoPtr pInfo, int value) { EventQueuePtr pQueue; if ((pQueue = EvdevNextInQueue(pInfo))) { pQueue->type = EV_QUEUE_PROXIMITY; pQueue->key = 0; pQueue->val = value; } } /** * Post button event right here, right now. * Interface for MB emulation since these need to post immediately. */ void EvdevPostButtonEvent(InputInfoPtr pInfo, int button, int value) { xf86PostButtonEvent(pInfo->dev, 0, button, value, 0, 0); } void EvdevQueueButtonClicks(InputInfoPtr pInfo, int button, int count) { int i; for (i = 0; i private; *num_v = *first_v = 0; /* convert to relative motion for touchpads */ if (pEvdev->abs_queued && (pEvdev->flags & EVDEV_RELATIVE_MODE)) { if (pEvdev->in_proximity) { if (pEvdev->old_vals[0] != -1) pEvdev->delta[REL_X] = pEvdev->vals[0] – pEvdev->old_vals[0]; if (pEvdev->old_vals[1] != -1) pEvdev->delta[REL_Y] = pEvdev->vals[1] – pEvdev->old_vals[1]; if (pEvdev->abs_queued & ABS_X_VALUE) pEvdev->old_vals[0] = pEvdev->vals[0]; if (pEvdev->abs_queued & ABS_Y_VALUE) pEvdev->old_vals[1] = pEvdev->vals[1]; } else { pEvdev->old_vals[0] = pEvdev->old_vals[1] = -1; } pEvdev->abs_queued = 0; pEvdev->rel_queued = 1; } if (pEvdev->rel_queued) { int first = REL_CNT, last = -1; int i; if (pEvdev->swap_axes) { tmp = pEvdev->delta[REL_X]; pEvdev->delta[REL_X] = pEvdev->delta[REL_Y]; pEvdev->delta[REL_Y] = tmp; } if (pEvdev->invert_x) pEvdev->delta[REL_X] *= -1; if (pEvdev->invert_y) pEvdev->delta[REL_Y] *= -1; for (i = 0; i axis_map[i]; if (pEvdev->delta[i] && map != -1) { v[map] = pEvdev->delta[i]; if (map last) last = map; } } if (last >= 0) { *num_v = (last – first + 1); *first_v = first; } } /* * Some devices only generate valid abs coords when BTN_TOOL_PEN is * pressed. On wacom tablets, this means that the pen is in * proximity of the tablet. After the pen is removed, BTN_TOOL_PEN is * released, and a (0, 0) absolute event is generated. Checking * pEvdev->in_proximity here lets us ignore that event. pEvdev is * initialized to 1 so devices that don’t use this scheme still * just works. */ else if (pEvdev->abs_queued && pEvdev->in_proximity) { memcpy(v, pEvdev->vals, sizeof(int) * pEvdev->num_vals); if (pEvdev->swap_axes) { int tmp = v[0]; v[0] = xf86ScaleAxis(v[1], pEvdev->absinfo[ABS_X].maximum, pEvdev->absinfo[ABS_X].minimum, pEvdev->absinfo[ABS_Y].maximum, pEvdev->absinfo[ABS_Y].minimum); v[1] = xf86ScaleAxis(tmp, pEvdev->absinfo[ABS_Y].maximum, pEvdev->absinfo[ABS_Y].minimum, pEvdev->absinfo[ABS_X].maximum, pEvdev->absinfo[ABS_X].minimum); } if (pEvdev->flags & EVDEV_CALIBRATED) { v[0] = xf86ScaleAxis(v[0], pEvdev->absinfo[ABS_X].maximum, pEvdev->absinfo[ABS_X].minimum, pEvdev->calibration.max_x, pEvdev->calibration.min_x); v[1] = xf86ScaleAxis(v[1], pEvdev->absinfo[ABS_Y].maximum, pEvdev->absinfo[ABS_Y].minimum, pEvdev->calibration.max_y, pEvdev->calibration.min_y); } if (pEvdev->invert_x) v[0] = (pEvdev->absinfo[ABS_X].maximum – v[0] + pEvdev->absinfo[ABS_X].minimum); if (pEvdev->invert_y) v[1] = (pEvdev->absinfo[ABS_Y].maximum – v[1] + pEvdev->absinfo[ABS_Y].minimum); *num_v = pEvdev->num_vals; *first_v = 0; } } static void EvdevProcessProximityEvent(InputInfoPtr pInfo, struct input_event *ev) { EvdevPtr pEvdev = pInfo->private; if (!pEvdev->use_proximity) return; pEvdev->prox_queued = 1; EvdevQueueProximityEvent(pInfo, ev->value); } /** * Proximity handling is rather weird because of tablet-specific issues. * Some tablets, notably Wacoms, send a 0/0 coordinate in the same EV_SYN as * the out-of-proximity notify. We need to ignore those, hence we only * actually post valuator events when we’re in proximity. * * Other tablets send the x/y coordinates, then EV_SYN, then the proximity * event. For those, we need to remember x/y to post it when the proximity * comes. * * If we’re not in proximity and we get valuator events, remember that, they * won’t be posted though. If we move into proximity without valuators, use * the last ones we got and let the rest of the code post them. */ static int EvdevProcessProximityState(InputInfoPtr pInfo) { EvdevPtr pEvdev = pInfo->private; int prox_state = 0; int i; /* no proximity change in the queue */ if (!pEvdev->prox_queued) { if (pEvdev->abs_queued && !pEvdev->in_proximity) pEvdev->abs_prox = pEvdev->abs_queued; return 0; } for (i = 0; i num_queue; i++) { if (pEvdev->queue[i].type == EV_QUEUE_PROXIMITY) { prox_state = pEvdev->queue[i].val; break; } } if ((prox_state && !pEvdev->in_proximity) || (!prox_state && pEvdev->in_proximity)) { /* We’re about to go into/out of proximity but have no abs events * within the EV_SYN. Use the last coordinates we have. */ if (!pEvdev->abs_queued && pEvdev->abs_prox) { pEvdev->abs_queued = pEvdev->abs_prox; pEvdev->abs_prox = 0; } } pEvdev->in_proximity = prox_state; return 1; } /** * Take a button input event and process it accordingly. */ static void EvdevProcessButtonEvent(InputInfoPtr pInfo, struct input_event *ev) { unsigned int button; int value; EvdevPtr pEvdev = pInfo->private; button = EvdevUtilButtonEventToButtonNumber(pEvdev, ev->code); /* Get the signed value, earlier kernels had this as unsigned */ value = ev->value; /* Handle drag lock */ if (EvdevDragLockFilterEvent(pInfo, button, value)) return; if (EvdevWheelEmuFilterButton(pInfo, button, value)) return; if (EvdevMBEmuFilterEvent(pInfo, button, value)) return; if (button) EvdevQueueButtonEvent(pInfo, button, value); else EvdevQueueKbdEvent(pInfo, ev, value); } /** * Take the relative motion input event and process it accordingly. */ static void EvdevProcessRelativeMotionEvent(InputInfoPtr pInfo, struct input_event *ev) { int value; EvdevPtr pEvdev = pInfo->private; /* Get the signed value, earlier kernels had this as unsigned */ value = ev->value; switch (ev->code) { case REL_WHEEL: if (value > 0) EvdevQueueButtonClicks(pInfo, wheel_up_button, value); else if (value 0) EvdevQueueButtonClicks(pInfo, wheel_right_button, value); else if (value flags & EVDEV_RELATIVE_EVENTS)) return; /* Handle mouse wheel emulation */ if (EvdevWheelEmuFilterMotion(pInfo, ev)) return; pEvdev->rel_queued = 1; pEvdev->delta[ev->code] += value; break; } } /** * Take the absolute motion input event and process it accordingly. */ static void EvdevProcessAbsoluteMotionEvent(InputInfoPtr pInfo, struct input_event *ev) { int value; EvdevPtr pEvdev = pInfo->private; /* Get the signed value, earlier kernels had this as unsigned */ value = ev->value; /* Ignore EV_ABS events if we never set up for them. */ if (!(pEvdev->flags & EVDEV_ABSOLUTE_EVENTS)) return; if (ev->code > ABS_MAX) return; if (EvdevWheelEmuFilterMotion(pInfo, ev)) return; pEvdev->vals[pEvdev->axis_map[ev->code]] = value; if (ev->code == ABS_X) pEvdev->abs_queued |= ABS_X_VALUE; else if (ev->code == ABS_Y) pEvdev->abs_queued |= ABS_Y_VALUE; else pEvdev->abs_queued |= ABS_VALUE; } /** * Take the key press/release input event and process it accordingly. */ static void EvdevProcessKeyEvent(InputInfoPtr pInfo, struct input_event *ev) { int value, i; EvdevPtr pEvdev = pInfo->private; /* Get the signed value, earlier kernels had this as unsigned */ value = ev->value; /* don’t repeat mouse buttons */ if (ev->code >= BTN_MOUSE && ev->code < KEY_OK) if (value == 2) return; for (i = 0; i code == proximity_bits[i]) { EvdevProcessProximityEvent(pInfo, ev); return; } } switch (ev->code) { case BTN_TOUCH: /* For devices that have but don’t use proximity, use * BTN_TOUCH as the proximity notifier */ if (!pEvdev->use_proximity) pEvdev->in_proximity = value ? ev->code : 0; if (!(pEvdev->flags & (EVDEV_TOUCHSCREEN | EVDEV_TABLET))) break; /* Treat BTN_TOUCH from devices that only have BTN_TOUCH as * BTN_LEFT. */ ev->code = BTN_LEFT; /* Intentional fallthrough! */ default: EvdevProcessButtonEvent(pInfo, ev); break; } } /** * Post the relative motion events. */ void EvdevPostRelativeMotionEvents(InputInfoPtr pInfo, int num_v, int first_v, int v[MAX_VALUATORS]) { EvdevPtr pEvdev = pInfo->private; if (pEvdev->rel_queued) { xf86PostMotionEventP(pInfo->dev, FALSE, first_v, num_v, v + first_v); } } /** * Post the absolute motion events. */ void EvdevPostAbsoluteMotionEvents(InputInfoPtr pInfo, int num_v, int first_v, int v[MAX_VALUATORS]) { EvdevPtr pEvdev = pInfo->private; /* * Some devices only generate valid abs coords when BTN_TOOL_PEN is * pressed. On wacom tablets, this means that the pen is in * proximity of the tablet. After the pen is removed, BTN_TOOL_PEN is * released, and a (0, 0) absolute event is generated. Checking * pEvdev->in_proximity here lets us ignore that event. * pEvdev->in_proximity is initialized to 1 so devices that don’t use * this scheme still just work. */ if (pEvdev->abs_queued && pEvdev->in_proximity) { xf86PostMotionEventP(pInfo->dev, TRUE, first_v, num_v, v + first_v); } } static void EvdevPostProximityEvents(InputInfoPtr pInfo, int which, int num_v, int first_v, int v[MAX_VALUATORS]) { int i; EvdevPtr pEvdev = pInfo->private; for (i = 0; pEvdev->prox_queued && i num_queue; i++) { switch (pEvdev->queue[i].type) { case EV_QUEUE_KEY: case EV_QUEUE_BTN: break; case EV_QUEUE_PROXIMITY: if (pEvdev->queue[i].val == which) xf86PostProximityEventP(pInfo->dev, which, first_v, num_v, v + first_v); break; } } } /** * Post the queued key/button events. */ static void EvdevPostQueuedEvents(InputInfoPtr pInfo, int num_v, int first_v, int v[MAX_VALUATORS]) { int i; EvdevPtr pEvdev = pInfo->private; for (i = 0; i num_queue; i++) { switch (pEvdev->queue[i].type) { case EV_QUEUE_KEY: xf86PostKeyboardEvent(pInfo->dev, pEvdev->queue[i].key, pEvdev->queue[i].val); break; case EV_QUEUE_BTN: #if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 11 if (pEvdev->abs_queued && pEvdev->in_proximity) { xf86PostButtonEventP(pInfo->dev, 1, pEvdev->queue[i].key, pEvdev->queue[i].val, first_v, num_v, v + first_v); } else #endif xf86PostButtonEvent(pInfo->dev, 0, pEvdev->queue[i].key, pEvdev->queue[i].val, 0, 0); break; case EV_QUEUE_PROXIMITY: break; } } } /** * Take the synchronization input event and process it accordingly; the motion * notify events are sent first, then any button/key press/release events. */ static void EvdevProcessSyncEvent(InputInfoPtr pInfo, struct input_event *ev) { int num_v = 0, first_v = 0; int v[MAX_VALUATORS] = {}; EvdevPtr pEvdev = pInfo->private; EvdevProcessProximityState(pInfo); EvdevProcessValuators(pInfo, v, &num_v, &first_v); EvdevPostProximityEvents(pInfo, TRUE, num_v, first_v, v); EvdevPostRelativeMotionEvents(pInfo, num_v, first_v, v); EvdevPostAbsoluteMotionEvents(pInfo, num_v, first_v, v); EvdevPostQueuedEvents(pInfo, num_v, first_v, v); EvdevPostProximityEvents(pInfo, FALSE, num_v, first_v, v); memset(pEvdev->delta, 0, sizeof(pEvdev->delta)); memset(pEvdev->queue, 0, sizeof(pEvdev->queue)); pEvdev->num_queue = 0; pEvdev->abs_queued = 0; pEvdev->rel_queued = 0; pEvdev->prox_queued = 0; } /** * Process the events from the device; nothing is actually posted to the server * until an EV_SYN event is received. */ static void EvdevProcessEvent(InputInfoPtr pInfo, struct input_event *ev) { switch (ev->type) { case EV_REL: EvdevProcessRelativeMotionEvent(pInfo, ev); break; case EV_ABS: EvdevProcessAbsoluteMotionEvent(pInfo, ev); break; case EV_KEY: EvdevProcessKeyEvent(pInfo, ev); break; case EV_SYN: EvdevProcessSyncEvent(pInfo, ev); break; } } #undef ABS_X_VALUE #undef ABS_Y_VALUE #undef ABS_VALUE /* just a magic number to reduce the number of reads */ #define NUM_EVENTS 16 static void EvdevReadInput(InputInfoPtr pInfo) { struct input_event ev[NUM_EVENTS]; int i, len = sizeof(ev); while (len == sizeof(ev)) { len = read(pInfo->fd, &ev, sizeof(ev)); if (len fd); pInfo->fd = -1; } else if (errno != EAGAIN) { /* We use X_NONE here because it doesn’t alloc */ xf86MsgVerb(X_NONE, 0, „%s: Read error: %sn”, pInfo->name, strerror(errno)); } break; } /* The kernel promises that we always only read a complete * event, so len != sizeof ev is an error. */ if (len % sizeof(ev[0])) { /* We use X_NONE here because it doesn’t alloc */ xf86MsgVerb(X_NONE, 0, „%s: Read error: %sn”, pInfo->name, strerror(errno)); break; } for (i = 0; i < len/sizeof(ev[0]); i++) EvdevProcessEvent(pInfo, &ev[i]); } } #define TestBit(bit, array) ((array[(bit) / LONG_BITS]) & (1L << ((bit) % LONG_BITS))) static void EvdevPtrCtrlProc(DeviceIntPtr device, PtrCtrl *ctrl) { /* Nothing to do, dix handles all settings */ } #if GET_ABI_MAJOR(ABI_XINPUT_VERSION) public.devicePrivate; pEvdev = pInfo->private; /* Compute the modifier map */ memset(modMap, 0, sizeof modMap); for (i = 0; i < ArrayLength(map) / GLYPHS_PER_KEY; i++) { sym = map[i * GLYPHS_PER_KEY]; for (j = 0; j rmlvo.rules, pEvdev->rmlvo.model, pEvdev->rmlvo.layout, pEvdev->rmlvo.variant, pEvdev->rmlvo.options); if (!XkbInitKeyboardDeviceStruct(device, &pEvdev->xkbnames, &keySyms, modMap, NULL, EvdevKbdCtrl)) return 0; return 1; } #endif static void EvdevKbdCtrl(DeviceIntPtr device, KeybdCtrl *ctrl) { static struct { int xbit, code; } bits[] = { { CAPSFLAG, LED_CAPSL }, { NUMFLAG, LED_NUML }, { SCROLLFLAG, LED_SCROLLL }, { MODEFLAG, LED_KANA }, { COMPOSEFLAG, LED_COMPOSE } }; InputInfoPtr pInfo; struct input_event ev[ArrayLength(bits)]; int i; memset(ev, 0, sizeof(ev)); pInfo = device->public.devicePrivate; for (i = 0; i leds & bits[i].xbit) > 0; } write(pInfo->fd, ev, sizeof ev); } static int EvdevAddKeyClass(DeviceIntPtr device) { InputInfoPtr pInfo; EvdevPtr pEvdev; pInfo = device->public.devicePrivate; pEvdev = pInfo->private; /* sorry, no rules change allowed for you */ xf86ReplaceStrOption(pInfo->options, „xkb_rules”, „evdev”); SetXkbOption(pInfo, „xkb_rules”, &pEvdev->rmlvo.rules); SetXkbOption(pInfo, „xkb_model”, &pEvdev->rmlvo.model); if (!pEvdev->rmlvo.model) SetXkbOption(pInfo, „XkbModel”, &pEvdev->rmlvo.model); SetXkbOption(pInfo, „xkb_layout”, &pEvdev->rmlvo.layout); if (!pEvdev->rmlvo.layout) SetXkbOption(pInfo, „XkbLayout”, &pEvdev->rmlvo.layout); SetXkbOption(pInfo, „xkb_variant”, &pEvdev->rmlvo.variant); if (!pEvdev->rmlvo.variant) SetXkbOption(pInfo, „XkbVariant”, &pEvdev->rmlvo.variant); SetXkbOption(pInfo, „xkb_options”, &pEvdev->rmlvo.options); if (!pEvdev->rmlvo.options) SetXkbOption(pInfo, „XkbOptions”, &pEvdev->rmlvo.options); #if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 5 if (!InitKeyboardDeviceStruct(device, &pEvdev->rmlvo, NULL, EvdevKbdCtrl)) return !Success; #else if (!EvdevInitKeysyms(device)) return !Success; #endif return Success; } static int EvdevAddAbsClass(DeviceIntPtr device) { InputInfoPtr pInfo; EvdevPtr pEvdev; int num_axes, axis, i = 0; Atom *atoms; pInfo = device->public.devicePrivate; pEvdev = pInfo->private; if (!TestBit(EV_ABS, pEvdev->bitmask)) return !Success; num_axes = EvdevCountBits(pEvdev->abs_bitmask, NLONGS(ABS_MAX)); if (num_axes MAX_VALUATORS) { xf86Msg(X_WARNING, „%s: found %d axes, limiting to %d.n”, device->name, num_axes, MAX_VALUATORS); num_axes = MAX_VALUATORS; } pEvdev->num_vals = num_axes; memset(pEvdev->vals, 0, num_axes * sizeof(int)); memset(pEvdev->old_vals, -1, num_axes * sizeof(int)); atoms = malloc(pEvdev->num_vals * sizeof(Atom)); for (axis = ABS_X; i < MAX_VALUATORS && axis axis_map[axis] = -1; if (!TestBit(axis, pEvdev->abs_bitmask)) continue; pEvdev->axis_map[axis] = i; i++; } EvdevInitAxesLabels(pEvdev, pEvdev->num_vals, atoms); if (!InitValuatorClassDeviceStruct(device, num_axes, #if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 7 atoms, #endif #if GET_ABI_MAJOR(ABI_XINPUT_VERSION) name); return !Success; } for (axis = ABS_X; axis axis_map[axis]; int resolution = 10000; if (axnum == -1) continue; #if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 30) /* Kernel provides units/mm, X wants units/m */ if (pEvdev->absinfo[axis].resolution) resolution = pEvdev->absinfo[axis].resolution * 1000; #endif xf86InitValuatorAxisStruct(device, axnum, #if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 7 atoms[axnum], #endif pEvdev->absinfo[axis].minimum, pEvdev->absinfo[axis].maximum, resolution, 0, resolution #if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 12 , Absolute #endif ); xf86InitValuatorDefaults(device, axnum); pEvdev->old_vals[axnum] = -1; } free(atoms); for (i = 0; i use_proximity) break; if (TestBit(proximity_bits[i], pEvdev->key_bitmask)) { InitProximityClassDeviceStruct(device); break; } } if (!InitPtrFeedbackClassDeviceStruct(device, EvdevPtrCtrlProc)) { xf86Msg(X_ERROR, „%s: failed to initialize pointer feedback class ” „device.n”, device->name); return !Success; } if (pEvdev->flags & EVDEV_TOUCHPAD) pEvdev->flags |= EVDEV_RELATIVE_MODE; else pEvdev->flags &= ~EVDEV_RELATIVE_MODE; if (xf86FindOption(pInfo->options, „Mode”)) { char *mode; mode = xf86SetStrOption(pInfo->options, „Mode”, NULL); if (!strcasecmp(„absolute”, mode)) pEvdev->flags &= ~EVDEV_RELATIVE_MODE; else if (!strcasecmp(„relative”, mode)) pEvdev->flags |= EVDEV_RELATIVE_MODE; else xf86Msg(X_INFO, „%s: unknown mode, use defaultn”, pInfo->name); free(mode); } return Success; } static int EvdevAddRelClass(DeviceIntPtr device) { InputInfoPtr pInfo; EvdevPtr pEvdev; int num_axes, axis, i = 0; Atom *atoms; pInfo = device->public.devicePrivate; pEvdev = pInfo->private; if (!TestBit(EV_REL, pEvdev->bitmask)) return !Success; num_axes = EvdevCountBits(pEvdev->rel_bitmask, NLONGS(REL_MAX)); if (num_axes rel_bitmask)) num_axes–; if (TestBit(REL_HWHEEL, pEvdev->rel_bitmask)) num_axes–; if (TestBit(REL_DIAL, pEvdev->rel_bitmask)) num_axes–; if (num_axes MAX_VALUATORS) { xf86Msg(X_WARNING, „%s: found %d axes, limiting to %d.n”, device->name, num_axes, MAX_VALUATORS); num_axes = MAX_VALUATORS; } pEvdev->num_vals = num_axes; memset(pEvdev->vals, 0, num_axes * sizeof(int)); atoms = malloc(pEvdev->num_vals * sizeof(Atom)); for (axis = REL_X; i < MAX_VALUATORS && axis axis_map[axis] = -1; /* We don’t post wheel events, so ignore them here too */ if (axis == REL_WHEEL || axis == REL_HWHEEL || axis == REL_DIAL) continue; if (!TestBit(axis, pEvdev->rel_bitmask)) continue; pEvdev->axis_map[axis] = i; i++; } EvdevInitAxesLabels(pEvdev, pEvdev->num_vals, atoms); if (!InitValuatorClassDeviceStruct(device, num_axes, #if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 7 atoms, #endif #if GET_ABI_MAJOR(ABI_XINPUT_VERSION) name); return !Success; } if (!InitPtrFeedbackClassDeviceStruct(device, EvdevPtrCtrlProc)) { xf86Msg(X_ERROR, „%s: failed to initialize pointer feedback class ” „device.n”, device->name); return !Success; } for (axis = REL_X; axis axis_map[axis]; if (axnum == -1) continue; xf86InitValuatorAxisStruct(device, axnum, #if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 7 atoms[axnum], #endif -1, -1, 1, 0, 1 #if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 12 , Relative #endif ); xf86InitValuatorDefaults(device, axnum); } free(atoms); return Success; } static int EvdevAddButtonClass(DeviceIntPtr device) { InputInfoPtr pInfo; EvdevPtr pEvdev; Atom *labels; pInfo = device->public.devicePrivate; pEvdev = pInfo->private; labels = malloc(pEvdev->num_buttons * sizeof(Atom)); EvdevInitButtonLabels(pEvdev, pEvdev->num_buttons, labels); if (!InitButtonClassDeviceStruct(device, pEvdev->num_buttons, #if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 7 labels, #endif pEvdev->btnmap)) return !Success; free(labels); return Success; } /** * Init the button mapping for the device. By default, this is a 1:1 mapping, * i.e. Button 1 maps to Button 1, Button 2 to 2, etc. * * If a mapping has been specified, the mapping is the default, with the * user-defined ones overwriting the defaults. * i.e. a user-defined mapping of „3 2 1” results in a mapping of 3 2 1 4 5 6 … * * Invalid button mappings revert to the default. * * Note that index 0 is unused, button 0 does not exist. * This mapping is initialised for all devices, but only applied if the device * has buttons (in EvdevAddButtonClass). */ static void EvdevInitButtonMapping(InputInfoPtr pInfo) { int i, nbuttons = 1; char *mapping = NULL; EvdevPtr pEvdev = pInfo->private; /* Check for user-defined button mapping */ if ((mapping = xf86CheckStrOption(pInfo->options, „ButtonMapping”, NULL))) { char *map, *s = ” „; int btn = 0; xf86Msg(X_CONFIG, „%s: ButtonMapping ‚%s’n”, pInfo->name, mapping); map = mapping; while (s && *s != ” && nbuttons < EVDEV_MAXBUTTONS) { btn = strtol(map, &s, 10); if (s == map || btn EVDEV_MAXBUTTONS) { xf86Msg(X_ERROR, „%s: … Invalid button mapping. Using defaultsn”, pInfo->name); nbuttons = 1; /* ensure defaults start at 1 */ break; } pEvdev->btnmap[nbuttons++] = btn; map = s; } free(mapping); } for (i = nbuttons; i btnmap); i++) pEvdev->btnmap[i] = i; } static void EvdevInitAnyClass(DeviceIntPtr device, EvdevPtr pEvdev) { if (pEvdev->flags & EVDEV_RELATIVE_EVENTS && EvdevAddRelClass(device) == Success) xf86Msg(X_INFO, „%s: initialized for relative axes.n”, device->name); if (pEvdev->flags & EVDEV_ABSOLUTE_EVENTS && EvdevAddAbsClass(device) == Success) xf86Msg(X_INFO, „%s: initialized for absolute axes.n”, device->name); } static void EvdevInitAbsClass(DeviceIntPtr device, EvdevPtr pEvdev) { if (EvdevAddAbsClass(device) == Success) { xf86Msg(X_INFO,”%s: initialized for absolute axes.n”, device->name); } else { xf86Msg(X_ERROR,”%s: failed to initialize for absolute axes.n”, device->name); pEvdev->flags &= ~EVDEV_ABSOLUTE_EVENTS; } } static void EvdevInitRelClass(DeviceIntPtr device, EvdevPtr pEvdev) { int has_abs_axes = pEvdev->flags & EVDEV_ABSOLUTE_EVENTS; if (EvdevAddRelClass(device) == Success) { xf86Msg(X_INFO,”%s: initialized for relative axes.n”, device->name); if (has_abs_axes) { xf86Msg(X_WARNING,”%s: ignoring absolute axes.n”, device->name); pEvdev->flags &= ~EVDEV_ABSOLUTE_EVENTS; } } else { xf86Msg(X_ERROR,”%s: failed to initialize for relative axes.n”, device->name); pEvdev->flags &= ~EVDEV_RELATIVE_EVENTS; if (has_abs_axes) EvdevInitAbsClass(device, pEvdev); } } static void EvdevInitTouchDevice(DeviceIntPtr device, EvdevPtr pEvdev) { if (pEvdev->flags & EVDEV_RELATIVE_EVENTS) { xf86Msg(X_WARNING,”%s: touchpads, tablets and touchscreens ignore ” „relative axes.n”, device->name); pEvdev->flags &= ~EVDEV_RELATIVE_EVENTS; } EvdevInitAbsClass(device, pEvdev); } static int EvdevInit(DeviceIntPtr device) { int i; InputInfoPtr pInfo; EvdevPtr pEvdev; pInfo = device->public.devicePrivate; pEvdev = pInfo->private; /* clear all axis_map entries */ for(i = 0; i axis_map[i]=-1; if (pEvdev->flags & EVDEV_KEYBOARD_EVENTS) EvdevAddKeyClass(device); if (pEvdev->flags & EVDEV_BUTTON_EVENTS) EvdevAddButtonClass(device); /* We don’t allow relative and absolute axes on the same device. The * reason is that some devices (MS Optical Desktop 2000) register both * rel and abs axes for x/y. * * The abs axes register min/max; this min/max then also applies to the * relative device (the mouse) and caps it at 0..255 for both axes. * So, unless you have a small screen, you won’t be enjoying it much; * consequently, absolute axes are generally ignored. * * However, currenly only a device with absolute axes can be registered * as a touch{pad,screen}. Thus, given such a device, absolute axes are * used and relative axes are ignored. */ if (pEvdev->flags & (EVDEV_UNIGNORE_RELATIVE | EVDEV_UNIGNORE_ABSOLUTE)) EvdevInitAnyClass(device, pEvdev); else if (pEvdev->flags & (EVDEV_TOUCHPAD | EVDEV_TOUCHSCREEN | EVDEV_TABLET)) EvdevInitTouchDevice(device, pEvdev); else if (pEvdev->flags & EVDEV_RELATIVE_EVENTS) EvdevInitRelClass(device, pEvdev); else if (pEvdev->flags & EVDEV_ABSOLUTE_EVENTS) EvdevInitAbsClass(device, pEvdev); #ifdef HAVE_PROPERTIES /* We drop the return value, the only time we ever want the handlers to * unregister is when the device dies. In which case we don’t have to * unregister anyway */ EvdevInitProperty(device); XIRegisterPropertyHandler(device, EvdevSetProperty, NULL, NULL); EvdevMBEmuInitProperty(device); EvdevWheelEmuInitProperty(device); EvdevDragLockInitProperty(device); #endif return Success; } /** * Init all extras (wheel emulation, etc.) and grab the device. */ static int EvdevOn(DeviceIntPtr device) { InputInfoPtr pInfo; EvdevPtr pEvdev; int rc = Success; pInfo = device->public.devicePrivate; pEvdev = pInfo->private; /* after PreInit fd is still open */ rc = EvdevOpenDevice(pInfo); if (rc != Success) return rc; EvdevGrabDevice(pInfo, 1, 0); xf86FlushInput(pInfo->fd); xf86AddEnabledDevice(pInfo); EvdevMBEmuOn(pInfo); pEvdev->flags |= EVDEV_INITIALIZED; device->public.on = TRUE; return Success; } static int EvdevProc(DeviceIntPtr device, int what) { InputInfoPtr pInfo; EvdevPtr pEvdev; pInfo = device->public.devicePrivate; pEvdev = pInfo->private; switch (what) { case DEVICE_INIT: return EvdevInit(device); case DEVICE_ON: return EvdevOn(device); case DEVICE_OFF: if (pEvdev->flags & EVDEV_INITIALIZED) EvdevMBEmuFinalize(pInfo); if (pInfo->fd != -1) { EvdevGrabDevice(pInfo, 0, 1); xf86RemoveEnabledDevice(pInfo); close(pInfo->fd); pInfo->fd = -1; } pEvdev->min_maj = 0; pEvdev->flags &= ~EVDEV_INITIALIZED; device->public.on = FALSE; break; case DEVICE_CLOSE: xf86Msg(X_INFO, „%s: Closen”, pInfo->name); if (pInfo->fd != -1) { close(pInfo->fd); pInfo->fd = -1; } EvdevRemoveDevice(pInfo); pEvdev->min_maj = 0; break; } return Success; } /** * Get as much information as we can from the fd and cache it. * * @return Success if the information was cached, or !Success otherwise. */ static int EvdevCache(InputInfoPtr pInfo) { EvdevPtr pEvdev = pInfo->private; int i, len; char name[1024] = {0}; unsigned long bitmask[NLONGS(EV_CNT)] = {0}; unsigned long key_bitmask[NLONGS(KEY_CNT)] = {0}; unsigned long rel_bitmask[NLONGS(REL_CNT)] = {0}; unsigned long abs_bitmask[NLONGS(ABS_CNT)] = {0}; unsigned long led_bitmask[NLONGS(LED_CNT)] = {0}; if (ioctl(pInfo->fd, EVIOCGNAME(sizeof(name) – 1), name) name, name); len = ioctl(pInfo->fd, EVIOCGBIT(0, sizeof(bitmask)), bitmask); if (len name, strerror(errno)); goto error; } memcpy(pEvdev->bitmask, bitmask, len); len = ioctl(pInfo->fd, EVIOCGBIT(EV_REL, sizeof(rel_bitmask)), rel_bitmask); if (len name, strerror(errno)); goto error; } memcpy(pEvdev->rel_bitmask, rel_bitmask, len); len = ioctl(pInfo->fd, EVIOCGBIT(EV_ABS, sizeof(abs_bitmask)), abs_bitmask); if (len name, strerror(errno)); goto error; } memcpy(pEvdev->abs_bitmask, abs_bitmask, len); len = ioctl(pInfo->fd, EVIOCGBIT(EV_LED, sizeof(led_bitmask)), led_bitmask); if (len name, strerror(errno)); goto error; } memcpy(pEvdev->led_bitmask, led_bitmask, len); /* * Do not try to validate absinfo data since it is not expected * to be static, always refresh it in evdev structure. */ for (i = ABS_X; i fd, EVIOCGABS(i), &pEvdev->absinfo[i]); if (len name, i, strerror(errno)); goto error; } } } len = ioctl(pInfo->fd, EVIOCGBIT(EV_KEY, sizeof(key_bitmask)), key_bitmask); if (len name, strerror(errno)); goto error; } /* Copy the data so we have reasonably up-to-date info */ memcpy(pEvdev->key_bitmask, key_bitmask, len); return Success; error: return !Success; } /** * Issue an EVIOCGRAB on the device file, either as a grab or to ungrab, or * both. Return TRUE on success, otherwise FALSE. Failing the release is a * still considered a success, because it’s not as if you could do anything * about it. */ static BOOL EvdevGrabDevice(InputInfoPtr pInfo, int grab, int ungrab) { EvdevPtr pEvdev = pInfo->private; if (pEvdev->grabDevice) { if (grab && ioctl(pInfo->fd, EVIOCGRAB, (void *)1)) { xf86Msg(X_WARNING, „%s: Grab failed (%s)n”, pInfo->name, strerror(errno)); return FALSE; } else if (ungrab && ioctl(pInfo->fd, EVIOCGRAB, (void *)0)) xf86Msg(X_WARNING, „%s: Release failed (%s)n”, pInfo->name, strerror(errno)); } return TRUE; } static int EvdevProbe(InputInfoPtr pInfo) { int i, has_rel_axes, has_abs_axes, has_keys, num_buttons, has_scroll; int has_lmr; /* left middle right */ int ignore_abs = 0, ignore_rel = 0; EvdevPtr pEvdev = pInfo->private; int rc = 1; /* Trinary state for ignoring axes: – unset: do the normal thing. – TRUE: explicitly ignore them. – FALSE: unignore axes, use them at all cost if they’re present. */ if (xf86FindOption(pInfo->options, „IgnoreRelativeAxes”)) { if (xf86SetBoolOption(pInfo->options, „IgnoreRelativeAxes”, FALSE)) ignore_rel = TRUE; else pEvdev->flags |= EVDEV_UNIGNORE_RELATIVE; } if (xf86FindOption(pInfo->options, „IgnoreAbsoluteAxes”)) { if (xf86SetBoolOption(pInfo->options, „IgnoreAbsoluteAxes”, FALSE)) ignore_abs = TRUE; else pEvdev->flags |= EVDEV_UNIGNORE_ABSOLUTE; } has_rel_axes = FALSE; has_abs_axes = FALSE; has_keys = FALSE; has_scroll = FALSE; has_lmr = FALSE; num_buttons = 0; /* count all buttons */ for (i = BTN_MISC; i key_bitmask)) { mapping = EvdevUtilButtonEventToButtonNumber(pEvdev, i); if (mapping > num_buttons) num_buttons = mapping; } } has_lmr = TestBit(BTN_LEFT, pEvdev->key_bitmask) || TestBit(BTN_MIDDLE, pEvdev->key_bitmask) || TestBit(BTN_RIGHT, pEvdev->key_bitmask); if (num_buttons) { pEvdev->flags |= EVDEV_BUTTON_EVENTS; pEvdev->num_buttons = num_buttons; xf86Msg(X_PROBED, „%s: Found %d mouse buttonsn”, pInfo->name, num_buttons); } for (i = 0; i rel_bitmask)) { has_rel_axes = TRUE; break; } } if (has_rel_axes) { if (TestBit(REL_WHEEL, pEvdev->rel_bitmask) || TestBit(REL_HWHEEL, pEvdev->rel_bitmask) || TestBit(REL_DIAL, pEvdev->rel_bitmask)) { xf86Msg(X_PROBED, „%s: Found scroll wheel(s)n”, pInfo->name); has_scroll = TRUE; if (!num_buttons) xf86Msg(X_INFO, „%s: Forcing buttons for scroll wheel(s)n”, pInfo->name); num_buttons = (num_buttons num_buttons = num_buttons; } if (!ignore_rel) { xf86Msg(X_PROBED, „%s: Found relative axesn”, pInfo->name); pEvdev->flags |= EVDEV_RELATIVE_EVENTS; if (TestBit(REL_X, pEvdev->rel_bitmask) && TestBit(REL_Y, pEvdev->rel_bitmask)) { xf86Msg(X_PROBED, „%s: Found x and y relative axesn”, pInfo->name); } } else { xf86Msg(X_INFO, „%s: Relative axes present but ignored.n”, pInfo->name); has_rel_axes = FALSE; } } for (i = 0; i abs_bitmask)) { has_abs_axes = TRUE; break; } } if (ignore_abs && has_abs_axes) { xf86Msg(X_INFO, „%s: Absolute axes present but ignored.n”, pInfo->name); has_abs_axes = FALSE; } else if (has_abs_axes) { xf86Msg(X_PROBED, „%s: Found absolute axesn”, pInfo->name); pEvdev->flags |= EVDEV_ABSOLUTE_EVENTS; if ((TestBit(ABS_X, pEvdev->abs_bitmask) && TestBit(ABS_Y, pEvdev->abs_bitmask))) { xf86Msg(X_PROBED, „%s: Found x and y absolute axesn”, pInfo->name); if (TestBit(BTN_TOOL_PEN, pEvdev->key_bitmask) || TestBit(BTN_STYLUS, pEvdev->key_bitmask) || TestBit(BTN_STYLUS2, pEvdev->key_bitmask)) { xf86Msg(X_PROBED, „%s: Found absolute tablet.n”, pInfo->name); pEvdev->flags |= EVDEV_TABLET; if (!pEvdev->num_buttons) { pEvdev->num_buttons = 7; /* LMR + scroll wheels */ pEvdev->flags |= EVDEV_BUTTON_EVENTS; } } else if (TestBit(ABS_PRESSURE, pEvdev->abs_bitmask) || TestBit(BTN_TOUCH, pEvdev->key_bitmask)) { if (has_lmr || TestBit(BTN_TOOL_FINGER, pEvdev->key_bitmask)) { xf86Msg(X_PROBED, „%s: Found absolute touchpad.n”, pInfo->name); pEvdev->flags |= EVDEV_TOUCHPAD; memset(pEvdev->old_vals, -1, sizeof(int) * pEvdev->num_vals); } else { xf86Msg(X_PROBED, „%s: Found absolute touchscreenn”, pInfo->name); pEvdev->flags |= EVDEV_TOUCHSCREEN; pEvdev->flags |= EVDEV_BUTTON_EVENTS; } } } } for (i = 0; i key_bitmask)) { xf86Msg(X_PROBED, „%s: Found keysn”, pInfo->name); pEvdev->flags |= EVDEV_KEYBOARD_EVENTS; has_keys = TRUE; break; } } if (has_rel_axes || has_abs_axes) { char *str; int num_calibration = 0, calibration[4] = { 0, 0, 0, 0 }; pEvdev->invert_x = xf86SetBoolOption(pInfo->options, „InvertX”, FALSE); pEvdev->invert_y = xf86SetBoolOption(pInfo->options, „InvertY”, FALSE); pEvdev->swap_axes = xf86SetBoolOption(pInfo->options, „SwapAxes”, FALSE); str = xf86CheckStrOption(pInfo->options, „Calibration”, NULL); if (str) { num_calibration = sscanf(str, „%d %d %d %d”, &calibration[0], &calibration[1], &calibration[2], &calibration[3]); free(str); if (num_calibration == 4) EvdevSetCalibration(pInfo, num_calibration, calibration); else xf86Msg(X_ERROR, „%s: Insufficient calibration factors (%d). Ignoring calibrationn”, pInfo->name, num_calibration); } } if (has_rel_axes || has_abs_axes || num_buttons) { pInfo->flags |= XI86_SEND_DRAG_EVENTS; if (pEvdev->flags & EVDEV_TOUCHPAD) { xf86Msg(X_INFO, „%s: Configuring as touchpadn”, pInfo->name); pInfo->type_name = XI_TOUCHPAD; pEvdev->use_proximity = 0; } else if (pEvdev->flags & EVDEV_TABLET) { xf86Msg(X_INFO, „%s: Configuring as tabletn”, pInfo->name); pInfo->type_name = XI_TABLET; } else if (pEvdev->flags & EVDEV_TOUCHSCREEN) { xf86Msg(X_INFO, „%s: Configuring as touchscreenn”, pInfo->name); pInfo->type_name = XI_TOUCHSCREEN; } else { xf86Msg(X_INFO, „%s: Configuring as mousen”, pInfo->name); pInfo->type_name = XI_MOUSE; } rc = 0; } if (has_keys) { xf86Msg(X_INFO, „%s: Configuring as keyboardn”, pInfo->name); pInfo->type_name = XI_KEYBOARD; rc = 0; } if (has_scroll && (has_rel_axes || has_abs_axes || num_buttons || has_keys)) { xf86Msg(X_INFO, „%s: Adding scrollwheel supportn”, pInfo->name); pEvdev->flags |= EVDEV_BUTTON_EVENTS; pEvdev->flags |= EVDEV_RELATIVE_EVENTS; } if (rc) xf86Msg(X_WARNING, „%s: Don’t know how to use devicen”, pInfo->name); return rc; } static void EvdevSetCalibration(InputInfoPtr pInfo, int num_calibration, int calibration[4]) { EvdevPtr pEvdev = pInfo->private; if (num_calibration == 0) { pEvdev->flags &= ~EVDEV_CALIBRATED; pEvdev->calibration.min_x = 0; pEvdev->calibration.max_x = 0; pEvdev->calibration.min_y = 0; pEvdev->calibration.max_y = 0; } else if (num_calibration == 4) { pEvdev->flags |= EVDEV_CALIBRATED; pEvdev->calibration.min_x = calibration[0]; pEvdev->calibration.max_x = calibration[1]; pEvdev->calibration.min_y = calibration[2]; pEvdev->calibration.max_y = calibration[3]; } } static int EvdevOpenDevice(InputInfoPtr pInfo) { EvdevPtr pEvdev = pInfo->private; char *device = (char*)pEvdev->device; if (!device) { device = xf86CheckStrOption(pInfo->options, „Device”, NULL); if (!device) { xf86Msg(X_ERROR, „%s: No device specified.n”, pInfo->name); return BadValue; } pEvdev->device = device; xf86Msg(X_CONFIG, „%s: Device: ”%s”n”, pInfo->name, device); } if (pInfo->fd fd = open(device, O_RDWR | O_NONBLOCK, 0); } while (pInfo->fd fd min_maj = EvdevGetMajorMinor(pInfo); if (EvdevIsDuplicate(pInfo)) { xf86Msg(X_WARNING, „%s: device file is duplicate. Ignoring.n”, pInfo->name); close(pInfo->fd); return BadMatch; } return Success; } #if GET_ABI_MAJOR(ABI_XINPUT_VERSION) fd = -1; pInfo->name = dev->identifier; pInfo->flags = 0; pInfo->history_size = 0; pInfo->control_proc = NULL; pInfo->close_proc = NULL; pInfo->conversion_proc = NULL; pInfo->reverse_conversion_proc = NULL; pInfo->dev = NULL; pInfo->private_flags = 0; pInfo->always_core_feedback = NULL; pInfo->conf_idev = dev; pInfo->private = NULL; xf86CollectInputOptions(pInfo, (const char**)evdevDefaults, NULL); xf86ProcessCommonOptions(pInfo, pInfo->options); if (NewEvdevPreInit(drv, pInfo, flags) == Success) { pInfo->flags |= XI86_CONFIGURED; return pInfo; } xf86DeleteInput(pInfo, 0); return NULL; } static int NewEvdevPreInit(InputDriverPtr drv, InputInfoPtr pInfo, int flags) #else static int EvdevPreInit(InputDriverPtr drv, InputInfoPtr pInfo, int flags) #endif { EvdevPtr pEvdev; int rc = BadAlloc; if (!(pEvdev = calloc(sizeof(EvdevRec), 1))) goto error; pInfo->private = pEvdev; pInfo->type_name = „UNKNOWN”; pInfo->device_control = EvdevProc; pInfo->read_input = EvdevReadInput; pInfo->switch_mode = EvdevSwitchMode; rc = EvdevOpenDevice(pInfo); if (rc != Success) goto error; /* * We initialize pEvdev->in_proximity to 1 so that device that doesn’t use * proximity will still report events. */ pEvdev->in_proximity = 1; pEvdev->use_proximity = 1; /* Grabbing the event device stops in-kernel event forwarding. In other words, it disables rfkill and the „Macintosh mouse button emulation”. Note that this needs a server that sets the console to RAW mode. */ pEvdev->grabDevice = xf86CheckBoolOption(pInfo->options, „GrabDevice”, 0); /* If grabDevice is set, ungrab immediately since we only want to grab * between DEVICE_ON and DEVICE_OFF. If we never get DEVICE_ON, don’t * hold a grab. */ if (!EvdevGrabDevice(pInfo, 1, 1)) { xf86Msg(X_WARNING, „%s: Device may already be configured.n”, pInfo->name); rc = BadMatch; goto error; } EvdevInitButtonMapping(pInfo); if (EvdevCache(pInfo) || EvdevProbe(pInfo)) { rc = BadMatch; goto error; } EvdevAddDevice(pInfo); if (pEvdev->flags & EVDEV_BUTTON_EVENTS) { EvdevMBEmuPreInit(pInfo); EvdevWheelEmuPreInit(pInfo); EvdevDragLockPreInit(pInfo); } return Success; error: if (pInfo->fd >= 0) close(pInfo->fd); return rc; } _X_EXPORT InputDriverRec EVDEV = { 1, „evdev”, NULL, EvdevPreInit, NULL, NULL, #if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 12 evdevDefaults #endif }; static void EvdevUnplug(pointer p) { } static pointer EvdevPlug(pointer module, pointer options, int *errmaj, int *errmin) { xf86AddInputDriver(&EVDEV, module, 0); return module; } static XF86ModuleVersionInfo EvdevVersionRec = { „evdev”, MODULEVENDORSTRING, MODINFOSTRING1, MODINFOSTRING2, XORG_VERSION_CURRENT, PACKAGE_VERSION_MAJOR, PACKAGE_VERSION_MINOR, PACKAGE_VERSION_PATCHLEVEL, ABI_CLASS_XINPUT, ABI_XINPUT_VERSION, MOD_CLASS_XINPUT, {0, 0, 0, 0} }; _X_EXPORT XF86ModuleData evdevModuleData = { &EvdevVersionRec, EvdevPlug, EvdevUnplug }; /* Return an index value for a given button event code * returns 0 on non-button event. */ unsigned int EvdevUtilButtonEventToButtonNumber(EvdevPtr pEvdev, int code) { switch (code) { /* Mouse buttons */ case BTN_LEFT: return 1; case BTN_MIDDLE: return 2; case BTN_RIGHT: return 3; case BTN_SIDE … BTN_JOYSTICK – 1: return 8 + code – BTN_SIDE; /* Generic buttons */ case BTN_0 … BTN_2: return 1 + code – BTN_0; case BTN_3 … BTN_MOUSE – 1: return 8 + code – BTN_3; /* Tablet stylus buttons */ case BTN_TOUCH … BTN_STYLUS2: return 1 + code – BTN_TOUCH; /* The rest */ default: /* Ignore */ return 0; } } #ifdef HAVE_PROPERTIES #ifdef HAVE_LABELS /* Aligned with linux/input.h. Note that there are holes in the ABS_ range, these are simply replaced with MISC here */ static char* abs_labels[] = { AXIS_LABEL_PROP_ABS_X, /* 0x00 */ AXIS_LABEL_PROP_ABS_Y, /* 0x01 */ AXIS_LABEL_PROP_ABS_Z, /* 0x02 */ AXIS_LABEL_PROP_ABS_RX, /* 0x03 */ AXIS_LABEL_PROP_ABS_RY, /* 0x04 */ AXIS_LABEL_PROP_ABS_RZ, /* 0x05 */ AXIS_LABEL_PROP_ABS_THROTTLE, /* 0x06 */ AXIS_LABEL_PROP_ABS_RUDDER, /* 0x07 */ AXIS_LABEL_PROP_ABS_WHEEL, /* 0x08 */ AXIS_LABEL_PROP_ABS_GAS, /* 0x09 */ AXIS_LABEL_PROP_ABS_BRAKE, /* 0x0a */ AXIS_LABEL_PROP_ABS_MISC, /* undefined */ AXIS_LABEL_PROP_ABS_MISC, /* undefined */ AXIS_LABEL_PROP_ABS_MISC, /* undefined */ AXIS_LABEL_PROP_ABS_MISC, /* undefined */ AXIS_LABEL_PROP_ABS_MISC, /* undefined */ AXIS_LABEL_PROP_ABS_HAT0X, /* 0x10 */ AXIS_LABEL_PROP_ABS_HAT0Y, /* 0x11 */ AXIS_LABEL_PROP_ABS_HAT1X, /* 0x12 */ AXIS_LABEL_PROP_ABS_HAT1Y, /* 0x13 */ AXIS_LABEL_PROP_ABS_HAT2X, /* 0x14 */ AXIS_LABEL_PROP_ABS_HAT2Y, /* 0x15 */ AXIS_LABEL_PROP_ABS_HAT3X, /* 0x16 */ AXIS_LABEL_PROP_ABS_HAT3Y, /* 0x17 */ AXIS_LABEL_PROP_ABS_PRESSURE, /* 0x18 */ AXIS_LABEL_PROP_ABS_DISTANCE, /* 0x19 */ AXIS_LABEL_PROP_ABS_TILT_X, /* 0x1a */ AXIS_LABEL_PROP_ABS_TILT_Y, /* 0x1b */ AXIS_LABEL_PROP_ABS_TOOL_WIDTH, /* 0x1c */ AXIS_LABEL_PROP_ABS_MISC, /* undefined */ AXIS_LABEL_PROP_ABS_MISC, /* undefined */ AXIS_LABEL_PROP_ABS_MISC, /* undefined */ AXIS_LABEL_PROP_ABS_VOLUME /* 0x20 */ AXIS_LABEL_PROP_ABS_MISC, /* undefined */ AXIS_LABEL_PROP_ABS_MISC, /* undefined */ AXIS_LABEL_PROP_ABS_MISC, /* undefined */ AXIS_LABEL_PROP_ABS_MISC, /* undefined */ AXIS_LABEL_PROP_ABS_MISC, /* undefined */ AXIS_LABEL_PROP_ABS_MISC, /* undefined */ AXIS_LABEL_PROP_ABS_MISC, /* undefined */ AXIS_LABEL_PROP_ABS_MISC, /* undefined */ AXIS_LABEL_PROP_ABS_MISC, /* undefined */ AXIS_LABEL_PROP_ABS_MISC, /* undefined */ AXIS_LABEL_PROP_ABS_MISC, /* undefined */ AXIS_LABEL_PROP_ABS_MISC, /* undefined */ AXIS_LABEL_PROP_ABS_MISC, /* undefined */ AXIS_LABEL_PROP_ABS_MISC, /* undefined */ AXIS_LABEL_PROP_ABS_MISC, /* undefined */ AXIS_LABEL_PROP_ABS_MISC, /* undefined */ #if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 10 AXIS_LABEL_PROP_ABS_MT_TOUCH_MAJOR, /* 0x30 */ AXIS_LABEL_PROP_ABS_MT_TOUCH_MINOR, /* 0x31 */ AXIS_LABEL_PROP_ABS_MT_WIDTH_MAJOR, /* 0x32 */ AXIS_LABEL_PROP_ABS_MT_WIDTH_MINOR, /* 0x33 */ AXIS_LABEL_PROP_ABS_MT_ORIENTATION, /* 0x34 */ AXIS_LABEL_PROP_ABS_MT_POSITION_X, /* 0x35 */ AXIS_LABEL_PROP_ABS_MT_POSITION_Y, /* 0x36 */ AXIS_LABEL_PROP_ABS_MT_TOOL_TYPE, /* 0x37 */ AXIS_LABEL_PROP_ABS_MT_BLOB_ID, /* 0x38 */ AXIS_LABEL_PROP_ABS_MT_TRACKING_ID, /* 0x39 */ AXIS_LABEL_PROP_ABS_MT_PRESSURE, /* 0x3a */ #endif }; static char* rel_labels[] = { AXIS_LABEL_PROP_REL_X, AXIS_LABEL_PROP_REL_Y, AXIS_LABEL_PROP_REL_Z, AXIS_LABEL_PROP_REL_RX, AXIS_LABEL_PROP_REL_RY, AXIS_LABEL_PROP_REL_RZ, AXIS_LABEL_PROP_REL_HWHEEL, AXIS_LABEL_PROP_REL_DIAL, AXIS_LABEL_PROP_REL_WHEEL, AXIS_LABEL_PROP_REL_MISC }; static char* btn_labels[][16] = { { /* BTN_MISC group offset 0x100*/ BTN_LABEL_PROP_BTN_0, /* 0x00 */ BTN_LABEL_PROP_BTN_1, /* 0x01 */ BTN_LABEL_PROP_BTN_2, /* 0x02 */ BTN_LABEL_PROP_BTN_3, /* 0x03 */ BTN_LABEL_PROP_BTN_4, /* 0x04 */ BTN_LABEL_PROP_BTN_5, /* 0x05 */ BTN_LABEL_PROP_BTN_6, /* 0x06 */ BTN_LABEL_PROP_BTN_7, /* 0x07 */ BTN_LABEL_PROP_BTN_8, /* 0x08 */ BTN_LABEL_PROP_BTN_9 /* 0x09 */ }, { /* BTN_MOUSE group offset 0x110 */ BTN_LABEL_PROP_BTN_LEFT, /* 0x00 */ BTN_LABEL_PROP_BTN_RIGHT, /* 0x01 */ BTN_LABEL_PROP_BTN_MIDDLE, /* 0x02 */ BTN_LABEL_PROP_BTN_SIDE, /* 0x03 */ BTN_LABEL_PROP_BTN_EXTRA, /* 0x04 */ BTN_LABEL_PROP_BTN_FORWARD, /* 0x05 */ BTN_LABEL_PROP_BTN_BACK, /* 0x06 */ BTN_LABEL_PROP_BTN_TASK /* 0x07 */ }, { /* BTN_JOYSTICK group offset 0x120 */ BTN_LABEL_PROP_BTN_TRIGGER, /* 0x00 */ BTN_LABEL_PROP_BTN_THUMB, /* 0x01 */ BTN_LABEL_PROP_BTN_THUMB2, /* 0x02 */ BTN_LABEL_PROP_BTN_TOP, /* 0x03 */ BTN_LABEL_PROP_BTN_TOP2, /* 0x04 */ BTN_LABEL_PROP_BTN_PINKIE, /* 0x05 */ BTN_LABEL_PROP_BTN_BASE, /* 0x06 */ BTN_LABEL_PROP_BTN_BASE2, /* 0x07 */ BTN_LABEL_PROP_BTN_BASE3, /* 0x08 */ BTN_LABEL_PROP_BTN_BASE4, /* 0x09 */ BTN_LABEL_PROP_BTN_BASE5, /* 0x0a */ BTN_LABEL_PROP_BTN_BASE6, /* 0x0b */ NULL, NULL, NULL, BTN_LABEL_PROP_BTN_DEAD /* 0x0f */ }, { /* BTN_GAMEPAD group offset 0x130 */ BTN_LABEL_PROP_BTN_A, /* 0x00 */ BTN_LABEL_PROP_BTN_B, /* 0x01 */ BTN_LABEL_PROP_BTN_C, /* 0x02 */ BTN_LABEL_PROP_BTN_X, /* 0x03 */ BTN_LABEL_PROP_BTN_Y, /* 0x04 */ BTN_LABEL_PROP_BTN_Z, /* 0x05 */ BTN_LABEL_PROP_BTN_TL, /* 0x06 */ BTN_LABEL_PROP_BTN_TR, /* 0x07 */ BTN_LABEL_PROP_BTN_TL2, /* 0x08 */ BTN_LABEL_PROP_BTN_TR2, /* 0x09 */ BTN_LABEL_PROP_BTN_SELECT, /* 0x0a */ BTN_LABEL_PROP_BTN_START, /* 0x0b */ BTN_LABEL_PROP_BTN_MODE, /* 0x0c */ BTN_LABEL_PROP_BTN_THUMBL, /* 0x0d */ BTN_LABEL_PROP_BTN_THUMBR /* 0x0e */ }, { /* BTN_DIGI group offset 0x140 */ BTN_LABEL_PROP_BTN_TOOL_PEN, /* 0x00 */ BTN_LABEL_PROP_BTN_TOOL_RUBBER, /* 0x01 */ BTN_LABEL_PROP_BTN_TOOL_BRUSH, /* 0x02 */ BTN_LABEL_PROP_BTN_TOOL_PENCIL, /* 0x03 */ BTN_LABEL_PROP_BTN_TOOL_AIRBRUSH, /* 0x04 */ BTN_LABEL_PROP_BTN_TOOL_FINGER,

        maniek

        29 Maj 2012 at 13:13

  3. Link do pliku http://sterownikico.pl/maxter/evdev.c

    Proszę o podpowiedź gdzie wstawić: xf86Msg(X_WARNING, „%s: unable to handle keycode>255: %d\n”,

    maniek

    29 Maj 2012 at 13:56


Skomentuj

Wprowadź swoje dane lub kliknij jedną z tych ikon, aby się zalogować:

Logo WordPress.com

Komentujesz korzystając z konta WordPress.com. Log Out / Zmień )

Zdjęcie z Twittera

Komentujesz korzystając z konta Twitter. Log Out / Zmień )

Facebook photo

Komentujesz korzystając z konta Facebook. Log Out / Zmień )

Google+ photo

Komentujesz korzystając z konta Google+. Log Out / Zmień )

Connecting to %s

%d bloggers like this: