Revision:
0:63d45df56584
Child:
1:4461071ed964
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/UsbStructures.h	Sun Jul 08 20:18:58 2012 +0000
@@ -0,0 +1,452 @@
+/**
+    A host controller driver from the mBed device.
+    Copyright (C) 2012  Richard e Collins - richard.collins@linux.com
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+    
+    This is just a container header for all the stuctures I use in talking to the usb device and host controller.
+    Some are real packets sent, some are structures used by the hardware host controller.
+    
+    Some of the objects here maybe accessed by the Host controller.
+    Some are here just for the driver. I could have 'hid' them in the driver
+    but did not so to keep the code less cluttered and more readable.
+
+*/
+
+#ifndef __USB_STRUCTURES_H__
+#define __USB_STRUCTURES_H__
+
+namespace USB
+{
+
+/**
+ * The device descriptor of a USB device represents the entire device.
+ * As a result a USB device can only have one device descriptor.
+ * It specifies some basic, yet important information about the device such as the supported USB version, maximum packet size,
+ * vendor and product IDs and the number of possible configurations the device can have.
+ * 
+ * The bcdUSB field reports the highest version of USB the device supports.
+ *      The value is in binary coded decimal with a format of 0xJJMN where JJ is the major version number, M is the minor version number and N is the sub minor version number.
+ *      e.g. USB 2.0 is reported as 0x0200, USB 1.1 as 0x0110 and USB 1.0 as 0x0100.
+ * 
+ * The bDeviceClass, bDeviceSubClass and bDeviceProtocol are used by the operating system to find a class driver for your device.
+ *      Typically only the bDeviceClass is set at the device level. Most class specifications choose to identify itself at the interface level and as a result set the bDeviceClass as 0x00.
+ *      This allows for the one device to support multiple classes.
+ * 
+ * The bMaxPacketSize field reports the maximum packet size for endpoint zero. All devices must support endpoint zero.
+ * 
+ * The idVendor and idProduct are used by the operating system to find a driver for your device. The Vendor ID is assigned by the USB-IF.
+ * 
+ * The bcdDevice has the same format than the bcdUSB and is used to provide a device version number. This value is assigned by the developer.
+ * 
+ * Three string descriptors exist to provide details of the manufacturer, product and serial number.
+ *      There is no requirement to have string descriptors. If no string descriptor is present, a index of zero should be used.
+ * 
+ * bNumConfigurations defines the number of configurations the device supports at its current speed.
+ */
+struct DeviceDescription
+{
+    uint8_t  length;            //Size of the Descriptor in Bytes (18 bytes)
+    uint8_t  descriptorType;    //Device Descriptor (0x01)
+    uint16_t usbVersion;            //USB Specification Number which device complies too. BCD format.
+    uint8_t  deviceClass;      //Class Code (Assigned by USB Org) If equal to Zero, each interface specifies it&#65533;s own class code. If equal to 0xFF, the class code is vendor specified. Otherwise field is valid Class Code.
+    uint8_t  deviceSubClass;   //Subclass Code (Assigned by USB Org)
+    uint8_t  deviceProtocol;   //Protocol Code (Assigned by USB Org)
+    uint8_t  maxPacketSize;    //Maximum Packet Size for Zero Endpoint. Valid Sizes are 8, 16, 32, 64
+    uint16_t idVendor;          //Vendor ID (Assigned by USB Org)
+    uint16_t idProduct;         //Product ID (Assigned by Manufacturer)
+    uint16_t deviceVersion;         //Device Release Number BCD Format.
+    uint8_t  manufacturerName;     //Index of Manufacturer String Descriptor
+    uint8_t  productName;          //Index of Product String Descriptor
+    uint8_t  serialNumber;     //Index of Serial Number String Descriptor
+    uint8_t  numConfigurations;//Number of Possible Configurations
+};
+
+/**
+ * A USB device can have several different configurations although the majority of devices are simple and only have one.
+ * The configuration descriptor specifies how the device is powered, what the maximum power consumption is, the number of interfaces it has.
+ * Therefore it is possible to have two configurations, one for when the device is bus powered and another when it is mains powered.
+ * As this is a "header" to the Interface descriptors, its also feasible to have one configuration using a different transfer mode to that of another configuration.
+ * Once all the configurations have been examined by the host, the host will send a SetConfiguration command with a non zero value
+ * which matches the bConfigurationValue of one of the configurations. This is used to select the desired configuration.
+ */
+struct ConfigurationDescription
+{
+    uint8_t length;             // Size of Descriptor in Bytes
+    uint8_t type;               // Configuration Descriptor
+    uint16_t totalLength;       // Total length in bytes of data returned
+    uint8_t numInterfaces;      // Number of Interfaces
+    uint8_t configID;           // Value to use as an argument to select this configuration
+    uint8_t configStringIndex;  // Index of String Descriptor describing this configuration
+    uint8_t attributes;         // D7 Reserved, set to 1. (USB 1.0 Bus Powered) D6 Self Powered D5 Remote Wakeup D4..0 Reserved, set to 0.
+    uint8_t maxPower;           // Maximum Power Consumption in 2mA units
+};
+
+/**
+ * USB interface association descriptor (IAD) allows the device to group interfaces that belong to a function. This topic describes how a client driver can determine whether the device contains an IAD for a function.
+ * The Universal Serial Bus Specification, revision 2.0, does not support grouping more than one interface of a composite device within a single function. However, the USB Device Working Group (DWG) created USB device classes that allow for functions with multiple interfaces, and the USB Implementor's Forum issued an Engineering Change Notification (ECN) that defines a mechanism for grouping interfaces.
+ * The ECN specifies a USB descriptor, called the Interface Association Descriptor (IAD), that allows hardware manufacturers to define groupings of interfaces.
+ */
+struct InterfaceAssociation
+{
+    uint8_t length;
+    uint8_t descriptorType;
+    uint8_t firstInterface;
+    uint8_t interfaceCount;
+    uint8_t functionClass;
+    uint8_t functionSubClass;
+    uint8_t functionProtocol;
+    uint8_t function;
+};
+
+/**
+ * The interface descriptor could be seen as a header or grouping of the endpoints into a functional group performing a single feature of the device. The interface descriptor conforms to the following format,
+ */
+struct InterfaceDescription
+{
+    uint8_t length;             //Size of Descriptor in Bytes (9 Bytes)
+    uint8_t descriptorType;     //Interface Descriptor (0x04)
+    uint8_t interfaceNumber;    //Number of Interface
+    uint8_t alternateSetting;   //Value used to select alternative setting
+    uint8_t numEndpoints;       //Number of Endpoints used for this interface
+    uint8_t interfaceClass;     //Class Code (Assigned by USB Org)
+    uint8_t interfaceSubClass;  //Subclass Code (Assigned by USB Org)
+    uint8_t interfaceProtocol;  //Protocol Code (Assigned by USB Org)
+    uint8_t interface;          //Index of String Descriptor Describing this interface
+};
+
+/**
+ * Endpoint descriptors are used to describe endpoints other than endpoint zero.
+ * Endpoint zero is always assumed to be a control endpoint and is configured before any descriptors are even requested.
+ * The host will use the information returned from these descriptors to determine the bandwidth requirements of the bus.
+ */
+struct EndpointDescription
+{
+    uint8_t length;             //Size of Descriptor in Bytes (7 bytes)
+    uint8_t descriptorType;     //Endpoint Descriptor (0x05)
+    uint8_t endpointAddress;    //Endpoint Address Bits 0..3b Endpoint Number. Bits 4..6b Reserved. Set to Zero Bits 7 Direction 0 = Out, 1 = In (Ignored for Control Endpoints)
+    uint8_t attributes;         //Bits 0..1 Transfer Type 00 = Control 01 = Isochronous 10 = Bulk 11 = Interrupt
+                                //Bits 2..7 are reserved. If Isochronous endpoint, 
+                                //Bits 3..2 = Synchronisation Type (Iso Mode) 00 = No Synchonisation 01 = Asynchronous 10 = Adaptive 11 = Synchronous
+                                //Bits 5..4 = Usage Type (Iso Mode) 00 = Data Endpoint 01 = Feedback Endpoint 10 = Explicit Feedback Data Endpoint 11 = Reserved
+    uint16_t maxPacketSize;     //Maximum Packet Size this endpoint is capable of sending or receiving
+    uint8_t interval;           //Interval for polling endpoint data transfers. Value in frame counts. Ignored for Bulk & Control Endpoints. Isochronous must equal 1 and field may range from 1 to 255 for interrupt endpoints.
+};
+
+/**
+ * For the transfer descriptors, endpoint descriptors and setup structures I 'allocate' and use one of these ojects from a pool of memory.
+ * The pool is a linked list with each node being 16 bytes in size.
+ * This gives excelent allocate and object deallocation speed, also allows one pool for all types used giving very good memory utilisation.
+ * Memory pools are used extensivly in software where the allocation size is constant and frequent and high speed is required.
+ * For examples a 'bullet' object in a game. Using the normal memory allocator would cause a significant cpu load.
+ */
+struct LinkedListItem
+{
+    LinkedListItem* next;
+    uint32_t padding[3];//So struct is 16 bytes in size.
+};
+
+/**
+ * There are fields that are read/write by the HC. The unused portion of this
+ * Dword must either not be written by Host Controller or must be read,
+ * and then written back unmodified. The Host Controller Driver should not modify any
+ * portion of the transfer descriptor while it is accessible to the HC.
+ * As well as using the first 18bits that are garnteed not to be altered by the host
+ * I have made this structure 32 bytes in size. (helps with keeping it 16 byte aligned)
+ * The extra 16 bytes are for when there is a callback defined for an interupt transfer or a
+ * bulk transfer called with a callback. The host will not change the extra 16 bytes.
+ * Because of the extra size this stuct comes from it's own memory pool.
+ */
+struct TransferDescriptor
+{
+    /**
+     * The next 18 bits are unused by the controller and the spec says that they should not be
+     * modified by the host controller. So this means we can use it as a way to 'mark'
+     * a transfer so that when it is returned having been completed we can resolve
+     * who it was for.
+     */
+    volatile unsigned deviceID:18;
+        
+    /**
+     * If this bit is 0, then the last data packet to a TD from an endpoint must
+     * exactly fill the defined data buffer. If the bit is 1, then the last data
+     * packet may be smaller than the defined buffer without causing an error
+     * condition on the TD.
+     */
+    volatile unsigned bufferRounding:1;
+    
+    /**
+     * This 2-bit field indicates the direction of data flow and the PID to be used
+     * for the token. This field is only relevant to the HC if the D field in the ED
+     * was set to 00b or 11b indicating that the PID determination is deferred to
+     * the TD. The encoding of the bits within the byte for this field are:
+     *
+     * Code
+     * 00b SETUP - to endpoint
+     * 01b OUT - to endpoint
+     * 10b IN - from endpoint
+     * 11b Reserved
+     */
+    volatile unsigned direction:2;
+    
+    /**
+     * This field contains the interrupt delay count for this TD. When a TD is
+     * complete the HC may wait for DelayInterrupt frames before generating
+     * an interrupt. If DelayInterrupt is 111b, then there is no interrupt
+     * associated with completion of this TD
+     */
+    volatile unsigned delayInterrupt:3;
+    
+    /**
+     * This 2-bit field is used to generate/compare the data PID value (DATA0 or DATA1).
+     * It is updated after each successful transmission/reception of
+     * a data packet. The MSb of this field is &#65533;0&#65533; when the data toggle value is
+     * acquired from the toggleCarry field in the ED and &#65533;1&#65533; when the data
+     * toggle value is taken from the LSb of this field.
+     */
+    volatile unsigned dataToggle:2;
+    
+    /**
+     * For each transmission error, this value is incremented. If ErrorCount is
+     * 2 and another error occurs, the error type is recorded in the
+     * ConditionCode field and placed on the done queue. When a
+     * transaction completes without error, ErrorCount is reset to 0.
+     */
+    volatile unsigned errorCount:2;
+    
+    /**
+     * This field contains the status of the last attempted transaction.
+     */
+    volatile unsigned conditionCode:4;
+    
+    /**
+     * Contains the physical address of the next memory location that will be
+     * accessed for transfer to/from the endpoint. A value of 0 indicates a zero-
+     * length data packet or that all bytes have been transferred.
+     */
+    const volatile uint8_t* CurrentBufferPointer;
+
+    /**
+     * his entry points to the next TD on the list of TDs linked to this endpoint
+     */    
+    volatile TransferDescriptor *nextTD;
+    
+    /**
+     * Contains physical address of the last byte in the buffer for this TD
+     */
+    const volatile uint8_t* bufferEnd;
+    
+    /**
+     * Extra 16 bytes for the callback info.
+     *
+
+    int callbakID;
+    const uint8_t* buffer;
+    int bufferSize;
+    int padding;*/
+};
+
+/**
+ * Host Controller Endpoint Descriptor.
+ * An Endpoint Descriptor (ED) is a 16-byte, memory resident structure that must be aligned to a
+ * 16-byte boundary. The Host Controller traverses lists of EDs and if there are TDs linked to an
+ * ED, the Host Controller performs the indicated transfer.
+ */
+struct EndpointDescriptor
+{    
+    /**
+     * This is the USB address of the function containing the endpoint that this ED controls
+     * In the docs this is called 'FunctionAddress' but it is for our use for when the controller
+     * passes the object back to us.
+     * unsigned functionAddress:7;
+     *
+     * This is the USB address of the endpoint within the function.
+     * unsigned endpointNumber:4;
+     * 
+     * unsigned D:2;
+     * unsigned S:1;
+     * unsigned K:1;
+     * unsigned F:1;
+     *     
+     * This field indicates the maximum number of bytes that can be sent to or received from the endpoint in a single data packet
+     * unsigned maximumPacketSize:11;
+     *
+     * unsigned padding:5;
+     */
+    uint32_t control;  
+
+    volatile TransferDescriptor* TailTD;       //physical pointer to HC_TRANSFER_DESCRIPTOR
+    volatile TransferDescriptor* HeadTD;       //flags + phys ptr to HC_TRANSFER_DESCRIPTOR
+    EndpointDescriptor* NextED;      //phys ptr to HC_ENDPOINT_DESCRIPTOR
+};
+
+
+
+/*
+ * Size is kept to 16 bytes so that I can use the pool of memory in
+ * the host controller driver and so not use any of the main 32k of ram.
+ */
+struct Device
+{
+    /**
+     * When we allocated a device with give it an ID and then set the USB device's ID with the set address command.
+     */
+    unsigned id:8;
+    
+    unsigned lowspeed:1;
+    unsigned controlTransferDirToHost:1;//LIBUSB_ENDPOINT_IN when set
+    unsigned controlTransferState:2;     //See enum ControlTransferState, the control transfer has several states it can be in.
+    unsigned padding:4;
+    
+    /**
+     * This is the packet size of endpoint zero the docs say valid Sizes are 8, 16, 32, 64. Could be out of date.
+     */
+    uint16_t endpointZeroMaxPacketSize;
+    
+    /**
+     * This data is used whilst there is a control transfer in progress.
+     * When finished controlTransferDataLength will be the number of bytes recived.
+     */
+    const uint8_t* controlTransferData;
+    uint16_t controlTransferDataLength;
+    
+    /**
+     * The first language ID I find from string index zero. Makes life easier.
+     * Used in getting the descriptor strings.
+     */
+    uint16_t languageID;
+    
+    /**
+     * Free to be used later.
+     */
+    uint32_t padding2;
+
+};
+
+/**
+ * request_type of setup packet defined as....
+    * 0 = Device
+    * 1 = Interface
+    * 2 = Endpoint
+    * 3 = Other
+    * 4..31 Reserved
+    unsigned recipient:5;
+    
+    * 0 = Standard
+    * 1 = Class
+    * 2 = Vendor
+    * 3 = Reserved.
+    unsigned type:2;
+     
+    * 0 = Host to device.
+    * 1 = Device to host.
+    unsigned transferDirection:1;
+*/
+struct SetupPacket
+{
+    uint8_t requestType;
+    uint8_t request;
+    uint16_t value;
+    uint16_t index;
+    
+    /**
+     * The number of bytes in the data phase.
+     */
+    uint16_t length;
+};
+
+
+/**
+ * The Host Controller Communications Area (HCCA) is a 256-byte structure of system memory
+ * that is used by system software to send and receive specific control and status information to and
+ * from the HC. This structure must be located on a 256-byte boundary. System software must
+ * write the address of this structure in HcHCCA in the HC. This structure allows the software to
+ * direct the HC&#65533;s functions without having to read from the Host Controller except in unusual
+ * circumstances (e.g., error conditions). Normal interaction with the Host Controller can be
+ * accomplished by reading values from this structure that were written by the Host Controller and
+ * by writing to the HC&#65533;s operation registers.
+ * 
+ */
+struct HostControllerCommunicationsArea
+{
+    /**
+     * These 32 Dwords are pointers to interrupt EDs
+     */
+    uint32_t interruptTable[32];
+    
+    /**
+     * Contains the current frame number. This value
+     * is updated by the HC before it begins
+     * processing the periodic lists for the frame.
+     */
+    uint16_t frameNumber;
+    
+    /**
+     * When the HC updates HccaFrameNumber, it sets this word to 0.
+     */
+    uint16_t pad1;
+    
+    /**
+     * When the HC reaches the end of a frame and
+     * its deferred interrupt register is 0, it writes the
+     * current value of its HcDoneHead to this
+     * location and generates an interrupt if interrupts
+     * are enabled. This location is not written by the
+     * HC again until software clears the WD bit in
+     * the HcInterruptStatus register. This protocol provides an interlocked exchange of the Done Queue.
+     * The LSb of this entry is set to 1 to indicate
+     * whether an unmasked HcInterruptStatus was
+     * set when HccaDoneHead was written.
+     * I don't process this in the interupt but in the driver update.
+     * The interupt flags the driver that stuff is done.
+     */
+    struct TransferDescriptor* doneHead;
+    
+    /**
+     * Reserved for use by HC, also makes the data after this 16 byte aligned.
+     */
+    uint8_t reserved[120];
+    
+    /**
+     * I have added onto the end of this alligned struct some extra data that I don't want to be taken out
+     * of the main 32k of main ram.
+     */
+     
+    /**
+     * for some reason the controler does not use a NULL for end of list but an object that does no transfer. Not sure why or if I got that correct.
+     */
+    TransferDescriptor commonTail;
+     
+    /**
+     * Device zero is used for enumeration and setup when a usb device is inserted. 
+     */
+    Device deviceZero;
+     
+    /**
+     * My memory pool of 16 byte objects that MUST be aligned on a 16byte boundry.
+     * So don't move this entry or add stuff before it!
+     */
+    LinkedListItem memoryPool[64];
+     
+    /**
+     * And now some scratch ram to used when I am reciving strings.
+     */
+    uint8_t scratchRam[256];
+};
+
+
+};//end namespace USB
+
+#endif //#ifndef__USB_STRUCTURES_H__
+