I am working on a project using the SMI (Secondary Memory Interface) peripheral found on most raspberry pi models (Pre Pi 5) to implement a bit-banged USB Low Speed HID Host. Primarily intended for using USB keyboards.
I have gotten decently far in having successfully implemented NRZI packet encoding/decoding, data transmission, device enumeration, and polling, albeit only with my test keyboard thus far (see attached video below).
I am having an issue however where due to the software processing of the data received packets often come in corrupted. The program is not fast enough to analyze a packet before the ACK timeout elapses and so simply heuristically ACKs every received data packet and re-requests if the data is corrupted. This is an acceptable tradeoff for a keyboard driver as no important data is likely to be lost in transit.
Where this becomes an issue however is that the USB-HID protocol defines an Idle interval, wherein the keyboard will respond to further polling requests with a NAK packet as opposed to a full key report in order to save bandwidth if the pressed keys have not changed, meaning that if the initial packet gets corrupted the program has no way of knowing which keys are pressed until this idle period expires. The HID Spec mandates a command "set_idle" where this interval can be set but it seems a large number of USB keyboards do not implement this correctly including the devices I am testing with which have an indefinite idle interval and so will never send another report untill the pressed keys are changed.
There is also supposedly another option the "get_report" command which is supposed to allow requesting a report via the control endpoint, but my test keyboard seems to incorrectly implement this as well.
If any of y'all have any ideas on how I can force a full report from the keyboard in the event of a corrupted packet I am all ears. I have attached a repository link and a (poorly shot) showcase video below.
EDIT: I have largely fixed the error problem. My RX buffer parsing function was incredibly naive in assuming that signal noise would only mess with the contents of each NRZI run and not the length. I have since amended it to handle each run in one go and extrapolate how many bits the length corresponds to instead of taking a certain number of samples and assuming they align to bit boundaries. This has reduced the error rate to practically zero and it now enumerates and polls the test keyboard perfectly. Now all I have to do is figure out why polling is not working on other keyboards.
github.com/StrayerRussell/rpi_smi_usb
https://youtu.be/Oza2_v8EOi8