Skip to content

Commit

Permalink
Move usb utility functions to usb-util module
Browse files Browse the repository at this point in the history
  • Loading branch information
keeramis committed May 20, 2024
1 parent 41a5b4c commit 6b39eeb
Show file tree
Hide file tree
Showing 2 changed files with 69 additions and 66 deletions.
62 changes: 61 additions & 1 deletion src/cmd/usb-util.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
const { spin } = require('../app/ui');
const { getDevice, isDeviceId } = require('./device-util');
const { systemSupportsUdev, promptAndInstallUdevRules } = require('./udev');
const { delay } = require('../lib/utilities');
Expand Down Expand Up @@ -346,6 +347,63 @@ async function reopenDevice(device) {
throw new Error('Unable to reconnect to the device. Try again or run particle update to repair the device');
}

async function forEachUsbDevice(args, func, { dfuMode = false } = {}){
const msg = 'Getting device information...';
const operation = openUsbDevices(args, { dfuMode });
let lastError = null;
return spin(operation, msg)
.then(usbDevices => {
const p = usbDevices.map(usbDevice => {
return Promise.resolve()
.then(() => func(usbDevice))
.catch(e => lastError = e)
.finally(() => usbDevice.close());
});
return spin(Promise.all(p), 'Sending a command to the device...');
})
.then(() => {
if (lastError){
throw lastError;
}
});
}

async function openUsbDevices(args, { dfuMode = false } = {}){
const deviceIds = args.params.devices;
return Promise.resolve()
.then(() => {
if (args.all){
return getUsbDevices({ dfuMode: true })
.then(usbDevices => {
return asyncMapSeries(usbDevices, (usbDevice) => {
return openUsbDevice(usbDevice, { dfuMode })
.then(() => usbDevice);
});
});
}

if (deviceIds.length === 0){
return getUsbDevices({ dfuMode: true })
.then(usbDevices => {
if (usbDevices.length === 0){
throw new Error('No devices found');
}
if (usbDevices.length > 1){
throw new Error('Found multiple devices. Please specify the ID or name of one of them');
}
const usbDevice = usbDevices[0];
return openUsbDevice(usbDevice, { dfuMode })
.then(() => [usbDevice]);
});
}

return asyncMapSeries(deviceIds, (id) => {
return openUsbDeviceByIdOrName(id, this._api, this._auth, { dfuMode })
.then(usbDevice => usbDevice);
});
});
}

