You are viewing [info]lukego's journal

Luke's Weblog - USB [entries|archive|friends|userinfo]
Luke Gorrie

[ website | My Website ]
[ userinfo | livejournal userinfo ]
[ archive | journal archive ]

USB [Apr. 7th, 2009|06:39 pm]
Previous Entry Add to Memories Share Next Entry
Here's what I've discovered about some kinds of USB device:
  • Keyboard and mouse: they support a simplified bootstrap mode that's very simple to deal with. Here's a driver for the common parts of bootstrap-mode keyboard and mouse:
    USBHID : USBDevice ()
    
    USBHID init: devicename
    [
      super init: (OFW open: devicename).
      self setConfiguration: 1.
      self setBootstrapProtocol.
    ]
    
    USBHID setBootstrapProtocol
    [
      self controlSetIndex: 0 value: 0
           requestType: (DR_HIDD bitOr: DR_OUT) request: SET_PROTOCOL
    ]
    
    USBHID setIdle: ms
    [
      self controlSetIndex: 0 value: (ms // 4 << 8)
           requestType: (DR_HIDD bitOr: DR_OUT) request: SET_IDLE
    ]
    
    USBHID selftest
    [
      self init.
      1000 timesRepeat: [ self readReport ifNotNilDo: [ :e | e println]. ]
    ]
    
    and here's a subclass that knows how to turn the reports into mouse events:
    USBMouse : USBHID ()
    
    USBMouse init         [ self init: '/mouse' ]
    USBMouse init: device [ super init: device. self setIdle: 0 ]
    
    USBMouse readReport   [ ^MouseEvent fromUSB: (self intrIn: 1) ]
    
    MouseEvent fromUSB: report
    [
      self := self new.
      left  := (report first bitAnd: 1) ~~ 0.
      right := (report first bitAnd: 2) ~~ 0.
      dx := report second.
      dy := report third.
      "Treat bit 8 as sign."
      (dx bitAnd: 0x80) ~~ 0 ifTrue: [ dx := dx - 256 ].
      (dy bitAnd: 0x80) ~~ 0 ifTrue: [ dy := dy - 256 ].
    ]
    
    The keyboard is similar: it reports the set of keys (identified by scancode) that are currently pressed, and uses a fixed mapping from scancodes onto key identifiers.

    I regret that I haven't come back to look at the full-blown USB Human Input Device protocol yet!

  • Ethernet: In theory the USB Communications Device Class specifies the high-level interface for ethernet-like network adapters, but in practice most USB-ethernet dongles seem to be built from an ASIX USB-ethernet chip. For example, the Apple USB-ethernet dongle is internally an ASIX 88772A.

    ASIX chips aren't compatible with the USB CDC standard, they use their own custom protocol instead. The protocol is simple but it's lower-level than CDC: you're sometimes peeking and poking registers instead of exchanging messages.

  • Display: My previous posts (first, second) describe the USB-VGA adapter I found. I'm unhappy with this device: taking a notoriously closed graphics chip and blindly bridging its PCI bus onto USB is really kludgy. The components don't even seem to be particularly cheap (Octopart suggests $15 for the USB-PCI bridge chip) so I suppose the intention was to save development money by not having to program the dongle. I'd be happier if they'd spent the same money on an ARM- or FPGA- based dongle and programmed it to do the job gracefully, but that's me being a naive software guy.
I'm finding driver writing frustratingly slow going. I'm used to a very experimental and exploratory programming style, but that's not very effective because when you make a mistake the devices won't tell you where! This reminds me of talking to SIM cards and web services. I'm looking for a smarter working style.
LinkReply

Comments:
[User Picture]From: [info]kragen
2009-05-20 12:28 am (UTC)

(Link)

Pretty cool stuff. Any idea what the simplified bootstrap interface is called?
From: (Anonymous)
2009-05-20 09:12 am (UTC)

(Link)

The details are in the main USB HID standard that's online in PDF -- it's called something like "bootstrap protocol" and intended for BIOSes. I'd chase up the link but I'm on a klunky airport internet terminal that only allows one non-tabbed Internet Explorer window to be open on the machine.. my god, what year is this?