A DIY USB Mouse Jiggler
Jun 21, 2020 tech embeddedThe Great Pandemic Lockdown of 2020 forced companies to adopt remote work. With no existing provisions for WFH, bizarre ad-hoc setups emerged. A case in point, my roommate was issued two laptops: One for development and a second locked down machine to connect to production servers. The second laptop was configured with a very aggressive lock screen timeout with no way to change or disable it. This made keeping an eye on prod rather annoying.
One way to prevent Windows from locking the screen is by simulating user activity: say moving the mouse. This would have been trivial to accomplish in software if it wasn’t for the administrative policy restricting which applications could be run.
This seems to be a common enough occurrence in corporate environments that there are companies that sell purpose-built hardware to mitigate the situation. Basically, these devices pretend to be a USB mouse or keyboard and periodically send random mouse events or keystrokes to the connected host computer. Getting hold of one of these seems unlikely in the current situation. Building one was the only option. Fortunately, I had a Stellaris Launchpad lying around, (literally) gathering dust that was perfect for this.
The board has a USB capable ARM Cortex microcontroller onboard and can be used with a USB stack that TI provides royalty-free. All I had to do was to figure out how to configure the USB stack to emulate a USB HID mouse. The documentation refers to a usb_dev_mouse
example application but I for one was unable to find it in the TivaWare package. The TivaWare USB Library is fairly straightforward to use. Apart from the minimal boiler-plate, it is almost as simple as Arduino’s Mouse library. Coupled with the Driverlib HAL to configure the timer, I was able to get a mouse jiggler working in short order. The USB string descriptors took up more lines of code than the actual application:
void
timerISR (void)
{
// Clear the timer interrupt source to avoid being triggered again
// immediately on exit
TimerIntClear (TIMER0_BASE, TIMER_TIMA_TIMEOUT);
// Disable interrupts so we can get some work done
IntMasterDisable ();
// Move the cursor by a pixel along each axis in a random direction
int8_t x = (rand () & 1) ? 1 : -1;
int8_t y = (rand () & 1) ? 1 : -1;
USBDHIDMouseStateChange ((void *) &g_jiggler, x, y, 0);
IntMasterEnable ();
}
int
main (void)
{
// Configure the clock to directly run from the crysal oscillator
SysCtlClockSet (SYSCTL_SYSDIV_1 | SYSCTL_USE_OSC | SYSCTL_OSC_MAIN |
SYSCTL_XTAL_16MHZ);
SysCtlPeripheralEnable (SYSCTL_PERIPH_TIMER0);
// Enable the USB peripheral
SysCtlPeripheralEnable (SYSCTL_PERIPH_GPIOD);
GPIOPinTypeUSBAnalog (GPIO_PORTD_BASE, GPIO_PIN_4 | GPIO_PIN_5);
// Configure the Timer to fire every 30 seconds
TimerConfigure (TIMER0_BASE, TIMER_CFG_PERIODIC);
TimerLoadSet (TIMER0_BASE, TIMER_A, SysCtlClockGet () * 30);
IntEnable (INT_TIMER0A);
TimerIntEnable (TIMER0_BASE, TIMER_TIMA_TIMEOUT);
TimerEnable (TIMER0_BASE, TIMER_A);
USBStackModeSet (0, USB_MODE_DEVICE, 0);
// Initialize the USB controller and attach the mouse jiggler
// device to the USB bus
USBDHIDMouseInit (0, (tUSBDHIDMouseDevice *) &g_jiggler );
// Enable processor interrupts
IntMasterEnable ();
while (1);
}
So, with the jiggler attached and the laptop hooked up to a TV screen, my roommate can monitor prod and continue to lose sleep in peace.