-
Notifications
You must be signed in to change notification settings - Fork 11
Expand file tree
/
Copy pathdevice.rb
More file actions
111 lines (92 loc) · 2.52 KB
/
device.rb
File metadata and controls
111 lines (92 loc) · 2.52 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
require 'ffi'
module HidApi
class Device < FFI::Pointer
extend FFI::DataConverter
native_type FFI::Type::POINTER
def self.from_native(value, ctx)
new(value)
end
def close
HidApi.close(self)
end
def set_nonblocking(int)
HidApi.hid_set_nonblocking self, int
end
def get_manufacturer_string
get_buffered_string :manufacturer
end
def get_product_string
get_buffered_string :product
end
def get_serial_number_string
get_buffered_string :serial_number
end
def read(length)
buffer = clear_buffer length
with_hid_error_handling do
HidApi.hid_read self, buffer, buffer.length
end
buffer
end
def read_timeout(length, timeout)
buffer = clear_buffer length
with_hid_error_handling do
HidApi.hid_read_timeout self, buffer, buffer.length, timeout
end
buffer
end
def write(data)
buffer = clear_buffer data.length
case data
when String then buffer.put_bytes 0, data
when Array then buffer.put_array_of_char 0, data
end
with_hid_error_handling do
HidApi.hid_write self, buffer, buffer.length
end
end
def get_feature_report(data)
buffer = clear_buffer data.length
case data
when String then buffer.put_bytes 0, data
when Array then buffer.put_array_of_char 0, data
end
with_hid_error_handling do
HidApi.hid_get_feature_report self, buffer, buffer.length
end
end
def send_feature_report(data)
buffer = clear_buffer data.length
case data
when String then buffer.put_bytes 0, data
when Array then buffer.put_array_of_char 0, data
end
with_hid_error_handling do
HidApi.hid_send_feature_report self, buffer, buffer.length
end
end
def error
# NOTE: hid_error is only implemented on Windows systems and returns nil
# on other platforms
HidApi.hid_error(self)
end
private
def clear_buffer length
b = FFI::Buffer.new(1, length)
# FFI::Buffer doesn't clear the first byte if length < 8
b.put_char 0, 0
b
end
def get_buffered_string field
buffer = clear_buffer 255
HidApi.send "hid_get_#{field}_string", self, buffer, buffer.length
buffer.read_wchar_string
end
def with_hid_error_handling
raise ArgumentError, "Block required" unless block_given?
yield.tap do |result|
raise HidError, error if result == -1
end
end
end
end