From fcdfa173f1191a18a33ba7cad1a9be24bd91baae Mon Sep 17 00:00:00 2001 From: Sebastian Hildebrandt Date: Sun, 10 Jan 2021 19:33:55 +0100 Subject: [PATCH] added usb --- lib/index.js | 3 + lib/printer.js | 46 ++++++--- lib/usb.js | 257 +++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 291 insertions(+), 15 deletions(-) create mode 100644 lib/usb.js diff --git a/lib/index.js b/lib/index.js index 002a3c8..3470e2c 100755 --- a/lib/index.js +++ b/lib/index.js @@ -38,6 +38,7 @@ const internet = require('./internet'); const docker = require('./docker'); const vbox = require('./virtualbox'); const printer = require('./printer'); +const usb = require('./usb'); let _platform = process.platform; const _windows = (_platform === 'win32'); @@ -456,6 +457,8 @@ exports.vboxInfo = vbox.vboxInfo; exports.printer = printer.printer; +exports.usb = usb.usb; + exports.getStaticData = getStaticData; exports.getDynamicData = getDynamicData; exports.getAllData = getAllData; diff --git a/lib/printer.js b/lib/printer.js index 3625572..9a126b5 100644 --- a/lib/printer.js +++ b/lib/printer.js @@ -30,6 +30,16 @@ const _sunos = (_platform === 'sunos'); const NOT_SUPPORTED = 'not supported'; +const winPrinterStatus = { + 1: 'Other', + 2: 'Unknown', + 3: 'Idle', + 4: 'Printing', + 5: 'Warmup', + 6: 'Stopped Printing', + 7: 'Offline', +} + function parseLinuxCupsHeader(lines) { const result = {} if (lines && lines.length) { @@ -88,8 +98,21 @@ function parseDarwinPrinters(printerObject, id) { return result; } -function parseWindowsPrinters(lines) { - return lines; +function parseWindowsPrinters(lines, id) { + const result = {}; + const status = parseInt(util.getValue(lines, 'PrinterStatus', '='), 10); + + result.id = id; + result.name = util.getValue(lines, 'name', '='); + result.model = util.getValue(lines, 'DriverName', '='); + result.uri = null; + result.uuid = null + result.status = winPrinterStatus[status] ? winPrinterStatus[status] : null; + result.local = util.getValue(lines, 'Local', '=') === 'TRUE'; + result.default = util.getValue(lines, 'Default', '=') === 'TRUE'; + result.shared = util.getValue(lines, 'Shared', '=') === 'TRUE'; + + return result; } function printer(callback) { @@ -105,7 +128,7 @@ function printer(callback) { const parts = stdout.toString().split('= 0) { + const parts = lines[0].split(' '); + result.bus = parseInt(parts[0], 10); + if (parts[2]) { + result.deviceId = parseInt(parts[2], 10); + } else { + result.deviceId = null; + } + } else { + result.bus = null; + result.deviceId = null; + } + const idVendor = util.getValue(lines, 'idVendor', ' ', true); + let vendorParts = idVendor.split(' '); + vendorParts.shift(); + const vendor = vendorParts.join(' '); + + const idProduct = util.getValue(lines, 'idProduct', ' ', true); + let productParts = idProduct.split(' '); + productParts.shift(); + const product = productParts.join(' '); + + const interfaceClass = util.getValue(lines, 'bInterfaceClass', ' ', true); + let interfaceClassParts = interfaceClass.split(' '); + interfaceClassParts.shift(); + const usbType = interfaceClassParts.join(' '); + + const iManufacturer = util.getValue(lines, 'iManufacturer', ' ', true); + let iManufacturerParts = iManufacturer.split(' '); + iManufacturerParts.shift(); + const manufacturer = iManufacturerParts.join(' '); + + result.id = idVendor.startWith('0x') ? idVendor.split(' ').substr(2, 10) : '' + ':' + idProduct.startWith('0x') ? idProduct.split(' ').substr(2, 10) : ''; + result.name = product + result.type = usbType; + result.removable = null; + result.vendor = vendor; + result.manufacturer = manufacturer + result.maxPower = util.getValue(lines, 'MaxPower', ' ', true); + result.serialNumber = null; + + return result; +} + +// bus +// deviceId +// id +// name(product) +// type(bInterfaceClass) +// removable / hotplug +// vendor +// manufacturer +// maxpower(linux) + +function getDarwinUsbType(name) { + let result = '' + if (name.indexOf('camera') >= 0) { result = 'Camera'; } + else if (name.indexOf('touch bar') >= 0) { result = 'Touch Bar'; } + else if (name.indexOf('controller') >= 0) { result = 'Controller'; } + else if (name.indexOf('headset') >= 0) { result = 'Audio'; } + else if (name.indexOf('keyboard') >= 0) { result = 'Keyboard'; } + else if (name.indexOf('trackpad') >= 0) { result = 'Trackpad'; } + else if (name.indexOf('sensor') >= 0) { result = 'Sensor'; } + else if (name.indexOf('bthusb') >= 0) { result = 'Bluetooth'; } + else if (name.indexOf('bth') >= 0) { result = 'Bluetooth'; } + else if (name.indexOf('rfcomm') >= 0) { result = 'Bluetooth'; } + else if (name.indexOf('usbhub') >= 0) { result = 'Hub'; } + return result; +} + + +function parseDarwinUsb(usb, id) { + const result = {}; + result.id = id; + + usb = usb.replace(/ \|/g, '') + usb = usb.trim(); + let lines = usb.split('\n'); + lines.shift(); + try { + for (let i = 0; i < lines.length; i++) { + lines[i] = lines[i].trim(); + lines[i] = lines[i].replace(/=/g, ':'); + if (lines[i] !== '{' && lines[i] !== '}' && lines[i + 1] && lines[i + 1].trim() !== '}') { + lines[i] = lines[i] + ','; + } + lines[i] = lines[i].replace(' Yes,', '"Yes",'); + } + const usbObj = JSON.parse(lines.join('\n')); + + result.bus = null; + result.deviceId = null; + result.id = usbObj['USB Address']; + result.name = usbObj['kUSBProductString']; + result.type = getDarwinUsbType(usbObj['kUSBProductString'].toLowerCase()); + result.removable = usbObj['Built-In'].toLowerCase() !== 'yes'; + result.vendor = usbObj['kUSBVendorString']; + result.manufacturer = usbObj['kUSBVendorString']; + result.maxPower = null; + result.serialNumber = usbObj['kUSBSerialNumberString'] || null; + + if (result.name) { + return result; + } else { + return null; + } + } catch (e) { + return null; + } +} + +function getWindowsUsbType(service) { + let result = '' + if (service.indexOf('usbhub3') >= 0) { result = 'Hub'; } + else if (service.indexOf('usbstor') >= 0) { result = 'Storage'; } + else if (service.indexOf('hidUsb') >= 0) { result = 'Input'; } + else if (service.indexOf('mouhid') >= 0) { result = 'Mouse'; } + else if (service.indexOf('usbccgp') >= 0) { result = 'Controller'; } + else if (service.indexOf('kbdhid') >= 0) { result = 'Keyboard'; } + else if (service.indexOf('disk') >= 0) { result = 'Storage'; } + else if (service.indexOf('bthusb') >= 0) { result = 'Bluetooth'; } + else if (service.indexOf('bth') >= 0) { result = 'Bluetooth'; } + else if (service.indexOf('rfcomm') >= 0) { result = 'Bluetooth'; } + else if (service.indexOf('usbhub') >= 0) { result = 'Hub'; } + return result; +} + +function parseWindowsUsb(lines, id) { + const usbType = getWindowsUsbType(util.getValue(lines, 'Service', '=').toLowerCase()); + + if (usbType) { + const result = {}; + result.bus = null; + result.deviceId = null; + result.id = id; + result.name = util.getValue(lines, 'name', '='); + result.type = usbType; + result.removable = null; + result.vendor = null; + result.manufacturer = util.getValue(lines, 'Manufacturer', '='); + result.maxPower = null; + result.serialNumber = null; + + return result; + } else { + return null + } + +} + +function usb(callback) { + + return new Promise((resolve, reject) => { + process.nextTick(() => { + let result = []; + if (_linux) { + const cmd = 'export LC_ALL=C; lsusb -v 2>/dev/null; unset LC_ALL'; + exec(cmd, { maxBuffer: 1024 * 1024 * 128 }, function (error, stdout) { + if (!error) { + const parts = ('\n\n' + stdout.toString()).split('\n\nBus '); + for (let i = 1; i < parts.length; i++) { + const usb = parseLinuxUsb(parts[i]); + result.push(usb); + } + } + if (callback) { + callback(result); + } + resolve(result); + }); + } + if (_darwin) { + let cmd = 'ioreg -p IOUSB -c AppleUSBRootHubDevice -w0 -l' + exec(cmd, {maxBuffer: 1024 * 1024 * 128}, function (error, stdout) { + if (!error) { + const parts = (stdout.toString()).split(' +-o '); + for (let i = 2; i < parts.length; i++) { + const usb = parseDarwinUsb(parts[i]); + if (usb) { + result.push(usb) + } + } + if (callback) { + callback(result); + } + resolve(result); + } + if (callback) { + callback(result); + } + resolve(result); + }); + } + if (_windows) { + util.powerShell('gwmi Win32_USBControllerDevice |%{[wmi]($_.Dependent)}', function (error, stdout) { + if (!error) { + const parts = stdout.toString().split(/\n\s*\n/); + for (let i = 0; i < parts.length; i++) { + const usb = parseWindowsUsb(parts[i].split('\n'), i) + if (usb) { + result.push(usb) + } + } + } + if (callback) { + callback(result); + } + resolve(result); + }); + } + if (_sunos || _freebsd || _openbsd || _netbsd) { + let error = new Error(NOT_SUPPORTED); + if (callback) { + callback(NOT_SUPPORTED); + } + reject(error); + } + }); + }); +} + +exports.usb = usb;