Takumi Odashima / ArduinoUsbHostShield

Dependents:   USBHOST_PS5

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 
00025 // warning
00026 // #define _usb_h_
00027 // #define MBED_H
00028 
00029 #if !defined(_usb_h_) || defined(USBCORE_H)
00030 #error "Never include UsbCore.h directly; include Usb.h instead"
00031 #else
00032 #define USBCORE_H
00033 
00034 // Not used anymore? If anyone uses this, please let us know so that this may be
00035 // moved to the proper place, settings.h.
00036 //#define USB_METHODS_INLINE
00037 
00038 
00039 /* Common setup data constant combinations  */
00040 #define bmREQ_GET_DESCR USB_SETUP_DEVICE_TO_HOST | USB_SETUP_TYPE_STANDARD | USB_SETUP_RECIPIENT_DEVICE   //get descriptor request type
00041 #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'
00042 #define bmREQ_CL_GET_INTF USB_SETUP_DEVICE_TO_HOST | USB_SETUP_TYPE_CLASS | USB_SETUP_RECIPIENT_INTERFACE //get interface request type
00043 
00044 // D7           data transfer direction (0 - host-to-device, 1 - device-to-host)
00045 // D6-5         Type (0- standard, 1 - class, 2 - vendor, 3 - reserved)
00046 // D4-0         Recipient (0 - device, 1 - interface, 2 - endpoint, 3 - other, 4..31 - reserved)
00047 
00048 // USB Device Classes
00049 #define USB_CLASS_USE_CLASS_INFO 0x00                                                                     // Use Class Info in the Interface Descriptors
00050 #define USB_CLASS_AUDIO 0x01                                                                              // Audio
00051 #define USB_CLASS_COM_AND_CDC_CTRL 0x02                                                                   // Communications and CDC Control
00052 #define USB_CLASS_HID 0x03                                                                                // HID
00053 #define USB_CLASS_PHYSICAL 0x05                                                                           // Physical
00054 #define USB_CLASS_IMAGE 0x06                                                                              // Image
00055 #define USB_CLASS_PRINTER 0x07                                                                            // Printer
00056 #define USB_CLASS_MASS_STORAGE 0x08                                                                       // Mass Storage
00057 #define USB_CLASS_HUB 0x09                                                                                // Hub
00058 #define USB_CLASS_CDC_DATA 0x0a                                                                           // CDC-Data
00059 #define USB_CLASS_SMART_CARD 0x0b                                                                         // Smart-Card
00060 #define USB_CLASS_CONTENT_SECURITY 0x0d                                                                   // Content Security
00061 #define USB_CLASS_VIDEO 0x0e                                                                              // Video
00062 #define USB_CLASS_PERSONAL_HEALTH 0x0f                                                                    // Personal Healthcare
00063 #define USB_CLASS_DIAGNOSTIC_DEVICE 0xdc                                                                  // Diagnostic Device
00064 #define USB_CLASS_WIRELESS_CTRL 0xe0                                                                      // Wireless Controller
00065 #define USB_CLASS_MISC 0xef                                                                               // Miscellaneous
00066 #define USB_CLASS_APP_SPECIFIC 0xfe                                                                       // Application Specific
00067 #define USB_CLASS_VENDOR_SPECIFIC 0xff                                                                    // Vendor Specific
00068 
00069 // Additional Error Codes
00070 #define USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED 0xD1
00071 #define USB_DEV_CONFIG_ERROR_DEVICE_INIT_INCOMPLETE 0xD2
00072 #define USB_ERROR_UNABLE_TO_REGISTER_DEVICE_CLASS 0xD3
00073 #define USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL 0xD4
00074 #define USB_ERROR_HUB_ADDRESS_OVERFLOW 0xD5
00075 #define USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL 0xD6
00076 #define USB_ERROR_EPINFO_IS_NULL 0xD7
00077 #define USB_ERROR_INVALID_ARGUMENT 0xD8
00078 #define USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE 0xD9
00079 #define USB_ERROR_INVALID_MAX_PKT_SIZE 0xDA
00080 #define USB_ERROR_EP_NOT_FOUND_IN_TBL 0xDB
00081 #define USB_ERROR_CONFIG_REQUIRES_ADDITIONAL_RESET 0xE0
00082 #define USB_ERROR_FailGetDevDescr 0xE1
00083 #define USB_ERROR_FailSetDevTblEntry 0xE2
00084 #define USB_ERROR_FailGetConfDescr 0xE3
00085 #define USB_ERROR_TRANSFER_TIMEOUT 0xFF
00086 
00087 #define USB_XFER_TIMEOUT 5000 // (5000) USB transfer timeout in milliseconds, per section 9.2.6.1 of USB 2.0 spec
00088 //#define USB_NAK_LIMIT         32000   // NAK limit for a transfer. 0 means NAKs are not counted
00089 #define USB_RETRY_LIMIT 3     // 3 retry limit for a transfer
00090 #define USB_SETTLE_DELAY 200  // settle delay in milliseconds
00091 
00092 #define USB_NUMDEVICES 16       //number of USB devices
00093 //#define HUB_MAX_HUBS          7       // maximum number of hubs that can be attached to the host controller
00094 #define HUB_PORT_RESET_DELAY 20 // hub port reset delay 10 ms recomended, can be up to 20 ms
00095 
00096 /* USB state machine states */
00097 #define USB_STATE_MASK 0xf0
00098 
00099 #define USB_STATE_DETACHED 0x10
00100 #define USB_DETACHED_SUBSTATE_INITIALIZE 0x11
00101 #define USB_DETACHED_SUBSTATE_WAIT_FOR_DEVICE 0x12
00102 #define USB_DETACHED_SUBSTATE_ILLEGAL 0x13
00103 #define USB_ATTACHED_SUBSTATE_SETTLE 0x20
00104 #define USB_ATTACHED_SUBSTATE_RESET_DEVICE 0x30
00105 #define USB_ATTACHED_SUBSTATE_WAIT_RESET_COMPLETE 0x40
00106 #define USB_ATTACHED_SUBSTATE_WAIT_SOF 0x50
00107 #define USB_ATTACHED_SUBSTATE_WAIT_RESET 0x51
00108 #define USB_ATTACHED_SUBSTATE_GET_DEVICE_DESCRIPTOR_SIZE 0x60
00109 #define USB_STATE_ADDRESSING 0x70
00110 #define USB_STATE_CONFIGURING 0x80
00111 #define USB_STATE_RUNNING 0x90
00112 #define USB_STATE_ERROR 0xa0
00113 
00114 class USBDeviceConfig
00115 {
00116 public:
00117     virtual uint8_t Init(uint8_t parent __attribute__((unused)), uint8_t port __attribute__((unused)), bool lowspeed __attribute__((unused)))
00118     {
00119         return 0;
00120     }
00121 
00122     virtual uint8_t ConfigureDevice(uint8_t parent __attribute__((unused)), uint8_t port __attribute__((unused)), bool lowspeed __attribute__((unused)))
00123     {
00124         return 0;
00125     }
00126 
00127     virtual uint8_t Release()
00128     {
00129         return 0;
00130     }
00131 
00132     virtual uint8_t Poll()
00133     {
00134         return 0;
00135     }
00136 
00137     virtual uint8_t GetAddress()
00138     {
00139         return 0;
00140     }
00141 
00142     virtual void ResetHubPort(uint8_t port __attribute__((unused)))
00143     {
00144         return;
00145     } // Note used for hubs only!
00146 
00147     virtual bool VIDPIDOK(uint16_t vid __attribute__((unused)), uint16_t pid __attribute__((unused)))
00148     {
00149         return false;
00150     }
00151 
00152     virtual bool DEVCLASSOK(uint8_t klass __attribute__((unused)))
00153     {
00154         return false;
00155     }
00156 
00157     virtual bool DEVSUBCLASSOK(uint8_t subklass __attribute__((unused)))
00158     {
00159         return true;
00160     }
00161 };
00162 
00163 /* USB Setup Packet Structure   */
00164 typedef struct
00165 {
00166 
00167     union {                    // offset   description
00168         uint8_t bmRequestType; //   0      Bit-map of request type
00169 
00170         struct
00171         {
00172             uint8_t recipient : 5; //          Recipient of the request
00173             uint8_t type : 2;      //          Type of request
00174             uint8_t direction : 1; //          Direction of data X-fer
00175         } __attribute__((packed));
00176     } ReqType_u;
00177     uint8_t bRequest; //   1      Request
00178 
00179     union {
00180         uint16_t wValue; //   2      Depends on bRequest
00181 
00182         struct
00183         {
00184             uint8_t wValueLo;
00185             uint8_t wValueHi;
00186         } __attribute__((packed));
00187     } wVal_u;
00188     uint16_t wIndex;  //   4      Depends on bRequest
00189     uint16_t wLength; //   6      Depends on bRequest
00190 } __attribute__((packed)) SETUP_PKT, *PSETUP_PKT;
00191 
00192 // Base class for incoming data parser
00193 
00194 class USBReadParser
00195 {
00196 public:
00197     virtual void Parse(const uint16_t len, const uint8_t *pbuf, const uint16_t &offset) = 0;
00198 };
00199 
00200 class USB : public MAX3421E
00201 {
00202     AddressPoolImpl<USB_NUMDEVICES> addrPool;
00203     USBDeviceConfig *devConfig[USB_NUMDEVICES];
00204     uint8_t bmHubPre;
00205 
00206 private:
00207     static Timer arduinoTimer; // for millis() & micros() function in Arduino
00208 public:
00209     static uint32_t read_ms() { return arduinoTimer.read_ms(); }
00210     static uint32_t read_us() { return arduinoTimer.read_us(); }
00211     
00212 public:
00213     USB(PinName mosi, PinName miso, PinName sclk, PinName ssel, PinName intr);
00214 
00215     void SetHubPreMask()
00216     {
00217         bmHubPre |= bmHUBPRE;
00218     };
00219 
00220     void ResetHubPreMask()
00221     {
00222         bmHubPre &= (~bmHUBPRE);
00223     };
00224 
00225     AddressPool &GetAddressPool()
00226     {
00227         return (AddressPool &)addrPool;
00228     };
00229 
00230     uint8_t RegisterDeviceClass(USBDeviceConfig *pdev)
00231     {
00232         for (uint8_t i = 0; i < USB_NUMDEVICES; i++)
00233         {
00234             if (!devConfig[i])
00235             {
00236                 devConfig[i] = pdev;
00237                 return 0;
00238             }
00239         }
00240         return USB_ERROR_UNABLE_TO_REGISTER_DEVICE_CLASS;
00241     };
00242 
00243     void ForEachUsbDevice(UsbDeviceHandleFunc pfunc)
00244     {
00245         addrPool.ForEachUsbDevice(pfunc);
00246     };
00247     uint8_t getUsbTaskState(void);
00248     void setUsbTaskState(uint8_t state);
00249 
00250     EpInfo *getEpInfoEntry(uint8_t addr, uint8_t ep);
00251     uint8_t setEpInfoEntry(uint8_t addr, uint8_t epcount, EpInfo *eprecord_ptr);
00252 
00253     /* Control requests */
00254     uint8_t getDevDescr(uint8_t addr, uint8_t ep, uint16_t nbytes, uint8_t *dataptr);
00255     uint8_t getConfDescr(uint8_t addr, uint8_t ep, uint16_t nbytes, uint8_t conf, uint8_t *dataptr);
00256 
00257     uint8_t getConfDescr(uint8_t addr, uint8_t ep, uint8_t conf, USBReadParser *p);
00258 
00259     uint8_t getStrDescr(uint8_t addr, uint8_t ep, uint16_t nbytes, uint8_t index, uint16_t langid, uint8_t *dataptr);
00260     uint8_t setAddr(uint8_t oldaddr, uint8_t ep, uint8_t newaddr);
00261     uint8_t setConf(uint8_t addr, uint8_t ep, uint8_t conf_value);
00262     /**/
00263     uint8_t ctrlData(uint8_t addr, uint8_t ep, uint16_t nbytes, uint8_t *dataptr, bool direction);
00264     uint8_t ctrlStatus(uint8_t ep, bool direction, uint16_t nak_limit);
00265     uint8_t inTransfer(uint8_t addr, uint8_t ep, uint16_t *nbytesptr, uint8_t *data, uint8_t bInterval = 0);
00266     uint8_t outTransfer(uint8_t addr, uint8_t ep, uint16_t nbytes, uint8_t *data);
00267     uint8_t dispatchPkt(uint8_t token, uint8_t ep, uint16_t nak_limit);
00268 
00269     void Task(void);
00270 
00271     uint8_t DefaultAddressing(uint8_t parent, uint8_t port, bool lowspeed);
00272     uint8_t Configuring(uint8_t parent, uint8_t port, bool lowspeed);
00273     uint8_t ReleaseDevice(uint8_t addr);
00274 
00275     uint8_t ctrlReq(uint8_t addr, uint8_t ep, uint8_t bmReqType, uint8_t bRequest, uint8_t wValLo, uint8_t wValHi,
00276                     uint16_t wInd, uint16_t total, uint16_t nbytes, uint8_t *dataptr, USBReadParser *p);
00277     
00278 private:
00279     void init();
00280     uint8_t SetAddress(uint8_t addr, uint8_t ep, EpInfo **ppep, uint16_t *nak_limit);
00281     uint8_t OutTransfer(EpInfo *pep, uint16_t nak_limit, uint16_t nbytes, uint8_t *data);
00282     uint8_t InTransfer(EpInfo *pep, uint16_t nak_limit, uint16_t *nbytesptr, uint8_t *data, uint8_t bInterval = 0);
00283     uint8_t AttemptConfig(uint8_t driver, uint8_t parent, uint8_t port, bool lowspeed);
00284 };
00285 
00286 #if 0 //defined(USB_METHODS_INLINE)
00287 //get device descriptor
00288 
00289 inline uint8_t USB::getDevDescr(uint8_t addr, uint8_t ep, uint16_t nbytes, uint8_t* dataptr) {
00290         return ( ctrlReq(addr, ep, bmREQ_GET_DESCR, USB_REQUEST_GET_DESCRIPTOR, 0x00, USB_DESCRIPTOR_DEVICE, 0x0000, nbytes, dataptr));
00291 }
00292 //get configuration descriptor
00293 
00294 inline uint8_t USB::getConfDescr(uint8_t addr, uint8_t ep, uint16_t nbytes, uint8_t conf, uint8_t* dataptr) {
00295         return ( ctrlReq(addr, ep, bmREQ_GET_DESCR, USB_REQUEST_GET_DESCRIPTOR, conf, USB_DESCRIPTOR_CONFIGURATION, 0x0000, nbytes, dataptr));
00296 }
00297 //get string descriptor
00298 
00299 inline uint8_t USB::getStrDescr(uint8_t addr, uint8_t ep, uint16_t nuint8_ts, uint8_t index, uint16_t langid, uint8_t* dataptr) {
00300         return ( ctrlReq(addr, ep, bmREQ_GET_DESCR, USB_REQUEST_GET_DESCRIPTOR, index, USB_DESCRIPTOR_STRING, langid, nuint8_ts, dataptr));
00301 }
00302 //set address
00303 
00304 inline uint8_t USB::setAddr(uint8_t oldaddr, uint8_t ep, uint8_t newaddr) {
00305         return ( ctrlReq(oldaddr, ep, bmREQ_SET, USB_REQUEST_SET_ADDRESS, newaddr, 0x00, 0x0000, 0x0000, NULL));
00306 }
00307 //set configuration
00308 
00309 inline uint8_t USB::setConf(uint8_t addr, uint8_t ep, uint8_t conf_value) {
00310         return ( ctrlReq(addr, ep, bmREQ_SET, USB_REQUEST_SET_CONFIGURATION, conf_value, 0x00, 0x0000, 0x0000, NULL));
00311 }
00312 
00313 //Timer USB::arduinoTimer;
00314 
00315 #endif // defined(USB_METHODS_INLINE)
00316 
00317 #endif /* USBCORE_H */