world’s simplest usb host application lane hauck [email protected]

33
World’s Simplest USB Host Application Lane Hauck [email protected]

Upload: loreen-floyd

Post on 17-Dec-2015

220 views

Category:

Documents


1 download

TRANSCRIPT

World’s Simplest USB Host Application

Lane [email protected]

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 31

Keypad NAKS, then ready

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.