myhidapi 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: adfdddd71f381dfa83086b83af2a81dc686adf21df076b0286e253eb002491e1
4
+ data.tar.gz: 712d3badf64f7fdae9d6e6fbb8ebfda805f1668d83539a5ac6761d9a39b9198d
5
+ SHA512:
6
+ metadata.gz: 8a965240dbb7b7a760626bf7827beded3544c13629c021cb5980674ebecea5255a8734e22093aafded0fdfcf46c17b0e8c3a2f345262d18590a74564c9c523d4
7
+ data.tar.gz: 10d73dd3d377bc809e6d670de618dfa22459197ddf076630f3732a6d3815ad66bccd6cdbcafb3509b7b73f320d8a3e7580edd6052ab3b2f2265cdb38f83fc461
@@ -0,0 +1,6 @@
1
+ === 1.0.0 / 2019-02-15
2
+
3
+ * 1 major enhancement
4
+
5
+ * Birthday!
6
+
@@ -0,0 +1,10 @@
1
+ CHANGELOG.md
2
+ Manifest.txt
3
+ README.md
4
+ Rakefile
5
+ ext/myhidapi/extconf.rb
6
+ ext/myhidapi/myhidapi.c
7
+ lib/myhidapi.rb
8
+ sample/kbprog.rb
9
+ sample/set_hsv.rb
10
+ test/test_myhidapi.rb
@@ -0,0 +1,73 @@
1
+ # MyHIDAPI
2
+
3
+ * https://github.com/tenderlove/myhidapi
4
+
5
+ ## DESCRIPTION:
6
+
7
+ This is a small wrapper around HIDAPI. I couldn't get other HIDAPI wrappers to
8
+ work, so I wrote this one. I'm using it to communicate with my keyboard, so
9
+ it really only supports enough of the HIDAPI to do that.
10
+
11
+ ## FEATURES/PROBLEMS:
12
+
13
+ * Incomplete
14
+ * No tests
15
+ * Seems to work (for me)
16
+
17
+ ## SYNOPSIS:
18
+
19
+ ```ruby
20
+ devices = MyHIDAPI.enumerate 0x0, 0x0
21
+ dev = devices.find { |dev| dev.product_string == "ErgoDox EZ" }
22
+
23
+ handle = dev.open
24
+
25
+ while !handle
26
+ p "retry"
27
+ handle = dev.open
28
+ end
29
+
30
+ p handle
31
+
32
+ buf = [0x0, 0x3, 35]
33
+ loop do
34
+ break if handle.write buf.pack('C*')
35
+ end
36
+ puts "done writing"
37
+
38
+ buf = handle.read_timeout 1, 500
39
+ p buf
40
+ ```
41
+
42
+ ## REQUIREMENTS:
43
+
44
+ This depends on libhidapi.
45
+
46
+ ## INSTALL:
47
+
48
+ * Install hidapi. On MacOS that is `brew install hidapi`
49
+
50
+ ## LICENSE:
51
+
52
+ (The MIT License)
53
+
54
+ Copyright (c) 2019 Aaron Patterson
55
+
56
+ Permission is hereby granted, free of charge, to any person obtaining
57
+ a copy of this software and associated documentation files (the
58
+ 'Software'), to deal in the Software without restriction, including
59
+ without limitation the rights to use, copy, modify, merge, publish,
60
+ distribute, sublicense, and/or sell copies of the Software, and to
61
+ permit persons to whom the Software is furnished to do so, subject to
62
+ the following conditions:
63
+
64
+ The above copyright notice and this permission notice shall be
65
+ included in all copies or substantial portions of the Software.
66
+
67
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
68
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
69
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
70
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
71
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
72
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
73
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,41 @@
1
+ # -*- ruby -*-
2
+
3
+ require 'rubygems'
4
+
5
+ tries = 0
6
+ begin
7
+ require 'hoe'
8
+ require 'minitest'
9
+ require 'rake/extensiontask'
10
+ rescue LoadError
11
+ tries += 1
12
+ Gem.install 'hoe'
13
+ Gem.install 'rake-compiler'
14
+ Gem.install 'hoe-gemspec'
15
+ Gem.install 'hoe-git'
16
+ Gem.install 'minitest'
17
+ raise unless tries < 10
18
+ retry
19
+ end
20
+
21
+ Hoe.plugin :minitest
22
+ Hoe.plugin :gemspec # `gem install hoe-gemspec`
23
+ Hoe.plugin :git # `gem install hoe-git`
24
+
25
+ HOE = Hoe.spec 'myhidapi' do
26
+ developer('Aaron Patterson', 'tenderlove@ruby-lang.org')
27
+ license "MIT"
28
+ self.readme_file = 'README.md'
29
+ self.history_file = 'CHANGELOG.md'
30
+ self.extra_rdoc_files = FileList['*.md']
31
+
32
+ self.spec_extras = {
33
+ :extensions => ["ext/myhidapi/extconf.rb"],
34
+ :required_ruby_version => '>= 2.3.0'
35
+ }
36
+ end
37
+
38
+ Rake::ExtensionTask.new("myhidapi", HOE.spec) do |ext|
39
+ end
40
+
41
+ # vim: syntax=ruby
@@ -0,0 +1,25 @@
1
+ require 'mkmf'
2
+
3
+ ldflags = cppflags = nil
4
+ if RbConfig::CONFIG["host_os"] =~ /darwin/
5
+ begin
6
+ brew_prefix = `brew --prefix hidapi`.chomp
7
+ ldflags = "#{brew_prefix}/lib"
8
+ cppflags = "#{brew_prefix}/include"
9
+ pkg_conf = "#{brew_prefix}/lib/pkgconfig"
10
+
11
+ # pkg_config should be less error prone than parsing compiler
12
+ # commandline options, but we need to set default ldflags and cpp flags
13
+ # in case the user doesn't have pkg-config installed
14
+ ENV['PKG_CONFIG_PATH'] ||= pkg_conf
15
+ rescue
16
+ end
17
+ end
18
+
19
+ pkg_config 'hidapi'
20
+
21
+ dir_config("hidapi", cppflags, ldflags)
22
+
23
+ raise "Install hidapi (brew install hidapi)" unless have_header 'hidapi.h'
24
+
25
+ create_makefile 'myhidapi'
@@ -0,0 +1,178 @@
1
+ #include <ruby.h>
2
+ #include <hidapi.h>
3
+ #include <stdlib.h>
4
+
5
+ VALUE mMyHIDAPI;
6
+ VALUE cMyHIDAPIHandle;
7
+
8
+ static void dealloc(void * ptr)
9
+ {
10
+ hid_device *handle = (hid_device *)ptr;
11
+ hid_close(handle);
12
+ }
13
+
14
+ static const rb_data_type_t myhidapi_handle_type = {
15
+ "MyHIDAPI/Handle",
16
+ {0, dealloc, 0,},
17
+ 0, 0,
18
+ #ifdef RUBY_TYPED_FREE_IMMEDIATELY
19
+ RUBY_TYPED_FREE_IMMEDIATELY,
20
+ #endif
21
+ };
22
+
23
+ #define BUF_SIZE 4096
24
+
25
+ static VALUE
26
+ rb_wcstombs(wchar_t *str)
27
+ {
28
+ char buf[BUF_SIZE];
29
+ int len;
30
+ len = wcstombs(buf, str, BUF_SIZE);
31
+ if (len > 0) {
32
+ return rb_str_new(buf, len);
33
+ } else {
34
+ return Qnil;
35
+ }
36
+ }
37
+
38
+ static VALUE
39
+ enumerate(VALUE mod, VALUE vendor_id, VALUE product_id)
40
+ {
41
+ VALUE devices;
42
+ struct hid_device_info *devs, *cur_dev;
43
+
44
+ devices = rb_ary_new();
45
+ devs = hid_enumerate(NUM2USHORT(vendor_id), NUM2USHORT(product_id));
46
+ cur_dev = devs;
47
+ while (cur_dev) {
48
+ rb_ary_push(devices, rb_funcall(mMyHIDAPI, rb_intern("build_device_info"), 8,
49
+ INT2NUM(cur_dev->vendor_id),
50
+ INT2NUM(cur_dev->product_id),
51
+ rb_str_new2(cur_dev->path),
52
+ rb_wcstombs(cur_dev->serial_number),
53
+ rb_wcstombs(cur_dev->manufacturer_string),
54
+ rb_wcstombs(cur_dev->product_string),
55
+ INT2NUM(cur_dev->usage),
56
+ INT2NUM(cur_dev->interface_number)
57
+ ));
58
+ cur_dev = cur_dev->next;
59
+ }
60
+ hid_free_enumeration(devs);
61
+
62
+ return devices;
63
+ }
64
+
65
+ static VALUE
66
+ rb_hid_open(VALUE mod, VALUE vid, VALUE pid)
67
+ {
68
+ hid_device *handle;
69
+
70
+ handle = hid_open(NUM2USHORT(vid), NUM2USHORT(pid), NULL);
71
+
72
+ if (handle) {
73
+ return TypedData_Wrap_Struct(cMyHIDAPIHandle, &myhidapi_handle_type, handle);
74
+ } else {
75
+ return Qfalse;
76
+ }
77
+ }
78
+
79
+ static VALUE
80
+ rb_hid_open_path(VALUE mod, VALUE path)
81
+ {
82
+ hid_device *handle;
83
+
84
+ handle = hid_open_path(StringValueCStr(path));
85
+
86
+ if (handle) {
87
+ return TypedData_Wrap_Struct(cMyHIDAPIHandle, &myhidapi_handle_type, handle);
88
+ } else {
89
+ return Qfalse;
90
+ }
91
+ }
92
+
93
+ static VALUE
94
+ rb_hid_write(VALUE self, VALUE str)
95
+ {
96
+ hid_device *handle;
97
+ int written;
98
+
99
+ TypedData_Get_Struct(self, hid_device, &myhidapi_handle_type, handle);
100
+
101
+ written = hid_write(handle, (unsigned char *)StringValuePtr(str), RSTRING_LEN(str));
102
+
103
+ if (written >= 0) {
104
+ return INT2NUM(written);
105
+ } else {
106
+ return Qfalse;
107
+ }
108
+ }
109
+
110
+ static VALUE
111
+ rb_hid_set_nonblocking(VALUE self, VALUE val)
112
+ {
113
+ hid_device *handle;
114
+ TypedData_Get_Struct(self, hid_device, &myhidapi_handle_type, handle);
115
+ if (!hid_set_nonblocking(handle, NUM2INT(val))) {
116
+ return Qtrue;
117
+ } else {
118
+ return Qnil;
119
+ }
120
+ }
121
+
122
+ static VALUE
123
+ rb_hid_read(VALUE self, VALUE size)
124
+ {
125
+ hid_device *handle;
126
+ unsigned char * buf;
127
+ int read;
128
+ VALUE ret;
129
+
130
+ TypedData_Get_Struct(self, hid_device, &myhidapi_handle_type, handle);
131
+
132
+ buf = xcalloc(NUM2SIZET(size), sizeof(unsigned char));
133
+
134
+ read = hid_read(handle, buf, NUM2SIZET(size));
135
+
136
+ if (read > 0) {
137
+ ret = rb_str_new((char *)buf, read);
138
+ } else {
139
+ ret = Qnil;
140
+ }
141
+ xfree(buf);
142
+ return ret;
143
+ }
144
+
145
+ static VALUE
146
+ rb_hid_read_timeout(VALUE self, VALUE size, VALUE timeout_ms)
147
+ {
148
+ hid_device *handle;
149
+ unsigned char * buf;
150
+ int read;
151
+ VALUE ret;
152
+
153
+ TypedData_Get_Struct(self, hid_device, &myhidapi_handle_type, handle);
154
+
155
+ buf = xcalloc(NUM2SIZET(size), sizeof(unsigned char));
156
+
157
+ read = hid_read_timeout(handle, buf, NUM2SIZET(size), NUM2INT(timeout_ms));
158
+
159
+ if (read > 0) {
160
+ ret = rb_str_new((char *)buf, read);
161
+ } else {
162
+ ret = Qnil;
163
+ }
164
+ xfree(buf);
165
+ return ret;
166
+ }
167
+
168
+ void Init_myhidapi() {
169
+ mMyHIDAPI = rb_define_module("MyHIDAPI");
170
+ cMyHIDAPIHandle = rb_define_class_under(mMyHIDAPI, "Handle", rb_cObject);
171
+ rb_define_singleton_method(mMyHIDAPI, "enumerate", enumerate, 2);
172
+ rb_define_singleton_method(mMyHIDAPI, "open", rb_hid_open, 2);
173
+ rb_define_singleton_method(mMyHIDAPI, "open_path", rb_hid_open_path, 1);
174
+ rb_define_method(cMyHIDAPIHandle, "write", rb_hid_write, 1);
175
+ rb_define_method(cMyHIDAPIHandle, "read", rb_hid_read, 1);
176
+ rb_define_method(cMyHIDAPIHandle, "read_timeout", rb_hid_read_timeout, 2);
177
+ rb_define_method(cMyHIDAPIHandle, "set_nonblocking", rb_hid_set_nonblocking, 1);
178
+ }
@@ -0,0 +1,28 @@
1
+ require "myhidapi.so"
2
+
3
+ module MyHIDAPI
4
+ VERSION = '1.0.0'
5
+
6
+ class DeviceInfo
7
+ attr_reader :vendor_id, :product_id, :path, :serial_number, :manufacturer_string, :product_string, :usage, :interface_number
8
+
9
+ def initialize vendor_id, product_id, path, serial_number, manufacturer_string, product_string, usage, interface_number
10
+ @vendor_id = vendor_id
11
+ @product_id = product_id
12
+ @path = path
13
+ @serial_number = serial_number
14
+ @manufacturer_string = manufacturer_string
15
+ @product_string = product_string
16
+ @usage = usage
17
+ @interface_number = interface_number
18
+ end
19
+
20
+ def open
21
+ MyHIDAPI.open vendor_id, product_id
22
+ end
23
+ end
24
+
25
+ def self.build_device_info(*args)
26
+ DeviceInfo.new(*args)
27
+ end
28
+ end
@@ -0,0 +1,190 @@
1
+ require 'myhidapi'
2
+ require 'optparse'
3
+
4
+ class TeeloKB
5
+ class Error < StandardError; end
6
+ class CouldNotReadError < Error; end
7
+ class KeyboardNotFoundError < Error; end
8
+
9
+ COMMAND_VERSIONS = { 1 => {} }
10
+
11
+ %i{
12
+ version
13
+ rgblight_enable
14
+ rgblight_disable
15
+ rgblight_toggle
16
+ rgblight_mode
17
+ rgblight_sethsv
18
+ rgblight_get_mode
19
+ rgblight_get_hue
20
+ rgblight_get_sat
21
+ rgblight_get_val
22
+ }.each_with_index do |command, index|
23
+ COMMAND_VERSIONS[1][command] = index + 1
24
+ end
25
+
26
+ def self.find
27
+ MyHIDAPI.enumerate(0x0, 0x0).find { |dev| dev.product_string == "ErgoDox EZ" }
28
+ end
29
+
30
+ def self.open
31
+ dev = self.find
32
+
33
+ retries = 0
34
+ handle = dev.open
35
+ while !handle
36
+ retries += 1
37
+ raise KeyboardNotFoundError, "Couldn't find keyboard" if retries > 10
38
+ handle = dev.open
39
+ end
40
+
41
+ new handle
42
+ end
43
+
44
+ def initialize handle
45
+ @handle = handle
46
+ @version = protocol_version
47
+ end
48
+
49
+ def protocol_version
50
+ write [0x0, 0x1]
51
+ read(2).inject(:+)
52
+ end
53
+
54
+ def solid
55
+ rgblight_mode 0x1
56
+ end
57
+
58
+ def enable
59
+ write [0x0, _(:rgblight_enable)]
60
+ read 10
61
+ end
62
+
63
+ def disable
64
+ write [0x0, _(:rgblight_disable)]
65
+ read 10
66
+ end
67
+
68
+ def toggle
69
+ write [0x0, _(:rgblight_toggle)]
70
+ read 10
71
+ end
72
+
73
+ def mode
74
+ write [0x0, _(:rgblight_get_mode)]
75
+ read(2).last
76
+ end
77
+
78
+ def rainbow style = 0x6
79
+ rgblight_mode style
80
+ end
81
+
82
+ def rgblight_mode value
83
+ write [0x0, _(:rgblight_mode), value & 0xFF]
84
+ read 10
85
+ end
86
+ alias :mode= :rgblight_mode
87
+
88
+ def rgblight_sethsv h, s, v
89
+ write([0x0, _(:rgblight_sethsv)] + [(h >> 8) & 0xFF, h & 0xFF, s & 0xFF, v & 0xFF])
90
+ read 10
91
+ end
92
+ alias :sethsv :rgblight_sethsv
93
+
94
+ def setrgb r, g, b
95
+ sethsv *rgb2hsv(r, g, b)
96
+ end
97
+
98
+ def hue
99
+ write [0x0, _(:rgblight_get_hue)]
100
+ _, upper, lower = read 3
101
+ (upper << 8) | lower
102
+ end
103
+
104
+ def saturation
105
+ write [0x0, _(:rgblight_get_sat)]
106
+ read(2)[1]
107
+ end
108
+
109
+ def value
110
+ write [0x0, _(:rgblight_get_val)]
111
+ read(2)[1]
112
+ end
113
+
114
+ def hsv
115
+ [hue, saturation, value]
116
+ end
117
+
118
+ private
119
+
120
+ def rgb2hsv r, g, b
121
+ v = [r, g, b].max
122
+ delta = v - [r, g, b].min
123
+
124
+ s = v == 0 ? 0 : (delta / v.to_f)
125
+ h = delta == 0 ? 0 : (case v
126
+ when r then ((g - b) / delta) % 6
127
+ when g then ((b - r) / delta) + 2
128
+ when b then ((r - g) / delta) + 4
129
+ end) * 60
130
+
131
+ [h.round, (s * 255).round, v]
132
+ end
133
+
134
+ def write buf
135
+ loop do
136
+ break if @handle.write buf.pack('C*')
137
+ end
138
+ end
139
+
140
+ def read size
141
+ buf = @handle.read_timeout size, 300 # 300 ms timeout
142
+ if buf
143
+ buf.unpack('C*')
144
+ else
145
+ # Unfortunately, this seems to happen frequently.
146
+ raise CouldNotReadError, "could not read from device"
147
+ end
148
+ end
149
+
150
+ def _ command
151
+ COMMAND_VERSIONS.fetch(@version).fetch(command)
152
+ end
153
+ end
154
+
155
+ commands = []
156
+ responses = []
157
+
158
+ OptionParser.new do |opts|
159
+ opts.banner = "Usage: kbprog.rb [options]"
160
+
161
+ opts.on("--hsv=[HSV]", "Set or get HSV (comma separated)") do |v|
162
+ if v
163
+ commands << lambda { |kb| kb.sethsv(*v.split(",").map(&:to_i)) }
164
+ else
165
+ commands << lambda { |kb| responses << { hsv: kb.hsv } }
166
+ end
167
+ end
168
+ opts.on("--mode=[HSV]", "Set or get mode") do |v|
169
+ if v
170
+ commands << lambda { |kb| kb.mode = v.to_i }
171
+ else
172
+ commands << lambda { |kb| responses << { mode: kb.mode } }
173
+ end
174
+ end
175
+ end.parse!
176
+
177
+ kb = TeeloKB.open
178
+ commands.each { |cmd| cmd.call kb }
179
+ responses.each do |res|
180
+ p res
181
+ end
182
+
183
+ #p ez.mode
184
+ #ez.mode = 5
185
+ #ez.sethsv 300, 250, 255
186
+ #p ez.hsv
187
+
188
+ #rescue TeeloKB::Error => e
189
+ # exec "ruby --disable-gems -I lib:test #{__FILE__}"
190
+ #end
@@ -0,0 +1,21 @@
1
+ require 'myhidapi'
2
+
3
+ def try_block times
4
+ times.times { x = yield; return x if x }
5
+ raise "Couldn't do it"
6
+ end
7
+
8
+ dev = MyHIDAPI.enumerate(0x0, 0x0).find { |dev| dev.product_string == "ErgoDox EZ" }
9
+
10
+ handle = try_block(10) { dev.open }
11
+ p handle
12
+
13
+ h = 0 # 0x0 to 0x168 (which is 360 base 10)
14
+ s = 0xFF # 0x0 to 0xFF
15
+ v = 0xFF # 0x0 to 0xFF
16
+
17
+ try_block(10) do
18
+ handle.write [0x0, 0x6, (h >> 8) & 0xFF, h & 0xFF, s, v].pack('C*')
19
+ end
20
+
21
+ handle.read_timeout 10, 300 # 300 ms timeout
@@ -0,0 +1,33 @@
1
+ require 'minitest/autorun'
2
+ require 'myhidapi'
3
+
4
+ class TestMyHIDAPI < MiniTest::Test
5
+ def test_it_works
6
+ devices = MyHIDAPI.enumerate 0x0, 0x0
7
+ dev = devices.find { |dev| dev.product_string == "ErgoDox EZ" }
8
+
9
+ handle = dev.open
10
+
11
+ while !handle
12
+ p "retry"
13
+ handle = dev.open
14
+ end
15
+
16
+ p handle
17
+
18
+ buf = [0x0, 0x3, 35]
19
+ loop do
20
+ break if handle.write buf.pack('C*')
21
+ end
22
+ puts "done writing"
23
+
24
+ buf = handle.read_timeout 1, 500
25
+ p buf
26
+ end
27
+
28
+ def test_can_enumerate_by_ids
29
+ devices = MyHIDAPI.enumerate(0xfeed, 0x1307)
30
+
31
+ refute_predicate devices, :empty?
32
+ end
33
+ end
metadata ADDED
@@ -0,0 +1,110 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: myhidapi
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Aaron Patterson
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2019-06-10 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: minitest
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '5.11'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '5.11'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rdoc
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '4.0'
34
+ - - "<"
35
+ - !ruby/object:Gem::Version
36
+ version: '7'
37
+ type: :development
38
+ prerelease: false
39
+ version_requirements: !ruby/object:Gem::Requirement
40
+ requirements:
41
+ - - ">="
42
+ - !ruby/object:Gem::Version
43
+ version: '4.0'
44
+ - - "<"
45
+ - !ruby/object:Gem::Version
46
+ version: '7'
47
+ - !ruby/object:Gem::Dependency
48
+ name: hoe
49
+ requirement: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - "~>"
52
+ - !ruby/object:Gem::Version
53
+ version: '3.17'
54
+ type: :development
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - "~>"
59
+ - !ruby/object:Gem::Version
60
+ version: '3.17'
61
+ description: |-
62
+ This is a small wrapper around HIDAPI. I couldn't get other HIDAPI wrappers to
63
+ work, so I wrote this one. I'm using it to communicate with my keyboard, so
64
+ it really only supports enough of the HIDAPI to do that.
65
+ email:
66
+ - tenderlove@ruby-lang.org
67
+ executables: []
68
+ extensions:
69
+ - ext/myhidapi/extconf.rb
70
+ extra_rdoc_files:
71
+ - CHANGELOG.md
72
+ - Manifest.txt
73
+ - README.md
74
+ files:
75
+ - CHANGELOG.md
76
+ - Manifest.txt
77
+ - README.md
78
+ - Rakefile
79
+ - ext/myhidapi/extconf.rb
80
+ - ext/myhidapi/myhidapi.c
81
+ - lib/myhidapi.rb
82
+ - sample/kbprog.rb
83
+ - sample/set_hsv.rb
84
+ - test/test_myhidapi.rb
85
+ homepage: https://github.com/tenderlove/myhidapi
86
+ licenses:
87
+ - MIT
88
+ metadata: {}
89
+ post_install_message:
90
+ rdoc_options:
91
+ - "--main"
92
+ - README.md
93
+ require_paths:
94
+ - lib
95
+ required_ruby_version: !ruby/object:Gem::Requirement
96
+ requirements:
97
+ - - ">="
98
+ - !ruby/object:Gem::Version
99
+ version: 2.3.0
100
+ required_rubygems_version: !ruby/object:Gem::Requirement
101
+ requirements:
102
+ - - ">="
103
+ - !ruby/object:Gem::Version
104
+ version: '0'
105
+ requirements: []
106
+ rubygems_version: 3.0.1
107
+ signing_key:
108
+ specification_version: 4
109
+ summary: This is a small wrapper around HIDAPI
110
+ test_files: []