myhidapi 1.0.0

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.
@@ -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: []