summaryrefslogtreecommitdiff
path: root/tinyusb
diff options
context:
space:
mode:
authorhathach <[email protected]>2013-10-24 15:32:54 +0700
committerhathach <[email protected]>2013-10-24 15:32:54 +0700
commitb71ffe3d5a7b97010b7ac2096271e03dcb35c2dd (patch)
tree512a6798926f074a93701a10a31a6e6721b78e02 /tinyusb
parent2076e57d7072bb77c116c3cea51f640081da4aab (diff)
change TUSB_CFG_CONTROLLER0/1_MODE to TUSB_CFG_CONTROLLER_0/1_MODE for clearance
adding configuration docs for tinyusb_config.h document HID mouse & keyboard API
Diffstat (limited to 'tinyusb')
-rw-r--r--tinyusb/class/cdc.h686
-rw-r--r--tinyusb/class/hid.h1010
-rw-r--r--tinyusb/class/hid_host.c608
-rw-r--r--tinyusb/class/hid_host.h332
-rw-r--r--tinyusb/doxygen/configuration.h39
-rw-r--r--tinyusb/doxygen/overview.md3
-rw-r--r--tinyusb/hal/hal_lpc43xx.c246
-rw-r--r--tinyusb/host/ehci/ehci.c2196
-rw-r--r--tinyusb/mcu_capacity.h196
-rw-r--r--tinyusb/osal/osal.h413
-rw-r--r--tinyusb/tusb_option.h387
11 files changed, 3127 insertions, 2989 deletions
diff --git a/tinyusb/class/cdc.h b/tinyusb/class/cdc.h
index faa6310fa..7bbeb714f 100644
--- a/tinyusb/class/cdc.h
+++ b/tinyusb/class/cdc.h
@@ -1,343 +1,343 @@
-/**************************************************************************/
-/*!
- @file cdc.h
- @author hathach (tinyusb.org)
-
- @section LICENSE
-
- Software License Agreement (BSD License)
-
- Copyright (c) 2013, hathach (tinyusb.org)
- All rights reserved.
-
- Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions are met:
- 1. Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
- 2. Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
- 3. Neither the name of the copyright holders nor the
- names of its contributors may be used to endorse or promote products
- derived from this software without specific prior written permission.
-
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
- EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
- DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION HOWEVER CAUSED AND
- ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- INCLUDING NEGLIGENCE OR OTHERWISE ARISING IN ANY WAY OUT OF THE USE OF THIS
- SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
- This file is part of the tinyusb stack.
-*/
-/**************************************************************************/
-
-/** \file
- * \brief CDC Class Driver
- *
- * \note TBD
- */
-
-/**
- * \addtogroup Group_ClassDriver Class Driver
- * @{
- * \defgroup Group_CDC Communication Device Class
- * @{
- */
-
-#ifndef _TUSB_CDC_H__
-#define _TUSB_CDC_H__
-
-#include "common/common.h"
-
-#ifdef __cplusplus
- extern "C" {
-#endif
-
-//--------------------------------------------------------------------+
-// CDC COMMUNICATION INTERFACE CLASS
-//--------------------------------------------------------------------+
-enum {
- CDC_COMM_SUBCLASS_DIRECT_LINE_CONTROL_MODEL = 0x01 ,
- CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL ,
- CDC_COMM_SUBCLASS_TELEPHONE_CONTROL_MODEL ,
- CDC_COMM_SUBCLASS_MULTICHANNEL_CONTROL_MODEL ,
- CDC_COMM_SUBCLASS_CAPI_CONTROL_MODEL ,
- CDC_COMM_SUBCLASS_ETHERNET_NETWORKING_CONTROL_MODEL ,
- CDC_COMM_SUBCLASS_ATM_NETWORKING_CONTROL_MODEL ,
- CDC_COMM_SUBCLASS_WIRELESS_HANDSET_CONTROL_MODEL ,
- CDC_COMM_SUBCLASS_DEVICE_MANAGEMENT ,
- CDC_COMM_SUBCLASS_MOBILE_DIRECT_LINE_MODEL ,
- CDC_COMM_SUBCLASS_OBEX ,
- CDC_COMM_SUBCLASS_ETHERNET_EMULATION_MODEL
-};
-
-enum {
- CDC_COMM_PROTOCOL_ATCOMMAND = 0x01 , // ITU-T V2.50
- CDC_COMM_PROTOCOL_ATCOMMAND_PCCA_101 ,
- CDC_COMM_PROTOCOL_ATCOMMAND_PCCA_101_AND_ANNEXO ,
- CDC_COMM_PROTOCOL_ATCOMMAND_GSM_707 ,
- CDC_COMM_PROTOCOL_ATCOMMAND_3GPP_27007 ,
- CDC_COMM_PROTOCOL_ATCOMMAND_CDMA , // defined by TIA
- CDC_COMM_PROTOCOL_ETHERNET_EMULATION_MODEL
-};
-
-//------------- SubType Descriptor in COMM Functional Descriptor -------------//
-enum {
- CDC_FUNC_DESC_HEADER = 0x00 ,
- CDC_FUNC_DESC_CALL_MANAGEMENT = 0x01 ,
- CDC_FUNC_DESC_ABSTRACT_CONTROL_MANAGEMENT = 0x02 ,
- CDC_FUNC_DESC_DIRECT_LINE_MANAGEMENT = 0x03 ,
- CDC_FUNC_DESC_TELEPHONE_RINGER = 0x04 ,
- CDC_FUNC_DESC_TELEPHONE_CALL_AND_LINE_STATE_REPORTING_CAPACITY = 0x05 ,
- CDC_FUNC_DESC_UNION = 0x06 ,
- CDC_FUNC_DESC_COUNTRY_SELECTION = 0x07 ,
- CDC_FUNC_DESC_TELEPHONE_OPERATIONAL_MODES = 0x08 ,
- CDC_FUNC_DESC_USB_TERMINAL = 0x09 ,
- CDC_FUNC_DESC_NETWORK_CHANNEL_TERMINAL = 0x0A ,
- CDC_FUNC_DESC_PROTOCOL_UNIT = 0x0B ,
- CDC_FUNC_DESC_EXTENSION_UNIT = 0x0C ,
- CDC_FUNC_DESC_MULTICHANEL_MANAGEMENT = 0x0D ,
- CDC_FUNC_DESC_CAPI_CONTROL_MANAGEMENT = 0x0E ,
- CDC_FUNC_DESC_ETHERNET_NETWORKING = 0x0F ,
- CDC_FUNC_DESC_ATM_NETWORKING = 0x10 ,
- CDC_FUNC_DESC_WIRELESS_HANDSET_CONTROL_MODEL = 0x11 ,
- CDC_FUNC_DESC_MOBILE_DIRECT_LINE_MODEL = 0x12 ,
- CDC_FUNC_DESC_MOBILE_DIRECT_LINE_MODEL_DETAIL = 0x13 ,
- CDC_FUNC_DESC_DEVICE_MANAGEMENT_MODEL = 0x14 ,
- CDC_FUNC_DESC_OBEX = 0x15 ,
- CDC_FUNC_DESC_COMMAND_SET = 0x16 ,
- CDC_FUNC_DESC_COMMAND_SET_DETAIL = 0x17 ,
- CDC_FUNC_DESC_TELEPHONE_CONTROL_MODEL = 0x18 ,
- CDC_FUNC_DESC_OBEX_SERVICE_IDENTIFIER = 0x19
-};
-
-//--------------------------------------------------------------------+
-// CDC DATA INTERFACE CLASS
-//--------------------------------------------------------------------+
-
-// SUBCLASS code of Data Interface is not used and should/must be zero
-
-enum{
- CDC_DATA_PROTOCOL_ISDN_BRI = 0x30,
- CDC_DATA_PROTOCOL_HDLC = 0x31,
- CDC_DATA_PROTOCOL_TRANSPARENT = 0x32,
- CDC_DATA_PROTOCOL_Q921_MANAGEMENT = 0x50,
- CDC_DATA_PROTOCOL_Q921_DATA_LINK = 0x51,
- CDC_DATA_PROTOCOL_Q921_TEI_MULTIPLEXOR = 0x52,
- CDC_DATA_PROTOCOL_V42BIS_DATA_COMPRESSION = 0x90,
- CDC_DATA_PROTOCOL_EURO_ISDN = 0x91,
- CDC_DATA_PROTOCOL_V24_RATE_ADAPTION_TO_ISDN = 0x92,
- CDC_DATA_PROTOCOL_CAPI_COMMAND = 0x93,
- CDC_DATA_PROTOCOL_HOST_BASED_DRIVER = 0xFD,
- CDC_DATA_PROTOCOL_IN_PROTOCOL_UNIT_FUNCTIONAL_DESCRIPTOR = 0xFE
-};
-
-//--------------------------------------------------------------------+
-// MANAGEMENT ELEMENT REQUEST (CONTROL ENDPOINT)
-//--------------------------------------------------------------------+
-typedef enum {
- SEND_ENCAPSULATED_COMMAND = 0x00,
- GET_ENCAPSULATED_RESPONSE = 0x01,
-
- SET_COMM_FEATURE = 0x02,
- GET_COMM_FEATURE = 0x03,
- CLEAR_COMM_FEATURE = 0x04,
-
- SET_AUX_LINE_STATE = 0x10,
- SET_HOOK_STATE = 0x11,
- PULSE_SETUP = 0x12,
- SEND_PULSE = 0x13,
- SET_PULSE_TIME = 0x14,
- RING_AUX_JACK = 0x15,
-
- SET_LINE_CODING = 0x20,
- GET_LINE_CODING = 0x21,
- SET_CONTROL_LINE_STATE = 0x22,
- SEND_BREAK = 0x23,
-
- SET_RINGER_PARMS = 0x30,
- GET_RINGER_PARMS = 0x31,
- SET_OPERATION_PARMS = 0x32,
- GET_OPERATION_PARMS = 0x33,
- SET_LINE_PARMS = 0x34,
- GET_LINE_PARMS = 0x35,
- DIAL_DIGITS = 0x36,
- SET_UNIT_PARAMETER = 0x37,
- GET_UNIT_PARAMETER = 0x38,
- CLEAR_UNIT_PARAMETER = 0x39,
- GET_PROFILE = 0x3A,
-
- SET_ETHERNET_MULTICAST_FILTERS = 0x40,
- SET_ETHERNET_POWER_MANAGEMENT_PATTERN_FILTER = 0x41,
- GET_ETHERNET_POWER_MANAGEMENT_PATTERN_FILTER = 0x42,
- SET_ETHERNET_PACKET_FILTER = 0x43,
- GET_ETHERNET_STATISTIC = 0x44,
-
- SET_ATM_DATA_FORMAT = 0x50,
- GET_ATM_DEVICE_STATISTICS = 0x51,
- SET_ATM_DEFAULT_VC = 0x52,
- GET_ATM_VC_STATISTICS = 0x53,
-
- MDLM_SEMANTIC_MODEL = 0x60,
-}cdc_management_request_t;
-
-//--------------------------------------------------------------------+
-// MANAGEMENT ELEMENENT NOTIFICATION (NOTIFICATION ENDPOINT)
-//--------------------------------------------------------------------+
-typedef enum {
- NETWORK_CONNECTION = 0x00,
- RESPONSE_AVAILABLE = 0x01,
-
- AUX_JACK_HOOK_STATE = 0x08,
- RING_DETECT = 0x09,
-
- SERIAL_STATE = 0x20,
-
- CALL_STATE_CHANGE = 0x28,
- LINE_STATE_CHANGE = 0x29,
- CONNECTION_SPEED_CHANGE = 0x2A,
- MDLM_SEMANTIC_MODEL_NOTIFICATION = 0x40,
-}cdc_notification_request_t;
-
-//--------------------------------------------------------------------+
-// FUNCTIONAL DESCRIPTOR
-//--------------------------------------------------------------------+
-typedef ATTR_PACKED_STRUCT(struct) {
- uint8_t bLength ; ///< Size of this descriptor in bytes.
- uint8_t bDescriptorType ; ///< Descriptor Type, must be Class-Specific
- uint8_t bDescriptorSubType ; ///< Descriptor SubType one of above CDC_FUCN_DESC_
- uint16_t bcdCDC ; ///< CDC release number in Binary-Coded Decimal
-}cdc_desc_func_header_t;
-
-typedef ATTR_PACKED_STRUCT(struct) {
- uint8_t bLength ; ///< Size of this descriptor in bytes.
- uint8_t bDescriptorType ; ///< Descriptor Type, must be Class-Specific
- uint8_t bDescriptorSubType ; ///< Descriptor SubType one of above CDC_FUCN_DESC_
- uint8_t bControlInterface ; ///< Interface number of Communication Interface
- uint8_t bSubordinateInterface ; ///< Array of Interface number of Data Interface
-}cdc_desc_func_union_t;
-
-#define cdc_desc_func_union_n_t(no_slave)\
- ATTR_PACKED_STRUCT(struct) { \
- uint8_t bLength ;\
- uint8_t bDescriptorType ;\
- uint8_t bDescriptorSubType ;\
- uint8_t bControlInterface ;\
- uint8_t bSubordinateInterface[no_slave] ;\
-}
-
-typedef ATTR_PACKED_STRUCT(struct) {
- uint8_t bLength ; ///< Size of this descriptor in bytes.
- uint8_t bDescriptorType ; ///< Descriptor Type, must be Class-Specific
- uint8_t bDescriptorSubType ; ///< Descriptor SubType one of above CDC_FUCN_DESC_
- uint8_t iCountryCodeRelDate ; ///< Index of a string giving the release date for the implemented ISO 3166 Country Codes.
- uint16_t wCountryCode[] ; ///< Country code in the format as defined in [ISO3166], release date as specified inoffset 3 for the first supported country.
-}cdc_desc_func_country_selection_t;
-
-#define cdc_desc_func_country_selection_n_t(no_country) \
- ATTR_PACKED_STRUCT(struct) {\
- uint8_t bLength ;\
- uint8_t bDescriptorType ;\
- uint8_t bDescriptorSubType ;\
- uint8_t iCountryCodeRelDate ;\
- uint16_t wCountryCode[no_country] ;\
-}
-
-//--------------------------------------------------------------------+
-// PUBLIC SWITCHED TELEPHONE NETWORK (PSTN) SUBCLASS
-//--------------------------------------------------------------------+
-typedef ATTR_PACKED_STRUCT(struct) {
- uint8_t bLength ; ///< Size of this descriptor in bytes.
- uint8_t bDescriptorType ; ///< Descriptor Type, must be Class-Specific
- uint8_t bDescriptorSubType ; ///< Descriptor SubType one of above CDC_FUCN_DESC_
-
- struct {
- uint8_t handle_call : 1; ///< 0 - Device sends/receives call management information only over the Communications Class interface. 1 - Device can send/receive call management information over a Data Class interface.
- uint8_t send_recv_call : 1; ///< 0 - Device does not handle call management itself. 1 - Device handles call management itself.
- uint8_t : 0;
- } bmCapabilities;
-
- uint8_t bDataInterface;
-}cdc_desc_func_call_management_t;
-
-typedef ATTR_PACKED_STRUCT(struct) {
- uint8_t support_comm_request : 1; ///< Device supports the request combination of Set_Comm_Feature, Clear_Comm_Feature, and Get_Comm_Feature.
- uint8_t support_line_request : 1; ///< Device supports the request combination of Set_Line_Coding, Set_Control_Line_State, Get_Line_Coding, and the notification Serial_State.
- uint8_t support_send_break : 1; ///< Device supports the request Send_Break
- uint8_t support_notification_network_connection : 1; ///< Device supports the notification Network_Connection.
- uint8_t : 0;
-}cdc_acm_capability_t;
-
-STATIC_ASSERT(sizeof(cdc_acm_capability_t) == 1, "mostly problem with compiler");
-
-typedef ATTR_PACKED_STRUCT(struct) {
- uint8_t bLength ; ///< Size of this descriptor in bytes.
- uint8_t bDescriptorType ; ///< Descriptor Type, must be Class-Specific
- uint8_t bDescriptorSubType ; ///< Descriptor SubType one of above CDC_FUCN_DESC_
- cdc_acm_capability_t bmCapabilities ;
-}cdc_desc_func_abstract_control_management_t;
-
-typedef ATTR_PACKED_STRUCT(struct) {
- uint8_t bLength ; ///< Size of this descriptor in bytes.
- uint8_t bDescriptorType ; ///< Descriptor Type, must be Class-Specific
- uint8_t bDescriptorSubType ; ///< Descriptor SubType one of above CDC_FUCN_DESC_
- struct {
- uint8_t require_pulse_setup : 1; ///< Device requires extra Pulse_Setup request during pulse dialing sequence to disengage holding circuit.
- uint8_t support_aux_request : 1; ///< Device supports the request combination of Set_Aux_Line_State, Ring_Aux_Jack, and notification Aux_Jack_Hook_State.
- uint8_t support_pulse_request : 1; ///< Device supports the request combination of Pulse_Setup, Send_Pulse, and Set_Pulse_Time.
- uint8_t : 0;
- } bmCapabilities;
-}cdc_desc_func_direct_line_management_t;
-
-typedef ATTR_PACKED_STRUCT(struct) {
- uint8_t bLength ; ///< Size of this descriptor in bytes.
- uint8_t bDescriptorType ; ///< Descriptor Type, must be Class-Specific
- uint8_t bDescriptorSubType ; ///< Descriptor SubType one of above CDC_FUCN_DESC_
- uint8_t bRingerVolSteps ;
- uint8_t bNumRingerPatterns ;
-}cdc_desc_func_telephone_ringer_t;
-
-typedef ATTR_PACKED_STRUCT(struct) {
- uint8_t bLength ; ///< Size of this descriptor in bytes.
- uint8_t bDescriptorType ; ///< Descriptor Type, must be Class-Specific
- uint8_t bDescriptorSubType ; ///< Descriptor SubType one of above CDC_FUCN_DESC_
- struct {
- uint8_t simple_mode : 1;
- uint8_t standalone_mode : 1;
- uint8_t computer_centric_mode : 1;
- uint8_t : 0;
- } bmCapabilities;
-}cdc_desc_func_telephone_operational_modes_t;
-
-typedef ATTR_PACKED_STRUCT(struct) {
- uint8_t bLength ; ///< Size of this descriptor in bytes.
- uint8_t bDescriptorType ; ///< Descriptor Type, must be Class-Specific
- uint8_t bDescriptorSubType ; ///< Descriptor SubType one of above CDC_FUCN_DESC_
- struct {
- uint32_t interrupted_dialtone : 1; ///< 0 : Reports only dialtone (does not differentiate between normal and interrupted dialtone). 1 : Reports interrupted dialtone in addition to normal dialtone
- uint32_t ringback_busy_fastbusy : 1; ///< 0 : Reports only dialing state. 1 : Reports ringback, busy, and fast busy states.
- uint32_t caller_id : 1; ///< 0 : Does not report caller ID. 1 : Reports caller ID information.
- uint32_t incoming_distinctive : 1; ///< 0 : Reports only incoming ringing. 1 : Reports incoming distinctive ringing patterns.
- uint32_t dual_tone_multi_freq : 1; ///< 0 : Cannot report dual tone multi-frequency (DTMF) digits input remotely over the telephone line. 1 : Can report DTMF digits input remotely over the telephone line.
- uint32_t line_state_change : 1; ///< 0 : Does not support line state change notification. 1 : Does support line state change notification
- uint32_t : 0;
- } bmCapabilities;
-}cdc_desc_func_telephone_call_state_reporting_capabilities_t;
-
-static inline uint8_t cdc_functional_desc_typeof(uint8_t const * p_desc) ATTR_PURE ATTR_ALWAYS_INLINE;
-static inline uint8_t cdc_functional_desc_typeof(uint8_t const * p_desc)
-{
- return p_desc[2];
-}
-
-
-#ifdef __cplusplus
- }
-#endif
-
-#endif
+/**************************************************************************/
+/*!
+ @file cdc.h
+ @author hathach (tinyusb.org)
+
+ @section LICENSE
+
+ Software License Agreement (BSD License)
+
+ Copyright (c) 2013, hathach (tinyusb.org)
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ 3. Neither the name of the copyright holders nor the
+ names of its contributors may be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
+ EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
+ DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION HOWEVER CAUSED AND
+ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ INCLUDING NEGLIGENCE OR OTHERWISE ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ This file is part of the tinyusb stack.
+*/
+/**************************************************************************/
+
+/** \file
+ * \brief CDC Class Driver
+ *
+ * \note TBD
+ */
+
+/**
+ * \addtogroup ClassDriver Class Driver
+ * @{
+ * \defgroup ClassDriver_CDC Communication Device Class
+ * @{
+ */
+
+#ifndef _TUSB_CDC_H__
+#define _TUSB_CDC_H__
+
+#include "common/common.h"
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+//--------------------------------------------------------------------+
+// CDC COMMUNICATION INTERFACE CLASS
+//--------------------------------------------------------------------+
+enum {
+ CDC_COMM_SUBCLASS_DIRECT_LINE_CONTROL_MODEL = 0x01 ,
+ CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL ,
+ CDC_COMM_SUBCLASS_TELEPHONE_CONTROL_MODEL ,
+ CDC_COMM_SUBCLASS_MULTICHANNEL_CONTROL_MODEL ,
+ CDC_COMM_SUBCLASS_CAPI_CONTROL_MODEL ,
+ CDC_COMM_SUBCLASS_ETHERNET_NETWORKING_CONTROL_MODEL ,
+ CDC_COMM_SUBCLASS_ATM_NETWORKING_CONTROL_MODEL ,
+ CDC_COMM_SUBCLASS_WIRELESS_HANDSET_CONTROL_MODEL ,
+ CDC_COMM_SUBCLASS_DEVICE_MANAGEMENT ,
+ CDC_COMM_SUBCLASS_MOBILE_DIRECT_LINE_MODEL ,
+ CDC_COMM_SUBCLASS_OBEX ,
+ CDC_COMM_SUBCLASS_ETHERNET_EMULATION_MODEL
+};
+
+enum {
+ CDC_COMM_PROTOCOL_ATCOMMAND = 0x01 , // ITU-T V2.50
+ CDC_COMM_PROTOCOL_ATCOMMAND_PCCA_101 ,
+ CDC_COMM_PROTOCOL_ATCOMMAND_PCCA_101_AND_ANNEXO ,
+ CDC_COMM_PROTOCOL_ATCOMMAND_GSM_707 ,
+ CDC_COMM_PROTOCOL_ATCOMMAND_3GPP_27007 ,
+ CDC_COMM_PROTOCOL_ATCOMMAND_CDMA , // defined by TIA
+ CDC_COMM_PROTOCOL_ETHERNET_EMULATION_MODEL
+};
+
+//------------- SubType Descriptor in COMM Functional Descriptor -------------//
+enum {
+ CDC_FUNC_DESC_HEADER = 0x00 ,
+ CDC_FUNC_DESC_CALL_MANAGEMENT = 0x01 ,
+ CDC_FUNC_DESC_ABSTRACT_CONTROL_MANAGEMENT = 0x02 ,
+ CDC_FUNC_DESC_DIRECT_LINE_MANAGEMENT = 0x03 ,
+ CDC_FUNC_DESC_TELEPHONE_RINGER = 0x04 ,
+ CDC_FUNC_DESC_TELEPHONE_CALL_AND_LINE_STATE_REPORTING_CAPACITY = 0x05 ,
+ CDC_FUNC_DESC_UNION = 0x06 ,
+ CDC_FUNC_DESC_COUNTRY_SELECTION = 0x07 ,
+ CDC_FUNC_DESC_TELEPHONE_OPERATIONAL_MODES = 0x08 ,
+ CDC_FUNC_DESC_USB_TERMINAL = 0x09 ,
+ CDC_FUNC_DESC_NETWORK_CHANNEL_TERMINAL = 0x0A ,
+ CDC_FUNC_DESC_PROTOCOL_UNIT = 0x0B ,
+ CDC_FUNC_DESC_EXTENSION_UNIT = 0x0C ,
+ CDC_FUNC_DESC_MULTICHANEL_MANAGEMENT = 0x0D ,
+ CDC_FUNC_DESC_CAPI_CONTROL_MANAGEMENT = 0x0E ,
+ CDC_FUNC_DESC_ETHERNET_NETWORKING = 0x0F ,
+ CDC_FUNC_DESC_ATM_NETWORKING = 0x10 ,
+ CDC_FUNC_DESC_WIRELESS_HANDSET_CONTROL_MODEL = 0x11 ,
+ CDC_FUNC_DESC_MOBILE_DIRECT_LINE_MODEL = 0x12 ,
+ CDC_FUNC_DESC_MOBILE_DIRECT_LINE_MODEL_DETAIL = 0x13 ,
+ CDC_FUNC_DESC_DEVICE_MANAGEMENT_MODEL = 0x14 ,
+ CDC_FUNC_DESC_OBEX = 0x15 ,
+ CDC_FUNC_DESC_COMMAND_SET = 0x16 ,
+ CDC_FUNC_DESC_COMMAND_SET_DETAIL = 0x17 ,
+ CDC_FUNC_DESC_TELEPHONE_CONTROL_MODEL = 0x18 ,
+ CDC_FUNC_DESC_OBEX_SERVICE_IDENTIFIER = 0x19
+};
+
+//--------------------------------------------------------------------+
+// CDC DATA INTERFACE CLASS
+//--------------------------------------------------------------------+
+
+// SUBCLASS code of Data Interface is not used and should/must be zero
+
+enum{
+ CDC_DATA_PROTOCOL_ISDN_BRI = 0x30,
+ CDC_DATA_PROTOCOL_HDLC = 0x31,
+ CDC_DATA_PROTOCOL_TRANSPARENT = 0x32,
+ CDC_DATA_PROTOCOL_Q921_MANAGEMENT = 0x50,
+ CDC_DATA_PROTOCOL_Q921_DATA_LINK = 0x51,
+ CDC_DATA_PROTOCOL_Q921_TEI_MULTIPLEXOR = 0x52,
+ CDC_DATA_PROTOCOL_V42BIS_DATA_COMPRESSION = 0x90,
+ CDC_DATA_PROTOCOL_EURO_ISDN = 0x91,
+ CDC_DATA_PROTOCOL_V24_RATE_ADAPTION_TO_ISDN = 0x92,
+ CDC_DATA_PROTOCOL_CAPI_COMMAND = 0x93,
+ CDC_DATA_PROTOCOL_HOST_BASED_DRIVER = 0xFD,
+ CDC_DATA_PROTOCOL_IN_PROTOCOL_UNIT_FUNCTIONAL_DESCRIPTOR = 0xFE
+};
+
+//--------------------------------------------------------------------+
+// MANAGEMENT ELEMENT REQUEST (CONTROL ENDPOINT)
+//--------------------------------------------------------------------+
+typedef enum {
+ SEND_ENCAPSULATED_COMMAND = 0x00,
+ GET_ENCAPSULATED_RESPONSE = 0x01,
+
+ SET_COMM_FEATURE = 0x02,
+ GET_COMM_FEATURE = 0x03,
+ CLEAR_COMM_FEATURE = 0x04,
+
+ SET_AUX_LINE_STATE = 0x10,
+ SET_HOOK_STATE = 0x11,
+ PULSE_SETUP = 0x12,
+ SEND_PULSE = 0x13,
+ SET_PULSE_TIME = 0x14,
+ RING_AUX_JACK = 0x15,
+
+ SET_LINE_CODING = 0x20,
+ GET_LINE_CODING = 0x21,
+ SET_CONTROL_LINE_STATE = 0x22,
+ SEND_BREAK = 0x23,
+
+ SET_RINGER_PARMS = 0x30,
+ GET_RINGER_PARMS = 0x31,
+ SET_OPERATION_PARMS = 0x32,
+ GET_OPERATION_PARMS = 0x33,
+ SET_LINE_PARMS = 0x34,
+ GET_LINE_PARMS = 0x35,
+ DIAL_DIGITS = 0x36,
+ SET_UNIT_PARAMETER = 0x37,
+ GET_UNIT_PARAMETER = 0x38,
+ CLEAR_UNIT_PARAMETER = 0x39,
+ GET_PROFILE = 0x3A,
+
+ SET_ETHERNET_MULTICAST_FILTERS = 0x40,
+ SET_ETHERNET_POWER_MANAGEMENT_PATTERN_FILTER = 0x41,
+ GET_ETHERNET_POWER_MANAGEMENT_PATTERN_FILTER = 0x42,
+ SET_ETHERNET_PACKET_FILTER = 0x43,
+ GET_ETHERNET_STATISTIC = 0x44,
+
+ SET_ATM_DATA_FORMAT = 0x50,
+ GET_ATM_DEVICE_STATISTICS = 0x51,
+ SET_ATM_DEFAULT_VC = 0x52,
+ GET_ATM_VC_STATISTICS = 0x53,
+
+ MDLM_SEMANTIC_MODEL = 0x60,
+}cdc_management_request_t;
+
+//--------------------------------------------------------------------+
+// MANAGEMENT ELEMENENT NOTIFICATION (NOTIFICATION ENDPOINT)
+//--------------------------------------------------------------------+
+typedef enum {
+ NETWORK_CONNECTION = 0x00,
+ RESPONSE_AVAILABLE = 0x01,
+
+ AUX_JACK_HOOK_STATE = 0x08,
+ RING_DETECT = 0x09,
+
+ SERIAL_STATE = 0x20,
+
+ CALL_STATE_CHANGE = 0x28,
+ LINE_STATE_CHANGE = 0x29,
+ CONNECTION_SPEED_CHANGE = 0x2A,
+ MDLM_SEMANTIC_MODEL_NOTIFICATION = 0x40,
+}cdc_notification_request_t;
+
+//--------------------------------------------------------------------+
+// FUNCTIONAL DESCRIPTOR
+//--------------------------------------------------------------------+
+typedef ATTR_PACKED_STRUCT(struct) {
+ uint8_t bLength ; ///< Size of this descriptor in bytes.
+ uint8_t bDescriptorType ; ///< Descriptor Type, must be Class-Specific
+ uint8_t bDescriptorSubType ; ///< Descriptor SubType one of above CDC_FUCN_DESC_
+ uint16_t bcdCDC ; ///< CDC release number in Binary-Coded Decimal
+}cdc_desc_func_header_t;
+
+typedef ATTR_PACKED_STRUCT(struct) {
+ uint8_t bLength ; ///< Size of this descriptor in bytes.
+ uint8_t bDescriptorType ; ///< Descriptor Type, must be Class-Specific
+ uint8_t bDescriptorSubType ; ///< Descriptor SubType one of above CDC_FUCN_DESC_
+ uint8_t bControlInterface ; ///< Interface number of Communication Interface
+ uint8_t bSubordinateInterface ; ///< Array of Interface number of Data Interface
+}cdc_desc_func_union_t;
+
+#define cdc_desc_func_union_n_t(no_slave)\
+ ATTR_PACKED_STRUCT(struct) { \
+ uint8_t bLength ;\
+ uint8_t bDescriptorType ;\
+ uint8_t bDescriptorSubType ;\
+ uint8_t bControlInterface ;\
+ uint8_t bSubordinateInterface[no_slave] ;\
+}
+
+typedef ATTR_PACKED_STRUCT(struct) {
+ uint8_t bLength ; ///< Size of this descriptor in bytes.
+ uint8_t bDescriptorType ; ///< Descriptor Type, must be Class-Specific
+ uint8_t bDescriptorSubType ; ///< Descriptor SubType one of above CDC_FUCN_DESC_
+ uint8_t iCountryCodeRelDate ; ///< Index of a string giving the release date for the implemented ISO 3166 Country Codes.
+ uint16_t wCountryCode[] ; ///< Country code in the format as defined in [ISO3166], release date as specified inoffset 3 for the first supported country.
+}cdc_desc_func_country_selection_t;
+
+#define cdc_desc_func_country_selection_n_t(no_country) \
+ ATTR_PACKED_STRUCT(struct) {\
+ uint8_t bLength ;\
+ uint8_t bDescriptorType ;\
+ uint8_t bDescriptorSubType ;\
+ uint8_t iCountryCodeRelDate ;\
+ uint16_t wCountryCode[no_country] ;\
+}
+
+//--------------------------------------------------------------------+
+// PUBLIC SWITCHED TELEPHONE NETWORK (PSTN) SUBCLASS
+//--------------------------------------------------------------------+
+typedef ATTR_PACKED_STRUCT(struct) {
+ uint8_t bLength ; ///< Size of this descriptor in bytes.
+ uint8_t bDescriptorType ; ///< Descriptor Type, must be Class-Specific
+ uint8_t bDescriptorSubType ; ///< Descriptor SubType one of above CDC_FUCN_DESC_
+
+ struct {
+ uint8_t handle_call : 1; ///< 0 - Device sends/receives call management information only over the Communications Class interface. 1 - Device can send/receive call management information over a Data Class interface.
+ uint8_t send_recv_call : 1; ///< 0 - Device does not handle call management itself. 1 - Device handles call management itself.
+ uint8_t : 0;
+ } bmCapabilities;
+
+ uint8_t bDataInterface;
+}cdc_desc_func_call_management_t;
+
+typedef ATTR_PACKED_STRUCT(struct) {
+ uint8_t support_comm_request : 1; ///< Device supports the request combination of Set_Comm_Feature, Clear_Comm_Feature, and Get_Comm_Feature.
+ uint8_t support_line_request : 1; ///< Device supports the request combination of Set_Line_Coding, Set_Control_Line_State, Get_Line_Coding, and the notification Serial_State.
+ uint8_t support_send_break : 1; ///< Device supports the request Send_Break
+ uint8_t support_notification_network_connection : 1; ///< Device supports the notification Network_Connection.
+ uint8_t : 0;
+}cdc_acm_capability_t;
+
+STATIC_ASSERT(sizeof(cdc_acm_capability_t) == 1, "mostly problem with compiler");
+
+typedef ATTR_PACKED_STRUCT(struct) {
+ uint8_t bLength ; ///< Size of this descriptor in bytes.
+ uint8_t bDescriptorType ; ///< Descriptor Type, must be Class-Specific
+ uint8_t bDescriptorSubType ; ///< Descriptor SubType one of above CDC_FUCN_DESC_
+ cdc_acm_capability_t bmCapabilities ;
+}cdc_desc_func_abstract_control_management_t;
+
+typedef ATTR_PACKED_STRUCT(struct) {
+ uint8_t bLength ; ///< Size of this descriptor in bytes.
+ uint8_t bDescriptorType ; ///< Descriptor Type, must be Class-Specific
+ uint8_t bDescriptorSubType ; ///< Descriptor SubType one of above CDC_FUCN_DESC_
+ struct {
+ uint8_t require_pulse_setup : 1; ///< Device requires extra Pulse_Setup request during pulse dialing sequence to disengage holding circuit.
+ uint8_t support_aux_request : 1; ///< Device supports the request combination of Set_Aux_Line_State, Ring_Aux_Jack, and notification Aux_Jack_Hook_State.
+ uint8_t support_pulse_request : 1; ///< Device supports the request combination of Pulse_Setup, Send_Pulse, and Set_Pulse_Time.
+ uint8_t : 0;
+ } bmCapabilities;
+}cdc_desc_func_direct_line_management_t;
+
+typedef ATTR_PACKED_STRUCT(struct) {
+ uint8_t bLength ; ///< Size of this descriptor in bytes.
+ uint8_t bDescriptorType ; ///< Descriptor Type, must be Class-Specific
+ uint8_t bDescriptorSubType ; ///< Descriptor SubType one of above CDC_FUCN_DESC_
+ uint8_t bRingerVolSteps ;
+ uint8_t bNumRingerPatterns ;
+}cdc_desc_func_telephone_ringer_t;
+
+typedef ATTR_PACKED_STRUCT(struct) {
+ uint8_t bLength ; ///< Size of this descriptor in bytes.
+ uint8_t bDescriptorType ; ///< Descriptor Type, must be Class-Specific
+ uint8_t bDescriptorSubType ; ///< Descriptor SubType one of above CDC_FUCN_DESC_
+ struct {
+ uint8_t simple_mode : 1;
+ uint8_t standalone_mode : 1;
+ uint8_t computer_centric_mode : 1;
+ uint8_t : 0;
+ } bmCapabilities;
+}cdc_desc_func_telephone_operational_modes_t;
+
+typedef ATTR_PACKED_STRUCT(struct) {
+ uint8_t bLength ; ///< Size of this descriptor in bytes.
+ uint8_t bDescriptorType ; ///< Descriptor Type, must be Class-Specific
+ uint8_t bDescriptorSubType ; ///< Descriptor SubType one of above CDC_FUCN_DESC_
+ struct {
+ uint32_t interrupted_dialtone : 1; ///< 0 : Reports only dialtone (does not differentiate between normal and interrupted dialtone). 1 : Reports interrupted dialtone in addition to normal dialtone
+ uint32_t ringback_busy_fastbusy : 1; ///< 0 : Reports only dialing state. 1 : Reports ringback, busy, and fast busy states.
+ uint32_t caller_id : 1; ///< 0 : Does not report caller ID. 1 : Reports caller ID information.
+ uint32_t incoming_distinctive : 1; ///< 0 : Reports only incoming ringing. 1 : Reports incoming distinctive ringing patterns.
+ uint32_t dual_tone_multi_freq : 1; ///< 0 : Cannot report dual tone multi-frequency (DTMF) digits input remotely over the telephone line. 1 : Can report DTMF digits input remotely over the telephone line.
+ uint32_t line_state_change : 1; ///< 0 : Does not support line state change notification. 1 : Does support line state change notification
+ uint32_t : 0;
+ } bmCapabilities;
+}cdc_desc_func_telephone_call_state_reporting_capabilities_t;
+
+static inline uint8_t cdc_functional_desc_typeof(uint8_t const * p_desc) ATTR_PURE ATTR_ALWAYS_INLINE;
+static inline uint8_t cdc_functional_desc_typeof(uint8_t const * p_desc)
+{
+ return p_desc[2];
+}
+
+
+#ifdef __cplusplus
+ }
+#endif
+
+#endif
diff --git a/tinyusb/class/hid.h b/tinyusb/class/hid.h
index 6a983648b..636cdac8b 100644
--- a/tinyusb/class/hid.h
+++ b/tinyusb/class/hid.h
@@ -1,505 +1,505 @@
-/**************************************************************************/
-/*!
- @file hid.h
- @author hathach (tinyusb.org)
-
- @section LICENSE
-
- Software License Agreement (BSD License)
-
- Copyright (c) 2013, hathach (tinyusb.org)
- All rights reserved.
-
- Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions are met:
- 1. Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
- 2. Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
- 3. Neither the name of the copyright holders nor the
- names of its contributors may be used to endorse or promote products
- derived from this software without specific prior written permission.
-
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
- EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
- DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION HOWEVER CAUSED AND
- ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- INCLUDING NEGLIGENCE OR OTHERWISE ARISING IN ANY WAY OUT OF THE USE OF THIS
- SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
- This file is part of the tinyusb stack.
-*/
-/**************************************************************************/
-
-/**
- * \addtogroup Group_ClassDriver Class Driver
- * @{
- * \defgroup Group_HID Human Interface Device
- * @{
- */
-
-#ifndef _TUSB_HID_H_
-#define _TUSB_HID_H_
-
-#include "common/common.h"
-
-#ifdef __cplusplus
- extern "C" {
-#endif
-
-enum {
- HID_SUBCLASS_NONE = 0,
- HID_SUBCLASS_BOOT = 1
-};
-
-enum {
- HID_PROTOCOL_NONE = 0,
- HID_PROTOCOL_KEYBOARD = 1,
- HID_PROTOCOL_MOUSE = 2
-};
-
-enum {
- HID_DESC_TYPE_HID = 0x21,
- HID_DESC_TYPE_REPORT = 0x22,
- HID_DESC_TYPE_PHYSICAL = 0x23
-};
-
-enum {
- HID_REQUEST_REPORT_INPUT = 1,
- HID_REQUEST_REPORT_OUTPUT,
- HID_REQUEST_REPORT_FEATURE
-};
-
-enum {
- HID_REQUEST_CONTROL_GET_REPORT = 0x01,
- HID_REQUEST_CONTROL_GET_IDLE = 0x02,
- HID_REQUEST_CONTROL_GET_PROTOCOL = 0x03,
- HID_REQUEST_CONTROL_SET_REPORT = 0x09,
- HID_REQUEST_CONTROL_SET_IDLE = 0x0a,
- HID_REQUEST_CONTROL_SET_PROTOCOL = 0x0b
-};
-
-typedef ATTR_PACKED_STRUCT(struct) {
- uint8_t bLength; /**< Numeric expression that is the total size of the HID descriptor */
- uint8_t bDescriptorType; /**< Constant name specifying type of HID descriptor. */
-
- uint16_t bcdHID; /**< Numeric expression identifying the HID Class Specification release */
- uint8_t bCountryCode; /**< Numeric expression identifying country code of the localized hardware. */
- uint8_t bNumDescriptors; /**< Numeric expression specifying the number of class descriptors */
-
- uint8_t bReportType; /**< Type of HID class report. */
- uint16_t wReportLength; /**< the total size of the Report descriptor. */
-} tusb_hid_descriptor_hid_t;
-
-/**
- * \brief Standard HID Boot Protocol Mouse Report.
- *
- * Type define for a standard Boot Protocol Mouse report
- */
-typedef ATTR_PACKED_STRUCT(struct)
-{
- uint8_t buttons; /**< buttons mask for currently pressed buttons in the mouse. */
- int8_t x; /**< Current delta x movement of the mouse. */
- int8_t y; /**< Current delta y movement on the mouse. */
- int8_t wheel; /**< Current delta wheel movement on the mouse. */
-} tusb_mouse_report_t;
-
-/**
- * \brief Standard HID Boot Protocol Keyboard Report.
- *
- * Type define for a standard Boot Protocol Keyboard report
- */
-typedef ATTR_PACKED_STRUCT(struct)
-{
- uint8_t modifier; /**< Keyboard modifier byte, indicating pressed modifier keys (a combination of HID_KEYBOARD_MODIFER_* masks). */
- uint8_t reserved; /**< Reserved for OEM use, always set to 0. */
- uint8_t keycode[6]; /**< Key codes of the currently pressed keys. */
-} tusb_keyboard_report_t;
-
-/**
- * \brief buttons codes for HID mouse
- */
-enum {
- MOUSE_BUTTON_LEFT = BIT_(0),
- MOUSE_BUTTON_RIGHT = BIT_(1),
- MOUSE_BUTTON_MIDDLE = BIT_(2)
-};
-
-/**
- * \brief KB modifier codes for HID KB
- */
-enum {
- KEYBOARD_MODIFIER_LEFTCTRL = BIT_(0),
- KEYBOARD_MODIFIER_LEFTSHIFT = BIT_(1),
- KEYBOARD_MODIFIER_LEFTALT = BIT_(2),
- KEYBOARD_MODIFIER_LEFTGUI = BIT_(3),
- KEYBOARD_MODIFIER_RIGHTCTRL = BIT_(4),
- KEYBOARD_MODIFIER_RIGHTSHIFT = BIT_(5),
- KEYBOARD_MODIFIER_RIGHTALT = BIT_(6),
- KEYBOARD_MODIFIER_RIGHTGUI = BIT_(7)
-};
-
-#define HID_KEYCODE_TABLE(ENTRY) \
- ENTRY( 0x04, 'a', 'A' )\
- ENTRY( 0x05, 'b', 'B' )\
- ENTRY( 0x06, 'c', 'C' )\
- ENTRY( 0x07, 'd', 'D' )\
- ENTRY( 0x08, 'e', 'E' )\
- ENTRY( 0x09, 'f', 'F' )\
- ENTRY( 0x0a, 'g', 'G' )\
- ENTRY( 0x0b, 'h', 'H' )\
- ENTRY( 0x0c, 'i', 'I' )\
- ENTRY( 0x0d, 'j', 'J' )\
- ENTRY( 0x0e, 'k', 'K' )\
- ENTRY( 0x0f, 'l', 'L' )\
- \
- ENTRY( 0x10, 'm', 'M' )\
- ENTRY( 0x11, 'n', 'N' )\
- ENTRY( 0x12, 'o', 'O' )\
- ENTRY( 0x13, 'p', 'P' )\
- ENTRY( 0x14, 'q', 'Q' )\
- ENTRY( 0x15, 'r', 'R' )\
- ENTRY( 0x16, 's', 'S' )\
- ENTRY( 0x17, 't', 'T' )\
- ENTRY( 0x18, 'u', 'U' )\
- ENTRY( 0x19, 'v', 'V' )\
- ENTRY( 0x1a, 'w', 'W' )\
- ENTRY( 0x1b, 'x', 'X' )\
- ENTRY( 0x1c, 'y', 'Y' )\
- ENTRY( 0x1d, 'z', 'Z' )\
- ENTRY( 0x1e, '1', '!' )\
- ENTRY( 0x1f, '2', '@' )\
- \
- ENTRY( 0x20, '3', '#' )\
- ENTRY( 0x21, '4', '$' )\
- ENTRY( 0x22, '5', '%' )\
- ENTRY( 0x23, '6', '^' )\
- ENTRY( 0x24, '7', '&' )\
- ENTRY( 0x25, '8', '*' )\
- ENTRY( 0x26, '9', '(' )\
- ENTRY( 0x27, '0', ')' )\
- ENTRY( 0x28, '\r', '\r' )\
- ENTRY( 0x29, '\e', '\e' )\
- ENTRY( 0x2a, '\b', '\b' )\
- ENTRY( 0x2b, '\t', '\t' )\
- ENTRY( 0x2c, ' ', ' ' )\
- ENTRY( 0x2d, '-', '_' )\
- ENTRY( 0x2e, '=', '+' )\
- ENTRY( 0x2f, '[', '{' )\
- \
- ENTRY( 0x30, ']', '}' )\
- ENTRY( 0x31, '\\', '|' )\
- ENTRY( 0x32, '#', '~' ) /* TODO non-US keyboard */ \
- ENTRY( 0x33, ';', ':' )\
- ENTRY( 0x34, '\'', '\"' )\
- ENTRY( 0x35, 0, 0 )\
- ENTRY( 0x36, ',', '<' )\
- ENTRY( 0x37, '.', '>' )\
- ENTRY( 0x38, '/', '?' )\
- ENTRY( 0x39, 0, 0 ) /* TODO CapsLock, non-locking key implementation*/ \
- \
- ENTRY( 0x54, '/', '/' )\
- ENTRY( 0x55, '*', '*' )\
- ENTRY( 0x56, '-', '-' )\
- ENTRY( 0x57, '+', '+' )\
- ENTRY( 0x58, '\r', '\r' )\
- ENTRY( 0x59, '1', 0 ) /* numpad1 & end */ \
- ENTRY( 0x5a, '2', 0 )\
- ENTRY( 0x5b, '3', 0 )\
- ENTRY( 0x5c, '4', 0 )\
- ENTRY( 0x5d, '5', '5' )\
- ENTRY( 0x5e, '6', 0 )\
- ENTRY( 0x5f, '7', 0 )\
- ENTRY( 0x60, '8', 0 )\
- ENTRY( 0x61, '9', 0 )\
- ENTRY( 0x62, '0', 0 )\
- ENTRY( 0x63, '0', 0 )\
- \
- ENTRY( 0x67, '=', '=' )\
-
-// TODO HID complete keycode table
-
-//enum
-//{
-// KEYBOARD_KEYCODE_A = 0x04,
-// KEYBOARD_KEYCODE_Z = 0x1d,
-//
-// KEYBOARD_KEYCODE_1 = 0x1e,
-// KEYBOARD_KEYCODE_0 = 0x27,
-//
-// KEYBOARD_KEYCODE_ENTER = 0x28,
-// KEYBOARD_KEYCODE_ESCAPE = 0x29,
-// KEYBOARD_KEYCODE_BACKSPACE = 0x2a,
-// KEYBOARD_KEYCODE_TAB = 0x2b,
-// KEYBOARD_KEYCODE_SPACEBAR = 0x2c,
-//
-//};
-
-/**
- * \brief Local Country code for HID
- */
-enum USB_HID_LOCAL_CODE
-{
- HID_Local_NotSupported = 0,
- HID_Local_Arabic,
- HID_Local_Belgian,
- HID_Local_Canadian_Bilingual,
- HID_Local_Canadian_French,
- HID_Local_Czech_Republic,
- HID_Local_Danish,
- HID_Local_Finnish,
- HID_Local_French,
- HID_Local_German,
- HID_Local_Greek,
- HID_Local_Hebrew,
- HID_Local_Hungary,
- HID_Local_International,
- HID_Local_Italian,
- HID_Local_Japan_Katakana,
- HID_Local_Korean,
- HID_Local_Latin_American,
- HID_Local_Netherlands_Dutch,
- HID_Local_Norwegian,
- HID_Local_Persian_Farsi,
- HID_Local_Poland,
- HID_Local_Portuguese,
- HID_Local_Russia,
- HID_Local_Slovakia,
- HID_Local_Spanish,
- HID_Local_Swedish,
- HID_Local_Swiss_French,
- HID_Local_Swiss_German,
- HID_Local_Switzerland,
- HID_Local_Taiwan,
- HID_Local_Turkish_Q,
- HID_Local_UK,
- HID_Local_US,
- HID_Local_Yugoslavia,
- HID_Local_Turkish_F
-};
-
-//--------------------------------------------------------------------+
-// REPORT DESCRIPTOR
-//--------------------------------------------------------------------+
-//------------- ITEM & TAG -------------//
-#define HID_REPORT_DATA_0(data)
-#define HID_REPORT_DATA_1(data) , data
-#define HID_REPORT_DATA_2(data) , U16_TO_U8S_LE(data)
-#define HID_REPORT_DATA_3(data) , U32_TO_U8S_LE(data)
-
-#define HID_REPORT_ITEM(data, tag, type, size) \
- (((tag) << 4) | ((type) << 2) | (size)) HID_REPORT_DATA_##size(data)
-
-#define RI_TYPE_MAIN 0
-#define RI_TYPE_GLOBAL 1
-#define RI_TYPE_LOCAL 2
-
-//------------- MAIN ITEMS 6.2.2.4 -------------//
-#define HID_INPUT(x) HID_REPORT_ITEM(x, 8, RI_TYPE_MAIN, 1)
-#define HID_OUTPUT(x) HID_REPORT_ITEM(x, 9, RI_TYPE_MAIN, 1)
-#define HID_COLLECTION(x) HID_REPORT_ITEM(x, 10, RI_TYPE_MAIN, 1)
-#define HID_FEATURE(x) HID_REPORT_ITEM(x, 11, RI_TYPE_MAIN, 1)
-#define HID_COLLECTION_END HID_REPORT_ITEM(x, 12, RI_TYPE_MAIN, 0)
-
-//------------- INPUT, OUTPUT, FEATURE 6.2.2.5 -------------//
-#define HID_DATA (0<<0)
-#define HID_CONSTANT (1<<0)
-
-#define HID_ARRAY (0<<1)
-#define HID_VARIABLE (1<<1)
-
-#define HID_ABSOLUTE (0<<2)
-#define HID_RELATIVE (1<<2)
-
-#define HID_WRAP_NO (0<<3)
-#define HID_WRAP (1<<3)
-
-#define HID_LINEAR (0<<4)
-#define HID_NONLINEAR (1<<4)
-
-#define HID_PREFERRED_STATE (0<<5)
-#define HID_PREFERRED_NO (1<<5)
-
-#define HID_NO_NULL_POSITION (0<<6)
-#define HID_NULL_STATE (1<<6)
-
-#define HID_NON_VOLATILE (0<<7)
-#define HID_VOLATILE (1<<7)
-
-#define HID_BITFIELD (0<<8)
-#define HID_BUFFERED_BYTES (1<<8)
-
-//------------- COLLECTION ITEM 6.2.2.6 -------------//
-enum {
- HID_COLLECTION_PHYSICAL = 0,
- HID_COLLECTION_APPLICATION,
- HID_COLLECTION_LOGICAL,
- HID_COLLECTION_REPORT,
- HID_COLLECTION_NAMED_ARRAY,
- HID_COLLECTION_USAGE_SWITCH,
- HID_COLLECTION_USAGE_MODIFIER
-};
-
-//------------- GLOBAL ITEMS 6.2.2.7 -------------//
-#define HID_USAGE_PAGE(x) HID_REPORT_ITEM(x, 0, RI_TYPE_GLOBAL, 1)
-#define HID_USAGE_PAGE_N(x, n) HID_REPORT_ITEM(x, 0, RI_TYPE_GLOBAL, n)
-
-#define HID_LOGICAL_MIN(x) HID_REPORT_ITEM(x, 1, RI_TYPE_GLOBAL, 1)
-#define HID_LOGICAL_MIN_N(x, n) HID_REPORT_ITEM(x, 1, RI_TYPE_GLOBAL, n)
-
-#define HID_LOGICAL_MAX(x) HID_REPORT_ITEM(x, 2, RI_TYPE_GLOBAL, 1)
-#define HID_LOGICAL_MAX_N(x, n) HID_REPORT_ITEM(x, 2, RI_TYPE_GLOBAL, n)
-
-#define HID_PHYSICAL_MIN(x) HID_REPORT_ITEM(x, 3, RI_TYPE_GLOBAL, 1)
-#define HID_PHYSICAL_MIN_N(x, n) HID_REPORT_ITEM(x, 3, RI_TYPE_GLOBAL, n)
-
-#define HID_PHYSICAL_MAX(x) HID_REPORT_ITEM(x, 4, RI_TYPE_GLOBAL, 1)
-#define HID_PHYSICAL_MAX_N(x, n) HID_REPORT_ITEM(x, 4, RI_TYPE_GLOBAL, n)
-
-#define HID_UNIT_EXPONENT(x) HID_REPORT_ITEM(x, 5, RI_TYPE_GLOBAL, 1)
-#define HID_UNIT_EXPONENT_N(x, n) HID_REPORT_ITEM(x, 5, RI_TYPE_GLOBAL, n)
-
-#define HID_UNIT(x) HID_REPORT_ITEM(x, 6, RI_TYPE_GLOBAL, 1)
-#define HID_UNIT_N(x, n) HID_REPORT_ITEM(x, 6, RI_TYPE_GLOBAL, n)
-
-#define HID_REPORT_SIZE(x) HID_REPORT_ITEM(x, 7, RI_TYPE_GLOBAL, 1)
-#define HID_REPORT_SIZE_N(x, n) HID_REPORT_ITEM(x, 7, RI_TYPE_GLOBAL, n)
-
-#define HID_REPORT_ID(x) HID_REPORT_ITEM(x, 8, RI_TYPE_GLOBAL, 1)
-#define HID_REPORT_ID_N(x) HID_REPORT_ITEM(x, 8, RI_TYPE_GLOBAL, n)
-
-#define HID_REPORT_COUNT(x) HID_REPORT_ITEM(x, 9, RI_TYPE_GLOBAL, 1)
-#define HID_REPORT_COUNT_N(x, n) HID_REPORT_ITEM(x, 9, RI_TYPE_GLOBAL, n)
-
-#define HID_PUSH HID_REPORT_ITEM(x, 10, RI_TYPE_GLOBAL, 0)
-#define HID_POP HID_REPORT_ITEM(x, 11, RI_TYPE_GLOBAL, 0)
-
-//------------- LOCAL ITEMS 6.2.2.8 -------------//
-#define HID_USAGE(x) HID_REPORT_ITEM(x, 0, RI_TYPE_LOCAL, 1)
-#define HID_USAGE_N(x, n) HID_REPORT_ITEM(x, 0, RI_TYPE_LOCAL, n)
-
-#define HID_USAGE_MIN(x) HID_REPORT_ITEM(x, 1, RI_TYPE_LOCAL, 1)
-#define HID_USAGE_MIN_N(x, n) HID_REPORT_ITEM(x, 1, RI_TYPE_LOCAL, n)
-
-#define HID_USAGE_MAX(x) HID_REPORT_ITEM(x, 2, RI_TYPE_LOCAL, 1)
-#define HID_USAGE_MAX_N(x, n) HID_REPORT_ITEM(x, 2, RI_TYPE_LOCAL, n)
-
-//--------------------------------------------------------------------+
-// Usage Table
-//--------------------------------------------------------------------+
-
-/// HID Usage Table - Table 1: Usage Page Summary
-enum {
- HID_USAGE_PAGE_DESKTOP = 0x01,
- HID_USAGE_PAGE_SIMULATE = 0x02,
- HID_USAGE_PAGE_VIRTUAL_REALITY = 0x03,
- HID_USAGE_PAGE_SPORT = 0x04,
- HID_USAGE_PAGE_GAME = 0x05,
- HID_USAGE_PAGE_GENERIC_DEVICE = 0x06,
- HID_USAGE_PAGE_KEYBOARD = 0x07,
- HID_USAGE_PAGE_LED = 0x08,
- HID_USAGE_PAGE_BUTTON = 0x09,
- HID_USAGE_PAGE_ORDINAL = 0x0a,
- HID_USAGE_PAGE_TELEPHONY = 0x0b,
- HID_USAGE_PAGE_CONSUMER = 0x0c,
- HID_USAGE_PAGE_DIGITIZER = 0x0d,
- HID_USAGE_PAGE_PID = 0x0f,
- HID_USAGE_PAGE_UNICODE = 0x10,
- HID_USAGE_PAGE_ALPHA_DISPLAY = 0x14,
- HID_USAGE_PAGE_MEDICAL = 0x40,
- HID_USAGE_PAGE_MONITOR = 0x80, //0x80 - 0x83
- HID_USAGE_PAGE_POWER = 0x84, // 0x084 - 0x87
- HID_USAGE_PAGE_BARCODE_SCANNER = 0x8c,
- HID_USAGE_PAGE_SCALE = 0x8d,
- HID_USAGE_PAGE_MSR = 0x8e,
- HID_USAGE_PAGE_CAMERA = 0x90,
- HID_USAGE_PAGE_ARCADE = 0x91,
- HID_USAGE_PAGE_VENDOR = 0xFFFF // 0xFF00 - 0xFFFF
-};
-
-/// HID Usage Table - Table 6: Generic Desktop Page
-enum {
- HID_USAGE_DESKTOP_POINTER = 0x01,
- HID_USAGE_DESKTOP_MOUSE = 0x02,
- HID_USAGE_DESKTOP_JOYSTICK = 0x04,
- HID_USAGE_DESKTOP_GAMEPAD = 0x05,
- HID_USAGE_DESKTOP_KEYBOARD = 0x06,
- HID_USAGE_DESKTOP_KEYPAD = 0x07,
- HID_USAGE_DESKTOP_MULTI_AXIS_CONTROLLER = 0x08,
- HID_USAGE_DESKTOP_TABLET_PC_SYSTEM = 0x09,
- HID_USAGE_DESKTOP_X = 0x30,
- HID_USAGE_DESKTOP_Y = 0x31,
- HID_USAGE_DESKTOP_Z = 0x32,
- HID_USAGE_DESKTOP_RX = 0x33,
- HID_USAGE_DESKTOP_RY = 0x34,
- HID_USAGE_DESKTOP_RZ = 0x35,
- HID_USAGE_DESKTOP_SLIDER = 0x36,
- HID_USAGE_DESKTOP_DIAL = 0x37,
- HID_USAGE_DESKTOP_WHEEL = 0x38,
- HID_USAGE_DESKTOP_HAT_SWITCH = 0x39,
- HID_USAGE_DESKTOP_COUNTED_BUFFER = 0x3a,
- HID_USAGE_DESKTOP_BYTE_COUNT = 0x3b,
- HID_USAGE_DESKTOP_MOTION_WAKEUP = 0x3c,
- HID_USAGE_DESKTOP_START = 0x3d,
- HID_USAGE_DESKTOP_SELECT = 0x3e,
- HID_USAGE_DESKTOP_VX = 0x40,
- HID_USAGE_DESKTOP_VY = 0x41,
- HID_USAGE_DESKTOP_VZ = 0x42,
- HID_USAGE_DESKTOP_VBRX = 0x43,
- HID_USAGE_DESKTOP_VBRY = 0x44,
- HID_USAGE_DESKTOP_VBRZ = 0x45,
- HID_USAGE_DESKTOP_VNO = 0x46,
- HID_USAGE_DESKTOP_FEATURE_NOTIFICATION = 0x47,
- HID_USAGE_DESKTOP_RESOLUTION_MULTIPLIER = 0x48,
- HID_USAGE_DESKTOP_SYSTEM_CONTROL = 0x80,
- HID_USAGE_DESKTOP_SYSTEM_POWER_DOWN = 0x81,
- HID_USAGE_DESKTOP_SYSTEM_SLEEP = 0x82,
- HID_USAGE_DESKTOP_SYSTEM_WAKE_UP = 0x83,
- HID_USAGE_DESKTOP_SYSTEM_CONTEXT_MENU = 0x84,
- HID_USAGE_DESKTOP_SYSTEM_MAIN_MENU = 0x85,
- HID_USAGE_DESKTOP_SYSTEM_APP_MENU = 0x86,
- HID_USAGE_DESKTOP_SYSTEM_MENU_HELP = 0x87,
- HID_USAGE_DESKTOP_SYSTEM_MENU_EXIT = 0x88,
- HID_USAGE_DESKTOP_SYSTEM_MENU_SELECT = 0x89,
- HID_USAGE_DESKTOP_SYSTEM_MENU_RIGHT = 0x8A,
- HID_USAGE_DESKTOP_SYSTEM_MENU_LEFT = 0x8B,
- HID_USAGE_DESKTOP_SYSTEM_MENU_UP = 0x8C,
- HID_USAGE_DESKTOP_SYSTEM_MENU_DOWN = 0x8D,
- HID_USAGE_DESKTOP_SYSTEM_COLD_RESTART = 0x8E,
- HID_USAGE_DESKTOP_SYSTEM_WARM_RESTART = 0x8F,
- HID_USAGE_DESKTOP_DPAD_UP = 0x90,
- HID_USAGE_DESKTOP_DPAD_DOWN = 0x91,
- HID_USAGE_DESKTOP_DPAD_RIGHT = 0x92,
- HID_USAGE_DESKTOP_DPAD_LEFT = 0x93,
- HID_USAGE_DESKTOP_SYSTEM_DOCK = 0xA0,
- HID_USAGE_DESKTOP_SYSTEM_UNDOCK = 0xA1,
- HID_USAGE_DESKTOP_SYSTEM_SETUP = 0xA2,
- HID_USAGE_DESKTOP_SYSTEM_BREAK = 0xA3,
- HID_USAGE_DESKTOP_SYSTEM_DEBUGGER_BREAK = 0xA4,
- HID_USAGE_DESKTOP_APPLICATION_BREAK = 0xA5,
- HID_USAGE_DESKTOP_APPLICATION_DEBUGGER_BREAK = 0xA6,
- HID_USAGE_DESKTOP_SYSTEM_SPEAKER_MUTE = 0xA7,
- HID_USAGE_DESKTOP_SYSTEM_HIBERNATE = 0xA8,
- HID_USAGE_DESKTOP_SYSTEM_DISPLAY_INVERT = 0xB0,
- HID_USAGE_DESKTOP_SYSTEM_DISPLAY_INTERNAL = 0xB1,
- HID_USAGE_DESKTOP_SYSTEM_DISPLAY_EXTERNAL = 0xB2,
- HID_USAGE_DESKTOP_SYSTEM_DISPLAY_BOTH = 0xB3,
- HID_USAGE_DESKTOP_SYSTEM_DISPLAY_DUAL = 0xB4,
- HID_USAGE_DESKTOP_SYSTEM_DISPLAY_TOGGLE_INT_EXT = 0xB5,
- HID_USAGE_DESKTOP_SYSTEM_DISPLAY_SWAP_PRIMARY_SECONDARY = 0xB6,
- HID_USAGE_DESKTOP_SYSTEM_DISPLAY_LCD_AUTOSCALE = 0xB7
-};
-
-#ifdef __cplusplus
- }
-#endif
-
-#endif /* _TUSB_HID_H__ */
-
-/// @}
-/// @}
+/**************************************************************************/
+/*!
+ @file hid.h
+ @author hathach (tinyusb.org)
+
+ @section LICENSE
+
+ Software License Agreement (BSD License)
+
+ Copyright (c) 2013, hathach (tinyusb.org)
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ 3. Neither the name of the copyright holders nor the
+ names of its contributors may be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
+ EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
+ DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION HOWEVER CAUSED AND
+ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ INCLUDING NEGLIGENCE OR OTHERWISE ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ This file is part of the tinyusb stack.
+*/
+/**************************************************************************/
+
+/**
+ * \addtogroup ClassDriver Class Driver
+ * @{
+ * \defgroup ClassDriver_HID Human Interface Device (HID)
+ * @{
+ */
+
+#ifndef _TUSB_HID_H_
+#define _TUSB_HID_H_
+
+#include "common/common.h"
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+enum {
+ HID_SUBCLASS_NONE = 0,
+ HID_SUBCLASS_BOOT = 1
+};
+
+enum {
+ HID_PROTOCOL_NONE = 0,
+ HID_PROTOCOL_KEYBOARD = 1,
+ HID_PROTOCOL_MOUSE = 2
+};
+
+enum {
+ HID_DESC_TYPE_HID = 0x21,
+ HID_DESC_TYPE_REPORT = 0x22,
+ HID_DESC_TYPE_PHYSICAL = 0x23
+};
+
+enum {
+ HID_REQUEST_REPORT_INPUT = 1,
+ HID_REQUEST_REPORT_OUTPUT,
+ HID_REQUEST_REPORT_FEATURE
+};
+
+enum {
+ HID_REQUEST_CONTROL_GET_REPORT = 0x01,
+ HID_REQUEST_CONTROL_GET_IDLE = 0x02,
+ HID_REQUEST_CONTROL_GET_PROTOCOL = 0x03,
+ HID_REQUEST_CONTROL_SET_REPORT = 0x09,
+ HID_REQUEST_CONTROL_SET_IDLE = 0x0a,
+ HID_REQUEST_CONTROL_SET_PROTOCOL = 0x0b
+};
+
+typedef ATTR_PACKED_STRUCT(struct) {
+ uint8_t bLength; /**< Numeric expression that is the total size of the HID descriptor */
+ uint8_t bDescriptorType; /**< Constant name specifying type of HID descriptor. */
+
+ uint16_t bcdHID; /**< Numeric expression identifying the HID Class Specification release */
+ uint8_t bCountryCode; /**< Numeric expression identifying country code of the localized hardware. */
+ uint8_t bNumDescriptors; /**< Numeric expression specifying the number of class descriptors */
+
+ uint8_t bReportType; /**< Type of HID class report. */
+ uint16_t wReportLength; /**< the total size of the Report descriptor. */
+} tusb_hid_descriptor_hid_t;
+
+/**
+ * \brief Standard HID Boot Protocol Mouse Report.
+ *
+ * Type define for a standard Boot Protocol Mouse report
+ */
+typedef ATTR_PACKED_STRUCT(struct)
+{
+ uint8_t buttons; /**< buttons mask for currently pressed buttons in the mouse. */
+ int8_t x; /**< Current delta x movement of the mouse. */
+ int8_t y; /**< Current delta y movement on the mouse. */
+ int8_t wheel; /**< Current delta wheel movement on the mouse. */
+} tusb_mouse_report_t;
+
+/**
+ * \brief Standard HID Boot Protocol Keyboard Report.
+ *
+ * Type define for a standard Boot Protocol Keyboard report
+ */
+typedef ATTR_PACKED_STRUCT(struct)
+{
+ uint8_t modifier; /**< Keyboard modifier byte, indicating pressed modifier keys (a combination of HID_KEYBOARD_MODIFER_* masks). */
+ uint8_t reserved; /**< Reserved for OEM use, always set to 0. */
+ uint8_t keycode[6]; /**< Key codes of the currently pressed keys. */
+} tusb_keyboard_report_t;
+
+/**
+ * \brief buttons codes for HID mouse
+ */
+enum {
+ MOUSE_BUTTON_LEFT = BIT_(0),
+ MOUSE_BUTTON_RIGHT = BIT_(1),
+ MOUSE_BUTTON_MIDDLE = BIT_(2)
+};
+
+/**
+ * \brief KB modifier codes for HID KB
+ */
+enum {
+ KEYBOARD_MODIFIER_LEFTCTRL = BIT_(0),
+ KEYBOARD_MODIFIER_LEFTSHIFT = BIT_(1),
+ KEYBOARD_MODIFIER_LEFTALT = BIT_(2),
+ KEYBOARD_MODIFIER_LEFTGUI = BIT_(3),
+ KEYBOARD_MODIFIER_RIGHTCTRL = BIT_(4),
+ KEYBOARD_MODIFIER_RIGHTSHIFT = BIT_(5),
+ KEYBOARD_MODIFIER_RIGHTALT = BIT_(6),
+ KEYBOARD_MODIFIER_RIGHTGUI = BIT_(7)
+};
+
+#define HID_KEYCODE_TABLE(ENTRY) \
+ ENTRY( 0x04, 'a', 'A' )\
+ ENTRY( 0x05, 'b', 'B' )\
+ ENTRY( 0x06, 'c', 'C' )\
+ ENTRY( 0x07, 'd', 'D' )\
+ ENTRY( 0x08, 'e', 'E' )\
+ ENTRY( 0x09, 'f', 'F' )\
+ ENTRY( 0x0a, 'g', 'G' )\
+ ENTRY( 0x0b, 'h', 'H' )\
+ ENTRY( 0x0c, 'i', 'I' )\
+ ENTRY( 0x0d, 'j', 'J' )\
+ ENTRY( 0x0e, 'k', 'K' )\
+ ENTRY( 0x0f, 'l', 'L' )\
+ \
+ ENTRY( 0x10, 'm', 'M' )\
+ ENTRY( 0x11, 'n', 'N' )\
+ ENTRY( 0x12, 'o', 'O' )\
+ ENTRY( 0x13, 'p', 'P' )\
+ ENTRY( 0x14, 'q', 'Q' )\
+ ENTRY( 0x15, 'r', 'R' )\
+ ENTRY( 0x16, 's', 'S' )\
+ ENTRY( 0x17, 't', 'T' )\
+ ENTRY( 0x18, 'u', 'U' )\
+ ENTRY( 0x19, 'v', 'V' )\
+ ENTRY( 0x1a, 'w', 'W' )\
+ ENTRY( 0x1b, 'x', 'X' )\
+ ENTRY( 0x1c, 'y', 'Y' )\
+ ENTRY( 0x1d, 'z', 'Z' )\
+ ENTRY( 0x1e, '1', '!' )\
+ ENTRY( 0x1f, '2', '@' )\
+ \
+ ENTRY( 0x20, '3', '#' )\
+ ENTRY( 0x21, '4', '$' )\
+ ENTRY( 0x22, '5', '%' )\
+ ENTRY( 0x23, '6', '^' )\
+ ENTRY( 0x24, '7', '&' )\
+ ENTRY( 0x25, '8', '*' )\
+ ENTRY( 0x26, '9', '(' )\
+ ENTRY( 0x27, '0', ')' )\
+ ENTRY( 0x28, '\r', '\r' )\
+ ENTRY( 0x29, '\e', '\e' )\
+ ENTRY( 0x2a, '\b', '\b' )\
+ ENTRY( 0x2b, '\t', '\t' )\
+ ENTRY( 0x2c, ' ', ' ' )\
+ ENTRY( 0x2d, '-', '_' )\
+ ENTRY( 0x2e, '=', '+' )\
+ ENTRY( 0x2f, '[', '{' )\
+ \
+ ENTRY( 0x30, ']', '}' )\
+ ENTRY( 0x31, '\\', '|' )\
+ ENTRY( 0x32, '#', '~' ) /* TODO non-US keyboard */ \
+ ENTRY( 0x33, ';', ':' )\
+ ENTRY( 0x34, '\'', '\"' )\
+ ENTRY( 0x35, 0, 0 )\
+ ENTRY( 0x36, ',', '<' )\
+ ENTRY( 0x37, '.', '>' )\
+ ENTRY( 0x38, '/', '?' )\
+ ENTRY( 0x39, 0, 0 ) /* TODO CapsLock, non-locking key implementation*/ \
+ \
+ ENTRY( 0x54, '/', '/' )\
+ ENTRY( 0x55, '*', '*' )\
+ ENTRY( 0x56, '-', '-' )\
+ ENTRY( 0x57, '+', '+' )\
+ ENTRY( 0x58, '\r', '\r' )\
+ ENTRY( 0x59, '1', 0 ) /* numpad1 & end */ \
+ ENTRY( 0x5a, '2', 0 )\
+ ENTRY( 0x5b, '3', 0 )\
+ ENTRY( 0x5c, '4', 0 )\
+ ENTRY( 0x5d, '5', '5' )\
+ ENTRY( 0x5e, '6', 0 )\
+ ENTRY( 0x5f, '7', 0 )\
+ ENTRY( 0x60, '8', 0 )\
+ ENTRY( 0x61, '9', 0 )\
+ ENTRY( 0x62, '0', 0 )\
+ ENTRY( 0x63, '0', 0 )\
+ \
+ ENTRY( 0x67, '=', '=' )\
+
+// TODO HID complete keycode table
+
+//enum
+//{
+// KEYBOARD_KEYCODE_A = 0x04,
+// KEYBOARD_KEYCODE_Z = 0x1d,
+//
+// KEYBOARD_KEYCODE_1 = 0x1e,
+// KEYBOARD_KEYCODE_0 = 0x27,
+//
+// KEYBOARD_KEYCODE_ENTER = 0x28,
+// KEYBOARD_KEYCODE_ESCAPE = 0x29,
+// KEYBOARD_KEYCODE_BACKSPACE = 0x2a,
+// KEYBOARD_KEYCODE_TAB = 0x2b,
+// KEYBOARD_KEYCODE_SPACEBAR = 0x2c,
+//
+//};
+
+/**
+ * \brief Local Country code for HID
+ */
+enum USB_HID_LOCAL_CODE
+{
+ HID_Local_NotSupported = 0,
+ HID_Local_Arabic,
+ HID_Local_Belgian,
+ HID_Local_Canadian_Bilingual,
+ HID_Local_Canadian_French,
+ HID_Local_Czech_Republic,
+ HID_Local_Danish,
+ HID_Local_Finnish,
+ HID_Local_French,
+ HID_Local_German,
+ HID_Local_Greek,
+ HID_Local_Hebrew,
+ HID_Local_Hungary,
+ HID_Local_International,
+ HID_Local_Italian,
+ HID_Local_Japan_Katakana,
+ HID_Local_Korean,
+ HID_Local_Latin_American,
+ HID_Local_Netherlands_Dutch,
+ HID_Local_Norwegian,
+ HID_Local_Persian_Farsi,
+ HID_Local_Poland,
+ HID_Local_Portuguese,
+ HID_Local_Russia,
+ HID_Local_Slovakia,
+ HID_Local_Spanish,
+ HID_Local_Swedish,
+ HID_Local_Swiss_French,
+ HID_Local_Swiss_German,
+ HID_Local_Switzerland,
+ HID_Local_Taiwan,
+ HID_Local_Turkish_Q,
+ HID_Local_UK,
+ HID_Local_US,
+ HID_Local_Yugoslavia,
+ HID_Local_Turkish_F
+};
+
+//--------------------------------------------------------------------+
+// REPORT DESCRIPTOR
+//--------------------------------------------------------------------+
+//------------- ITEM & TAG -------------//
+#define HID_REPORT_DATA_0(data)
+#define HID_REPORT_DATA_1(data) , data
+#define HID_REPORT_DATA_2(data) , U16_TO_U8S_LE(data)
+#define HID_REPORT_DATA_3(data) , U32_TO_U8S_LE(data)
+
+#define HID_REPORT_ITEM(data, tag, type, size) \
+ (((tag) << 4) | ((type) << 2) | (size)) HID_REPORT_DATA_##size(data)
+
+#define RI_TYPE_MAIN 0
+#define RI_TYPE_GLOBAL 1
+#define RI_TYPE_LOCAL 2
+
+//------------- MAIN ITEMS 6.2.2.4 -------------//
+#define HID_INPUT(x) HID_REPORT_ITEM(x, 8, RI_TYPE_MAIN, 1)
+#define HID_OUTPUT(x) HID_REPORT_ITEM(x, 9, RI_TYPE_MAIN, 1)
+#define HID_COLLECTION(x) HID_REPORT_ITEM(x, 10, RI_TYPE_MAIN, 1)
+#define HID_FEATURE(x) HID_REPORT_ITEM(x, 11, RI_TYPE_MAIN, 1)
+#define HID_COLLECTION_END HID_REPORT_ITEM(x, 12, RI_TYPE_MAIN, 0)
+
+//------------- INPUT, OUTPUT, FEATURE 6.2.2.5 -------------//
+#define HID_DATA (0<<0)
+#define HID_CONSTANT (1<<0)
+
+#define HID_ARRAY (0<<1)
+#define HID_VARIABLE (1<<1)
+
+#define HID_ABSOLUTE (0<<2)
+#define HID_RELATIVE (1<<2)
+
+#define HID_WRAP_NO (0<<3)
+#define HID_WRAP (1<<3)
+
+#define HID_LINEAR (0<<4)
+#define HID_NONLINEAR (1<<4)
+
+#define HID_PREFERRED_STATE (0<<5)
+#define HID_PREFERRED_NO (1<<5)
+
+#define HID_NO_NULL_POSITION (0<<6)
+#define HID_NULL_STATE (1<<6)
+
+#define HID_NON_VOLATILE (0<<7)
+#define HID_VOLATILE (1<<7)
+
+#define HID_BITFIELD (0<<8)
+#define HID_BUFFERED_BYTES (1<<8)
+
+//------------- COLLECTION ITEM 6.2.2.6 -------------//
+enum {
+ HID_COLLECTION_PHYSICAL = 0,
+ HID_COLLECTION_APPLICATION,
+ HID_COLLECTION_LOGICAL,
+ HID_COLLECTION_REPORT,
+ HID_COLLECTION_NAMED_ARRAY,
+ HID_COLLECTION_USAGE_SWITCH,
+ HID_COLLECTION_USAGE_MODIFIER
+};
+
+//------------- GLOBAL ITEMS 6.2.2.7 -------------//
+#define HID_USAGE_PAGE(x) HID_REPORT_ITEM(x, 0, RI_TYPE_GLOBAL, 1)
+#define HID_USAGE_PAGE_N(x, n) HID_REPORT_ITEM(x, 0, RI_TYPE_GLOBAL, n)
+
+#define HID_LOGICAL_MIN(x) HID_REPORT_ITEM(x, 1, RI_TYPE_GLOBAL, 1)
+#define HID_LOGICAL_MIN_N(x, n) HID_REPORT_ITEM(x, 1, RI_TYPE_GLOBAL, n)
+
+#define HID_LOGICAL_MAX(x) HID_REPORT_ITEM(x, 2, RI_TYPE_GLOBAL, 1)
+#define HID_LOGICAL_MAX_N(x, n) HID_REPORT_ITEM(x, 2, RI_TYPE_GLOBAL, n)
+
+#define HID_PHYSICAL_MIN(x) HID_REPORT_ITEM(x, 3, RI_TYPE_GLOBAL, 1)
+#define HID_PHYSICAL_MIN_N(x, n) HID_REPORT_ITEM(x, 3, RI_TYPE_GLOBAL, n)
+
+#define HID_PHYSICAL_MAX(x) HID_REPORT_ITEM(x, 4, RI_TYPE_GLOBAL, 1)
+#define HID_PHYSICAL_MAX_N(x, n) HID_REPORT_ITEM(x, 4, RI_TYPE_GLOBAL, n)
+
+#define HID_UNIT_EXPONENT(x) HID_REPORT_ITEM(x, 5, RI_TYPE_GLOBAL, 1)
+#define HID_UNIT_EXPONENT_N(x, n) HID_REPORT_ITEM(x, 5, RI_TYPE_GLOBAL, n)
+
+#define HID_UNIT(x) HID_REPORT_ITEM(x, 6, RI_TYPE_GLOBAL, 1)
+#define HID_UNIT_N(x, n) HID_REPORT_ITEM(x, 6, RI_TYPE_GLOBAL, n)
+
+#define HID_REPORT_SIZE(x) HID_REPORT_ITEM(x, 7, RI_TYPE_GLOBAL, 1)
+#define HID_REPORT_SIZE_N(x, n) HID_REPORT_ITEM(x, 7, RI_TYPE_GLOBAL, n)
+
+#define HID_REPORT_ID(x) HID_REPORT_ITEM(x, 8, RI_TYPE_GLOBAL, 1)
+#define HID_REPORT_ID_N(x) HID_REPORT_ITEM(x, 8, RI_TYPE_GLOBAL, n)
+
+#define HID_REPORT_COUNT(x) HID_REPORT_ITEM(x, 9, RI_TYPE_GLOBAL, 1)
+#define HID_REPORT_COUNT_N(x, n) HID_REPORT_ITEM(x, 9, RI_TYPE_GLOBAL, n)
+
+#define HID_PUSH HID_REPORT_ITEM(x, 10, RI_TYPE_GLOBAL, 0)
+#define HID_POP HID_REPORT_ITEM(x, 11, RI_TYPE_GLOBAL, 0)
+
+//------------- LOCAL ITEMS 6.2.2.8 -------------//
+#define HID_USAGE(x) HID_REPORT_ITEM(x, 0, RI_TYPE_LOCAL, 1)
+#define HID_USAGE_N(x, n) HID_REPORT_ITEM(x, 0, RI_TYPE_LOCAL, n)
+
+#define HID_USAGE_MIN(x) HID_REPORT_ITEM(x, 1, RI_TYPE_LOCAL, 1)
+#define HID_USAGE_MIN_N(x, n) HID_REPORT_ITEM(x, 1, RI_TYPE_LOCAL, n)
+
+#define HID_USAGE_MAX(x) HID_REPORT_ITEM(x, 2, RI_TYPE_LOCAL, 1)
+#define HID_USAGE_MAX_N(x, n) HID_REPORT_ITEM(x, 2, RI_TYPE_LOCAL, n)
+
+//--------------------------------------------------------------------+
+// Usage Table
+//--------------------------------------------------------------------+
+
+/// HID Usage Table - Table 1: Usage Page Summary
+enum {
+ HID_USAGE_PAGE_DESKTOP = 0x01,
+ HID_USAGE_PAGE_SIMULATE = 0x02,
+ HID_USAGE_PAGE_VIRTUAL_REALITY = 0x03,
+ HID_USAGE_PAGE_SPORT = 0x04,
+ HID_USAGE_PAGE_GAME = 0x05,
+ HID_USAGE_PAGE_GENERIC_DEVICE = 0x06,
+ HID_USAGE_PAGE_KEYBOARD = 0x07,
+ HID_USAGE_PAGE_LED = 0x08,
+ HID_USAGE_PAGE_BUTTON = 0x09,
+ HID_USAGE_PAGE_ORDINAL = 0x0a,
+ HID_USAGE_PAGE_TELEPHONY = 0x0b,
+ HID_USAGE_PAGE_CONSUMER = 0x0c,
+ HID_USAGE_PAGE_DIGITIZER = 0x0d,
+ HID_USAGE_PAGE_PID = 0x0f,
+ HID_USAGE_PAGE_UNICODE = 0x10,
+ HID_USAGE_PAGE_ALPHA_DISPLAY = 0x14,
+ HID_USAGE_PAGE_MEDICAL = 0x40,
+ HID_USAGE_PAGE_MONITOR = 0x80, //0x80 - 0x83
+ HID_USAGE_PAGE_POWER = 0x84, // 0x084 - 0x87
+ HID_USAGE_PAGE_BARCODE_SCANNER = 0x8c,
+ HID_USAGE_PAGE_SCALE = 0x8d,
+ HID_USAGE_PAGE_MSR = 0x8e,
+ HID_USAGE_PAGE_CAMERA = 0x90,
+ HID_USAGE_PAGE_ARCADE = 0x91,
+ HID_USAGE_PAGE_VENDOR = 0xFFFF // 0xFF00 - 0xFFFF
+};
+
+/// HID Usage Table - Table 6: Generic Desktop Page
+enum {
+ HID_USAGE_DESKTOP_POINTER = 0x01,
+ HID_USAGE_DESKTOP_MOUSE = 0x02,
+ HID_USAGE_DESKTOP_JOYSTICK = 0x04,
+ HID_USAGE_DESKTOP_GAMEPAD = 0x05,
+ HID_USAGE_DESKTOP_KEYBOARD = 0x06,
+ HID_USAGE_DESKTOP_KEYPAD = 0x07,
+ HID_USAGE_DESKTOP_MULTI_AXIS_CONTROLLER = 0x08,
+ HID_USAGE_DESKTOP_TABLET_PC_SYSTEM = 0x09,
+ HID_USAGE_DESKTOP_X = 0x30,
+ HID_USAGE_DESKTOP_Y = 0x31,
+ HID_USAGE_DESKTOP_Z = 0x32,
+ HID_USAGE_DESKTOP_RX = 0x33,
+ HID_USAGE_DESKTOP_RY = 0x34,
+ HID_USAGE_DESKTOP_RZ = 0x35,
+ HID_USAGE_DESKTOP_SLIDER = 0x36,
+ HID_USAGE_DESKTOP_DIAL = 0x37,
+ HID_USAGE_DESKTOP_WHEEL = 0x38,
+ HID_USAGE_DESKTOP_HAT_SWITCH = 0x39,
+ HID_USAGE_DESKTOP_COUNTED_BUFFER = 0x3a,
+ HID_USAGE_DESKTOP_BYTE_COUNT = 0x3b,
+ HID_USAGE_DESKTOP_MOTION_WAKEUP = 0x3c,
+ HID_USAGE_DESKTOP_START = 0x3d,
+ HID_USAGE_DESKTOP_SELECT = 0x3e,
+ HID_USAGE_DESKTOP_VX = 0x40,
+ HID_USAGE_DESKTOP_VY = 0x41,
+ HID_USAGE_DESKTOP_VZ = 0x42,
+ HID_USAGE_DESKTOP_VBRX = 0x43,
+ HID_USAGE_DESKTOP_VBRY = 0x44,
+ HID_USAGE_DESKTOP_VBRZ = 0x45,
+ HID_USAGE_DESKTOP_VNO = 0x46,
+ HID_USAGE_DESKTOP_FEATURE_NOTIFICATION = 0x47,
+ HID_USAGE_DESKTOP_RESOLUTION_MULTIPLIER = 0x48,
+ HID_USAGE_DESKTOP_SYSTEM_CONTROL = 0x80,
+ HID_USAGE_DESKTOP_SYSTEM_POWER_DOWN = 0x81,
+ HID_USAGE_DESKTOP_SYSTEM_SLEEP = 0x82,
+ HID_USAGE_DESKTOP_SYSTEM_WAKE_UP = 0x83,
+ HID_USAGE_DESKTOP_SYSTEM_CONTEXT_MENU = 0x84,
+ HID_USAGE_DESKTOP_SYSTEM_MAIN_MENU = 0x85,
+ HID_USAGE_DESKTOP_SYSTEM_APP_MENU = 0x86,
+ HID_USAGE_DESKTOP_SYSTEM_MENU_HELP = 0x87,
+ HID_USAGE_DESKTOP_SYSTEM_MENU_EXIT = 0x88,
+ HID_USAGE_DESKTOP_SYSTEM_MENU_SELECT = 0x89,
+ HID_USAGE_DESKTOP_SYSTEM_MENU_RIGHT = 0x8A,
+ HID_USAGE_DESKTOP_SYSTEM_MENU_LEFT = 0x8B,
+ HID_USAGE_DESKTOP_SYSTEM_MENU_UP = 0x8C,
+ HID_USAGE_DESKTOP_SYSTEM_MENU_DOWN = 0x8D,
+ HID_USAGE_DESKTOP_SYSTEM_COLD_RESTART = 0x8E,
+ HID_USAGE_DESKTOP_SYSTEM_WARM_RESTART = 0x8F,
+ HID_USAGE_DESKTOP_DPAD_UP = 0x90,
+ HID_USAGE_DESKTOP_DPAD_DOWN = 0x91,
+ HID_USAGE_DESKTOP_DPAD_RIGHT = 0x92,
+ HID_USAGE_DESKTOP_DPAD_LEFT = 0x93,
+ HID_USAGE_DESKTOP_SYSTEM_DOCK = 0xA0,
+ HID_USAGE_DESKTOP_SYSTEM_UNDOCK = 0xA1,
+ HID_USAGE_DESKTOP_SYSTEM_SETUP = 0xA2,
+ HID_USAGE_DESKTOP_SYSTEM_BREAK = 0xA3,
+ HID_USAGE_DESKTOP_SYSTEM_DEBUGGER_BREAK = 0xA4,
+ HID_USAGE_DESKTOP_APPLICATION_BREAK = 0xA5,
+ HID_USAGE_DESKTOP_APPLICATION_DEBUGGER_BREAK = 0xA6,
+ HID_USAGE_DESKTOP_SYSTEM_SPEAKER_MUTE = 0xA7,
+ HID_USAGE_DESKTOP_SYSTEM_HIBERNATE = 0xA8,
+ HID_USAGE_DESKTOP_SYSTEM_DISPLAY_INVERT = 0xB0,
+ HID_USAGE_DESKTOP_SYSTEM_DISPLAY_INTERNAL = 0xB1,
+ HID_USAGE_DESKTOP_SYSTEM_DISPLAY_EXTERNAL = 0xB2,
+ HID_USAGE_DESKTOP_SYSTEM_DISPLAY_BOTH = 0xB3,
+ HID_USAGE_DESKTOP_SYSTEM_DISPLAY_DUAL = 0xB4,
+ HID_USAGE_DESKTOP_SYSTEM_DISPLAY_TOGGLE_INT_EXT = 0xB5,
+ HID_USAGE_DESKTOP_SYSTEM_DISPLAY_SWAP_PRIMARY_SECONDARY = 0xB6,
+ HID_USAGE_DESKTOP_SYSTEM_DISPLAY_LCD_AUTOSCALE = 0xB7
+};
+
+#ifdef __cplusplus
+ }
+#endif
+
+#endif /* _TUSB_HID_H__ */
+
+/// @}
+/// @}
diff --git a/tinyusb/class/hid_host.c b/tinyusb/class/hid_host.c
index 0c7d4dc0a..e61590eab 100644
--- a/tinyusb/class/hid_host.c
+++ b/tinyusb/class/hid_host.c
@@ -1,304 +1,304 @@
-/**************************************************************************/
-/*!
- @file hid_host.c
- @author hathach (tinyusb.org)
-
- @section LICENSE
-
- Software License Agreement (BSD License)
-
- Copyright (c) 2013, hathach (tinyusb.org)
- All rights reserved.
-
- Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions are met:
- 1. Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
- 2. Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
- 3. Neither the name of the copyright holders nor the
- names of its contributors may be used to endorse or promote products
- derived from this software without specific prior written permission.
-
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
- EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
- DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION HOWEVER CAUSED AND
- ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- INCLUDING NEGLIGENCE OR OTHERWISE ARISING IN ANY WAY OUT OF THE USE OF THIS
- SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
- This file is part of the tinyusb stack.
-*/
-/**************************************************************************/
-
-#include "tusb_option.h"
-
-#if (MODE_HOST_SUPPORTED && HOST_CLASS_HID)
-
-#define _TINY_USB_SOURCE_FILE_
-//--------------------------------------------------------------------+
-// INCLUDE
-//--------------------------------------------------------------------+
-#include "common/common.h"
-#include "hid_host.h"
-
-//--------------------------------------------------------------------+
-// MACRO CONSTANT TYPEDEF
-//--------------------------------------------------------------------+
-
-//--------------------------------------------------------------------+
-// HID Interface common functions
-//--------------------------------------------------------------------+
-static inline tusb_error_t hidh_interface_open(uint8_t dev_addr, uint8_t interface_number, tusb_descriptor_endpoint_t const *p_endpoint_desc, hidh_interface_info_t *p_hid) ATTR_ALWAYS_INLINE;
-static inline tusb_error_t hidh_interface_open(uint8_t dev_addr, uint8_t interface_number, tusb_descriptor_endpoint_t const *p_endpoint_desc, hidh_interface_info_t *p_hid)
-{
- p_hid->pipe_hdl = hcd_pipe_open(dev_addr, p_endpoint_desc, TUSB_CLASS_HID);
- p_hid->report_size = p_endpoint_desc->wMaxPacketSize.size; // TODO get size from report descriptor
- p_hid->interface_number = interface_number;
-
- ASSERT (pipehandle_is_valid(p_hid->pipe_hdl), TUSB_ERROR_HCD_FAILED);
-
- return TUSB_ERROR_NONE;
-}
-
-static inline void hidh_interface_close(uint8_t dev_addr, hidh_interface_info_t *p_hid) ATTR_ALWAYS_INLINE;
-static inline void hidh_interface_close(uint8_t dev_addr, hidh_interface_info_t *p_hid)
-{
- (void) hcd_pipe_close(p_hid->pipe_hdl);
- memclr_(p_hid, sizeof(hidh_interface_info_t));
-}
-
-// called from public API need to validate parameters
-tusb_error_t hidh_interface_get_report(uint8_t dev_addr, void * report, hidh_interface_info_t *p_hid) ATTR_ALWAYS_INLINE;
-tusb_error_t hidh_interface_get_report(uint8_t dev_addr, void * report, hidh_interface_info_t *p_hid)
-{
- //------------- parameters validation -------------//
- // TODO change to use is configured function
- ASSERT_INT (TUSB_DEVICE_STATE_CONFIGURED, tusbh_device_get_state(dev_addr), TUSB_ERROR_DEVICE_NOT_READY);
- ASSERT_PTR (report, TUSB_ERROR_INVALID_PARA);
- ASSERT_FALSE(hcd_pipe_is_busy(p_hid->pipe_hdl), TUSB_ERROR_INTERFACE_IS_BUSY);
-
- ASSERT_STATUS( hcd_pipe_xfer(p_hid->pipe_hdl, report, p_hid->report_size, true) ) ;
-
- return TUSB_ERROR_NONE;
-}
-
-//--------------------------------------------------------------------+
-// KEYBOARD
-//--------------------------------------------------------------------+
-#if TUSB_CFG_HOST_HID_KEYBOARD
-
-#define EXPAND_KEYCODE_TO_ASCII(keycode, ascii, shift_modified) \
- [0][keycode] = ascii,\
- [1][keycode] = shift_modified,\
-
-// TODO size of table should be a macro for application to check boundary
-uint8_t const hid_keycode_to_ascii_tbl[2][128] =
-{
- HID_KEYCODE_TABLE(EXPAND_KEYCODE_TO_ASCII)
-};
-
-STATIC_VAR hidh_interface_info_t keyboardh_data[TUSB_CFG_HOST_DEVICE_MAX]; // does not have addr0, index = dev_address-1
-
-//------------- KEYBOARD PUBLIC API (parameter validation required) -------------//
-bool tusbh_hid_keyboard_is_mounted(uint8_t dev_addr)
-{
- return tusbh_device_is_configured(dev_addr) && pipehandle_is_valid(keyboardh_data[dev_addr-1].pipe_hdl);
-}
-
-tusb_error_t tusbh_hid_keyboard_get_report(uint8_t dev_addr, void* report)
-{
- return hidh_interface_get_report(dev_addr, report, &keyboardh_data[dev_addr-1]);
-}
-
-bool tusbh_hid_keyboard_is_busy(uint8_t dev_addr)
-{
- return tusbh_hid_keyboard_is_mounted(dev_addr) &&
- hcd_pipe_is_busy( keyboardh_data[dev_addr-1].pipe_hdl );
-}
-
-#endif
-
-//--------------------------------------------------------------------+
-// MOUSE
-//--------------------------------------------------------------------+
-#if TUSB_CFG_HOST_HID_MOUSE
-
-STATIC_VAR hidh_interface_info_t mouseh_data[TUSB_CFG_HOST_DEVICE_MAX]; // does not have addr0, index = dev_address-1
-
-//------------- Public API -------------//
-bool tusbh_hid_mouse_is_mounted(uint8_t dev_addr)
-{
- return tusbh_device_is_configured(dev_addr) && pipehandle_is_valid(mouseh_data[dev_addr-1].pipe_hdl);
-}
-
-bool tusbh_hid_mouse_is_busy(uint8_t dev_addr)
-{
- return tusbh_hid_mouse_is_mounted(dev_addr) &&
- hcd_pipe_is_busy( mouseh_data[dev_addr-1].pipe_hdl );
-}
-
-tusb_error_t tusbh_hid_mouse_get_report(uint8_t dev_addr, void * report)
-{
- return hidh_interface_get_report(dev_addr, report, &mouseh_data[dev_addr-1]);
-}
-
-#endif
-
-//--------------------------------------------------------------------+
-// GENERIC
-//--------------------------------------------------------------------+
-#if TUSB_CFG_HOST_HID_GENERIC
-
-//STATIC_ struct {
-// hidh_interface_info_t
-//} generic_data[TUSB_CFG_HOST_DEVICE_MAX];
-
-#endif
-
-//--------------------------------------------------------------------+
-// CLASS-USBH API (don't require to verify parameters)
-//--------------------------------------------------------------------+
-void hidh_init(void)
-{
-#if TUSB_CFG_HOST_HID_KEYBOARD
- memclr_(&keyboardh_data, sizeof(hidh_interface_info_t)*TUSB_CFG_HOST_DEVICE_MAX);
-#endif
-
-#if TUSB_CFG_HOST_HID_MOUSE
- memclr_(&mouseh_data, sizeof(hidh_interface_info_t)*TUSB_CFG_HOST_DEVICE_MAX);
-#endif
-
-#if TUSB_CFG_HOST_HID_GENERIC
- hidh_generic_init();
-#endif
-}
-
-#if 0
-uint8_t report_descriptor[256] TUSB_CFG_ATTR_USBRAM;
-#endif
-
-tusb_error_t hidh_open_subtask(uint8_t dev_addr, tusb_descriptor_interface_t const *p_interface_desc, uint16_t *p_length)
-{
- tusb_error_t error;
- uint8_t const *p_desc = (uint8_t const *) p_interface_desc;
-
- //------------- HID descriptor -------------//
- p_desc += p_desc[DESCRIPTOR_OFFSET_LENGTH];
- tusb_hid_descriptor_hid_t const *p_desc_hid = (tusb_hid_descriptor_hid_t const *) p_desc;
- ASSERT_INT(HID_DESC_TYPE_HID, p_desc_hid->bDescriptorType, TUSB_ERROR_INVALID_PARA);
-
- //------------- Endpoint Descriptor -------------//
- p_desc += p_desc[DESCRIPTOR_OFFSET_LENGTH];
- tusb_descriptor_endpoint_t const * p_endpoint_desc = (tusb_descriptor_endpoint_t const *) p_desc;
- ASSERT_INT(TUSB_DESC_TYPE_ENDPOINT, p_endpoint_desc->bDescriptorType, TUSB_ERROR_INVALID_PARA);
-
- OSAL_SUBTASK_BEGIN
-
- //------------- SET IDLE (0) request -------------//
- OSAL_SUBTASK_INVOKED_AND_WAIT(
- usbh_control_xfer_subtask( dev_addr, bm_request_type(TUSB_DIR_HOST_TO_DEV, TUSB_REQUEST_TYPE_CLASS, TUSB_REQUEST_RECIPIENT_INTERFACE),
- HID_REQUEST_CONTROL_SET_IDLE, 0, p_interface_desc->bInterfaceNumber,
- 0, NULL ),
- error
- );
-
-#if 0
- //------------- Get Report Descriptor TODO HID parser -------------//
- if ( p_desc_hid->bNumDescriptors )
- {
- OSAL_SUBTASK_INVOKED_AND_WAIT(
- usbh_control_xfer_subtask( dev_addr, bm_request_type(TUSB_DIR_DEV_TO_HOST, TUSB_REQUEST_TYPE_STANDARD, TUSB_REQUEST_RECIPIENT_INTERFACE),
- TUSB_REQUEST_GET_DESCRIPTOR, (p_desc_hid->bReportType << 8), 0,
- p_desc_hid->wReportLength, report_descriptor ),
- error
- );
- // if error in getting report descriptor --> treating like there is none
- }
-#endif
-
- if ( HID_SUBCLASS_BOOT == p_interface_desc->bInterfaceSubClass )
- {
- #if TUSB_CFG_HOST_HID_KEYBOARD
- if ( HID_PROTOCOL_KEYBOARD == p_interface_desc->bInterfaceProtocol)
- {
- SUBTASK_ASSERT_STATUS ( hidh_interface_open(dev_addr, p_interface_desc->bInterfaceNumber, p_endpoint_desc, &keyboardh_data[dev_addr-1]) );
- tusbh_hid_keyboard_mounted_cb(dev_addr);
- } else
- #endif
-
- #if TUSB_CFG_HOST_HID_MOUSE
- if ( HID_PROTOCOL_MOUSE == p_interface_desc->bInterfaceProtocol)
- {
- SUBTASK_ASSERT_STATUS ( hidh_interface_open(dev_addr, p_interface_desc->bInterfaceNumber, p_endpoint_desc, &mouseh_data[dev_addr-1]) );
- tusbh_hid_mouse_mounted_cb(dev_addr);
- } else
- #endif
-
- {
- SUBTASK_EXIT(TUSB_ERROR_HIDH_NOT_SUPPORTED_PROTOCOL); // exit & restart task
- }
- }else
- {
- SUBTASK_EXIT(TUSB_ERROR_HIDH_NOT_SUPPORTED_SUBCLASS); // exit & restart task
- }
-
- *p_length = sizeof(tusb_descriptor_interface_t) + sizeof(tusb_hid_descriptor_hid_t) + sizeof(tusb_descriptor_endpoint_t);
-
- OSAL_SUBTASK_END
-}
-
-void hidh_isr(pipe_handle_t pipe_hdl, tusb_event_t event, uint32_t xferred_bytes)
-{
-#if TUSB_CFG_HOST_HID_KEYBOARD
- if ( pipehandle_is_equal(pipe_hdl, keyboardh_data[pipe_hdl.dev_addr-1].pipe_hdl) )
- {
- tusbh_hid_keyboard_isr(pipe_hdl.dev_addr, event);
- return;
- }
-#endif
-
-#if TUSB_CFG_HOST_HID_MOUSE
- if ( pipehandle_is_equal(pipe_hdl, mouseh_data[pipe_hdl.dev_addr-1].pipe_hdl) )
- {
- tusbh_hid_mouse_isr(pipe_hdl.dev_addr, event);
- return;
- }
-#endif
-
-#if TUSB_CFG_HOST_HID_GENERIC
-
-#endif
-}
-
-void hidh_close(uint8_t dev_addr)
-{
-#if TUSB_CFG_HOST_HID_KEYBOARD
- if ( pipehandle_is_valid( keyboardh_data[dev_addr-1].pipe_hdl ) )
- {
- hidh_interface_close(dev_addr, &keyboardh_data[dev_addr-1]);
- tusbh_hid_keyboard_unmounted_cb(dev_addr);
- }
-#endif
-
-#if TUSB_CFG_HOST_HID_MOUSE
- if( pipehandle_is_valid( mouseh_data[dev_addr-1].pipe_hdl ) )
- {
- hidh_interface_close(dev_addr, &mouseh_data[dev_addr-1]);
- tusbh_hid_mouse_unmounted_cb( dev_addr );
- }
-#endif
-
-#if TUSB_CFG_HOST_HID_GENERIC
- hidh_generic_close(dev_addr);
-#endif
-}
-
-
-
-#endif
+/**************************************************************************/
+/*!
+ @file hid_host.c
+ @author hathach (tinyusb.org)
+
+ @section LICENSE
+
+ Software License Agreement (BSD License)
+
+ Copyright (c) 2013, hathach (tinyusb.org)
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ 3. Neither the name of the copyright holders nor the
+ names of its contributors may be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
+ EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
+ DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION HOWEVER CAUSED AND
+ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ INCLUDING NEGLIGENCE OR OTHERWISE ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ This file is part of the tinyusb stack.
+*/
+/**************************************************************************/
+
+#include "tusb_option.h"
+
+#if (MODE_HOST_SUPPORTED && HOST_CLASS_HID)
+
+#define _TINY_USB_SOURCE_FILE_
+//--------------------------------------------------------------------+
+// INCLUDE
+//--------------------------------------------------------------------+
+#include "common/common.h"
+#include "hid_host.h"
+
+//--------------------------------------------------------------------+
+// MACRO CONSTANT TYPEDEF
+//--------------------------------------------------------------------+
+
+//--------------------------------------------------------------------+
+// HID Interface common functions
+//--------------------------------------------------------------------+
+static inline tusb_error_t hidh_interface_open(uint8_t dev_addr, uint8_t interface_number, tusb_descriptor_endpoint_t const *p_endpoint_desc, hidh_interface_info_t *p_hid) ATTR_ALWAYS_INLINE;
+static inline tusb_error_t hidh_interface_open(uint8_t dev_addr, uint8_t interface_number, tusb_descriptor_endpoint_t const *p_endpoint_desc, hidh_interface_info_t *p_hid)
+{
+ p_hid->pipe_hdl = hcd_pipe_open(dev_addr, p_endpoint_desc, TUSB_CLASS_HID);
+ p_hid->report_size = p_endpoint_desc->wMaxPacketSize.size; // TODO get size from report descriptor
+ p_hid->interface_number = interface_number;
+
+ ASSERT (pipehandle_is_valid(p_hid->pipe_hdl), TUSB_ERROR_HCD_FAILED);
+
+ return TUSB_ERROR_NONE;
+}
+
+static inline void hidh_interface_close(uint8_t dev_addr, hidh_interface_info_t *p_hid) ATTR_ALWAYS_INLINE;
+static inline void hidh_interface_close(uint8_t dev_addr, hidh_interface_info_t *p_hid)
+{
+ (void) hcd_pipe_close(p_hid->pipe_hdl);
+ memclr_(p_hid, sizeof(hidh_interface_info_t));
+}
+
+// called from public API need to validate parameters
+tusb_error_t hidh_interface_get_report(uint8_t dev_addr, void * report, hidh_interface_info_t *p_hid) ATTR_ALWAYS_INLINE;
+tusb_error_t hidh_interface_get_report(uint8_t dev_addr, void * report, hidh_interface_info_t *p_hid)
+{
+ //------------- parameters validation -------------//
+ // TODO change to use is configured function
+ ASSERT_INT (TUSB_DEVICE_STATE_CONFIGURED, tusbh_device_get_state(dev_addr), TUSB_ERROR_DEVICE_NOT_READY);
+ ASSERT_PTR (report, TUSB_ERROR_INVALID_PARA);
+ ASSERT_FALSE(hcd_pipe_is_busy(p_hid->pipe_hdl), TUSB_ERROR_INTERFACE_IS_BUSY);
+
+ ASSERT_STATUS( hcd_pipe_xfer(p_hid->pipe_hdl, report, p_hid->report_size, true) ) ;
+
+ return TUSB_ERROR_NONE;
+}
+
+//--------------------------------------------------------------------+
+// KEYBOARD
+//--------------------------------------------------------------------+
+#if TUSB_CFG_HOST_HID_KEYBOARD
+
+#define EXPAND_KEYCODE_TO_ASCII(keycode, ascii, shift_modified) \
+ [0][keycode] = ascii,\
+ [1][keycode] = shift_modified,\
+
+// TODO size of table should be a macro for application to check boundary
+uint8_t const hid_keycode_to_ascii_tbl[2][128] =
+{
+ HID_KEYCODE_TABLE(EXPAND_KEYCODE_TO_ASCII)
+};
+
+STATIC_VAR hidh_interface_info_t keyboardh_data[TUSB_CFG_HOST_DEVICE_MAX]; // does not have addr0, index = dev_address-1
+
+//------------- KEYBOARD PUBLIC API (parameter validation required) -------------//
+bool tusbh_hid_keyboard_is_mounted(uint8_t dev_addr)
+{
+ return tusbh_device_is_configured(dev_addr) && pipehandle_is_valid(keyboardh_data[dev_addr-1].pipe_hdl);
+}
+
+tusb_error_t tusbh_hid_keyboard_get_report(uint8_t dev_addr, void* p_report)
+{
+ return hidh_interface_get_report(dev_addr, p_report, &keyboardh_data[dev_addr-1]);
+}
+
+bool tusbh_hid_keyboard_is_busy(uint8_t dev_addr)
+{
+ return tusbh_hid_keyboard_is_mounted(dev_addr) &&
+ hcd_pipe_is_busy( keyboardh_data[dev_addr-1].pipe_hdl );
+}
+
+#endif
+
+//--------------------------------------------------------------------+
+// MOUSE
+//--------------------------------------------------------------------+
+#if TUSB_CFG_HOST_HID_MOUSE
+
+STATIC_VAR hidh_interface_info_t mouseh_data[TUSB_CFG_HOST_DEVICE_MAX]; // does not have addr0, index = dev_address-1
+
+//------------- Public API -------------//
+bool tusbh_hid_mouse_is_mounted(uint8_t dev_addr)
+{
+ return tusbh_device_is_configured(dev_addr) && pipehandle_is_valid(mouseh_data[dev_addr-1].pipe_hdl);
+}
+
+bool tusbh_hid_mouse_is_busy(uint8_t dev_addr)
+{
+ return tusbh_hid_mouse_is_mounted(dev_addr) &&
+ hcd_pipe_is_busy( mouseh_data[dev_addr-1].pipe_hdl );
+}
+
+tusb_error_t tusbh_hid_mouse_get_report(uint8_t dev_addr, void * report)
+{
+ return hidh_interface_get_report(dev_addr, report, &mouseh_data[dev_addr-1]);
+}
+
+#endif
+
+//--------------------------------------------------------------------+
+// GENERIC
+//--------------------------------------------------------------------+
+#if TUSB_CFG_HOST_HID_GENERIC
+
+//STATIC_ struct {
+// hidh_interface_info_t
+//} generic_data[TUSB_CFG_HOST_DEVICE_MAX];
+
+#endif
+
+//--------------------------------------------------------------------+
+// CLASS-USBH API (don't require to verify parameters)
+//--------------------------------------------------------------------+
+void hidh_init(void)
+{
+#if TUSB_CFG_HOST_HID_KEYBOARD
+ memclr_(&keyboardh_data, sizeof(hidh_interface_info_t)*TUSB_CFG_HOST_DEVICE_MAX);
+#endif
+
+#if TUSB_CFG_HOST_HID_MOUSE
+ memclr_(&mouseh_data, sizeof(hidh_interface_info_t)*TUSB_CFG_HOST_DEVICE_MAX);
+#endif
+
+#if TUSB_CFG_HOST_HID_GENERIC
+ hidh_generic_init();
+#endif
+}
+
+#if 0
+uint8_t report_descriptor[256] TUSB_CFG_ATTR_USBRAM;
+#endif
+
+tusb_error_t hidh_open_subtask(uint8_t dev_addr, tusb_descriptor_interface_t const *p_interface_desc, uint16_t *p_length)
+{
+ tusb_error_t error;
+ uint8_t const *p_desc = (uint8_t const *) p_interface_desc;
+
+ //------------- HID descriptor -------------//
+ p_desc += p_desc[DESCRIPTOR_OFFSET_LENGTH];
+ tusb_hid_descriptor_hid_t const *p_desc_hid = (tusb_hid_descriptor_hid_t const *) p_desc;
+ ASSERT_INT(HID_DESC_TYPE_HID, p_desc_hid->bDescriptorType, TUSB_ERROR_INVALID_PARA);
+
+ //------------- Endpoint Descriptor -------------//
+ p_desc += p_desc[DESCRIPTOR_OFFSET_LENGTH];
+ tusb_descriptor_endpoint_t const * p_endpoint_desc = (tusb_descriptor_endpoint_t const *) p_desc;
+ ASSERT_INT(TUSB_DESC_TYPE_ENDPOINT, p_endpoint_desc->bDescriptorType, TUSB_ERROR_INVALID_PARA);
+
+ OSAL_SUBTASK_BEGIN
+
+ //------------- SET IDLE (0) request -------------//
+ OSAL_SUBTASK_INVOKED_AND_WAIT(
+ usbh_control_xfer_subtask( dev_addr, bm_request_type(TUSB_DIR_HOST_TO_DEV, TUSB_REQUEST_TYPE_CLASS, TUSB_REQUEST_RECIPIENT_INTERFACE),
+ HID_REQUEST_CONTROL_SET_IDLE, 0, p_interface_desc->bInterfaceNumber,
+ 0, NULL ),
+ error
+ );
+
+#if 0
+ //------------- Get Report Descriptor TODO HID parser -------------//
+ if ( p_desc_hid->bNumDescriptors )
+ {
+ OSAL_SUBTASK_INVOKED_AND_WAIT(
+ usbh_control_xfer_subtask( dev_addr, bm_request_type(TUSB_DIR_DEV_TO_HOST, TUSB_REQUEST_TYPE_STANDARD, TUSB_REQUEST_RECIPIENT_INTERFACE),
+ TUSB_REQUEST_GET_DESCRIPTOR, (p_desc_hid->bReportType << 8), 0,
+ p_desc_hid->wReportLength, report_descriptor ),
+ error
+ );
+ // if error in getting report descriptor --> treating like there is none
+ }
+#endif
+
+ if ( HID_SUBCLASS_BOOT == p_interface_desc->bInterfaceSubClass )
+ {
+ #if TUSB_CFG_HOST_HID_KEYBOARD
+ if ( HID_PROTOCOL_KEYBOARD == p_interface_desc->bInterfaceProtocol)
+ {
+ SUBTASK_ASSERT_STATUS ( hidh_interface_open(dev_addr, p_interface_desc->bInterfaceNumber, p_endpoint_desc, &keyboardh_data[dev_addr-1]) );
+ tusbh_hid_keyboard_mounted_cb(dev_addr);
+ } else
+ #endif
+
+ #if TUSB_CFG_HOST_HID_MOUSE
+ if ( HID_PROTOCOL_MOUSE == p_interface_desc->bInterfaceProtocol)
+ {
+ SUBTASK_ASSERT_STATUS ( hidh_interface_open(dev_addr, p_interface_desc->bInterfaceNumber, p_endpoint_desc, &mouseh_data[dev_addr-1]) );
+ tusbh_hid_mouse_mounted_cb(dev_addr);
+ } else
+ #endif
+
+ {
+ SUBTASK_EXIT(TUSB_ERROR_HIDH_NOT_SUPPORTED_PROTOCOL); // exit & restart task
+ }
+ }else
+ {
+ SUBTASK_EXIT(TUSB_ERROR_HIDH_NOT_SUPPORTED_SUBCLASS); // exit & restart task
+ }
+
+ *p_length = sizeof(tusb_descriptor_interface_t) + sizeof(tusb_hid_descriptor_hid_t) + sizeof(tusb_descriptor_endpoint_t);
+
+ OSAL_SUBTASK_END
+}
+
+void hidh_isr(pipe_handle_t pipe_hdl, tusb_event_t event, uint32_t xferred_bytes)
+{
+#if TUSB_CFG_HOST_HID_KEYBOARD
+ if ( pipehandle_is_equal(pipe_hdl, keyboardh_data[pipe_hdl.dev_addr-1].pipe_hdl) )
+ {
+ tusbh_hid_keyboard_isr(pipe_hdl.dev_addr, event);
+ return;
+ }
+#endif
+
+#if TUSB_CFG_HOST_HID_MOUSE
+ if ( pipehandle_is_equal(pipe_hdl, mouseh_data[pipe_hdl.dev_addr-1].pipe_hdl) )
+ {
+ tusbh_hid_mouse_isr(pipe_hdl.dev_addr, event);
+ return;
+ }
+#endif
+
+#if TUSB_CFG_HOST_HID_GENERIC
+
+#endif
+}
+
+void hidh_close(uint8_t dev_addr)
+{
+#if TUSB_CFG_HOST_HID_KEYBOARD
+ if ( pipehandle_is_valid( keyboardh_data[dev_addr-1].pipe_hdl ) )
+ {
+ hidh_interface_close(dev_addr, &keyboardh_data[dev_addr-1]);
+ tusbh_hid_keyboard_unmounted_cb(dev_addr);
+ }
+#endif
+
+#if TUSB_CFG_HOST_HID_MOUSE
+ if( pipehandle_is_valid( mouseh_data[dev_addr-1].pipe_hdl ) )
+ {
+ hidh_interface_close(dev_addr, &mouseh_data[dev_addr-1]);
+ tusbh_hid_mouse_unmounted_cb( dev_addr );
+ }
+#endif
+
+#if TUSB_CFG_HOST_HID_GENERIC
+ hidh_generic_close(dev_addr);
+#endif
+}
+
+
+
+#endif
diff --git a/tinyusb/class/hid_host.h b/tinyusb/class/hid_host.h
index 0c84bfbc3..f282621e9 100644
--- a/tinyusb/class/hid_host.h
+++ b/tinyusb/class/hid_host.h
@@ -1,119 +1,213 @@
-/**************************************************************************/
-/*!
- @file hid_host.h
- @author hathach (tinyusb.org)
-
- @section LICENSE
-
- Software License Agreement (BSD License)
-
- Copyright (c) 2013, hathach (tinyusb.org)
- All rights reserved.
-
- Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions are met:
- 1. Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
- 2. Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
- 3. Neither the name of the copyright holders nor the
- names of its contributors may be used to endorse or promote products
- derived from this software without specific prior written permission.
-
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
- EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
- DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION HOWEVER CAUSED AND
- ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- INCLUDING NEGLIGENCE OR OTHERWISE ARISING IN ANY WAY OUT OF THE USE OF THIS
- SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
- This file is part of the tinyusb stack.
-*/
-/**************************************************************************/
-
-/** \ingroup TBD
- * \defgroup TBD
- * \brief TBD
- *
- * @{
- */
-
-#ifndef _TUSB_HID_HOST_H_
-#define _TUSB_HID_HOST_H_
-
-#include "common/common.h"
-#include "host/usbh.h"
-#include "hid.h"
-
-#ifdef __cplusplus
- extern "C" {
-#endif
-
-//--------------------------------------------------------------------+
-// KEYBOARD Application API
-//--------------------------------------------------------------------+
-extern uint8_t const hid_keycode_to_ascii_tbl[2][128]; // TODO used weak attr if build failed without KEYBOARD enabled
-
-bool tusbh_hid_keyboard_is_mounted(uint8_t dev_addr) ATTR_PURE ATTR_WARN_UNUSED_RESULT;
-bool tusbh_hid_keyboard_is_busy(uint8_t dev_addr) ATTR_PURE ATTR_WARN_UNUSED_RESULT;
-tusb_error_t tusbh_hid_keyboard_get_report(uint8_t dev_addr, void * report) /*ATTR_WARN_UNUSED_RESULT*/;
-
-//------------- Application Callback -------------//
-void tusbh_hid_keyboard_isr(uint8_t dev_addr, tusb_event_t event);
-void tusbh_hid_keyboard_mounted_cb(uint8_t dev_addr);
-void tusbh_hid_keyboard_unmounted_cb(uint8_t dev_addr);
-
-//--------------------------------------------------------------------+
-// MOUSE Application API
-//--------------------------------------------------------------------+
-bool tusbh_hid_mouse_is_mounted(uint8_t dev_addr) ATTR_PURE ATTR_WARN_UNUSED_RESULT;
-bool tusbh_hid_mouse_is_busy(uint8_t dev_addr) ATTR_PURE ATTR_WARN_UNUSED_RESULT;
-tusb_error_t tusbh_hid_mouse_get_report(uint8_t dev_addr, void* report) /*ATTR_WARN_UNUSED_RESULT*/;
-
-//------------- Application Callback -------------//
-void tusbh_hid_mouse_isr(uint8_t dev_addr, tusb_event_t event);
-void tusbh_hid_mouse_mounted_cb(uint8_t dev_addr);
-void tusbh_hid_mouse_unmounted_cb(uint8_t dev_addr);
-
-//--------------------------------------------------------------------+
-// GENERIC Application API
-//--------------------------------------------------------------------+
-bool tusbh_hid_generic_is_mounted(uint8_t dev_addr) ATTR_PURE ATTR_WARN_UNUSED_RESULT;
-tusb_error_t tusbh_hid_generic_get_report(uint8_t dev_addr, void* report, bool int_on_complete) ATTR_WARN_UNUSED_RESULT;
-tusb_error_t tusbh_hid_generic_set_report(uint8_t dev_addr, void* report, bool int_on_complete) ATTR_WARN_UNUSED_RESULT;
-tusb_interface_status_t tusbh_hid_generic_get_status(uint8_t dev_addr) ATTR_WARN_UNUSED_RESULT;
-tusb_interface_status_t tusbh_hid_generic_set_status(uint8_t dev_addr) ATTR_WARN_UNUSED_RESULT;
-
-//------------- Application Callback -------------//
-void tusbh_hid_generic_isr(uint8_t dev_addr, tusb_event_t event);
-
-//--------------------------------------------------------------------+
-// USBH-CLASS DRIVER API
-//--------------------------------------------------------------------+
-#ifdef _TINY_USB_SOURCE_FILE_
-
-typedef struct {
- pipe_handle_t pipe_hdl;
- uint16_t report_size;
- uint8_t interface_number;
-}hidh_interface_info_t;
-
-void hidh_init(void);
-tusb_error_t hidh_open_subtask(uint8_t dev_addr, tusb_descriptor_interface_t const *p_interface_desc, uint16_t *p_length) ATTR_WARN_UNUSED_RESULT;
-void hidh_isr(pipe_handle_t pipe_hdl, tusb_event_t event, uint32_t xferred_bytes);
-void hidh_close(uint8_t dev_addr);
-
-#endif
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _TUSB_HID_HOST_H_ */
-
-/** @} */
+/**************************************************************************/
+/*!
+ @file hid_host.h
+ @author hathach (tinyusb.org)
+
+ @section LICENSE
+
+ Software License Agreement (BSD License)
+
+ Copyright (c) 2013, hathach (tinyusb.org)
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ 3. Neither the name of the copyright holders nor the
+ names of its contributors may be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
+ EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
+ DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION HOWEVER CAUSED AND
+ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ INCLUDING NEGLIGENCE OR OTHERWISE ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ This file is part of the tinyusb stack.
+*/
+/**************************************************************************/
+
+/** \addtogroup ClassDriver_HID
+ * @{ */
+
+#ifndef _TUSB_HID_HOST_H_
+#define _TUSB_HID_HOST_H_
+
+#include "common/common.h"
+#include "host/usbh.h"
+#include "hid.h"
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+/** \defgroup hid_keyboard Keyboard
+ * The interface API includes status checking function, data transferring function and callback functions
+ * @{ */
+//--------------------------------------------------------------------+
+// KEYBOARD Application API
+//--------------------------------------------------------------------+
+extern uint8_t const hid_keycode_to_ascii_tbl[2][128]; // TODO used weak attr if build failed without KEYBOARD enabled
+
+/** \brief Check if device supports Keyboard interface or not
+ * \param[in] dev_addr device address
+ * \retval true if device supports Keyboard interface
+ * \retval false if device does not support Keyboard interface or is not mounted
+ */
+bool tusbh_hid_keyboard_is_mounted(uint8_t dev_addr) ATTR_PURE ATTR_WARN_UNUSED_RESULT;
+
+/** \brief Check if the interface is currently busy or not
+ * \param[in] dev_addr device address
+ * \retval true if the interface is busy meaning the stack is still transferring/waiting data from/to device
+ * \retval false if the interface is not busy meaning the stack successfully transferred data from/to device
+ * \note This function is primarily used for polling/waiting result after \ref tusbh_hid_keyboard_get_report.
+ * Alternatively, asynchronous event API can be used
+ */
+bool tusbh_hid_keyboard_is_busy(uint8_t dev_addr) ATTR_PURE ATTR_WARN_UNUSED_RESULT;
+
+/** \brief Perform a get report from Keyboard interface
+ * \param[in] dev_addr device address
+ * \param[in,out] p_report address that is used to store data from device. Must be accessible by usb controller (see \ref TUSB_CFG_ATTR_USBRAM)
+ * \returns \ref tusb_error_t type to indicate success or error condition.
+ * \retval TUSB_ERROR_NONE on success
+ * \retval TUSB_ERROR_INTERFACE_IS_BUSY if the interface is already transferring data with device
+ * \retval TUSB_ERROR_DEVICE_NOT_READY if device is not yet configured (by SET CONFIGURED request)
+ * \retval TUSB_ERROR_INVALID_PARA if inputs parameter are not correct
+ * \note This function is non-blocking and returns immediately. The result of usb transfer will be reported by the interface's callback function
+ */
+tusb_error_t tusbh_hid_keyboard_get_report(uint8_t dev_addr, void * p_report) /*ATTR_WARN_UNUSED_RESULT*/;
+
+//------------- Application Callback -------------//
+/** \brief Callback function that is invoked when an transferring event occurred
+ * \param[in] dev_addr Address of device
+ * \param[in] event an value from \ref tusb_event_t
+ * \note event can be one of following
+ * - TUSB_EVENT_XFER_COMPLETE : previously scheduled transfer completes successfully.
+ * - TUSB_EVENT_XFER_ERROR : previously scheduled transfer encountered a transaction error.
+ * - TUSB_EVENT_XFER_STALLED : previously scheduled transfer is stalled by device.
+ * \note Application should schedule the next report by calling \ref tusbh_hid_keyboard_get_report within this callback
+ */
+void tusbh_hid_keyboard_isr(uint8_t dev_addr, tusb_event_t event);
+
+/** \brief Callback function that will be invoked when a device with Keyboard interface is mounted
+ * \param[in] dev_addr Address of newly mounted device
+ * \note This callback should be used by Application to set-up interface-related data
+ */
+void tusbh_hid_keyboard_mounted_cb(uint8_t dev_addr);
+
+/** \brief Callback function that will be invoked when a device with Keyboard interface is unmounted
+ * \param[in] dev_addr Address of newly unmounted device
+ * \note This callback should be used by Application to tear-down interface-related data
+ */
+void tusbh_hid_keyboard_unmounted_cb(uint8_t dev_addr);
+/** @} */
+
+/** \defgroup hid_mouse Mouse
+ * The interface API includes status checking function, data transferring function and callback functions
+ * @{ */
+//--------------------------------------------------------------------+
+// MOUSE Application API
+//--------------------------------------------------------------------+
+/** \brief Check if device supports Mouse interface or not
+ * \param[in] dev_addr device address
+ * \retval true if device supports Mouse interface
+ * \retval false if device does not support Mouse interface or is not mounted
+ */
+bool tusbh_hid_mouse_is_mounted(uint8_t dev_addr) ATTR_PURE ATTR_WARN_UNUSED_RESULT;
+
+/** \brief Check if the interface is currently busy or not
+ * \param[in] dev_addr device address
+ * \retval true if the interface is busy meaning the stack is still transferring/waiting data from/to device
+ * \retval false if the interface is not busy meaning the stack successfully transferred data from/to device
+ * \note This function is primarily used for polling/waiting result after \ref tusbh_hid_mouse_get_report.
+ * Alternatively, asynchronous event API can be used
+ */
+bool tusbh_hid_mouse_is_busy(uint8_t dev_addr) ATTR_PURE ATTR_WARN_UNUSED_RESULT;
+
+/** \brief Perform a get report from Mouse interface
+ * \param[in] dev_addr device address
+ * \param[in,out] p_report address that is used to store data from device. Must be accessible by usb controller (see \ref TUSB_CFG_ATTR_USBRAM)
+ * \returns \ref tusb_error_t type to indicate success or error condition.
+ * \retval TUSB_ERROR_NONE on success
+ * \retval TUSB_ERROR_INTERFACE_IS_BUSY if the interface is already transferring data with device
+ * \retval TUSB_ERROR_DEVICE_NOT_READY if device is not yet configured (by SET CONFIGURED request)
+ * \retval TUSB_ERROR_INVALID_PARA if inputs parameter are not correct
+ * \note This function is non-blocking and returns immediately. The result of usb transfer will be reported by the interface's callback function
+ */
+tusb_error_t tusbh_hid_mouse_get_report(uint8_t dev_addr, void* p_report) /*ATTR_WARN_UNUSED_RESULT*/;
+
+//------------- Application Callback -------------//
+/** \brief Callback function that is invoked when an transferring event occurred
+ * \param[in] dev_addr Address of device
+ * \param[in] event an value from \ref tusb_event_t
+ * \note event can be one of following
+ * - TUSB_EVENT_XFER_COMPLETE : previously scheduled transfer completes successfully.
+ * - TUSB_EVENT_XFER_ERROR : previously scheduled transfer encountered a transaction error.
+ * - TUSB_EVENT_XFER_STALLED : previously scheduled transfer is stalled by device.
+ * \note Application should schedule the next report by calling \ref tusbh_hid_mouse_get_report within this callback
+ */
+void tusbh_hid_mouse_isr(uint8_t dev_addr, tusb_event_t event);
+
+/** \brief Callback function that will be invoked when a device with Mouse interface is mounted
+ * \param[in] dev_addr Address of newly mounted device
+ * \note This callback should be used by Application to set-up interface-related data
+ */
+void tusbh_hid_mouse_mounted_cb(uint8_t dev_addr);
+
+/** \brief Callback function that will be invoked when a device with Mouse interface is unmounted
+ * \param[in] dev_addr Address of newly unmounted device
+ * \note This callback should be used by Application to tear-down interface-related data
+ */
+void tusbh_hid_mouse_unmounted_cb(uint8_t dev_addr);
+/** @} */
+
+/** \defgroup hid_generic Generic (not supported yet)
+ * The interface API includes status checking function, data transferring function and callback functions
+ * @{ */
+//--------------------------------------------------------------------+
+// GENERIC Application API
+//--------------------------------------------------------------------+
+bool tusbh_hid_generic_is_mounted(uint8_t dev_addr) ATTR_PURE ATTR_WARN_UNUSED_RESULT;
+tusb_error_t tusbh_hid_generic_get_report(uint8_t dev_addr, void* p_report, bool int_on_complete) ATTR_WARN_UNUSED_RESULT;
+tusb_error_t tusbh_hid_generic_set_report(uint8_t dev_addr, void* p_report, bool int_on_complete) ATTR_WARN_UNUSED_RESULT;
+tusb_interface_status_t tusbh_hid_generic_get_status(uint8_t dev_addr) ATTR_WARN_UNUSED_RESULT;
+tusb_interface_status_t tusbh_hid_generic_set_status(uint8_t dev_addr) ATTR_WARN_UNUSED_RESULT;
+
+//------------- Application Callback -------------//
+void tusbh_hid_generic_isr(uint8_t dev_addr, tusb_event_t event);
+/** @} */
+
+//--------------------------------------------------------------------+
+// USBH-CLASS DRIVER API
+//--------------------------------------------------------------------+
+#ifdef _TINY_USB_SOURCE_FILE_
+
+typedef struct {
+ pipe_handle_t pipe_hdl;
+ uint16_t report_size;
+ uint8_t interface_number;
+}hidh_interface_info_t;
+
+void hidh_init(void);
+tusb_error_t hidh_open_subtask(uint8_t dev_addr, tusb_descriptor_interface_t const *p_interface_desc, uint16_t *p_length) ATTR_WARN_UNUSED_RESULT;
+void hidh_isr(pipe_handle_t pipe_hdl, tusb_event_t event, uint32_t xferred_bytes);
+void hidh_close(uint8_t dev_addr);
+
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _TUSB_HID_HOST_H_ */
+
+/** @} */
diff --git a/tinyusb/doxygen/configuration.h b/tinyusb/doxygen/configuration.h
new file mode 100644
index 000000000..8f2d8bd34
--- /dev/null
+++ b/tinyusb/doxygen/configuration.h
@@ -0,0 +1,39 @@
+/** \addtogroup group_configuration
+ * @{ */
+
+/**
+ USB controller in MCU often has limited access to specific RAM section. The Stack will use this macro to place internal variables
+ into the USB RAM section as follows. if your mcu's usb controller has no such limit, define TUSB_CFG_ATTR_USBRAM as empty macro.
+
+ @code
+ uint8_t tinyusb_data[10] TUSB_CFG_ATTR_USBRAM;
+ @endcode
+ */
+#define TUSB_CFG_ATTR_USBRAM
+
+
+/** \defgroup TUSB_CFG_HOST Host
+ * @{ */
+
+/// Maximum number of device host stack can manage
+/// - If hub class is not enabled, set this equal to number of controllers in host mode
+/// - if hub class is enabled, make sure hub is also counted
+#define TUSB_CFG_HOST_DEVICE_MAX
+
+/// Buffer size used for getting device configuration descriptor. You may want to increase this from default
+/// to support lengthy composite device especially with Audio or Video class
+#define TUSB_CFG_HOST_ENUM_BUFFER_SIZE
+
+#define TUSB_CFG_HOST_HUB ///< Enable Hub Class
+#define TUSB_CFG_HOST_HID_KEYBOARD ///< Enable HID Class for Keyboard
+#define TUSB_CFG_HOST_HID_MOUSE ///< Enable HID Class for Mouse
+#define TUSB_CFG_HOST_HID_GENERIC ///< Enable HID Class for Generic (not supported yet)
+#define TUSB_CFG_HOST_MSC ///< Enable Mass Storage Class (SCSI subclass only)
+#define TUSB_CFG_HOST_CDC ///< Enable Virtual Serial (Communication Device Class)
+#define TUSB_CFG_HOST_CDC_RNDIS ///< Enable Remote Network Device (require TUSB_CFG_HOST_CDC to be enabled)
+
+/** @} */ // group Host
+
+
+
+/** @} */
diff --git a/tinyusb/doxygen/overview.md b/tinyusb/doxygen/overview.md
deleted file mode 100644
index 695690143..000000000
--- a/tinyusb/doxygen/overview.md
+++ /dev/null
@@ -1,3 +0,0 @@
-# What is tinyUSB
-
-![tinyUSB diagram](overview.png)
diff --git a/tinyusb/hal/hal_lpc43xx.c b/tinyusb/hal/hal_lpc43xx.c
index 6b23ca9a2..2fe019d09 100644
--- a/tinyusb/hal/hal_lpc43xx.c
+++ b/tinyusb/hal/hal_lpc43xx.c
@@ -1,123 +1,123 @@
-/**************************************************************************/
-/*!
- @file hal_lpc43xx.c
- @author hathach (tinyusb.org)
-
- @section LICENSE
-
- Software License Agreement (BSD License)
-
- Copyright (c) 2013, hathach (tinyusb.org)
- All rights reserved.
-
- Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions are met:
- 1. Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
- 2. Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
- 3. Neither the name of the copyright holders nor the
- names of its contributors may be used to endorse or promote products
- derived from this software without specific prior written permission.
-
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
- EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
- DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION HOWEVER CAUSED AND
- ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- INCLUDING NEGLIGENCE OR OTHERWISE ARISING IN ANY WAY OUT OF THE USE OF THIS
- SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
- This file is part of the tinyusb stack.
-*/
-/**************************************************************************/
-
-#include "common/common.h"
-#include "hal.h"
-
-#if MCU == MCU_LPC43XX
-
-#include "lpc43xx_cgu.h"
-#include "lpc43xx_scu.h"
-
-enum {
- LPC43XX_USBMODE_DEVICE = 2,
- LPC43XX_USBMODE_HOST = 3
-};
-
-enum {
- LPC43XX_USBMODE_VBUS_LOW = 0,
- LPC43XX_USBMODE_VBUS_HIGH = 1
-};
-
-tusb_error_t hal_init(void)
-{
- //------------- USB0 Clock -------------//
-#if TUSB_CFG_CONTROLLER0_MODE
- CGU_EnableEntity(CGU_CLKSRC_PLL0, DISABLE); /* Disable PLL first */
- ASSERT_INT( CGU_ERROR_SUCCESS, CGU_SetPLL0(), TUSB_ERROR_FAILED); /* the usb core require output clock = 480MHz */
- CGU_EntityConnect(CGU_CLKSRC_XTAL_OSC, CGU_CLKSRC_PLL0);
- CGU_EnableEntity(CGU_CLKSRC_PLL0, ENABLE); /* Enable PLL after all setting is done */
- LPC_CREG->CREG0 &= ~(1<<5); /* Turn on the phy */
-
- // reset controller & set role
- #if TUSB_CFG_CONTROLLER0_MODE & TUSB_MODE_HOST
- hcd_controller_reset(0); // TODO where to place prototype
- LPC_USB0->USBMODE_H = LPC43XX_USBMODE_HOST | (LPC43XX_USBMODE_VBUS_HIGH << 5);
- #else // TODO OTG
-// dcd_controller_reset(0);
-// LPC_USB0->USBMODE_D = LPC43XX_USBMODE_DEVICE;
-// LPC_USB0->OTGSC = (1<<3) | (1<<0) /*| (1<<16)| (1<<24)| (1<<25)| (1<<26)| (1<<27)| (1<<28)| (1<<29)| (1<<30)*/;
-// LPC_USB0->PORTSC1_D |= (1<<24); // force full speed
-// dcd_controller_connect(0);
- #endif
-
- hal_interrupt_enable(0);
-#endif
-
- //------------- USB1 Clock, only use on-chip FS PHY -------------//
-#if TUSB_CFG_CONTROLLER1_MODE
- // TODO confirm whether device mode require P2_5 or not
- scu_pinmux(0x2, 5, MD_PLN | MD_EZI | MD_ZI, FUNC2); // USB1_VBUS monitor presence, must be high for bus reset occur
-
- /* connect CLK_USB1 to 60 MHz clock */
- CGU_EntityConnect(CGU_CLKSRC_PLL1, CGU_BASE_USB1); /* FIXME Run base BASE_USB1_CLK clock from PLL1 (assume PLL1 is 60 MHz, no division required) */
- //LPC_CREG->CREG0 &= ~(1<<5); /* Turn on the phy */
- LPC_SCU->SFSUSB = (TUSB_CFG_CONTROLLER1_MODE & TUSB_MODE_HOST) ? 0x16 : 0x12; // enable USB1 with on-chip FS PHY
-
- #if TUSB_CFG_CONTROLLER1_MODE & TUSB_MODE_HOST
- hcd_controller_reset(1); // TODO where to place prototype
- LPC_USB1->USBMODE_H = LPC43XX_USBMODE_HOST | (LPC43XX_USBMODE_VBUS_HIGH << 5);
- #else // TODO OTG
-// dcd_controller_reset(1);
- LPC_USB0->USBMODE_D = LPC43XX_USBMODE_DEVICE;
- dcd_controller_connect(1);
- #endif
-
- LPC_USB1->PORTSC1_D |= (1<<24); // TODO abtract, force port to fullspeed
-
- hal_interrupt_enable(1);
-#endif
-
- return TUSB_ERROR_NONE;
-}
-
-#if TUSB_CFG_CONTROLLER0_MODE
-void USB0_IRQHandler(void)
-{
- tusb_isr(0);
-}
-#endif
-
-#if TUSB_CFG_CONTROLLER1_MODE
-void USB1_IRQHandler(void)
-{
- tusb_isr(1);
-}
-#endif
-
-#endif
+/**************************************************************************/
+/*!
+ @file hal_lpc43xx.c
+ @author hathach (tinyusb.org)
+
+ @section LICENSE
+
+ Software License Agreement (BSD License)
+
+ Copyright (c) 2013, hathach (tinyusb.org)
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ 3. Neither the name of the copyright holders nor the
+ names of its contributors may be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
+ EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
+ DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION HOWEVER CAUSED AND
+ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ INCLUDING NEGLIGENCE OR OTHERWISE ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ This file is part of the tinyusb stack.
+*/
+/**************************************************************************/
+
+#include "common/common.h"
+#include "hal.h"
+
+#if MCU == MCU_LPC43XX
+
+#include "lpc43xx_cgu.h"
+#include "lpc43xx_scu.h"
+
+enum {
+ LPC43XX_USBMODE_DEVICE = 2,
+ LPC43XX_USBMODE_HOST = 3
+};
+
+enum {
+ LPC43XX_USBMODE_VBUS_LOW = 0,
+ LPC43XX_USBMODE_VBUS_HIGH = 1
+};
+
+tusb_error_t hal_init(void)
+{
+ //------------- USB0 Clock -------------//
+#if TUSB_CFG_CONTROLLER_0_MODE
+ CGU_EnableEntity(CGU_CLKSRC_PLL0, DISABLE); /* Disable PLL first */
+ ASSERT_INT( CGU_ERROR_SUCCESS, CGU_SetPLL0(), TUSB_ERROR_FAILED); /* the usb core require output clock = 480MHz */
+ CGU_EntityConnect(CGU_CLKSRC_XTAL_OSC, CGU_CLKSRC_PLL0);
+ CGU_EnableEntity(CGU_CLKSRC_PLL0, ENABLE); /* Enable PLL after all setting is done */
+ LPC_CREG->CREG0 &= ~(1<<5); /* Turn on the phy */
+
+ // reset controller & set role
+ #if TUSB_CFG_CONTROLLER_0_MODE & TUSB_MODE_HOST
+ hcd_controller_reset(0); // TODO where to place prototype
+ LPC_USB0->USBMODE_H = LPC43XX_USBMODE_HOST | (LPC43XX_USBMODE_VBUS_HIGH << 5);
+ #else // TODO OTG
+// dcd_controller_reset(0);
+// LPC_USB0->USBMODE_D = LPC43XX_USBMODE_DEVICE;
+// LPC_USB0->OTGSC = (1<<3) | (1<<0) /*| (1<<16)| (1<<24)| (1<<25)| (1<<26)| (1<<27)| (1<<28)| (1<<29)| (1<<30)*/;
+// LPC_USB0->PORTSC1_D |= (1<<24); // force full speed
+// dcd_controller_connect(0);
+ #endif
+
+ hal_interrupt_enable(0);
+#endif
+
+ //------------- USB1 Clock, only use on-chip FS PHY -------------//
+#if TUSB_CFG_CONTROLLER_1_MODE
+ // TODO confirm whether device mode require P2_5 or not
+ scu_pinmux(0x2, 5, MD_PLN | MD_EZI | MD_ZI, FUNC2); // USB1_VBUS monitor presence, must be high for bus reset occur
+
+ /* connect CLK_USB1 to 60 MHz clock */
+ CGU_EntityConnect(CGU_CLKSRC_PLL1, CGU_BASE_USB1); /* FIXME Run base BASE_USB1_CLK clock from PLL1 (assume PLL1 is 60 MHz, no division required) */
+ //LPC_CREG->CREG0 &= ~(1<<5); /* Turn on the phy */
+ LPC_SCU->SFSUSB = (TUSB_CFG_CONTROLLER_1_MODE & TUSB_MODE_HOST) ? 0x16 : 0x12; // enable USB1 with on-chip FS PHY
+
+ #if TUSB_CFG_CONTROLLER_1_MODE & TUSB_MODE_HOST
+ hcd_controller_reset(1); // TODO where to place prototype
+ LPC_USB1->USBMODE_H = LPC43XX_USBMODE_HOST | (LPC43XX_USBMODE_VBUS_HIGH << 5);
+ #else // TODO OTG
+// dcd_controller_reset(1);
+ LPC_USB0->USBMODE_D = LPC43XX_USBMODE_DEVICE;
+ dcd_controller_connect(1);
+ #endif
+
+ LPC_USB1->PORTSC1_D |= (1<<24); // TODO abtract, force port to fullspeed
+
+ hal_interrupt_enable(1);
+#endif
+
+ return TUSB_ERROR_NONE;
+}
+
+#if TUSB_CFG_CONTROLLER_0_MODE
+void USB0_IRQHandler(void)
+{
+ tusb_isr(0);
+}
+#endif
+
+#if TUSB_CFG_CONTROLLER_1_MODE
+void USB1_IRQHandler(void)
+{
+ tusb_isr(1);
+}
+#endif
+
+#endif
diff --git a/tinyusb/host/ehci/ehci.c b/tinyusb/host/ehci/ehci.c
index 378e5f736..428c2636f 100644
--- a/tinyusb/host/ehci/ehci.c
+++ b/tinyusb/host/ehci/ehci.c
@@ -1,1098 +1,1098 @@
-/**************************************************************************/
-/*!
- @file ehci.c
- @author hathach (tinyusb.org)
-
- @section LICENSE
-
- Software License Agreement (BSD License)
-
- Copyright (c) 2013, hathach (tinyusb.org)
- All rights reserved.
-
- Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions are met:
- 1. Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
- 2. Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
- 3. Neither the name of the copyright holders nor the
- names of its contributors may be used to endorse or promote products
- derived from this software without specific prior written permission.
-
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
- EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
- DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION HOWEVER CAUSED AND
- ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- INCLUDING NEGLIGENCE OR OTHERWISE ARISING IN ANY WAY OUT OF THE USE OF THIS
- SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
- This file is part of the tinyusb stack.
-*/
-/**************************************************************************/
-
-#include "common/common.h"
-
-#if MODE_HOST_SUPPORTED && (MCU == MCU_LPC43XX || MCU == MCU_LPC18XX)
-//--------------------------------------------------------------------+
-// INCLUDE
-//--------------------------------------------------------------------+
-#include "hal/hal.h"
-#include "osal/osal.h"
-#include "common/timeout_timer.h"
-
-#include "../hcd.h"
-#include "../usbh_hcd.h"
-#include "ehci.h"
-
-//--------------------------------------------------------------------+
-// MACRO CONSTANT TYPEDEF
-//--------------------------------------------------------------------+
-
-//--------------------------------------------------------------------+
-// INTERNAL OBJECT & FUNCTION DECLARATION
-//--------------------------------------------------------------------+
-STATIC_VAR ehci_data_t ehci_data TUSB_CFG_ATTR_USBRAM;
-
-#if EHCI_PERIODIC_LIST
-
- #if (TUSB_CFG_CONTROLLER0_MODE & TUSB_MODE_HOST)
- ATTR_ALIGNED(4096) STATIC_VAR ehci_link_t period_frame_list0[EHCI_FRAMELIST_SIZE] TUSB_CFG_ATTR_USBRAM;
-
- #ifndef __ICCARM__ // IAR cannot able to determine the alignment with datalignment pragma
- STATIC_ASSERT( ALIGN_OF(period_frame_list0) == 4096, "Period Framelist must be 4k alginment"); // validation
- #endif
- #endif
-
- #if (TUSB_CFG_CONTROLLER1_MODE & TUSB_MODE_HOST)
- STATIC_VAR ehci_link_t period_frame_list1[EHCI_FRAMELIST_SIZE] ATTR_ALIGNED(4096) TUSB_CFG_ATTR_USBRAM;
-
- #ifndef __ICCARM__ // IAR cannot able to determine the alignment with datalignment pragma
- STATIC_ASSERT( ALIGN_OF(period_frame_list1) == 4096, "Period Framelist must be 4k alginment"); // validation
- #endif
- #endif
-#endif
-
-//------------- Validation -------------//
-// TODO static assert for memory placement on some known MCU such as lpc43xx
-
-//--------------------------------------------------------------------+
-// PROTOTYPE
-//--------------------------------------------------------------------+
-STATIC_ INLINE_ ehci_registers_t* get_operational_register(uint8_t hostid) ATTR_PURE ATTR_ALWAYS_INLINE ATTR_WARN_UNUSED_RESULT;
-STATIC_ INLINE_ ehci_link_t* get_period_frame_list(uint8_t hostid) ATTR_PURE ATTR_ALWAYS_INLINE ATTR_WARN_UNUSED_RESULT;
-STATIC_ INLINE_ uint8_t hostid_to_data_idx(uint8_t hostid) ATTR_ALWAYS_INLINE ATTR_CONST ATTR_WARN_UNUSED_RESULT;
-
-STATIC_ INLINE_ ehci_qhd_t* get_async_head(uint8_t hostid) ATTR_ALWAYS_INLINE ATTR_PURE ATTR_WARN_UNUSED_RESULT;
-STATIC_ INLINE_ ehci_link_t* get_period_head(uint8_t hostid, uint8_t interval_ms) ATTR_ALWAYS_INLINE ATTR_PURE ATTR_WARN_UNUSED_RESULT;
-
-STATIC_ INLINE_ ehci_qhd_t* get_control_qhd(uint8_t dev_addr) ATTR_ALWAYS_INLINE ATTR_PURE ATTR_WARN_UNUSED_RESULT;
-STATIC_ INLINE_ ehci_qtd_t* get_control_qtds(uint8_t dev_addr) ATTR_ALWAYS_INLINE ATTR_PURE ATTR_WARN_UNUSED_RESULT;
-
-static inline uint8_t qhd_get_index(ehci_qhd_t const * p_qhd) ATTR_ALWAYS_INLINE ATTR_PURE;
-static inline ehci_qhd_t* qhd_next(ehci_qhd_t const * p_qhd) ATTR_ALWAYS_INLINE ATTR_PURE;
-static inline ehci_qhd_t* qhd_find_free (uint8_t dev_addr) ATTR_PURE ATTR_ALWAYS_INLINE;
-static inline tusb_xfer_type_t qhd_get_xfer_type(ehci_qhd_t const * p_qhd) ATTR_ALWAYS_INLINE ATTR_PURE;
-STATIC_ INLINE_ ehci_qhd_t* qhd_get_from_pipe_handle(pipe_handle_t pipe_hdl) ATTR_PURE ATTR_ALWAYS_INLINE;
-static inline pipe_handle_t qhd_create_pipe_handle(ehci_qhd_t const * p_qhd, tusb_xfer_type_t xfer_type) ATTR_PURE ATTR_ALWAYS_INLINE;
-// determine if a queue head has bus-related error
-static inline bool qhd_has_xact_error(ehci_qhd_t * p_qhd) ATTR_ALWAYS_INLINE ATTR_PURE;
-static inline bool qhd_has_xact_error(ehci_qhd_t * p_qhd)
-{
- return ( p_qhd->qtd_overlay.buffer_err ||p_qhd->qtd_overlay.babble_err || p_qhd->qtd_overlay.xact_err );
- //p_qhd->qtd_overlay.non_hs_period_missed_uframe || p_qhd->qtd_overlay.pingstate_err TODO split transaction error
-}
-
-static void qhd_init(ehci_qhd_t *p_qhd, uint8_t dev_addr, uint16_t max_packet_size, uint8_t endpoint_addr, uint8_t xfer_type, uint8_t interval);
-
-
-STATIC_ INLINE_ ehci_qtd_t* qtd_find_free(uint8_t dev_addr) ATTR_PURE ATTR_ALWAYS_INLINE;
-static inline ehci_qtd_t* qtd_next(ehci_qtd_t const * p_qtd ) ATTR_PURE ATTR_ALWAYS_INLINE;
-static inline void qtd_insert_to_qhd(ehci_qhd_t *p_qhd, ehci_qtd_t *p_qtd_new) ATTR_ALWAYS_INLINE;
-static inline void qtd_remove_1st_from_qhd(ehci_qhd_t *p_qhd) ATTR_ALWAYS_INLINE;
-static void qtd_init(ehci_qtd_t* p_qtd, uint32_t data_ptr, uint16_t total_bytes);
-
-static inline void list_insert(ehci_link_t *current, ehci_link_t *new, uint8_t new_type) ATTR_ALWAYS_INLINE;
-static inline ehci_link_t* list_next(ehci_link_t *p_link_pointer) ATTR_PURE ATTR_ALWAYS_INLINE;
-static ehci_link_t* list_find_previous_item(ehci_link_t* p_head, ehci_link_t* p_current);
-static tusb_error_t list_remove_qhd(ehci_link_t* p_head, ehci_link_t* p_remove);
-
-static tusb_error_t hcd_controller_init(uint8_t hostid) ATTR_WARN_UNUSED_RESULT;
-static tusb_error_t hcd_controller_stop(uint8_t hostid) ATTR_WARN_UNUSED_RESULT;
-
-//--------------------------------------------------------------------+
-// USBH-HCD API
-//--------------------------------------------------------------------+
-tusb_error_t hcd_init(void)
-{
- //------------- Data Structure init -------------//
- memclr_(&ehci_data, sizeof(ehci_data_t));
-
- #if (TUSB_CFG_CONTROLLER0_MODE & TUSB_MODE_HOST)
- ASSERT_STATUS (hcd_controller_init(0));
- #endif
-
- #if (TUSB_CFG_CONTROLLER1_MODE & TUSB_MODE_HOST)
- ASSERT_STATUS (hcd_controller_init(1));
- #endif
-
- return TUSB_ERROR_NONE;
-}
-
-//--------------------------------------------------------------------+
-// PORT API
-//--------------------------------------------------------------------+
-void hcd_port_reset(uint8_t hostid)
-{
- ehci_registers_t* const regs = get_operational_register(hostid);
-
- regs->portsc_bit.port_enable = 0; // disable port before reset
- regs->portsc_bit.port_reset = 1;
-
-#ifndef _TEST_
- // NXP specific, port reset will automatically be 0 when reset sequence complete
- // there is chance device is unplugged while reset sequence is not complete
- while( regs->portsc_bit.port_reset) {} // TODO use task delay to remove blocking
-#endif
-}
-
-bool hcd_port_connect_status(uint8_t hostid)
-{
- return get_operational_register(hostid)->portsc_bit.current_connect_status;
-}
-
-tusb_speed_t hcd_port_speed_get(uint8_t hostid)
-{
- return (tusb_speed_t) get_operational_register(hostid)->portsc_bit.nxp_port_speed; // NXP specific port speed
-}
-
-//--------------------------------------------------------------------+
-// Controller API
-//--------------------------------------------------------------------+
-static tusb_error_t hcd_controller_init(uint8_t hostid)
-{
- ehci_registers_t* const regs = get_operational_register(hostid);
-
- //------------- CTRLDSSEGMENT Register (skip) -------------//
- //------------- USB INT Register -------------//
- regs->usb_int_enable = 0; // 1. disable all the interrupt
-#ifndef _TEST_ // the fake controller does not have write-to-clear behavior
- regs->usb_sts = EHCI_INT_MASK_ALL; // 2. clear all status
-#endif
- regs->usb_int_enable = EHCI_INT_MASK_ERROR | EHCI_INT_MASK_PORT_CHANGE |
-#if EHCI_PERIODIC_LIST
- EHCI_INT_MASK_NXP_PERIODIC |
-#endif
- EHCI_INT_MASK_ASYNC_ADVANCE | EHCI_INT_MASK_NXP_ASYNC;
-
- //------------- Asynchronous List -------------//
- ehci_qhd_t * const async_head = get_async_head(hostid);
- memclr_(async_head, sizeof(ehci_qhd_t));
-
- async_head->next.address = (uint32_t) async_head; // circular list, next is itself
- async_head->next.type = EHCI_QUEUE_ELEMENT_QHD;
- async_head->head_list_flag = 1;
- async_head->qtd_overlay.halted = 1; // inactive most of time
- async_head->qtd_overlay.next.terminate = 1; // TODO removed if verified
-
- regs->async_list_base = (uint32_t) async_head;
-
-#if EHCI_PERIODIC_LIST
- //------------- Periodic List -------------//
- // Build the polling interval tree with 1 ms, 2 ms, 4 ms and 8 ms (framesize) only
-
- for(uint32_t i=0; i<4; i++)
- {
- ehci_data.period_head_arr[ hostid_to_data_idx(hostid) ][i].interrupt_smask = 1; // queue head in period list must have smask non-zero
- ehci_data.period_head_arr[ hostid_to_data_idx(hostid) ][i].qtd_overlay.halted = 1; // dummy node, always inactive
- }
-
- ehci_link_t * const framelist = get_period_frame_list(hostid);
- ehci_link_t * const period_1ms = get_period_head(hostid, 1);
- // all links --> period_head_arr[0] (1ms)
- // 0, 2, 4, 6 etc --> period_head_arr[1] (2ms)
- // 1, 5 --> period_head_arr[2] (4ms)
- // 3 --> period_head_arr[3] (8ms)
-
- // TODO EHCI_FRAMELIST_SIZE with other size than 8
- for(uint32_t i=0; i<EHCI_FRAMELIST_SIZE; i++)
- {
- framelist[i].address = (uint32_t) period_1ms;
- framelist[i].type = EHCI_QUEUE_ELEMENT_QHD;
- }
-
- for(uint32_t i=0; i<EHCI_FRAMELIST_SIZE; i+=2)
- {
- list_insert(framelist + i, get_period_head(hostid, 2), EHCI_QUEUE_ELEMENT_QHD);
- }
-
- for(uint32_t i=1; i<EHCI_FRAMELIST_SIZE; i+=4)
- {
- list_insert(framelist + i, get_period_head(hostid, 4), EHCI_QUEUE_ELEMENT_QHD);
- }
-
- list_insert(framelist+3, get_period_head(hostid, 8), EHCI_QUEUE_ELEMENT_QHD);
-
- period_1ms->terminate = 1;
-
- regs->periodic_list_base = (uint32_t) framelist;
-#else
- regs->periodic_list_base = 0;
-#endif
-
- //------------- TT Control (NXP only) -------------//
- regs->tt_control = 0;
-
- //------------- USB CMD Register -------------//
-
- regs->usb_cmd |= BIT_(EHCI_USBCMD_POS_RUN_STOP) | BIT_(EHCI_USBCMD_POS_ASYNC_ENABLE)
-#if EHCI_PERIODIC_LIST
- | BIT_(EHCI_USBCMD_POS_PERIOD_ENABLE) // TODO enable period list only there is int/iso endpoint
-#endif
- | ((EHCI_CFG_FRAMELIST_SIZE_BITS & BIN8(011)) << EHCI_USBCMD_POS_FRAMELIST_SZIE)
- | ((EHCI_CFG_FRAMELIST_SIZE_BITS >> 2) << EHCI_USBCMD_POS_NXP_FRAMELIST_SIZE_MSB);
-
- //------------- ConfigFlag Register (skip) -------------//
-
- regs->portsc_bit.port_power = 1; // enable port power
-
- return TUSB_ERROR_NONE;
-}
-
-static tusb_error_t hcd_controller_stop(uint8_t hostid)
-{
- ehci_registers_t* const regs = get_operational_register(hostid);
- timeout_timer_t timeout;
-
- regs->usb_cmd_bit.run_stop = 0;
-
- timeout_set(&timeout, 2); // USB Spec: controller has to stop within 16 uframe = 2 frames
- while( regs->usb_sts_bit.hc_halted == 0 && !timeout_expired(&timeout)) {}
-
- return timeout_expired(&timeout) ? TUSB_ERROR_OSAL_TIMEOUT : TUSB_ERROR_NONE;
-}
-
-tusb_error_t hcd_controller_reset(uint8_t hostid)
-{
- ehci_registers_t* const regs = get_operational_register(hostid);
- timeout_timer_t timeout;
-
-// NXP chip powered with non-host mode --> sts bit is not correctly reflected
- regs->usb_cmd_bit.reset = 1;
-
- timeout_set(&timeout, 2); // should not take longer the time to stop controller
- while( regs->usb_cmd_bit.reset && !timeout_expired(&timeout)) {}
-
- return timeout_expired(&timeout) ? TUSB_ERROR_OSAL_TIMEOUT : TUSB_ERROR_NONE;
-}
-
-//--------------------------------------------------------------------+
-// CONTROL PIPE API
-//--------------------------------------------------------------------+
-tusb_error_t hcd_pipe_control_open(uint8_t dev_addr, uint8_t max_packet_size)
-{
- ehci_qhd_t * const p_qhd = get_control_qhd(dev_addr);
-
- qhd_init(p_qhd, dev_addr, max_packet_size, 0, TUSB_XFER_CONTROL, 1); // TODO binterval of control is ignored
-
- if (dev_addr != 0)
- {
- //------------- insert to async list -------------//
- // TODO might need to to disable async list first
- list_insert( (ehci_link_t*) get_async_head(usbh_devices[dev_addr].core_id),
- (ehci_link_t*) p_qhd, EHCI_QUEUE_ELEMENT_QHD);
- }
-
- return TUSB_ERROR_NONE;
-}
-
-tusb_error_t hcd_pipe_control_xfer(uint8_t dev_addr, tusb_control_request_t const * p_request, uint8_t data[])
-{
- ehci_qhd_t * const p_qhd = get_control_qhd(dev_addr);
-
- ehci_qtd_t *p_setup = get_control_qtds(dev_addr);
- ehci_qtd_t *p_data = p_setup + 1;
- ehci_qtd_t *p_status = p_setup + 2;
-
- //------------- SETUP Phase -------------//
- qtd_init(p_setup, (uint32_t) p_request, 8);
- p_setup->pid = EHCI_PID_SETUP;
- p_setup->next.address = (uint32_t) p_data;
-
- //------------- DATA Phase -------------//
- if (p_request->wLength > 0)
- {
- qtd_init(p_data, (uint32_t) data, p_request->wLength);
- p_data->data_toggle = 1;
- p_data->pid = p_request->bmRequestType_bit.direction ? EHCI_PID_IN : EHCI_PID_OUT;
- }else
- {
- p_data = p_setup;
- }
- p_data->next.address = (uint32_t) p_status;
-
- //------------- STATUS Phase -------------//
- qtd_init(p_status, 0, 0); // zero-length data
- p_status->int_on_complete = 1;
- p_status->data_toggle = 1;
- p_status->pid = p_request->bmRequestType_bit.direction ? EHCI_PID_OUT : EHCI_PID_IN; // reverse direction of data phase
- p_status->next.terminate = 1;
-
- //------------- Attach TDs list to Control Endpoint -------------//
- p_qhd->p_qtd_list_head = p_setup;
- p_qhd->p_qtd_list_tail = p_status;
-
- p_qhd->qtd_overlay.next.address = (uint32_t) p_setup;
-
- return TUSB_ERROR_NONE;
-}
-
-tusb_error_t hcd_pipe_control_close(uint8_t dev_addr)
-{
- //------------- TODO pipe handle validate -------------//
- ehci_qhd_t * const p_qhd = get_control_qhd(dev_addr);
-
- p_qhd->is_removing = 1;
-
- if (dev_addr != 0)
- {
- ASSERT_STATUS( list_remove_qhd( (ehci_link_t*) get_async_head( usbh_devices[dev_addr].core_id ),
- (ehci_link_t*) p_qhd) );
- }
-
- return TUSB_ERROR_NONE;
-}
-
-//--------------------------------------------------------------------+
-// BULK/INT/ISO PIPE API
-//--------------------------------------------------------------------+
-pipe_handle_t hcd_pipe_open(uint8_t dev_addr, tusb_descriptor_endpoint_t const * p_endpoint_desc, uint8_t class_code)
-{
- pipe_handle_t const null_handle = { .dev_addr = 0, .xfer_type = 0, .index = 0 };
-
- ASSERT(dev_addr > 0, null_handle);
-
- if (p_endpoint_desc->bmAttributes.xfer == TUSB_XFER_ISOCHRONOUS)
- return null_handle; // TODO not support ISO yet
-
- //------------- Prepare Queue Head -------------//
- ehci_qhd_t * const p_qhd = qhd_find_free(dev_addr);
- ASSERT_PTR(p_qhd, null_handle);
-
- qhd_init( p_qhd, dev_addr, p_endpoint_desc->wMaxPacketSize.size, p_endpoint_desc->bEndpointAddress,
- p_endpoint_desc->bmAttributes.xfer, p_endpoint_desc->bInterval );
- p_qhd->class_code = class_code;
-
- //------------- Insert to Async List -------------//
- ehci_link_t * list_head;
-
- if (p_endpoint_desc->bmAttributes.xfer == TUSB_XFER_BULK)
- {
- list_head = (ehci_link_t*) get_async_head(usbh_devices[dev_addr].core_id);
- }
- #if EHCI_PERIODIC_LIST // TODO refractor/group this together
- else if (p_endpoint_desc->bmAttributes.xfer == TUSB_XFER_INTERRUPT)
- {
- list_head = get_period_head(usbh_devices[dev_addr].core_id, p_qhd->interval_ms);
- }
- #endif
-
- //------------- insert to async/period list TODO might need to disable async/period list -------------//
- list_insert( list_head,
- (ehci_link_t*) p_qhd, EHCI_QUEUE_ELEMENT_QHD);
-
- return (pipe_handle_t) { .dev_addr = dev_addr, .xfer_type = p_endpoint_desc->bmAttributes.xfer, .index = qhd_get_index(p_qhd) };
-}
-
-tusb_error_t hcd_pipe_queue_xfer(pipe_handle_t pipe_hdl, uint8_t buffer[], uint16_t total_bytes)
-{
- //------------- TODO pipe handle validate -------------//
-
- //------------- set up QTD -------------//
- ehci_qhd_t *p_qhd = qhd_get_from_pipe_handle(pipe_hdl);
- ehci_qtd_t *p_qtd = qtd_find_free(pipe_hdl.dev_addr);
-
- ASSERT_PTR(p_qtd, TUSB_ERROR_EHCI_NOT_ENOUGH_QTD);
-
- qtd_init(p_qtd, (uint32_t) buffer, total_bytes);
- p_qtd->pid = p_qhd->pid_non_control;
-
- //------------- insert TD to TD list -------------//
- qtd_insert_to_qhd(p_qhd, p_qtd);
-
- return TUSB_ERROR_NONE;
-}
-
-tusb_error_t hcd_pipe_xfer(pipe_handle_t pipe_hdl, uint8_t buffer[], uint16_t total_bytes, bool int_on_complete)
-{
- ASSERT_STATUS ( hcd_pipe_queue_xfer(pipe_hdl, buffer, total_bytes) );
-
- ehci_qhd_t *p_qhd = qhd_get_from_pipe_handle(pipe_hdl);
-
- if ( int_on_complete )
- { // the just added qtd is pointed by list_tail
- p_qhd->p_qtd_list_tail->int_on_complete = 1;
- }
- p_qhd->qtd_overlay.next.address = (uint32_t) p_qhd->p_qtd_list_head; // attach to queue head to start transferring
-
- return TUSB_ERROR_NONE;
-}
-
-/// pipe_close should only be called as a part of unmount/safe-remove process
-tusb_error_t hcd_pipe_close(pipe_handle_t pipe_hdl)
-{
- ASSERT(pipe_hdl.dev_addr > 0, TUSB_ERROR_INVALID_PARA);
-
- ASSERT(pipe_hdl.xfer_type != TUSB_XFER_ISOCHRONOUS, TUSB_ERROR_INVALID_PARA);
-
- ehci_qhd_t *p_qhd = qhd_get_from_pipe_handle( pipe_hdl );
-
- // async list needs async advance handshake to make sure host controller has released cached data
- // non-control does not use async advance, it will eventually free by control pipe close
- // period list queue element is guarantee to be free in the next frame (1 ms)
- p_qhd->is_removing = 1; // TODO redundant, only apply to control queue head
-
- if ( pipe_hdl.xfer_type == TUSB_XFER_BULK )
- {
- ASSERT_STATUS( list_remove_qhd(
- (ehci_link_t*) get_async_head( usbh_devices[pipe_hdl.dev_addr].core_id ),
- (ehci_link_t*) p_qhd) );
- }
- #if EHCI_PERIODIC_LIST // TODO refractor/group this together
- else
- {
- ASSERT_STATUS( list_remove_qhd(
- get_period_head( usbh_devices[pipe_hdl.dev_addr].core_id, p_qhd->interval_ms ),
- (ehci_link_t*) p_qhd) );
- }
- #endif
-
- return TUSB_ERROR_NONE;
-}
-
-bool hcd_pipe_is_busy(pipe_handle_t pipe_hdl)
-{
- ehci_qhd_t *p_qhd = qhd_get_from_pipe_handle( pipe_hdl );
- return !p_qhd->qtd_overlay.halted && (p_qhd->p_qtd_list_head != NULL);
-}
-
-bool hcd_pipe_is_error(pipe_handle_t pipe_hdl)
-{
- ehci_qhd_t *p_qhd = qhd_get_from_pipe_handle( pipe_hdl );
- return p_qhd->qtd_overlay.halted;
-}
-
-bool hcd_pipe_is_idle(pipe_handle_t pipe_hdl)
-{ // TODO to be remove
- ehci_qhd_t *p_qhd = qhd_get_from_pipe_handle( pipe_hdl );
- return (p_qhd->p_qtd_list_head == NULL);
-}
-
-bool hcd_pipe_is_stalled(pipe_handle_t pipe_hdl)
-{
- ehci_qhd_t *p_qhd = qhd_get_from_pipe_handle( pipe_hdl );
- return p_qhd->qtd_overlay.halted && !qhd_has_xact_error(p_qhd);
-}
-
-uint8_t hcd_pipe_get_endpoint_addr(pipe_handle_t pipe_hdl)
-{
- ehci_qhd_t *p_qhd = qhd_get_from_pipe_handle( pipe_hdl );
- return p_qhd->endpoint_number + ( (p_qhd->pid_non_control == EHCI_PID_IN) ? 0x80 : 0);
-}
-
-tusb_error_t hcd_pipe_clear_stall(pipe_handle_t pipe_hdl)
-{
- ehci_qhd_t *p_qhd = qhd_get_from_pipe_handle( pipe_hdl );
- p_qhd->qtd_overlay.halted = 0;
-
- return TUSB_ERROR_NONE;
-}
-
-//--------------------------------------------------------------------+
-// EHCI Interrupt Handler
-//--------------------------------------------------------------------+
-
-// async_advance is handshake between sw stack & ehci controller where ehci free all memory from an deleted queue head.
-// In tinyusb, queue head is only removed when device is unplugged. So only control queue head is checked if removing
-static void async_advance_isr(ehci_qhd_t * const async_head)
-{
- // TODO do we need to close addr0
- if (async_head->is_removing) // closing control pipe of addr0
- {
- async_head->is_removing = 0;
- async_head->p_qtd_list_head = async_head->p_qtd_list_tail = NULL;
- async_head->qtd_overlay.halted = 1;
-
- usbh_devices[0].state = TUSB_DEVICE_STATE_UNPLUG;
- }
-
- for(uint8_t relative_dev_addr=0; relative_dev_addr < TUSB_CFG_HOST_DEVICE_MAX; relative_dev_addr++)
- {
- // check if control endpoint is removing
- ehci_qhd_t *p_control_qhd = &ehci_data.device[relative_dev_addr].control.qhd;
- if ( p_control_qhd->is_removing )
- {
- p_control_qhd->is_removing = 0;
- p_control_qhd->used = 0;
-
- // Host Controller has cleaned up its cached data for this device, set state to unplug
- usbh_devices[relative_dev_addr+1].state = TUSB_DEVICE_STATE_UNPLUG;
-
- for (uint8_t i=0; i<EHCI_MAX_QHD; i++) // free all qhd
- {
- ehci_data.device[relative_dev_addr].qhd[i].used = 0;
- ehci_data.device[relative_dev_addr].qhd[i].is_removing = 0;
- }
- for (uint8_t i=0; i<EHCI_MAX_QTD; i++) // free all qtd
- {
- ehci_data.device[relative_dev_addr].qtd[i].used = 0;
- }
- // TODO free all itd & sitd
- }
- } // end for device[] loop
-}
-
-static void port_connect_status_change_isr(uint8_t hostid)
-{
- ehci_registers_t* const regs = get_operational_register(hostid);
-
- // NOTE There is an sequence plug->unplug->…..-> plug if device is powering with pre-plugged device
- if (regs->portsc_bit.current_connect_status)
- {
- usbh_hcd_rhport_plugged_isr(hostid);
- }else // device unplugged
- {
- usbh_hcd_rhport_unplugged_isr(hostid);
-// regs->usb_cmd_bit.advacne_async = 1; // Async doorbell check EHCI 4.8.2 for operational details
- }
-}
-
-// TODO refractor abtract later
-void hcd_port_unplug(uint8_t hostid)
-{
- ehci_registers_t* const regs = get_operational_register(hostid);
- regs->usb_cmd_bit.advacne_async = 1; // Async doorbell check EHCI 4.8.2 for operational details
-}
-
-static void qhd_xfer_complete_isr(ehci_qhd_t * p_qhd)
-{
- uint8_t max_loop = 0;
- tusb_xfer_type_t const xfer_type = qhd_get_xfer_type(p_qhd);
-
- // free all TDs from the head td to the first active TD
- while(p_qhd->p_qtd_list_head != NULL && !p_qhd->p_qtd_list_head->active
- && max_loop < EHCI_MAX_QTD)
- {
- // TD need to be freed and removed from qhd, before invoking callback
- bool is_ioc = (p_qhd->p_qtd_list_head->int_on_complete != 0);
- p_qhd->total_xferred_bytes += p_qhd->p_qtd_list_head->expected_bytes - p_qhd->p_qtd_list_head->total_bytes;
-
- p_qhd->p_qtd_list_head->used = 0; // free QTD
- qtd_remove_1st_from_qhd(p_qhd);
-
- if (is_ioc) // end of request
- { // call USBH callback
- usbh_xfer_isr( qhd_create_pipe_handle(p_qhd, xfer_type),
- p_qhd->class_code, TUSB_EVENT_XFER_COMPLETE,
- p_qhd->total_xferred_bytes - (xfer_type == TUSB_XFER_CONTROL ? 8 : 0) ); // subtract setup packet size if control,
- p_qhd->total_xferred_bytes = 0;
- }
-
- max_loop++;
- }
-}
-
-static void async_list_xfer_complete_isr(ehci_qhd_t * const async_head)
-{
- uint8_t max_loop = 0;
- ehci_qhd_t *p_qhd = async_head;
- do
- {
- if ( !p_qhd->qtd_overlay.halted ) // halted or error is processed in error isr
- {
- qhd_xfer_complete_isr(p_qhd);
- }
- p_qhd = qhd_next(p_qhd);
- max_loop++;
- }while(p_qhd != async_head && max_loop < EHCI_MAX_QHD); // async list traversal, stop if loop around
- // TODO abstract max loop guard for async
-}
-
-#if EHCI_PERIODIC_LIST // TODO refractor/group this together
-static void period_list_xfer_complete_isr(uint8_t hostid, uint8_t interval_ms)
-{
- uint8_t max_loop = 0;
- uint32_t const period_1ms_addr = (uint32_t) get_period_head(hostid, 1);
- ehci_link_t next_item = * get_period_head(hostid, interval_ms);
-
- // TODO abstract max loop guard for period
- while( !next_item.terminate &&
- !(interval_ms > 1 && period_1ms_addr == align32(next_item.address)) &&
- max_loop < (EHCI_MAX_QHD + EHCI_MAX_ITD + EHCI_MAX_SITD))
- {
- switch ( next_item.type )
- {
- case EHCI_QUEUE_ELEMENT_QHD:
- {
- ehci_qhd_t *p_qhd_int = (ehci_qhd_t *) align32(next_item.address);
- if ( !p_qhd_int->qtd_overlay.halted )
- {
- qhd_xfer_complete_isr(p_qhd_int);
- }
- }
- break;
-
- case EHCI_QUEUE_ELEMENT_ITD:
- case EHCI_QUEUE_ELEMENT_SITD:
- case EHCI_QUEUE_ELEMENT_FSTN:
- default:
- ASSERT (false, VOID_RETURN); // TODO support hs/fs ISO
- break;
- }
-
- next_item = *list_next(&next_item);
- max_loop++;
- }
-}
-#endif
-
-static void qhd_xfer_error_isr(ehci_qhd_t * p_qhd)
-{
- if ( (p_qhd->device_address != 0 && p_qhd->qtd_overlay.halted) || // addr0 cannot be protocol STALL
- qhd_has_xact_error(p_qhd) )
- { // current qhd has error in transaction
- tusb_xfer_type_t const xfer_type = qhd_get_xfer_type(p_qhd);
- tusb_event_t error_event;
-
- // no error bits are set, endpoint is halted due to STALL
- error_event = qhd_has_xact_error(p_qhd) ? TUSB_EVENT_XFER_ERROR : TUSB_EVENT_XFER_STALLED;
-
- p_qhd->total_xferred_bytes += p_qhd->p_qtd_list_head->expected_bytes - p_qhd->p_qtd_list_head->total_bytes;
-
- // TODO skip unplugged device
- if ( TUSB_EVENT_XFER_ERROR == error_event ) hal_debugger_breakpoint();
-
- p_qhd->p_qtd_list_head->used = 0; // free QTD
- qtd_remove_1st_from_qhd(p_qhd);
-
- if ( TUSB_XFER_CONTROL == xfer_type )
- {
- p_qhd->total_xferred_bytes -= min8_of(8, p_qhd->total_xferred_bytes); // subtract setup size
-
- // control cannot be halted --> clear all qtd list
- p_qhd->p_qtd_list_head = NULL;
- p_qhd->p_qtd_list_tail = NULL;
-
- p_qhd->qtd_overlay.next.terminate = 1;
- p_qhd->qtd_overlay.alternate.terminate = 1;
- p_qhd->qtd_overlay.halted = 0;
-
- ehci_qtd_t *p_setup = get_control_qtds(p_qhd->device_address);
- ehci_qtd_t *p_data = p_setup + 1;
- ehci_qtd_t *p_status = p_setup + 2;
-
- p_setup->used = p_data->used = p_status->used = 0;
- }
-
- // call USBH callback
- usbh_xfer_isr( qhd_create_pipe_handle(p_qhd, xfer_type),
- p_qhd->class_code, error_event,
- p_qhd->total_xferred_bytes);
-
- p_qhd->total_xferred_bytes = 0;
- }
-}
-
-static void xfer_error_isr(uint8_t hostid)
-{
- //------------- async list -------------//
- uint8_t max_loop = 0;
- ehci_qhd_t * const async_head = get_async_head(hostid);
- ehci_qhd_t *p_qhd = async_head;
- do
- {
- qhd_xfer_error_isr( p_qhd );
- p_qhd = qhd_next(p_qhd);
- max_loop++;
- }while(p_qhd != async_head && max_loop < EHCI_MAX_QHD); // async list traversal, stop if loop around
-
- #if EHCI_PERIODIC_LIST
- //------------- TODO refractor period list -------------//
- uint32_t const period_1ms_addr = (uint32_t) get_period_head(hostid, 1);
- for (uint8_t interval_ms=1; interval_ms <= EHCI_FRAMELIST_SIZE; interval_ms *= 2)
- {
- uint8_t period_max_loop = 0;
- ehci_link_t next_item = * get_period_head(hostid, interval_ms);
-
- // TODO abstract max loop guard for period
- while( !next_item.terminate &&
- !(interval_ms > 1 && period_1ms_addr == align32(next_item.address)) &&
- period_max_loop < (EHCI_MAX_QHD + EHCI_MAX_ITD + EHCI_MAX_SITD))
- {
- switch ( next_item.type )
- {
- case EHCI_QUEUE_ELEMENT_QHD:
- {
- ehci_qhd_t *p_qhd_int = (ehci_qhd_t *) align32(next_item.address);
- qhd_xfer_error_isr(p_qhd_int);
- }
- break;
-
- case EHCI_QUEUE_ELEMENT_ITD:
- case EHCI_QUEUE_ELEMENT_SITD:
- case EHCI_QUEUE_ELEMENT_FSTN:
- default:
- ASSERT (false, VOID_RETURN); // TODO support hs/fs ISO
- break;
- }
-
- next_item = *list_next(&next_item);
- period_max_loop++;
- }
- }
- #endif
-}
-
-//------------- Host Controller Driver's Interrupt Handler -------------//
-void hcd_isr(uint8_t hostid)
-{
- ehci_registers_t* const regs = get_operational_register(hostid);
-
- uint32_t int_status = regs->usb_sts;
- int_status &= regs->usb_int_enable;
-
- regs->usb_sts |= int_status; // Acknowledge handled interrupt
-
- if (int_status == 0)
- return;
-
- if (int_status & EHCI_INT_MASK_PORT_CHANGE)
- {
- uint32_t port_status = regs->portsc & EHCI_PORTSC_MASK_ALL;
-
- if (regs->portsc_bit.connect_status_change)
- {
- port_connect_status_change_isr(hostid);
- }
-
- regs->portsc |= port_status; // Acknowledge change bits in portsc
- }
-
- if (int_status & EHCI_INT_MASK_ERROR)
- {
- xfer_error_isr(hostid);
- }
-
- //------------- some QTD/SITD/ITD with IOC set is completed -------------//
- if (int_status & EHCI_INT_MASK_NXP_ASYNC)
- {
- async_list_xfer_complete_isr( get_async_head(hostid) );
- }
-
-#if EHCI_PERIODIC_LIST // TODO refractor/group this together
- if (int_status & EHCI_INT_MASK_NXP_PERIODIC)
- {
- for (uint8_t i=1; i <= EHCI_FRAMELIST_SIZE; i *= 2)
- {
- period_list_xfer_complete_isr( hostid, i );
- }
- }
-#endif
-
- //------------- There is some removed async previously -------------//
- if (int_status & EHCI_INT_MASK_ASYNC_ADVANCE) // need to place after EHCI_INT_MASK_NXP_ASYNC
- {
- async_advance_isr( get_async_head(hostid) );
- }
-}
-
-//--------------------------------------------------------------------+
-// HELPER
-//--------------------------------------------------------------------+
-STATIC_ INLINE_ ehci_registers_t* get_operational_register(uint8_t hostid)
-{
- return (ehci_registers_t*) (hostid ? (&LPC_USB1->USBCMD_H) : (&LPC_USB0->USBCMD_H) );
-}
-
-#if EHCI_PERIODIC_LIST // TODO refractor/group this together
-STATIC_ INLINE_ ehci_link_t* get_period_frame_list(uint8_t hostid)
-{
- switch(hostid)
- {
-#if (TUSB_CFG_CONTROLLER0_MODE & TUSB_MODE_HOST)
- case 0:
- return period_frame_list0;
-#endif
-
-#if (TUSB_CFG_CONTROLLER1_MODE & TUSB_MODE_HOST)
- case 1:
- return period_frame_list1;
-#endif
-
- default: return NULL;
- }
-}
-#endif
-
-STATIC_ INLINE_ uint8_t hostid_to_data_idx(uint8_t hostid)
-{
- #if (CONTROLLER_HOST_NUMBER == 1) && (TUSB_CFG_CONTROLLER1_MODE & TUSB_MODE_HOST)
- (void) hostid;
- return 0;
- #else
- return hostid;
- #endif
-}
-
-//------------- queue head helper -------------//
-STATIC_ INLINE_ ehci_qhd_t* get_async_head(uint8_t hostid)
-{
- return &ehci_data.async_head[ hostid_to_data_idx(hostid) ];
-}
-
-#if EHCI_PERIODIC_LIST // TODO refractor/group this together
-STATIC_ INLINE_ ehci_link_t* get_period_head(uint8_t hostid, uint8_t interval_ms)
-{
- return (ehci_link_t*) (&ehci_data.period_head_arr[ hostid_to_data_idx(hostid) ]
- [ log2_of( min8_of(EHCI_FRAMELIST_SIZE, interval_ms) ) ] );
-}
-#endif
-
-STATIC_ INLINE_ ehci_qhd_t* get_control_qhd(uint8_t dev_addr)
-{
- return (dev_addr == 0) ?
- get_async_head( usbh_devices[dev_addr].core_id ) :
- &ehci_data.device[dev_addr-1].control.qhd;
-}
-STATIC_ INLINE_ ehci_qtd_t* get_control_qtds(uint8_t dev_addr)
-{
- return (dev_addr == 0) ?
- ehci_data.addr0_qtd :
- ehci_data.device[ dev_addr-1 ].control.qtd;
-
-}
-
-static inline ehci_qhd_t* qhd_find_free (uint8_t dev_addr)
-{
- uint8_t relative_address = dev_addr-1;
- uint8_t index=0;
- while( index<EHCI_MAX_QHD && ehci_data.device[relative_address].qhd[index].used )
- {
- index++;
- }
- return (index < EHCI_MAX_QHD) ? &ehci_data.device[relative_address].qhd[index] : NULL;
-}
-
-static inline uint8_t qhd_get_index(ehci_qhd_t const * p_qhd)
-{
- return p_qhd - ehci_data.device[p_qhd->device_address-1].qhd;
-}
-static inline tusb_xfer_type_t qhd_get_xfer_type(ehci_qhd_t const * p_qhd)
-{
- return ( p_qhd->endpoint_number == 0 ) ? TUSB_XFER_CONTROL :
- ( p_qhd->interrupt_smask != 0 ) ? TUSB_XFER_INTERRUPT : TUSB_XFER_BULK;
-}
-
-static inline ehci_qhd_t* qhd_next(ehci_qhd_t const * p_qhd)
-{
- return (ehci_qhd_t*) align32(p_qhd->next.address);
-}
-
-STATIC_ INLINE_ ehci_qhd_t* qhd_get_from_pipe_handle(pipe_handle_t pipe_hdl)
-{
- return &ehci_data.device[ pipe_hdl.dev_addr-1 ].qhd[ pipe_hdl.index ];
-}
-
-static inline pipe_handle_t qhd_create_pipe_handle(ehci_qhd_t const * p_qhd, tusb_xfer_type_t xfer_type)
-{
- pipe_handle_t pipe_hdl = {
- .dev_addr = p_qhd->device_address,
- .xfer_type = xfer_type
- };
-
- // TODO Isochronous transfer support
- if (TUSB_XFER_CONTROL != xfer_type) // qhd index for control is meaningless
- {
- pipe_hdl.index = qhd_get_index(p_qhd);
- }
-
- return pipe_hdl;
-}
-
-//------------- TD helper -------------//
-STATIC_ INLINE_ ehci_qtd_t* qtd_find_free(uint8_t dev_addr)
-{
- uint8_t index=0;
- while( index<EHCI_MAX_QTD && ehci_data.device[dev_addr-1].qtd[index].used )
- {
- index++;
- }
-
- return (index < EHCI_MAX_QTD) ? &ehci_data.device[dev_addr-1].qtd[index] : NULL;
-}
-
-static inline ehci_qtd_t* qtd_next(ehci_qtd_t const * p_qtd )
-{
- return (ehci_qtd_t*) align32(p_qtd->next.address);
-}
-
-static inline void qtd_remove_1st_from_qhd(ehci_qhd_t *p_qhd)
-{
- if (p_qhd->p_qtd_list_head == p_qhd->p_qtd_list_tail) // last TD --> make it NULL
- {
- p_qhd->p_qtd_list_head = p_qhd->p_qtd_list_tail = NULL;
- }else
- {
- p_qhd->p_qtd_list_head = qtd_next( p_qhd->p_qtd_list_head );
- }
-}
-
-static inline void qtd_insert_to_qhd(ehci_qhd_t *p_qhd, ehci_qtd_t *p_qtd_new)
-{
- if (p_qhd->p_qtd_list_head == NULL) // empty list
- {
- p_qhd->p_qtd_list_head = p_qhd->p_qtd_list_tail = p_qtd_new;
- }else
- {
- p_qhd->p_qtd_list_tail->next.address = (uint32_t) p_qtd_new;
- p_qhd->p_qtd_list_tail = p_qtd_new;
- }
-}
-
-static void qhd_init(ehci_qhd_t *p_qhd, uint8_t dev_addr, uint16_t max_packet_size, uint8_t endpoint_addr, uint8_t xfer_type, uint8_t interval)
-{
- // address 0 uses async head, which always on the list --> cannot be cleared (ehci halted otherwise)
- if (dev_addr != 0)
- {
- memclr_(p_qhd, sizeof(ehci_qhd_t));
- }
-
- p_qhd->device_address = dev_addr;
- p_qhd->non_hs_period_inactive_next_xact = 0;
- p_qhd->endpoint_number = endpoint_addr & 0x0F;
- p_qhd->endpoint_speed = usbh_devices[dev_addr].speed;
- p_qhd->data_toggle_control = (xfer_type == TUSB_XFER_CONTROL) ? 1 : 0;
- p_qhd->head_list_flag = (dev_addr == 0) ? 1 : 0; // addr0's endpoint is the static asyn list head
- p_qhd->max_package_size = max_packet_size;
- p_qhd->non_hs_control_endpoint = ((TUSB_XFER_CONTROL == xfer_type) && (p_qhd->endpoint_speed != TUSB_SPEED_HIGH)) ? 1 : 0;
- p_qhd->nak_count_reload = 0;
-
- // Bulk/Control -> smask = cmask = 0
- // TODO Isochronous
- if (TUSB_XFER_INTERRUPT == xfer_type)
- {
- if (TUSB_SPEED_HIGH == p_qhd->endpoint_speed)
- {
- ASSERT_INT_WITHIN(1, 16, interval, VOID_RETURN);
- if ( interval < 4) // sub milisecond interval
- {
- p_qhd->interval_ms = 0;
- p_qhd->interrupt_smask = (interval == 1) ? BIN8(11111111) :
- (interval == 2) ? BIN8(10101010) : BIN8(01000100);
- }else
- {
- p_qhd->interval_ms = (uint8_t) min16_of( 1 << (interval-4), 255 );
- p_qhd->interrupt_smask = BIT_(interval % 8);
- }
- }else
- {
- ASSERT( 0 != interval, VOID_RETURN);
- // Full/Low: 4.12.2.1 (EHCI) case 1 schedule start split at 1 us & complete split at 2,3,4 uframes
- p_qhd->interrupt_smask = 0x01;
- p_qhd->non_hs_interrupt_cmask = BIN8(11100);
- p_qhd->interval_ms = interval;
- }
- }else
- {
- p_qhd->interrupt_smask = p_qhd->non_hs_interrupt_cmask = 0;
- }
-
- p_qhd->hub_address = usbh_devices[dev_addr].hub_addr;
- p_qhd->hub_port = usbh_devices[dev_addr].hub_port;
- p_qhd->mult = 1; // TODO not use high bandwidth/park mode yet
-
- //------------- HCD Management Data -------------//
- p_qhd->used = 1;
- p_qhd->is_removing = 0;
- p_qhd->p_qtd_list_head = NULL;
- p_qhd->p_qtd_list_tail = NULL;
- p_qhd->pid_non_control = (endpoint_addr & 0x80) ? EHCI_PID_IN : EHCI_PID_OUT; // PID for TD under this endpoint
-
- //------------- active, but no TD list -------------//
- p_qhd->qtd_overlay.halted = 0;
- p_qhd->qtd_overlay.next.terminate = 1;
- p_qhd->qtd_overlay.alternate.terminate = 1;
- if (TUSB_XFER_BULK == xfer_type && p_qhd->endpoint_speed == TUSB_SPEED_HIGH && p_qhd->pid_non_control == EHCI_PID_OUT)
- {
- p_qhd->qtd_overlay.pingstate_err = 1; // do PING for Highspeed Bulk OUT, EHCI section 4.11
- }
-}
-
-static void qtd_init(ehci_qtd_t* p_qtd, uint32_t data_ptr, uint16_t total_bytes)
-{
- memclr_(p_qtd, sizeof(ehci_qtd_t));
-
- p_qtd->used = 1;
-
- p_qtd->next.terminate = 1; // init to null
- p_qtd->alternate.terminate = 1; // not used, always set to terminated
- p_qtd->active = 1;
- p_qtd->cerr = 3; // TODO 3 consecutive errors tolerance
- p_qtd->data_toggle = 0;
- p_qtd->total_bytes = total_bytes;
- p_qtd->expected_bytes = total_bytes;
-
- p_qtd->buffer[0] = data_ptr;
- for(uint8_t i=1; i<5; i++)
- {
- p_qtd->buffer[i] |= align4k( p_qtd->buffer[i-1] ) + 4096;
- }
-}
-
-//------------- List Managing Helper -------------//
-static inline void list_insert(ehci_link_t *current, ehci_link_t *new, uint8_t new_type)
-{
- new->address = current->address;
- current->address = ((uint32_t) new) | (new_type << 1);
-}
-
-static inline ehci_link_t* list_next(ehci_link_t *p_link_pointer)
-{
- return (ehci_link_t*) align32(p_link_pointer->address);
-}
-
-static ehci_link_t* list_find_previous_item(ehci_link_t* p_head, ehci_link_t* p_current)
-{
- ehci_link_t *p_prev = p_head;
- uint32_t max_loop = 0;
- while( (align32(p_prev->address) != (uint32_t) p_head) && // not loop around
- (align32(p_prev->address) != (uint32_t) p_current) && // not found yet
- !p_prev->terminate && // not advanceable
- max_loop < EHCI_MAX_QHD)
- {
- p_prev = list_next(p_prev);
- max_loop++;
- }
-
- return (align32(p_prev->address) != (uint32_t) p_head) ? p_prev : NULL;
-}
-
-static tusb_error_t list_remove_qhd(ehci_link_t* p_head, ehci_link_t* p_remove)
-{
- ehci_link_t *p_prev = list_find_previous_item(p_head, p_remove);
-
- ASSERT_PTR(p_prev, TUSB_ERROR_INVALID_PARA);
-
- p_prev->address = p_remove->address;
- // EHCI 4.8.2 link the removing queue head to async/period head (which always reachable by Host Controller)
- p_remove->address = ((uint32_t) p_head) | (EHCI_QUEUE_ELEMENT_QHD << 1);
-
- return TUSB_ERROR_NONE;
-}
-
-#endif
+/**************************************************************************/
+/*!
+ @file ehci.c
+ @author hathach (tinyusb.org)
+
+ @section LICENSE
+
+ Software License Agreement (BSD License)
+
+ Copyright (c) 2013, hathach (tinyusb.org)
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ 3. Neither the name of the copyright holders nor the
+ names of its contributors may be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
+ EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
+ DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION HOWEVER CAUSED AND
+ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ INCLUDING NEGLIGENCE OR OTHERWISE ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ This file is part of the tinyusb stack.
+*/
+/**************************************************************************/
+
+#include "common/common.h"
+
+#if MODE_HOST_SUPPORTED && (MCU == MCU_LPC43XX || MCU == MCU_LPC18XX)
+//--------------------------------------------------------------------+
+// INCLUDE
+//--------------------------------------------------------------------+
+#include "hal/hal.h"
+#include "osal/osal.h"
+#include "common/timeout_timer.h"
+
+#include "../hcd.h"
+#include "../usbh_hcd.h"
+#include "ehci.h"
+
+//--------------------------------------------------------------------+
+// MACRO CONSTANT TYPEDEF
+//--------------------------------------------------------------------+
+
+//--------------------------------------------------------------------+
+// INTERNAL OBJECT & FUNCTION DECLARATION
+//--------------------------------------------------------------------+
+STATIC_VAR ehci_data_t ehci_data TUSB_CFG_ATTR_USBRAM;
+
+#if EHCI_PERIODIC_LIST
+
+ #if (TUSB_CFG_CONTROLLER_0_MODE & TUSB_MODE_HOST)
+ ATTR_ALIGNED(4096) STATIC_VAR ehci_link_t period_frame_list0[EHCI_FRAMELIST_SIZE] TUSB_CFG_ATTR_USBRAM;
+
+ #ifndef __ICCARM__ // IAR cannot able to determine the alignment with datalignment pragma
+ STATIC_ASSERT( ALIGN_OF(period_frame_list0) == 4096, "Period Framelist must be 4k alginment"); // validation
+ #endif
+ #endif
+
+ #if (TUSB_CFG_CONTROLLER_1_MODE & TUSB_MODE_HOST)
+ STATIC_VAR ehci_link_t period_frame_list1[EHCI_FRAMELIST_SIZE] ATTR_ALIGNED(4096) TUSB_CFG_ATTR_USBRAM;
+
+ #ifndef __ICCARM__ // IAR cannot able to determine the alignment with datalignment pragma
+ STATIC_ASSERT( ALIGN_OF(period_frame_list1) == 4096, "Period Framelist must be 4k alginment"); // validation
+ #endif
+ #endif
+#endif
+
+//------------- Validation -------------//
+// TODO static assert for memory placement on some known MCU such as lpc43xx
+
+//--------------------------------------------------------------------+
+// PROTOTYPE
+//--------------------------------------------------------------------+
+STATIC_ INLINE_ ehci_registers_t* get_operational_register(uint8_t hostid) ATTR_PURE ATTR_ALWAYS_INLINE ATTR_WARN_UNUSED_RESULT;
+STATIC_ INLINE_ ehci_link_t* get_period_frame_list(uint8_t hostid) ATTR_PURE ATTR_ALWAYS_INLINE ATTR_WARN_UNUSED_RESULT;
+STATIC_ INLINE_ uint8_t hostid_to_data_idx(uint8_t hostid) ATTR_ALWAYS_INLINE ATTR_CONST ATTR_WARN_UNUSED_RESULT;
+
+STATIC_ INLINE_ ehci_qhd_t* get_async_head(uint8_t hostid) ATTR_ALWAYS_INLINE ATTR_PURE ATTR_WARN_UNUSED_RESULT;
+STATIC_ INLINE_ ehci_link_t* get_period_head(uint8_t hostid, uint8_t interval_ms) ATTR_ALWAYS_INLINE ATTR_PURE ATTR_WARN_UNUSED_RESULT;
+
+STATIC_ INLINE_ ehci_qhd_t* get_control_qhd(uint8_t dev_addr) ATTR_ALWAYS_INLINE ATTR_PURE ATTR_WARN_UNUSED_RESULT;
+STATIC_ INLINE_ ehci_qtd_t* get_control_qtds(uint8_t dev_addr) ATTR_ALWAYS_INLINE ATTR_PURE ATTR_WARN_UNUSED_RESULT;
+
+static inline uint8_t qhd_get_index(ehci_qhd_t const * p_qhd) ATTR_ALWAYS_INLINE ATTR_PURE;
+static inline ehci_qhd_t* qhd_next(ehci_qhd_t const * p_qhd) ATTR_ALWAYS_INLINE ATTR_PURE;
+static inline ehci_qhd_t* qhd_find_free (uint8_t dev_addr) ATTR_PURE ATTR_ALWAYS_INLINE;
+static inline tusb_xfer_type_t qhd_get_xfer_type(ehci_qhd_t const * p_qhd) ATTR_ALWAYS_INLINE ATTR_PURE;
+STATIC_ INLINE_ ehci_qhd_t* qhd_get_from_pipe_handle(pipe_handle_t pipe_hdl) ATTR_PURE ATTR_ALWAYS_INLINE;
+static inline pipe_handle_t qhd_create_pipe_handle(ehci_qhd_t const * p_qhd, tusb_xfer_type_t xfer_type) ATTR_PURE ATTR_ALWAYS_INLINE;
+// determine if a queue head has bus-related error
+static inline bool qhd_has_xact_error(ehci_qhd_t * p_qhd) ATTR_ALWAYS_INLINE ATTR_PURE;
+static inline bool qhd_has_xact_error(ehci_qhd_t * p_qhd)
+{
+ return ( p_qhd->qtd_overlay.buffer_err ||p_qhd->qtd_overlay.babble_err || p_qhd->qtd_overlay.xact_err );
+ //p_qhd->qtd_overlay.non_hs_period_missed_uframe || p_qhd->qtd_overlay.pingstate_err TODO split transaction error
+}
+
+static void qhd_init(ehci_qhd_t *p_qhd, uint8_t dev_addr, uint16_t max_packet_size, uint8_t endpoint_addr, uint8_t xfer_type, uint8_t interval);
+
+
+STATIC_ INLINE_ ehci_qtd_t* qtd_find_free(uint8_t dev_addr) ATTR_PURE ATTR_ALWAYS_INLINE;
+static inline ehci_qtd_t* qtd_next(ehci_qtd_t const * p_qtd ) ATTR_PURE ATTR_ALWAYS_INLINE;
+static inline void qtd_insert_to_qhd(ehci_qhd_t *p_qhd, ehci_qtd_t *p_qtd_new) ATTR_ALWAYS_INLINE;
+static inline void qtd_remove_1st_from_qhd(ehci_qhd_t *p_qhd) ATTR_ALWAYS_INLINE;
+static void qtd_init(ehci_qtd_t* p_qtd, uint32_t data_ptr, uint16_t total_bytes);
+
+static inline void list_insert(ehci_link_t *current, ehci_link_t *new, uint8_t new_type) ATTR_ALWAYS_INLINE;
+static inline ehci_link_t* list_next(ehci_link_t *p_link_pointer) ATTR_PURE ATTR_ALWAYS_INLINE;
+static ehci_link_t* list_find_previous_item(ehci_link_t* p_head, ehci_link_t* p_current);
+static tusb_error_t list_remove_qhd(ehci_link_t* p_head, ehci_link_t* p_remove);
+
+static tusb_error_t hcd_controller_init(uint8_t hostid) ATTR_WARN_UNUSED_RESULT;
+static tusb_error_t hcd_controller_stop(uint8_t hostid) ATTR_WARN_UNUSED_RESULT;
+
+//--------------------------------------------------------------------+
+// USBH-HCD API
+//--------------------------------------------------------------------+
+tusb_error_t hcd_init(void)
+{
+ //------------- Data Structure init -------------//
+ memclr_(&ehci_data, sizeof(ehci_data_t));
+
+ #if (TUSB_CFG_CONTROLLER_0_MODE & TUSB_MODE_HOST)
+ ASSERT_STATUS (hcd_controller_init(0));
+ #endif
+
+ #if (TUSB_CFG_CONTROLLER_1_MODE & TUSB_MODE_HOST)
+ ASSERT_STATUS (hcd_controller_init(1));
+ #endif
+
+ return TUSB_ERROR_NONE;
+}
+
+//--------------------------------------------------------------------+
+// PORT API
+//--------------------------------------------------------------------+
+void hcd_port_reset(uint8_t hostid)
+{
+ ehci_registers_t* const regs = get_operational_register(hostid);
+
+ regs->portsc_bit.port_enable = 0; // disable port before reset
+ regs->portsc_bit.port_reset = 1;
+
+#ifndef _TEST_
+ // NXP specific, port reset will automatically be 0 when reset sequence complete
+ // there is chance device is unplugged while reset sequence is not complete
+ while( regs->portsc_bit.port_reset) {} // TODO use task delay to remove blocking
+#endif
+}
+
+bool hcd_port_connect_status(uint8_t hostid)
+{
+ return get_operational_register(hostid)->portsc_bit.current_connect_status;
+}
+
+tusb_speed_t hcd_port_speed_get(uint8_t hostid)
+{
+ return (tusb_speed_t) get_operational_register(hostid)->portsc_bit.nxp_port_speed; // NXP specific port speed
+}
+
+//--------------------------------------------------------------------+
+// Controller API
+//--------------------------------------------------------------------+
+static tusb_error_t hcd_controller_init(uint8_t hostid)
+{
+ ehci_registers_t* const regs = get_operational_register(hostid);
+
+ //------------- CTRLDSSEGMENT Register (skip) -------------//
+ //------------- USB INT Register -------------//
+ regs->usb_int_enable = 0; // 1. disable all the interrupt
+#ifndef _TEST_ // the fake controller does not have write-to-clear behavior
+ regs->usb_sts = EHCI_INT_MASK_ALL; // 2. clear all status
+#endif
+ regs->usb_int_enable = EHCI_INT_MASK_ERROR | EHCI_INT_MASK_PORT_CHANGE |
+#if EHCI_PERIODIC_LIST
+ EHCI_INT_MASK_NXP_PERIODIC |
+#endif
+ EHCI_INT_MASK_ASYNC_ADVANCE | EHCI_INT_MASK_NXP_ASYNC;
+
+ //------------- Asynchronous List -------------//
+ ehci_qhd_t * const async_head = get_async_head(hostid);
+ memclr_(async_head, sizeof(ehci_qhd_t));
+
+ async_head->next.address = (uint32_t) async_head; // circular list, next is itself
+ async_head->next.type = EHCI_QUEUE_ELEMENT_QHD;
+ async_head->head_list_flag = 1;
+ async_head->qtd_overlay.halted = 1; // inactive most of time
+ async_head->qtd_overlay.next.terminate = 1; // TODO removed if verified
+
+ regs->async_list_base = (uint32_t) async_head;
+
+#if EHCI_PERIODIC_LIST
+ //------------- Periodic List -------------//
+ // Build the polling interval tree with 1 ms, 2 ms, 4 ms and 8 ms (framesize) only
+
+ for(uint32_t i=0; i<4; i++)
+ {
+ ehci_data.period_head_arr[ hostid_to_data_idx(hostid) ][i].interrupt_smask = 1; // queue head in period list must have smask non-zero
+ ehci_data.period_head_arr[ hostid_to_data_idx(hostid) ][i].qtd_overlay.halted = 1; // dummy node, always inactive
+ }
+
+ ehci_link_t * const framelist = get_period_frame_list(hostid);
+ ehci_link_t * const period_1ms = get_period_head(hostid, 1);
+ // all links --> period_head_arr[0] (1ms)
+ // 0, 2, 4, 6 etc --> period_head_arr[1] (2ms)
+ // 1, 5 --> period_head_arr[2] (4ms)
+ // 3 --> period_head_arr[3] (8ms)
+
+ // TODO EHCI_FRAMELIST_SIZE with other size than 8
+ for(uint32_t i=0; i<EHCI_FRAMELIST_SIZE; i++)
+ {
+ framelist[i].address = (uint32_t) period_1ms;
+ framelist[i].type = EHCI_QUEUE_ELEMENT_QHD;
+ }
+
+ for(uint32_t i=0; i<EHCI_FRAMELIST_SIZE; i+=2)
+ {
+ list_insert(framelist + i, get_period_head(hostid, 2), EHCI_QUEUE_ELEMENT_QHD);
+ }
+
+ for(uint32_t i=1; i<EHCI_FRAMELIST_SIZE; i+=4)
+ {
+ list_insert(framelist + i, get_period_head(hostid, 4), EHCI_QUEUE_ELEMENT_QHD);
+ }
+
+ list_insert(framelist+3, get_period_head(hostid, 8), EHCI_QUEUE_ELEMENT_QHD);
+
+ period_1ms->terminate = 1;
+
+ regs->periodic_list_base = (uint32_t) framelist;
+#else
+ regs->periodic_list_base = 0;
+#endif
+
+ //------------- TT Control (NXP only) -------------//
+ regs->tt_control = 0;
+
+ //------------- USB CMD Register -------------//
+
+ regs->usb_cmd |= BIT_(EHCI_USBCMD_POS_RUN_STOP) | BIT_(EHCI_USBCMD_POS_ASYNC_ENABLE)
+#if EHCI_PERIODIC_LIST
+ | BIT_(EHCI_USBCMD_POS_PERIOD_ENABLE) // TODO enable period list only there is int/iso endpoint
+#endif
+ | ((EHCI_CFG_FRAMELIST_SIZE_BITS & BIN8(011)) << EHCI_USBCMD_POS_FRAMELIST_SZIE)
+ | ((EHCI_CFG_FRAMELIST_SIZE_BITS >> 2) << EHCI_USBCMD_POS_NXP_FRAMELIST_SIZE_MSB);
+
+ //------------- ConfigFlag Register (skip) -------------//
+
+ regs->portsc_bit.port_power = 1; // enable port power
+
+ return TUSB_ERROR_NONE;
+}
+
+static tusb_error_t hcd_controller_stop(uint8_t hostid)
+{
+ ehci_registers_t* const regs = get_operational_register(hostid);
+ timeout_timer_t timeout;
+
+ regs->usb_cmd_bit.run_stop = 0;
+
+ timeout_set(&timeout, 2); // USB Spec: controller has to stop within 16 uframe = 2 frames
+ while( regs->usb_sts_bit.hc_halted == 0 && !timeout_expired(&timeout)) {}
+
+ return timeout_expired(&timeout) ? TUSB_ERROR_OSAL_TIMEOUT : TUSB_ERROR_NONE;
+}
+
+tusb_error_t hcd_controller_reset(uint8_t hostid)
+{
+ ehci_registers_t* const regs = get_operational_register(hostid);
+ timeout_timer_t timeout;
+
+// NXP chip powered with non-host mode --> sts bit is not correctly reflected
+ regs->usb_cmd_bit.reset = 1;
+
+ timeout_set(&timeout, 2); // should not take longer the time to stop controller
+ while( regs->usb_cmd_bit.reset && !timeout_expired(&timeout)) {}
+
+ return timeout_expired(&timeout) ? TUSB_ERROR_OSAL_TIMEOUT : TUSB_ERROR_NONE;
+}
+
+//--------------------------------------------------------------------+
+// CONTROL PIPE API
+//--------------------------------------------------------------------+
+tusb_error_t hcd_pipe_control_open(uint8_t dev_addr, uint8_t max_packet_size)
+{
+ ehci_qhd_t * const p_qhd = get_control_qhd(dev_addr);
+
+ qhd_init(p_qhd, dev_addr, max_packet_size, 0, TUSB_XFER_CONTROL, 1); // TODO binterval of control is ignored
+
+ if (dev_addr != 0)
+ {
+ //------------- insert to async list -------------//
+ // TODO might need to to disable async list first
+ list_insert( (ehci_link_t*) get_async_head(usbh_devices[dev_addr].core_id),
+ (ehci_link_t*) p_qhd, EHCI_QUEUE_ELEMENT_QHD);
+ }
+
+ return TUSB_ERROR_NONE;
+}
+
+tusb_error_t hcd_pipe_control_xfer(uint8_t dev_addr, tusb_control_request_t const * p_request, uint8_t data[])
+{
+ ehci_qhd_t * const p_qhd = get_control_qhd(dev_addr);
+
+ ehci_qtd_t *p_setup = get_control_qtds(dev_addr);
+ ehci_qtd_t *p_data = p_setup + 1;
+ ehci_qtd_t *p_status = p_setup + 2;
+
+ //------------- SETUP Phase -------------//
+ qtd_init(p_setup, (uint32_t) p_request, 8);
+ p_setup->pid = EHCI_PID_SETUP;
+ p_setup->next.address = (uint32_t) p_data;
+
+ //------------- DATA Phase -------------//
+ if (p_request->wLength > 0)
+ {
+ qtd_init(p_data, (uint32_t) data, p_request->wLength);
+ p_data->data_toggle = 1;
+ p_data->pid = p_request->bmRequestType_bit.direction ? EHCI_PID_IN : EHCI_PID_OUT;
+ }else
+ {
+ p_data = p_setup;
+ }
+ p_data->next.address = (uint32_t) p_status;
+
+ //------------- STATUS Phase -------------//
+ qtd_init(p_status, 0, 0); // zero-length data
+ p_status->int_on_complete = 1;
+ p_status->data_toggle = 1;
+ p_status->pid = p_request->bmRequestType_bit.direction ? EHCI_PID_OUT : EHCI_PID_IN; // reverse direction of data phase
+ p_status->next.terminate = 1;
+
+ //------------- Attach TDs list to Control Endpoint -------------//
+ p_qhd->p_qtd_list_head = p_setup;
+ p_qhd->p_qtd_list_tail = p_status;
+
+ p_qhd->qtd_overlay.next.address = (uint32_t) p_setup;
+
+ return TUSB_ERROR_NONE;
+}
+
+tusb_error_t hcd_pipe_control_close(uint8_t dev_addr)
+{
+ //------------- TODO pipe handle validate -------------//
+ ehci_qhd_t * const p_qhd = get_control_qhd(dev_addr);
+
+ p_qhd->is_removing = 1;
+
+ if (dev_addr != 0)
+ {
+ ASSERT_STATUS( list_remove_qhd( (ehci_link_t*) get_async_head( usbh_devices[dev_addr].core_id ),
+ (ehci_link_t*) p_qhd) );
+ }
+
+ return TUSB_ERROR_NONE;
+}
+
+//--------------------------------------------------------------------+
+// BULK/INT/ISO PIPE API
+//--------------------------------------------------------------------+
+pipe_handle_t hcd_pipe_open(uint8_t dev_addr, tusb_descriptor_endpoint_t const * p_endpoint_desc, uint8_t class_code)
+{
+ pipe_handle_t const null_handle = { .dev_addr = 0, .xfer_type = 0, .index = 0 };
+
+ ASSERT(dev_addr > 0, null_handle);
+
+ if (p_endpoint_desc->bmAttributes.xfer == TUSB_XFER_ISOCHRONOUS)
+ return null_handle; // TODO not support ISO yet
+
+ //------------- Prepare Queue Head -------------//
+ ehci_qhd_t * const p_qhd = qhd_find_free(dev_addr);
+ ASSERT_PTR(p_qhd, null_handle);
+
+ qhd_init( p_qhd, dev_addr, p_endpoint_desc->wMaxPacketSize.size, p_endpoint_desc->bEndpointAddress,
+ p_endpoint_desc->bmAttributes.xfer, p_endpoint_desc->bInterval );
+ p_qhd->class_code = class_code;
+
+ //------------- Insert to Async List -------------//
+ ehci_link_t * list_head;
+
+ if (p_endpoint_desc->bmAttributes.xfer == TUSB_XFER_BULK)
+ {
+ list_head = (ehci_link_t*) get_async_head(usbh_devices[dev_addr].core_id);
+ }
+ #if EHCI_PERIODIC_LIST // TODO refractor/group this together
+ else if (p_endpoint_desc->bmAttributes.xfer == TUSB_XFER_INTERRUPT)
+ {
+ list_head = get_period_head(usbh_devices[dev_addr].core_id, p_qhd->interval_ms);
+ }
+ #endif
+
+ //------------- insert to async/period list TODO might need to disable async/period list -------------//
+ list_insert( list_head,
+ (ehci_link_t*) p_qhd, EHCI_QUEUE_ELEMENT_QHD);
+
+ return (pipe_handle_t) { .dev_addr = dev_addr, .xfer_type = p_endpoint_desc->bmAttributes.xfer, .index = qhd_get_index(p_qhd) };
+}
+
+tusb_error_t hcd_pipe_queue_xfer(pipe_handle_t pipe_hdl, uint8_t buffer[], uint16_t total_bytes)
+{
+ //------------- TODO pipe handle validate -------------//
+
+ //------------- set up QTD -------------//
+ ehci_qhd_t *p_qhd = qhd_get_from_pipe_handle(pipe_hdl);
+ ehci_qtd_t *p_qtd = qtd_find_free(pipe_hdl.dev_addr);
+
+ ASSERT_PTR(p_qtd, TUSB_ERROR_EHCI_NOT_ENOUGH_QTD);
+
+ qtd_init(p_qtd, (uint32_t) buffer, total_bytes);
+ p_qtd->pid = p_qhd->pid_non_control;
+
+ //------------- insert TD to TD list -------------//
+ qtd_insert_to_qhd(p_qhd, p_qtd);
+
+ return TUSB_ERROR_NONE;
+}
+
+tusb_error_t hcd_pipe_xfer(pipe_handle_t pipe_hdl, uint8_t buffer[], uint16_t total_bytes, bool int_on_complete)
+{
+ ASSERT_STATUS ( hcd_pipe_queue_xfer(pipe_hdl, buffer, total_bytes) );
+
+ ehci_qhd_t *p_qhd = qhd_get_from_pipe_handle(pipe_hdl);
+
+ if ( int_on_complete )
+ { // the just added qtd is pointed by list_tail
+ p_qhd->p_qtd_list_tail->int_on_complete = 1;
+ }
+ p_qhd->qtd_overlay.next.address = (uint32_t) p_qhd->p_qtd_list_head; // attach to queue head to start transferring
+
+ return TUSB_ERROR_NONE;
+}
+
+/// pipe_close should only be called as a part of unmount/safe-remove process
+tusb_error_t hcd_pipe_close(pipe_handle_t pipe_hdl)
+{
+ ASSERT(pipe_hdl.dev_addr > 0, TUSB_ERROR_INVALID_PARA);
+
+ ASSERT(pipe_hdl.xfer_type != TUSB_XFER_ISOCHRONOUS, TUSB_ERROR_INVALID_PARA);
+
+ ehci_qhd_t *p_qhd = qhd_get_from_pipe_handle( pipe_hdl );
+
+ // async list needs async advance handshake to make sure host controller has released cached data
+ // non-control does not use async advance, it will eventually free by control pipe close
+ // period list queue element is guarantee to be free in the next frame (1 ms)
+ p_qhd->is_removing = 1; // TODO redundant, only apply to control queue head
+
+ if ( pipe_hdl.xfer_type == TUSB_XFER_BULK )
+ {
+ ASSERT_STATUS( list_remove_qhd(
+ (ehci_link_t*) get_async_head( usbh_devices[pipe_hdl.dev_addr].core_id ),
+ (ehci_link_t*) p_qhd) );
+ }
+ #if EHCI_PERIODIC_LIST // TODO refractor/group this together
+ else
+ {
+ ASSERT_STATUS( list_remove_qhd(
+ get_period_head( usbh_devices[pipe_hdl.dev_addr].core_id, p_qhd->interval_ms ),
+ (ehci_link_t*) p_qhd) );
+ }
+ #endif
+
+ return TUSB_ERROR_NONE;
+}
+
+bool hcd_pipe_is_busy(pipe_handle_t pipe_hdl)
+{
+ ehci_qhd_t *p_qhd = qhd_get_from_pipe_handle( pipe_hdl );
+ return !p_qhd->qtd_overlay.halted && (p_qhd->p_qtd_list_head != NULL);
+}
+
+bool hcd_pipe_is_error(pipe_handle_t pipe_hdl)
+{
+ ehci_qhd_t *p_qhd = qhd_get_from_pipe_handle( pipe_hdl );
+ return p_qhd->qtd_overlay.halted;
+}
+
+bool hcd_pipe_is_idle(pipe_handle_t pipe_hdl)
+{ // TODO to be remove
+ ehci_qhd_t *p_qhd = qhd_get_from_pipe_handle( pipe_hdl );
+ return (p_qhd->p_qtd_list_head == NULL);
+}
+
+bool hcd_pipe_is_stalled(pipe_handle_t pipe_hdl)
+{
+ ehci_qhd_t *p_qhd = qhd_get_from_pipe_handle( pipe_hdl );
+ return p_qhd->qtd_overlay.halted && !qhd_has_xact_error(p_qhd);
+}
+
+uint8_t hcd_pipe_get_endpoint_addr(pipe_handle_t pipe_hdl)
+{
+ ehci_qhd_t *p_qhd = qhd_get_from_pipe_handle( pipe_hdl );
+ return p_qhd->endpoint_number + ( (p_qhd->pid_non_control == EHCI_PID_IN) ? 0x80 : 0);
+}
+
+tusb_error_t hcd_pipe_clear_stall(pipe_handle_t pipe_hdl)
+{
+ ehci_qhd_t *p_qhd = qhd_get_from_pipe_handle( pipe_hdl );
+ p_qhd->qtd_overlay.halted = 0;
+
+ return TUSB_ERROR_NONE;
+}
+
+//--------------------------------------------------------------------+
+// EHCI Interrupt Handler
+//--------------------------------------------------------------------+
+
+// async_advance is handshake between sw stack & ehci controller where ehci free all memory from an deleted queue head.
+// In tinyusb, queue head is only removed when device is unplugged. So only control queue head is checked if removing
+static void async_advance_isr(ehci_qhd_t * const async_head)
+{
+ // TODO do we need to close addr0
+ if (async_head->is_removing) // closing control pipe of addr0
+ {
+ async_head->is_removing = 0;
+ async_head->p_qtd_list_head = async_head->p_qtd_list_tail = NULL;
+ async_head->qtd_overlay.halted = 1;
+
+ usbh_devices[0].state = TUSB_DEVICE_STATE_UNPLUG;
+ }
+
+ for(uint8_t relative_dev_addr=0; relative_dev_addr < TUSB_CFG_HOST_DEVICE_MAX; relative_dev_addr++)
+ {
+ // check if control endpoint is removing
+ ehci_qhd_t *p_control_qhd = &ehci_data.device[relative_dev_addr].control.qhd;
+ if ( p_control_qhd->is_removing )
+ {
+ p_control_qhd->is_removing = 0;
+ p_control_qhd->used = 0;
+
+ // Host Controller has cleaned up its cached data for this device, set state to unplug
+ usbh_devices[relative_dev_addr+1].state = TUSB_DEVICE_STATE_UNPLUG;
+
+ for (uint8_t i=0; i<EHCI_MAX_QHD; i++) // free all qhd
+ {
+ ehci_data.device[relative_dev_addr].qhd[i].used = 0;
+ ehci_data.device[relative_dev_addr].qhd[i].is_removing = 0;
+ }
+ for (uint8_t i=0; i<EHCI_MAX_QTD; i++) // free all qtd
+ {
+ ehci_data.device[relative_dev_addr].qtd[i].used = 0;
+ }
+ // TODO free all itd & sitd
+ }
+ } // end for device[] loop
+}
+
+static void port_connect_status_change_isr(uint8_t hostid)
+{
+ ehci_registers_t* const regs = get_operational_register(hostid);
+
+ // NOTE There is an sequence plug->unplug->…..-> plug if device is powering with pre-plugged device
+ if (regs->portsc_bit.current_connect_status)
+ {
+ usbh_hcd_rhport_plugged_isr(hostid);
+ }else // device unplugged
+ {
+ usbh_hcd_rhport_unplugged_isr(hostid);
+// regs->usb_cmd_bit.advacne_async = 1; // Async doorbell check EHCI 4.8.2 for operational details
+ }
+}
+
+// TODO refractor abtract later
+void hcd_port_unplug(uint8_t hostid)
+{
+ ehci_registers_t* const regs = get_operational_register(hostid);
+ regs->usb_cmd_bit.advacne_async = 1; // Async doorbell check EHCI 4.8.2 for operational details
+}
+
+static void qhd_xfer_complete_isr(ehci_qhd_t * p_qhd)
+{
+ uint8_t max_loop = 0;
+ tusb_xfer_type_t const xfer_type = qhd_get_xfer_type(p_qhd);
+
+ // free all TDs from the head td to the first active TD
+ while(p_qhd->p_qtd_list_head != NULL && !p_qhd->p_qtd_list_head->active
+ && max_loop < EHCI_MAX_QTD)
+ {
+ // TD need to be freed and removed from qhd, before invoking callback
+ bool is_ioc = (p_qhd->p_qtd_list_head->int_on_complete != 0);
+ p_qhd->total_xferred_bytes += p_qhd->p_qtd_list_head->expected_bytes - p_qhd->p_qtd_list_head->total_bytes;
+
+ p_qhd->p_qtd_list_head->used = 0; // free QTD
+ qtd_remove_1st_from_qhd(p_qhd);
+
+ if (is_ioc) // end of request
+ { // call USBH callback
+ usbh_xfer_isr( qhd_create_pipe_handle(p_qhd, xfer_type),
+ p_qhd->class_code, TUSB_EVENT_XFER_COMPLETE,
+ p_qhd->total_xferred_bytes - (xfer_type == TUSB_XFER_CONTROL ? 8 : 0) ); // subtract setup packet size if control,
+ p_qhd->total_xferred_bytes = 0;
+ }
+
+ max_loop++;
+ }
+}
+
+static void async_list_xfer_complete_isr(ehci_qhd_t * const async_head)
+{
+ uint8_t max_loop = 0;
+ ehci_qhd_t *p_qhd = async_head;
+ do
+ {
+ if ( !p_qhd->qtd_overlay.halted ) // halted or error is processed in error isr
+ {
+ qhd_xfer_complete_isr(p_qhd);
+ }
+ p_qhd = qhd_next(p_qhd);
+ max_loop++;
+ }while(p_qhd != async_head && max_loop < EHCI_MAX_QHD); // async list traversal, stop if loop around
+ // TODO abstract max loop guard for async
+}
+
+#if EHCI_PERIODIC_LIST // TODO refractor/group this together
+static void period_list_xfer_complete_isr(uint8_t hostid, uint8_t interval_ms)
+{
+ uint8_t max_loop = 0;
+ uint32_t const period_1ms_addr = (uint32_t) get_period_head(hostid, 1);
+ ehci_link_t next_item = * get_period_head(hostid, interval_ms);
+
+ // TODO abstract max loop guard for period
+ while( !next_item.terminate &&
+ !(interval_ms > 1 && period_1ms_addr == align32(next_item.address)) &&
+ max_loop < (EHCI_MAX_QHD + EHCI_MAX_ITD + EHCI_MAX_SITD))
+ {
+ switch ( next_item.type )
+ {
+ case EHCI_QUEUE_ELEMENT_QHD:
+ {
+ ehci_qhd_t *p_qhd_int = (ehci_qhd_t *) align32(next_item.address);
+ if ( !p_qhd_int->qtd_overlay.halted )
+ {
+ qhd_xfer_complete_isr(p_qhd_int);
+ }
+ }
+ break;
+
+ case EHCI_QUEUE_ELEMENT_ITD:
+ case EHCI_QUEUE_ELEMENT_SITD:
+ case EHCI_QUEUE_ELEMENT_FSTN:
+ default:
+ ASSERT (false, VOID_RETURN); // TODO support hs/fs ISO
+ break;
+ }
+
+ next_item = *list_next(&next_item);
+ max_loop++;
+ }
+}
+#endif
+
+static void qhd_xfer_error_isr(ehci_qhd_t * p_qhd)
+{
+ if ( (p_qhd->device_address != 0 && p_qhd->qtd_overlay.halted) || // addr0 cannot be protocol STALL
+ qhd_has_xact_error(p_qhd) )
+ { // current qhd has error in transaction
+ tusb_xfer_type_t const xfer_type = qhd_get_xfer_type(p_qhd);
+ tusb_event_t error_event;
+
+ // no error bits are set, endpoint is halted due to STALL
+ error_event = qhd_has_xact_error(p_qhd) ? TUSB_EVENT_XFER_ERROR : TUSB_EVENT_XFER_STALLED;
+
+ p_qhd->total_xferred_bytes += p_qhd->p_qtd_list_head->expected_bytes - p_qhd->p_qtd_list_head->total_bytes;
+
+ // TODO skip unplugged device
+ if ( TUSB_EVENT_XFER_ERROR == error_event ) hal_debugger_breakpoint();
+
+ p_qhd->p_qtd_list_head->used = 0; // free QTD
+ qtd_remove_1st_from_qhd(p_qhd);
+
+ if ( TUSB_XFER_CONTROL == xfer_type )
+ {
+ p_qhd->total_xferred_bytes -= min8_of(8, p_qhd->total_xferred_bytes); // subtract setup size
+
+ // control cannot be halted --> clear all qtd list
+ p_qhd->p_qtd_list_head = NULL;
+ p_qhd->p_qtd_list_tail = NULL;
+
+ p_qhd->qtd_overlay.next.terminate = 1;
+ p_qhd->qtd_overlay.alternate.terminate = 1;
+ p_qhd->qtd_overlay.halted = 0;
+
+ ehci_qtd_t *p_setup = get_control_qtds(p_qhd->device_address);
+ ehci_qtd_t *p_data = p_setup + 1;
+ ehci_qtd_t *p_status = p_setup + 2;
+
+ p_setup->used = p_data->used = p_status->used = 0;
+ }
+
+ // call USBH callback
+ usbh_xfer_isr( qhd_create_pipe_handle(p_qhd, xfer_type),
+ p_qhd->class_code, error_event,
+ p_qhd->total_xferred_bytes);
+
+ p_qhd->total_xferred_bytes = 0;
+ }
+}
+
+static void xfer_error_isr(uint8_t hostid)
+{
+ //------------- async list -------------//
+ uint8_t max_loop = 0;
+ ehci_qhd_t * const async_head = get_async_head(hostid);
+ ehci_qhd_t *p_qhd = async_head;
+ do
+ {
+ qhd_xfer_error_isr( p_qhd );
+ p_qhd = qhd_next(p_qhd);
+ max_loop++;
+ }while(p_qhd != async_head && max_loop < EHCI_MAX_QHD); // async list traversal, stop if loop around
+
+ #if EHCI_PERIODIC_LIST
+ //------------- TODO refractor period list -------------//
+ uint32_t const period_1ms_addr = (uint32_t) get_period_head(hostid, 1);
+ for (uint8_t interval_ms=1; interval_ms <= EHCI_FRAMELIST_SIZE; interval_ms *= 2)
+ {
+ uint8_t period_max_loop = 0;
+ ehci_link_t next_item = * get_period_head(hostid, interval_ms);
+
+ // TODO abstract max loop guard for period
+ while( !next_item.terminate &&
+ !(interval_ms > 1 && period_1ms_addr == align32(next_item.address)) &&
+ period_max_loop < (EHCI_MAX_QHD + EHCI_MAX_ITD + EHCI_MAX_SITD))
+ {
+ switch ( next_item.type )
+ {
+ case EHCI_QUEUE_ELEMENT_QHD:
+ {
+ ehci_qhd_t *p_qhd_int = (ehci_qhd_t *) align32(next_item.address);
+ qhd_xfer_error_isr(p_qhd_int);
+ }
+ break;
+
+ case EHCI_QUEUE_ELEMENT_ITD:
+ case EHCI_QUEUE_ELEMENT_SITD:
+ case EHCI_QUEUE_ELEMENT_FSTN:
+ default:
+ ASSERT (false, VOID_RETURN); // TODO support hs/fs ISO
+ break;
+ }
+
+ next_item = *list_next(&next_item);
+ period_max_loop++;
+ }
+ }
+ #endif
+}
+
+//------------- Host Controller Driver's Interrupt Handler -------------//
+void hcd_isr(uint8_t hostid)
+{
+ ehci_registers_t* const regs = get_operational_register(hostid);
+
+ uint32_t int_status = regs->usb_sts;
+ int_status &= regs->usb_int_enable;
+
+ regs->usb_sts |= int_status; // Acknowledge handled interrupt
+
+ if (int_status == 0)
+ return;
+
+ if (int_status & EHCI_INT_MASK_PORT_CHANGE)
+ {
+ uint32_t port_status = regs->portsc & EHCI_PORTSC_MASK_ALL;
+
+ if (regs->portsc_bit.connect_status_change)
+ {
+ port_connect_status_change_isr(hostid);
+ }
+
+ regs->portsc |= port_status; // Acknowledge change bits in portsc
+ }
+
+ if (int_status & EHCI_INT_MASK_ERROR)
+ {
+ xfer_error_isr(hostid);
+ }
+
+ //------------- some QTD/SITD/ITD with IOC set is completed -------------//
+ if (int_status & EHCI_INT_MASK_NXP_ASYNC)
+ {
+ async_list_xfer_complete_isr( get_async_head(hostid) );
+ }
+
+#if EHCI_PERIODIC_LIST // TODO refractor/group this together
+ if (int_status & EHCI_INT_MASK_NXP_PERIODIC)
+ {
+ for (uint8_t i=1; i <= EHCI_FRAMELIST_SIZE; i *= 2)
+ {
+ period_list_xfer_complete_isr( hostid, i );
+ }
+ }
+#endif
+
+ //------------- There is some removed async previously -------------//
+ if (int_status & EHCI_INT_MASK_ASYNC_ADVANCE) // need to place after EHCI_INT_MASK_NXP_ASYNC
+ {
+ async_advance_isr( get_async_head(hostid) );
+ }
+}
+
+//--------------------------------------------------------------------+
+// HELPER
+//--------------------------------------------------------------------+
+STATIC_ INLINE_ ehci_registers_t* get_operational_register(uint8_t hostid)
+{
+ return (ehci_registers_t*) (hostid ? (&LPC_USB1->USBCMD_H) : (&LPC_USB0->USBCMD_H) );
+}
+
+#if EHCI_PERIODIC_LIST // TODO refractor/group this together
+STATIC_ INLINE_ ehci_link_t* get_period_frame_list(uint8_t hostid)
+{
+ switch(hostid)
+ {
+#if (TUSB_CFG_CONTROLLER_0_MODE & TUSB_MODE_HOST)
+ case 0:
+ return period_frame_list0;
+#endif
+
+#if (TUSB_CFG_CONTROLLER_1_MODE & TUSB_MODE_HOST)
+ case 1:
+ return period_frame_list1;
+#endif
+
+ default: return NULL;
+ }
+}
+#endif
+
+STATIC_ INLINE_ uint8_t hostid_to_data_idx(uint8_t hostid)
+{
+ #if (CONTROLLER_HOST_NUMBER == 1) && (TUSB_CFG_CONTROLLER_1_MODE & TUSB_MODE_HOST)
+ (void) hostid;
+ return 0;
+ #else
+ return hostid;
+ #endif
+}
+
+//------------- queue head helper -------------//
+STATIC_ INLINE_ ehci_qhd_t* get_async_head(uint8_t hostid)
+{
+ return &ehci_data.async_head[ hostid_to_data_idx(hostid) ];
+}
+
+#if EHCI_PERIODIC_LIST // TODO refractor/group this together
+STATIC_ INLINE_ ehci_link_t* get_period_head(uint8_t hostid, uint8_t interval_ms)
+{
+ return (ehci_link_t*) (&ehci_data.period_head_arr[ hostid_to_data_idx(hostid) ]
+ [ log2_of( min8_of(EHCI_FRAMELIST_SIZE, interval_ms) ) ] );
+}
+#endif
+
+STATIC_ INLINE_ ehci_qhd_t* get_control_qhd(uint8_t dev_addr)
+{
+ return (dev_addr == 0) ?
+ get_async_head( usbh_devices[dev_addr].core_id ) :
+ &ehci_data.device[dev_addr-1].control.qhd;
+}
+STATIC_ INLINE_ ehci_qtd_t* get_control_qtds(uint8_t dev_addr)
+{
+ return (dev_addr == 0) ?
+ ehci_data.addr0_qtd :
+ ehci_data.device[ dev_addr-1 ].control.qtd;
+
+}
+
+static inline ehci_qhd_t* qhd_find_free (uint8_t dev_addr)
+{
+ uint8_t relative_address = dev_addr-1;
+ uint8_t index=0;
+ while( index<EHCI_MAX_QHD && ehci_data.device[relative_address].qhd[index].used )
+ {
+ index++;
+ }
+ return (index < EHCI_MAX_QHD) ? &ehci_data.device[relative_address].qhd[index] : NULL;
+}
+
+static inline uint8_t qhd_get_index(ehci_qhd_t const * p_qhd)
+{
+ return p_qhd - ehci_data.device[p_qhd->device_address-1].qhd;
+}
+static inline tusb_xfer_type_t qhd_get_xfer_type(ehci_qhd_t const * p_qhd)
+{
+ return ( p_qhd->endpoint_number == 0 ) ? TUSB_XFER_CONTROL :
+ ( p_qhd->interrupt_smask != 0 ) ? TUSB_XFER_INTERRUPT : TUSB_XFER_BULK;
+}
+
+static inline ehci_qhd_t* qhd_next(ehci_qhd_t const * p_qhd)
+{
+ return (ehci_qhd_t*) align32(p_qhd->next.address);
+}
+
+STATIC_ INLINE_ ehci_qhd_t* qhd_get_from_pipe_handle(pipe_handle_t pipe_hdl)
+{
+ return &ehci_data.device[ pipe_hdl.dev_addr-1 ].qhd[ pipe_hdl.index ];
+}
+
+static inline pipe_handle_t qhd_create_pipe_handle(ehci_qhd_t const * p_qhd, tusb_xfer_type_t xfer_type)
+{
+ pipe_handle_t pipe_hdl = {
+ .dev_addr = p_qhd->device_address,
+ .xfer_type = xfer_type
+ };
+
+ // TODO Isochronous transfer support
+ if (TUSB_XFER_CONTROL != xfer_type) // qhd index for control is meaningless
+ {
+ pipe_hdl.index = qhd_get_index(p_qhd);
+ }
+
+ return pipe_hdl;
+}
+
+//------------- TD helper -------------//
+STATIC_ INLINE_ ehci_qtd_t* qtd_find_free(uint8_t dev_addr)
+{
+ uint8_t index=0;
+ while( index<EHCI_MAX_QTD && ehci_data.device[dev_addr-1].qtd[index].used )
+ {
+ index++;
+ }
+
+ return (index < EHCI_MAX_QTD) ? &ehci_data.device[dev_addr-1].qtd[index] : NULL;
+}
+
+static inline ehci_qtd_t* qtd_next(ehci_qtd_t const * p_qtd )
+{
+ return (ehci_qtd_t*) align32(p_qtd->next.address);
+}
+
+static inline void qtd_remove_1st_from_qhd(ehci_qhd_t *p_qhd)
+{
+ if (p_qhd->p_qtd_list_head == p_qhd->p_qtd_list_tail) // last TD --> make it NULL
+ {
+ p_qhd->p_qtd_list_head = p_qhd->p_qtd_list_tail = NULL;
+ }else
+ {
+ p_qhd->p_qtd_list_head = qtd_next( p_qhd->p_qtd_list_head );
+ }
+}
+
+static inline void qtd_insert_to_qhd(ehci_qhd_t *p_qhd, ehci_qtd_t *p_qtd_new)
+{
+ if (p_qhd->p_qtd_list_head == NULL) // empty list
+ {
+ p_qhd->p_qtd_list_head = p_qhd->p_qtd_list_tail = p_qtd_new;
+ }else
+ {
+ p_qhd->p_qtd_list_tail->next.address = (uint32_t) p_qtd_new;
+ p_qhd->p_qtd_list_tail = p_qtd_new;
+ }
+}
+
+static void qhd_init(ehci_qhd_t *p_qhd, uint8_t dev_addr, uint16_t max_packet_size, uint8_t endpoint_addr, uint8_t xfer_type, uint8_t interval)
+{
+ // address 0 uses async head, which always on the list --> cannot be cleared (ehci halted otherwise)
+ if (dev_addr != 0)
+ {
+ memclr_(p_qhd, sizeof(ehci_qhd_t));
+ }
+
+ p_qhd->device_address = dev_addr;
+ p_qhd->non_hs_period_inactive_next_xact = 0;
+ p_qhd->endpoint_number = endpoint_addr & 0x0F;
+ p_qhd->endpoint_speed = usbh_devices[dev_addr].speed;
+ p_qhd->data_toggle_control = (xfer_type == TUSB_XFER_CONTROL) ? 1 : 0;
+ p_qhd->head_list_flag = (dev_addr == 0) ? 1 : 0; // addr0's endpoint is the static asyn list head
+ p_qhd->max_package_size = max_packet_size;
+ p_qhd->non_hs_control_endpoint = ((TUSB_XFER_CONTROL == xfer_type) && (p_qhd->endpoint_speed != TUSB_SPEED_HIGH)) ? 1 : 0;
+ p_qhd->nak_count_reload = 0;
+
+ // Bulk/Control -> smask = cmask = 0
+ // TODO Isochronous
+ if (TUSB_XFER_INTERRUPT == xfer_type)
+ {
+ if (TUSB_SPEED_HIGH == p_qhd->endpoint_speed)
+ {
+ ASSERT_INT_WITHIN(1, 16, interval, VOID_RETURN);
+ if ( interval < 4) // sub milisecond interval
+ {
+ p_qhd->interval_ms = 0;
+ p_qhd->interrupt_smask = (interval == 1) ? BIN8(11111111) :
+ (interval == 2) ? BIN8(10101010) : BIN8(01000100);
+ }else
+ {
+ p_qhd->interval_ms = (uint8_t) min16_of( 1 << (interval-4), 255 );
+ p_qhd->interrupt_smask = BIT_(interval % 8);
+ }
+ }else
+ {
+ ASSERT( 0 != interval, VOID_RETURN);
+ // Full/Low: 4.12.2.1 (EHCI) case 1 schedule start split at 1 us & complete split at 2,3,4 uframes
+ p_qhd->interrupt_smask = 0x01;
+ p_qhd->non_hs_interrupt_cmask = BIN8(11100);
+ p_qhd->interval_ms = interval;
+ }
+ }else
+ {
+ p_qhd->interrupt_smask = p_qhd->non_hs_interrupt_cmask = 0;
+ }
+
+ p_qhd->hub_address = usbh_devices[dev_addr].hub_addr;
+ p_qhd->hub_port = usbh_devices[dev_addr].hub_port;
+ p_qhd->mult = 1; // TODO not use high bandwidth/park mode yet
+
+ //------------- HCD Management Data -------------//
+ p_qhd->used = 1;
+ p_qhd->is_removing = 0;
+ p_qhd->p_qtd_list_head = NULL;
+ p_qhd->p_qtd_list_tail = NULL;
+ p_qhd->pid_non_control = (endpoint_addr & 0x80) ? EHCI_PID_IN : EHCI_PID_OUT; // PID for TD under this endpoint
+
+ //------------- active, but no TD list -------------//
+ p_qhd->qtd_overlay.halted = 0;
+ p_qhd->qtd_overlay.next.terminate = 1;
+ p_qhd->qtd_overlay.alternate.terminate = 1;
+ if (TUSB_XFER_BULK == xfer_type && p_qhd->endpoint_speed == TUSB_SPEED_HIGH && p_qhd->pid_non_control == EHCI_PID_OUT)
+ {
+ p_qhd->qtd_overlay.pingstate_err = 1; // do PING for Highspeed Bulk OUT, EHCI section 4.11
+ }
+}
+
+static void qtd_init(ehci_qtd_t* p_qtd, uint32_t data_ptr, uint16_t total_bytes)
+{
+ memclr_(p_qtd, sizeof(ehci_qtd_t));
+
+ p_qtd->used = 1;
+
+ p_qtd->next.terminate = 1; // init to null
+ p_qtd->alternate.terminate = 1; // not used, always set to terminated
+ p_qtd->active = 1;
+ p_qtd->cerr = 3; // TODO 3 consecutive errors tolerance
+ p_qtd->data_toggle = 0;
+ p_qtd->total_bytes = total_bytes;
+ p_qtd->expected_bytes = total_bytes;
+
+ p_qtd->buffer[0] = data_ptr;
+ for(uint8_t i=1; i<5; i++)
+ {
+ p_qtd->buffer[i] |= align4k( p_qtd->buffer[i-1] ) + 4096;
+ }
+}
+
+//------------- List Managing Helper -------------//
+static inline void list_insert(ehci_link_t *current, ehci_link_t *new, uint8_t new_type)
+{
+ new->address = current->address;
+ current->address = ((uint32_t) new) | (new_type << 1);
+}
+
+static inline ehci_link_t* list_next(ehci_link_t *p_link_pointer)
+{
+ return (ehci_link_t*) align32(p_link_pointer->address);
+}
+
+static ehci_link_t* list_find_previous_item(ehci_link_t* p_head, ehci_link_t* p_current)
+{
+ ehci_link_t *p_prev = p_head;
+ uint32_t max_loop = 0;
+ while( (align32(p_prev->address) != (uint32_t) p_head) && // not loop around
+ (align32(p_prev->address) != (uint32_t) p_current) && // not found yet
+ !p_prev->terminate && // not advanceable
+ max_loop < EHCI_MAX_QHD)
+ {
+ p_prev = list_next(p_prev);
+ max_loop++;
+ }
+
+ return (align32(p_prev->address) != (uint32_t) p_head) ? p_prev : NULL;
+}
+
+static tusb_error_t list_remove_qhd(ehci_link_t* p_head, ehci_link_t* p_remove)
+{
+ ehci_link_t *p_prev = list_find_previous_item(p_head, p_remove);
+
+ ASSERT_PTR(p_prev, TUSB_ERROR_INVALID_PARA);
+
+ p_prev->address = p_remove->address;
+ // EHCI 4.8.2 link the removing queue head to async/period head (which always reachable by Host Controller)
+ p_remove->address = ((uint32_t) p_head) | (EHCI_QUEUE_ELEMENT_QHD << 1);
+
+ return TUSB_ERROR_NONE;
+}
+
+#endif
diff --git a/tinyusb/mcu_capacity.h b/tinyusb/mcu_capacity.h
index e287cf4b5..958a71f01 100644
--- a/tinyusb/mcu_capacity.h
+++ b/tinyusb/mcu_capacity.h
@@ -1,98 +1,98 @@
-/**************************************************************************/
-/*!
- @file mcu_capacity.h
- @author hathach (tinyusb.org)
-
- @section LICENSE
-
- Software License Agreement (BSD License)
-
- Copyright (c) 2013, hathach (tinyusb.org)
- All rights reserved.
-
- Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions are met:
- 1. Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
- 2. Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
- 3. Neither the name of the copyright holders nor the
- names of its contributors may be used to endorse or promote products
- derived from this software without specific prior written permission.
-
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
- EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
- DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION HOWEVER CAUSED AND
- ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- INCLUDING NEGLIGENCE OR OTHERWISE ARISING IN ANY WAY OUT OF THE USE OF THIS
- SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
- This file is part of the tinyusb stack.
-*/
-/**************************************************************************/
-
-/** \file
- * \brief TBD
- *
- * \note TBD
- */
-
-/** \ingroup TBD
- * \defgroup TBD
- * \brief TBD
- *
- * @{
- */
-
-#ifndef _TUSB_MCU_CAPACITY_H_
-#define _TUSB_MCU_CAPACITY_H_
-
-#ifdef __cplusplus
- extern "C" {
-#endif
-
-// CAP is abbreviation for Capacity
-
-//--------------------------------------------------------------------+
-// ARCHTECTURE
-//--------------------------------------------------------------------+
-
-
-
-//--------------------------------------------------------------------+
-// Controller
-//--------------------------------------------------------------------+
-#if MCU == MCU_LPC43XX || MCU == MCU_LPC18XX
- #define CAP_CONTROLLER_NUMBER 2
-#else
- #define CAP_CONTROLLER_NUMBER 1
-#endif
-
-#define CAP_MODE_DEVICE
-#if MCU == MCU_LPC43XX || MCU == MCU_LPC18XX || MCU == MCU_LPC175X_6X
- #define CAP_MODE_HOST
-#endif
-
-#if MCU == MCU_LPC43XX || MCU == MCU_LPC18XX || MCU == MCU_LPC11UXX || MCU == MCU_LPC13UXX
- #define CAP_DEVICE_ROMDRIVER
-#endif
-
-//--------------------------------------------------------------------+
-// Validation
-//--------------------------------------------------------------------+
-#if (CAP_CONTROLLER_NUMBER == 1) && ( defined TUSB_CFG_CONTROLLER1_MODE)
- #error current MCU does not have the required number of controllers
-#endif
-
-#ifdef __cplusplus
- }
-#endif
-
-#endif /* _TUSB_MCU_CAPACITY_H_ */
-
-/** @} */
+/**************************************************************************/
+/*!
+ @file mcu_capacity.h
+ @author hathach (tinyusb.org)
+
+ @section LICENSE
+
+ Software License Agreement (BSD License)
+
+ Copyright (c) 2013, hathach (tinyusb.org)
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ 3. Neither the name of the copyright holders nor the
+ names of its contributors may be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
+ EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
+ DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION HOWEVER CAUSED AND
+ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ INCLUDING NEGLIGENCE OR OTHERWISE ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ This file is part of the tinyusb stack.
+*/
+/**************************************************************************/
+
+/** \file
+ * \brief TBD
+ *
+ * \note TBD
+ */
+
+/** \ingroup TBD
+ * \defgroup TBD
+ * \brief TBD
+ *
+ * @{
+ */
+
+#ifndef _TUSB_MCU_CAPACITY_H_
+#define _TUSB_MCU_CAPACITY_H_
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+// CAP is abbreviation for Capacity
+
+//--------------------------------------------------------------------+
+// ARCHTECTURE
+//--------------------------------------------------------------------+
+
+
+
+//--------------------------------------------------------------------+
+// Controller
+//--------------------------------------------------------------------+
+#if MCU == MCU_LPC43XX || MCU == MCU_LPC18XX
+ #define CAP_CONTROLLER_NUMBER 2
+#else
+ #define CAP_CONTROLLER_NUMBER 1
+#endif
+
+#define CAP_MODE_DEVICE
+#if MCU == MCU_LPC43XX || MCU == MCU_LPC18XX || MCU == MCU_LPC175X_6X
+ #define CAP_MODE_HOST
+#endif
+
+#if MCU == MCU_LPC43XX || MCU == MCU_LPC18XX || MCU == MCU_LPC11UXX || MCU == MCU_LPC13UXX
+ #define CAP_DEVICE_ROMDRIVER
+#endif
+
+//--------------------------------------------------------------------+
+// Validation
+//--------------------------------------------------------------------+
+#if (CAP_CONTROLLER_NUMBER == 1) && ( defined TUSB_CFG_CONTROLLER_1_MODE)
+ #error current MCU does not have the required number of controllers
+#endif
+
+#ifdef __cplusplus
+ }
+#endif
+
+#endif /* _TUSB_MCU_CAPACITY_H_ */
+
+/** @} */
diff --git a/tinyusb/osal/osal.h b/tinyusb/osal/osal.h
index d23cb518c..4c45b0087 100644
--- a/tinyusb/osal/osal.h
+++ b/tinyusb/osal/osal.h
@@ -1,204 +1,209 @@
-/**************************************************************************/
-/*!
- @file osal.h
- @author hathach (tinyusb.org)
-
- @section LICENSE
-
- Software License Agreement (BSD License)
-
- Copyright (c) 2013, hathach (tinyusb.org)
- All rights reserved.
-
- Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions are met:
- 1. Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
- 2. Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
- 3. Neither the name of the copyright holders nor the
- names of its contributors may be used to endorse or promote products
- derived from this software without specific prior written permission.
-
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
- EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
- DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION HOWEVER CAUSED AND
- ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- INCLUDING NEGLIGENCE OR OTHERWISE ARISING IN ANY WAY OUT OF THE USE OF THIS
- SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
- This file is part of the tinyusb stack.
-*/
-/**************************************************************************/
-
-/** \file
- * \brief TBD
- *
- * \note TBD
- */
-
-/** \ingroup TBD
- * \defgroup TBD
- * \brief TBD
- *
- * @{
- */
-
-#ifndef _TUSB_OSAL_H_
-#define _TUSB_OSAL_H_
-
-#ifdef __cplusplus
- extern "C" {
-#endif
-
-#include "tusb_option.h"
-
-#define TUSB_OS_NONE 1
-#define TUSB_OS_FREERTOS 2
-#define TUSB_OS_CMSIS_RTX 3
-#define TUSB_OS_UCOS2 4
-#define TUSB_OS_UCOS3 5
-
-#ifndef _TEST_
-
-#if TUSB_CFG_OS == TUSB_OS_NONE
- #include "osal_none.h"
-#else
- #define OSAL_VAR
- #if TUSB_CFG_OS == TUSB_OS_FREERTOS
- #include "osal_freeRTOS.h"
- #elif TUSB_CFG_OS == TUSB_OS_CMSIS_RTX
- #include "osal_cmsis_rtx.h"
- #else
- #error TUSB_CFG_OS is not defined or OS is not supported yet
- #endif
-#endif
-
-#else // OSAL API for cmock
-
-#define OSAL_VAR
-#include "osal_common.h"
-
-//------------- Tick -------------//
-uint32_t osal_tick_get(void);
-
-//--------------------------------------------------------------------+
-// TASK API
-//--------------------------------------------------------------------+
-typedef uint32_t osal_task_t;
-tusb_error_t osal_task_create(osal_task_t *task);
-
-#define OSAL_TASK_DEF(code, stack_depth, prio) \
- osal_task_t variable
-
-#define OSAL_TASK_REF(name) (&name)
-
-#define OSAL_TASK_FUNCTION(task_name) \
- void task_name
-
-void osal_task_delay(uint32_t msec);
-
-#define OSAL_TASK_LOOP_BEGIN
-#define OSAL_TASK_LOOP_END
-
-#define SUBTASK_EXIT(error) return error;
-
-//------------- Sub Task -------------//
-#define OSAL_SUBTASK_INVOKED_AND_WAIT(subtask, status) \
- status = subtask
-
-#define OSAL_SUBTASK_BEGIN
-#define OSAL_SUBTASK_END \
- return TUSB_ERROR_NONE;
-
-//------------- Sub Task Assert -------------//
-#define _SUBTASK_ASSERT_ERROR_HANDLER(error, func_call)\
- func_call; return error
-
-#define SUBTASK_ASSERT_STATUS(sts) ASSERT_STATUS(sts)
-
-#define SUBTASK_ASSERT_STATUS_WITH_HANDLER(sts, func_call) \
- ASSERT_DEFINE_WITH_HANDLER(_SUBTASK_ASSERT_ERROR_HANDLER, func_call, tusb_error_t status = (tusb_error_t)(sts),\
- TUSB_ERROR_NONE == status, status, "%s", TUSB_ErrorStr[status])
-
-#define SUBTASK_ASSERT(condition) ASSERT(condition, TUSB_ERROR_OSAL_TASK_FAILED)
-
-#define SUBTASK_ASSERT_WITH_HANDLER(condition, func_call) \
- ASSERT_DEFINE_WITH_HANDLER(_SUBTASK_ASSERT_ERROR_HANDLER, func_call, ,\
- condition, TUSB_ERROR_OSAL_TASK_FAILED, "%s", "evaluated to false")
-
-
-//--------------------------------------------------------------------+
-// Semaphore API
-//--------------------------------------------------------------------+
-typedef volatile uint8_t osal_semaphore_t;
-typedef osal_semaphore_t * osal_semaphore_handle_t;
-
-#define OSAL_SEM_DEF(name)\
- osal_semaphore_t name
-
-#define OSAL_SEM_REF(name)\
- &name
-
-osal_semaphore_handle_t osal_semaphore_create(osal_semaphore_t * p_sem);
-void osal_semaphore_wait(osal_semaphore_handle_t sem_hdl, uint32_t msec, tusb_error_t *p_error);
-tusb_error_t osal_semaphore_post(osal_semaphore_handle_t sem_hdl);
-void osal_semaphore_reset(osal_semaphore_handle_t sem_hdl);
-
-//--------------------------------------------------------------------+
-// MUTEX API (priority inheritance)
-//--------------------------------------------------------------------+
-#define OSAL_MUTEX_DEF(name)\
- osal_mutex_t name
-
-#define OSAL_MUTEX_REF(name)\
- &name
-
-typedef osal_semaphore_t osal_mutex_t;
-typedef osal_semaphore_handle_t osal_mutex_handle_t;
-
-osal_mutex_handle_t osal_mutex_create(osal_mutex_t * p_mutex);
-void osal_mutex_wait(osal_mutex_handle_t mutex_hdl, uint32_t msec, tusb_error_t *p_error);
-tusb_error_t osal_mutex_release(osal_mutex_handle_t mutex_hdl);
-void osal_mutex_reset(osal_mutex_handle_t mutex_hdl);
-//--------------------------------------------------------------------+
-// QUEUE API
-//--------------------------------------------------------------------+
-typedef struct{
- uint32_t * const buffer ; ///< buffer pointer
- uint8_t const depth ; ///< buffer size
- volatile uint8_t count ; ///< bytes in fifo
- volatile uint8_t wr_idx ; ///< write pointer
- volatile uint8_t rd_idx ; ///< read pointer
-} osal_queue_t;
-
-typedef osal_queue_t * osal_queue_handle_t;
-
-#define OSAL_QUEUE_DEF(name, queue_depth, type) \
- osal_queue_t name
-
-#define OSAL_QUEUE_REF(name) (&name)
-
-osal_queue_handle_t osal_queue_create (osal_queue_t *p_queue);
-void osal_queue_receive (osal_queue_handle_t const queue_hdl, void *p_data, uint32_t msec, tusb_error_t *p_error);
-tusb_error_t osal_queue_send (osal_queue_handle_t const queue_hdl, const void * data);
-void osal_queue_flush(osal_queue_handle_t const queue_hdl);
-
-//--------------------------------------------------------------------+
-// TICK API
-//--------------------------------------------------------------------+
-uint32_t osal_tick_get(void);
-#endif
-
-#ifdef __cplusplus
- }
-#endif
-
-#endif /* _TUSB_OSAL_H_ */
-
-/** @} */
+/**************************************************************************/
+/*!
+ @file osal.h
+ @author hathach (tinyusb.org)
+
+ @section LICENSE
+
+ Software License Agreement (BSD License)
+
+ Copyright (c) 2013, hathach (tinyusb.org)
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ 3. Neither the name of the copyright holders nor the
+ names of its contributors may be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
+ EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
+ DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION HOWEVER CAUSED AND
+ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ INCLUDING NEGLIGENCE OR OTHERWISE ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ This file is part of the tinyusb stack.
+*/
+/**************************************************************************/
+
+/** \file
+ * \brief TBD
+ *
+ * \note TBD
+ */
+
+/** \ingroup TBD
+ * \defgroup TBD
+ * \brief TBD
+ *
+ * @{
+ */
+
+#ifndef _TUSB_OSAL_H_
+#define _TUSB_OSAL_H_
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+#include "tusb_option.h"
+
+/** \ingroup group_configuration
+ * \defgroup TUSB_OS RTOS Integration Selection
+ * \brief TUSB_CFG_OS must be defined to one of these
+ * @{ */
+#define TUSB_OS_NONE 1 ///< No RTOS is used
+#define TUSB_OS_FREERTOS 2 ///< FreeRTOS is used
+#define TUSB_OS_CMSIS_RTX 3 ///< CMSIS RTX is used
+#define TUSB_OS_UCOS2 4 ///< MicroC OS II is used (not supported yet)
+#define TUSB_OS_UCOS3 5 ///< MicroC OS III is used (not supported yet)
+/** @} */
+
+#ifndef _TEST_
+
+#if TUSB_CFG_OS == TUSB_OS_NONE
+ #include "osal_none.h"
+#else
+ #define OSAL_VAR
+ #if TUSB_CFG_OS == TUSB_OS_FREERTOS
+ #include "osal_freeRTOS.h"
+ #elif TUSB_CFG_OS == TUSB_OS_CMSIS_RTX
+ #include "osal_cmsis_rtx.h"
+ #else
+ #error TUSB_CFG_OS is not defined or OS is not supported yet
+ #endif
+#endif
+
+#else // OSAL API for cmock
+
+#define OSAL_VAR
+#include "osal_common.h"
+
+//------------- Tick -------------//
+uint32_t osal_tick_get(void);
+
+//--------------------------------------------------------------------+
+// TASK API
+//--------------------------------------------------------------------+
+typedef uint32_t osal_task_t;
+tusb_error_t osal_task_create(osal_task_t *task);
+
+#define OSAL_TASK_DEF(code, stack_depth, prio) \
+ osal_task_t variable
+
+#define OSAL_TASK_REF(name) (&name)
+
+#define OSAL_TASK_FUNCTION(task_name) \
+ void task_name
+
+void osal_task_delay(uint32_t msec);
+
+#define OSAL_TASK_LOOP_BEGIN
+#define OSAL_TASK_LOOP_END
+
+#define SUBTASK_EXIT(error) return error;
+
+//------------- Sub Task -------------//
+#define OSAL_SUBTASK_INVOKED_AND_WAIT(subtask, status) \
+ status = subtask
+
+#define OSAL_SUBTASK_BEGIN
+#define OSAL_SUBTASK_END \
+ return TUSB_ERROR_NONE;
+
+//------------- Sub Task Assert -------------//
+#define _SUBTASK_ASSERT_ERROR_HANDLER(error, func_call)\
+ func_call; return error
+
+#define SUBTASK_ASSERT_STATUS(sts) ASSERT_STATUS(sts)
+
+#define SUBTASK_ASSERT_STATUS_WITH_HANDLER(sts, func_call) \
+ ASSERT_DEFINE_WITH_HANDLER(_SUBTASK_ASSERT_ERROR_HANDLER, func_call, tusb_error_t status = (tusb_error_t)(sts),\
+ TUSB_ERROR_NONE == status, status, "%s", TUSB_ErrorStr[status])
+
+#define SUBTASK_ASSERT(condition) ASSERT(condition, TUSB_ERROR_OSAL_TASK_FAILED)
+
+#define SUBTASK_ASSERT_WITH_HANDLER(condition, func_call) \
+ ASSERT_DEFINE_WITH_HANDLER(_SUBTASK_ASSERT_ERROR_HANDLER, func_call, ,\
+ condition, TUSB_ERROR_OSAL_TASK_FAILED, "%s", "evaluated to false")
+
+
+//--------------------------------------------------------------------+
+// Semaphore API
+//--------------------------------------------------------------------+
+typedef volatile uint8_t osal_semaphore_t;
+typedef osal_semaphore_t * osal_semaphore_handle_t;
+
+#define OSAL_SEM_DEF(name)\
+ osal_semaphore_t name
+
+#define OSAL_SEM_REF(name)\
+ &name
+
+osal_semaphore_handle_t osal_semaphore_create(osal_semaphore_t * p_sem);
+void osal_semaphore_wait(osal_semaphore_handle_t sem_hdl, uint32_t msec, tusb_error_t *p_error);
+tusb_error_t osal_semaphore_post(osal_semaphore_handle_t sem_hdl);
+void osal_semaphore_reset(osal_semaphore_handle_t sem_hdl);
+
+//--------------------------------------------------------------------+
+// MUTEX API (priority inheritance)
+//--------------------------------------------------------------------+
+#define OSAL_MUTEX_DEF(name)\
+ osal_mutex_t name
+
+#define OSAL_MUTEX_REF(name)\
+ &name
+
+typedef osal_semaphore_t osal_mutex_t;
+typedef osal_semaphore_handle_t osal_mutex_handle_t;
+
+osal_mutex_handle_t osal_mutex_create(osal_mutex_t * p_mutex);
+void osal_mutex_wait(osal_mutex_handle_t mutex_hdl, uint32_t msec, tusb_error_t *p_error);
+tusb_error_t osal_mutex_release(osal_mutex_handle_t mutex_hdl);
+void osal_mutex_reset(osal_mutex_handle_t mutex_hdl);
+//--------------------------------------------------------------------+
+// QUEUE API
+//--------------------------------------------------------------------+
+typedef struct{
+ uint32_t * const buffer ; ///< buffer pointer
+ uint8_t const depth ; ///< buffer size
+ volatile uint8_t count ; ///< bytes in fifo
+ volatile uint8_t wr_idx ; ///< write pointer
+ volatile uint8_t rd_idx ; ///< read pointer
+} osal_queue_t;
+
+typedef osal_queue_t * osal_queue_handle_t;
+
+#define OSAL_QUEUE_DEF(name, queue_depth, type) \
+ osal_queue_t name
+
+#define OSAL_QUEUE_REF(name) (&name)
+
+osal_queue_handle_t osal_queue_create (osal_queue_t *p_queue);
+void osal_queue_receive (osal_queue_handle_t const queue_hdl, void *p_data, uint32_t msec, tusb_error_t *p_error);
+tusb_error_t osal_queue_send (osal_queue_handle_t const queue_hdl, const void * data);
+void osal_queue_flush(osal_queue_handle_t const queue_hdl);
+
+//--------------------------------------------------------------------+
+// TICK API
+//--------------------------------------------------------------------+
+uint32_t osal_tick_get(void);
+#endif
+
+#ifdef __cplusplus
+ }
+#endif
+
+#endif /* _TUSB_OSAL_H_ */
+
+/** @} */
diff --git a/tinyusb/tusb_option.h b/tinyusb/tusb_option.h
index f479d0a79..2330835d8 100644
--- a/tinyusb/tusb_option.h
+++ b/tinyusb/tusb_option.h
@@ -1,192 +1,195 @@
-/**************************************************************************/
-/*!
- @file tusb_option.h
- @author hathach (tinyusb.org)
-
- @section LICENSE
-
- Software License Agreement (BSD License)
-
- Copyright (c) 2013, hathach (tinyusb.org)
- All rights reserved.
-
- Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions are met:
- 1. Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
- 2. Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
- 3. Neither the name of the copyright holders nor the
- names of its contributors may be used to endorse or promote products
- derived from this software without specific prior written permission.
-
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
- EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
- DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION HOWEVER CAUSED AND
- ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- INCLUDING NEGLIGENCE OR OTHERWISE ARISING IN ANY WAY OUT OF THE USE OF THIS
- SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
- This file is part of the tinyusb stack.
-*/
-/**************************************************************************/
-
-/** \file
- * \brief Configure File
- *
- * \note TBD
- */
-
-/**
- * \defgroup Group_TinyUSB_Configure Configuration tusb_option.h
- * @{
- */
-
-#ifndef _TUSB_TUSB_OPTION_H_
-#define _TUSB_TUSB_OPTION_H_
-
-#define TUSB_VERSION_YEAR 00
-#define TUSB_VERSION_MONTH 00
-#define TUSB_VERSION_WEEK 0
-#define TUSB_VERSION_NAME "alpha"
-#define TUSB_VERSION XSTRING_(TUSB_VERSION_YEAR) "." XSTRING_(TUSB_VERSION_MONTH)
-
-#define MCU_LPC13UXX 1
-#define MCU_LPC11UXX 2
-#define MCU_LPC43XX 3
-#define MCU_LPC18XX 4
-#define MCU_LPC175X_6X 5
-#define MCU_LPC177X_8X 6
-
-/// define this symbol will make tinyusb look for external configure file
-#include "mcu_capacity.h"
-
-#ifdef TUSB_CFG_CONFIG_FILE
- #include TUSB_CFG_CONFIG_FILE
-#else
- #include "tusb_config.h"
-#endif
-
-//--------------------------------------------------------------------+
-// CONTROLLER
-//--------------------------------------------------------------------+
-#define TUSB_MODE_HOST 0x02
-#define TUSB_MODE_DEVICE 0x01
-#define TUSB_MODE_NONE 0x00
-
-#define CONTROLLER_HOST_NUMBER (\
- ((TUSB_CFG_CONTROLLER0_MODE & TUSB_MODE_HOST) ? 1 : 0) + \
- ((TUSB_CFG_CONTROLLER1_MODE & TUSB_MODE_HOST) ? 1 : 0))
-
-#define CONTROLLER_DEVICE_NUMBER (\
- ((TUSB_CFG_CONTROLLER0_MODE & TUSB_MODE_DEVICE) ? 1 : 0) + \
- ((TUSB_CFG_CONTROLLER1_MODE & TUSB_MODE_DEVICE) ? 1 : 0))
-
-#define MODE_HOST_SUPPORTED (CONTROLLER_HOST_NUMBER > 0)
-#define MODE_DEVICE_SUPPORTED (CONTROLLER_DEVICE_NUMBER > 0)
-
-#if !MODE_HOST_SUPPORTED && !MODE_DEVICE_SUPPORTED
- #error please configure at least 1 TUSB_CFG_CONTROLLERn_MODE to TUSB_MODE_HOST and/or TUSB_MODE_DEVICE
-#endif
-
-//--------------------------------------------------------------------+
-// COMMON OPTIONS
-//--------------------------------------------------------------------+
-
-// level 3: ATTR_ALWAYS_INLINE is null, ASSERT has text, Error has its String, STATIC_VAR is NULL
-// level 2: ATTR_ALWAYS_INLINE is attribute, ASSERT has no text, Error has no strings
-/// 0: no debug information 3: most debug information provided
-#ifndef TUSB_CFG_DEBUG
- #define TUSB_CFG_DEBUG 2
- #warning TUSB_CFG_DEBUG is not defined, default value is 3
-#endif
-
-/// USB RAM Section Placement, MCU's usb controller often has limited access to specific RAM region. This will be used to declare internal variables as follow:
-/// uint8_t tinyusb_data[10] TUSB_CFG_ATTR_USBRAM;
-/// if your mcu's usb controller has no such limit, define TUSB_CFG_ATTR_USBRAM as empty macro.
-#ifndef TUSB_CFG_ATTR_USBRAM
- #error TUSB_CFG_ATTR_USBRAM is not defined, please help me know how to place data in accessible RAM for usb controller
-#endif
-
-#if TUSB_CFG_OS == TUSB_OS_NONE
- #ifndef TUSB_CFG_OS_TICKS_PER_SECOND
- #error TUSB_CFG_OS_TICKS_PER_SECOND is required to use with OS_NONE
- #endif
-#else
- #ifndef TUSB_CFG_OS_TASK_PRIO
- #error TUSB_CFG_OS_TASK_PRIO need to be defined (hint: use the highest if possible)
- #endif
-#endif
-
-#ifndef TUSB_CFG_CONFIGURATION_MAX
- #define TUSB_CFG_CONFIGURATION_MAX 1
- #warning TUSB_CFG_CONFIGURATION_MAX is not defined, default value is 1
-#endif
-
-//--------------------------------------------------------------------+
-// HOST OPTIONS
-//--------------------------------------------------------------------+
-#if MODE_HOST_SUPPORTED
- #ifndef TUSB_CFG_HOST_DEVICE_MAX
- #define TUSB_CFG_HOST_DEVICE_MAX 1
- #warning TUSB_CFG_HOST_DEVICE_MAX is not defined, default value is 1
- #endif
-
- //------------- HUB CLASS -------------//
- #if TUSB_CFG_HOST_HUB && (TUSB_CFG_HOST_DEVICE_MAX == 1)
- #error there is no benefit enable hub with max device is 1. Please disable hub or increase TUSB_CFG_HOST_DEVICE_MAX
- #endif
-
- //------------- HID CLASS -------------//
- #define HOST_CLASS_HID ( TUSB_CFG_HOST_HID_KEYBOARD + TUSB_CFG_HOST_HID_MOUSE + TUSB_CFG_HOST_HID_GENERIC )
- #if HOST_CLASS_HID
- #define HOST_HCD_XFER_INTERRUPT
- #endif
-
- #ifndef TUSB_CFG_HOST_ENUM_BUFFER_SIZE
- #define TUSB_CFG_HOST_ENUM_BUFFER_SIZE 256
- #warning TUSB_CFG_HOST_ENUM_BUFFER_SIZE is not defined, default value is 256
- #endif
-
- //------------- CLASS -------------//
-#endif // end TUSB_CFG_HOST
-
-//--------------------------------------------------------------------+
-// DEVICE OPTIONS
-//--------------------------------------------------------------------+
-#if MODE_DEVICE_SUPPORTED
-
-#if defined(CAP_DEVICE_ROMDRIVER) && !TUSB_CFG_DEVICE_USE_ROM_DRIVER
- #error only rom driver for these mcu are supported now
-#endif
-
-#define DEVICE_CLASS_HID ( TUSB_CFG_DEVICE_HID_KEYBOARD + TUSB_CFG_DEVICE_HID_MOUSE + TUSB_CFG_DEVICE_HID_GENERIC )
-
-
-#endif
-
-
-
-#define USB_FS_MAX_BULK_PACKET 64
-#define USB_HS_MAX_BULK_PACKET USB_FS_MAX_BULK_PACKET /* Full speed device only */
-
-/* HID In/Out Endpoint Address */
-#define HID_KEYBOARD_EP_IN ENDPOINT_IN_LOGICAL_TO_PHYSICAL(1)
-#define HID_MOUSE_EP_IN ENDPOINT_IN_LOGICAL_TO_PHYSICAL(4)
-
-/* CDC Endpoint Address */
-#define CDC_NOTIFICATION_EP ENDPOINT_IN_LOGICAL_TO_PHYSICAL(2)
-#define CDC_DATA_EP_OUT ENDPOINT_OUT_LOGICAL_TO_PHYSICAL(3)
-#define CDC_DATA_EP_IN ENDPOINT_IN_LOGICAL_TO_PHYSICAL(3)
-
-#define CDC_NOTIFICATION_EP_MAXPACKETSIZE 8
-#define CDC_DATA_EP_MAXPACKET_SIZE 16
-
-#endif /* _TUSB_TUSB_OPTION_H_ */
-
-/** @} */
+/**************************************************************************/
+/*!
+ @file tusb_option.h
+ @author hathach (tinyusb.org)
+
+ @section LICENSE
+
+ Software License Agreement (BSD License)
+
+ Copyright (c) 2013, hathach (tinyusb.org)
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ 3. Neither the name of the copyright holders nor the
+ names of its contributors may be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
+ EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
+ DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION HOWEVER CAUSED AND
+ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ INCLUDING NEGLIGENCE OR OTHERWISE ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ This file is part of the tinyusb stack.
+*/
+/**************************************************************************/
+
+#ifndef _TUSB_TUSB_OPTION_H_
+#define _TUSB_TUSB_OPTION_H_
+
+/** \defgroup group_configuration Configuration tusb_config.h
+ * @{ */
+
+#define TUSB_VERSION_YEAR 00
+#define TUSB_VERSION_MONTH 00
+#define TUSB_VERSION_WEEK 0
+#define TUSB_VERSION_NAME "alpha"
+#define TUSB_VERSION XSTRING_(TUSB_VERSION_YEAR) "." XSTRING_(TUSB_VERSION_MONTH)
+
+/** \defgroup MCU_ MCU Selection
+ * \brief TUSB_CFG_MCU must be defined to one of these
+ * @{ */
+#define MCU_LPC13XX_12ADC 1 ///< NXP LPC13xx 12 bit ADC family with USB on-chip Rom Driver (not supported yet)
+#define MCU_LPC13XX_10ADC 2 ///< NXP LPC13xx 10 bit ADC family (not supported yet)
+#define MCU_LPC11UXX 3 ///< NXP LPC11Uxx family (not supported yet)
+#define MCU_LPC43XX 4 ///< NXP LPC43xx family
+#define MCU_LPC18XX 5 ///< NXP LPC18xx family (not supported yet)
+#define MCU_LPC175X_6X 6 ///< NXP LPC175x, LPC176x family (not supported yet)
+#define MCU_LPC177X_8X 7 ///< NXP LPC177x, LPC178x family (not supported yet)
+/** @} */
+
+#include "mcu_capacity.h"
+
+#ifdef TUSB_CFG_CONFIG_FILE
+ #include TUSB_CFG_CONFIG_FILE
+#else
+ #include "tusb_config.h"
+#endif
+
+//--------------------------------------------------------------------+
+// CONTROLLER
+//--------------------------------------------------------------------+
+/** \defgroup TUSB_MODE Host/Device Mode Selection
+ * \brief TUSB_CFG_CONTROLLER_N_MODE must be defined with these
+ * @{ */
+#define TUSB_MODE_HOST 0x02 ///< Host Mode
+#define TUSB_MODE_DEVICE 0x01 ///< Device Mode
+#define TUSB_MODE_NONE 0x00 ///< Disabled
+/** @} */
+
+#define CONTROLLER_HOST_NUMBER (\
+ ((TUSB_CFG_CONTROLLER_0_MODE & TUSB_MODE_HOST) ? 1 : 0) + \
+ ((TUSB_CFG_CONTROLLER_1_MODE & TUSB_MODE_HOST) ? 1 : 0))
+
+#define CONTROLLER_DEVICE_NUMBER (\
+ ((TUSB_CFG_CONTROLLER_0_MODE & TUSB_MODE_DEVICE) ? 1 : 0) + \
+ ((TUSB_CFG_CONTROLLER_1_MODE & TUSB_MODE_DEVICE) ? 1 : 0))
+
+#define MODE_HOST_SUPPORTED (CONTROLLER_HOST_NUMBER > 0)
+#define MODE_DEVICE_SUPPORTED (CONTROLLER_DEVICE_NUMBER > 0)
+
+#if !MODE_HOST_SUPPORTED && !MODE_DEVICE_SUPPORTED
+ #error please configure at least 1 TUSB_CFG_CONTROLLER_N_MODE to TUSB_MODE_HOST and/or TUSB_MODE_DEVICE
+#endif
+
+//--------------------------------------------------------------------+
+// COMMON OPTIONS
+//--------------------------------------------------------------------+
+/**
+ determines the debug level for the stack
+ - Level 3: ATTR_ALWAYS_INLINE is null, ASSERT has text, Error has its String, STATIC_VAR is NULL
+ - Level 2: ATTR_ALWAYS_INLINE is attribute, ASSERT has no text, Error has no strings
+ - Level 1: TBD
+ - Level 0: no debug information is generated
+*/
+#ifndef TUSB_CFG_DEBUG
+ #define TUSB_CFG_DEBUG 2
+ #warning TUSB_CFG_DEBUG is not defined, default value is 3
+#endif
+
+#ifndef TUSB_CFG_ATTR_USBRAM
+ #error TUSB_CFG_ATTR_USBRAM is not defined, please help me know how to place data in accessible RAM for usb controller
+#endif
+
+#if TUSB_CFG_OS == TUSB_OS_NONE
+ #ifndef TUSB_CFG_OS_TICKS_PER_SECOND
+ #error TUSB_CFG_OS_TICKS_PER_SECOND is required to use with OS_NONE
+ #endif
+#else
+ #ifndef TUSB_CFG_OS_TASK_PRIO
+ #error TUSB_CFG_OS_TASK_PRIO need to be defined (hint: use the highest if possible)
+ #endif
+#endif
+
+/**
+ * Maximum number of supported USB's configuration (currently only support only 1)
+ */
+#ifndef TUSB_CFG_CONFIGURATION_MAX
+ #define TUSB_CFG_CONFIGURATION_MAX 1
+ #warning TUSB_CFG_CONFIGURATION_MAX is not defined, default value is 1
+#endif
+
+//--------------------------------------------------------------------+
+// HOST OPTIONS
+//--------------------------------------------------------------------+
+#if MODE_HOST_SUPPORTED
+ #ifndef TUSB_CFG_HOST_DEVICE_MAX
+ #define TUSB_CFG_HOST_DEVICE_MAX 1
+ #warning TUSB_CFG_HOST_DEVICE_MAX is not defined, default value is 1
+ #endif
+
+ //------------- HUB CLASS -------------//
+ #if TUSB_CFG_HOST_HUB && (TUSB_CFG_HOST_DEVICE_MAX == 1)
+ #error there is no benefit enable hub with max device is 1. Please disable hub or increase TUSB_CFG_HOST_DEVICE_MAX
+ #endif
+
+ //------------- HID CLASS -------------//
+ #define HOST_CLASS_HID ( TUSB_CFG_HOST_HID_KEYBOARD + TUSB_CFG_HOST_HID_MOUSE + TUSB_CFG_HOST_HID_GENERIC )
+ #if HOST_CLASS_HID
+ #define HOST_HCD_XFER_INTERRUPT
+ #endif
+
+ #ifndef TUSB_CFG_HOST_ENUM_BUFFER_SIZE
+ #define TUSB_CFG_HOST_ENUM_BUFFER_SIZE 256
+ #warning TUSB_CFG_HOST_ENUM_BUFFER_SIZE is not defined, default value is 256
+ #endif
+
+ //------------- CLASS -------------//
+#endif // MODE_HOST_SUPPORTED
+
+//--------------------------------------------------------------------+
+// DEVICE OPTIONS
+//--------------------------------------------------------------------+
+#if MODE_DEVICE_SUPPORTED
+
+#if defined(CAP_DEVICE_ROMDRIVER) && !TUSB_CFG_DEVICE_USE_ROM_DRIVER
+ #error only rom driver for these mcu are supported now
+#endif
+
+#define DEVICE_CLASS_HID ( TUSB_CFG_DEVICE_HID_KEYBOARD + TUSB_CFG_DEVICE_HID_MOUSE + TUSB_CFG_DEVICE_HID_GENERIC )
+
+
+#endif // MODE_DEVICE_SUPPORTED
+
+
+
+#define USB_FS_MAX_BULK_PACKET 64
+#define USB_HS_MAX_BULK_PACKET USB_FS_MAX_BULK_PACKET /* Full speed device only */
+
+/* HID In/Out Endpoint Address */
+#define HID_KEYBOARD_EP_IN ENDPOINT_IN_LOGICAL_TO_PHYSICAL(1)
+#define HID_MOUSE_EP_IN ENDPOINT_IN_LOGICAL_TO_PHYSICAL(4)
+
+/* CDC Endpoint Address */
+#define CDC_NOTIFICATION_EP ENDPOINT_IN_LOGICAL_TO_PHYSICAL(2)
+#define CDC_DATA_EP_OUT ENDPOINT_OUT_LOGICAL_TO_PHYSICAL(3)
+#define CDC_DATA_EP_IN ENDPOINT_IN_LOGICAL_TO_PHYSICAL(3)
+
+#define CDC_NOTIFICATION_EP_MAXPACKETSIZE 8
+#define CDC_DATA_EP_MAXPACKET_SIZE 16
+
+#endif /* _TUSB_TUSB_OPTION_H_ */
+
+/** @} */