Class: ComputeUnit::Device
- Inherits:
-
Object
- Object
- ComputeUnit::Device
- Includes:
- Utils
- Defined in:
- lib/compute_unit/device.rb
Direct Known Subclasses
Constant Summary collapse
- SYSFS_DEVICES_PATH =
We can supply a mock sysfs path in order to test with containers and other scenarios
File.join(ComputeUnit::SYSFS_PATH, 'bus', 'pci', 'devices')
- PROC_PATH =
ENV['PROC_PATH'] || '/proc'
Instance Attribute Summary collapse
-
#device_class_id ⇒ Object
readonly
Returns the value of attribute device_class_id.
-
#device_id ⇒ Object
readonly
Returns the value of attribute device_id.
-
#device_path ⇒ Object
readonly
Returns the value of attribute device_path.
-
#device_vendor_id ⇒ Object
readonly
Returns the value of attribute device_vendor_id.
-
#make ⇒ String
readonly
-
the name of the vendor who made the device.
-
-
#model ⇒ String
readonly
-
the name of the device model (specific name).
-
-
#subsystem_device_id ⇒ Object
readonly
Returns the value of attribute subsystem_device_id.
-
#subsystem_vendor_id ⇒ Object
readonly
Returns the value of attribute subsystem_vendor_id.
-
#vendor ⇒ String
readonly
-
the name of the vendor who resold the device.
-
Class Method Summary collapse
-
.create_from_path(device_path) ⇒ Device
-
creates a device from the given path.
-
-
.device(device_path) ⇒ String
-
the device number ie.
-
-
.device_class(device_path) ⇒ String
-
the class number ie.
-
-
.device_lookup(device_id) ⇒ String
queries the pci_database that is shipped with this gem and looks up the device.
-
.device_vendor(device_path) ⇒ String
-
the vendor number ie.
-
-
.find_all(device_class_id = nil) ⇒ Array
-
an array of pci bus device locations (every device on the pci bus).
-
- .logger ⇒ Object
- .manual_device_database ⇒ Object
- .manual_device_lookup(device_id, subsystem_device_id, vendor_id) ⇒ Object
-
.manual_vendor_lookup(id) ⇒ String
-
return the string of the device vendor.
-
-
.manual_vendors ⇒ Hash
-
a hash of vendors names and ids.
-
-
.name_map ⇒ Hash
sometimes we just wamnt a shorter name to see.
-
.name_translation(name) ⇒ String
-
translation of vendor names to how we known them.
-
-
.pci_database ⇒ Array
Syntax: vendor vendor_name device device_name <– single tab subvendor subdevice subsystem_name <– two tabs.
-
.read_kernel_setting(device_path, setting, default = 0) ⇒ String
-
read a kernel setting using the device_path.
-
-
.subsystem_device(device_path) ⇒ String
-
the device number ie.
-
-
.subsystem_device_lookup(device_id, subsystem_device_id, vendor_id) ⇒ String
-
the name of the device.
-
-
.subsystem_vendor(device_path) ⇒ String
example: XFX is the reseller of the AMD chips.
-
.subsystem_vendor_lookup(vendor_id) ⇒ String
-
the name of the subsystem vendor with a possible translation.
-
-
.system_checksum ⇒ String
-
a sha1 digest that represents the pci devices found on the system.
-
-
.vendor_lookup(vendor_id) ⇒ String
-
the name of the subsystem vendor with a possible translation.
-
-
.write_kernel_setting(device_path, setting, value) ⇒ String
-
read a kernel setting using the device_path.
-
Instance Method Summary collapse
-
#base_hwmon_path ⇒ String
-
base hwmon path of the device.
-
- #expired_metadata? ⇒ Boolean
-
#generic_model ⇒ String
-
the name of the device model (sometimes not specific).
-
-
#hwmon_path ⇒ String
-
the directory path to the hwmon dir for this device.
-
-
#initialize(device_path, opts = {}) ⇒ Device
constructor
A new instance of Device.
-
#lock_rom ⇒ String
must be root.
- #read_file(path, default = nil) ⇒ Object
-
#read_hwmon_data(item, default = nil) ⇒ String
-
the value of the item looked up.
-
-
#read_kernel_setting(setting, default = 0) ⇒ String
-
read a kernel setting using the device_path.
-
-
#rom_data ⇒ String::IO
-
the contents of the rom file.
-
-
#rom_path ⇒ String
-
the path to the rom file if available.
-
-
#sysfs_model_name ⇒ String
-
the name of the device model (specific name).
-
- #to_h ⇒ Object
- #to_json(c = nil) ⇒ Object
-
#unlock_rom ⇒ String
must be root.
- #write_hwmon_data(item, value) ⇒ Object
-
#write_kernel_setting(setting, value) ⇒ String
-
a reading of the kernel setting using the device_path.
-
Methods included from Utils
Constructor Details
#initialize(device_path, opts = {}) ⇒ Device
Returns a new instance of Device.
26 27 28 29 30 31 32 33 |
# File 'lib/compute_unit/device.rb', line 26 def initialize(device_path, opts = {}) @device_path = device_path @device_class_id = opts[:device_class_id] @device_id = opts[:device_id] @device_vendor_id = opts[:device_vendor_id] @subsystem_vendor_id = opts[:subsystem_vendor_id] @subsystem_device_id = opts[:subsystem_device_id] end |
Instance Attribute Details
#device_class_id ⇒ Object (readonly)
Returns the value of attribute device_class_id.
14 15 16 |
# File 'lib/compute_unit/device.rb', line 14 def device_class_id @device_class_id end |
#device_id ⇒ Object (readonly)
Returns the value of attribute device_id.
14 15 16 |
# File 'lib/compute_unit/device.rb', line 14 def device_id @device_id end |
#device_path ⇒ Object (readonly)
Returns the value of attribute device_path.
14 15 16 |
# File 'lib/compute_unit/device.rb', line 14 def device_path @device_path end |
#device_vendor_id ⇒ Object (readonly)
Returns the value of attribute device_vendor_id.
14 15 16 |
# File 'lib/compute_unit/device.rb', line 14 def device_vendor_id @device_vendor_id end |
#make ⇒ String (readonly)
Returns - the name of the vendor who made the device.
87 88 89 |
# File 'lib/compute_unit/device.rb', line 87 def make @make end |
#model ⇒ String (readonly)
Returns - the name of the device model (specific name).
114 115 116 |
# File 'lib/compute_unit/device.rb', line 114 def model @model end |
#subsystem_device_id ⇒ Object (readonly)
Returns the value of attribute subsystem_device_id.
14 15 16 |
# File 'lib/compute_unit/device.rb', line 14 def subsystem_device_id @subsystem_device_id end |
#subsystem_vendor_id ⇒ Object (readonly)
Returns the value of attribute subsystem_vendor_id.
14 15 16 |
# File 'lib/compute_unit/device.rb', line 14 def subsystem_vendor_id @subsystem_vendor_id end |
#vendor ⇒ String (readonly)
Returns - the name of the vendor who resold the device.
95 96 97 |
# File 'lib/compute_unit/device.rb', line 95 def vendor @vendor end |
Class Method Details
.create_from_path(device_path) ⇒ Device
Returns - creates a device from the given path.
183 184 185 186 187 188 189 190 191 192 |
# File 'lib/compute_unit/device.rb', line 183 def self.create_from_path(device_path) opts = { device_class_id: device_class(device_path), device_id: device(device_path), device_vendor_id: device_vendor(device_path), subsystem_vendor_id: subsystem_vendor(device_path), subsystem_device_id: subsystem_device(device_path) } new(device_path, opts) end |
.device(device_path) ⇒ String
Returns - the device number ie. 1002.
246 247 248 |
# File 'lib/compute_unit/device.rb', line 246 def self.device(device_path) read_kernel_setting(device_path, 'device', '').slice(2, 6) end |
.device_class(device_path) ⇒ String
helps determine what kind of device this is ie. graphics, storage, …
Returns - the class number ie. 040300.
257 258 259 |
# File 'lib/compute_unit/device.rb', line 257 def self.device_class(device_path) read_kernel_setting(device_path, 'class', '').slice(2, 8) end |
.device_lookup(device_id) ⇒ String
queries the pci_database that is shipped with this gem and looks up the device
382 383 384 385 386 387 388 389 390 391 392 393 394 |
# File 'lib/compute_unit/device.rb', line 382 def self.device_lookup(device_id) # "\t687f Vega 10 XT [Radeon RX Vega 64]\n" re = Regexp.new(/\A\t#{device_id}/) d = pci_database.find do |line| re.match(line) rescue ArgumentError next end return d unless d name = d[/\t\w+\s+(.*)\n/, 1] name[/.*\[(.*)\]/, 1] || name if name end |
.device_vendor(device_path) ⇒ String
Returns - the vendor number ie. 1002.
251 252 253 |
# File 'lib/compute_unit/device.rb', line 251 def self.device_vendor(device_path) read_kernel_setting(device_path, 'vendor', '').slice(2, 6) end |
.find_all(device_class_id = nil) ⇒ Array
there is not a filter applied
Returns - an array of pci bus device locations (every device on the pci bus).
197 198 199 200 201 202 |
# File 'lib/compute_unit/device.rb', line 197 def self.find_all(device_class_id = nil) Dir.glob(File.join(ComputeUnit::Device::SYSFS_DEVICES_PATH, '*')).map do |device_path| next create_from_path(device_path) unless device_class_id next create_from_path(device_path) if device_class(device_path) == device_class_id end.compact end |
.logger ⇒ Object
396 397 398 |
# File 'lib/compute_unit/device.rb', line 396 def self.logger ComputeUnit::Logger.logger end |
.manual_device_database ⇒ Object
315 316 317 318 319 |
# File 'lib/compute_unit/device.rb', line 315 def self.manual_device_database @manual_device_database ||= { '687f_0b36_1002' => 'Radeon RX Vega 64' } end |
.manual_device_lookup(device_id, subsystem_device_id, vendor_id) ⇒ Object
321 322 323 324 |
# File 'lib/compute_unit/device.rb', line 321 def self.manual_device_lookup(device_id, subsystem_device_id, vendor_id) key = "#{device_id}_#{subsystem_device_id}_#{vendor_id}" manual_device_database.fetch(key, nil) end |
.manual_vendor_lookup(id) ⇒ String
Returns - return the string of the device vendor.
360 361 362 |
# File 'lib/compute_unit/device.rb', line 360 def self.manual_vendor_lookup(id) manual_vendors[id] end |
.manual_vendors ⇒ Hash
Returns - a hash of vendors names and ids.
354 355 356 |
# File 'lib/compute_unit/device.rb', line 354 def self.manual_vendors @manual_vendors ||= { '196e' => 'PNY' } end |
.name_map ⇒ Hash
sometimes we just wamnt a shorter name to see
211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 |
# File 'lib/compute_unit/device.rb', line 211 def self.name_map @name_map ||= { 'ASUSTeK COMPUTER INC.' => 'Asus', 'ASUSTeK Computer Inc.' => 'Asus', 'Advanced Micro Devices, Inc. [AMD/ATI]' => 'AMD', 'XFX Pine Group Inc.' => 'XFX', 'NVIDIA Corporation' => 'Nvidia', 'Gigabyte Technology Co., Ltd' => 'Gigabyte', 'Sapphire Technology Limited' => 'Sapphire', 'eVga.com. Corp.' => 'Evga', 'Micro-Star International Co., Ltd. [MSI]' => 'MSI', 'Micro-Star International Co., Ltd.' => 'MSI', 'Intel Corporation' => 'Intel', 'ASMedia Technology Inc.' => 'AsMedia Tech', 'Advanced Micro Devices, Inc. [AMD]' => 'AMD', 'Tul Corporation / PowerColor' => 'PowerColor', 'PC Partner Limited / Sapphire Technology' => 'Sapphire', 'Realtek Semiconductor Co., Ltd.' => 'Realtek', 'Samsung Electronics Co Ltd' => 'Samsung', 'ZOTAC International (MCO) Ltd.' => 'Zotac' } end |
.name_translation(name) ⇒ String
Returns - translation of vendor names to how we known them.
205 206 207 |
# File 'lib/compute_unit/device.rb', line 205 def self.name_translation(name) name_map[name] || name end |
.pci_database ⇒ Array
Syntax: vendor vendor_name
device device_name <-- single tab
subvendor subdevice subsystem_name <-- two tabs
309 310 311 312 313 |
# File 'lib/compute_unit/device.rb', line 309 def self.pci_database @pci_database ||= begin IO.foreach(ComputeUnit::PCI_DATABASE_PATH).lazy end end |
.read_kernel_setting(device_path, setting, default = 0) ⇒ String
Returns - read a kernel setting using the device_path.
265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 |
# File 'lib/compute_unit/device.rb', line 265 def self.read_kernel_setting(device_path, setting, default = 0) path = File.join(device_path, setting) logger.debug("reading kernel file #{path}") value = begin File.read(path).chomp rescue Errno::EINVAL, Errno::EPERM logger.fatal(e.) default rescue Errno::ENOENT logger.debug("File #{path} does not exist") default rescue Errno::EACCES logger.fatal('Run this command as root or with sudo') default end end |
.subsystem_device(device_path) ⇒ String
Returns - the device number ie. 1002 (can be different from vendor).
235 236 237 |
# File 'lib/compute_unit/device.rb', line 235 def self.subsystem_device(device_path) read_kernel_setting(device_path, 'subsystem_device', '').slice(2, 6) end |
.subsystem_device_lookup(device_id, subsystem_device_id, vendor_id) ⇒ String
Returns - the name of the device.
330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 |
# File 'lib/compute_unit/device.rb', line 330 def self.subsystem_device_lookup(device_id, subsystem_device_id, vendor_id) # "\t\t1002 687f Vega 10 XT [Radeon RX Vega 64]\n" p = manual_device_lookup(device_id, subsystem_device_id, vendor_id) return p if p re = Regexp.new(/\A\t\t#{vendor_id}\s+#{subsystem_device_id}/) d = pci_database.find do |line| re.match(line) rescue ArgumentError next end return d unless d name = d[/\t\t\w+\s+\w+\s+(.*)\n/, 1] name[/.*\[(.*)\]/, 1] || name if name end |
.subsystem_vendor(device_path) ⇒ String
example: XFX is the reseller of the AMD chips
241 242 243 |
# File 'lib/compute_unit/device.rb', line 241 def self.subsystem_vendor(device_path) read_kernel_setting(device_path, 'subsystem_vendor', '').slice(2, 6) end |
.subsystem_vendor_lookup(vendor_id) ⇒ String
Returns - the name of the subsystem vendor with a possible translation.
348 349 350 351 |
# File 'lib/compute_unit/device.rb', line 348 def self.subsystem_vendor_lookup(vendor_id) # "1002 Advanced Micro Devices, Inc. [AMD/ATI]\n" vendor_lookup(vendor_id) end |
.system_checksum ⇒ String
Returns - a sha1 digest that represents the pci devices found on the system.
298 299 300 301 302 |
# File 'lib/compute_unit/device.rb', line 298 def self.system_checksum @system_checksum ||= Dir.chdir(ComputeUnit::SYS_DEVICE_PATH) do Digest::SHA1.hexdigest(Dir.glob('*').sort.join) end end |
.vendor_lookup(vendor_id) ⇒ String
Returns - the name of the subsystem vendor with a possible translation.
365 366 367 368 369 370 371 372 373 374 375 376 377 |
# File 'lib/compute_unit/device.rb', line 365 def self.vendor_lookup(vendor_id) # "1002 Advanced Micro Devices, Inc. [AMD/ATI]\n" re = Regexp.new(/\A#{vendor_id}/) d = pci_database.find do |line| re.match(line) rescue ArgumentError next end return manual_vendor_lookup(vendor_id) unless d name = d[/\w+\s+(.*)\n/, 1] name_translation(name) end |
.write_kernel_setting(device_path, setting, value) ⇒ String
Returns - read a kernel setting using the device_path.
285 286 287 288 289 290 291 292 293 294 295 |
# File 'lib/compute_unit/device.rb', line 285 def self.write_kernel_setting(device_path, setting, value) path = File.join(device_path, setting) File.write(path, value) read_kernel_setting(device_path, setting) rescue Errno::EINVAL, Errno::EPERM => e logger.fatal(e.) rescue Errno::ENOENT logger.warn("File #{path} does not exist") rescue Errno::EACCES logger.fatal('Run this command as root or with sudo') end |
Instance Method Details
#base_hwmon_path ⇒ String
this is used mainly for easier mocking
Returns - base hwmon path of the device.
159 160 161 |
# File 'lib/compute_unit/device.rb', line 159 def base_hwmon_path File.join(device_path, 'hwmon') end |
#expired_metadata? ⇒ Boolean
173 174 175 |
# File 'lib/compute_unit/device.rb', line 173 def + CACHE_TIMEOUT < Time.now.to_i end |
#generic_model ⇒ String
Returns - the name of the device model (sometimes not specific).
121 122 123 124 125 126 |
# File 'lib/compute_unit/device.rb', line 121 def generic_model @generic_model ||= begin name = self.class.device_lookup(device_id) name[/\[?(.*)\]?/, 1] if name end end |
#hwmon_path ⇒ String
this path can be different for each device
returns the base_hwmon_path if no path is found
Returns - the directory path to the hwmon dir for this device.
166 167 168 169 170 171 |
# File 'lib/compute_unit/device.rb', line 166 def hwmon_path @hwmon_path ||= begin paths = Dir.glob(File.join(base_hwmon_path, '*')) paths.first || base_hwmon_path end end |
#lock_rom ⇒ String
must be root
56 57 58 |
# File 'lib/compute_unit/device.rb', line 56 def lock_rom File.write(rom_path, '0') if File.exist?(rom_path) end |
#read_file(path, default = nil) ⇒ Object
128 129 130 131 132 133 134 135 136 137 138 |
# File 'lib/compute_unit/device.rb', line 128 def read_file(path, default = nil) File.read(path).chomp rescue Errno::EINVAL, Errno::EPERM default rescue Errno::ENOENT logger.debug("File #{path} does not exist, using defaults") default rescue Errno::EACCES logger.fatal('run this command as root or with sudo, using default value') default end |
#read_hwmon_data(item, default = nil) ⇒ String
Returns - the value of the item looked up.
143 144 145 146 |
# File 'lib/compute_unit/device.rb', line 143 def read_hwmon_data(item, default = nil) path = File.join(hwmon_path, item) read_file(path, default) end |
#read_kernel_setting(setting, default = 0) ⇒ String
Returns - read a kernel setting using the device_path.
75 76 77 |
# File 'lib/compute_unit/device.rb', line 75 def read_kernel_setting(setting, default = 0) self.class.read_kernel_setting(device_path, setting, default) end |
#rom_data ⇒ String::IO
Returns - the contents of the rom file.
61 62 63 64 65 66 67 68 69 70 |
# File 'lib/compute_unit/device.rb', line 61 def rom_data return unless File.exist?(rom_path) begin unlock_rom IO.read(rom_path, mode: 'rb') ensure lock_rom end end |
#rom_path ⇒ String
Returns - the path to the rom file if available.
44 45 46 |
# File 'lib/compute_unit/device.rb', line 44 def rom_path @rom_path ||= File.join(device_path, 'rom') end |
#sysfs_model_name ⇒ String
Returns - the name of the device model (specific name).
107 108 109 110 111 |
# File 'lib/compute_unit/device.rb', line 107 def sysfs_model_name name = self.class.subsystem_device_lookup(device_id, subsystem_device_id, subsystem_vendor_id) m = name[/\[?(.*)\]?/, 1] if name m || generic_model end |
#to_h ⇒ Object
35 36 37 38 39 40 41 |
# File 'lib/compute_unit/device.rb', line 35 def to_h { chip_make: make, make: vendor, model: model, device_id: device_id, vendor_id: device_vendor_id, subsystem_device_id: subsystem_device_id, subsystem_vendor_id: subsystem_vendor_id, device_class: device_class_id } end |
#to_json(c = nil) ⇒ Object
177 178 179 |
# File 'lib/compute_unit/device.rb', line 177 def to_json(c = nil) to_h.to_json(c) end |
#unlock_rom ⇒ String
must be root
50 51 52 |
# File 'lib/compute_unit/device.rb', line 50 def unlock_rom File.write(rom_path, '1') if File.exist?(rom_path) end |
#write_hwmon_data(item, value) ⇒ Object
150 151 152 153 154 155 |
# File 'lib/compute_unit/device.rb', line 150 def write_hwmon_data(item, value) File.write(File.join(hwmon_path, item), value) rescue Errno::EACCES => e logger.info(e.) check_for_root end |
#write_kernel_setting(setting, value) ⇒ String
Returns - a reading of the kernel setting using the device_path.
82 83 84 |
# File 'lib/compute_unit/device.rb', line 82 def write_kernel_setting(setting, value) self.class.write_kernel_setting(device_path, setting, value) end |