Skip to content

Commit

Permalink
[CP-3210][Re-flashing Mac] Simplify logic by applying filters in devi…
Browse files Browse the repository at this point in the history
…ce retrieval (#2134)
  • Loading branch information
dkarski authored Oct 23, 2024
1 parent 75369fa commit beb7a16
Show file tree
Hide file tree
Showing 5 changed files with 241 additions and 18 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,11 @@ import { ProductID, VendorID } from "Core/device/constants"

export const getUsbDevicesMacOS = async (): Promise<PortInfo | void> => {
try {
const devices = await MacosUSBPortDeviceParser.getUSBPortDevices()
const device = devices.find((device) => {
return (
device.vendorId?.includes(VendorID.MuditaHarmony) &&
device.productId?.includes(ProductID.MuditaHarmonyMsc)
)
const devices = await MacosUSBPortDeviceParser.getUSBPortDevices({
vendorId: VendorID.MuditaHarmony,
productId: ProductID.MuditaHarmonyMsc,
})
const device = devices[0]

if (device !== undefined) {
return device
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,14 +32,11 @@ class MacDeviceFlashService implements IDeviceFlash {

async findDeviceByDeviceName(): Promise<string> {
console.log(`Searching for device...`)
const devices = await MacosUSBPortDeviceParser.getUSBPortDevices()

const device = devices.find((device) => {
return (
device.vendorId?.includes("3310") &&
device.name?.includes("Mudita Harmony (MSC mode)")
)
const devices = await MacosUSBPortDeviceParser.getUSBPortDevices({
vendorId: "3310",
name: "Mudita Harmony (MSC mode)",
})
const device = devices[0]

if (!device) {
console.error(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,5 @@ export interface USBPortDevice extends USBDevice, PortInfo {
path: string
pnpId?: string | undefined
}

export type USBPortDeviceFilters = Partial<USBPortDevice>;
Original file line number Diff line number Diff line change
Expand Up @@ -421,3 +421,214 @@ USB:
expect(devices.length).toBe(0)
})
})

it("should correctly filter devices by vendorId", async () => {
const output = `
USB:
USB 3.1 Bus:
Host Controller Driver: AppleT8122USBXHCI
Mudita Harmony (MSC mode):
Product ID: 0x0103
Vendor ID: 0x3310
Version: 1.01
Serial Number: 0123456789ABCDEF
Manufacturer: Mudita
Mudita Bell:
Product ID: 0x0104
Vendor ID: 0x3311
Version: 1.02
Serial Number: ABCDEF1234567890
Manufacturer: Mudita
`
;(execPromise as jest.Mock).mockResolvedValue(output)

const devices = await MacosUSBPortDeviceParser.getUSBPortDevices({ vendorId: '3310' })

expect(devices.length).toBe(1)
expect(devices[0]).toEqual({
productId: '0103',
vendorId: '3310',
version: '1.01',
serialNumber: '0123456789ABCDEF',
manufacturer: 'Mudita',
name: 'Mudita Harmony (MSC mode)',
path: '3310/0103/0123456789ABCDEF',
})
})

it("should correctly filter devices by productId", async () => {
const output = `
USB:
USB 3.1 Bus:
Host Controller Driver: AppleT8122USBXHCI
Mudita Harmony (MSC mode):
Product ID: 0x0103
Vendor ID: 0x3310
Version: 1.01
Serial Number: 0123456789ABCDEF
Manufacturer: Mudita
Mudita Bell:
Product ID: 0x0104
Vendor ID: 0x3310
Version: 1.02
Serial Number: ABCDEF1234567890
Manufacturer: Mudita
`
;(execPromise as jest.Mock).mockResolvedValue(output)

const devices = await MacosUSBPortDeviceParser.getUSBPortDevices({ productId: '0104' })

expect(devices.length).toBe(1)
expect(devices[0]).toEqual({
productId: '0104',
vendorId: '3310',
version: '1.02',
serialNumber: 'ABCDEF1234567890',
manufacturer: 'Mudita',
name: 'Mudita Bell',
path: '3310/0104/ABCDEF1234567890',
})
})

it("should correctly filter devices by name", async () => {
const output = `
USB:
USB 3.1 Bus:
Host Controller Driver: AppleT8122USBXHCI
Mudita Harmony (MSC mode):
Product ID: 0x0103
Vendor ID: 0x3310
Version: 1.01
Serial Number: 0123456789ABCDEF
Manufacturer: Mudita
Mudita Bell:
Product ID: 0x0104
Vendor ID: 0x3310
Version: 1.02
Serial Number: ABCDEF1234567890
Manufacturer: Mudita
`
;(execPromise as jest.Mock).mockResolvedValue(output)

const devices = await MacosUSBPortDeviceParser.getUSBPortDevices({ name: 'Mudita Bell' })

expect(devices.length).toBe(1)
expect(devices[0]).toEqual({
productId: '0104',
vendorId: '3310',
version: '1.02',
serialNumber: 'ABCDEF1234567890',
manufacturer: 'Mudita',
name: 'Mudita Bell',
path: '3310/0104/ABCDEF1234567890',
})
})

it("should correctly filter devices by vendorId and productId when both match", async () => {
const output = `
USB:
USB 3.1 Bus:
Host Controller Driver: AppleT8122USBXHCI
Mudita Harmony (MSC mode):
Product ID: 0x0103
Vendor ID: 0x3310
Version: 1.01
Serial Number: 0123456789ABCDEF
Manufacturer: Mudita
Mudita Bell:
Product ID: 0x0104
Vendor ID: 0x3311
Version: 1.02
Serial Number: ABCDEF1234567890
Manufacturer: Mudita
`
;(execPromise as jest.Mock).mockResolvedValue(output)

const devices = await MacosUSBPortDeviceParser.getUSBPortDevices({ vendorId: '3310', productId: '0103' })

expect(devices.length).toBe(1)
expect(devices[0]).toEqual({
productId: '0103',
vendorId: '3310',
version: '1.01',
serialNumber: '0123456789ABCDEF',
manufacturer: 'Mudita',
name: 'Mudita Harmony (MSC mode)',
path: '3310/0103/0123456789ABCDEF',
})
})

it("should return an empty array when vendorId matches but productId does not", async () => {
const output = `
USB:
USB 3.1 Bus:
Host Controller Driver: AppleT8122USBXHCI
Mudita Harmony (MSC mode):
Product ID: 0x0103
Vendor ID: 0x3310
Version: 1.01
Serial Number: 0123456789ABCDEF
Manufacturer: Mudita
Mudita Bell:
Product ID: 0x0104
Vendor ID: 0x3311
Version: 1.02
Serial Number: ABCDEF1234567890
Manufacturer: Mudita
`
;(execPromise as jest.Mock).mockResolvedValue(output)

const devices = await MacosUSBPortDeviceParser.getUSBPortDevices({ vendorId: '3310', productId: '0104' })

expect(devices.length).toBe(0)
})

it("should return an empty array when productId matches but vendorId does not", async () => {
const output = `
USB:
USB 3.1 Bus:
Host Controller Driver: AppleT8122USBXHCI
Mudita Harmony (MSC mode):
Product ID: 0x0103
Vendor ID: 0x3310
Version: 1.01
Serial Number: 0123456789ABCDEF
Manufacturer: Mudita
Mudita Bell:
Product ID: 0x0104
Vendor ID: 0x3311
Version: 1.02
Serial Number: ABCDEF1234567890
Manufacturer: Mudita
`
;(execPromise as jest.Mock).mockResolvedValue(output)

const devices = await MacosUSBPortDeviceParser.getUSBPortDevices({ vendorId: '3311', productId: '0103' })

expect(devices.length).toBe(0)
})

it("should return an empty array when neither vendorId nor productId match", async () => {
const output = `
USB:
USB 3.1 Bus:
Host Controller Driver: AppleT8122USBXHCI
Mudita Harmony (MSC mode):
Product ID: 0x0103
Vendor ID: 0x3310
Version: 1.01
Serial Number: 0123456789ABCDEF
Manufacturer: Mudita
Mudita Bell:
Product ID: 0x0104
Vendor ID: 0x3311
Version: 1.02
Serial Number: ABCDEF1234567890
Manufacturer: Mudita
`
;(execPromise as jest.Mock).mockResolvedValue(output)

const devices = await MacosUSBPortDeviceParser.getUSBPortDevices({ vendorId: '9999', productId: '9999' })

expect(devices.length).toBe(0)
})
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,12 @@
* For licensing, see https://github.com/mudita/mudita-center/blob/master/LICENSE.md
*/

import isMatch from "lodash/isMatch"
import { execPromise } from "../exec-command"
import {
USBDevice,
USBPortDevice,
USBPortDeviceFilters,
} from "./macos-usb-port-device-parser.interface"

const fieldPatterns: Partial<Record<keyof USBDevice, RegExp>> = {
Expand All @@ -20,24 +22,37 @@ const fieldPatterns: Partial<Record<keyof USBDevice, RegExp>> = {
}

export class MacosUSBPortDeviceParser {
static async getUSBPortDevices(): Promise<USBPortDevice[]> {
static async getUSBPortDevices(
filters?: USBPortDeviceFilters
): Promise<USBPortDevice[]> {
const usbDevices = await MacosUSBPortDeviceParser.getUSBDevice()
return usbDevices.map((usbDevice) => {
return usbDevices.reduce<USBPortDevice[]>((filteredDevices, usbDevice) => {
const vendorId = usbDevice.vendorId?.replace("0x", "")
const productId = usbDevice.productId?.replace("0x", "")
const serialNumber = usbDevice.serialNumber?.replace("0x", "")
const locationId = usbDevice.locationId?.split(" ")[0]
const path = vendorId && productId && serialNumber && `${vendorId}/${productId}/${serialNumber}`
const path =
vendorId &&
productId &&
serialNumber &&
`${vendorId}/${productId}/${serialNumber}`

return {
const mappedDevice: USBPortDevice = {
...usbDevice,
productId,
vendorId,
serialNumber,
locationId,
path: path ?? "unknown",
}
})

if (filters && !isMatch(mappedDevice, filters)) {
return filteredDevices
}

filteredDevices.push(mappedDevice)
return filteredDevices
}, [])
}

private static async getUSBDevice(): Promise<USBDevice[]> {
Expand Down

0 comments on commit beb7a16

Please sign in to comment.