From cad2cdbbe999ec90cca71e76a4fea979c1aadabf Mon Sep 17 00:00:00 2001 From: Manishrn Date: Sun, 30 Aug 2026 15:32:21 +0530 Subject: [PATCH] Ignore unsolicited/late HID input reports instead of throwing Wireless SpeechMikes (e.g. Ambient PSM5000) emit unsolicited status/handshake reports on connect, power-cycle and machine lock/unlock, and may deliver command replies after their 5s resolver has already timed out. These reach the final else-branch of onInputReport() and previously threw 'Unhandled input report from command N', flooding consumers and window.onerror. Log such reports at debug level and ignore them instead of throwing. The original caller was already rejected on timeout, and the late/stale reply is unusable, so nothing is lost. Adds a regression test covering an unrecognized input report. --- src/speechmike_hid_device.ts | 5 ++++- src/speechmike_hid_device_test.ts | 16 ++++++++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/src/speechmike_hid_device.ts b/src/speechmike_hid_device.ts index 8e571e0..3150395 100644 --- a/src/speechmike_hid_device.ts +++ b/src/speechmike_hid_device.ts @@ -369,7 +369,10 @@ export class SpeechMikeHidDevice extends DictationDeviceBase { } else if (this.commandResolvers.get(command) !== undefined) { await this.handleCommandResponse(command, data); } else { - throw new Error(`Unhandled input report from command ${command}`); + // Ignore extra status messages and slow replies from the device + // (common on wireless devices like the SpeechMike Ambient PSM5000, + // e.g. on device power off/on or machine lock/unlock). + console.debug(`Ignoring unhandled input report from command ${command}`); } } diff --git a/src/speechmike_hid_device_test.ts b/src/speechmike_hid_device_test.ts index c2979a8..09bebcd 100644 --- a/src/speechmike_hid_device_test.ts +++ b/src/speechmike_hid_device_test.ts @@ -474,6 +474,22 @@ describe('SpeechMikeHidDevice', () => { state.dictationDevice, MotionEvent.LAYED_DOWN); }); + it('ignores unrecognized input reports without throwing', async () => { + await createDictationDeviceForType(DeviceType.SPEECHMIKE_SMP_3700); + + // Wireless SpeechMikes (e.g. Ambient PSM5000) emit unsolicited + // status/handshake reports, and may deliver command replies after their + // resolver has timed out. Command 134 (0x86) matches neither a button, + // motion nor wireless-status event, and has no pending resolver, so it must + // be ignored rather than throwing. + await expectAsync( + state.fakeHidDevice.handleInputReport([134, 0, 0, 0, 0, 0, 0, 0, 0])) + .toBeResolved(); + + expect(state.buttonEventListener).not.toHaveBeenCalled(); + expect(state.motionEventListener).not.toHaveBeenCalled(); + }); + describe('handles input reports', () => { it('SpeechMikes_Pro', async () => { await createDictationDeviceForType(DeviceType.SPEECHMIKE_SMP_3700);