world’s simplest usb host application lane hauck [email protected]
TRANSCRIPT
Embedding USB Embedded Systems Conference, March 2002 2
Question
How simple can embedded host firmware be?
Let’s figure out a really simple (but useful) interface and write the code.
Application
Host Controller
Embedding USB Embedded Systems Conference, March 2002 3
A USB “Point Solution”
Scope Trigger
8051
CS#
WR#
A0
RD#
PB1
PB0
PA0
EZ-USBDevelopment
Board
D[7..0]
CS#
WR#
A0
RD#
M/S#
RES#
SL-811USB HostController
USB D+D-
USBKeypadHost
Firmware
Demo
Embedding USB Embedded Systems Conference, March 2002 4
USB Enumeration
1. Detect device2. Detect speed3. Issue USB bus reset4. Get Descriptor: Device5. Set Address6. Get Descriptor: Configuration7. Get String: Product8. Set Configuration
Embedding USB Embedded Systems Conference, March 2002 5
Assumptions save codeInitial conditions are known
1. Detect device It’s plugged in2. Detect speed Low speed3. Issue USB bus reset4. Get Descriptor: Device 5. Set Address6. Get Descriptor: Configuration7. Get String: Product8. Set Configuration
Embedding USB Embedded Systems Conference, March 2002 6
How about the descriptors?
They’re fixed (hardwired) in the keypad They are the same every time we ask
for them• With a “Get_Descriptor” request
If we know them in advance, we can save the code that asks for and interprets them
Device assumptions save code• But limit our code to a specific device
Embedding USB Embedded Systems Conference, March 2002 7
Assumptions save codeThe keypad’s device
descriptor
Offset Field Description Value0 bLength Length of this descriptor = 18 bytes 12H1 bDescriptorType Descriptor Type = Device 01H2 bcdUSB (L) USB spec version 1.00 (L) 00H3 bcdUSB (H) USB spec version 1.00 (H) 01H4 bDeviceClass Device class (FF is vendor-specific) 00H5 bDeviceSubClass Device sub-class (FF is vendor-specific) 00H6 bDeviceProtocol Device Protocol (FF is vendor-specific) 00H7 bMaxPacketSize0 Max packet size for EP0 08H8 idVendor (L) Vendor id (L) 18H9 idVendor (H) Vendor id (H) 06H
10 idProduct (L) Product id (L) 00H11 idProduct (H) Product id (H) 03H12 bcdDevice (L) Device release Number (BCD,L) 20H13 bcdDevice (H) Device release Number (BCD,H) 01H14 iManufacturer Manufacturer index string 04H15 iProduct Product index string 0EH16 iSerialNumber Serial number index string 00H17 bNumConfigurations Number of configurations in this interface 01H
Embedding USB Embedded Systems Conference, March 2002 8
Assumptions save codeThe keypad’s device
descriptor
Offset Field Description Value0 bLength Length of this descriptor = 18 bytes 12H1 bDescriptorType Descriptor Type = Device 01H2 bcdUSB (L) USB spec version 1.00 (L) 00H3 bcdUSB (H) USB spec version 1.00 (H) 01H4 bDeviceClass Device class (FF is vendor-specific) 00H5 bDeviceSubClass Device sub-class (FF is vendor-specific) 00H6 bDeviceProtocol Device Protocol (FF is vendor-specific) 00H7 bMaxPacketSize0 Max packet size for EP0 08H8 idVendor (L) Vendor id (L) 18H9 idVendor (H) Vendor id (H) 06H
10 idProduct (L) Product id (L) 00H11 idProduct (H) Product id (H) 03H12 bcdDevice (L) Device release Number (BCD,L) 20H13 bcdDevice (H) Device release Number (BCD,H) 01H14 iManufacturer Manufacturer index string 04H15 iProduct Product index string 0EH16 iSerialNumber Serial number index string 00H17 bNumConfigurations Number of configurations in this interface 01H
Conclusion: EP0 has 8 byte max packet size
Embedding USB Embedded Systems Conference, March 2002 9
Assumptions save codeConfig. & interface
descriptors
Offset Field Description Value0 bLength Length of this descriptor = 9 bytes 09H1 bDescriptorType Descriptor Type = Configuration 02H2 wTotalLength (L) Total length (L) incl. IF & EP descriptors 22H3 wTotalLength (H) Total length (H) 00H4 bNumInterfaces Number of interfaces in this configuration 01H5 bConfigurationValue Configuration value 01H6 iConfiguration Index of string describing this configuration 00H7 bmAttributes Attributes - bus powered, no remote wakeup 80H8 MaxPower Max power - 100 ma 32H0 bLength Length of the interface descriptor 09H1 bDescriptorType Descriptor Type = Interface 04H2 bInterfaceNumber Zero based index of this interface = 0 00H3 bAlternateSetting Alternate setting value = 0 00H4 bNumEndpoints Number of endpoints in this interface 01H5 bInterfaceClass Interface class 03 = HID 03H6 bInterfaceSubClass Interface sub-class 00H7 bInterfaceProtocol Interface protocol 01H8 iInterface Index to string descriptor for this interface 00H
Embedding USB Embedded Systems Conference, March 2002 10
Assumptions save codeConfig. & interface
descriptors
Offset Field Description Value0 bLength Length of this descriptor = 9 bytes 09H1 bDescriptorType Descriptor Type = Configuration 02H2 wTotalLength (L) Total length (L) incl. IF & EP descriptors 22H3 wTotalLength (H) Total length (H) 00H4 bNumInterfaces Number of interfaces in this configuration 01H5 bConfigurationValue Configuration value 01H6 iConfiguration Index of string describing this configuration 00H7 bmAttributes Attributes - bus powered, no remote wakeup 80H8 MaxPower Max power - 100 ma 32H0 bLength Length of the interface descriptor 09H1 bDescriptorType Descriptor Type = Interface 04H2 bInterfaceNumber Zero based index of this interface = 0 00H3 bAlternateSetting Alternate setting value = 0 00H4 bNumEndpoints Number of endpoints in this interface 01H5 bInterfaceClass Interface class 03 = HID 03H6 bInterfaceSubClass Interface sub-class 00H7 bInterfaceProtocol Interface protocol 01H8 iInterface Index to string descriptor for this interface 00H
Conclusion: One config (=
1)
Embedding USB Embedded Systems Conference, March 2002 11
Assumptions save codeEndpoint & HID descriptors
Offset Field Description Value0 bLength length of this endpoint descriptor 07H1 bDescriptorType Descriptor Type = Endpoint 05H2 bEndpointAddress endpoint direction (1 is in) and address = IN1 81H3 bmAttributes xfr type = ISO(01) BULK(10) INT (11) 03H4 wMaxPacketSize (L) max packet size 04H5 WMaxPacketSize (H) max packet size - high 00H6 bInterval polling interval in milliseconds = 10 msec 0AH
Offset Field Description Value0 bLength length of the configuration descriptor 09H1 bDescriptorType Descriptor Type = HID 21H2 bcdHIDL HID Spec version (BCD) L 00H3 bcdHIDH HID Spec version (BCD) H 01H4 bCountryCode 00 means 'not localized' 00H5 bNumDescriiptors Number of class descriptors (one: report) 01H6 bDescriptorType Type of class descriptor. 22 = 'report' 22H7 bDescriptorLengthL Total size of report descriptor L 3FH8 bDescriptorLengthH Total size of report descriptor H 00H
Note: In HID version 1.1 the order of these descriptors is HID, Endpoint.
Embedding USB Embedded Systems Conference, March 2002 12
Assumptions save codeEndpoint & HID descriptors
Offset Field Description Value0 bLength length of this endpoint descriptor 07H1 bDescriptorType Descriptor Type = Endpoint 05H2 bEndpointAddress endpoint direction (1 is in) and address = IN1 81H3 bmAttributes xfr type = ISO(01) BULK(10) INT (11) 03H4 wMaxPacketSize (L) max packet size 04H5 WMaxPacketSize (H) max packet size - high 00H6 bInterval polling interval in milliseconds = 10 msec 0AH
Offset Field Description Value0 bLength length of the configuration descriptor 09H1 bDescriptorType Descriptor Type = HID 21H2 bcdHIDL HID Spec version (BCD) L 00H3 bcdHIDH HID Spec version (BCD) H 01H4 bCountryCode 00 means 'not localized' 00H5 bNumDescriiptors Number of class descriptors (one: report) 01H6 bDescriptorType Type of class descriptor. 22 = 'report' 22H7 bDescriptorLengthL Total size of report descriptor L 3FH8 bDescriptorLengthH Total size of report descriptor H 00H
Note: In HID version 1.1 the order of these descriptors is HID, Endpoint.
Conclusion: Send IN
tokens to EP1
Embedding USB Embedded Systems Conference, March 2002 13
Assumptions save codeHID Report descriptor
It’s complicated• The HID spec is 100 pages long and handles
such issues as how to report controls attached to various body parts.
• It helps an application discover the capabilities of any Human-Interface Device attached to a PC without prior knowledge of the device.
All we really need to know:• Keystroke data is delivered in 3-byte packets,
with the keypress code in the third byte. We could deduce this by deciphering the HID
descriptor, or by watching a little bus traffic.
Embedding USB Embedded Systems Conference, March 2002 14
What we know in advance
It’s a low-speed HID (keypad) • It reports data on EP1-IN
– Which is an INTERRUPT endpoint with an 8-byte MaxPacketSize
It responds to IN requests with a 3-byte payload.
The keycode is in the third byte
Embedding USB Embedded Systems Conference, March 2002 15
Init. code simplifies to this
1. Detect device2. Detect speed 3. Issue USB bus reset4. Get Descriptor: Device 5. Set Address6. Get Descriptor: Configuration7. Get String: Product8. Set Configuration
Embedding USB Embedded Systems Conference, March 2002 16
Operation code is simple
Send 1 msec “keep alive” pulses (EOP) so the keypad doesn’t suspend.• Automatic, just initialize the 811H chip
Whenever we feel like it, send an IN token.• If the keypad has a new keycode to report,
it responds with a DATA PID and 3 bytes of data.
• If it doesn’t, it sends a NAK PID. If we get data, use it.
• 811H chip automatically ACKS the transfer
Embedding USB Embedded Systems Conference, March 2002 17
Our IN RequestKeypad has no new data
Sync00000001
IN10010110
AD0000001
EP0001
CRC5
xy
Sync00000001
NAK10100101
Host (us)
Keypad
Embedding USB Embedded Systems Conference, March 2002 18
Our IN RequestKeypad reports a new
keystroke
Sync00000001
IN10010110
AD0000001
EP0001
CRC5
xy
Sync00000001
ACK01001011
Sync00000001
DATA0/110010110
CRC16
wxyz
DataA B CKeypad
Host (us)
Host (us)
Embedding USB Embedded Systems Conference, March 2002 19
Code-1Initialize the 811H and USB
void main(void) {BYTE result;// set up the EZ-USB chip to talk to the 811 chip and provide a scope triggerPORTCCFG = 0xC0; // enable RD, WR pinsOEB = 0x03; // PB0 is SL811 RESET, PB1 is Host/Slave pin)OEA = 0x01; // PA0 is scope triggerSCOPE_LO; // initialize scope trigger// Reset the SL811H chipOUTB = 0x00; // PB1=0 means we're the hostdelay(1000);OUTB = 0x01; // remove reset, keep PB1 LOW for SLAVE
// SL811 initializationwr811(BUFADR,0x10); // start of SETUP/IN internal data bufferwr811(BUFLEN,0x08); // reserve 8 bytes// (1) Reset the USB device. This makes it listen to address 0.wr811(CTL1,USB_RESET); // Speed=1(L), JKFORCE=1, SOFEN=1delay(10000); // about 18 millisecondswr811(CTL1,USB_OPERATE);// Enable sending 1 msec EOP's (the low-speed version of SOF's)wr811(SOFCT_L, 0xE0); // Set the SOF generator time constantwr811(SOFCT_H, 0x2E | 0xC0); // 1 msec SOF rate, b7=HOST, b6=POLSWAP
Embedding USB Embedded Systems Conference, March 2002 21
Review:CONTROL (CTL) transfer
IN
ADDR
ENDP
CRC5
Token Packet
DATA1
PayloadData
CRC16
Data Packet
ACK
H/S Pkt
H P H
DA
TA
H H P H H P
DATA1
OUT
ADDR
ENDP
CRC5
Token Packet
CRC16
Data Pkt
NAK
H/S Pkt
DATA1
OUT
ADDR
ENDP
CRC5
Token Packet
CRC16
Data Pkt
ACK
H/S Pkt
(Operation not completed) (Operation completed)HA
ND
SH
AK
EDATA0
8 bytesSetupData
CRC16
Data Packet
ACK
H/S Pkt
SETUP
ADDR
ENDP
CRC5
Token Packet
H H P
SE
TU
PH is Host
P is Peripheral
Set_Address & Set_Configuration data is contained in the SETUP stage, so no DATA stage is required.
Embedding USB Embedded Systems Conference, March 2002 23
Code-2Issue Set_Address CTL
transfer
// (2) Issue a SET_ADDRESS USB request, setting the peripheral address to 1// From the USB spec, Chapter 9, here is the data for a "SET_ADDRESS" request:// Note: every SL811_DATA load increments an internal SL811 address pointerSL811_ADDR = 0x10; // next SL811_DATA byte goes hereSL811_DATA = 0x00; // bmRequestType (h->d,std request,device is recipient)SL811_DATA = 0x05; // bRequest (SET_ADDRESS)SL811_DATA = 0x01; // wValueL (device address)--we're setting it to ONESL811_DATA = 0x00; // wValueH (zero)SL811_DATA = 0x00; // wIndexL (zero)SL811_DATA = 0x00; // wIndexH (zero)SL811_DATA = 0x00; // wLengthL (zero)SL811_DATA = 0x00; // wLengthH (zero)wr811(FNADDR,0x00); // USB address zerowr811(PID_EP,SETUP_PID | 0x00); // SETUP PID, EP0result=go(0x07); // DIREC=1(out), ENAB=1, ARM=1// STATUS stage is a no-data IN to EP0wr811(PID_EP,IN_PID | 0x00); // IN PID, EP0result=go(0x03); // Don't sync to SOF, DIREC=0(in), ENAB, ARM
Embedding USB Embedded Systems Conference, March 2002 24
// (2) Issue a SET_ADDRESS USB request, setting the peripheral address to 1// From the USB spec, Chapter 9, here is the data for a "SET_ADDRESS" request:// Note: every SL811_DATA load increments an internal SL811 address pointerSL811_ADDR = 0x10; // next SL811_DATA byte goes hereSL811_DATA = 0x00; // bmRequestType (h->d,std request,device is recipient)SL811_DATA = 0x05; // bRequest (SET_ADDRESS)SL811_DATA = 0x01; // wValueL (device address)--we're setting it to ONESL811_DATA = 0x00; // wValueH (zero)SL811_DATA = 0x00; // wIndexL (zero)SL811_DATA = 0x00; // wIndexH (zero)SL811_DATA = 0x00; // wLengthL (zero)SL811_DATA = 0x00; // wLengthH (zero)wr811(FNADDR,0x00); // USB address zerowr811(PID_EP,SETUP_PID | 0x00); // SETUP PID, EP0result=go(0x07); // DIREC=1(out), ENAB=1, ARM=1// STATUS stage is a no-data IN to EP0wr811(PID_EP,IN_PID | 0x00); // IN PID, EP0result=go(0x03); // Don't sync to SOF, DIREC=0(in), ENAB, ARM
D-
PA0
Code-2On the wire
Embedding USB Embedded Systems Conference, March 2002 25
// (2) Issue a SET_ADDRESS USB request, setting the peripheral address to 1// From the USB spec, Chapter 9, here is the data for a "SET_ADDRESS" request:// Note: every SL811_DATA load increments an internal SL811 address pointerSL811_ADDR = 0x10; // next SL811_DATA byte goes hereSL811_DATA = 0x00; // bmRequestType (h->d,std request,device is recipient)SL811_DATA = 0x05; // bRequest (SET_ADDRESS)SL811_DATA = 0x01; // wValueL (device address)--we're setting it to ONESL811_DATA = 0x00; // wValueH (zero)SL811_DATA = 0x00; // wIndexL (zero)SL811_DATA = 0x00; // wIndexH (zero)SL811_DATA = 0x00; // wLengthL (zero)SL811_DATA = 0x00; // wLengthH (zero)wr811(FNADDR,0x00); // USB address zerowr811(PID_EP,SETUP_PID | 0x00); // SETUP PID, EP0result=go(0x07); // DIREC=1(out), ENAB=1, ARM=1// STATUS stage is a no-data IN to EP0wr811(PID_EP,IN_PID | 0x00); // IN PID, EP0result=go(0x03); // Don't sync to SOF, DIREC=0(in), ENAB, ARM
Code-2CATC trace
Embedding USB Embedded Systems Conference, March 2002 26
Code-3Issue Set_Config. CTL
Transfer
// (3) Send a CONTROL transfer to select configuration #1. Until we do this// the device is in an "unconfigured" state and probably won't send data.// Again, from USB spec Chapter 9:SL811_ADDR = 0x10; // reset pointer to beginning of internal buffer.SL811_DATA = 0x00; // bmRequestType (h->d,std request,device is recipient)SL811_DATA = 0x09; // bRequest (SET_CONFIGURATION)SL811_DATA = 0x01; // wValueL (configuration = 1)SL811_DATA = 0x00; // wValueH (zero)SL811_DATA = 0x00; // wIndexL (zero)SL811_DATA = 0x00; // wIndexH (zero)SL811_DATA = 0x00; // wLengthL (zero)SL811_DATA = 0x00; // wLengthH (zero)wr811(FNADDR,0x01); // now talking to USB device at address 1wr811(PID_EP,SETUP_PID | 0x00); // OR in the endpoint (zero)result=go(0x07); // DIREC=1(out), ENAB=1, ARM=1// STATUS stage is a no-data IN to EP0wr811(PID_EP,IN_PID | 0x00); // IN PID, EP0result=go(0x03); // DIREC=0(in), ENAB=1, ARM=1
Embedding USB Embedded Systems Conference, March 2002 27
// (3) Send a CONTROL transfer to select configuration #1. Until we do this// the device is in an "unconfigured" state and probably won't send data.// Again, from USB spec Chapter 9:SL811_ADDR = 0x10; // reset pointer to beginning of internal buffer.SL811_DATA = 0x00; // bmRequestType (h->d,std request,device is recipient)SL811_DATA = 0x09; // bRequest (SET_CONFIGURATION)SL811_DATA = 0x01; // wValueL (configuration = 1)SL811_DATA = 0x00; // wValueH (zero)SL811_DATA = 0x00; // wIndexL (zero)SL811_DATA = 0x00; // wIndexH (zero)SL811_DATA = 0x00; // wLengthL (zero)SL811_DATA = 0x00; // wLengthH (zero)wr811(FNADDR,0x01); // now talking to USB device at address 1wr811(PID_EP,SETUP_PID | 0x00); // OR in the endpoint (zero)result=go(0x07); // DIREC=1(out), ENAB=1, ARM=1// STATUS stage is a no-data IN to EP0wr811(PID_EP,IN_PID | 0x00); // IN PID, EP0result=go(0x03); // DIREC=0(in), ENAB=1, ARM=1
D-
PA0
Code-3On the wire
Embedding USB Embedded Systems Conference, March 2002 28
// (3) Send a CONTROL transfer to select configuration #1. Until we do this// the device is in an "unconfigured" state and probably won't send data.// Again, from USB spec Chapter 9:SL811_ADDR = 0x10; // reset pointer to beginning of internal buffer.SL811_DATA = 0x00; // bmRequestType (h->d,std request,device is recipient)SL811_DATA = 0x09; // bRequest (SET_CONFIGURATION)SL811_DATA = 0x01; // wValueL (configuration = 1)SL811_DATA = 0x00; // wValueH (zero)SL811_DATA = 0x00; // wIndexL (zero)SL811_DATA = 0x00; // wIndexH (zero)SL811_DATA = 0x00; // wLengthL (zero)SL811_DATA = 0x00; // wLengthH (zero)wr811(FNADDR,0x01); // now talking to USB device at address 1wr811(PID_EP,SETUP_PID | 0x00); // OR in the endpoint (zero)result=go(0x07); // DIREC=1(out), ENAB=1, ARM=1// STATUS stage is a no-data IN to EP0wr811(PID_EP,IN_PID | 0x00); // IN PID, EP0result=go(0x03); // DIREC=0(in), ENAB=1, ARM=1
Code-3CATC trace
Embedding USB Embedded Systems Conference, March 2002 29
Code-4Ping the keypad, display new
data
// (4) Send constant IN requests to Addr 1, EP1
wr811(PID_EP,IN_PID | 0x01); // set up for IN PIDS to endpoint 1
while(1) {
SL811_ADDR = 0x10; // reset pointer to beginning of internal buffer waitframes(4); // send the IN requests every n milliseconds
result=go(0x03); // DIREC=0(in), ENAB=1, ARM=1
if (result & 0x01) // look only for ACK
display_hex(rd811(0x12)); } // KB value is in third byte of 3-byte packet
Embedding USB Embedded Systems Conference, March 2002 30
Entire startup sequence
D-
PA0
SetAddress
Handshake Set Config
Handshake IN:Dev=1, EP=1
EOP
Embedding USB Embedded Systems Conference, March 2002 32
Code-5Housekeeping
void wr811(BYTE address, BYTE value){
SL811_ADDR = address;SL811_DATA = value;
}BYTE rd811(BYTE address){
SL811_ADDR = address;return SL811_DATA;
}
BYTE go(BYTE cmd) { // Launch an 811H operation.
SCOPE_HI;
wr811(INTSTATUS,0x01); // clear the DONE bit
wr811(CTL,cmd); // start the operation
delay(100);
while(rd811(INTSTATUS) & 0x01==0) { } // spin while "done" bit is low
SCOPE_LO;
return rd811(PKTSTAT); } // return the status of this transfer
Embedding USB Embedded Systems Conference, March 2002 33
Code Size
* * * * * * * C O D E M E M O R Y * * * * * * * CODE 0000H 0003H ABSOLUTE 0003H 00FDH *** GAP *** CODE 0100H 00DDH UNIT ?PR?MAIN?MINHOST CODE 01DDH 008CH UNIT ?C_C51STARTUP CODE 0269H 003FH UNIT ?PR?_DISPLAY_HEX?MINHOST CODE 02A8H 0037H UNIT ?PR?_WAITFRAMES?MINHOST CODE 02DFH 0027H UNIT ?PR?_GO?MINHOST CODE 0306H 0014H UNIT ?C_INITSEG CODE 031AH 000FH UNIT ?PR?_WR811?MINHOST CODE 0329H 000BH UNIT ?PR?_DELAY?MINHOST CODE 0334H 0009H UNIT ?PR?_RD811?MINHOST
350 bytes
Embedding USB Embedded Systems Conference, March 2002 34
Creeping Elegance
Detect device plug-in Put the device to sleep (suspend)
• Easy—just disable 1 msec EOP’s Wake up the device (resume)
• Start sending EOP’s again Operate through a hub
• Keep track of more than one device address
Embedding USB Embedded Systems Conference, March 2002 35
Resources: www.usb.org
Tools USBCV Beta 2 - Windows 2000 and Windows XP only The installation utility, USBCVBeta2.msi (11 MB), contains USB Command
Verifier (USBCV) version 0.9.0.6. USBCV is the new compliance test tool which evaluates High, Full and Low-speed USB devices for conformance to the USB Device Framework (Chapter 9), Hub device class (Chapter 11), and HID specifications. USBCV is a replacement for USBCheck and is the preferred compliance tool to be used at this time. The final release of USBCV is expected to occur no later than Q2 2002. At that time USBCheck will be made obsolete and removed from this site. Users are encouraged to immediately use USBCV along with or instead of USBCheck. Until USBCheck is made obsolete, test results from either tool are considered by the compliance team to have equal weight. This version of USBCV was posted on 1/22/02. This software release will only work on Windows 2000 and Windows XP. Please check the release notes and accompanying documentations for details on using USBCV and how to provide the USB-IF feedback on issues and suggestions. This software is provided courtesy of Intel Corporation.