Zoltan Hudak / UsbHostMAX3421E

Dependents:   UsbHostMAX3421E_Hello

Revision:
0:84353c479782
Child:
1:2263e77400e9
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/UsbCore.h	Sun Jul 12 20:39:26 2020 +0000
@@ -0,0 +1,340 @@
+/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.
+
+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 2 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, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+Contact information
+-------------------
+
+Circuits At Home, LTD
+Web      :  http://www.circuitsathome.com
+e-mail   :  support@circuitsathome.com
+ */
+#ifndef USBCORE_H
+#define USBCORE_H
+
+#include "MAX3421E.h"
+#include "address.h"
+
+//#define USB_METHODS_INLINE
+/* Common setup data constant combinations  */
+#define bmREQ_GET_DESCR     USB_SETUP_DEVICE_TO_HOST | USB_SETUP_TYPE_STANDARD | USB_SETUP_RECIPIENT_DEVICE //get descriptor request type
+#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'
+#define bmREQ_CL_GET_INTF   USB_SETUP_DEVICE_TO_HOST | USB_SETUP_TYPE_CLASS | USB_SETUP_RECIPIENT_INTERFACE //get interface request type
+// D7           data transfer direction (0 - host-to-device, 1 - device-to-host)
+// D6-5         Type (0- standard, 1 - class, 2 - vendor, 3 - reserved)
+// D4-0         Recipient (0 - device, 1 - interface, 2 - endpoint, 3 - other, 4..31 - reserved)
+// USB Device Classes
+#define USB_CLASS_USE_CLASS_INFO    0x00                    // Use Class Info in the Interface Descriptors
+#define USB_CLASS_AUDIO             0x01                    // Audio
+#define USB_CLASS_COM_AND_CDC_CTRL  0x02                    // Communications and CDC Control
+#define USB_CLASS_HID               0x03                    // HID
+#define USB_CLASS_PHYSICAL          0x05                    // Physical
+#define USB_CLASS_IMAGE             0x06                    // Image
+#define USB_CLASS_PRINTER           0x07                    // Printer
+#define USB_CLASS_MASS_STORAGE      0x08                    // Mass Storage
+#define USB_CLASS_HUB               0x09                    // Hub
+#define USB_CLASS_CDC_DATA          0x0a                    // CDC-Data
+#define USB_CLASS_SMART_CARD        0x0b                    // Smart-Card
+#define USB_CLASS_CONTENT_SECURITY  0x0d                    // Content Security
+#define USB_CLASS_VIDEO             0x0e                    // Video
+#define USB_CLASS_PERSONAL_HEALTH   0x0f                    // Personal Healthcare
+#define USB_CLASS_DIAGNOSTIC_DEVICE 0xdc                    // Diagnostic Device
+#define USB_CLASS_WIRELESS_CTRL     0xe0                    // Wireless Controller
+#define USB_CLASS_MISC              0xef                    // Miscellaneous
+#define USB_CLASS_APP_SPECIFIC      0xfe                    // Application Specific
+#define USB_CLASS_VENDOR_SPECIFIC   0xff                    // Vendor Specific
+
+// Additional Error Codes
+#define USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED   0xD1
+#define USB_DEV_CONFIG_ERROR_DEVICE_INIT_INCOMPLETE 0xD2
+#define USB_ERROR_UNABLE_TO_REGISTER_DEVICE_CLASS   0xD3
+#define USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL      0xD4
+#define USB_ERROR_HUB_ADDRESS_OVERFLOW              0xD5
+#define USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL         0xD6
+#define USB_ERROR_EPINFO_IS_NULL                    0xD7
+#define USB_ERROR_INVALID_ARGUMENT                  0xD8
+#define USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE     0xD9
+#define USB_ERROR_INVALID_MAX_PKT_SIZE              0xDA
+#define USB_ERROR_EP_NOT_FOUND_IN_TBL               0xDB
+#define USB_ERROR_CONFIG_REQUIRES_ADDITIONAL_RESET  0xE0
+#define USB_ERROR_FailGetDevDescr                   0xE1
+#define USB_ERROR_FailSetDevTblEntry                0xE2
+#define USB_ERROR_FailGetConfDescr                  0xE3
+#define USB_ERROR_TRANSFER_TIMEOUT                  0xFF
+
+#define USB_XFER_TIMEOUT                            5000    // (5000) USB transfer timeout in milliseconds, per section 9.2.6.1 of USB 2.0 spec
+#define USB_RETRY_LIMIT                             3       // 3 retry limit for a transfer
+#define USB_SETTLE_DELAY                            200     // settle delay in milliseconds
+#define USB_NUMDEVICES                              16      //number of USB devices
+#define HUB_PORT_RESET_DELAY                        20      // hub port reset delay 10 ms recomended, can be up to 20 ms
+//#define USB_NAK_LIMIT         32000   // NAK limit for a transfer. 0 means NAKs are not counted
+//#define HUB_MAX_HUBS          7       // maximum number of hubs that can be attached to the host controller
+/* USB state machine states */
+#define USB_STATE_MASK                                      0xf0
+#define USB_STATE_DETACHED                                  0x10
+#define USB_DETACHED_SUBSTATE_INITIALIZE                    0x11
+#define USB_DETACHED_SUBSTATE_WAIT_FOR_DEVICE               0x12
+#define USB_DETACHED_SUBSTATE_ILLEGAL                       0x13
+#define USB_ATTACHED_SUBSTATE_SETTLE                        0x20
+#define USB_ATTACHED_SUBSTATE_RESET_DEVICE                  0x30
+#define USB_ATTACHED_SUBSTATE_WAIT_RESET_COMPLETE           0x40
+#define USB_ATTACHED_SUBSTATE_WAIT_SOF                      0x50
+#define USB_ATTACHED_SUBSTATE_WAIT_RESET                    0x51
+#define USB_ATTACHED_SUBSTATE_GET_DEVICE_DESCRIPTOR_SIZE    0x60
+#define USB_STATE_ADDRESSING                                0x70
+#define USB_STATE_CONFIGURING                               0x80
+#define USB_STATE_RUNNING                                   0x90
+#define USB_STATE_ERROR                                     0xa0
+
+
+class USBDeviceConfig
+{
+public:
+    virtual uint8_t Init
+    (
+        uint8_t parent __attribute__((unused)),
+        uint8_t port __attribute__((unused)),
+        bool lowspeed __attribute__((unused))
+    )
+    {
+        return 0;
+    }
+
+    virtual uint8_t ConfigureDevice
+    (
+        uint8_t parent __attribute__((unused)),
+        uint8_t port __attribute__((unused)),
+        bool lowspeed __attribute__((unused))
+    )
+    {
+        return 0;
+    }
+
+    virtual uint8_t Release()                                           { return 0; }
+    virtual uint8_t Poll()                                              { return 0; }
+    virtual uint8_t GetAddress()                                        { return 0; }
+    virtual void    ResetHubPort(uint8_t port __attribute__((unused)))  { return; }
+
+    // Note used for hubs only!
+    virtual bool    VIDPIDOK(uint16_t vid __attribute__((unused)), uint16_t pid __attribute__((unused)))   { return false; }
+    virtual bool    DEVCLASSOK(uint8_t klass __attribute__((unused)))           { return false; }
+    virtual bool    DEVSUBCLASSOK(uint8_t subklass __attribute__((unused)))     { return true; }
+};
+
+/* USB Setup Packet Structure   */
+typedef struct
+{
+    union
+    {                               // offset   description
+        uint8_t bmRequestType;      //   0      Bit-map of request type
+
+        struct
+        {
+            uint8_t recipient : 5;  //          Recipient of the request
+            uint8_t type : 2;       //          Type of request
+            uint8_t direction : 1;  //          Direction of data X-fer
+        } __attribute__((packed));
+    }
+    ReqType_u;
+    uint8_t bRequest;               //   1      Request
+
+    union
+    {
+        uint16_t    wValue;         //   2      Depends on bRequest
+
+        struct
+        {
+            uint8_t wValueLo;
+            uint8_t wValueHi;
+        } __attribute__((packed));
+    }
+    wVal_u;
+    uint16_t    wIndex;             //   4      Depends on bRequest
+    uint16_t    wLength;            //   6      Depends on bRequest
+}
+__attribute__((packed))
+SETUP_PKT, *PSETUP_PKT;
+
+// Base class for incoming data parser
+class USBReadParser
+{
+public:
+    virtual void    Parse(const uint16_t len, const uint8_t* pbuf, const uint16_t& offset) = 0;
+};
+
+class USB : public MAX3421E
+{
+    AddressPoolImpl<USB_NUMDEVICES> addrPool;
+    USBDeviceConfig*                devConfig[USB_NUMDEVICES];
+    uint8_t                         bmHubPre;
+public:
+    USB(PinName mosi, PinName miso, PinName sck, PinName ss, PinName intr);
+    int8_t          init();
+    void            SetHubPreMask()     { bmHubPre |= bmHUBPRE; }
+    void            ResetHubPreMask()   { bmHubPre &= (~bmHUBPRE); }
+    AddressPool&    GetAddressPool()    { return (AddressPool&)addrPool; }
+    uint8_t RegisterDeviceClass(USBDeviceConfig* pdev)
+    {
+        for (uint8_t i = 0; i < USB_NUMDEVICES; i++) {
+            if (!devConfig[i]) {
+                devConfig[i] = pdev;
+                return 0;
+            }
+        }
+
+        return USB_ERROR_UNABLE_TO_REGISTER_DEVICE_CLASS;
+    }
+
+    void        ForEachUsbDevice(UsbDeviceHandleFunc pfunc)     { addrPool.ForEachUsbDevice(pfunc); }
+    uint8_t     getUsbTaskState(void);
+    void        setUsbTaskState(uint8_t state);
+
+    EpInfo*     getEpInfoEntry(uint8_t addr, uint8_t ep);
+    uint8_t     setEpInfoEntry(uint8_t addr, uint8_t epcount, EpInfo* eprecord_ptr);
+
+    /* Control requests */
+    uint8_t     getDevDescr(uint8_t addr, uint8_t ep, uint16_t nbytes, uint8_t* dataptr);
+    uint8_t     getConfDescr(uint8_t addr, uint8_t ep, uint16_t nbytes, uint8_t conf, uint8_t* dataptr);
+
+    uint8_t     getConfDescr(uint8_t addr, uint8_t ep, uint8_t conf, USBReadParser* p);
+
+    uint8_t     getStrDescr
+                (
+                    uint8_t     addr,
+                    uint8_t     ep,
+                    uint16_t    nbytes,
+                    uint8_t     index,
+                    uint16_t    langid,
+                    uint8_t*    dataptr
+                );
+    uint8_t     setAddr(uint8_t oldaddr, uint8_t ep, uint8_t newaddr);
+    uint8_t     setConf(uint8_t addr, uint8_t ep, uint8_t conf_value);
+    /**/
+    uint8_t     ctrlData(uint8_t addr, uint8_t ep, uint16_t nbytes, uint8_t* dataptr, bool direction);
+    uint8_t     ctrlStatus(uint8_t ep, bool direction, uint16_t nak_limit);
+    uint8_t     inTransfer(uint8_t addr, uint8_t ep, uint16_t* nbytesptr, uint8_t* data, uint8_t bInterval = 0);
+    uint8_t     outTransfer(uint8_t addr, uint8_t ep, uint16_t nbytes, uint8_t* data);
+    uint8_t     dispatchPkt(uint8_t token, uint8_t ep, uint16_t nak_limit);
+
+    void        task(void);
+
+    uint8_t     defaultAddressing(uint8_t parent, uint8_t port, bool lowspeed);
+    uint8_t     configuring(uint8_t parent, uint8_t port, bool lowspeed);
+    uint8_t     releaseDevice(uint8_t addr);
+
+    uint8_t     ctrlReq
+                (
+                    uint8_t         addr,
+                    uint8_t         ep,
+                    uint8_t         bmReqType,
+                    uint8_t         bRequest,
+                    uint8_t         wValLo,
+                    uint8_t         wValHi,
+                    uint16_t        wInd,
+                    uint16_t        total,
+                    uint16_t        nbytes,
+                    uint8_t*        dataptr,
+                    USBReadParser*  p
+                );
+private:
+    uint8_t setAddress(uint8_t addr, uint8_t ep, EpInfo ** ppep, uint16_t* nak_limit);
+    uint8_t outTransfer(EpInfo* pep, uint16_t nak_limit, uint16_t nbytes, uint8_t* data);
+    uint8_t inTransfer(EpInfo* pep, uint16_t nak_limit, uint16_t* nbytesptr, uint8_t* data, uint8_t bInterval = 0);
+    uint8_t attemptConfig(uint8_t driver, uint8_t parent, uint8_t port, bool lowspeed);
+};
+
+#if 0   //defined(USB_METHODS_INLINE)
+
+//get device descriptor
+inline uint8_t USB::getDevDescr(uint8_t addr, uint8_t ep, uint16_t nbytes, uint8_t* dataptr)
+{
+    return
+        (
+            ctrlReq
+            (
+                addr,
+                ep,
+                bmREQ_GET_DESCR,
+                USB_REQUEST_GET_DESCRIPTOR,
+                0x00,
+                USB_DESCRIPTOR_DEVICE,
+                0x0000,
+                nbytes,
+                dataptr
+            )
+        );
+}
+
+//get configuration descriptor
+inline uint8_t USB::getConfDescr(uint8_t addr, uint8_t ep, uint16_t nbytes, uint8_t conf, uint8_t* dataptr)
+{
+    return
+        (
+            ctrlReq
+            (
+                addr,
+                ep,
+                bmREQ_GET_DESCR,
+                USB_REQUEST_GET_DESCRIPTOR,
+                conf,
+                USB_DESCRIPTOR_CONFIGURATION,
+                0x0000,
+                nbytes,
+                dataptr
+            )
+        );
+}
+
+//get string descriptor
+inline uint8_t USB::getStrDescr
+(
+    uint8_t     addr,
+    uint8_t     ep,
+    uint16_t    nuint8_ts,
+    uint8_t     index,
+    uint16_t    langid,
+    uint8_t*    dataptr
+)
+{
+    return
+        (
+            ctrlReq
+            (
+                addr,
+                ep,
+                bmREQ_GET_DESCR,
+                USB_REQUEST_GET_DESCRIPTOR,
+                index,
+                USB_DESCRIPTOR_STRING,
+                langid,
+                nuint8_ts,
+                dataptr
+            )
+        );
+}
+
+//set address
+inline uint8_t USB::setAddr(uint8_t oldaddr, uint8_t ep, uint8_t newaddr)
+{
+    return(ctrlReq(oldaddr, ep, bmREQ_SET, USB_REQUEST_SET_ADDRESS, newaddr, 0x00, 0x0000, 0x0000, NULL));
+}
+
+//set configuration
+inline uint8_t USB::setConf(uint8_t addr, uint8_t ep, uint8_t conf_value)
+{
+    return(ctrlReq(addr, ep, bmREQ_SET, USB_REQUEST_SET_CONFIGURATION, conf_value, 0x00, 0x0000, 0x0000, NULL));
+}
+#endif // defined(USB_METHODS_INLINE)
+#endif /* USBCORE_H */