Skip to content

Instantly share code, notes, and snippets.

@konsumer
Created February 11, 2019 23:34
Show Gist options
  • Save konsumer/e65020916e5c6f8a5d73d12cac24c01b to your computer and use it in GitHub Desktop.
Save konsumer/e65020916e5c6f8a5d73d12cac24c01b to your computer and use it in GitHub Desktop.
An OSX parser for `ioreg` that will get you vendor/device ID and name of devices on PCI bus
const { spawn } = require('child_process')
const Xml = require('xml-stream')
const fetch = require('node-fetch')
const cheerio = require('cheerio')
// apple returns IDs in funny order
const unmangleID = string => {
if (string) {
const s = string.split('').slice(0, 4)
return `${s[2]}${s[3]}${s[0]}${s[1]}`
}
}
const getDevices = () => new Promise((resolve, reject) => {
const plist = spawn('ioreg', ['-c', 'IOPCIDevice', '-a'])
const xml = new Xml(plist.stdout)
xml.on('error', reject)
const out = []
xml.on('end', () => { resolve(out) })
xml.preserve('dict', true)
xml.on('endElement: dict', item => {
if (item.$children) {
item.$children.forEach(c => {
if (c.$text === 'IOPCIDevice') {
const info = item.$children.filter(cc => cc && cc.$text && cc.$text.trim() !== '')
let vendor
let device
let subsystem
let subsystemVendor
info.forEach((iv, ii) => {
if (iv.$text === 'vendor-id') {
vendor = unmangleID(Buffer.from(info[ii + 1].$text, 'base64').toString('hex'))
}
if (iv.$text === 'device-id') {
device = unmangleID(Buffer.from(info[ii + 1].$text, 'base64').toString('hex'))
}
if (iv.$text === 'subsystem-vendor-id') {
subsystemVendor = unmangleID(Buffer.from(info[ii + 1].$text, 'base64').toString('hex'))
}
if (iv.$text === 'subsystem-id') {
subsystem = unmangleID(Buffer.from(info[ii + 1].$text, 'base64').toString('hex'))
}
})
if (subsystem) {
out.push(`${vendor}:${device} - ${subsystemVendor} ${subsystem}`)
} else {
out.push(`${vendor}:${device}`)
}
}
})
}
})
})
// use pci-ids.ucw.cz to lookup vendor/device IDs
const lookup = async () => {
const devices = await getDevices()
console.log(await Promise.all(devices.map(d => {
const [ vendor, device ] = d.split(' - ')[0].split(':')
return fetch(`https://pci-ids.ucw.cz/read/PC/${vendor}/${device}`)
.then(r => r.status === 200 && r.text())
.then(b => b && cheerio.load(b)('.name').text().replace('Name: ', ''))
.then(name => {
if (name) {
return `${d} | ${name}`
} else {
return d
}
})
})))
}
lookup()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment