linux_stat 0.9.2 → 1.1.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,196 @@
1
+ module LinuxStat
2
+ module USB
3
+ class << self
4
+ ##
5
+ # = devices_stat(hwdata: true)
6
+ #
7
+ # Returns details about the devices found in /sys/bus/usb/devices/
8
+ #
9
+ # The return value is an Array of multiple Hashes. If there's no info available,
10
+ # it will rather return an empty Array.
11
+ #
12
+ # On Android Termux for example, it can not list the directories because they are
13
+ # not readable the the regular user.
14
+ #
15
+ # It can have information like:
16
+ #
17
+ # path, id, vendor id, product id, manufacturer, serial, bus number, dev number,
18
+ # b_max_power, b_max_packet_size, etc.
19
+ #
20
+ # An example of the returned sample from a test machine is:
21
+ # LinuxStat::USB.devices_stat
22
+ #
23
+ # => [{:path=>"/sys/bus/usb/devices/1-1.2/", :id=>"04d9:1203", :vendor_id=>"04d9", :product_id=>"1203", :bus_num=>1, :dev_num=>4, :hwdata=>{:vendor=>"Holtek Semiconductor, Inc.", :product=>"Keyboard"}, :authorized=>true, :b_max_power=>"100mA", :b_max_packet_size0=>8}
24
+ #
25
+ # Right, it's an array of Hashes.
26
+ #
27
+ # It also takes one option. The hwdata, which is true by default.
28
+ #
29
+ # Information about usb devices is found inside /usr/share/hwdata/usb.ids
30
+ #
31
+ # The data contains the vendor and the product.
32
+ #
33
+ # If the option is enabled, it will try look at /usr/share/hwdata/usb.ids
34
+ #
35
+ # But the file will be read only once. The consecutive calls to this method
36
+ # won't open the hwdata all the times.
37
+ #
38
+ # But if there's no hwdata, the Hash returned by this method will not contain
39
+ # hwdata key.
40
+ #
41
+ # The data is only populated if it's available. For example, if there's no
42
+ # manufacturer available for the product, the returned Hash will not contain the
43
+ # information about the manufacturer.
44
+ #
45
+ # Also note that if there's no info available or no USB devices, it will return an empty
46
+ # Hash.
47
+ def devices_stat(hwdata: true)
48
+ @@sys_usb_readable ||= File.readable?('/sys/bus/usb/devices/')
49
+ return [] unless @@sys_usb_readable
50
+
51
+ Dir['/sys/bus/usb/devices/*/'.freeze].sort!.map! { |x|
52
+ id_vendor_file = File.join(x, 'idVendor'.freeze)
53
+ next unless File.readable?(id_vendor_file)
54
+ id_vendor = IO.read(id_vendor_file).strip
55
+
56
+ id_product_file = File.join(x, 'idProduct'.freeze)
57
+ next unless File.readable?(id_vendor_file)
58
+ id_product = IO.read(id_product_file).strip
59
+
60
+ bus_num_file = File.join(x, 'busnum'.freeze)
61
+ bus_num = File.readable?(bus_num_file) ? IO.read(bus_num_file).strip : ''.freeze
62
+
63
+ dev_num_file = File.join(x, 'devnum'.freeze)
64
+ dev_num = File.readable?(dev_num_file) ? IO.read(dev_num_file).strip : ''.freeze
65
+
66
+ serial_file = File.join(x, 'serial'.freeze)
67
+ serial = File.readable?(serial_file) ? IO.read(serial_file).strip : ''.freeze
68
+
69
+ product_file = File.join(x, 'product'.freeze)
70
+ product = File.readable?(product_file) ? IO.read(product_file).strip : ''.freeze
71
+
72
+ manufacturer_file = File.join(x, 'manufacturer'.freeze)
73
+ manufacturer = File.readable?(manufacturer_file) ? IO.read(manufacturer_file).strip : ''.freeze
74
+
75
+ removable_file = File.join(x, 'removable'.freeze)
76
+ removable = File.readable?(removable_file) ? IO.read(removable_file).strip : ''.freeze
77
+
78
+ authorized_file = File.join(x, 'authorized'.freeze)
79
+ authorized = File.readable?(authorized_file) ? IO.read(authorized_file).to_i : ''.freeze
80
+
81
+ b_max_power_file = File.join(x, 'bMaxPower'.freeze)
82
+ b_max_power = File.readable?(b_max_power_file) ? IO.read(b_max_power_file).strip : ''.freeze
83
+
84
+ b_max_packet_size0_file = File.join(x, 'bMaxPacketSize0'.freeze)
85
+ b_max_packet_size0 = File.readable?(b_max_packet_size0_file) ? IO.read(b_max_packet_size0_file).to_i : ''.freeze
86
+
87
+ query = hwdata ? query_hwdata(id_vendor, id_product) : {}
88
+
89
+ removable.downcase!
90
+ is_removable = if removable == 'removable'.freeze
91
+ true
92
+ elsif removable == 'unknown'.freeze
93
+ nil
94
+ else
95
+ false
96
+ end
97
+
98
+ ret = {
99
+ path: x, id: "#{id_vendor}:#{id_product}",
100
+ vendor_id: id_vendor, product_id: id_product
101
+ }
102
+
103
+ ret.merge!(bus_num: bus_num.to_i) unless bus_num.empty?
104
+ ret.merge!(dev_num: dev_num.to_i) unless dev_num.empty?
105
+
106
+ ret.merge!(serial: serial) unless serial.empty?
107
+
108
+ ret.merge!(hwdata: query) unless query.empty?
109
+ ret.merge!(product: product) unless product.empty?
110
+ ret.merge!(manufacturer: manufacturer) unless manufacturer.empty?
111
+
112
+ ret.merge!(removable: is_removable) unless is_removable.nil?
113
+ ret.merge!(authorized: authorized == 1)
114
+
115
+ ret.merge!(b_max_power: b_max_power) unless b_max_power.empty?
116
+ ret.merge!(b_max_packet_size0: b_max_packet_size0) if b_max_packet_size0
117
+
118
+ ret
119
+ }.tap(&:compact!)
120
+ end
121
+
122
+ ##
123
+ # Opens /sys/bus/usb/devices, and counts the total number of
124
+ # devices connected to the USB interface.
125
+ # The return type is an integer.
126
+ #
127
+ # It checks for devices with vendor and product id file.
128
+ # If there's no such file, it will not count them as a USB device.
129
+ #
130
+ # It could be also an integrated hub or a webcam, as well as
131
+ # external hotpluggable devices like printer, USB storage devices,
132
+ # USB mouse, USB keyboard, USB joypad etc.
133
+ #
134
+ # But if the information isn't available, it will return nil.
135
+ def count
136
+ @@sys_usb_readable ||= File.readable?('/sys/bus/usb/devices/')
137
+ return nil unless @@sys_usb_readable
138
+
139
+ Dir['/sys/bus/usb/devices/*/'.freeze].count { |x|
140
+ id_vendor_file = File.join(x, 'idVendor'.freeze)
141
+ id_product_file = File.join(x, 'idProduct'.freeze)
142
+ File.readable?(id_vendor_file) && File.readable?(id_product_file)
143
+ }
144
+ end
145
+
146
+ alias count_devices count
147
+
148
+ private
149
+ def hwdata
150
+ @@hwdata_file ||= "/usr/share/hwdata/usb.ids"
151
+
152
+ @@hwdata ||= if File.readable?(@@hwdata_file)
153
+ file_data = IO.readlines(@@hwdata_file, encoding: 'ASCII-8BIT')
154
+ ret, vendor_id = {}, nil
155
+
156
+ i = -1
157
+ file_data_size = file_data.size
158
+
159
+ while (i += 1) < file_data_size
160
+ x = file_data[i]
161
+
162
+ _lstripped = x.lstrip
163
+ next if _lstripped[0] == ?#.freeze || _lstripped.empty?
164
+
165
+ if x[0] == ?\t.freeze
166
+ next unless vendor_id
167
+
168
+ x.strip!
169
+ device_id = x[/\A.*?\s/].to_s.strip
170
+ device = x[device_id.length..-1].to_s.strip
171
+ ret[vendor_id][1][device_id] = device
172
+ else
173
+ x.strip!
174
+ vendor_id = x[/\A.*?\s/].to_s.strip
175
+ vendor = x[vendor_id.length..-1].to_s.strip
176
+ ret[vendor_id] = [vendor, {}]
177
+ end
178
+ end
179
+
180
+ ret.freeze
181
+ else
182
+ {}
183
+ end
184
+ end
185
+
186
+ def query_hwdata(vendor_id, product_id)
187
+ vendor = hwdata[vendor_id]
188
+ if vendor
189
+ {vendor: vendor[0], product: vendor[1][product_id]}
190
+ else
191
+ {}
192
+ end
193
+ end
194
+ end
195
+ end
196
+ end
@@ -1,3 +1,3 @@
1
1
  module LinuxStat