async function handleUsbError(err){
if (err instanceof NotAllowedError) {
err = new UsbPermissionsError('Missing permissions to access the USB device');
Expand All @@ -371,5 +429,7 @@ module.exports = {
reopenDevice,
UsbPermissionsError,
TimeoutError,
DeviceProtectionError
DeviceProtectionError,
forEachUsbDevice,
openUsbDevices
};
73 changes: 8 additions & 65 deletions src/cmd/usb.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
const { spin } = require('../app/ui');
const { delay, asyncMapSeries, buildDeviceFilter } = require('../lib/utilities');
const { getDevice, formatDeviceInfo } = require('./device-util');
const { getUsbDevices, openUsbDevice, openUsbDeviceByIdOrName, TimeoutError, DeviceProtectionError } = require('./usb-util');
const { getUsbDevices, openUsbDevice, openUsbDeviceByIdOrName, TimeoutError, DeviceProtectionError, forEachUsbDevice } = require('./usb-util');
const { systemSupportsUdev, udevRulesInstalled, installUdevRules } = require('./udev');
const { platformForId, isKnownPlatformId } = require('../lib/platform');
const ParticleApi = require('./api');
Expand Down Expand Up @@ -109,7 +109,7 @@ module.exports = class UsbCommand extends CLICommandBase {
}

startListening(args) {
return this._forEachUsbDevice(args, usbDevice => {
return forEachUsbDevice(args, usbDevice => {
return usbDevice.enterListeningMode();
})
.then(() => {
Expand All @@ -118,7 +118,7 @@ module.exports = class UsbCommand extends CLICommandBase {
}

stopListening(args) {
return this._forEachUsbDevice(args, usbDevice => {
return forEachUsbDevice(args, usbDevice => {
return usbDevice.leaveListeningMode();
})
.then(() => {
Expand All @@ -127,7 +127,7 @@ module.exports = class UsbCommand extends CLICommandBase {
}

safeMode(args) {
return this._forEachUsbDevice(args, usbDevice => {
return forEachUsbDevice(args, usbDevice => {
return usbDevice.enterSafeMode();
})
.then(() => {
Expand All @@ -136,7 +136,7 @@ module.exports = class UsbCommand extends CLICommandBase {
}

dfu(args) {
return this._forEachUsbDevice(args, usbDevice => {
return forEachUsbDevice(args, usbDevice => {
if (!usbDevice.isInDfuMode) {
return usbDevice.enterDfuMode();
}
Expand All @@ -147,7 +147,7 @@ module.exports = class UsbCommand extends CLICommandBase {
}

reset(args) {
return this._forEachUsbDevice(args, usbDevice => {
return forEachUsbDevice(args, usbDevice => {
return usbDevice.reset();
}, { dfuMode: true })
.then(() => {
Expand All @@ -157,7 +157,7 @@ module.exports = class UsbCommand extends CLICommandBase {

setSetupDone(args) {
const done = !args.reset;
return this._forEachUsbDevice(args, usbDevice => {
return forEachUsbDevice(args, usbDevice => {
if (usbDevice.isGen3Device) {
return usbDevice.setSetupDone(done)
.then(() => {
Expand Down Expand Up @@ -234,63 +234,6 @@ module.exports = class UsbCommand extends CLICommandBase {
.finally(() => deviceMgr.close());
}

_forEachUsbDevice(args, func, { dfuMode = false } = {}){
const msg = 'Getting device information...';
const operation = this._openUsbDevices(args, { dfuMode });
let lastError = null;
return spin(operation, msg)
.then(usbDevices => {
const p = usbDevices.map(usbDevice => {
return Promise.resolve()
.then(() => func(usbDevice))
.catch(e => lastError = e)
.finally(() => usbDevice.close());
});
return spin(Promise.all(p), 'Sending a command to the device...');
})
.then(() => {
if (lastError){
throw lastError;
}
});
}

_openUsbDevices(args, { dfuMode = false } = {}){
const deviceIds = args.params.devices;
return Promise.resolve()
.then(() => {
if (args.all){
return getUsbDevices({ dfuMode: true })
.then(usbDevices => {
return asyncMapSeries(usbDevices, (usbDevice) => {
return openUsbDevice(usbDevice, { dfuMode })
.then(() => usbDevice);
});
});
}

if (deviceIds.length === 0){
return getUsbDevices({ dfuMode: true })
.then(usbDevices => {
if (usbDevices.length === 0){
throw new Error('No devices found');
}
if (usbDevices.length > 1){
throw new Error('Found multiple devices. Please specify the ID or name of one of them');
}
const usbDevice = usbDevices[0];
return openUsbDevice(usbDevice, { dfuMode })
.then(() => [usbDevice]);
});
}

return asyncMapSeries(deviceIds, (id) => {
return openUsbDeviceByIdOrName(id, this._api, this._auth, { dfuMode })
.then(usbDevice => usbDevice);
});
});
}

// Helper function to convert CIDR notation to netmask to imitate the 'ifconfig' output
_cidrToNetmask(cidr) {
let mask = [];
Expand All @@ -317,7 +260,7 @@ module.exports = class UsbCommand extends CLICommandBase {
// define output array with logs to prevent interleaving with the spinner
let output = [];

await this._forEachUsbDevice(args, usbDevice => {
await forEachUsbDevice(args, usbDevice => {
const platform = platformForId(usbDevice.platformId);
return this.getNetworkIfaceInfo(usbDevice)
.then((nwIfaces) => {
Expand Down

0 comments on commit 6b39eeb

Please sign in to comment.