The ADB protocol involves signal edges as often as every 25us, and V-USB's interrupt handler can take over 100us (and is cycle-timed, so cannot be interrupted). This requires that we synchronize with USB interrupts and do ADB transactions *between* them. Even doing ADB using the AVR's capture and PWM wouldn't work around this, due to the frequency of events relative to how long V-USB's interrupt handler can take. The USB interrupt packet comes every 8ms, leaving sufficient time for the 4ms of ADB polling/reply activity. Since USB packets for other devices can occur between this, usbdrv has been modified to set a global variable when our 8ms packet is received. This way we can disable interrupts between and ignore the other packets without error.
When the host is updating a USB keyboard's LEDs, it sends these commands between the usual 8ms packets. These would be lost while doing ADB polling during that time. So the code waits a few ms after the 8ms packet for any more, before doing ADB polling. If it receives an LED change packet during that time, it skips ADB polling for that period and resumes after the next 8ms packet. See timing-leds.png: just after +10ms, the Num Lock key is pressed and the ADB poll receives that. Then the next 8ms USB packet comes in, followed by three more to change the LED state. ADB polling is skipped there. Then the next two normal ADB polls occur, and after +40ms the ADB commands to change the keyboard LED are sent.