README.md in device_input-0.0.3.1 vs README.md in device_input-0.1.0.1

- old
+ new

@@ -26,18 +26,18 @@ To determine the message size, we need to know the data structure. For a long time, it was pretty simple: events are 16 bytes: * timestamp - 8 bytes -* type - 1 byte -* code - 1 byte -* value - 2 bytes +* type - 2 bytes +* code - 2 bytes +* value - 4 bytes However, this is only true for 32-bit platforms. On 64-bit platforms, event -timestamps became 16 bytes, increasing events from 16 to 24 bytes. This is -because a timestamp is defined as two `long`s, and `long`s are bigger on -64-bit platforms. It's easy to remember: +timestamps became 16 bytes, increasing the size of events from 16 to 24 bytes. +This is because a timestamp is defined (ultimately) as two `long`s, and +`long`s are bigger on 64-bit platforms. It's easy to remember: * 32-bit platform: 32-bit `long` (4 bytes) * 64-bit platform: 64-bit `long` (8 bytes) `read(/dev/input/event0, 16)` will fail on a 64-bit machine. @@ -48,18 +48,20 @@ encoded values to friendly strings for display, and provides both library and executable code to assist in examining kernel input events. # Installation -Install the gem: +Requirements: Ruby >= 2.0 +Dependencies: none + +Install the gem: ``` $ gem install device_input # sudo as necessary ``` Or, if using [Bundler](http://bundler.io/), add to your `Gemfile`: - ``` gem 'device_input', '~> 0.0' ``` # Usage @@ -69,42 +71,51 @@ ``` $ sudo devsniff /dev/input/event0 ``` When the `f` key is pressed: - ``` Misc:ScanCode:33 Key:F:1 Sync:Sync:0 ``` And released: ``` Misc:ScanCode:33 +Key:F:1 +Sync:Sync:0 +Misc:ScanCode:33 Key:F:0 Sync:Sync:0 ``` ## Library ``` require 'device_input' +# this loops forever and blocks waiting for input DeviceInput.read_from('/dev/input/event0') do |event| puts event + # break if event.time > start + 30 end ``` An event has: -* `#data` - a Struct of ints (class name Data) -* `#time` - a Time, accurate to usecs -* `#type` - a String, possibly UNK-X where X is the integer from `#data` -* `#code` - a String, possibly UNK-X-Y where X and Y are from `#data` -* `#value` - a Fixnum (signed) +* `#data`: Struct of ints (class name Data) +* `#time`: Time, accurate to usecs +* `#type`: String label, possibly `UNK-X` where X is the integer from `#data` +* `#code`: String label, possibly `UNK-X-Y` where X and Y are from `#data` +* `#value`: Fixnum (signed) from `#data` +You will probably want to write your own read loop for your own project. +[`DeviceInput.read_from`](lib/device_input.rb#L111) is very simple and can +easily be rewritten outside of this project's namespace and adapted for your +needs. + # Research ## Kernel docs * https://www.kernel.org/doc/Documentation/input/input.txt @@ -114,11 +125,10 @@ about these structs towards the end of this document. ## Kernel structs from https://www.kernel.org/doc/Documentation/input/input.txt - ``` struct input_event { struct timeval time; unsigned short type; unsigned short code; @@ -126,31 +136,28 @@ }; ``` from https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/include/uapi/linux/input.h#n25 - ``` struct input_event { struct timeval time; __u16 type; __u16 code; __s32 value; }; ``` What's a [`timeval`](https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/include/uapi/linux/time.h#n15)? - ``` struct timeval { __kernel_time_t tv_sec; /* seconds */ __kernel_suseconds_t tv_usec; /* microseconds */ }; ``` What's a [`__kernel_time_t`](https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/include/uapi/asm-generic/posix_types.h#n88)? - ``` typedef long __kernel_long_t; # ... typedef __kernel_long_t __kernel_suseconds_t; # ... @@ -158,11 +165,10 @@ ``` What's a [`__u16`](https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/include/uapi/asm-generic/int-l64.h#n23)? We're pretty sure it's an unsigned 16 bit integer. Likewise `__s32` should be a signed 32-bit integer: - ``` typedef unsigned short __u16; typedef __signed__ int __s32; ``` @@ -188,13 +194,13 @@ (8 bytes). This means that the event is 16 bytes on a 32-bit machine and 24 bytes on a 64-bit machine. Software will need to accommodate. ## Ruby tools -We can use `RbConfig` and `Array#pack`/`String#unpack` to help us read these -binary structs: - +We can use +[`RbConfig::SIZEOF`](http://idiosyncratic-ruby.com/42-ruby-config.html#rbconfigsizeof) +and `Array#pack`/`String#unpack` to help us read these binary structs: ``` FIELD C RbConfig Pack --- --- --- --- tv_sec long long l! tv_usec long long l! @@ -204,7 +210,8 @@ ``` # Acknowledgments * Inspired by https://github.com/prullmann/libdevinput (don't use it) - - also the source of the [event code labels](lib/device_input/codes.rb) + - also the source of an early version of the + [event code labels](lib/device_input/codes.rb) * Thanks to al2o3-cr from #ruby on Freenode for feedback