2
- VERSION ||= "0.9.2"
2
+ VERSION ||= "1.1.0"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: linux_stat
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.2
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sourav Goswami
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-12-22 00:00:00.000000000 Z
11
+ date: 2020-12-26 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: Linux only, efficient linux system utilization reporting and system monitoring
14
14
  gem
@@ -18,9 +18,9 @@ executables:
18
18
  - linuxstat.rb
19
19
  extensions:
20
20
  - ext/fs_stat/extconf.rb
21
+ - ext/nproc/extconf.rb
21
22
  - ext/sysconf/extconf.rb
22
23
  - ext/utsname/extconf.rb
23
- - ext/nproc/extconf.rb
24
24
  extra_rdoc_files:
25
25
  - README.md
26
26
  files:
@@ -47,10 +47,12 @@ files:
47
47
  - lib/linux_stat/mounts.rb
48
48
  - lib/linux_stat/net.rb
49
49
  - lib/linux_stat/os.rb
50
+ - lib/linux_stat/pci.rb
50
51
  - lib/linux_stat/prettify_bytes.rb
51
52
  - lib/linux_stat/process.rb
52
53
  - lib/linux_stat/process_info.rb
53
54
  - lib/linux_stat/swap.rb
55
+ - lib/linux_stat/usb.rb
54
56
  - lib/linux_stat/user.rb
55
57
  - lib/linux_stat/version.rb
56
58
  homepage: https://github.com/Souravgoswami/linux_stat/