| 1 | // Phase 0: list HID devices so we can identify the MX Creative Console halves. |
| 2 | // Keypad is expected as Elgato (0x0fd9); the Bluetooth dialpad is likely |
| 3 | // Logitech (0x046d) speaking HID++. |
| 4 | const { devices } = await import("node-hid"); |
| 5 | |
| 6 | const VENDOR_NAMES: Record<number, string> = { |
| 7 | 0x046d: "Logitech", |
| 8 | 0x0fd9: "Elgato", |
| 9 | 0x05ac: "Apple", |
| 10 | }; |
| 11 | |
| 12 | const hex = (n: number | undefined, width = 4) => "0x" + (n ?? 0).toString(16).padStart(width, "0"); |
| 13 | |
| 14 | const all = devices(); |
| 15 | |
| 16 | const format = (d: import("node-hid").Device) => |
| 17 | [ |
| 18 | `${hex(d.vendorId)}:${hex(d.productId)}`, |
| 19 | (VENDOR_NAMES[d.vendorId] ?? "?").padEnd(8), |
| 20 | `usage=${hex(d.usagePage)}/${hex(d.usage)}`, |
| 21 | `iface=${d.interface}`, |
| 22 | `| ${d.manufacturer ?? ""} ${d.product ?? ""}`.trim(), |
| 23 | d.path ? `\n path=${d.path}` : "", |
| 24 | ].join(" "); |
| 25 | |
| 26 | const interesting = all.filter( |
| 27 | (d) => d.vendorId === 0x046d || d.vendorId === 0x0fd9, |
| 28 | ); |
| 29 | |
| 30 | console.info(`Total HID devices: ${all.length}`); |
| 31 | console.info(`\n=== Logitech (0x046d) + Elgato (0x0fd9) ===`); |
| 32 | if (interesting.length === 0) { |
| 33 | console.info(" (none found — dialpad may not surface as a HID device)"); |
| 34 | } else { |
| 35 | for (const d of interesting) console.info(" " + format(d)); |
| 36 | } |
| 37 | |
| 38 | console.info(`\n=== All vendors present ===`); |
| 39 | const byVendor = new Map<number, number>(); |
| 40 | for (const d of all) byVendor.set(d.vendorId, (byVendor.get(d.vendorId) ?? 0) + 1); |
| 41 | for (const [vid, count] of [...byVendor].sort((a, b) => b[1] - a[1])) { |
| 42 | console.info(` ${hex(vid)} ${(VENDOR_NAMES[vid] ?? "").padEnd(8)} ${count}`); |
| 43 | } |