Notes about writing usb slave drivers I passionately hate USB. Maybe I'm just dumb, but I think USB is horribly complex. I once mentioned this to a friend, who's a hardware (chip) guy, and he was surprised me saying so. The thing is that the hardware side of usb is actually quite simple, and that's why it's cheap. The software layers on top of it howerever are simply horrible. A marvelous example of design-by-committee[1], where an overly complex spec leads to to misunderstanding by developers that design devices, which leads to bugs that stick because the existence of workarounds on the host side -- introduced by a first generation of buggy devices -- never encourages developers to actually follow the specs since "it works, anyway". (Postel's law gone bad [2]). The big irony of USB is that it contains a lot of device classes that are supposed to be universal: one host driver handles them all. However, if you look at the host driver in in Linux, it still needs to identify the devices by their vendor:device ID in order to perform workarounds, because in reality many of these devices contain bugs. The dream does does seem to work in general for printers, disks, keyboards and mice. And audio and midi devices. So I'm going to assume I'm just dumb and will now go out to slay that dragon. [1] http://en.wikipedia.org/wiki/Design_by_committee [2] http://en.wikipedia.org/wiki/Robustness_principle Entry: Setup Date: Sun Mar 6 10:00:18 EST 2011 * Host: linux. This makes it easier to see what's actually going on. I'm using a KVM instance with a modified kernel. * Slave: AT91SAM7 + eCos to serve as example, but my real target is the PIC18F with drivers implemented in Staapl. Entry: Linux KVM workbench Date: Sun Mar 6 10:01:43 EST 2011 My test host is called `kers', which is a KVM running a debian 2.6.32 kernel. The idea is modify only the modules that are necessary for debugging. Starting kvm with the option "-usb -usbdevice host:056a:00d4" allows you to attach a particular USB device to the vm. Then to make the usbserial generic driver work, changing the identifier in drivers/usb/seria/generic.c or choosing the predefined identifier 05f9:ffff. Entry: USB docs Date: Sun Mar 6 10:02:50 EST 2011 The general USB1.1 doc is a good starting point [2]. Any later versions are simply too complex. The goal is to implement some device classes. Docs are here[1]. I'm implementing a driver for the PIC18F2550[3]. [1] http://www.usb.org/developers/devclass_docs [2] http://esd.cs.ucr.edu/webres/usb11.pdf [3] http://www.microchip.com/wwwproducts/Devices.aspx?dDocName=en010280 Entry: Staapl code on PIC18 Date: Mon Mar 7 12:44:55 EST 2011 Trivially compiling picstamp.fm, the file usb.f is missing. I have no idea where this went. Last code doing something[1] (It works "a bit"..). Todo: rewrite the whole .fm file into a Scheme module file. No Forth syntax for the driver. This is going to take a while as the `load' word is not supported in Scheme, and needs to be replaced with units. The 2 words that need to be plugged in are: - fosc - baud These are grabbed from the global context in monitor-serial-core.f and then passed on as parameters to the lower level modules. That seems to be a good idea: keep as much as possible in module form, using lexical parameters, and use "integration units" to pass parameters around. Is there a problem with p18f2550.f ? Currently it only includes p18f2550.f It's probably simplest to start at that file. Best would be something that can work directly from the header file. EDIT: added staapl/pic18/genheader.ss to compile an INC file to a scheme module. This triggers a problem with units: ROADMAP: - fix header file parsing DONE - fix low-level pic18 const dependenices (exercise for general unit problems) - fix p18f2550.f - fix monitor-serial-core.f [1] entry://../staapl/20090215-181941 [2] entry://../staapl/20110307-191827 Entry: libusb talk Date: Mon Mar 14 19:57:54 EDT 2011 Peter Stuge[1] Descriptors: Device (one per device) Configuration (mutually exclusive operation modes) Interface (independent behaviours) Endpoint (in/out channels per interface) [1] http://www.youtube.com/watch?v=SodMHKpykXw Entry: libusb, Racket FFI and PK2 Date: Tue Mar 29 12:14:36 EDT 2011 I've fixed some issues with the libusb FFI I'm using for the PK2 driver. Currently working on the PK2 ICSP/ICD protocol for use with the Staapl monitor, which I think is more important than the USB interface. Dev is going better than before now that I have a DSO to actually see what's going on. Entry: PK2 done Date: Fri Apr 8 14:32:08 EDT 2011 I've got the PK2 interface running reasonably reliably with asynch log display from PIC. Still some quirks that I expect to be either PK2 bugs, or improper PK2 init or error handling. So, time to tackle the USB. Let's stick to the previous organization: - Low level communications driver: handles all USB responses and transfers. - High level protocol: construction of per-device descriptors and endpoints. Entry: USB low-level Date: Fri Apr 8 14:35:32 EDT 2011 Following _usb.f : making sense of the different request dispatch levels. Each level is one decision down the tree, following only the first ones. level 0: dispatch UIR interrupts: error, soframe, idle, activity, stall, reset and transaction. level 1: transaction: - IN - OUT - SETUP level 2: SETUP - 0 GET_STATUS - 1 CLEAR_STATUS - 3 SET_FEATURE - 5 SET_ADDRESS - 6 GET_DESCRIPTOR - 7 SET_DESCRIPTOR - 8 GET_CONFIGURATION - 9 SET_CONFIGURATION - A GET_INTERFACE - B SET_INTERFACE level 3: GET_DESCRIPTOR - 1 DEVICE - 2 CONFIGURATION - 3 STRING - 4 INTERFACE - 5 ENDPOINT What about this: - generate macros for all code that simply returns a fixed reply packet. - use long names: SETUP.GET_DESCRIPTOR.DEVICE