device_input 0.2.1.1 → 1.0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: ef70d561e40df5e3bd0df134ede59a38b11b8b78
4
- data.tar.gz: 5c902897dcd290b0cac172629833e12851dd04e2
2
+ SHA256:
3
+ metadata.gz: 01a4b48883bd7c07006de058e16d3ff8ff1d9792b8905eb8abae64a82e577e5a
4
+ data.tar.gz: c61bb60b4f227a3718cf90c4704df38574a7a52797cd644549a15a0076b52175
5
5
  SHA512:
6
- metadata.gz: '00688046ffe558c9d16b321eb33e121acfacd88ff61ab6eddc2a3abe076a71662fc4224b1c7cbc9e6457c16c88b1f58ae566784852dcffba3e0edb873cd53915'
7
- data.tar.gz: d547249fbaf0dd1872910a7b55b61512e27054a0169489a8c81ed5672bb521fa0d62570a0b53c1de95ed77c121cc86bc46f58e5f95ac39747097a483afe8c571
6
+ metadata.gz: 6190ef1adafadaeadd24532e92ca1fa72bbdd72d00583165952b946538f55940cd211cf283171c7e467c705958038afba41c0c43224d0704e527d6ace4d8e89d
7
+ data.tar.gz: 9a3dcfacafc3487358f88f3796a477410225a4ebfa3e41df06b2afc3da48717e7f053b8ab51ec607f5644ca537b68a371179bade3588b2b3df441a780c7e7e30
data/README.md CHANGED
@@ -1,13 +1,19 @@
1
+ [![CI Status](https://github.com/rickhull/device_input/actions/workflows/ci.yaml/badge.svg)](https://github.com/rickhull/device_input/actions/workflows/ci.yaml)
2
+ [![Gem Version](https://badge.fury.io/rb/device_input.svg)](http://badge.fury.io/rb/device_input)
3
+ [![Code Climate](https://codeclimate.com/github/rickhull/device_input/badges/gpa.svg)](https://codeclimate.com/github/rickhull/device_input)
4
+
1
5
  # Device Input
2
6
 
3
7
  *for the Linux kernel*
4
8
 
5
- We want to read events from e.g. `/dev/input/event0` in Ruby. For example,
6
- if you want to see what's happening "on the wire" when you press a special
7
- function key on a laptop. While this code can be used for the purpose of
8
- malicious keystroke logging, it is not well suited for it and does not provide
9
- the root privileges in order to read `/dev/input`. Once you've got the
10
- privilege to read `/dev/input` it's *game over* anyway.
9
+ This is a very basic tool for reading device input events from e.g.
10
+ `/dev/input/event0` in Ruby. For example, in order to see what's happening
11
+ "on the wire" when a special laptop function key is pressed. While this tool
12
+ can plausibly be used for the purpose of malicious keystroke logging, it is
13
+ not well suited for it and does not provide the root privileges in order to
14
+ read `/dev/input`.
15
+
16
+ Once you've given up the privilege to read `/dev/input` it's *game over* anyway.
11
17
 
12
18
  ## Rationale
13
19
 
@@ -34,8 +40,7 @@ long time, it was pretty simple: events are 16 bytes:
34
40
 
35
41
  However, this is only true for 32-bit platforms. On 64-bit platforms, event
36
42
  timestamps became 16 bytes, increasing the size of events from 16 to 24 bytes.
37
- This is because a timestamp is defined (ultimately) as two `long`s, and as
38
- everyone knows, two longs don't make a light. No, wait -- it's that `long`s
43
+ This is because a timestamp is defined (ultimately) as two `long`s, which
39
44
  are bigger on 64-bit platforms. It's easy to remember:
40
45
 
41
46
  * 32-bit platform: 32-bit `long` (4 bytes)
@@ -61,12 +66,12 @@ executable code to assist in examining kernel input events.
61
66
 
62
67
  Install the gem:
63
68
  ```shell
64
- $ gem install device_input # sudo as necessary
69
+ $ gem install device_input
65
70
  ```
66
71
 
67
72
  Or, if using [Bundler](http://bundler.io/), add to your `Gemfile`:
68
73
  ```ruby
69
- gem 'device_input', '~> 0.1'
74
+ gem 'device_input', '~> 0.3'
70
75
  ```
71
76
 
72
77
  # Usage
@@ -74,7 +79,7 @@ gem 'device_input', '~> 0.1'
74
79
  ## Executable
75
80
 
76
81
  ```shell
77
- $ sudo devsniff /dev/input/event0
82
+ $ evdump /dev/input/event0 # sudo as necessary
78
83
  ```
79
84
 
80
85
  When the `f` key is pressed:
@@ -96,7 +101,7 @@ EV_SYN:SYN_REPORT:0
96
101
 
97
102
  How about pretty mode?
98
103
  ```shell
99
- $ sudo devsniff /dev/input/event0 pretty
104
+ $ sudo cat /dev/input/event0 | evdump --print pretty
100
105
 
101
106
  # f
102
107
 
@@ -110,7 +115,7 @@ $ sudo devsniff /dev/input/event0 pretty
110
115
 
111
116
  We can pull off the labels and go raw:
112
117
  ```shell
113
- $ sudo devsniff /dev/input/event0 raw
118
+ $ sudo cat /dev/input/event0 | evdump --print raw
114
119
 
115
120
  # f
116
121
 
@@ -124,7 +129,7 @@ $ sudo devsniff /dev/input/event0 raw
124
129
 
125
130
  Fulfill your hacker-matrix fantasies:
126
131
  ```shell
127
- $ sudo devsniff /dev/input/event0 hex
132
+ $ sudo cat /dev/input/event0 | evdump --print hex
128
133
 
129
134
  # f
130
135
 
@@ -141,10 +146,12 @@ $ sudo devsniff /dev/input/event0 hex
141
146
  ```ruby
142
147
  require 'device_input'
143
148
 
144
- # this loops forever and blocks waiting for input
145
- DeviceInput.read_from('/dev/input/event0') do |event|
146
- puts event
147
- # break if event.time > start + 30
149
+ File.open('/dev/input/event0', 'r') do |dev|
150
+ # this loops forever and blocks waiting for input
151
+ DeviceInput.read_loop(dev) do |event|
152
+ puts event
153
+ # break if event.time > start + 30
154
+ end
148
155
  end
149
156
  ```
150
157
 
@@ -157,21 +164,18 @@ An event has:
157
164
  * `#value`: Fixnum (signed) from `#data`
158
165
 
159
166
  You will probably want to write your own read loop for your own project.
160
- [`DeviceInput.read_from`](lib/device_input.rb#L100) is very simple and can
167
+ [`DeviceInput.read_loop`](lib/device_input.rb#L98) is very simple and can
161
168
  easily be rewritten outside of this project's namespace and adapted for your
162
169
  needs.
163
170
 
164
- # Research
171
+ # Background
165
172
 
166
173
  ## Kernel docs
167
174
 
168
175
  * https://www.kernel.org/doc/Documentation/input/input.txt
169
176
  * https://www.kernel.org/doc/Documentation/input/event-codes.txt
170
177
 
171
- These events are defined as C structs with a fixed size in bytes. See more
172
- about these structs towards the end of this document.
173
-
174
- ## Kernel structs
178
+ ### Kernel structs
175
179
 
176
180
  from https://www.kernel.org/doc/Documentation/input/input.txt
177
181
  ```
@@ -206,7 +210,7 @@ What's a [`__kernel_time_t`](https://git.kernel.org/cgit/linux/kernel/git/torval
206
210
  ```
207
211
  typedef long __kernel_long_t;
208
212
  # ...
209
- typedef __kernel_long_t __kernel_suseconds_t;
213
+ typedef __kernel_long_t __kernel_suseconds_t;
210
214
  # ...
211
215
  typedef __kernel_long_t __kernel_time_t;
212
216
  ```
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.2.1.1
1
+ 1.0.0.1
data/bin/evdump ADDED
@@ -0,0 +1,54 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'device_input'
4
+ require 'slop'
5
+
6
+ opts = Slop.parse do |o|
7
+ o.banner = "evdump [OPTIONS] [DEVICE]"
8
+ o.string '-p', '--print', 'pretty|raw|hex|off'
9
+ o.int '-d', '--duration', 'number of seconds to read input [inf]'
10
+ o.int '-c', '--count', 'number of events to read [inf]'
11
+ o.on '-h', '--help' do
12
+ puts o
13
+ exit
14
+ end
15
+ end
16
+
17
+ def opts.error(msg = nil)
18
+ puts self
19
+ puts "ERROR: #{msg}" if msg
20
+ exit 1
21
+ end
22
+
23
+ case opts[:print]
24
+ when 'off'
25
+ print_meth = nil
26
+ when 'pretty', 'raw', 'hex'
27
+ print_meth = opts[:print]
28
+ else
29
+ print_meth = 'to_s'
30
+ end
31
+
32
+ if $stdin.tty?
33
+ device = opts.arguments.shift
34
+ opts.error "Please specify an input device file" unless device
35
+ opts.error "#{device} is not a character device" unless File.chardev? device
36
+ opts.error "#{device} is not readable" unless File.readable? device
37
+ device = File.new(device, 'r')
38
+ else
39
+ device = $stdin
40
+ end
41
+
42
+ start = Time.now
43
+ duration = opts[:duration]
44
+ count = 0
45
+ max = opts[:count]
46
+
47
+ DeviceInput.read_loop(device) { |event|
48
+ puts event.send(print_meth) if print_meth
49
+ if max
50
+ count += 1
51
+ break if count >= max
52
+ end
53
+ break if duration and Time.now - start > duration
54
+ }
@@ -42,423 +42,423 @@ module DeviceInput
42
42
  },
43
43
 
44
44
  EV_KEY => {
45
- 0 => 'Reserved',
46
- 1 => 'Esc',
47
- 2 => '1',
48
- 3 => '2',
49
- 4 => '3',
50
- 5 => '4',
51
- 6 => '5',
52
- 7 => '6',
53
- 8 => '7',
54
- 9 => '8',
55
- 10 => '9',
56
- 11 => '0',
57
- 12 => 'Minus',
58
- 13 => 'Equal',
59
- 14 => 'Backspace',
60
- 15 => 'Tab',
61
- 16 => 'Q',
62
- 17 => 'W',
63
- 18 => 'E',
64
- 19 => 'R',
65
- 20 => 'T',
66
- 21 => 'Y',
67
- 22 => 'U',
68
- 23 => 'I',
69
- 24 => 'O',
70
- 25 => 'P',
71
- 26 => 'LeftBrace',
72
- 27 => 'RightBrace',
73
- 28 => 'Enter',
74
- 29 => 'LeftControl',
75
- 30 => 'A',
76
- 31 => 'S',
77
- 32 => 'D',
78
- 33 => 'F',
79
- 34 => 'G',
80
- 35 => 'H',
81
- 36 => 'J',
82
- 37 => 'K',
83
- 38 => 'L',
84
- 39 => 'Semicolon',
85
- 40 => 'Apostrophe',
86
- 41 => 'Grave',
87
- 42 => 'LeftShift',
88
- 43 => 'BackSlash',
89
- 44 => 'Z',
90
- 45 => 'X',
91
- 46 => 'C',
92
- 47 => 'V',
93
- 48 => 'B',
94
- 49 => 'N',
95
- 50 => 'M',
96
- 51 => 'Comma',
97
- 52 => 'Dot',
98
- 53 => 'Slash',
99
- 54 => 'RightShift',
100
- 55 => 'KPAsterisk',
101
- 56 => 'LeftAlt',
102
- 57 => 'Space',
103
- 58 => 'CapsLock',
104
- 59 => 'F1',
105
- 60 => 'F2',
106
- 61 => 'F3',
107
- 62 => 'F4',
108
- 63 => 'F5',
109
- 64 => 'F6',
110
- 65 => 'F7',
111
- 66 => 'F8',
112
- 67 => 'F9',
113
- 68 => 'F10',
114
- 69 => 'NumLock',
115
- 70 => 'ScrollLock',
116
- 71 => 'KP7',
117
- 72 => 'KP8',
118
- 73 => 'KP9',
119
- 74 => 'KPMinus',
120
- 75 => 'KP4',
121
- 76 => 'KP5',
122
- 77 => 'KP6',
123
- 78 => 'KPPlus',
124
- 79 => 'KP1',
125
- 80 => 'KP2',
126
- 81 => 'KP3',
127
- 82 => 'KP0',
128
- 83 => 'KPDot',
129
- 85 => 'Zenkaku/Hankaku',
130
- 86 => '102nd',
131
- 87 => 'F11',
132
- 88 => 'F12',
133
- 89 => 'RO',
134
- 90 => 'Katakana',
135
- 91 => 'HIRAGANA',
136
- 92 => 'Henkan',
137
- 93 => 'Katakana/Hiragana',
138
- 94 => 'Muhenkan',
139
- 95 => 'KPJpComma',
140
- 96 => 'KPEnter',
141
- 97 => 'RightCtrl',
142
- 98 => 'KPSlash',
143
- 99 => 'SysRq',
144
- 100 => 'RightAlt',
145
- 101 => 'LineFeed',
146
- 102 => 'Home',
147
- 103 => 'Up',
148
- 104 => 'PageUp',
149
- 105 => 'Left',
150
- 106 => 'Right',
151
- 107 => 'End',
152
- 108 => 'Down',
153
- 109 => 'PageDown',
154
- 110 => 'Insert',
155
- 111 => 'Delete',
156
- 112 => 'Macro',
157
- 113 => 'Mute',
158
- 114 => 'VolumeDown',
159
- 115 => 'VolumeUp',
160
- 116 => 'Power',
161
- 117 => 'KPEqual',
162
- 118 => 'KPPlusMinus',
163
- 119 => 'Pause',
164
- 121 => 'KPComma',
165
- 122 => 'Hanguel',
166
- 123 => 'Hanja',
167
- 124 => 'Yen',
168
- 125 => 'LeftMeta',
169
- 126 => 'RightMeta',
170
- 127 => 'Compose',
171
- 128 => 'Stop',
172
- 129 => 'Again',
173
- 130 => 'Props',
174
- 131 => 'Undo',
175
- 132 => 'Front',
176
- 133 => 'Copy',
177
- 134 => 'Open',
178
- 135 => 'Paste',
179
- 136 => 'Find',
180
- 137 => 'Cut',
181
- 138 => 'Help',
182
- 139 => 'Menu',
183
- 140 => 'Calc',
184
- 141 => 'Setup',
185
- 142 => 'Sleep',
186
- 143 => 'WakeUp',
187
- 144 => 'File',
188
- 145 => 'SendFile',
189
- 146 => 'DeleteFile',
190
- 147 => 'X-fer',
191
- 148 => 'Prog1',
192
- 149 => 'Prog2',
193
- 150 => 'WWW',
194
- 151 => 'MSDOS',
195
- 152 => 'Coffee',
196
- 153 => 'Direction',
197
- 154 => 'CycleWindows',
198
- 155 => 'Mail',
199
- 156 => 'Bookmarks',
200
- 157 => 'Computer',
201
- 158 => 'Back',
202
- 159 => 'Forward',
203
- 160 => 'CloseCD',
204
- 161 => 'EjectCD',
205
- 162 => 'EjectCloseCD',
206
- 163 => 'NextSong',
207
- 164 => 'PlayPause',
208
- 165 => 'PreviousSong',
209
- 166 => 'StopCD',
210
- 167 => 'Record',
211
- 168 => 'Rewind',
212
- 169 => 'Phone',
213
- 170 => 'ISOKey',
214
- 171 => 'Config',
215
- 172 => 'HomePage',
216
- 173 => 'Refresh',
217
- 174 => 'Exit',
218
- 175 => 'Move',
219
- 176 => 'Edit',
220
- 177 => 'ScrollUp',
221
- 178 => 'ScrollDown',
222
- 179 => 'KPLeftParenthesis',
223
- 180 => 'KPRightParenthesis',
224
- 183 => 'F13',
225
- 184 => 'F14',
226
- 185 => 'F15',
227
- 186 => 'F16',
228
- 187 => 'F17',
229
- 188 => 'F18',
230
- 189 => 'F19',
231
- 190 => 'F20',
232
- 191 => 'F21',
233
- 192 => 'F22',
234
- 193 => 'F23',
235
- 194 => 'F24',
236
- 200 => 'PlayCD',
237
- 201 => 'PauseCD',
238
- 202 => 'Prog3',
239
- 203 => 'Prog4',
240
- 205 => 'Suspend',
241
- 206 => 'Close',
242
- 207 => 'Play',
243
- 208 => 'Fast Forward',
244
- 209 => 'Bass Boost',
245
- 210 => 'Print',
246
- 211 => 'HP',
247
- 212 => 'Camera',
248
- 213 => 'Sound',
249
- 214 => 'Question',
250
- 215 => 'Email',
251
- 216 => 'Chat',
252
- 217 => 'Search',
253
- 218 => 'Connect',
254
- 219 => 'Finance',
255
- 220 => 'Sport',
256
- 221 => 'Shop',
257
- 222 => 'Alternate Erase',
258
- 223 => 'Cancel',
259
- 224 => 'Brightness down',
260
- 225 => 'Brightness up',
261
- 226 => 'Media',
262
- 240 => 'Unknown',
263
- 256 => 'Btn0',
264
- 257 => 'Btn1',
265
- 258 => 'Btn2',
266
- 259 => 'Btn3',
267
- 260 => 'Btn4',
268
- 261 => 'Btn5',
269
- 262 => 'Btn6',
270
- 263 => 'Btn7',
271
- 264 => 'Btn8',
272
- 265 => 'Btn9',
273
- 272 => 'LeftBtn',
274
- 273 => 'RightBtn',
275
- 274 => 'MiddleBtn',
276
- 275 => 'SideBtn',
277
- 276 => 'ExtraBtn',
278
- 277 => 'ForwardBtn',
279
- 278 => 'BackBtn',
280
- 279 => 'TaskBtn',
281
- 288 => 'Trigger',
282
- 289 => 'ThumbBtn',
283
- 290 => 'ThumbBtn2',
284
- 291 => 'TopBtn',
285
- 292 => 'TopBtn2',
286
- 293 => 'PinkieBtn',
287
- 294 => 'BaseBtn',
288
- 295 => 'BaseBtn2',
289
- 296 => 'BaseBtn3',
290
- 297 => 'BaseBtn4',
291
- 298 => 'BaseBtn5',
292
- 299 => 'BaseBtn6',
293
- 303 => 'BtnDead',
294
- 304 => 'BtnA',
295
- 305 => 'BtnB',
296
- 306 => 'BtnC',
297
- 307 => 'BtnX',
298
- 308 => 'BtnY',
299
- 309 => 'BtnZ',
300
- 310 => 'BtnTL',
301
- 311 => 'BtnTR',
302
- 312 => 'BtnTL2',
303
- 313 => 'BtnTR2',
304
- 314 => 'BtnSelect',
305
- 315 => 'BtnStart',
306
- 316 => 'BtnMode',
307
- 317 => 'BtnThumbL',
308
- 318 => 'BtnThumbR',
309
- 320 => 'ToolPen',
310
- 321 => 'ToolRubber',
311
- 322 => 'ToolBrush',
312
- 323 => 'ToolPencil',
313
- 324 => 'ToolAirbrush',
314
- 325 => 'ToolFinger',
315
- 326 => 'ToolMouse',
316
- 327 => 'ToolLens',
317
- 330 => 'Touch',
318
- 331 => 'Stylus',
319
- 332 => 'Stylus2',
320
- 333 => 'Tool Doubletap',
321
- 334 => 'Tool Tripletap',
322
- 336 => 'WheelBtn',
323
- 337 => 'Gear up',
324
- 352 => 'Ok',
325
- 353 => 'Select',
326
- 354 => 'Goto',
327
- 355 => 'Clear',
328
- 356 => 'Power2',
329
- 357 => 'Option',
330
- 358 => 'Info',
331
- 359 => 'Time',
332
- 360 => 'Vendor',
333
- 361 => 'Archive',
334
- 362 => 'Program',
335
- 363 => 'Channel',
336
- 364 => 'Favorites',
337
- 365 => 'EPG',
338
- 366 => 'PVR',
339
- 367 => 'MHP',
340
- 368 => 'Language',
341
- 369 => 'Title',
342
- 370 => 'Subtitle',
343
- 371 => 'Angle',
344
- 372 => 'Zoom',
345
- 373 => 'Mode',
346
- 374 => 'Keyboard',
347
- 375 => 'Screen',
348
- 376 => 'PC',
349
- 377 => 'TV',
350
- 378 => 'TV2',
351
- 379 => 'VCR',
352
- 380 => 'VCR2',
353
- 381 => 'Sat',
354
- 382 => 'Sat2',
355
- 383 => 'CD',
356
- 384 => 'Tape',
357
- 385 => 'Radio',
358
- 386 => 'Tuner',
359
- 387 => 'Player',
360
- 388 => 'Text',
361
- 389 => 'DVD',
362
- 390 => 'Aux',
363
- 391 => 'MP3',
364
- 392 => 'Audio',
365
- 393 => 'Video',
366
- 394 => 'Directory',
367
- 395 => 'List',
368
- 396 => 'Memo',
369
- 397 => 'Calendar',
370
- 398 => 'Red',
371
- 399 => 'Green',
372
- 400 => 'Yellow',
373
- 401 => 'Blue',
374
- 402 => 'ChannelUp',
375
- 403 => 'ChannelDown',
376
- 404 => 'First',
377
- 405 => 'Last',
378
- 406 => 'AB',
379
- 407 => 'Next',
380
- 408 => 'Restart',
381
- 409 => 'Slow',
382
- 410 => 'Shuffle',
383
- 411 => 'Break',
384
- 412 => 'Previous',
385
- 413 => 'Digits',
386
- 414 => 'TEEN',
387
- 415 => 'TWEN',
388
- 448 => 'Delete EOL',
389
- 449 => 'Delete EOS',
390
- 450 => 'Insert line',
391
- 451 => 'Delete line',
45
+ 0 => ['Reserved'],
46
+ 1 => ['Esc'],
47
+ 2 => ['1'],
48
+ 3 => ['2'],
49
+ 4 => ['3'],
50
+ 5 => ['4'],
51
+ 6 => ['5'],
52
+ 7 => ['6'],
53
+ 8 => ['7'],
54
+ 9 => ['8'],
55
+ 10 => ['9'],
56
+ 11 => ['0'],
57
+ 12 => ['Minus'],
58
+ 13 => ['Equal'],
59
+ 14 => ['Backspace'],
60
+ 15 => ['Tab'],
61
+ 16 => ['Q'],
62
+ 17 => ['W'],
63
+ 18 => ['E'],
64
+ 19 => ['R'],
65
+ 20 => ['T'],
66
+ 21 => ['Y'],
67
+ 22 => ['U'],
68
+ 23 => ['I'],
69
+ 24 => ['O'],
70
+ 25 => ['P'],
71
+ 26 => ['LeftBrace'],
72
+ 27 => ['RightBrace'],
73
+ 28 => ['Enter'],
74
+ 29 => ['LeftControl'],
75
+ 30 => ['A'],
76
+ 31 => ['S'],
77
+ 32 => ['D'],
78
+ 33 => ['F'],
79
+ 34 => ['G'],
80
+ 35 => ['H'],
81
+ 36 => ['J'],
82
+ 37 => ['K'],
83
+ 38 => ['L'],
84
+ 39 => ['Semicolon'],
85
+ 40 => ['Apostrophe'],
86
+ 41 => ['Grave'],
87
+ 42 => ['LeftShift'],
88
+ 43 => ['BackSlash'],
89
+ 44 => ['Z'],
90
+ 45 => ['X'],
91
+ 46 => ['C'],
92
+ 47 => ['V'],
93
+ 48 => ['B'],
94
+ 49 => ['N'],
95
+ 50 => ['M'],
96
+ 51 => ['Comma'],
97
+ 52 => ['Dot'],
98
+ 53 => ['Slash'],
99
+ 54 => ['RightShift'],
100
+ 55 => ['KPAsterisk'],
101
+ 56 => ['LeftAlt'],
102
+ 57 => ['Space'],
103
+ 58 => ['CapsLock'],
104
+ 59 => ['F1'],
105
+ 60 => ['F2'],
106
+ 61 => ['F3'],
107
+ 62 => ['F4'],
108
+ 63 => ['F5'],
109
+ 64 => ['F6'],
110
+ 65 => ['F7'],
111
+ 66 => ['F8'],
112
+ 67 => ['F9'],
113
+ 68 => ['F10'],
114
+ 69 => ['NumLock'],
115
+ 70 => ['ScrollLock'],
116
+ 71 => ['KP7'],
117
+ 72 => ['KP8'],
118
+ 73 => ['KP9'],
119
+ 74 => ['KPMinus'],
120
+ 75 => ['KP4'],
121
+ 76 => ['KP5'],
122
+ 77 => ['KP6'],
123
+ 78 => ['KPPlus'],
124
+ 79 => ['KP1'],
125
+ 80 => ['KP2'],
126
+ 81 => ['KP3'],
127
+ 82 => ['KP0'],
128
+ 83 => ['KPDot'],
129
+ 85 => ['Zenkaku/Hankaku'],
130
+ 86 => ['102nd'],
131
+ 87 => ['F11'],
132
+ 88 => ['F12'],
133
+ 89 => ['RO'],
134
+ 90 => ['Katakana'],
135
+ 91 => ['HIRAGANA'],
136
+ 92 => ['Henkan'],
137
+ 93 => ['Katakana/Hiragana'],
138
+ 94 => ['Muhenkan'],
139
+ 95 => ['KPJpComma'],
140
+ 96 => ['KPEnter'],
141
+ 97 => ['RightCtrl'],
142
+ 98 => ['KPSlash'],
143
+ 99 => ['SysRq'],
144
+ 100 => ['RightAlt'],
145
+ 101 => ['LineFeed'],
146
+ 102 => ['Home'],
147
+ 103 => ['Up'],
148
+ 104 => ['PageUp'],
149
+ 105 => ['Left'],
150
+ 106 => ['Right'],
151
+ 107 => ['End'],
152
+ 108 => ['Down'],
153
+ 109 => ['PageDown'],
154
+ 110 => ['Insert'],
155
+ 111 => ['Delete'],
156
+ 112 => ['Macro'],
157
+ 113 => ['Mute'],
158
+ 114 => ['VolumeDown'],
159
+ 115 => ['VolumeUp'],
160
+ 116 => ['Power'],
161
+ 117 => ['KPEqual'],
162
+ 118 => ['KPPlusMinus'],
163
+ 119 => ['Pause'],
164
+ 121 => ['KPComma'],
165
+ 122 => ['Hanguel'],
166
+ 123 => ['Hanja'],
167
+ 124 => ['Yen'],
168
+ 125 => ['LeftMeta'],
169
+ 126 => ['RightMeta'],
170
+ 127 => ['Compose'],
171
+ 128 => ['Stop'],
172
+ 129 => ['Again'],
173
+ 130 => ['Props'],
174
+ 131 => ['Undo'],
175
+ 132 => ['Front'],
176
+ 133 => ['Copy'],
177
+ 134 => ['Open'],
178
+ 135 => ['Paste'],
179
+ 136 => ['Find'],
180
+ 137 => ['Cut'],
181
+ 138 => ['Help'],
182
+ 139 => ['Menu'],
183
+ 140 => ['Calc'],
184
+ 141 => ['Setup'],
185
+ 142 => ['Sleep'],
186
+ 143 => ['WakeUp'],
187
+ 144 => ['File'],
188
+ 145 => ['SendFile'],
189
+ 146 => ['DeleteFile'],
190
+ 147 => ['X-fer'],
191
+ 148 => ['Prog1'],
192
+ 149 => ['Prog2'],
193
+ 150 => ['WWW'],
194
+ 151 => ['MSDOS'],
195
+ 152 => ['Coffee'],
196
+ 153 => ['Direction'],
197
+ 154 => ['CycleWindows'],
198
+ 155 => ['Mail'],
199
+ 156 => ['Bookmarks'],
200
+ 157 => ['Computer'],
201
+ 158 => ['Back'],
202
+ 159 => ['Forward'],
203
+ 160 => ['CloseCD'],
204
+ 161 => ['EjectCD'],
205
+ 162 => ['EjectCloseCD'],
206
+ 163 => ['NextSong'],
207
+ 164 => ['PlayPause'],
208
+ 165 => ['PreviousSong'],
209
+ 166 => ['StopCD'],
210
+ 167 => ['Record'],
211
+ 168 => ['Rewind'],
212
+ 169 => ['Phone'],
213
+ 170 => ['ISOKey'],
214
+ 171 => ['Config'],
215
+ 172 => ['HomePage'],
216
+ 173 => ['Refresh'],
217
+ 174 => ['Exit'],
218
+ 175 => ['Move'],
219
+ 176 => ['Edit'],
220
+ 177 => ['ScrollUp'],
221
+ 178 => ['ScrollDown'],
222
+ 179 => ['KPLeftParenthesis'],
223
+ 180 => ['KPRightParenthesis'],
224
+ 183 => ['F13'],
225
+ 184 => ['F14'],
226
+ 185 => ['F15'],
227
+ 186 => ['F16'],
228
+ 187 => ['F17'],
229
+ 188 => ['F18'],
230
+ 189 => ['F19'],
231
+ 190 => ['F20'],
232
+ 191 => ['F21'],
233
+ 192 => ['F22'],
234
+ 193 => ['F23'],
235
+ 194 => ['F24'],
236
+ 200 => ['PlayCD'],
237
+ 201 => ['PauseCD'],
238
+ 202 => ['Prog3'],
239
+ 203 => ['Prog4'],
240
+ 205 => ['Suspend'],
241
+ 206 => ['Close'],
242
+ 207 => ['Play'],
243
+ 208 => ['Fast Forward'],
244
+ 209 => ['Bass Boost'],
245
+ 210 => ['Print'],
246
+ 211 => ['HP'],
247
+ 212 => ['Camera'],
248
+ 213 => ['Sound'],
249
+ 214 => ['Question'],
250
+ 215 => ['Email'],
251
+ 216 => ['Chat'],
252
+ 217 => ['Search'],
253
+ 218 => ['Connect'],
254
+ 219 => ['Finance'],
255
+ 220 => ['Sport'],
256
+ 221 => ['Shop'],
257
+ 222 => ['Alternate Erase'],
258
+ 223 => ['Cancel'],
259
+ 224 => ['Brightness down'],
260
+ 225 => ['Brightness up'],
261
+ 226 => ['Media'],
262
+ 240 => ['Unknown'],
263
+ 256 => ['Btn0'],
264
+ 257 => ['Btn1'],
265
+ 258 => ['Btn2'],
266
+ 259 => ['Btn3'],
267
+ 260 => ['Btn4'],
268
+ 261 => ['Btn5'],
269
+ 262 => ['Btn6'],
270
+ 263 => ['Btn7'],
271
+ 264 => ['Btn8'],
272
+ 265 => ['Btn9'],
273
+ 272 => ['LeftBtn'],
274
+ 273 => ['RightBtn'],
275
+ 274 => ['MiddleBtn'],
276
+ 275 => ['SideBtn'],
277
+ 276 => ['ExtraBtn'],
278
+ 277 => ['ForwardBtn'],
279
+ 278 => ['BackBtn'],
280
+ 279 => ['TaskBtn'],
281
+ 288 => ['Trigger'],
282
+ 289 => ['ThumbBtn'],
283
+ 290 => ['ThumbBtn2'],
284
+ 291 => ['TopBtn'],
285
+ 292 => ['TopBtn2'],
286
+ 293 => ['PinkieBtn'],
287
+ 294 => ['BaseBtn'],
288
+ 295 => ['BaseBtn2'],
289
+ 296 => ['BaseBtn3'],
290
+ 297 => ['BaseBtn4'],
291
+ 298 => ['BaseBtn5'],
292
+ 299 => ['BaseBtn6'],
293
+ 303 => ['BtnDead'],
294
+ 304 => ['BtnA'],
295
+ 305 => ['BtnB'],
296
+ 306 => ['BtnC'],
297
+ 307 => ['BtnX'],
298
+ 308 => ['BtnY'],
299
+ 309 => ['BtnZ'],
300
+ 310 => ['BtnTL'],
301
+ 311 => ['BtnTR'],
302
+ 312 => ['BtnTL2'],
303
+ 313 => ['BtnTR2'],
304
+ 314 => ['BtnSelect'],
305
+ 315 => ['BtnStart'],
306
+ 316 => ['BtnMode'],
307
+ 317 => ['BtnThumbL'],
308
+ 318 => ['BtnThumbR'],
309
+ 320 => ['ToolPen'],
310
+ 321 => ['ToolRubber'],
311
+ 322 => ['ToolBrush'],
312
+ 323 => ['ToolPencil'],
313
+ 324 => ['ToolAirbrush'],
314
+ 325 => ['ToolFinger'],
315
+ 326 => ['ToolMouse'],
316
+ 327 => ['ToolLens'],
317
+ 330 => ['Touch'],
318
+ 331 => ['Stylus'],
319
+ 332 => ['Stylus2'],
320
+ 333 => ['Tool Doubletap'],
321
+ 334 => ['Tool Tripletap'],
322
+ 336 => ['WheelBtn'],
323
+ 337 => ['Gear up'],
324
+ 352 => ['Ok'],
325
+ 353 => ['Select'],
326
+ 354 => ['Goto'],
327
+ 355 => ['Clear'],
328
+ 356 => ['Power2'],
329
+ 357 => ['Option'],
330
+ 358 => ['Info'],
331
+ 359 => ['Time'],
332
+ 360 => ['Vendor'],
333
+ 361 => ['Archive'],
334
+ 362 => ['Program'],
335
+ 363 => ['Channel'],
336
+ 364 => ['Favorites'],
337
+ 365 => ['EPG'],
338
+ 366 => ['PVR'],
339
+ 367 => ['MHP'],
340
+ 368 => ['Language'],
341
+ 369 => ['Title'],
342
+ 370 => ['Subtitle'],
343
+ 371 => ['Angle'],
344
+ 372 => ['Zoom'],
345
+ 373 => ['Mode'],
346
+ 374 => ['Keyboard'],
347
+ 375 => ['Screen'],
348
+ 376 => ['PC'],
349
+ 377 => ['TV'],
350
+ 378 => ['TV2'],
351
+ 379 => ['VCR'],
352
+ 380 => ['VCR2'],
353
+ 381 => ['Sat'],
354
+ 382 => ['Sat2'],
355
+ 383 => ['CD'],
356
+ 384 => ['Tape'],
357
+ 385 => ['Radio'],
358
+ 386 => ['Tuner'],
359
+ 387 => ['Player'],
360
+ 388 => ['Text'],
361
+ 389 => ['DVD'],
362
+ 390 => ['Aux'],
363
+ 391 => ['MP3'],
364
+ 392 => ['Audio'],
365
+ 393 => ['Video'],
366
+ 394 => ['Directory'],
367
+ 395 => ['List'],
368
+ 396 => ['Memo'],
369
+ 397 => ['Calendar'],
370
+ 398 => ['Red'],
371
+ 399 => ['Green'],
372
+ 400 => ['Yellow'],
373
+ 401 => ['Blue'],
374
+ 402 => ['ChannelUp'],
375
+ 403 => ['ChannelDown'],
376
+ 404 => ['First'],
377
+ 405 => ['Last'],
378
+ 406 => ['AB'],
379
+ 407 => ['Next'],
380
+ 408 => ['Restart'],
381
+ 409 => ['Slow'],
382
+ 410 => ['Shuffle'],
383
+ 411 => ['Break'],
384
+ 412 => ['Previous'],
385
+ 413 => ['Digits'],
386
+ 414 => ['TEEN'],
387
+ 415 => ['TWEN'],
388
+ 448 => ['Delete EOL'],
389
+ 449 => ['Delete EOS'],
390
+ 450 => ['Insert line'],
391
+ 451 => ['Delete line'],
392
392
  },
393
393
 
394
394
  EV_REL => {
395
- 0 => 'X',
396
- 1 => 'Y',
397
- 2 => 'Z',
398
- 6 => 'HWheel',
399
- 7 => 'Dial',
400
- 8 => 'Wheel',
401
- 9 => 'Misc',
395
+ 0 => ['X'],
396
+ 1 => ['Y'],
397
+ 2 => ['Z'],
398
+ 6 => ['HWheel'],
399
+ 7 => ['Dial'],
400
+ 8 => ['Wheel'],
401
+ 9 => ['Misc'],
402
402
  },
403
403
 
404
404
  EV_ABS => {
405
- 0 => 'X',
406
- 1 => 'Y',
407
- 2 => 'Z',
408
- 3 => 'Rx',
409
- 4 => 'Ry',
410
- 5 => 'Rz',
411
- 6 => 'Throttle',
412
- 7 => 'Rudder',
413
- 8 => 'Wheel',
414
- 9 => 'Gas',
415
- 10 => 'Brake',
416
- 16 => 'Hat0X',
417
- 17 => 'Hat0Y',
418
- 18 => 'Hat1X',
419
- 19 => 'Hat1Y',
420
- 20 => 'Hat2X',
421
- 21 => 'Hat2Y',
422
- 22 => 'Hat3X',
423
- 23 => 'Hat 3Y',
424
- 24 => 'Pressure',
425
- 25 => 'Distance',
426
- 26 => 'XTilt',
427
- 27 => 'YTilt',
428
- 28 => 'Tool Width',
429
- 32 => 'Volume',
430
- 40 => 'Misc',
405
+ 0 => ['X'],
406
+ 1 => ['Y'],
407
+ 2 => ['Z'],
408
+ 3 => ['Rx'],
409
+ 4 => ['Ry'],
410
+ 5 => ['Rz'],
411
+ 6 => ['Throttle'],
412
+ 7 => ['Rudder'],
413
+ 8 => ['Wheel'],
414
+ 9 => ['Gas'],
415
+ 10 => ['Brake'],
416
+ 16 => ['Hat0X'],
417
+ 17 => ['Hat0Y'],
418
+ 18 => ['Hat1X'],
419
+ 19 => ['Hat1Y'],
420
+ 20 => ['Hat2X'],
421
+ 21 => ['Hat2Y'],
422
+ 22 => ['Hat3X'],
423
+ 23 => ['Hat 3Y'],
424
+ 24 => ['Pressure'],
425
+ 25 => ['Distance'],
426
+ 26 => ['XTilt'],
427
+ 27 => ['YTilt'],
428
+ 28 => ['Tool Width'],
429
+ 32 => ['Volume'],
430
+ 40 => ['Misc'],
431
431
  },
432
432
 
433
433
  EV_MSC => {
434
- 0 => 'Serial',
435
- 1 => 'Pulseled',
436
- 2 => 'Gesture',
437
- 3 => 'RawData',
438
- 4 => 'ScanCode',
434
+ 0 => ['Serial'],
435
+ 1 => ['Pulseled'],
436
+ 2 => ['Gesture'],
437
+ 3 => ['RawData'],
438
+ 4 => ['ScanCode'],
439
439
  },
440
440
 
441
441
  EV_LED => {
442
- 0 => 'NumLock',
443
- 1 => 'CapsLock',
444
- 2 => 'ScrollLock',
445
- 3 => 'Compose',
446
- 4 => 'Kana',
447
- 5 => 'Sleep',
448
- 6 => 'Suspend',
449
- 7 => 'Mute',
450
- 8 => 'Misc',
442
+ 0 => ['NumLock'],
443
+ 1 => ['CapsLock'],
444
+ 2 => ['ScrollLock'],
445
+ 3 => ['Compose'],
446
+ 4 => ['Kana'],
447
+ 5 => ['Sleep'],
448
+ 6 => ['Suspend'],
449
+ 7 => ['Mute'],
450
+ 8 => ['Misc'],
451
451
  },
452
452
 
453
453
  EV_SND => {
454
- 0 => 'Click',
455
- 1 => 'Bell',
456
- 2 => 'Tone',
454
+ 0 => ['Click'],
455
+ 1 => ['Bell'],
456
+ 2 => ['Tone'],
457
457
  },
458
458
 
459
459
  EV_REP => {
460
- 0 => 'Delay',
461
- 1 => 'Period',
460
+ 0 => ['Delay'],
461
+ 1 => ['Period'],
462
462
  },
463
463
  }
464
464
  end
data/lib/device_input.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  require 'device_input/labels'
2
- require 'device_input/compat'
2
+ require 'rbconfig/sizeof'
3
3
 
4
4
  module DeviceInput
5
5
  class Event
@@ -40,13 +40,7 @@ module DeviceInput
40
40
 
41
41
  # return an array of equivalent labels, prettier toward the end
42
42
  def self.code_labels(type_val, code_val)
43
- labels = CODES.dig(type_val, code_val)
44
- if labels
45
- # not all labels have been converted to arrays yet
46
- labels.kind_of?(String) ? [labels] : labels
47
- else
48
- ["UNK-#{type_val}-#{code_val}"]
49
- end
43
+ CODES.dig(type_val, code_val) || ["UNK-#{type_val}-#{code_val}"]
50
44
  end
51
45
 
52
46
  NULL_DATA = Data.new(0, 0, 0, 0, 0)
@@ -59,8 +53,8 @@ module DeviceInput
59
53
  @data = data # sorry for the name. it's a Data. data everywhere
60
54
  @time = Time.at(data.tv_sec, data.tv_usec)
61
55
  # take the raw label, closest to the metal
62
- @type = self.class.type_labels(data.type).first
63
- @code = self.class.code_labels(data.type, data.code).first
56
+ @type = Event.type_labels(data.type).first
57
+ @code = Event.code_labels(data.type, data.code).first
64
58
  end
65
59
 
66
60
  def value
@@ -74,8 +68,8 @@ module DeviceInput
74
68
  # show timestamp and use the last of the labels
75
69
  def pretty
76
70
  [@time.strftime("%Y-%m-%d %H:%M:%S.%L"),
77
- [self.class.type_labels(@data.type).last,
78
- self.class.code_labels(@data.type, @data.code).last,
71
+ [Event.type_labels(@data.type).last,
72
+ Event.code_labels(@data.type, @data.code).last,
79
73
  @data.value].join(':'),
80
74
  ].join(" ")
81
75
  end
@@ -86,8 +80,7 @@ module DeviceInput
86
80
  end
87
81
 
88
82
  # display fields in hex
89
- def ruby23_hex
90
- require 'rbconfig/sizeof' # new in ruby 2.3
83
+ def hex
91
84
  DEFINITION.inject('') { |memo, (field, type)|
92
85
  int = @data.send(field)
93
86
  width = RbConfig::SIZEOF.fetch(type)
@@ -95,18 +88,14 @@ module DeviceInput
95
88
  memo + ("%0.#{width * 2}x" % int) + " "
96
89
  }
97
90
  end
98
-
99
- alias_method :hex, RUBY23 ? :ruby23_hex : :to_s
100
91
  end
101
92
 
102
- # never gonna give you up
103
- def self.read_from(filename)
104
- File.open(filename, 'r') { |f|
105
- loop {
106
- bytes = f.read(Event::BYTE_LENGTH)
107
- data = Event.decode(bytes)
108
- yield Event.new(data)
109
- }
93
+ def self.read_loop(io)
94
+ loop {
95
+ bytes = io.read(Event::BYTE_LENGTH)
96
+ break unless (bytes and bytes.length == Event::BYTE_LENGTH)
97
+ data = Event.decode(bytes)
98
+ yield Event.new(data)
110
99
  }
111
100
  end
112
101
  end
metadata CHANGED
@@ -1,66 +1,78 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: device_input
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.1.1
4
+ version: 1.0.0.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Rick Hull
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-01-26 00:00:00.000000000 Z
11
+ date: 2022-05-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: buildar
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - "~>"
17
+ - - ">="
18
18
  - !ruby/object:Gem::Version
19
19
  version: '2'
20
20
  type: :development
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - "~>"
24
+ - - ">="
25
25
  - !ruby/object:Gem::Version
26
26
  version: '2'
27
+ - !ruby/object:Gem::Dependency
28
+ name: slop
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '4'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '4'
27
41
  description: |
28
42
  Pure ruby to read input events from the Linux kernel input device subsystem.
29
43
  No dependencies. Ruby 2+ required
30
- email:
44
+ email:
31
45
  executables:
32
- - devsniff
46
+ - evdump
33
47
  extensions: []
34
48
  extra_rdoc_files: []
35
49
  files:
36
50
  - README.md
37
51
  - VERSION
38
- - bin/devsniff
52
+ - bin/evdump
39
53
  - lib/device_input.rb
40
- - lib/device_input/compat.rb
41
54
  - lib/device_input/labels.rb
42
55
  homepage: https://github.com/rickhull/device_input
43
56
  licenses:
44
57
  - GPL-3.0
45
58
  metadata: {}
46
- post_install_message:
59
+ post_install_message:
47
60
  rdoc_options: []
48
61
  require_paths:
49
62
  - lib
50
63
  required_ruby_version: !ruby/object:Gem::Requirement
51
64
  requirements:
52
- - - "~>"
65
+ - - ">="
53
66
  - !ruby/object:Gem::Version
54
- version: '2'
67
+ version: '2.3'
55
68
  required_rubygems_version: !ruby/object:Gem::Requirement
56
69
  requirements:
57
70
  - - ">="
58
71
  - !ruby/object:Gem::Version
59
72
  version: '0'
60
73
  requirements: []
61
- rubyforge_project:
62
- rubygems_version: 2.6.8
63
- signing_key:
74
+ rubygems_version: 3.2.26
75
+ signing_key:
64
76
  specification_version: 4
65
77
  summary: Read input events from e.g. /dev/input/event0
66
78
  test_files: []
data/bin/devsniff DELETED
@@ -1,26 +0,0 @@
1
- #!/usr/bin/env ruby
2
-
3
- require 'device_input'
4
-
5
- device = ARGV.shift || '/dev/input/event0'
6
- mode = (ARGV.shift || 'normal').downcase
7
-
8
- if !File.readable?(device)
9
- puts "#{device} cannot be read. Perhaps you need to sudo?"
10
- exit 1
11
- end
12
-
13
- case mode
14
- when 'normal'
15
- mode = 'to_s'
16
- when 'bytes' # legacy
17
- mode = 'hex'
18
- when 'pretty', 'raw', 'hex'
19
- # ok
20
- else
21
- raise "unsupported mode: #{mode}"
22
- end
23
-
24
- DeviceInput.read_from(device) { |event|
25
- puts event.send(mode)
26
- }
@@ -1,20 +0,0 @@
1
- module DeviceInput
2
- if RbConfig::CONFIG.fetch("MAJOR").to_i < 2
3
- raise "unsupported ruby version #{RbConfig::CONFIG['RUBY_VERSION_NAME']}"
4
- else
5
- RUBY23 = RbConfig::CONFIG.fetch("MINOR").to_i >= 3
6
- end
7
-
8
- unless RUBY23
9
- class Event
10
- def CODES.dig(*args)
11
- memo = self
12
- args.each { |a|
13
- memo = memo[a] rescue nil
14
- break unless memo
15
- }
16
- memo
17
- end
18
- end
19
- end
20
- end