Zoltan Hudak / UsbHostMAX3421E

Dependents:   UsbHostMAX3421E_Hello

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers UsbCore.h Source File

UsbCore.h

00001 /* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.
00002 
00003 This program is free software; you can redistribute it and/or modify
00004 it under the terms of the GNU General Public License as published by
00005 the Free Software Foundation; either version 2 of the License, or
00006 (at your option) any later version.
00007 
00008 This program is distributed in the hope that it will be useful,
00009 but WITHOUT ANY WARRANTY; without even the implied warranty of
00010 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00011 GNU General Public License for more details.
00012 
00013 You should have received a copy of the GNU General Public License
00014 along with this program; if not, write to the Free Software
00015 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00016 
00017 Contact information
00018 -------------------
00019 
00020 Circuits At Home, LTD
00021 Web      :  http://www.circuitsathome.com
00022 e-mail   :  support@circuitsathome.com
00023  */
00024 #ifndef USBCORE_H
00025 #define USBCORE_H
00026 
00027 #include "MAX3421E.h"
00028 #include "address.h"
00029 
00030 //#define USB_METHODS_INLINE
00031 /* Common setup data constant combinations  */
00032 #define bmREQ_GET_DESCR     USB_SETUP_DEVICE_TO_HOST | USB_SETUP_TYPE_STANDARD | USB_SETUP_RECIPIENT_DEVICE //get descriptor request type
00033 #define bmREQ_SET           USB_SETUP_HOST_TO_DEVICE | USB_SETUP_TYPE_STANDARD | USB_SETUP_RECIPIENT_DEVICE //set request type for all but 'set feature' and 'set interface'
00034 #define bmREQ_CL_GET_INTF   USB_SETUP_DEVICE_TO_HOST | USB_SETUP_TYPE_CLASS | USB_SETUP_RECIPIENT_INTERFACE //get interface request type
00035 // D7           data transfer direction (0 - host-to-device, 1 - device-to-host)
00036 // D6-5         Type (0- standard, 1 - class, 2 - vendor, 3 - reserved)
00037 // D4-0         Recipient (0 - device, 1 - interface, 2 - endpoint, 3 - other, 4..31 - reserved)
00038 // USB Device Classes
00039 #define USB_CLASS_USE_CLASS_INFO    0x00                    // Use Class Info in the Interface Descriptors
00040 #define USB_CLASS_AUDIO             0x01                    // Audio
00041 #define USB_CLASS_COM_AND_CDC_CTRL  0x02                    // Communications and CDC Control
00042 #define USB_CLASS_HID               0x03                    // HID
00043 #define USB_CLASS_PHYSICAL          0x05                    // Physical
00044 #define USB_CLASS_IMAGE             0x06                    // Image
00045 #define USB_CLASS_PRINTER           0x07                    // Printer
00046 #define USB_CLASS_MASS_STORAGE      0x08                    // Mass Storage
00047 #define USB_CLASS_HUB               0x09                    // Hub
00048 #define USB_CLASS_CDC_DATA          0x0a                    // CDC-Data
00049 #define USB_CLASS_SMART_CARD        0x0b                    // Smart-Card
00050 #define USB_CLASS_CONTENT_SECURITY  0x0d                    // Content Security
00051 #define USB_CLASS_VIDEO             0x0e                    // Video
00052 #define USB_CLASS_PERSONAL_HEALTH   0x0f                    // Personal Healthcare
00053 #define USB_CLASS_DIAGNOSTIC_DEVICE 0xdc                    // Diagnostic Device
00054 #define USB_CLASS_WIRELESS_CTRL     0xe0                    // Wireless Controller
00055 #define USB_CLASS_MISC              0xef                    // Miscellaneous
00056 #define USB_CLASS_APP_SPECIFIC      0xfe                    // Application Specific
00057 #define USB_CLASS_VENDOR_SPECIFIC   0xff                    // Vendor Specific
00058 
00059 // Additional Error Codes
00060 #define USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED   0xD1
00061 #define USB_DEV_CONFIG_ERROR_DEVICE_INIT_INCOMPLETE 0xD2
00062 #define USB_ERROR_UNABLE_TO_REGISTER_DEVICE_CLASS   0xD3
00063 #define USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL      0xD4
00064 #define USB_ERROR_HUB_ADDRESS_OVERFLOW              0xD5
00065 #define USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL         0xD6
00066 #define USB_ERROR_EPINFO_IS_NULL                    0xD7
00067 #define USB_ERROR_INVALID_ARGUMENT                  0xD8
00068 #define USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE     0xD9
00069 #define USB_ERROR_INVALID_MAX_PKT_SIZE              0xDA
00070 #define USB_ERROR_EP_NOT_FOUND_IN_TBL               0xDB
00071 #define USB_ERROR_CONFIG_REQUIRES_ADDITIONAL_RESET  0xE0
00072 #define USB_ERROR_FailGetDevDescr                   0xE1
00073 #define USB_ERROR_FailSetDevTblEntry                0xE2
00074 #define USB_ERROR_FailGetConfDescr                  0xE3
00075 #define USB_ERROR_TRANSFER_TIMEOUT                  0xFF
00076 
00077 #define USB_XFER_TIMEOUT                            5000    // (5000) USB transfer timeout in milliseconds, per section 9.2.6.1 of USB 2.0 spec
00078 #define USB_RETRY_LIMIT                             3       // 3 retry limit for a transfer
00079 #define USB_SETTLE_DELAY                            200     // settle delay in milliseconds
00080 #define USB_NUMDEVICES                              16      //number of USB devices
00081 #define HUB_PORT_RESET_DELAY                        20      // hub port reset delay 10 ms recomended, can be up to 20 ms
00082 //#define USB_NAK_LIMIT         32000   // NAK limit for a transfer. 0 means NAKs are not counted
00083 //#define HUB_MAX_HUBS          7       // maximum number of hubs that can be attached to the host controller
00084 /* USB state machine states */
00085 #define USB_STATE_MASK                                      0xf0
00086 #define USB_STATE_DETACHED                                  0x10
00087 #define USB_DETACHED_SUBSTATE_INITIALIZE                    0x11
00088 #define USB_DETACHED_SUBSTATE_WAIT_FOR_DEVICE               0x12
00089 #define USB_DETACHED_SUBSTATE_ILLEGAL                       0x13
00090 #define USB_ATTACHED_SUBSTATE_SETTLE                        0x20
00091 #define USB_ATTACHED_SUBSTATE_RESET_DEVICE                  0x30
00092 #define USB_ATTACHED_SUBSTATE_WAIT_RESET_COMPLETE           0x40
00093 #define USB_ATTACHED_SUBSTATE_WAIT_SOF                      0x50
00094 #define USB_ATTACHED_SUBSTATE_WAIT_RESET                    0x51
00095 #define USB_ATTACHED_SUBSTATE_GET_DEVICE_DESCRIPTOR_SIZE    0x60
00096 #define USB_STATE_ADDRESSING                                0x70
00097 #define USB_STATE_CONFIGURING                               0x80
00098 #define USB_STATE_RUNNING                                   0x90
00099 #define USB_STATE_ERROR                                     0xa0
00100 
00101 
00102 class USBDeviceConfig
00103 {
00104 public:
00105     virtual uint8_t Init
00106     (
00107         uint8_t parent __attribute__((unused)),
00108         uint8_t port __attribute__((unused)),
00109         bool lowspeed __attribute__((unused))
00110     )
00111     {
00112         return 0;
00113     }
00114 
00115     virtual uint8_t ConfigureDevice
00116     (
00117         uint8_t parent __attribute__((unused)),
00118         uint8_t port __attribute__((unused)),
00119         bool lowspeed __attribute__((unused))
00120     )
00121     {
00122         return 0;
00123     }
00124 
00125     virtual uint8_t Release()                                           { return 0; }
00126     virtual uint8_t Poll()                                              { return 0; }
00127     virtual uint8_t GetAddress()                                        { return 0; }
00128     virtual void    ResetHubPort(uint8_t port __attribute__((unused)))  { return; }
00129 
00130     // Note used for hubs only!
00131     virtual bool    VIDPIDOK(uint16_t vid __attribute__((unused)), uint16_t pid __attribute__((unused)))   { return false; }
00132     virtual bool    DEVCLASSOK(uint8_t klass __attribute__((unused)))           { return false; }
00133     virtual bool    DEVSUBCLASSOK(uint8_t subklass __attribute__((unused)))     { return true; }
00134 };
00135 
00136 /* USB Setup Packet Structure   */
00137 typedef struct
00138 {
00139     union
00140     {                               // offset   description
00141         uint8_t bmRequestType;      //   0      Bit-map of request type
00142 
00143         struct
00144         {
00145             uint8_t recipient : 5;  //          Recipient of the request
00146             uint8_t type : 2;       //          Type of request
00147             uint8_t direction : 1;  //          Direction of data X-fer
00148         } __attribute__((packed));
00149     }
00150     ReqType_u;
00151     uint8_t bRequest;               //   1      Request
00152 
00153     union
00154     {
00155         uint16_t    wValue;         //   2      Depends on bRequest
00156 
00157         struct
00158         {
00159             uint8_t wValueLo;
00160             uint8_t wValueHi;
00161         } __attribute__((packed));
00162     }
00163     wVal_u;
00164     uint16_t    wIndex;             //   4      Depends on bRequest
00165     uint16_t    wLength;            //   6      Depends on bRequest
00166 }
00167 __attribute__((packed))
00168 SETUP_PKT, *PSETUP_PKT;
00169 
00170 // Base class for incoming data parser
00171 class USBReadParser
00172 {
00173 public:
00174     virtual void    Parse(const uint16_t len, const uint8_t* pbuf, const uint16_t& offset) = 0;
00175 };
00176 
00177 class Usb : public MAX3421E
00178 {
00179     AddressPoolImpl<USB_NUMDEVICES> addrPool;
00180     USBDeviceConfig*                devConfig[USB_NUMDEVICES];
00181     uint8_t                         bmHubPre;
00182 public:
00183     Usb(PinName mosi, PinName miso, PinName sck, PinName ss, PinName intr);
00184     int8_t          init();
00185     void            SetHubPreMask()     { bmHubPre |= bmHUBPRE; }
00186     void            ResetHubPreMask()   { bmHubPre &= (~bmHUBPRE); }
00187     AddressPool&    GetAddressPool()    { return (AddressPool&)addrPool; }
00188     uint8_t RegisterDeviceClass(USBDeviceConfig* pdev)
00189     {
00190         for (uint8_t i = 0; i < USB_NUMDEVICES; i++) {
00191             if (!devConfig[i]) {
00192                 devConfig[i] = pdev;
00193                 return 0;
00194             }
00195         }
00196 
00197         return USB_ERROR_UNABLE_TO_REGISTER_DEVICE_CLASS;
00198     }
00199 
00200     void        ForEachUsbDevice(UsbDeviceHandleFunc pfunc)     { addrPool.ForEachUsbDevice(pfunc); }
00201     uint8_t     getUsbTaskState(void);
00202     void        setUsbTaskState(uint8_t state);
00203 
00204     EpInfo*     getEpInfoEntry(uint8_t addr, uint8_t ep);
00205     uint8_t     setEpInfoEntry(uint8_t addr, uint8_t epcount, EpInfo* eprecord_ptr);
00206 
00207     /* Control requests */
00208     uint8_t     getDevDescr(uint8_t addr, uint8_t ep, uint16_t nbytes, uint8_t* dataptr);
00209     uint8_t     getConfDescr(uint8_t addr, uint8_t ep, uint16_t nbytes, uint8_t conf, uint8_t* dataptr);
00210 
00211     uint8_t     getConfDescr(uint8_t addr, uint8_t ep, uint8_t conf, USBReadParser* p);
00212 
00213     uint8_t     getStrDescr
00214                 (
00215                     uint8_t     addr,
00216                     uint8_t     ep,
00217                     uint16_t    nbytes,
00218                     uint8_t     index,
00219                     uint16_t    langid,
00220                     uint8_t*    dataptr
00221                 );
00222     uint8_t     setAddr(uint8_t oldaddr, uint8_t ep, uint8_t newaddr);
00223     uint8_t     setConf(uint8_t addr, uint8_t ep, uint8_t conf_value);
00224     /**/
00225     uint8_t     ctrlData(uint8_t addr, uint8_t ep, uint16_t nbytes, uint8_t* dataptr, bool direction);
00226     uint8_t     ctrlStatus(uint8_t ep, bool direction, uint16_t nak_limit);
00227     uint8_t     inTransfer(uint8_t addr, uint8_t ep, uint16_t* nbytesptr, uint8_t* data, uint8_t bInterval = 0);
00228     uint8_t     outTransfer(uint8_t addr, uint8_t ep, uint16_t nbytes, uint8_t* data);
00229     uint8_t     dispatchPkt(uint8_t token, uint8_t ep, uint16_t nak_limit);
00230 
00231     void        task(void);
00232 
00233     uint8_t     defaultAddressing(uint8_t parent, uint8_t port, bool lowspeed);
00234     uint8_t     configuring(uint8_t parent, uint8_t port, bool lowspeed);
00235     uint8_t     releaseDevice(uint8_t addr);
00236 
00237     uint8_t     ctrlReq
00238                 (
00239                     uint8_t         addr,
00240                     uint8_t         ep,
00241                     uint8_t         bmReqType,
00242                     uint8_t         bRequest,
00243                     uint8_t         wValLo,
00244                     uint8_t         wValHi,
00245                     uint16_t        wInd,
00246                     uint16_t        total,
00247                     uint16_t        nbytes,
00248                     uint8_t*        dataptr,
00249                     USBReadParser*  p
00250                 );
00251 private:
00252     uint8_t setAddress(uint8_t addr, uint8_t ep, EpInfo ** ppep, uint16_t* nak_limit);
00253     uint8_t outTransfer(EpInfo* pep, uint16_t nak_limit, uint16_t nbytes, uint8_t* data);
00254     uint8_t inTransfer(EpInfo* pep, uint16_t nak_limit, uint16_t* nbytesptr, uint8_t* data, uint8_t bInterval = 0);
00255     uint8_t attemptConfig(uint8_t driver, uint8_t parent, uint8_t port, bool lowspeed);
00256 };
00257 
00258 #if 0   //defined(USB_METHODS_INLINE)
00259 
00260 //get device descriptor
00261 inline uint8_t Usb::getDevDescr(uint8_t addr, uint8_t ep, uint16_t nbytes, uint8_t* dataptr)
00262 {
00263     return
00264         (
00265             ctrlReq
00266             (
00267                 addr,
00268                 ep,
00269                 bmREQ_GET_DESCR,
00270                 USB_REQUEST_GET_DESCRIPTOR,
00271                 0x00,
00272                 USB_DESCRIPTOR_DEVICE,
00273                 0x0000,
00274                 nbytes,
00275                 dataptr
00276             )
00277         );
00278 }
00279 
00280 //get configuration descriptor
00281 inline uint8_t Usb::getConfDescr(uint8_t addr, uint8_t ep, uint16_t nbytes, uint8_t conf, uint8_t* dataptr)
00282 {
00283     return
00284         (
00285             ctrlReq
00286             (
00287                 addr,
00288                 ep,
00289                 bmREQ_GET_DESCR,
00290                 USB_REQUEST_GET_DESCRIPTOR,
00291                 conf,
00292                 USB_DESCRIPTOR_CONFIGURATION,
00293                 0x0000,
00294                 nbytes,
00295                 dataptr
00296             )
00297         );
00298 }
00299 
00300 //get string descriptor
00301 inline uint8_t Usb::getStrDescr
00302 (
00303     uint8_t     addr,
00304     uint8_t     ep,
00305     uint16_t    nuint8_ts,
00306     uint8_t     index,
00307     uint16_t    langid,
00308     uint8_t*    dataptr
00309 )
00310 {
00311     return
00312         (
00313             ctrlReq
00314             (
00315                 addr,
00316                 ep,
00317                 bmREQ_GET_DESCR,
00318                 USB_REQUEST_GET_DESCRIPTOR,
00319                 index,
00320                 USB_DESCRIPTOR_STRING,
00321                 langid,
00322                 nuint8_ts,
00323                 dataptr
00324             )
00325         );
00326 }
00327 
00328 //set address
00329 inline uint8_t Usb::setAddr(uint8_t oldaddr, uint8_t ep, uint8_t newaddr)
00330 {
00331     return(ctrlReq(oldaddr, ep, bmREQ_SET, USB_REQUEST_SET_ADDRESS, newaddr, 0x00, 0x0000, 0x0000, NULL));
00332 }
00333 
00334 //set configuration
00335 inline uint8_t Usb::setConf(uint8_t addr, uint8_t ep, uint8_t conf_value)
00336 {
00337     return(ctrlReq(addr, ep, bmREQ_SET, USB_REQUEST_SET_CONFIGURATION, conf_value, 0x00, 0x0000, 0x0000, NULL));
00338 }
00339 #endif // defined(USB_METHODS_INLINE)
00340 #endif /* USBCORE_H */