From 424735d44041fc478b572f973d997829b402153d Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 18 Jun 2018 14:05:24 +0700 Subject: rename subfolder source to src --- src/host/ehci/ehci.c | 1068 ++++++++++++++++++++++++++++++++++++++++++++++++++ src/host/ehci/ehci.h | 485 +++++++++++++++++++++++ src/host/hcd.c | 44 +++ src/host/hcd.h | 129 ++++++ src/host/hub.c | 251 ++++++++++++ src/host/hub.h | 210 ++++++++++ src/host/ohci/ohci.c | 710 +++++++++++++++++++++++++++++++++ src/host/ohci/ohci.h | 310 +++++++++++++++ src/host/usbh.c | 642 ++++++++++++++++++++++++++++++ src/host/usbh.h | 116 ++++++ src/host/usbh_hcd.h | 114 ++++++ src/host/usbh_hub.h | 64 +++ 12 files changed, 4143 insertions(+) create mode 100644 src/host/ehci/ehci.c create mode 100644 src/host/ehci/ehci.h create mode 100644 src/host/hcd.c create mode 100644 src/host/hcd.h create mode 100644 src/host/hub.c create mode 100644 src/host/hub.h create mode 100644 src/host/ohci/ohci.c create mode 100644 src/host/ohci/ohci.h create mode 100644 src/host/usbh.c create mode 100644 src/host/usbh.h create mode 100644 src/host/usbh_hcd.h create mode 100644 src/host/usbh_hub.h (limited to 'src/host') diff --git a/src/host/ehci/ehci.c b/src/host/ehci/ehci.c new file mode 100644 index 000000000..c9cd39378 --- /dev/null +++ b/src/host/ehci/ehci.c @@ -0,0 +1,1068 @@ +/**************************************************************************/ +/*! + @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/tusb_common.h" + +#if MODE_HOST_SUPPORTED && (CFG_TUSB_MCU == OPT_MCU_LPC43XX || CFG_TUSB_MCU == OPT_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 +//--------------------------------------------------------------------+ +CFG_TUSB_ATTR_USBRAM STATIC_VAR ehci_data_t ehci_data; + +#if EHCI_PERIODIC_LIST + + #if (CFG_TUSB_RHPORT0_MODE & OPT_MODE_HOST) + CFG_TUSB_ATTR_USBRAM ATTR_ALIGNED(4096) STATIC_VAR ehci_link_t period_frame_list0[EHCI_FRAMELIST_SIZE]; + + #ifndef __ICCARM__ // IAR cannot able to determine the alignment with datalignment pragma + VERIFY_STATIC( ALIGN_OF(period_frame_list0) == 4096, "Period Framelist must be 4k alginment"); // validation + #endif + #endif + + #if (CFG_TUSB_RHPORT1_MODE & OPT_MODE_HOST) + CFG_TUSB_ATTR_USBRAM ATTR_ALIGNED(4096) STATIC_VAR ehci_link_t period_frame_list1[EHCI_FRAMELIST_SIZE]; + + #ifndef __ICCARM__ // IAR cannot able to determine the alignment with datalignment pragma + VERIFY_STATIC( 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 ATTR_UNUSED; + +//--------------------------------------------------------------------+ +// USBH-HCD API +//--------------------------------------------------------------------+ +tusb_error_t hcd_init(void) +{ + //------------- Data Structure init -------------// + memclr_(&ehci_data, sizeof(ehci_data_t)); + + #if (CFG_TUSB_RHPORT0_MODE & OPT_MODE_HOST) + TU_ASSERT_ERR (hcd_controller_init(0)); + #endif + + #if (CFG_TUSB_RHPORT1_MODE & OPT_MODE_HOST) + TU_ASSERT_ERR (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; +} + +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 +} + +// 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 +} + +//--------------------------------------------------------------------+ +// 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; iterminate = 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; +} + +//--------------------------------------------------------------------+ +// 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 -------------// + 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) + { + TU_ASSERT_ERR( 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_desc_endpoint_t const * p_endpoint_desc, uint8_t class_code) +{ + pipe_handle_t const null_handle = { .dev_addr = 0, .xfer_type = 0, .index = 0 }; + + TU_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); + TU_ASSERT(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); + + TU_ASSERT(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) +{ + TU_ASSERT_ERR ( 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 head QTD to QHD 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) +{ + TU_ASSERT(pipe_hdl.dev_addr > 0, TUSB_ERROR_INVALID_PARA); + + TU_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 ) + { + TU_ASSERT_ERR( 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 + { + TU_ASSERT_ERR( 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_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) ? TUSB_DIR_IN_MASK : 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; + // TODO reset data toggle ? + 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 < CFG_TUSB_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; iunplug->…..-> plug if device is powering with pre-plugged device + if (regs->portsc_bit.current_connect_status) + { + hcd_port_reset(hostid); + usbh_hcd_rhport_plugged_isr(hostid); + }else // device unplugged + { + usbh_hcd_rhport_unplugged_isr(hostid); + } +} + +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 < HCD_MAX_XFER) + { + // 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 < HCD_MAX_ENDPOINT*CFG_TUSB_HOST_DEVICE_MAX); // 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 < (HCD_MAX_ENDPOINT + EHCI_MAX_ITD + EHCI_MAX_SITD)*CFG_TUSB_HOST_DEVICE_MAX) + { + 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: // TODO support hs/fs ISO + case EHCI_QUEUE_ELEMENT_SITD: + case EHCI_QUEUE_ELEMENT_FSTN: + + default: 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; + + +// if ( TUSB_EVENT_XFER_ERROR == error_event ) verify_breakpoint(); // TODO skip unplugged device + + 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 < HCD_MAX_ENDPOINT*CFG_TUSB_HOST_DEVICE_MAX); // 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 < (HCD_MAX_ENDPOINT + EHCI_MAX_ITD + EHCI_MAX_SITD)*CFG_TUSB_HOST_DEVICE_MAX) + { + 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; + + // TODO support hs/fs ISO + case EHCI_QUEUE_ELEMENT_ITD: + case EHCI_QUEUE_ELEMENT_SITD: + case EHCI_QUEUE_ELEMENT_FSTN: + default: break; + } + + next_item = *list_next(&next_item); + period_max_loop++; + } + } + #endif +} + +//------------- Host Controller Driver's Interrupt Handler -------------// +void hal_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 (CFG_TUSB_RHPORT0_MODE & OPT_MODE_HOST) + case 0: + return period_frame_list0; +#endif + +#if (CFG_TUSB_RHPORT1_MODE & OPT_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) && (CFG_TUSB_RHPORT1_MODE & OPT_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( indexdevice_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( indexnext.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 is used as 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) + { + TU_ASSERT( interval <= 16, 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 + { + TU_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 < HCD_MAX_ENDPOINT) + { + 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); + + TU_ASSERT(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/src/host/ehci/ehci.h b/src/host/ehci/ehci.h new file mode 100644 index 000000000..250023ee5 --- /dev/null +++ b/src/host/ehci/ehci.h @@ -0,0 +1,485 @@ +/**************************************************************************/ +/*! + @file ehci.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 Group_HCD + * @{ + * \defgroup EHCI + * \brief EHCI driver. All documents sources mentioned here (eg section 3.5) is referring to EHCI Specs unless state otherwise + * @{ */ + +#ifndef _TUSB_EHCI_H_ +#define _TUSB_EHCI_H_ + +#include "common/tusb_common.h" +#include "../hcd.h" + +/* Abbreviation + * HC: Host Controller + * HCD: Host Controller Driver + * QHD: Queue Head for non-ISO transfer + * QTD: Queue Transfer Descriptor for non-ISO transfer + * ITD: Iso Transfer Descriptor for highspeed + * SITD: Split ISO Transfer Descriptor for full-speed + * SMASK: Start Split mask for Slipt Transaction + * CMASK: Complete Split mask for Slipt Transaction + * RO: Read Only + * R/WC: Read, Write to Clear +*/ + +#ifdef __cplusplus + extern "C" { +#endif + +//--------------------------------------------------------------------+ +// EHCI CONFIGURATION & CONSTANTS +//--------------------------------------------------------------------+ +#define HOST_HCD_XFER_INTERRUPT // TODO interrupt is used widely, should always be enalbed +#define EHCI_PERIODIC_LIST (defined HOST_HCD_XFER_INTERRUPT || defined HOST_HCD_XFER_ISOCHRONOUS) + +#define EHCI_CFG_FRAMELIST_SIZE_BITS 7 /// Framelist Size (NXP specific) (0:1024) - (1:512) - (2:256) - (3:128) - (4:64) - (5:32) - (6:16) - (7:8) +#define EHCI_FRAMELIST_SIZE (1024 >> EHCI_CFG_FRAMELIST_SIZE_BITS) + +// TODO merge OHCI with EHCI +enum { + EHCI_MAX_ITD = 4, + EHCI_MAX_SITD = 16 +}; + +//------------- Validation -------------// +VERIFY_STATIC(EHCI_CFG_FRAMELIST_SIZE_BITS <= 7, "incorrect value"); + +//--------------------------------------------------------------------+ +// EHCI Data Structure +//--------------------------------------------------------------------+ +enum ehci_queue_element_type_{ + EHCI_QUEUE_ELEMENT_ITD = 0 , ///< 0 + EHCI_QUEUE_ELEMENT_QHD , ///< 1 + EHCI_QUEUE_ELEMENT_SITD , ///< 2 + EHCI_QUEUE_ELEMENT_FSTN ///< 3 +}; + +/// EHCI PID +enum tusb_pid_{ + EHCI_PID_OUT = 0 , + EHCI_PID_IN , + EHCI_PID_SETUP +}; + +/// Link pointer +typedef union { + uint32_t address; + struct { + uint32_t terminate : 1; + uint32_t type : 2; + }; +}ehci_link_t; + +/// Queue Element Transfer Descriptor (section 3.5) +typedef struct { + + /// Word 0: Next QTD Pointer + ehci_link_t next; + + /// Word 1: Alternate Next QTD Pointer (not used) + union{ + ehci_link_t alternate; + struct { + uint32_t : 5; + uint32_t used : 1; + uint32_t : 10; + uint32_t expected_bytes : 16; + }; + }; + + /// Word 2: qTQ Token + volatile uint32_t pingstate_err : 1 ; ///< If the QH.EPSfield indicates a High-speed device and the PID_Codeindicates an OUT endpoint, then this is the state bit for the Ping protocol. 0b=OUT 1b=PING + volatile uint32_t non_hs_split_state : 1 ; ///< This bit is ignored by the host controller unless the QH.EPSfield indicates a full- or low-speed endpoint. When a Full- or Low-speed device, the host controller uses this bit to track the state of the split-transaction. The functional requirements of the host controller for managing this state bit and the split transaction protocol depends on whether the endpoint is in the periodic or asynchronous schedule. 0b=Start Split 1b=Complete Split + volatile uint32_t non_hs_period_missed_uframe : 1 ; ///< This bit is ignored unless the QH.EPSfield indicates a full- or low-speed endpoint and the queue head is in the periodic list. This bit is set when the host controller detected that a host-induced hold-off caused the host controller to miss a required complete-split transaction. If the host controller sets this bit to a one, then it remains a one for the duration of the transfer. + volatile uint32_t xact_err : 1 ; ///< Set to a one by the Host Controller during status update in the case where the host did not receive a valid response from the device (Timeout, CRC, Bad PID, etc.) + volatile uint32_t babble_err : 1 ; ///< Set to a 1 by the Host Controller during status update when a babble is detected during the transaction. In addition to setting this bit, the Host Controller also sets the Haltedbit to a 1 + volatile uint32_t buffer_err : 1 ; ///< Set to a 1 by the Host Controller during status update to indicate that the Host Controller is unable to keep up with the reception of incoming data (overrun) or is unable to supply data fast enough during transmission (underrun) + volatile uint32_t halted : 1 ; ///< Set to a 1 by the Host Controller during status updates to indicate that a serious error has occurred at the device/endpoint addressed by this qTD. This can be caused by babble, the error counter counting down to zero, or reception of the STALL handshake from the device during a transaction. Any time that a transaction results in the Halted bit being set to a one, the Active bit is also set to 0 + volatile uint32_t active : 1 ; ///< Set to 1 by software to enable the execution of transactions by the Host Controller + + uint32_t pid : 2 ; ///< This field is an encoding of the token which should be used for transactions associated with this transfer descriptor. 00=OUT 01=IN 10=SETUP + volatile uint32_t cerr : 2 ; ///< Error Counter, This field is a 2-bit down counter that keeps track of the number of consecutive Errors detected while executing this qTD + volatile uint32_t current_page : 3 ; ///< This field is used as an index into the qTD buffer pointer list + uint32_t int_on_complete : 1 ; ///< If this bit is set to a one, it specifies that when this qTD is completed, the Host Controller should issue an interrupt at the next interrupt threshold + + volatile uint32_t total_bytes : 15 ; ///< This field specifies the total number of bytes to be moved with this transfer descriptor + volatile uint32_t data_toggle : 1 ; ///< This is the data toggle sequence bit + uint32_t : 0 ; // padding to the end of current storage unit + // End of Word 2 + + /// Buffer Page Pointer List, Each element in the list is a 4K page aligned, physical memory address. The lower 12 bits in each pointer are reserved (except for the first one) as each memory pointer must reference the start of a 4K page + uint32_t buffer[5]; +} ehci_qtd_t; // XXX qtd is used to declare overlay in ehci_qhd_t -> cannot be declared with ATTR_ALIGNED(32) + +VERIFY_STATIC( sizeof(ehci_qtd_t) == 32, "size is not correct" ); + +/// Queue Head (section 3.6) +typedef struct ATTR_ALIGNED(32) { + /// Word 0: Queue Head Horizontal Link Pointer + ehci_link_t next; + + /// Word 1 : Endpoint Characteristics + uint32_t device_address : 7 ; ///< This field selects the specific device serving as the data source or sink + uint32_t non_hs_period_inactive_next_xact : 1 ; ///< This bit is used by system software to request that the host controller set the Active bit to zero. See Section 4.12.2.5 for full operational details + uint32_t endpoint_number : 4 ; ///< This 4-bit field selects the particular endpoint number on the device serving as the data source or sink. + uint32_t endpoint_speed : 2 ; ///< This is the speed of the associated endpoint 00b=Full 01b=Low 10b=High 11b=Reserved + uint32_t data_toggle_control : 1 ; ///< This bit specifies where the host controller should get the initial data toggle on an overlay transition. 0b=Ignore DT bit of qTD, 1b=Use DT bit of qTD + uint32_t head_list_flag : 1 ; ///< This bit is set by System Software to mark a queue head as being the head of the reclamation list. See Section 4.8 for operational model + uint32_t max_package_size : 11 ; ///< This directly corresponds to the maximum packet size of the associated endpoint (wMaxPacketSize) + uint32_t non_hs_control_endpoint : 1 ; ///< If the QH.EPSfield indicates the endpoint is not a high-speed device, and the endpoint is an control endpoint, then software must set this bit to a one. Otherwise it should always set this bit to a zero. + uint32_t nak_count_reload : 4 ; ///< This field contains a value, which is used by the host controller to reload the Nak Counter field. + uint32_t : 0 ; // padding to the end of current storage unit + // End of Word 1 + + /// Word 2 : Endpoint Capabilities + uint32_t interrupt_smask : 8 ; ///< This field is used for all endpoint speeds. Software should set this field to a zero when the queue head is on the asynchronous schedule. A non-zero value in this field indicates an interrupt endpoint + uint32_t non_hs_interrupt_cmask : 8 ; ///< This field is ignored by the host controller unless the EPSfield indicates this device is a low- or full-speed device and this queue head is in the periodic list. This field (along with the Activeand SplitX-statefields) is used to determine during which micro-frames the host controller should execute a complete-split transaction + uint32_t hub_address : 7 ; ///< This field is ignored by the host controller unless the EPSfield indicates a full- or low-speed device. The value is the USB device address of the USB 2.0 Hub below which the full- or low-speed device associated with this endpoint is attached. This field is used in the split-transaction protocol. See Section 4.12. + uint32_t hub_port : 7 ; ///< This field is ignored by the host controller unless the EPSfield indicates a full- or low-speed device. The value is the port number identifier on the USB 2.0 Hub (for hub at device address Hub Addrbelow), below which the full- or low-speed device associated with this endpoint is attached. This information is used in the split-transaction protocol. See Section 4.12. + uint32_t mult : 2 ; ///< This field is a multiplier used to key the host controller as the number of successive packets the host controller may submit to the endpoint in the current execution. 00b=Reserved 01b,10b,11b= 1 (2, 3) Transaction for this endpoint/micro frame + uint32_t : 0 ; // padding to the end of current storage unit + // End of Word 2 + + /// Word 3: Current qTD Pointer + volatile uint32_t qtd_addr; + + /// Word 4-11: Transfer Overlay + volatile ehci_qtd_t qtd_overlay; + + //--------------------------------------------------------------------+ + /// Due to the fact QHD is 32 bytes aligned but occupies only 48 bytes + /// thus there are 16 bytes padding free that we can make use of. + //--------------------------------------------------------------------+ + uint8_t used; + uint8_t is_removing; + uint8_t pid_non_control; + uint8_t class_code; + + uint16_t total_xferred_bytes; // number of bytes xferred until a qtd with ioc bit set + uint8_t interval_ms; // polling interval in frames (or milisecond) + uint8_t reserved; + + ehci_qtd_t * volatile p_qtd_list_head; // head of the scheduled TD list + ehci_qtd_t * volatile p_qtd_list_tail; // tail of the scheduled TD list +} ehci_qhd_t; + +VERIFY_STATIC( sizeof(ehci_qhd_t) == 64, "size is not correct" ); + +/// Highspeed Isochronous Transfer Descriptor (section 3.3) +typedef struct ATTR_ALIGNED(32) { + /// Word 0: Next Link Pointer + ehci_link_t next; + + /// Word 1-8: iTD Transaction Status and Control List + struct { + // iTD Control + volatile uint32_t offset : 12 ; ///< This field is a value that is an offset, expressed in bytes, from the beginning of a buffer. + volatile uint32_t page_select : 3 ; ///< These bits are set by software to indicate which of the buffer page pointers the offset field in this slot should be concatenated to produce the starting memory address for this transaction. The valid range of values for this field is 0 to 6 + uint32_t int_on_complete : 1 ; ///< If this bit is set to a one, it specifies that when this transaction completes, the Host Controller should issue an interrupt at the next interrupt threshold + volatile uint32_t length : 12 ; ///< For an OUT, this field is the number of data bytes the host controller will send during the transaction. The host controller is not required to update this field to reflect the actual number of bytes transferred during the transfer + ///< For an IN, the initial value of the field is the number of bytes the host expects the endpoint to deliver. During the status update, the host controller writes back the number of bytes successfully received. The value in this register is the actual byte count + // iTD Status + volatile uint32_t error : 1 ; ///< Set to a one by the Host Controller during status update in the case where the host did not receive a valid response from the device (Timeout, CRC, Bad PID, etc.). This bit may only be set for isochronous IN transactions. + volatile uint32_t babble_err : 1 ; ///< Set to a 1 by the Host Controller during status update when a babble is detected during the transaction + volatile uint32_t buffer_err : 1 ; ///< Set to a 1 by the Host Controller during status update to indicate that the Host Controller is unable to keep up with the reception of incoming data (overrun) or is unable to supply data fast enough during transmission (underrun). + volatile uint32_t active : 1 ; ///< Set to 1 by software to enable the execution of an isochronous transaction by the Host Controller + } xact[8]; + + ///Word 9-15 Buffer Page Pointer List (Plus) + uint32_t BufferPointer[7]; + +// // FIXME: Store meta data into buffer pointer reserved for saving memory +// /*---------- HCD Area ----------*/ +// uint32_t used; +// uint32_t IhdIdx; +// uint32_t reserved[6]; +} ehci_itd_t; + +VERIFY_STATIC( sizeof(ehci_itd_t) == 64, "size is not correct" ); + +/// Split (Full-Speed) Isochronous Transfer Descriptor +typedef struct ATTR_ALIGNED(32) { + /// Word 0: Next Link Pointer + ehci_link_t next; + + /// Word 1: siTD Endpoint Characteristics + uint32_t device_address : 7; ///< This field selects the specific device serving as the data source or sink. + uint32_t : 1; ///< reserved + uint32_t endpoint_number : 4; ///< This 4-bit field selects the particular endpoint number on the device serving as the data source or sink. + uint32_t : 4; ///< This field is reserved and should be set to zero. + uint32_t hub_address : 7; ///< This field holds the device address of the transaction translators’ hub. + uint32_t : 1; ///< reserved + uint32_t port_number : 7; ///< This field is the port number of the recipient transaction translator. + uint32_t direction : 1; ///< 0 = OUT; 1 = IN. This field encodes whether the full-speed transaction should be an IN or OUT. + uint32_t : 0; // padding to the end of current storage unit + // End of Word 1 + + /// Word 2: Micro-frame Schedule Control + uint8_t interrupt_smask ; ///< This field (along with the Activeand SplitX-statefields in the Statusbyte) are used to determine during which micro-frames the host controller should execute complete-split transactions + uint8_t non_hs_interrupt_cmask ; ///< This field (along with the Activeand SplitX-statefields in the Statusbyte) are used to determine during which micro-frames the host controller should execute start-split transactions. + uint16_t reserved ; ///< reserved + // End of Word 2 + + /// Word 3: siTD Transfer Status and Control + // Status [7:0] TODO indentical to qTD Token'status --> refractor later + volatile uint32_t : 1 ; // reserved + volatile uint32_t split_state : 1 ; + volatile uint32_t missed_uframe : 1 ; + volatile uint32_t xact_err : 1 ; + volatile uint32_t babble_err : 1 ; + volatile uint32_t buffer_err : 1 ; + volatile uint32_t error : 1 ; + volatile uint32_t active : 1 ; + // Micro-frame Schedule Control + volatile uint32_t cmask_progress : 8 ; ///< This field is used by the host controller to record which split-completes have been executed. See Section 4.12.3.3.2 for behavioral requirements. + volatile uint32_t total_bytes : 10 ; ///< This field is initialized by software to the total number of bytes expected in this transfer. Maximum value is 1023 + volatile uint32_t : 4 ; ///< reserved + volatile uint32_t page_select : 1 ; ///< Used to indicate which data page pointer should be concatenated with the CurrentOffsetfield to construct a data buffer pointer + uint32_t int_on_complete : 1 ; ///< Do not interrupt when transaction is complete. 1 = Do interrupt when transaction is complete + uint32_t : 0 ; // padding to the end of current storage unit + // End of Word 3 + + /// Word 4-5: Buffer Pointer List + uint32_t buffer[2]; // buffer[1] TP: Transaction Position - T-Count: Transaction Count + +// union{ +// uint32_t BufferPointer1; +// struct { +// volatile uint32_t TCount : 3; +// volatile uint32_t TPosition : 2; +// }; +// }; + + /*---------- Word 6 ----------*/ + ehci_link_t back; + + /// SITD is 32-byte aligned but occupies only 28 --> 4 bytes for storing extra data + uint8_t used; + uint8_t ihd_idx; + uint8_t reserved2[2]; +} ehci_sitd_t; + +VERIFY_STATIC( sizeof(ehci_sitd_t) == 32, "size is not correct" ); + +//--------------------------------------------------------------------+ +// EHCI Operational Register +//--------------------------------------------------------------------+ +enum ehci_interrupt_mask_{ + EHCI_INT_MASK_USB = BIT_(0), + EHCI_INT_MASK_ERROR = BIT_(1), + EHCI_INT_MASK_PORT_CHANGE = BIT_(2), + + EHCI_INT_MASK_FRAMELIST_ROLLOVER = BIT_(3), + EHCI_INT_MASK_PCI_HOST_SYSTEM_ERROR = BIT_(4), + EHCI_INT_MASK_ASYNC_ADVANCE = BIT_(5), + EHCI_INT_MASK_NXP_SOF = BIT_(7), + + EHCI_INT_MASK_NXP_ASYNC = BIT_(18), + EHCI_INT_MASK_NXP_PERIODIC = BIT_(19), + + EHCI_INT_MASK_ALL = + EHCI_INT_MASK_USB | EHCI_INT_MASK_ERROR | EHCI_INT_MASK_PORT_CHANGE | + EHCI_INT_MASK_FRAMELIST_ROLLOVER | EHCI_INT_MASK_PCI_HOST_SYSTEM_ERROR | + EHCI_INT_MASK_ASYNC_ADVANCE | EHCI_INT_MASK_NXP_SOF | + EHCI_INT_MASK_NXP_ASYNC | EHCI_INT_MASK_NXP_PERIODIC +}; + +enum ehci_usbcmd_pos_ { + EHCI_USBCMD_POS_RUN_STOP = 0, + EHCI_USBCMD_POS_FRAMELIST_SZIE = 2, + EHCI_USBCMD_POS_PERIOD_ENABLE = 4, + EHCI_USBCMD_POS_ASYNC_ENABLE = 5, + EHCI_USBCMD_POS_NXP_FRAMELIST_SIZE_MSB = 15, + EHCI_USBCMD_POS_INTERRUPT_THRESHOLD = 16 +}; + +enum ehci_portsc_change_mask_{ + EHCI_PORTSC_MASK_CONNECT_STATUS_CHANGE = BIT_(1), + EHCI_PORTSC_MASK_PORT_ENABLE_CHAGNE = BIT_(3), + EHCI_PORTSC_MASK_OVER_CURRENT_CHANGE = BIT_(5), + + EHCI_PORTSC_MASK_ALL = + EHCI_PORTSC_MASK_CONNECT_STATUS_CHANGE | + EHCI_PORTSC_MASK_PORT_ENABLE_CHAGNE | + EHCI_PORTSC_MASK_OVER_CURRENT_CHANGE +}; + +typedef volatile struct { + union { + uint32_t usb_cmd ; ///< The Command Register indicates the command to be executed by the serial bus host controller. Writing to the register causes a command to be executed + struct { + uint32_t run_stop : 1 ; ///< Default 0b. 1=Run. 0=Stop. When set to a 1, the Host Controller proceeds with execution of the schedule. The Host Controller continues execution as long as this bit is set to a 1. When this bit is set to 0, the Host Controller completes the current and any actively pipelined transactions on the USB and then halts. The Host Controller must halt within 16 micro-frames after software clears the Run bit. The HC Halted bit in the status register indicates when the Host Controller has finished its pending pipelined transactions and has entered the stopped state. Software must not write a one to this field unless the host controller is in the Halted state (i.e. HCHaltedin the USBSTS register is a one). Doing so will yield undefined results. + uint32_t reset : 1 ; ///< his control bit is used by software to reset the host controller. The effects of this on Root Hub registers are similar to a Chip Hardware Reset. When software writes a one to this bit, the Host Controller resets its internal pipelines, timers, counters, state machines, etc. to their initial value. Any transaction currently in progress on USB is immediately terminated. A USB reset is not driven on downstream ports.This bit is set to zero by the Host Controller when the reset process is complete. Software cannot terminate the reset process early by writing a zero to this register. Software should not set this bit to a one when the HCHaltedbit in the USBSTS register is a zero. Attempting to reset an actively running host controller will result in undefined behavior. + uint32_t framelist_size : 2 ; ///< This field is R/W only if Programmable Frame List Flagin the HCCPARAMS registers is set to a one. This field specifies the size of the frame list.00b 1024 elements (4096 bytes) Default value 01b 512 elements (2048 bytes) 10b 256 elements (1024 bytes) + uint32_t periodic_enable : 1 ; ///< This bit controls whether the host controller skips processing the Periodic Schedule. Values mean: 0b Do not process the Periodic Schedule 1b Use the PERIODICLISTBASE register to access the Periodic Schedule. + uint32_t async_enable : 1 ; ///< This bit controls whether the host controller skips processing the Asynchronous Schedule. Values mean: 0b Do not process the Asynchronous Schedule 1b Use the ASYNCLISTADDR register to access the Asynchronous Schedule. + uint32_t advacne_async : 1 ; ///< This bit is used as a doorbell by software to tell the host controller to issue an interrupt the next time it advances asynchronous schedule. Software must write a 1 to this bit to ringthe doorbell. When the host controller has evicted all appropriate cached schedule state, it sets the Interrupt on Async Advancestatus bit in the USBSTS register. If the Interrupt on Async Advance Enablebit in the USBINTR register is a one then the host controller will assert an interrupt at the next interrupt threshold. See Section 4.8.2 for operational details. The host controller sets this bit to a zero after it has set the Interrupt on Async Advance status bit in the USBSTS register to a one. Software should not write a one to this bit when the asynchronous schedule is disabled. Doing so will yield undefined results. + uint32_t light_reset : 1 ; ///< This control bit is not required. If implemented, it allows the driver to reset the EHCI controller without affecting the state of the ports or the relationship to the companion host controllers. For example, the PORSTC registers should not be reset to their default values and the CF bit setting should not go to zero (retaining port ownership relationships). A host software read of this bit as zero indicates the Light Host Controller Reset has completed and it is safe for host software to re-initialize the host controller. A host software read of this bit as a one indicates the Light Host Controller Reset has not yet completed. + uint32_t async_park : 2 ; ///< It contains a count of the number of successive transactions the host controller is allowed to execute from a high-speed queue head on the Asynchronous schedule before continuing traversal of the Asynchronous schedule. See Section 4.10.3.2 for full operational details. Valid values are 1h to 3h. Software must not write a zero to this bit when Park Mode Enableis a one as this will result in undefined behavior. + uint32_t : 1 ; ///< reserved + uint32_t async_park_enable : 1 ; ///< Software uses this bit to enable or disable Park mode. When this bit is one, Park mode is enabled. When this bit is a zero, Park mode is disabled. + uint32_t : 3 ; ///< reserved + uint32_t nxp_framelist_size_msb : 1 ; ///< NXP customized : Bit 2 of the Frame List Size bits \n 011b: 128 elements \n 100b: 64 elements \n 101b: 32 elements \n 110b: 16 elements \n 111b: 8 elements + uint32_t int_threshold : 8 ; ///< Default 08h. This field is used by system software to select the maximum rate at which the host controller will issue interrupts. The only valid values are defined below. If software writes an invalid value to this register, the results are undefined. Value Maximum Interrupt Interval 00h Reserved 01h 1 micro-frame 02h 2 micro-frames 04h 4 micro-frames 08h 8 micro-frames (default, equates to 1 ms) 10h 16 micro-frames (2 ms) 20h 32 micro-frames (4 ms) 40h 64 micro-frames (8 ms) Refer to Section 4.15 for interrupts affected by this register. Any other value in this register yields undefined results. Software modifications to this bit while HCHalted bit is equal to zero results in undefined behavior. + uint32_t : 0 ; // padding to the boundary of storage unit + }usb_cmd_bit; + }; + + union { + uint32_t usb_sts ; ///< This register indicates pending interrupts and various states of the Host Controller. The status resulting from a transaction on the serial bus is not indicated in this register. Software sets a bit to 0 in this register by writing a 1 to it. See Section 4.15 for additional information concerning USB interrupt conditions. + struct { + uint32_t usb : 1 ; ///< R/WC The Host Controller sets this bit to 1 on the completion of a USB transaction, which results in the retirement of a Transfer Descriptor that had its IOC bit set. \n The Host Controller also sets this bit to 1 when a short packet is detected (actual number of bytes received was less than the expected number of bytes). + uint32_t usb_error : 1 ; ///< R/WC The Host Controller sets this bit to 1 when completion of a USB transaction results in an error condition (e.g., error counter underflow). If the TD on which the error interrupt occurred also had its IOC bit set, both this bit and USBINT bit are set. See Section 4.15.1 for a list of the USB errors that will result in this bit being set to a one. + uint32_t port_change_detect : 1 ; ///< R/WC The Host Controller sets this bit to a one when any port for which the Port Ownerbit is set to zero (see Section 2.3.9) has a change bit transition from a zero to a one or a Force Port Resumebit transition from a zero to a one as a result of a J-K transition detected on a suspended port. + uint32_t framelist_rollover : 1 ; ///< R/WC The Host Controller sets this bit to a one when the Frame List Index(see Section 2.3.4) rolls over from its maximum value to zero. The exact value at which the rollover occurs depends on the frame list size. For example, if the frame list size (as programmed in the Frame List Sizefield of the USBCMD register) is 1024, the Frame Index Registerrolls over every time FRINDEX[13] toggles. Similarly, if the size is 512, the Host Controller sets this bit to a one every time FRINDEX[12] toggles. + uint32_t pci_host_system_error : 1 ; ///< R/WC (not used by NXP) The Host Controller sets this bit to 1 when a serious error occurs during a host system access involving the Host Controller module. In a PCI system, conditions that set this bit to 1 include PCI Parity error, PCI Master Abort, and PCI Target Abort. When this error occurs, the Host Controller clears the Run/Stop bit in the Command register to prevent further execution of the scheduled TDs. + uint32_t async_advance : 1 ; ///< R/WC 0=Default. System software can force the host controller to issue an interrupt the next time the host controller advances the asynchronous schedule by writing a one to the Interrupt on Async Advance Doorbell bit in the USBCMD register. This status bit indicates the assertion of that interrupt source. + uint32_t : 1 ; ///< These bits are reserved and should be set to zero. + uint32_t nxp_int_sof : 1 ; ///< R/WC NXP customized: this bit will be set every 125us and can be used by host controller driver as a time base. + uint32_t : 4 ; ///< These bits are reserved and should be set to zero. + uint32_t hc_halted : 1 ; ///< Read-Only 1=Default. This bit is a zero whenever the Run/Stop bit is a one. The Host Controller sets this bit to one after it has stopped executing as a result of the Run/Stop bit being set to 0, either by software or by the Host Controller hardware (e.g. internal error). + uint32_t reclamation : 1 ; ///< Read-Only 0=Default. This is a read-only status bit, which is used to detect an empty asynchronous schedule. The operational model of empty schedule detection is described in Section 4.8.3. The valid transitions for this bit are described in Section 4.8.6. + uint32_t period_schedule_status : 1 ; ///< Read-Only The bit reports the current real status of the Periodic Schedule. If this bit is a zero then the status of the Periodic Schedule is disabled. If this bit is a one then the status of the Periodic Schedule is enabled + uint32_t async_schedule_status : 1 ; ///< Read-Only 0=Default. The bit reports the current real status of the Asynchronous Schedule. If this bit is a zero then the status of the Asynchronous Schedule is disabled. If this bit is a one then the status of the Asynchronous Schedule is enabled. + uint32_t : 2 ; ///< reseved + uint32_t nxp_int_async : 1 ; ///< R/WC NXP customized: This bit is set by the Host Controller when the cause of an interrupt is a completion of a USB transaction where the Transfer Descriptor (TD) has an interrupt on complete (IOC) bit set andthe TD was from the asynchronous schedule. This bit is also set by the Host when a short packet is detected andthe packet is on the asynchronous schedule. + uint32_t nxp_int_period : 1 ; ///< R/WC NXP customized: This bit is set by the Host Controller when the cause of an interrupt is a completion of a USB transaction where the Transfer Descriptor (TD) has an interrupt on complete (IOC) bit set andthe TD was from the periodic schedule. + uint32_t : 12 ; ///< reserved + uint32_t : 0 ; // padding to the boundary of storage unit + }usb_sts_bit; + }; + + union{ + uint32_t usb_int_enable ; ///< This register enables and disables reporting of the corresponding interrupt to the software. When a bit is set and the corresponding interrupt is active, an interrupt is generated to the host. Interrupt sources that are disabled in this register still appear in the USBSTS to allow the software to poll for events. + struct { + uint32_t usb : 1 ; ///< When this bit is a one, and the USBINT bit in the USBSTS register is a one, the host controller will issue an interrupt at the next interrupt threshold. The interrupt is acknowledged by software clearing the USBINTbit. + uint32_t usb_error : 1 ; ///< When this bit is a one, and the USBERRINT bit in the USBSTS register is a one, the host controller will issue an interrupt at the next interrupt threshold. The interrupt is acknowledged by software clearing the USBERRINTbit. + uint32_t port_change_detect : 1 ; ///< When this bit is a one, and the Port Change Detect bit in the USBSTS register is a one, the host controller will issue an interrupt. The interrupt is acknowledged by software clearing the Port Change Detectbit. + uint32_t framelist_rollover : 1 ; ///< When this bit is a one, and the Frame List Rolloverbit in the USBSTS register is a one, the host controller will issue an interrupt. The interrupt is acknowledged by software clearing the Frame List Rollover bit. + uint32_t pci_host_system_error : 1 ; ///< (not used by NXP) When this bit is a one, and the Host System Error Statusbit in the USBSTS register is a one, the host controller will issue an interrupt. The interrupt is acknowledged by software clearing the Host System Error bit. + uint32_t async_advance : 1 ; ///< When this bit is a one, and the Interrupt on Async Advancebit in the USBSTS register is a one, the host controller will issue an interrupt at the next interrupt threshold. The interrupt is acknowledged by software clearing the Interrupt on Async Advancebit. + uint32_t : 1 ; ///< reserved + uint32_t nxp_int_sof : 1 ; ///< NXP customized: if this bit is one and the SRI bit in the USBSTS register is one, the host controller will issue an interrupt. In host mode, the SRI bit will be set every 125 micro sec and can be used by the host controller as a time base. The interrupt is acknowledged by software clearing the SRI bit in the USBSTS register. + uint32_t : 10 ; ///< reserved + uint32_t nxp_int_async : 1 ; ///< NXP customized: When this bit is a one, and the USBHSTASYNCINT bit in the USBSTS register is a one, the host controller will issue an interrupt at the next interrupt threshold. The interrupt is acknowledged by software clearing the USBHSTASYNCINT bit. + uint32_t nxp_int_period : 1 ; ///< NXP customized: When this bit is a one, and the USBHSTPERINT bit in the USBSTS register is a one, the host controller will issue an interrupt at the next interrupt threshold. The interrupt is acknowledged by software clearing the USBHSTPERINT bit. + uint32_t : 12 ; ///< reserved + uint32_t : 0 ; // padding to the boundary of storage unit + }usb_int_enable_bit; + }; + + uint32_t frame_index ; ///< This register is used by the host controller to index into the periodic frame list. The register updates every 125 microseconds (once each micro-frame). Bits [N:3] are used to select a particular entry in the Periodic Frame List during periodic schedule execution. The number of bits used for the index depends on the size of the frame list as set by system software in the Frame List Sizefield in the USBCMD register + uint32_t ctrl_ds_seg ; ///< (not used by NXP) This 32-bit register corresponds to the most significant address bits [63:32] for all EHCI data structures. If the 64-bit Addressing Capabilityfield in HCCPARAMS is a zero, then this register is not used + uint32_t periodic_list_base ; ///< This 32-bit register contains the beginning address of the Periodic Frame List in the system memory. System software loads this register prior to starting the schedule execution by the Host Controller (see 4.1). The memory structure referenced by this physical memory pointer is assumed to be 4-Kbyte aligned. The contents of this register are combined with the Frame Index Register (FRINDEX) to enable the Host Controller to step through the Periodic Frame List in sequence. + uint32_t async_list_base ; ///< This 32-bit register contains the address of the next asynchronous queue head to be executed. Bits [4:0] of this register cannot be modified by system software and will always return a zero when read. The memory structure referenced by this physical memory pointer is assumed to be 32-byte (cache line) aligned + uint32_t tt_control ; ///< nxp embedded transaction translator (reserved by EHCI specs) + uint32_t reserved[8] ; ///< reserved by EHCI specs + uint32_t config_flag ; ///< (not used by NXP) configured flag register + + union { + uint32_t portsc ; ///< port status and control + struct { + uint32_t current_connect_status : 1; ///< RO 1=Device is present on port. 0=No device is present. Default = 0. This value reflects the current state of the port, and may not correspond directly to the event that caused the Connect Status Change bit (Bit 1) to be set. This field is zero if Port Power is zero. + uint32_t connect_status_change : 1; ///< R/WC 1=Change in Current Connect Status. 0=No change. Default = 0. Indicates a change has occurred in the port's Current Connect Status. The host controller sets this bit for all changes to the port device connect status, even if system software has not cleared an existing connect status change. For example, the insertion status changes twice before system software has cleared the changed condition, hub hardware will be "setting" an already-set bit (i.e., the bit will remain set). Software sets this bit to 0 by writing a 1 to it. This field is zero if Port Power is zero. + uint32_t port_enable : 1; ///< 1=Enable. 0=Disable. Default = 0. Ports can only be enabled by the host controller as a part of the reset and enable. Software cannot enable a port by writing a one to this field. The host controller will only set this bit to a one when the reset sequence determines that the attached device is a high-speed device. Ports can be disabled by either a fault condition (disconnect event or other fault condition) or by host software. Note that the bit status does not change until the port state actually changes. + uint32_t port_enable_change : 1; ///< R/WC 1=Port enabled/disabled status has changed. 0=No change. Default = 0. For the root hub, this bit gets set to a one only when a port is disabled due to the appropriate conditions existing at the EOF2 point (See Chapter 11 of the USB Specification for the definition of a Port Error). Software clears this bit by writing a 1 to it. This field is zero if Port Power is zero. + uint32_t over_current_active : 1; ///< RO Default = 0. 1=This port currently has an over-current condition. 0=This port does not have an over-current condition. This bit will automatically transition from a one to a zero when the over current condition is removed. + uint32_t over_current_change : 1; ///< R/WC Default = 0. 1=This bit gets set to a one when there is a change to Over-current Active. Software clears this bit by writing a one to this bit position. + uint32_t force_port_resume : 1; ///< 1= Resume detected/driven on port. 0=No resume (K-state) detected/driven on port. Default = 0. This functionality defined for manipulating this bit depends on the value of the Suspendbit. For example, if the port is not suspended (Suspendand Enabledbits are a one) and software transitions this bit to a one, then the effects on the bus are undefined. Software sets this bit to a 1 to drive resume signaling. The Host Controller sets this bit to a 1 if a J-to-K transition is detected while the port is in the Suspend state. When this bit transitions to a one because a J-to-K transition is detected, the Port Change Detectbit in the USBSTS register is also set to a one. If software sets this bit to a one, the host controller must not set the Port Change Detectbit. + uint32_t suspend : 1; ///< 1=Port in suspend state. 0=Port not in suspend state. Default = 0. Port Enabled Bit and Suspend bit of this register define the port states as follows: Bits [Port Enabled, Suspend] Port State 0X Disable 10 Enable 11 Suspend When in suspend state, downstream propagation of data is blocked on this port, except for port reset. The blocking occurs at the end of the current transaction, if a transaction was in progress when this bit was written to 1. In the suspend state, the port is sensitive to resume detection. Note that the bit status does not change until the port is suspended and that there may be a delay in suspending a port if there is a transaction currently in progress on the USB. A write of zero to this bit is ignored by the host controller. The host controller will unconditionally set this bit to a zero when: •Software sets the Force Port Resumebit to a zero (from a one). •Software sets the Port Resetbit to a one (from a zero). + uint32_t port_reset : 1; ///< 1=Port is in Reset. 0=Port is not in Reset. Default = 0. When software writes a one to this bit (from a zero) + uint32_t nxp_highspeed_status : 1; ///< NXP customized: 0=connected to the port is not in High-speed mode, 1=connected to the port is in High-speed mode + uint32_t line_status : 2; ///< hese bits reflect the current logical levels of the D+ (bit 11) and D- (bit 10) signal lines. These bits are used for detection of low-speed USB devices prior to the port reset and enable sequence. This field is valid only when the port enable bit is zero and the current connect status bit is set to a one. The encoding of the bits are: 00b SE0, 10b J-state, 01b K-state, 11b undefined + uint32_t port_power : 1; ///< 0= power off, 1= power on, Host/OTG controller requires port power control switches. This bit represents the current setting of the switch (0=off, 1=on). When power is not available on a port (i.e. PP equals a 0), the port is non-functional and will not report attaches, detaches, etc. When an over-current condition is detected on a powered port and PPC is a one, the PP bit in each affected port may be transitioned by the host controller driver from a one to a zero (removing power from the port). + uint32_t port_owner : 1; ///< (not used by NXP) + uint32_t port_indicator_control : 2; ///< Writing to this field effects the value of the pins USB0_IND1 and USB0_IND0. 00b: Port indication is off, 01b: Amber, 10b: green, 11b: undefined + uint32_t port_test_control : 4; ///< When this field is zero, the port is NOT operating in a test mode. A non-zero value indicates that it is operating in test mode + uint32_t wake_on_connect_enable : 1; ///< Default = 0b. Writing this bit to a one enables the port to be sensitive to device connects as wake-up events. See Section 4.3 for effects of this bit on resume event behavior. Refer to Section 4.3.1 for operational model. + uint32_t wake_on_disconnect_enable : 1; ///< Default = 0b. Writing this bit to a one enables the port to be sensitive to device disconnects as wake-up events. See Section 4.3 for effects of this bit on resume event behavior. Refer to Section 4.3.1 for operational model. + uint32_t wake_on_over_current_enable : 1; ///< Default = 0b. Writing this bit to a one enables the port to be sensitive to over-current conditions as wake-up events. See Section 4.3 for effects of this bit on resume event behavior. Refer to Section 4.3.1 for operational model. + uint32_t nxp_phy_clock_disable : 1; ///< NXP customized: the PHY can be put into Low Power Suspend – Clock Disable when the downstream device has been put into suspend mode or when no downstream device is connected. Low power suspend is completely under the control of software. 0: enable PHY clock, 1: disable PHY clock + uint32_t nxp_port_force_fullspeed : 1; ///< NXP customized: Writing this bit to a 1 will force the port to only connect at Full Speed. It disables the chirp sequence that allowsthe port to identify itself as High Speed. This is useful for testing FS configurations with a HS host, hub or device. + uint32_t : 1; + uint32_t nxp_port_speed : 2; ///< NXP customized: This register field indicates the speed atwhich the port is operating. For HS mode operation in the host controllerand HS/FS operation in the device controller the port routing steers data to the Protocol engine. For FS and LS mode operation in the host controller, the port routing steers data to the Protocol Engine w/ Embedded Transaction Translator. 0x0: Fullspeed, 0x1: Lowspeed, 0x2: Highspeed + uint32_t : 0; // padding to the boundary of storage unit + }portsc_bit; + }; +}ehci_registers_t; + +//--------------------------------------------------------------------+ +// EHCI Data Organization +//--------------------------------------------------------------------+ +typedef struct { + //------------- Static Async/Period List Head, Each for one controller -------------// + ehci_qhd_t async_head[CONTROLLER_HOST_NUMBER]; /// head qhd of async list, also is used as control endpoint for address 0 + +#if EHCI_PERIODIC_LIST + // for NXP ECHI, only implement 1 ms & 2 ms & 4 ms, 8 ms (framelist) + // [0] : 1ms, [1] : 2ms, [2] : 4ms, [3] : 8 ms + ehci_qhd_t period_head_arr[CONTROLLER_HOST_NUMBER][4]; +#endif + + //------------- Data for Address 0 (use async head as its queue head) -------------// + ehci_qtd_t addr0_qtd[3]; + + struct { + struct { + ehci_qhd_t qhd; + ehci_qtd_t qtd[3]; + }control; + + ehci_qhd_t qhd[HCD_MAX_ENDPOINT] ; ///< Queue Head Pool + ehci_qtd_t qtd[HCD_MAX_XFER] ATTR_ALIGNED(32) ; ///< Queue Element Transfer Pool +// ehci_itd_t itd[EHCI_MAX_ITD] ; ///< Iso Transfer Pool +// ehci_sitd_t sitd[EHCI_MAX_SITD] ; ///< Split (FS) Isochronous Transfer Pool + }device[CFG_TUSB_HOST_DEVICE_MAX]; +}ehci_data_t; + +#ifdef __cplusplus + } +#endif + +#endif /* _TUSB_EHCI_H_ */ + +/** @} */ +/** @} */ + diff --git a/src/host/hcd.c b/src/host/hcd.c new file mode 100644 index 000000000..092ca96da --- /dev/null +++ b/src/host/hcd.c @@ -0,0 +1,44 @@ +/**************************************************************************/ +/*! + @file hcd.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 "hcd.h" + +#if MODE_HOST_SUPPORTED + + +#endif diff --git a/src/host/hcd.h b/src/host/hcd.h new file mode 100644 index 000000000..b9f6a1ff7 --- /dev/null +++ b/src/host/hcd.h @@ -0,0 +1,129 @@ +/**************************************************************************/ +/*! + @file hcd.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 group_usbh + * \defgroup Group_HCD Host Controller Driver (HCD) + * @{ */ + +#ifndef _TUSB_HCD_H_ +#define _TUSB_HCD_H_ + +#ifdef __cplusplus + extern "C" { +#endif + +#include + +#if MODE_HOST_SUPPORTED +// Max number of endpoints per device +enum { + HCD_MAX_ENDPOINT = CFG_TUSB_HOST_HUB + CFG_TUSB_HOST_HID_KEYBOARD + CFG_TUSB_HOST_HID_MOUSE + CFG_TUSB_HOST_HID_GENERIC + + CFG_TUSB_HOST_MSC*2 + CFG_TUSB_HOST_CDC*3, + + HCD_MAX_XFER = HCD_MAX_ENDPOINT*2, +}; +#endif + +//--------------------------------------------------------------------+ +// MACRO CONSTANT TYPEDEF +//--------------------------------------------------------------------+ +typedef struct { + uint8_t dev_addr; + uint8_t xfer_type; + uint8_t index; + uint8_t reserved; +} pipe_handle_t; + +static inline bool pipehandle_is_valid(pipe_handle_t pipe_hdl) ATTR_CONST ATTR_ALWAYS_INLINE ATTR_WARN_UNUSED_RESULT; +static inline bool pipehandle_is_valid(pipe_handle_t pipe_hdl) +{ + return pipe_hdl.dev_addr > 0; +} + +static inline bool pipehandle_is_equal(pipe_handle_t x, pipe_handle_t y) ATTR_CONST ATTR_ALWAYS_INLINE ATTR_WARN_UNUSED_RESULT; +static inline bool pipehandle_is_equal(pipe_handle_t x, pipe_handle_t y) +{ + return (x.dev_addr == y.dev_addr) && (x.xfer_type == y.xfer_type) && (x.index == y.index); +} + +//--------------------------------------------------------------------+ +// USBH-HCD API +//--------------------------------------------------------------------+ +tusb_error_t hcd_init(void) ATTR_WARN_UNUSED_RESULT; +void hal_hcd_isr(uint8_t hostid); + +//--------------------------------------------------------------------+ +// PIPE API +//--------------------------------------------------------------------+ +// TODO control xfer should be used via usbh layer +tusb_error_t hcd_pipe_control_open(uint8_t dev_addr, uint8_t max_packet_size) ATTR_WARN_UNUSED_RESULT; +tusb_error_t hcd_pipe_control_xfer(uint8_t dev_addr, tusb_control_request_t const * p_request, uint8_t data[]) ATTR_WARN_UNUSED_RESULT; +tusb_error_t hcd_pipe_control_close(uint8_t dev_addr) ATTR_WARN_UNUSED_RESULT; + +pipe_handle_t hcd_pipe_open(uint8_t dev_addr, tusb_desc_endpoint_t const * endpoint_desc, uint8_t class_code) ATTR_WARN_UNUSED_RESULT; +tusb_error_t hcd_pipe_queue_xfer(pipe_handle_t pipe_hdl, uint8_t buffer[], uint16_t total_bytes) ATTR_WARN_UNUSED_RESULT; // only queue, not transferring yet +tusb_error_t hcd_pipe_xfer(pipe_handle_t pipe_hdl, uint8_t buffer[], uint16_t total_bytes, bool int_on_complete) ATTR_WARN_UNUSED_RESULT; +tusb_error_t hcd_pipe_close(pipe_handle_t pipe_hdl) /*ATTR_WARN_UNUSED_RESULT*/; + +bool hcd_pipe_is_busy(pipe_handle_t pipe_hdl) ATTR_PURE; +bool hcd_pipe_is_error(pipe_handle_t pipe_hdl) ATTR_PURE; +bool hcd_pipe_is_stalled(pipe_handle_t pipe_hdl) ATTR_PURE; // stalled also counted as error + +uint8_t hcd_pipe_get_endpoint_addr(pipe_handle_t pipe_hdl) ATTR_PURE; +tusb_error_t hcd_pipe_clear_stall(pipe_handle_t pipe_hdl); + +#if 0 +tusb_error_t hcd_pipe_cancel()ATTR_WARN_UNUSED_RESULT; +#endif + +//--------------------------------------------------------------------+ +// PORT API +//--------------------------------------------------------------------+ +/// return the current connect status of roothub port +bool hcd_port_connect_status(uint8_t hostid) ATTR_PURE ATTR_WARN_UNUSED_RESULT; // TODO make inline if possible +void hcd_port_reset(uint8_t hostid); +tusb_speed_t hcd_port_speed_get(uint8_t hostid) ATTR_PURE ATTR_WARN_UNUSED_RESULT; // TODO make inline if possible +void hcd_port_unplug(uint8_t hostid); // called by usbh to instruct hcd that it can execute unplug procedure + +#ifdef __cplusplus + } +#endif + +#endif /* _TUSB_HCD_H_ */ + +/// @} diff --git a/src/host/hub.c b/src/host/hub.c new file mode 100644 index 000000000..063cef61a --- /dev/null +++ b/src/host/hub.c @@ -0,0 +1,251 @@ +/**************************************************************************/ +/*! + @file hub.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 && CFG_TUSB_HOST_HUB) + +#define _TINY_USB_SOURCE_FILE_ + +//--------------------------------------------------------------------+ +// INCLUDE +//--------------------------------------------------------------------+ +#include "hub.h" +#include "usbh_hub.h" + +//--------------------------------------------------------------------+ +// MACRO CONSTANT TYPEDEF +//--------------------------------------------------------------------+ +typedef struct { + pipe_handle_t pipe_status; + uint8_t interface_number; + uint8_t port_number; + uint8_t status_change; // data from status change interrupt endpoint +}usbh_hub_t; + +CFG_TUSB_ATTR_USBRAM STATIC_VAR usbh_hub_t hub_data[CFG_TUSB_HOST_DEVICE_MAX]; +ATTR_ALIGNED(4) CFG_TUSB_ATTR_USBRAM STATIC_VAR uint8_t hub_enum_buffer[sizeof(descriptor_hub_desc_t)]; + +//OSAL_SEM_DEF(hub_enum_semaphore); +//static osal_semaphore_handle_t hub_enum_sem_hdl; + +//--------------------------------------------------------------------+ +// HUB +//--------------------------------------------------------------------+ +tusb_error_t hub_port_clear_feature_subtask(uint8_t hub_addr, uint8_t hub_port, uint8_t feature) +{ + tusb_error_t error; + + OSAL_SUBTASK_BEGIN + + STASK_ASSERT(HUB_FEATURE_PORT_CONNECTION_CHANGE <= feature && + feature <= HUB_FEATURE_PORT_RESET_CHANGE); + + //------------- Clear Port Feature request -------------// + STASK_INVOKE( + usbh_control_xfer_subtask( hub_addr, bm_request_type(TUSB_DIR_OUT, TUSB_REQ_TYPE_CLASS, TUSB_REQ_RCPT_OTHER), + HUB_REQUEST_CLEAR_FEATURE, feature, hub_port, + 0, NULL ), + error + ); + STASK_ASSERT_ERR( error ); + + //------------- Get Port Status to check if feature is cleared -------------// + STASK_INVOKE( + usbh_control_xfer_subtask( hub_addr, bm_request_type(TUSB_DIR_IN, TUSB_REQ_TYPE_CLASS, TUSB_REQ_RCPT_OTHER), + HUB_REQUEST_GET_STATUS, 0, hub_port, + 4, hub_enum_buffer ), + error + ); + STASK_ASSERT_ERR( error ); + + //------------- Check if feature is cleared -------------// + hub_port_status_response_t * p_port_status; + p_port_status = (hub_port_status_response_t *) hub_enum_buffer; + + STASK_ASSERT( !BIT_TEST_(p_port_status->status_change.value, feature-16) ); + + OSAL_SUBTASK_END +} + +tusb_error_t hub_port_reset_subtask(uint8_t hub_addr, uint8_t hub_port) +{ + enum { RESET_DELAY = 200 }; // USB specs say only 50ms but many devices require much longer + tusb_error_t error; + + OSAL_SUBTASK_BEGIN + + //------------- Set Port Reset -------------// + STASK_INVOKE( + usbh_control_xfer_subtask( hub_addr, bm_request_type(TUSB_DIR_OUT, TUSB_REQ_TYPE_CLASS, TUSB_REQ_RCPT_OTHER), + HUB_REQUEST_SET_FEATURE, HUB_FEATURE_PORT_RESET, hub_port, + 0, NULL ), + error + ); + STASK_ASSERT_ERR( error ); + + osal_task_delay(RESET_DELAY); // TODO Hub wait for Status Endpoint on Reset Change + + //------------- Get Port Status to check if port is enabled, powered and reset_change -------------// + STASK_INVOKE( + usbh_control_xfer_subtask( hub_addr, bm_request_type(TUSB_DIR_IN, TUSB_REQ_TYPE_CLASS, TUSB_REQ_RCPT_OTHER), + HUB_REQUEST_GET_STATUS, 0, hub_port, + 4, hub_enum_buffer ), + error + ); + STASK_ASSERT_ERR( error ); + + hub_port_status_response_t * p_port_status; + p_port_status = (hub_port_status_response_t *) hub_enum_buffer; + + STASK_ASSERT ( p_port_status->status_change.reset && p_port_status->status_current.connect_status && + p_port_status->status_current.port_power && p_port_status->status_current.port_enable); + + OSAL_SUBTASK_END +} + +// can only get the speed RIGHT AFTER hub_port_reset_subtask call +tusb_speed_t hub_port_get_speed(void) +{ + hub_port_status_response_t * p_port_status = (hub_port_status_response_t *) hub_enum_buffer; + return (p_port_status->status_current.high_speed_device_attached) ? TUSB_SPEED_HIGH : + (p_port_status->status_current.low_speed_device_attached ) ? TUSB_SPEED_LOW : TUSB_SPEED_FULL; +} + +//--------------------------------------------------------------------+ +// CLASS-USBH API (don't require to verify parameters) +//--------------------------------------------------------------------+ +void hub_init(void) +{ + memclr_(hub_data, CFG_TUSB_HOST_DEVICE_MAX*sizeof(usbh_hub_t)); +// hub_enum_sem_hdl = osal_semaphore_create( OSAL_SEM_REF(hub_enum_semaphore) ); +} + +tusb_error_t hub_open_subtask(uint8_t dev_addr, tusb_desc_interface_t const *p_interface_desc, uint16_t *p_length) +{ + tusb_error_t error; + + OSAL_SUBTASK_BEGIN + + // not support multiple TT yet + if ( p_interface_desc->bInterfaceProtocol > 1 ) return TUSB_ERROR_HUB_FEATURE_NOT_SUPPORTED; + + //------------- Open Interrupt Status Pipe -------------// + tusb_desc_endpoint_t const *p_endpoint; + p_endpoint = (tusb_desc_endpoint_t const *) descriptor_next( (uint8_t const*) p_interface_desc ); + + STASK_ASSERT(TUSB_DESC_ENDPOINT == p_endpoint->bDescriptorType); + STASK_ASSERT(TUSB_XFER_INTERRUPT == p_endpoint->bmAttributes.xfer); + + hub_data[dev_addr-1].pipe_status = hcd_pipe_open(dev_addr, p_endpoint, TUSB_CLASS_HUB); + STASK_ASSERT( pipehandle_is_valid(hub_data[dev_addr-1].pipe_status) ); + hub_data[dev_addr-1].interface_number = p_interface_desc->bInterfaceNumber; + + (*p_length) = sizeof(tusb_desc_interface_t) + sizeof(tusb_desc_endpoint_t); + + //------------- Get Hub Descriptor -------------// + STASK_INVOKE( + usbh_control_xfer_subtask( dev_addr, bm_request_type(TUSB_DIR_IN, TUSB_REQ_TYPE_CLASS, TUSB_REQ_RCPT_DEVICE), + HUB_REQUEST_GET_DESCRIPTOR, 0, 0, + sizeof(descriptor_hub_desc_t), hub_enum_buffer ), + error + ); + STASK_ASSERT_ERR(error); + + // only care about this field in hub descriptor + hub_data[dev_addr-1].port_number = ((descriptor_hub_desc_t*) hub_enum_buffer)->bNbrPorts; + + //------------- Set Port_Power on all ports -------------// + static uint8_t i; + for(i=1; i <= hub_data[dev_addr-1].port_number; i++) + { + STASK_INVOKE( + usbh_control_xfer_subtask( dev_addr, bm_request_type(TUSB_DIR_OUT, TUSB_REQ_TYPE_CLASS, TUSB_REQ_RCPT_OTHER), + HUB_REQUEST_SET_FEATURE, HUB_FEATURE_PORT_POWER, i, + 0, NULL ), + error + ); + } + + //------------- Queue the initial Status endpoint transfer -------------// + STASK_ASSERT_ERR ( hcd_pipe_xfer(hub_data[dev_addr-1].pipe_status, &hub_data[dev_addr-1].status_change, 1, true) ); + + OSAL_SUBTASK_END +} + +// is the response of interrupt endpoint polling +void hub_isr(pipe_handle_t pipe_hdl, tusb_event_t event, uint32_t xferred_bytes) +{ + (void) xferred_bytes; // TODO can be more than 1 for hub with lots of ports + + usbh_hub_t * p_hub = &hub_data[pipe_hdl.dev_addr-1]; + + if ( event == TUSB_EVENT_XFER_COMPLETE ) + { + for (uint8_t port=1; port <= p_hub->port_number; port++) + { // TODO HUB ignore bit0 hub_status_change + if ( BIT_TEST_(p_hub->status_change, port) ) + { + usbh_hub_port_plugged_isr(pipe_hdl.dev_addr, port); + break; // handle one port at a time, next port if any will be handled in the next cycle + } + } + // NOTE: next status transfer is queued by usbh.c after handling this request + } + else + { + // TODO [HUB] check if hub is still plugged before polling status endpoint since failed usually mean hub unplugged +// TU_ASSERT ( TUSB_ERROR_NONE == hcd_pipe_xfer(pipe_hdl, &p_hub->status_change, 1, true) ); + } +} + +void hub_close(uint8_t dev_addr) +{ + (void) hcd_pipe_close(hub_data[dev_addr-1].pipe_status); + memclr_(&hub_data[dev_addr-1], sizeof(usbh_hub_t)); + +// osal_semaphore_reset(hub_enum_sem_hdl); +} + +tusb_error_t hub_status_pipe_queue(uint8_t dev_addr) +{ + return hcd_pipe_xfer(hub_data[dev_addr-1].pipe_status, &hub_data[dev_addr-1].status_change, 1, true); +} + + +#endif diff --git a/src/host/hub.h b/src/host/hub.h new file mode 100644 index 000000000..b8499275c --- /dev/null +++ b/src/host/hub.h @@ -0,0 +1,210 @@ +/**************************************************************************/ +/*! + @file hub.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 group_class + * \defgroup ClassDriver_Hub Hub (Host only) + * \details Like most PC's OS, Hub support is completely hidden from Application. In fact, application cannot determine whether + * a device is mounted directly via roothub or via a hub's port. All Hub-related procedures are performed and managed + * by tinyusb stack. Unless you are trying to develop the stack itself, there are nothing else can be used by Application. + * \note Due to my laziness, only 1-level of Hub is supported. In other way, the stack cannot mount a hub via another hub. + * @{ + */ + +#ifndef _TUSB_HUB_H_ +#define _TUSB_HUB_H_ + +#include +#include "usbh.h" + +#ifdef __cplusplus + extern "C" { +#endif + +//D1...D0: Logical Power Switching Mode +//00: Ganged power switching (all ports’power at +//once) +//01: Individual port power switching +//1X: Reserved. Used only on 1.0 compliant hubs +//that implement no power switching +//D2: Identifies a Compound Device +//0: Hub is not part of a compound device. +//1: Hub is part of a compound device. +//D4...D3: Over-current Protection Mode +//00: Global Over-current Protection. The hub +//reports over-current as a summation of all +//ports’current draw, without a breakdown of +//individual port over-current status. +//01: Individual Port Over-current Protection. The +//hub reports over-current on a per-port basis. +//Each port has an over-current status. +//1X: No Over-current Protection. This option is +//allowed only for bus-powered hubs that do not +//implement over-current protection. +// +//D6...D5: TT Think TIme +//00: TT requires at most 8 FS bit times of inter +//transaction gap on a full-/low-speed +//downstream bus. +//01: TT requires at most 16 FS bit times. +//10: TT requires at most 24 FS bit times. +//11: TT requires at most 32 FS bit times. +//D7: Port Indicators Supported +//0: Port Indicators are not supported on its +//downstream facing ports and the +//PORT_INDICATOR request has no effect. +//1: Port Indicators are supported on its +//downstream facing ports and the +//PORT_INDICATOR request controls the +//indicators. See Section 11.5.3. +//D15...D8: Reserved + +typedef struct ATTR_PACKED{ + uint8_t bLength ; ///< Size of descriptor + uint8_t bDescriptorType ; ///< Other_speed_Configuration Type + uint8_t bNbrPorts; + uint16_t wHubCharacteristics; + uint8_t bPwrOn2PwrGood; + uint8_t bHubContrCurrent; + uint8_t DeviceRemovable; // bitmap each bit for a port (from bit1) + uint8_t PortPwrCtrlMask; // just for compatibility, should be 0xff +} descriptor_hub_desc_t; + +VERIFY_STATIC( sizeof(descriptor_hub_desc_t) == 9, "size is not correct"); + +enum { + HUB_REQUEST_GET_STATUS = 0 , + HUB_REQUEST_CLEAR_FEATURE = 1 , + + HUB_REQUEST_SET_FEATURE = 3 , + + HUB_REQUEST_GET_DESCRIPTOR = 6 , + HUB_REQUEST_SET_DESCRIPTOR = 7 , + HUB_REQUEST_CLEAR_TT_BUFFER = 8 , + HUB_REQUEST_RESET_TT = 9 , + HUB_REQUEST_GET_TT_STATE = 10 , + HUB_REQUEST_STOP_TT = 11 +}; + +enum { + HUB_FEATURE_HUB_LOCAL_POWER_CHANGE = 0, + HUB_FEATURE_HUB_OVER_CURRENT_CHANGE +}; + +enum{ + HUB_FEATURE_PORT_CONNECTION = 0, + HUB_FEATURE_PORT_ENABLE = 1, + HUB_FEATURE_PORT_SUSPEND = 2, + HUB_FEATURE_PORT_OVER_CURRENT = 3, + HUB_FEATURE_PORT_RESET = 4, + + HUB_FEATURE_PORT_POWER = 8, + HUB_FEATURE_PORT_LOW_SPEED = 9, + + HUB_FEATURE_PORT_CONNECTION_CHANGE = 16, + HUB_FEATURE_PORT_ENABLE_CHANGE = 17, + HUB_FEATURE_PORT_SUSPEND_CHANGE = 18, + HUB_FEATURE_PORT_OVER_CURRENT_CHANGE = 19, + HUB_FEATURE_PORT_RESET_CHANGE = 20, + HUB_FEATURE_PORT_TEST = 21, + HUB_FEATURE_PORT_INDICATOR = 22 +}; + +// data in response of HUB_REQUEST_GET_STATUS, wIndex = 0 (hub) +typedef struct { + union{ + struct ATTR_PACKED { + uint16_t local_power_source : 1; + uint16_t over_current : 1; + uint16_t : 14; + }; + + uint16_t value; + } status, status_change; +} hub_status_response_t; + +VERIFY_STATIC( sizeof(hub_status_response_t) == 4, "size is not correct"); + +// data in response of HUB_REQUEST_GET_STATUS, wIndex = Port num +typedef struct { + union { + struct ATTR_PACKED { + uint16_t connect_status : 1; + uint16_t port_enable : 1; + uint16_t suspend : 1; + uint16_t over_current : 1; + uint16_t reset : 1; + + uint16_t : 3; + uint16_t port_power : 1; + uint16_t low_speed_device_attached : 1; + uint16_t high_speed_device_attached : 1; + uint16_t port_test_mode : 1; + uint16_t port_indicator_control : 1; + uint16_t : 0; + }; + + uint16_t value; + } status_current, status_change; +} hub_port_status_response_t; + +VERIFY_STATIC( sizeof(hub_port_status_response_t) == 4, "size is not correct"); + +tusb_error_t hub_port_reset_subtask(uint8_t hub_addr, uint8_t hub_port); +tusb_error_t hub_port_clear_feature_subtask(uint8_t hub_addr, uint8_t hub_port, uint8_t feature); +tusb_speed_t hub_port_get_speed(void); +tusb_error_t hub_status_pipe_queue(uint8_t dev_addr); + +//--------------------------------------------------------------------+ +// USBH-CLASS DRIVER API +//--------------------------------------------------------------------+ +#ifdef _TINY_USB_SOURCE_FILE_ + +void hub_init(void); +tusb_error_t hub_open_subtask(uint8_t dev_addr, tusb_desc_interface_t const *p_interface_desc, uint16_t *p_length) ATTR_WARN_UNUSED_RESULT; +void hub_isr(pipe_handle_t pipe_hdl, tusb_event_t event, uint32_t xferred_bytes); +void hub_close(uint8_t dev_addr); + +#endif + +#ifdef __cplusplus + } +#endif + +#endif /* _TUSB_HUB_H_ */ + +/** @} */ diff --git a/src/host/ohci/ohci.c b/src/host/ohci/ohci.c new file mode 100644 index 000000000..5788aac94 --- /dev/null +++ b/src/host/ohci/ohci.c @@ -0,0 +1,710 @@ +/**************************************************************************/ +/*! + @file ohci.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 + +#if MODE_HOST_SUPPORTED && (CFG_TUSB_MCU == OPT_MCU_LPC175X_6X) +//--------------------------------------------------------------------+ +// INCLUDE +//--------------------------------------------------------------------+ +#include "hal/hal.h" +#include "osal/osal.h" +#include "common/timeout_timer.h" + +#include "../hcd.h" +#include "../usbh_hcd.h" +#include "ohci.h" + +//--------------------------------------------------------------------+ +// MACRO CONSTANT TYPEDEF +//--------------------------------------------------------------------+ +#define OHCI_REG ((ohci_registers_t *) LPC_USB_BASE) + +enum { + OHCI_CONTROL_FUNCSTATE_RESET = 0, + OHCI_CONTROL_FUNCSTATE_RESUME, + OHCI_CONTROL_FUNCSTATE_OPERATIONAL, + OHCI_CONTROL_FUNCSTATE_SUSPEND +}; + +enum { + OHCI_CONTROL_CONTROL_BULK_RATIO = 3, ///< This specifies the service ratio between Control and Bulk EDs. 0 = 1:1, 3 = 4:1 + OHCI_CONTROL_LIST_PERIODIC_ENABLE_MASK = BIT_(2), + OHCI_CONTROL_LIST_ISOCHRONOUS_ENABLE_MASK = BIT_(3), + OHCI_CONTROL_LIST_CONTROL_ENABLE_MASK = BIT_(4), + OHCI_CONTROL_LIST_BULK_ENABLE_MASK = BIT_(5), +}; + +enum { + OHCI_FMINTERVAL_FI = 0x2EDF, // 7.3.1 nominal (reset) value + OHCI_FMINTERVAL_FSMPS = (6*(OHCI_FMINTERVAL_FI-210)) / 7, // 5.4 calculated based on maximum overhead + bit stuffing +}; + +enum { + OHCI_PERIODIC_START = 0x3E67 +}; + +#ifdef __CC_ARM +#pragma diag_suppress 66 // Suppress Keil warnings #66-D: enumeration value is out of "int" range +#endif + +enum { + OHCI_INT_SCHEDULING_OVERUN_MASK = BIT_(0), + OHCI_INT_WRITEBACK_DONEHEAD_MASK = BIT_(1), + OHCI_INT_SOF_MASK = BIT_(2), + OHCI_INT_RESUME_DETECTED_MASK = BIT_(3), + OHCI_INT_UNRECOVERABLE_ERROR_MASK = BIT_(4), + OHCI_INT_FRAME_OVERFLOW_MASK = BIT_(5), + OHCI_INT_RHPORT_STATUS_CHANGE_MASK = BIT_(6), + + OHCI_INT_OWNERSHIP_CHANGE_MASK = BIT_(30), + OHCI_INT_MASTER_ENABLE_MASK = BIT_(31), +}; + +#ifdef __CC_ARM +#pragma diag_default 66 // return Keil 66 to normal severity +#endif + +enum { + OHCI_RHPORT_CURRENT_CONNECT_STATUS_MASK = BIT_(0), + OHCI_RHPORT_PORT_ENABLE_STATUS_MASK = BIT_(1), + OHCI_RHPORT_PORT_SUSPEND_STATUS_MASK = BIT_(2), + OHCI_RHPORT_PORT_OVER_CURRENT_INDICATOR_MASK = BIT_(3), + OHCI_RHPORT_PORT_RESET_STATUS_MASK = BIT_(4), ///< write '1' to reset port + + OHCI_RHPORT_PORT_POWER_STATUS_MASK = BIT_(8), + OHCI_RHPORT_LOW_SPEED_DEVICE_ATTACHED_MASK = BIT_(9), + + OHCI_RHPORT_CONNECT_STATUS_CHANGE_MASK = BIT_(16), + OHCI_RHPORT_PORT_ENABLE_CHANGE_MASK = BIT_(17), + OHCI_RHPORT_PORT_SUSPEND_CHANGE_MASK = BIT_(18), + OHCI_RHPORT_OVER_CURRENT_CHANGE_MASK = BIT_(19), + OHCI_RHPORT_PORT_RESET_CHANGE_MASK = BIT_(20), + + OHCI_RHPORT_ALL_CHANGE_MASK = OHCI_RHPORT_CONNECT_STATUS_CHANGE_MASK | OHCI_RHPORT_PORT_ENABLE_CHANGE_MASK | + OHCI_RHPORT_PORT_SUSPEND_CHANGE_MASK | OHCI_RHPORT_OVER_CURRENT_CHANGE_MASK | OHCI_RHPORT_PORT_RESET_CHANGE_MASK +}; + +enum { + OHCI_CCODE_NO_ERROR = 0, + OHCI_CCODE_CRC = 1, + OHCI_CCODE_BIT_STUFFING = 2, + OHCI_CCODE_DATA_TOGGLE_MISMATCH = 3, + OHCI_CCODE_STALL = 4, + OHCI_CCODE_DEVICE_NOT_RESPONDING = 5, + OHCI_CCODE_PID_CHECK_FAILURE = 6, + OHCI_CCODE_UNEXPECTED_PID = 7, + OHCI_CCODE_DATA_OVERRUN = 8, + OHCI_CCODE_DATA_UNDERRUN = 9, + OHCI_CCODE_BUFFER_OVERRUN = 12, + OHCI_CCODE_BUFFER_UNDERRUN = 13, + OHCI_CCODE_NOT_ACCESSED = 14, +}; + +enum { + OHCI_INT_ON_COMPLETE_YES = 0, + OHCI_INT_ON_COMPLETE_NO = BIN8(111) +}; +//--------------------------------------------------------------------+ +// INTERNAL OBJECT & FUNCTION DECLARATION +//--------------------------------------------------------------------+ +CFG_TUSB_ATTR_USBRAM ATTR_ALIGNED(256) STATIC_VAR ohci_data_t ohci_data; + +static ohci_ed_t * const p_ed_head[] = +{ + [TUSB_XFER_CONTROL] = &ohci_data.control[0].ed, + [TUSB_XFER_BULK ] = &ohci_data.bulk_head_ed, + [TUSB_XFER_INTERRUPT] = &ohci_data.period_head_ed, + [TUSB_XFER_ISOCHRONOUS] = NULL // TODO Isochronous +}; + +static void ed_list_insert(ohci_ed_t * p_pre, ohci_ed_t * p_ed); +static void ed_list_remove(ohci_ed_t * p_head, ohci_ed_t * p_ed); + +static ohci_ed_t * ed_list_find_previous(ohci_ed_t const * p_head, ohci_ed_t const * p_ed); + +//--------------------------------------------------------------------+ +// USBH-HCD API +//--------------------------------------------------------------------+ +// Initialization according to 5.1.1.4 +tusb_error_t hcd_init(void) +{ + //------------- Data Structure init -------------// + memclr_(&ohci_data, sizeof(ohci_data_t)); + for(uint8_t i=0; i<32; i++) + { // assign all interrupt pointes to period head ed + ohci_data.hcca.interrupt_table[i] = (uint32_t) &ohci_data.period_head_ed; + } + + ohci_data.control[0].ed.skip = 1; + ohci_data.bulk_head_ed.skip = 1; + ohci_data.period_head_ed.skip = 1; + + // reset controller + OHCI_REG->command_status_bit.controller_reset = 1; + while( OHCI_REG->command_status_bit.controller_reset ) {} // should not take longer than 10 us + + //------------- init ohci registers -------------// + OHCI_REG->control_head_ed = (uint32_t) &ohci_data.control[0].ed; + OHCI_REG->bulk_head_ed = (uint32_t) &ohci_data.bulk_head_ed; + OHCI_REG->hcca = (uint32_t) &ohci_data.hcca; + + OHCI_REG->interrupt_disable = OHCI_REG->interrupt_enable; // disable all interrupts + OHCI_REG->interrupt_status = OHCI_REG->interrupt_status; // clear current set bits + OHCI_REG->interrupt_enable = OHCI_INT_WRITEBACK_DONEHEAD_MASK | OHCI_INT_RESUME_DETECTED_MASK | + OHCI_INT_UNRECOVERABLE_ERROR_MASK | /*OHCI_INT_FRAME_OVERFLOW_MASK |*/ OHCI_INT_RHPORT_STATUS_CHANGE_MASK | + OHCI_INT_MASTER_ENABLE_MASK; + + OHCI_REG->control |= OHCI_CONTROL_CONTROL_BULK_RATIO | OHCI_CONTROL_LIST_CONTROL_ENABLE_MASK | + OHCI_CONTROL_LIST_BULK_ENABLE_MASK | OHCI_CONTROL_LIST_PERIODIC_ENABLE_MASK; // TODO Isochronous + + OHCI_REG->frame_interval = (OHCI_FMINTERVAL_FSMPS << 16) | OHCI_FMINTERVAL_FI; + OHCI_REG->periodic_start = (OHCI_FMINTERVAL_FI * 9) / 10; // Periodic start is 90% of frame interval + + OHCI_REG->control_bit.hc_functional_state = OHCI_CONTROL_FUNCSTATE_OPERATIONAL; // make HC's state to operational state TODO use this to suspend (save power) + OHCI_REG->rh_status_bit.local_power_status_change = 1; // set global power for ports + + return TUSB_ERROR_NONE; +} + +//--------------------------------------------------------------------+ +// PORT API +//--------------------------------------------------------------------+ +void hcd_port_reset(uint8_t hostid) +{ + OHCI_REG->rhport_status[0] = OHCI_RHPORT_PORT_RESET_STATUS_MASK; +} + +bool hcd_port_connect_status(uint8_t hostid) +{ + return OHCI_REG->rhport_status_bit[0].current_connect_status; +} + +tusb_speed_t hcd_port_speed_get(uint8_t hostid) +{ + return OHCI_REG->rhport_status_bit[0].low_speed_device_attached ? TUSB_SPEED_LOW : TUSB_SPEED_FULL; +} + +// TODO refractor abtract later +void hcd_port_unplug(uint8_t hostid) +{ + // TODO OHCI +} + +//--------------------------------------------------------------------+ +// Controller API +//--------------------------------------------------------------------+ + +//--------------------------------------------------------------------+ +// CONTROL PIPE API +//--------------------------------------------------------------------+ +static inline tusb_xfer_type_t ed_get_xfer_type(ohci_ed_t const * const p_ed) ATTR_PURE ATTR_ALWAYS_INLINE; +static inline tusb_xfer_type_t ed_get_xfer_type(ohci_ed_t const * const p_ed) +{ + return (p_ed->endpoint_number == 0 ) ? TUSB_XFER_CONTROL : + (p_ed->is_iso ) ? TUSB_XFER_ISOCHRONOUS : + (p_ed->is_interrupt_xfer ) ? TUSB_XFER_INTERRUPT : TUSB_XFER_BULK; +} + +static void ed_init(ohci_ed_t *p_ed, uint8_t dev_addr, uint16_t max_packet_size, uint8_t endpoint_addr, uint8_t xfer_type, uint8_t interval) +{ + // address 0 is used as async head, which always on the list --> cannot be cleared + if (dev_addr != 0) + { + memclr_(p_ed, sizeof(ohci_ed_t)); + } + + p_ed->device_address = dev_addr; + p_ed->endpoint_number = endpoint_addr & 0x0F; + p_ed->direction = (xfer_type == TUSB_XFER_CONTROL) ? OHCI_PID_SETUP : ( (endpoint_addr & TUSB_DIR_IN_MASK) ? OHCI_PID_IN : OHCI_PID_OUT ); + p_ed->speed = usbh_devices[dev_addr].speed; + p_ed->is_iso = (xfer_type == TUSB_XFER_ISOCHRONOUS) ? 1 : 0; + p_ed->max_package_size = max_packet_size; + + p_ed->used = 1; + p_ed->is_interrupt_xfer = (xfer_type == TUSB_XFER_INTERRUPT ? 1 : 0); +} + +static void gtd_init(ohci_gtd_t* p_td, void* data_ptr, uint16_t total_bytes) +{ + memclr_(p_td, sizeof(ohci_gtd_t)); + + p_td->used = 1; + p_td->expected_bytes = total_bytes; + + p_td->buffer_rounding = 1; // less than queued length is not a error + p_td->delay_interrupt = OHCI_INT_ON_COMPLETE_NO; + p_td->condition_code = OHCI_CCODE_NOT_ACCESSED; + + p_td->current_buffer_pointer = data_ptr; + p_td->buffer_end = total_bytes ? (((uint8_t*) data_ptr) + total_bytes-1) : NULL; +} + +tusb_error_t hcd_pipe_control_open(uint8_t dev_addr, uint8_t max_packet_size) +{ + ohci_ed_t* const p_ed = &ohci_data.control[dev_addr].ed; + + ed_init(p_ed, dev_addr, max_packet_size, 0, TUSB_XFER_CONTROL, 0); // TODO binterval of control is ignored + + if ( dev_addr != 0 ) + { // insert to control head + ed_list_insert( p_ed_head[TUSB_XFER_CONTROL], p_ed); + }else + { + p_ed->skip = 0; // addr0 is used as static control head --> only need to clear skip bit + } + + 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[]) +{ + ohci_ed_t* const p_ed = &ohci_data.control[dev_addr].ed; + + ohci_gtd_t *p_setup = &ohci_data.control[dev_addr].gtd[0]; + ohci_gtd_t *p_data = p_setup + 1; + ohci_gtd_t *p_status = p_setup + 2; + + //------------- SETUP Phase -------------// + gtd_init(p_setup, (void*) p_request, 8); + p_setup->index = dev_addr; + p_setup->pid = OHCI_PID_SETUP; + p_setup->data_toggle = BIN8(10); // DATA0 + p_setup->next_td = (uint32_t) p_data; + + //------------- DATA Phase -------------// + if (p_request->wLength > 0) + { + gtd_init(p_data, data, p_request->wLength); + p_data->index = dev_addr; + p_data->pid = p_request->bmRequestType_bit.direction ? OHCI_PID_IN : OHCI_PID_OUT; + p_data->data_toggle = BIN8(11); // DATA1 + }else + { + p_data = p_setup; + } + p_data->next_td = (uint32_t) p_status; + + //------------- STATUS Phase -------------// + gtd_init(p_status, NULL, 0); // zero-length data + p_status->index = dev_addr; + p_status->pid = p_request->bmRequestType_bit.direction ? OHCI_PID_OUT : OHCI_PID_IN; // reverse direction of data phase + p_status->data_toggle = BIN8(11); // DATA1 + p_status->delay_interrupt = OHCI_INT_ON_COMPLETE_YES; + + //------------- Attach TDs list to Control Endpoint -------------// + p_ed->td_head.address = (uint32_t) p_setup; + + OHCI_REG->command_status_bit.control_list_filled = 1; + + return TUSB_ERROR_NONE; +} + +tusb_error_t hcd_pipe_control_close(uint8_t dev_addr) +{ + ohci_ed_t* const p_ed = &ohci_data.control[dev_addr].ed; + + if ( dev_addr == 0 ) + { // addr0 serves as static head --> only set skip bitx + p_ed->skip = 1; + }else + { + ed_list_remove( p_ed_head[ ed_get_xfer_type(p_ed)], p_ed ); + + // TODO refractor to be USBH + usbh_devices[dev_addr].state = TUSB_DEVICE_STATE_UNPLUG; + } + + return TUSB_ERROR_NONE; +} + +//--------------------------------------------------------------------+ +// BULK/INT/ISO PIPE API +//--------------------------------------------------------------------+ +static inline uint8_t ed_get_index(ohci_ed_t const * const p_ed) ATTR_PURE ATTR_ALWAYS_INLINE; +static inline uint8_t ed_get_index(ohci_ed_t const * const p_ed) +{ + return p_ed - ohci_data.device[p_ed->device_address-1].ed; +} + +static inline ohci_ed_t * ed_from_pipe_handle(pipe_handle_t pipe_hdl) ATTR_PURE ATTR_ALWAYS_INLINE; +static inline ohci_ed_t * ed_from_pipe_handle(pipe_handle_t pipe_hdl) +{ + return &ohci_data.device[pipe_hdl.dev_addr-1].ed[pipe_hdl.index]; +} + +static inline ohci_ed_t * ed_find_free(uint8_t dev_addr) ATTR_PURE ATTR_ALWAYS_INLINE; +static inline ohci_ed_t * ed_find_free(uint8_t dev_addr) +{ + for(uint8_t i = 0; i < HCD_MAX_ENDPOINT; i++) + { + if ( !ohci_data.device[dev_addr-1].ed[i].used ) + { + return &ohci_data.device[dev_addr-1].ed[i]; + } + } + + return NULL; +} + +static ohci_ed_t * ed_list_find_previous(ohci_ed_t const * p_head, ohci_ed_t const * p_ed) +{ + uint32_t max_loop = HCD_MAX_ENDPOINT*CFG_TUSB_HOST_DEVICE_MAX; + + ohci_ed_t const * p_prev = p_head; + + TU_ASSERT(p_prev, NULL); + + while ( align16(p_prev->next_ed) != 0 && /* not reach null */ + align16(p_prev->next_ed) != (uint32_t) p_ed && /* not found yet */ + max_loop > 0) + { + p_prev = (ohci_ed_t const *) align16(p_prev->next_ed); + max_loop--; + } + + return ( align16(p_prev->next_ed) == (uint32_t) p_ed ) ? (ohci_ed_t*) p_prev : NULL; +} + +static void ed_list_insert(ohci_ed_t * p_pre, ohci_ed_t * p_ed) +{ + p_ed->next_ed |= p_pre->next_ed; // to reserve 4 lsb bits + p_pre->next_ed = (p_pre->next_ed & 0x0FUL) | ((uint32_t) p_ed); +} + +static void ed_list_remove(ohci_ed_t * p_head, ohci_ed_t * p_ed) +{ + ohci_ed_t * const p_prev = ed_list_find_previous(p_head, p_ed); + + p_prev->next_ed = (p_prev->next_ed & 0x0fUL) | align16(p_ed->next_ed); + // point the removed ED's next pointer to list head to make sure HC can always safely move away from this ED + p_ed->next_ed = (uint32_t) p_head; + p_ed->used = 0; // free ED +} + +pipe_handle_t hcd_pipe_open(uint8_t dev_addr, tusb_desc_endpoint_t const * p_endpoint_desc, uint8_t class_code) +{ + pipe_handle_t const null_handle = { .dev_addr = 0, .xfer_type = 0, .index = 0 }; + + // TODO iso support + TU_ASSERT(p_endpoint_desc->bmAttributes.xfer != TUSB_XFER_ISOCHRONOUS, null_handle ); + + //------------- Prepare Queue Head -------------// + ohci_ed_t * const p_ed = ed_find_free(dev_addr); + TU_ASSERT(p_ed, null_handle); + + ed_init( p_ed, dev_addr, p_endpoint_desc->wMaxPacketSize.size, p_endpoint_desc->bEndpointAddress, + p_endpoint_desc->bmAttributes.xfer, p_endpoint_desc->bInterval ); + p_ed->td_tail.class_code = class_code; + + ed_list_insert( p_ed_head[p_endpoint_desc->bmAttributes.xfer], p_ed ); + + return (pipe_handle_t) + { + .dev_addr = dev_addr, + .xfer_type = p_endpoint_desc->bmAttributes.xfer, + .index = ed_get_index(p_ed) + }; +} + +static ohci_gtd_t * gtd_find_free(uint8_t dev_addr) +{ + for(uint8_t i=0; i < HCD_MAX_XFER; i++) + { + if (!ohci_data.device[dev_addr-1].gtd[i].used) + { + return &ohci_data.device[dev_addr-1].gtd[i]; + } + } + + return NULL; +} + +static void td_insert_to_ed(ohci_ed_t* p_ed, ohci_gtd_t * p_gtd) +{ + // tail is always NULL + if ( align16(p_ed->td_head.address) == 0 ) + { // TD queue is empty --> head = TD + p_ed->td_head.address |= (uint32_t) p_gtd; + } + else + { // TODO currently only support queue up to 2 TD each endpoint at a time + ((ohci_gtd_t*) align16(p_ed->td_head.address))->next_td = (uint32_t) p_gtd; + } +} + +static tusb_error_t pipe_queue_xfer(pipe_handle_t pipe_hdl, uint8_t buffer[], uint16_t total_bytes, bool int_on_complete) +{ + ohci_ed_t* const p_ed = ed_from_pipe_handle(pipe_hdl); + + if ( !p_ed->is_iso ) + { + ohci_gtd_t * const p_gtd = gtd_find_free(pipe_hdl.dev_addr); + TU_ASSERT(p_gtd, TUSB_ERROR_EHCI_NOT_ENOUGH_QTD); // TODO refractor error code + + gtd_init(p_gtd, buffer, total_bytes); + p_gtd->index = pipe_hdl.index; + if ( int_on_complete ) p_gtd->delay_interrupt = OHCI_INT_ON_COMPLETE_YES; + + td_insert_to_ed(p_ed, p_gtd); + }else + { + TU_ASSERT_ERR(TUSB_ERROR_NOT_SUPPORTED_YET); + } + + return TUSB_ERROR_NONE; +} + +tusb_error_t hcd_pipe_queue_xfer(pipe_handle_t pipe_hdl, uint8_t buffer[], uint16_t total_bytes) +{ + return pipe_queue_xfer(pipe_hdl, buffer, total_bytes, false); +} + +tusb_error_t hcd_pipe_xfer(pipe_handle_t pipe_hdl, uint8_t buffer[], uint16_t total_bytes, bool int_on_complete) +{ + TU_ASSERT_ERR( pipe_queue_xfer(pipe_hdl, buffer, total_bytes, true) ); + + tusb_xfer_type_t xfer_type = ed_get_xfer_type( ed_from_pipe_handle(pipe_hdl) ); + + if (TUSB_XFER_BULK == xfer_type) OHCI_REG->command_status_bit.bulk_list_filled = 1; + + return TUSB_ERROR_NONE; +} + +/// pipe_close should only be called as a part of unmount/safe-remove process +// endpoints are tied to an address, which only reclaim after a long delay when enumerating +// thus there is no need to make sure ED is not in HC's cahed as it will not for sure +tusb_error_t hcd_pipe_close(pipe_handle_t pipe_hdl) +{ + ohci_ed_t * const p_ed = ed_from_pipe_handle(pipe_hdl); + + ed_list_remove( p_ed_head[ ed_get_xfer_type(p_ed)], p_ed ); + + return TUSB_ERROR_FAILED; +} + +bool hcd_pipe_is_busy(pipe_handle_t pipe_hdl) +{ + ohci_ed_t const * const p_ed = ed_from_pipe_handle(pipe_hdl); + return align16(p_ed->td_head.address) != align16(p_ed->td_tail.address); +} + +bool hcd_pipe_is_error(pipe_handle_t pipe_hdl) +{ + ohci_ed_t const * const p_ed = ed_from_pipe_handle(pipe_hdl); + return p_ed->td_head.halted; +} + +bool hcd_pipe_is_stalled(pipe_handle_t pipe_hdl) +{ + ohci_ed_t const * const p_ed = ed_from_pipe_handle(pipe_hdl); + return p_ed->td_head.halted && p_ed->is_stalled; +} + +uint8_t hcd_pipe_get_endpoint_addr(pipe_handle_t pipe_hdl) +{ + ohci_ed_t const * const p_ed = ed_from_pipe_handle(pipe_hdl); + return p_ed->endpoint_number | (p_ed->direction == OHCI_PID_IN ? TUSB_DIR_IN_MASK : 0 ); +} + +tusb_error_t hcd_pipe_clear_stall(pipe_handle_t pipe_hdl) +{ + ohci_ed_t * const p_ed = ed_from_pipe_handle(pipe_hdl); + + p_ed->is_stalled = 0; + p_ed->td_tail.address &= 0x0Ful; // set tail pointer back to NULL + + p_ed->td_head.toggle = 0; // reset data toggle + p_ed->td_head.halted = 0; + + if ( TUSB_XFER_BULK == ed_get_xfer_type(p_ed) ) OHCI_REG->command_status_bit.bulk_list_filled = 1; + + return TUSB_ERROR_NONE; +} + + +//--------------------------------------------------------------------+ +// OHCI Interrupt Handler +//--------------------------------------------------------------------+ +static ohci_td_item_t* list_reverse(ohci_td_item_t* td_head) +{ + ohci_td_item_t* td_reverse_head = NULL; + + while(td_head != NULL) + { + uint32_t next = td_head->next_td; + + // make current's item become reverse's first item + td_head->next_td = (uint32_t) td_reverse_head; + td_reverse_head = td_head; + + td_head = (ohci_td_item_t*) next; // advance to next item + } + + return td_reverse_head; +} + +static inline bool gtd_is_control(ohci_gtd_t const * const p_qtd) ATTR_CONST ATTR_ALWAYS_INLINE; +static inline bool gtd_is_control(ohci_gtd_t const * const p_qtd) +{ + return ((uint32_t) p_qtd) < ((uint32_t) ohci_data.device); // check ohci_data_t for memory layout +} + +static inline ohci_ed_t* gtd_get_ed(ohci_gtd_t const * const p_qtd) ATTR_PURE ATTR_ALWAYS_INLINE; +static inline ohci_ed_t* gtd_get_ed(ohci_gtd_t const * const p_qtd) +{ + if ( gtd_is_control(p_qtd) ) + { + return &ohci_data.control[p_qtd->index].ed; + }else + { + uint8_t dev_addr_idx = (((uint32_t)p_qtd) - ((uint32_t)ohci_data.device)) / sizeof(ohci_data.device[0]); + + return &ohci_data.device[dev_addr_idx].ed[p_qtd->index]; + } +} + +static inline uint32_t gtd_xfer_byte_left(uint32_t buffer_end, uint32_t current_buffer) ATTR_CONST ATTR_ALWAYS_INLINE; +static inline uint32_t gtd_xfer_byte_left(uint32_t buffer_end, uint32_t current_buffer) +{ // 5.2.9 OHCI sample code + return (align4k(buffer_end ^ current_buffer) ? 0x1000 : 0) + + offset4k(buffer_end) - offset4k(current_buffer) + 1; +} + +static void done_queue_isr(uint8_t hostid) +{ + uint8_t max_loop = (CFG_TUSB_HOST_DEVICE_MAX+1)*(HCD_MAX_XFER+OHCI_MAX_ITD); + + // done head is written in reversed order of completion --> need to reverse the done queue first + ohci_td_item_t* td_head = list_reverse ( (ohci_td_item_t*) align16(ohci_data.hcca.done_head) ); + + while( td_head != NULL && max_loop > 0) + { + // TODO check if td_head is iso td + //------------- Non ISO transfer -------------// + ohci_gtd_t * const p_qtd = (ohci_gtd_t *) td_head; + tusb_event_t const event = (p_qtd->condition_code == OHCI_CCODE_NO_ERROR) ? TUSB_EVENT_XFER_COMPLETE : + (p_qtd->condition_code == OHCI_CCODE_STALL) ? TUSB_EVENT_XFER_STALLED : TUSB_EVENT_XFER_ERROR; + + p_qtd->used = 0; // free TD + if ( (p_qtd->delay_interrupt == OHCI_INT_ON_COMPLETE_YES) || (event != TUSB_EVENT_XFER_COMPLETE) ) + { + ohci_ed_t * const p_ed = gtd_get_ed(p_qtd); + + uint32_t const xferred_bytes = p_qtd->expected_bytes - gtd_xfer_byte_left((uint32_t) p_qtd->buffer_end, (uint32_t) p_qtd->current_buffer_pointer); + + // NOTE Assuming the current list is BULK and there is no other EDs in the list has queued TDs. + // When there is a error resulting this ED is halted, and this EP still has other queued TD + // --> the Bulk list only has this halted EP queueing TDs (remaining) + // --> Bulk list will be considered as not empty by HC !!! while there is no attempt transaction on this list + // --> HC will not process Control list (due to service ratio when Bulk list not empty) + // To walk-around this, the halted ED will have TailP = HeadP (empty list condition), when clearing halt + // the TailP must be set back to NULL for processing remaining TDs + if ((event != TUSB_EVENT_XFER_COMPLETE)) + { + p_ed->td_tail.address &= 0x0Ful; + p_ed->td_tail.address |= align16(p_ed->td_head.address); // mark halted EP as empty queue + if ( event == TUSB_EVENT_XFER_STALLED ) p_ed->is_stalled = 1; + } + + pipe_handle_t pipe_hdl = + { + .dev_addr = p_ed->device_address, + .xfer_type = ed_get_xfer_type(p_ed), + }; + + if ( pipe_hdl.xfer_type != TUSB_XFER_CONTROL) pipe_hdl.index = ed_get_index(p_ed); + + usbh_xfer_isr(pipe_hdl, p_ed->td_tail.class_code, event, xferred_bytes); + } + + td_head = (ohci_td_item_t*) td_head->next_td; + max_loop--; + } +} + +void hal_hcd_isr(uint8_t hostid) +{ + uint32_t const int_en = OHCI_REG->interrupt_enable; + uint32_t const int_status = OHCI_REG->interrupt_status & int_en; + + if (int_status == 0) return; + + //------------- RootHub status -------------// + if ( int_status & OHCI_INT_RHPORT_STATUS_CHANGE_MASK ) + { + uint32_t const rhport_status = OHCI_REG->rhport_status[0] & OHCI_RHPORT_ALL_CHANGE_MASK; + + // TODO dual port is not yet supported + if ( rhport_status & OHCI_RHPORT_CONNECT_STATUS_CHANGE_MASK ) + { + // TODO check if remote wake-up + if ( OHCI_REG->rhport_status_bit[0].current_connect_status ) + { + // TODO reset port immediately, without this controller will got 2-3 (debouncing connection status change) + OHCI_REG->rhport_status[0] = OHCI_RHPORT_PORT_RESET_STATUS_MASK; + usbh_hcd_rhport_plugged_isr(0); + }else + { + usbh_hcd_rhport_unplugged_isr(0); + } + } + + if ( rhport_status & OHCI_RHPORT_PORT_SUSPEND_CHANGE_MASK) + { + + } + + OHCI_REG->rhport_status[0] = rhport_status; // acknowledge all interrupt + } + + //------------- Transfer Complete -------------// + if ( int_status & OHCI_INT_WRITEBACK_DONEHEAD_MASK) + { + done_queue_isr(hostid); + } + + OHCI_REG->interrupt_status = int_status; // Acknowledge handled interrupt +} +//--------------------------------------------------------------------+ +// HELPER +//--------------------------------------------------------------------+ + + +#endif + diff --git a/src/host/ohci/ohci.h b/src/host/ohci/ohci.h new file mode 100644 index 000000000..f49d85261 --- /dev/null +++ b/src/host/ohci/ohci.h @@ -0,0 +1,310 @@ +/**************************************************************************/ +/*! + @file ohci.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 Group_HCD + * @{ + * \defgroup OHCI + * \brief OHCI driver. All documents sources mentioned here (eg section 3.5) is referring to OHCI Specs unless state otherwise + * @{ */ + +#ifndef _TUSB_OHCI_H_ +#define _TUSB_OHCI_H_ + +#ifdef __cplusplus + extern "C" { +#endif + +#include "common/tusb_common.h" + +//--------------------------------------------------------------------+ +// OHCI CONFIGURATION & CONSTANTS +//--------------------------------------------------------------------+ +#define HOST_HCD_XFER_INTERRUPT // TODO interrupt is used widely, should always be enalbed +#define OHCI_PERIODIC_LIST (defined HOST_HCD_XFER_INTERRUPT || defined HOST_HCD_XFER_ISOCHRONOUS) + +// TODO merge OHCI with EHCI +enum { + OHCI_MAX_ITD = 4 +}; + +enum { + OHCI_PID_SETUP = 0, + OHCI_PID_OUT, + OHCI_PID_IN, +}; + +//--------------------------------------------------------------------+ +// OHCI Data Structure +//--------------------------------------------------------------------+ +typedef struct { + uint32_t interrupt_table[32]; + volatile uint16_t frame_number; + volatile uint16_t frame_pad; + volatile uint32_t done_head; + uint8_t reserved[116+4]; // TODO try to make use of this area if possible, extra 4 byte to make the whole struct size = 256 +}ohci_hcca_t; // ATTR_ALIGNED(256) + +VERIFY_STATIC( sizeof(ohci_hcca_t) == 256, "size is not correct" ); + +typedef struct { + uint32_t reserved[2]; + volatile uint32_t next_td; + uint32_t reserved2; +}ohci_td_item_t; + + +typedef struct ATTR_ALIGNED(16) { + //------------- Word 0 -------------// + uint32_t used : 1; + uint32_t index : 4; // endpoint index the td belongs to, or device address in case of control xfer + uint32_t expected_bytes : 13; // TODO available for hcd + + uint32_t buffer_rounding : 1; + uint32_t pid : 2; + uint32_t delay_interrupt : 3; + volatile uint32_t data_toggle : 2; + volatile uint32_t error_count : 2; + volatile uint32_t condition_code : 4; + /*---------- End Word 1 ----------*/ + + //------------- Word 1 -------------// + volatile uint8_t* current_buffer_pointer; + + //------------- Word 2 -------------// + volatile uint32_t next_td; + + //------------- Word 3 -------------// + uint8_t* buffer_end; +} ohci_gtd_t; + +VERIFY_STATIC( sizeof(ohci_gtd_t) == 16, "size is not correct" ); + +typedef struct ATTR_ALIGNED(16) { + //------------- Word 0 -------------// + uint32_t device_address : 7; + uint32_t endpoint_number : 4; + uint32_t direction : 2; + uint32_t speed : 1; + uint32_t skip : 1; + uint32_t is_iso : 1; + uint32_t max_package_size : 11; + + uint32_t used : 1; // HCD + uint32_t is_interrupt_xfer : 1; + uint32_t is_stalled : 1; + uint32_t : 2; + + + //------------- Word 1 -------------// + union { + uint32_t address; // 4 lsb bits are free to use + struct { + uint32_t class_code : 4; // FIXME refractor to use interface number instead + uint32_t : 28; + }; + }td_tail; + + //------------- Word 2 -------------// + volatile union { + uint32_t address; + struct { + uint32_t halted : 1; + uint32_t toggle : 1; + uint32_t : 30; + }; + }td_head; + + //------------- Word 3 -------------// + uint32_t next_ed; // 4 lsb bits are free to use +} ohci_ed_t; + +VERIFY_STATIC( sizeof(ohci_ed_t) == 16, "size is not correct" ); + +typedef struct ATTR_ALIGNED(32) { + /*---------- Word 1 ----------*/ + uint32_t starting_frame : 16; + uint32_t : 5; // can be used + uint32_t delay_interrupt : 3; + uint32_t frame_count : 3; + uint32_t : 1; // can be used + volatile uint32_t condition_code : 4; + /*---------- End Word 1 ----------*/ + + /*---------- Word 2 ----------*/ + uint32_t buffer_page0; // 12 lsb bits can be used + + /*---------- Word 3 ----------*/ + volatile uint32_t next_td; + + /*---------- Word 4 ----------*/ + uint32_t buffer_end; + + /*---------- Word 5-8 ----------*/ + volatile uint16_t offset_packetstatus[8]; +} ochi_itd_t; + +VERIFY_STATIC( sizeof(ochi_itd_t) == 32, "size is not correct" ); + +// structure with member alignment required from large to small +typedef struct ATTR_ALIGNED(256) { + ohci_hcca_t hcca; + + ohci_ed_t bulk_head_ed; // static bulk head (dummy) + ohci_ed_t period_head_ed; // static periodic list head (dummy) + + // control endpoints has reserved resources + struct { + ohci_ed_t ed; + ohci_gtd_t gtd[3]; // setup, data, status + }control[CFG_TUSB_HOST_DEVICE_MAX+1]; + + struct { + // ochi_itd_t itd[OHCI_MAX_ITD]; // itd requires alignment of 32 + ohci_ed_t ed[HCD_MAX_ENDPOINT]; + ohci_gtd_t gtd[HCD_MAX_XFER]; + }device[CFG_TUSB_HOST_DEVICE_MAX]; + +} ohci_data_t; + +//--------------------------------------------------------------------+ +// OHCI Operational Register +//--------------------------------------------------------------------+ + + +//--------------------------------------------------------------------+ +// OHCI Data Organization +//--------------------------------------------------------------------+ +typedef volatile struct +{ + uint32_t revision; + + union { + uint32_t control; + struct { + uint32_t control_bulk_service_ratio : 2; + uint32_t periodic_list_enable : 1; + uint32_t isochronous_enable : 1; + uint32_t control_list_enable : 1; + uint32_t bulk_list_enable : 1; + uint32_t hc_functional_state : 2; + uint32_t interrupt_routing : 1; + uint32_t remote_wakeup_connected : 1; + uint32_t remote_wakeup_enale : 1; + uint32_t : 0; + }control_bit; + }; + + union { + uint32_t command_status; + struct { + uint32_t controller_reset : 1; + uint32_t control_list_filled : 1; + uint32_t bulk_list_filled : 1; + uint32_t ownership_change_request : 1; + uint32_t : 12; + uint32_t scheduling_overrun_count : 2; + }command_status_bit; + }; + + uint32_t interrupt_status; + uint32_t interrupt_enable; + uint32_t interrupt_disable; + + uint32_t hcca; + uint32_t period_current_ed; + uint32_t control_head_ed; + uint32_t control_current_ed; + uint32_t bulk_head_ed; + uint32_t bulk_current_ed; + uint32_t done_head; + + uint32_t frame_interval; + uint32_t frame_remaining; + uint32_t frame_number; + uint32_t periodic_start; + uint32_t lowspeed_threshold; + + uint32_t rh_descriptorA; + uint32_t rh_descriptorB; + + union { + uint32_t rh_status; + struct { + uint32_t local_power_status : 1; // read Local Power Status; write: Clear Global Power + uint32_t over_current_indicator : 1; + uint32_t : 13; + uint32_t device_remote_wakeup_enable : 1; + uint32_t local_power_status_change : 1; + uint32_t over_current_indicator_change : 1; + uint32_t : 13; + uint32_t clear_remote_wakeup_enable : 1; + }rh_status_bit; + }; + + union { + uint32_t rhport_status[2]; // TODO NXP OHCI controller only has 2 ports + struct { + uint32_t current_connect_status : 1; + uint32_t port_enable_status : 1; + uint32_t port_suspend_status : 1; + uint32_t port_over_current_indicator : 1; + uint32_t port_reset_status : 1; + uint32_t : 3; + uint32_t port_power_status : 1; + uint32_t low_speed_device_attached : 1; + uint32_t : 6; + uint32_t connect_status_change : 1; + uint32_t port_enable_status_change : 1; + uint32_t port_suspend_status_change : 1; + uint32_t port_over_current_indicator_change : 1; + uint32_t port_reset_status_change : 1; + uint32_t : 0; + }rhport_status_bit[2]; + }; +}ohci_registers_t; + +VERIFY_STATIC( sizeof(ohci_registers_t) == 0x5c, "size is not correct"); + +#ifdef __cplusplus + } +#endif + +#endif /* _TUSB_OHCI_H_ */ + +/** @} */ +/** @} */ diff --git a/src/host/usbh.c b/src/host/usbh.c new file mode 100644 index 000000000..506135b49 --- /dev/null +++ b/src/host/usbh.c @@ -0,0 +1,642 @@ +/**************************************************************************/ +/*! + @file usbd_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 "common/tusb_common.h" + +#if MODE_HOST_SUPPORTED + +#define _TINY_USB_SOURCE_FILE_ + +#ifndef CFG_TUD_TASK_PRIO +#define CFG_TUD_TASK_PRIO 0 +#endif + +//--------------------------------------------------------------------+ +// INCLUDE +//--------------------------------------------------------------------+ +#include "tusb.h" +#include "hub.h" +#include "usbh_hcd.h" + +//--------------------------------------------------------------------+ +// MACRO CONSTANT TYPEDEF +//--------------------------------------------------------------------+ +static host_class_driver_t const usbh_class_drivers[] = +{ + #if HOST_CLASS_HID + [TUSB_CLASS_HID] = { + .init = hidh_init, + .open_subtask = hidh_open_subtask, + .isr = hidh_isr, + .close = hidh_close + }, + #endif + + #if CFG_TUSB_HOST_CDC + [TUSB_CLASS_CDC] = { + .init = cdch_init, + .open_subtask = cdch_open_subtask, + .isr = cdch_isr, + .close = cdch_close + }, + #endif + + #if CFG_TUSB_HOST_MSC + [TUSB_CLASS_MSC] = { + .init = msch_init, + .open_subtask = msch_open_subtask, + .isr = msch_isr, + .close = msch_close + }, + #endif + + #if CFG_TUSB_HOST_HUB + [TUSB_CLASS_HUB] = { + .init = hub_init, + .open_subtask = hub_open_subtask, + .isr = hub_isr, + .close = hub_close + }, + #endif + + #if CFG_TUSB_HOST_CUSTOM_CLASS + [TUSB_CLASS_MAPPED_INDEX_END-1] = { + .init = cush_init, + .open_subtask = cush_open_subtask, + .isr = cush_isr, + .close = cush_close + } + #endif +}; + +enum { USBH_CLASS_DRIVER_COUNT = sizeof(usbh_class_drivers) / sizeof(host_class_driver_t) }; + +//--------------------------------------------------------------------+ +// INTERNAL OBJECT & FUNCTION DECLARATION +//--------------------------------------------------------------------+ +CFG_TUSB_ATTR_USBRAM usbh_device_info_t usbh_devices[CFG_TUSB_HOST_DEVICE_MAX+1]; // including zero-address + +//------------- Enumeration Task Data -------------/ +enum { ENUM_QUEUE_DEPTH = 16 }; + +STATIC_VAR osal_queue_t enum_queue_hdl; +CFG_TUSB_ATTR_USBRAM ATTR_ALIGNED(4) STATIC_VAR uint8_t enum_data_buffer[CFG_TUSB_HOST_ENUM_BUFFER_SIZE]; + +//------------- Reporter Task Data -------------// + +//------------- Helper Function Prototypes -------------// +static inline uint8_t get_new_address(void) ATTR_ALWAYS_INLINE; +static inline uint8_t get_configure_number_for_device(tusb_desc_device_t* dev_desc) ATTR_ALWAYS_INLINE; + +//--------------------------------------------------------------------+ +// PUBLIC API (Parameter Verification is required) +//--------------------------------------------------------------------+ +tusb_device_state_t tuh_device_get_state (uint8_t const dev_addr) +{ + TU_ASSERT( dev_addr <= CFG_TUSB_HOST_DEVICE_MAX, TUSB_DEVICE_STATE_INVALID_PARAMETER); + return (tusb_device_state_t) usbh_devices[dev_addr].state; +} + +uint32_t tuh_device_get_mounted_class_flag(uint8_t dev_addr) +{ + return tuh_device_is_configured(dev_addr) ? usbh_devices[dev_addr].flag_supported_class : 0; +} + +//--------------------------------------------------------------------+ +// CLASS-USBD API (don't require to verify parameters) +//--------------------------------------------------------------------+ +tusb_error_t usbh_init(void) +{ + memclr_(usbh_devices, sizeof(usbh_device_info_t)*(CFG_TUSB_HOST_DEVICE_MAX+1)); + + TU_ASSERT_ERR( hcd_init() ); + + //------------- Enumeration & Reporter Task init -------------// + enum_queue_hdl = osal_queue_create( ENUM_QUEUE_DEPTH, sizeof(uint32_t) ); + TU_ASSERT(enum_queue_hdl, TUSB_ERROR_OSAL_QUEUE_FAILED); + + osal_task_create(usbh_enumeration_task, "usbh", 200, NULL, CFG_TUD_TASK_PRIO); + + //------------- Semaphore, Mutex for Control Pipe -------------// + for(uint8_t i=0; icontrol.sem_hdl = osal_semaphore_create(1, 0); + TU_ASSERT(p_device->control.sem_hdl, TUSB_ERROR_OSAL_SEMAPHORE_FAILED); + + p_device->control.mutex_hdl = osal_mutex_create(); + TU_ASSERT(p_device->control.mutex_hdl, TUSB_ERROR_OSAL_MUTEX_FAILED); + } + + //------------- class init -------------// + for (uint8_t class_index = 1; class_index < USBH_CLASS_DRIVER_COUNT; class_index++) + { + if (usbh_class_drivers[class_index].init) + { + usbh_class_drivers[class_index].init(); + } + } + + return TUSB_ERROR_NONE; +} + +//------------- USBH control transfer -------------// +// function called within a task, requesting os blocking services, subtask input parameter must be static/global variables or constant +tusb_error_t usbh_control_xfer_subtask(uint8_t dev_addr, uint8_t bmRequestType, uint8_t bRequest, + uint16_t wValue, uint16_t wIndex, uint16_t wLength, uint8_t* data) +{ + static tusb_error_t error; // FIXME [CMSIS-RTX] use svc for OS API, error value changed after mutex release at the end of function + + OSAL_SUBTASK_BEGIN + + osal_mutex_wait(usbh_devices[dev_addr].control.mutex_hdl, OSAL_TIMEOUT_NORMAL, &error); + STASK_ASSERT_ERR_HDLR(error, osal_mutex_release(usbh_devices[dev_addr].control.mutex_hdl)); + + usbh_devices[dev_addr].control.request = (tusb_control_request_t) { + {.bmRequestType = bmRequestType}, + .bRequest = bRequest, + .wValue = wValue, + .wIndex = wIndex, + .wLength = wLength + }; + +#ifndef _TEST_ + usbh_devices[dev_addr].control.pipe_status = 0; +#else + usbh_devices[dev_addr].control.pipe_status = TUSB_EVENT_XFER_COMPLETE; // in Test project, mark as complete immediately +#endif + + error = hcd_pipe_control_xfer(dev_addr, &usbh_devices[dev_addr].control.request, data); + if ( TUSB_ERROR_NONE == error ) osal_semaphore_wait(usbh_devices[dev_addr].control.sem_hdl, OSAL_TIMEOUT_NORMAL, &error); + osal_mutex_release(usbh_devices[dev_addr].control.mutex_hdl); + + STASK_ASSERT_ERR(error); + if (TUSB_EVENT_XFER_STALLED == usbh_devices[dev_addr].control.pipe_status) STASK_RETURN(TUSB_ERROR_USBH_XFER_STALLED); + if (TUSB_EVENT_XFER_ERROR == usbh_devices[dev_addr].control.pipe_status) STASK_RETURN(TUSB_ERROR_USBH_XFER_FAILED); + +// STASK_ASSERT_HDLR(TUSB_ERROR_NONE == error && +// TUSB_EVENT_XFER_COMPLETE == usbh_devices[dev_addr].control.pipe_status, +// tuh_device_mount_failed_cb(TUSB_ERROR_USBH_MOUNT_DEVICE_NOT_RESPOND, NULL) ); + + OSAL_SUBTASK_END +} + +tusb_error_t usbh_pipe_control_open(uint8_t dev_addr, uint8_t max_packet_size) ATTR_ALWAYS_INLINE; +tusb_error_t usbh_pipe_control_open(uint8_t dev_addr, uint8_t max_packet_size) +{ + osal_semaphore_reset( usbh_devices[dev_addr].control.sem_hdl ); + osal_mutex_reset( usbh_devices[dev_addr].control.mutex_hdl ); + + TU_ASSERT_ERR( hcd_pipe_control_open(dev_addr, max_packet_size) ); + + return TUSB_ERROR_NONE; +} + +static inline tusb_error_t usbh_pipe_control_close(uint8_t dev_addr) ATTR_ALWAYS_INLINE; +static inline tusb_error_t usbh_pipe_control_close(uint8_t dev_addr) +{ + TU_ASSERT_ERR( hcd_pipe_control_close(dev_addr) ); + + return TUSB_ERROR_NONE; +} + +// TODO [USBH] unify pipe status get +//tusb_interface_status_t usbh_pipe_status_get(pipe_handle_t pipe_hdl) +//{ +// return TUSB_INTERFACE_STATUS_BUSY; +//} + +//--------------------------------------------------------------------+ +// USBH-HCD ISR/Callback API +//--------------------------------------------------------------------+ +// interrupt caused by a TD (with IOC=1) in pipe of class class_code +void usbh_xfer_isr(pipe_handle_t pipe_hdl, uint8_t class_code, tusb_event_t event, uint32_t xferred_bytes) +{ + uint8_t class_index = std_class_code_to_index(class_code); + if (TUSB_XFER_CONTROL == pipe_hdl.xfer_type) + { + usbh_devices[ pipe_hdl.dev_addr ].control.pipe_status = event; +// usbh_devices[ pipe_hdl.dev_addr ].control.xferred_bytes = xferred_bytes; not yet neccessary + osal_semaphore_post( usbh_devices[ pipe_hdl.dev_addr ].control.sem_hdl ); + }else if (usbh_class_drivers[class_index].isr) + { + usbh_class_drivers[class_index].isr(pipe_hdl, event, xferred_bytes); + }else + { + TU_ASSERT(false); // something wrong, no one claims the isr's source + } +} + +void usbh_hub_port_plugged_isr(uint8_t hub_addr, uint8_t hub_port) +{ + usbh_enumerate_t enum_entry = + { + .core_id = usbh_devices[hub_addr].core_id, + .hub_addr = hub_addr, + .hub_port = hub_port + }; + + osal_queue_send(enum_queue_hdl, &enum_entry); +} + +void usbh_hcd_rhport_plugged_isr(uint8_t hostid) +{ + usbh_enumerate_t enum_entry = + { + .core_id = hostid, + .hub_addr = 0, + .hub_port = 0 + }; + + osal_queue_send(enum_queue_hdl, &enum_entry); +} + +// a device unplugged on hostid, hub_addr, hub_port +// return true if found and unmounted device, false if cannot find +static void usbh_device_unplugged(uint8_t hostid, uint8_t hub_addr, uint8_t hub_port) +{ + bool is_found = false; + //------------- find the all devices (star-network) under port that is unplugged -------------// + for (uint8_t dev_addr = 0; dev_addr <= CFG_TUSB_HOST_DEVICE_MAX; dev_addr ++) + { + if (usbh_devices[dev_addr].core_id == hostid && + (hub_addr == 0 || usbh_devices[dev_addr].hub_addr == hub_addr) && // hub_addr == 0 & hub_port == 0 means roothub + (hub_port == 0 || usbh_devices[dev_addr].hub_port == hub_port) && + usbh_devices[dev_addr].state != TUSB_DEVICE_STATE_UNPLUG) + { + // TODO Hub multiple level + for (uint8_t class_index = 1; class_index < USBH_CLASS_DRIVER_COUNT; class_index++) + { + if ((usbh_devices[dev_addr].flag_supported_class & BIT_(class_index)) && + usbh_class_drivers[class_index].close) + { + usbh_class_drivers[class_index].close(dev_addr); + } + } + + // TODO refractor + // set to REMOVING to allow HCD to clean up its cached data for this device + // HCD must set this device's state to TUSB_DEVICE_STATE_UNPLUG when done + usbh_devices[dev_addr].state = TUSB_DEVICE_STATE_REMOVING; + usbh_devices[dev_addr].flag_supported_class = 0; + + usbh_pipe_control_close(dev_addr); + + + is_found = true; + } + } + + if (is_found) hcd_port_unplug(usbh_devices[0].core_id); // TODO hack + +} + +void usbh_hcd_rhport_unplugged_isr(uint8_t hostid) +{ + usbh_enumerate_t enum_entry = + { + .core_id = hostid, + .hub_addr = 0, + .hub_port = 0 + }; + + osal_queue_send(enum_queue_hdl, &enum_entry); +} + +//--------------------------------------------------------------------+ +// ENUMERATION TASK +//--------------------------------------------------------------------+ +static tusb_error_t enumeration_body_subtask(void); + +// To enable the TASK_ASSERT style (quick return on false condition) in a real RTOS, a task must act as a wrapper +// and is used mainly to call subtasks. Within a subtask return statement can be called freely, the task with +// forever loop cannot have any return at all. +void usbh_enumeration_task(void* param) +{ + (void) param; + + OSAL_TASK_BEGIN + enumeration_body_subtask(); + OSAL_TASK_END +} + +tusb_error_t enumeration_body_subtask(void) +{ + enum { + POWER_STABLE_DELAY = 500, + RESET_DELAY = 200 // USB specs say only 50ms but many devices require much longer + }; + + tusb_error_t error; + usbh_enumerate_t enum_entry; + + // for OSAL_NONE local variable won't retain value after blocking service sem_wait/queue_recv + static uint8_t new_addr; + static uint8_t configure_selected = 1; // TODO move + static uint8_t *p_desc = NULL; // TODO move + + OSAL_SUBTASK_BEGIN + + osal_queue_receive(enum_queue_hdl, &enum_entry, OSAL_TIMEOUT_WAIT_FOREVER, &error); + STASK_ASSERT_ERR(error); + + usbh_devices[0].core_id = enum_entry.core_id; // TODO refractor integrate to device_pool + usbh_devices[0].hub_addr = enum_entry.hub_addr; + usbh_devices[0].hub_port = enum_entry.hub_port; + usbh_devices[0].state = TUSB_DEVICE_STATE_UNPLUG; + + //------------- connected/disconnected directly with roothub -------------// + if ( usbh_devices[0].hub_addr == 0) + { + if( hcd_port_connect_status(usbh_devices[0].core_id) ) + { // connection event + osal_task_delay(POWER_STABLE_DELAY); // wait until device is stable. Increase this if the first 8 bytes is failed to get + + if ( !hcd_port_connect_status(usbh_devices[0].core_id) ) STASK_RETURN(TUSB_ERROR_NONE); // exit if device unplugged while delaying + + hcd_port_reset( usbh_devices[0].core_id ); // port must be reset to have correct speed operation + osal_task_delay(RESET_DELAY); + + usbh_devices[0].speed = hcd_port_speed_get( usbh_devices[0].core_id ); + } + else + { // disconnection event + usbh_device_unplugged(usbh_devices[0].core_id, 0, 0); + STASK_RETURN(TUSB_ERROR_NONE); // restart task + } + } + #if CFG_TUSB_HOST_HUB + //------------- connected/disconnected via hub -------------// + else + { + //------------- Get Port Status -------------// + STASK_INVOKE( + usbh_control_xfer_subtask( usbh_devices[0].hub_addr, bm_request_type(TUSB_DIR_IN, TUSB_REQ_TYPE_CLASS, TUSB_REQ_RCPT_OTHER), + HUB_REQUEST_GET_STATUS, 0, usbh_devices[0].hub_port, + 4, enum_data_buffer ), + error + ); +// STASK_ASSERT_ERR( error ); + STASK_ASSERT_ERR_HDLR(error, hub_status_pipe_queue( usbh_devices[0].hub_addr) ); // TODO hub refractor + + // Acknowledge Port Connection Change + STASK_INVOKE( hub_port_clear_feature_subtask(usbh_devices[0].hub_addr, usbh_devices[0].hub_port, HUB_FEATURE_PORT_CONNECTION_CHANGE), error ); + + hub_port_status_response_t * p_port_status; + p_port_status = ((hub_port_status_response_t *) enum_data_buffer); + + if ( ! p_port_status->status_change.connect_status ) STASK_RETURN(TUSB_ERROR_NONE); // only handle connection change + + if ( ! p_port_status->status_current.connect_status ) + { // Disconnection event + usbh_device_unplugged(usbh_devices[0].core_id, usbh_devices[0].hub_addr, usbh_devices[0].hub_port); + + (void) hub_status_pipe_queue( usbh_devices[0].hub_addr ); // done with hub, waiting for next data on status pipe + STASK_RETURN(TUSB_ERROR_NONE); // restart task + } + else + { // Connection Event + STASK_INVOKE ( hub_port_reset_subtask(usbh_devices[0].hub_addr, usbh_devices[0].hub_port), error ); +// STASK_ASSERT_ERR( error ); + STASK_ASSERT_ERR_HDLR(error, hub_status_pipe_queue( usbh_devices[0].hub_addr) ); // TODO hub refractor + + usbh_devices[0].speed = hub_port_get_speed(); + + // Acknowledge Port Reset Change + STASK_INVOKE( hub_port_clear_feature_subtask(usbh_devices[0].hub_addr, usbh_devices[0].hub_port, HUB_FEATURE_PORT_RESET_CHANGE), error ); + } + } + #endif + + STASK_ASSERT_ERR( usbh_pipe_control_open(0, 8) ); + usbh_devices[0].state = TUSB_DEVICE_STATE_ADDRESSED; + + //------------- Get first 8 bytes of device descriptor to get Control Endpoint Size -------------// + STASK_INVOKE( + usbh_control_xfer_subtask( 0, bm_request_type(TUSB_DIR_IN, TUSB_REQ_TYPE_STANDARD, TUSB_REQ_RCPT_DEVICE), + TUSB_REQ_GET_DESCRIPTOR, (TUSB_DESC_DEVICE << 8), 0, + 8, enum_data_buffer ), + error + ); + + //------------- Reset device again before Set Address -------------// + if (usbh_devices[0].hub_addr == 0) + { // connected directly to roothub + STASK_ASSERT_ERR(error); // TODO some slow device is observed to fail the very fist controller xfer, can try more times + hcd_port_reset( usbh_devices[0].core_id ); // reset port after 8 byte descriptor + osal_task_delay(RESET_DELAY); + } + #if CFG_TUSB_HOST_HUB + else + { // connected via a hub + STASK_ASSERT_ERR_HDLR(error, hub_status_pipe_queue( usbh_devices[0].hub_addr) ); // TODO hub refractor + STASK_INVOKE ( hub_port_reset_subtask(usbh_devices[0].hub_addr, usbh_devices[0].hub_port), error ); + + if ( TUSB_ERROR_NONE == error ) + { // Acknowledge Port Reset Change if Reset Successful + STASK_INVOKE( hub_port_clear_feature_subtask(usbh_devices[0].hub_addr, usbh_devices[0].hub_port, HUB_FEATURE_PORT_RESET_CHANGE), error ); + } + + (void) hub_status_pipe_queue( usbh_devices[0].hub_addr ); // done with hub, waiting for next data on status pipe + } + #endif + + //------------- Set new address -------------// + new_addr = get_new_address(); + STASK_ASSERT(new_addr <= CFG_TUSB_HOST_DEVICE_MAX); // TODO notify application we reach max devices + + STASK_INVOKE( + usbh_control_xfer_subtask( 0, bm_request_type(TUSB_DIR_OUT, TUSB_REQ_TYPE_STANDARD, TUSB_REQ_RCPT_DEVICE), + TUSB_REQ_SET_ADDRESS, new_addr, 0, + 0, NULL ), + error + ); + STASK_ASSERT_ERR(error); + + //------------- update port info & close control pipe of addr0 -------------// + usbh_devices[new_addr].core_id = usbh_devices[0].core_id; + usbh_devices[new_addr].hub_addr = usbh_devices[0].hub_addr; + usbh_devices[new_addr].hub_port = usbh_devices[0].hub_port; + usbh_devices[new_addr].speed = usbh_devices[0].speed; + usbh_devices[new_addr].state = TUSB_DEVICE_STATE_ADDRESSED; + + usbh_pipe_control_close(0); + usbh_devices[0].state = TUSB_DEVICE_STATE_UNPLUG; + + // open control pipe for new address + STASK_ASSERT_ERR ( usbh_pipe_control_open(new_addr, ((tusb_desc_device_t*) enum_data_buffer)->bMaxPacketSize0 ) ); + + //------------- Get full device descriptor -------------// + STASK_INVOKE( + usbh_control_xfer_subtask( new_addr, bm_request_type(TUSB_DIR_IN, TUSB_REQ_TYPE_STANDARD, TUSB_REQ_RCPT_DEVICE), + TUSB_REQ_GET_DESCRIPTOR, (TUSB_DESC_DEVICE << 8), 0, + 18, enum_data_buffer ), + error + ); + STASK_ASSERT_ERR(error); + + // update device info TODO alignment issue + usbh_devices[new_addr].vendor_id = ((tusb_desc_device_t*) enum_data_buffer)->idVendor; + usbh_devices[new_addr].product_id = ((tusb_desc_device_t*) enum_data_buffer)->idProduct; + usbh_devices[new_addr].configure_count = ((tusb_desc_device_t*) enum_data_buffer)->bNumConfigurations; + + configure_selected = get_configure_number_for_device((tusb_desc_device_t*) enum_data_buffer); + STASK_ASSERT(configure_selected <= usbh_devices[new_addr].configure_count); // TODO notify application when invalid configuration + + //------------- Get 9 bytes of configuration descriptor -------------// + STASK_INVOKE( + usbh_control_xfer_subtask( new_addr, bm_request_type(TUSB_DIR_IN, TUSB_REQ_TYPE_STANDARD, TUSB_REQ_RCPT_DEVICE), + TUSB_REQ_GET_DESCRIPTOR, (TUSB_DESC_CONFIGURATION << 8) | (configure_selected - 1), 0, + 9, enum_data_buffer ), + error + ); + STASK_ASSERT_ERR(error); + STASK_ASSERT_HDLR( CFG_TUSB_HOST_ENUM_BUFFER_SIZE >= ((tusb_desc_configuration_t*)enum_data_buffer)->wTotalLength, + tuh_device_mount_failed_cb(TUSB_ERROR_USBH_MOUNT_CONFIG_DESC_TOO_LONG, NULL) ); + + //------------- Get full configuration descriptor -------------// + STASK_INVOKE( + usbh_control_xfer_subtask( new_addr, bm_request_type(TUSB_DIR_IN, TUSB_REQ_TYPE_STANDARD, TUSB_REQ_RCPT_DEVICE), + TUSB_REQ_GET_DESCRIPTOR, (TUSB_DESC_CONFIGURATION << 8) | (configure_selected - 1), 0, + CFG_TUSB_HOST_ENUM_BUFFER_SIZE, enum_data_buffer ), + error + ); + STASK_ASSERT_ERR(error); + + // update configuration info + usbh_devices[new_addr].interface_count = ((tusb_desc_configuration_t*) enum_data_buffer)->bNumInterfaces; + + //------------- Set Configure -------------// + STASK_INVOKE( + usbh_control_xfer_subtask( new_addr, bm_request_type(TUSB_DIR_OUT, TUSB_REQ_TYPE_STANDARD, TUSB_REQ_RCPT_DEVICE), + TUSB_REQ_SET_CONFIGURATION, configure_selected, 0, + 0, NULL ), + error + ); + STASK_ASSERT_ERR(error); + + usbh_devices[new_addr].state = TUSB_DEVICE_STATE_CONFIGURED; + + //------------- TODO Get String Descriptors -------------// + + //------------- parse configuration & install drivers -------------// + p_desc = enum_data_buffer + sizeof(tusb_desc_configuration_t); + + // parse each interfaces + while( p_desc < enum_data_buffer + ((tusb_desc_configuration_t*)enum_data_buffer)->wTotalLength ) + { + // skip until we see interface descriptor + if ( TUSB_DESC_INTERFACE != p_desc[DESCRIPTOR_OFFSET_TYPE] ) + { + p_desc += p_desc[DESCRIPTOR_OFFSET_LENGTH]; // skip the descriptor, increase by the descriptor's length + }else + { + static uint8_t class_index; // has to be static as it is used to call class's open_subtask + + class_index = std_class_code_to_index( ((tusb_desc_interface_t*) p_desc)->bInterfaceClass ); + STASK_ASSERT( class_index != 0 ); // class_index == 0 means corrupted data, abort enumeration + + if (usbh_class_drivers[class_index].open_subtask && + !(class_index == TUSB_CLASS_HUB && usbh_devices[new_addr].hub_addr != 0)) + { // supported class, TODO Hub disable multiple level + static uint16_t length; + length = 0; + + STASK_INVOKE ( // parameters in task/sub_task must be static storage (static or global) + usbh_class_drivers[class_index].open_subtask( new_addr, (tusb_desc_interface_t*) p_desc, &length ), + error + ); + + if (error == TUSB_ERROR_NONE) + { + STASK_ASSERT( length >= sizeof(tusb_desc_interface_t) ); + usbh_devices[new_addr].flag_supported_class |= BIT_(class_index); + p_desc += length; + }else // Interface open failed, for example a subclass is not supported + { + p_desc += p_desc[DESCRIPTOR_OFFSET_LENGTH]; // skip this interface, the rest will be skipped by the above loop + } + } else // unsupported class (not enable or yet implemented) + { + p_desc += p_desc[DESCRIPTOR_OFFSET_LENGTH]; // skip this interface, the rest will be skipped by the above loop + } + } + } + + tuh_device_mount_succeed_cb(new_addr); + + OSAL_SUBTASK_END +} + +//--------------------------------------------------------------------+ +// REPORTER TASK & ITS DATA +//--------------------------------------------------------------------+ + + + + + +//--------------------------------------------------------------------+ +// INTERNAL HELPER +//--------------------------------------------------------------------+ +static inline uint8_t get_new_address(void) +{ + uint8_t addr; + for (addr=1; addr <= CFG_TUSB_HOST_DEVICE_MAX; addr++) + { + if (usbh_devices[addr].state == TUSB_DEVICE_STATE_UNPLUG) + break; + } + return addr; +} + +static inline uint8_t get_configure_number_for_device(tusb_desc_device_t* dev_desc) +{ + uint8_t config_num = 1; + + // invoke callback to ask user which configuration to select + if (tuh_device_attached_cb) + { + config_num = min8_of(1, tuh_device_attached_cb(dev_desc) ); + } + + return config_num; +} + +#endif diff --git a/src/host/usbh.h b/src/host/usbh.h new file mode 100644 index 000000000..5aaeb4186 --- /dev/null +++ b/src/host/usbh.h @@ -0,0 +1,116 @@ +/**************************************************************************/ +/*! + @file usbh.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 group_usbh USB Host Core (USBH) + * @{ */ + +#ifndef _TUSB_USBH_H_ +#define _TUSB_USBH_H_ + +#ifdef __cplusplus + extern "C" { +#endif + +//--------------------------------------------------------------------+ +// INCLUDE +//--------------------------------------------------------------------+ +#include "osal/osal.h" // TODO refractor move to common.h ? +#include "hcd.h" + +//--------------------------------------------------------------------+ +// MACRO CONSTANT TYPEDEF +//--------------------------------------------------------------------+ +typedef enum tusb_interface_status_{ + TUSB_INTERFACE_STATUS_READY = 0, + TUSB_INTERFACE_STATUS_BUSY, + TUSB_INTERFACE_STATUS_COMPLETE, + TUSB_INTERFACE_STATUS_ERROR, + TUSB_INTERFACE_STATUS_INVALID_PARA +} tusb_interface_status_t; + +typedef struct { + void (* const init) (void); + tusb_error_t (* const open_subtask)(uint8_t, tusb_desc_interface_t const *, uint16_t*); + void (* const isr) (pipe_handle_t, tusb_event_t, uint32_t); + void (* const close) (uint8_t); +} host_class_driver_t; +//--------------------------------------------------------------------+ +// INTERNAL OBJECT & FUNCTION DECLARATION +//--------------------------------------------------------------------+ + +//--------------------------------------------------------------------+ +// APPLICATION API +//--------------------------------------------------------------------+ +//tusb_error_t tusbh_configuration_set (uint8_t dev_addr, uint8_t configure_number) ATTR_WARN_UNUSED_RESULT; +tusb_device_state_t tuh_device_get_state (uint8_t dev_addr) ATTR_WARN_UNUSED_RESULT ATTR_PURE; +static inline bool tuh_device_is_configured(uint8_t dev_addr) ATTR_ALWAYS_INLINE ATTR_WARN_UNUSED_RESULT ATTR_PURE; +static inline bool tuh_device_is_configured(uint8_t dev_addr) +{ + return tuh_device_get_state(dev_addr) == TUSB_DEVICE_STATE_CONFIGURED; +} +uint32_t tuh_device_get_mounted_class_flag(uint8_t dev_addr); + +//--------------------------------------------------------------------+ +// APPLICATION CALLBACK +//--------------------------------------------------------------------+ +ATTR_WEAK uint8_t tuh_device_attached_cb (tusb_desc_device_t const *p_desc_device) ATTR_WARN_UNUSED_RESULT; +ATTR_WEAK void tuh_device_mount_succeed_cb (uint8_t dev_addr); +ATTR_WEAK void tuh_device_mount_failed_cb(tusb_error_t error, tusb_desc_device_t const *p_desc_device); // TODO refractor remove desc_device + +//--------------------------------------------------------------------+ +// CLASS-USBH & INTERNAL API +//--------------------------------------------------------------------+ +#ifdef _TINY_USB_SOURCE_FILE_ + + +void usbh_enumeration_task(void* param); +tusb_error_t usbh_init(void); + +tusb_error_t usbh_control_xfer_subtask(uint8_t dev_addr, uint8_t bmRequestType, uint8_t bRequest, + uint16_t wValue, uint16_t wIndex, uint16_t wLength, uint8_t* data); + + +#endif + +#ifdef __cplusplus + } +#endif + +#endif /* _TUSB_USBH_H_ */ + +/** @} */ diff --git a/src/host/usbh_hcd.h b/src/host/usbh_hcd.h new file mode 100644 index 000000000..1c2c4ad0b --- /dev/null +++ b/src/host/usbh_hcd.h @@ -0,0 +1,114 @@ +/**************************************************************************/ +/*! + @file usbh_hcd.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 Group_HCD + * @{ */ + +#ifndef _TUSB_USBH_HCD_H_ +#define _TUSB_USBH_HCD_H_ + +#ifdef __cplusplus + extern "C" { +#endif + +//--------------------------------------------------------------------+ +// INCLUDE +//--------------------------------------------------------------------+ +#include "common/tusb_common.h" +#include "osal/osal.h" + +#ifdef _TEST_ +#include "hcd.h" +#endif + +//--------------------------------------------------------------------+ +// USBH-HCD common data structure +//--------------------------------------------------------------------+ +typedef struct ATTR_ALIGNED(4){ + uint8_t core_id; + uint8_t hub_addr; + uint8_t hub_port; + uint8_t reserve; +} usbh_enumerate_t; + +typedef struct { + //------------- port -------------// + uint8_t core_id; + uint8_t hub_addr; + uint8_t hub_port; + uint8_t speed; + + //------------- device descriptor -------------// + uint16_t vendor_id; + uint16_t product_id; + uint8_t configure_count; // bNumConfigurations alias + + //------------- configuration descriptor -------------// + uint8_t interface_count; // bNumInterfaces alias + + //------------- device -------------// + volatile uint8_t state; // device state, value from enum tusbh_device_state_t + uint32_t flag_supported_class; // a bitmap of supported class + + //------------- control pipe -------------// + struct { + volatile uint8_t pipe_status; +// uint8_t xferred_bytes; TODO not yet necessary + tusb_control_request_t request; + + osal_semaphore_t sem_hdl; // used to synchronize with HCD when control xfer complete + osal_mutex_t mutex_hdl; // used to exclusively occupy control pipe + } control; +} usbh_device_info_t; + +extern usbh_device_info_t usbh_devices[CFG_TUSB_HOST_DEVICE_MAX+1]; // including zero-address + +//--------------------------------------------------------------------+ +// callback from HCD ISR +//--------------------------------------------------------------------+ +void usbh_xfer_isr(pipe_handle_t pipe_hdl, uint8_t class_code, tusb_event_t event, uint32_t xferred_bytes); +void usbh_hcd_rhport_plugged_isr(uint8_t hostid); +void usbh_hcd_rhport_unplugged_isr(uint8_t hostid); + +#ifdef __cplusplus + } +#endif + +#endif /* _TUSB_USBH_HCD_H_ */ + +/** @} */ diff --git a/src/host/usbh_hub.h b/src/host/usbh_hub.h new file mode 100644 index 000000000..48a81bcd2 --- /dev/null +++ b/src/host/usbh_hub.h @@ -0,0 +1,64 @@ +/**************************************************************************/ +/*! + @file usbh_hub.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 group_usbh + * @{ */ + +#ifndef _TUSB_USBH_HUB_H_ +#define _TUSB_USBH_HUB_H_ + +//--------------------------------------------------------------------+ +// INCLUDE +//--------------------------------------------------------------------+ +#include "common/tusb_common.h" + +#ifdef __cplusplus + extern "C" { +#endif + + +void usbh_hub_port_plugged_isr(uint8_t hub_addr, uint8_t hub_port); + + +#ifdef __cplusplus + } +#endif + +#endif /* _TUSB_USBH_HUB_H_ */ + +/** @} */ -- cgit v1.3.1 From f8e7695fe932e79dfb590d96762db68cca1daf0c Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 18 Jun 2018 14:31:15 +0700 Subject: clean up --- src/common/tusb_types.h | 11 ----------- src/device/usbd.c | 2 +- src/host/usbh.c | 10 ++++++++++ 3 files changed, 11 insertions(+), 12 deletions(-) (limited to 'src/host') diff --git a/src/common/tusb_types.h b/src/common/tusb_types.h index f3fc856c3..b50cacb03 100644 --- a/src/common/tusb_types.h +++ b/src/common/tusb_types.h @@ -211,16 +211,6 @@ enum { INTERFACE_INVALID_NUMBER = 0xff }; -static inline uint8_t std_class_code_to_index(uint8_t std_class_code) -{ - return (std_class_code <= TUSB_CLASS_AUDIO_VIDEO ) ? std_class_code : - (std_class_code == TUSB_CLASS_DIAGNOSTIC ) ? TUSB_CLASS_MAPPED_INDEX_START : - (std_class_code == TUSB_CLASS_WIRELESS_CONTROLLER ) ? TUSB_CLASS_MAPPED_INDEX_START + 1 : - (std_class_code == TUSB_CLASS_MISC ) ? TUSB_CLASS_MAPPED_INDEX_START + 2 : - (std_class_code == TUSB_CLASS_APPLICATION_SPECIFIC ) ? TUSB_CLASS_MAPPED_INDEX_START + 3 : - (std_class_code == TUSB_CLASS_VENDOR_SPECIFIC ) ? TUSB_CLASS_MAPPED_INDEX_START + 4 : 0; -} - //--------------------------------------------------------------------+ // STANDARD DESCRIPTORS //--------------------------------------------------------------------+ @@ -363,7 +353,6 @@ typedef struct ATTR_PACKED /*------------------------------------------------------------------*/ /* Types *------------------------------------------------------------------*/ - typedef struct ATTR_PACKED{ union { struct ATTR_PACKED { diff --git a/src/device/usbd.c b/src/device/usbd.c index 6718c0876..74079d215 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -608,7 +608,7 @@ tusb_error_t usbd_open_edpt_pair(uint8_t rhport, tusb_desc_endpoint_t const* p_d TU_ASSERT( dcd_edpt_open(rhport, p_desc_ep), TUSB_ERROR_DCD_OPEN_PIPE_FAILED ); - if ( p_desc_ep->bEndpointAddress & TUSB_DIR_IN_MASK ) + if ( edpt_dir(p_desc_ep->bEndpointAddress) == TUSB_DIR_IN ) { (*ep_in) = p_desc_ep->bEndpointAddress; }else diff --git a/src/host/usbh.c b/src/host/usbh.c index 506135b49..a67bd8d8c 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -242,6 +242,16 @@ static inline tusb_error_t usbh_pipe_control_close(uint8_t dev_addr) // return TUSB_INTERFACE_STATUS_BUSY; //} +static inline uint8_t std_class_code_to_index(uint8_t std_class_code) +{ + return (std_class_code <= TUSB_CLASS_AUDIO_VIDEO ) ? std_class_code : + (std_class_code == TUSB_CLASS_DIAGNOSTIC ) ? TUSB_CLASS_MAPPED_INDEX_START : + (std_class_code == TUSB_CLASS_WIRELESS_CONTROLLER ) ? TUSB_CLASS_MAPPED_INDEX_START + 1 : + (std_class_code == TUSB_CLASS_MISC ) ? TUSB_CLASS_MAPPED_INDEX_START + 2 : + (std_class_code == TUSB_CLASS_APPLICATION_SPECIFIC ) ? TUSB_CLASS_MAPPED_INDEX_START + 3 : + (std_class_code == TUSB_CLASS_VENDOR_SPECIFIC ) ? TUSB_CLASS_MAPPED_INDEX_START + 4 : 0; +} + //--------------------------------------------------------------------+ // USBH-HCD ISR/Callback API //--------------------------------------------------------------------+ -- cgit v1.3.1 From 1efb552bfd097a23651bbb5ad29b6d8eb3bc9ccd Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 13 Jul 2018 17:48:26 +0700 Subject: add ep2drv, rename descriptor offset --- src/class/cdc/cdc_device.c | 12 +++---- src/class/cdc/cdc_host.c | 14 ++++---- src/class/hid/hid_device.c | 4 +-- src/class/hid/hid_host.c | 4 +-- src/common/tusb_common.h | 11 +++++-- src/common/tusb_types.h | 4 +-- src/device/usbd.c | 79 +++++++++++++++++++++++++++++++--------------- src/host/usbh.c | 8 ++--- 8 files changed, 85 insertions(+), 51 deletions(-) (limited to 'src/host') diff --git a/src/class/cdc/cdc_device.c b/src/class/cdc/cdc_device.c index 643706269..76526d40b 100644 --- a/src/class/cdc/cdc_device.c +++ b/src/class/cdc/cdc_device.c @@ -192,31 +192,31 @@ tusb_error_t cdcd_open(uint8_t rhport, tusb_desc_interface_t const * p_interface (*p_length) = sizeof(tusb_desc_interface_t); // Communication Functional Descriptors - while( TUSB_DESC_CLASS_SPECIFIC == p_desc[DESCRIPTOR_OFFSET_TYPE] ) + while( TUSB_DESC_CLASS_SPECIFIC == p_desc[DESC_OFFSET_TYPE] ) { - (*p_length) += p_desc[DESCRIPTOR_OFFSET_LENGTH]; + (*p_length) += p_desc[DESC_OFFSET_LEN]; p_desc = descriptor_next(p_desc); } - if ( TUSB_DESC_ENDPOINT == p_desc[DESCRIPTOR_OFFSET_TYPE]) + if ( TUSB_DESC_ENDPOINT == p_desc[DESC_OFFSET_TYPE]) { // notification endpoint if any TU_ASSERT( dcd_edpt_open(rhport, (tusb_desc_endpoint_t const *) p_desc), TUSB_ERROR_DCD_OPEN_PIPE_FAILED); p_cdc->ep_notif = ((tusb_desc_endpoint_t const *) p_desc)->bEndpointAddress; - (*p_length) += p_desc[DESCRIPTOR_OFFSET_LENGTH]; + (*p_length) += p_desc[DESC_OFFSET_LEN]; p_desc = descriptor_next(p_desc); } //------------- Data Interface (if any) -------------// - if ( (TUSB_DESC_INTERFACE == p_desc[DESCRIPTOR_OFFSET_TYPE]) && + if ( (TUSB_DESC_INTERFACE == p_desc[DESC_OFFSET_TYPE]) && (TUSB_CLASS_CDC_DATA == ((tusb_desc_interface_t const *) p_desc)->bInterfaceClass) ) { // p_cdc->itf_num = p_cdc->ep_count += ((tusb_desc_interface_t const *) p_desc)->bNumEndpoints; // next to endpoint descritpor - (*p_length) += p_desc[DESCRIPTOR_OFFSET_LENGTH]; + (*p_length) += p_desc[DESC_OFFSET_LEN]; p_desc = descriptor_next(p_desc); // Open endpoint pair with usbd helper diff --git a/src/class/cdc/cdc_host.c b/src/class/cdc/cdc_host.c index bd5b5e32c..6950759d1 100644 --- a/src/class/cdc/cdc_host.c +++ b/src/class/cdc/cdc_host.c @@ -167,32 +167,32 @@ tusb_error_t cdch_open_subtask(uint8_t dev_addr, tusb_desc_interface_t const *p_ //------------- Communication Interface -------------// (*p_length) = sizeof(tusb_desc_interface_t); - while( TUSB_DESC_CLASS_SPECIFIC == p_desc[DESCRIPTOR_OFFSET_TYPE] ) + while( TUSB_DESC_CLASS_SPECIFIC == p_desc[DESC_OFFSET_TYPE] ) { // Communication Functional Descriptors if ( CDC_FUNC_DESC_ABSTRACT_CONTROL_MANAGEMENT == cdc_functional_desc_typeof(p_desc) ) { // save ACM bmCapabilities p_cdc->acm_capability = ((cdc_desc_func_acm_t const *) p_desc)->bmCapabilities; } - (*p_length) += p_desc[DESCRIPTOR_OFFSET_LENGTH]; + (*p_length) += p_desc[DESC_OFFSET_LEN]; p_desc = descriptor_next(p_desc); } - if ( TUSB_DESC_ENDPOINT == p_desc[DESCRIPTOR_OFFSET_TYPE]) + if ( TUSB_DESC_ENDPOINT == p_desc[DESC_OFFSET_TYPE]) { // notification endpoint if any p_cdc->pipe_notification = hcd_pipe_open(dev_addr, (tusb_desc_endpoint_t const *) p_desc, TUSB_CLASS_CDC); - (*p_length) += p_desc[DESCRIPTOR_OFFSET_LENGTH]; + (*p_length) += p_desc[DESC_OFFSET_LEN]; p_desc = descriptor_next(p_desc); TU_ASSERT(pipehandle_is_valid(p_cdc->pipe_notification), TUSB_ERROR_HCD_OPEN_PIPE_FAILED); } //------------- Data Interface (if any) -------------// - if ( (TUSB_DESC_INTERFACE == p_desc[DESCRIPTOR_OFFSET_TYPE]) && + if ( (TUSB_DESC_INTERFACE == p_desc[DESC_OFFSET_TYPE]) && (TUSB_CLASS_CDC_DATA == ((tusb_desc_interface_t const *) p_desc)->bInterfaceClass) ) { - (*p_length) += p_desc[DESCRIPTOR_OFFSET_LENGTH]; + (*p_length) += p_desc[DESC_OFFSET_LEN]; p_desc = descriptor_next(p_desc); // data endpoints expected to be in pairs @@ -208,7 +208,7 @@ tusb_error_t cdch_open_subtask(uint8_t dev_addr, tusb_desc_interface_t const *p_ (*p_pipe_hdl) = hcd_pipe_open(dev_addr, p_endpoint, TUSB_CLASS_CDC); TU_ASSERT ( pipehandle_is_valid(*p_pipe_hdl), TUSB_ERROR_HCD_OPEN_PIPE_FAILED ); - (*p_length) += p_desc[DESCRIPTOR_OFFSET_LENGTH]; + (*p_length) += p_desc[DESC_OFFSET_LEN]; p_desc = descriptor_next( p_desc ); } } diff --git a/src/class/hid/hid_device.c b/src/class/hid/hid_device.c index bc2ee8c64..9f22697a6 100644 --- a/src/class/hid/hid_device.c +++ b/src/class/hid/hid_device.c @@ -259,12 +259,12 @@ tusb_error_t hidd_open(uint8_t rhport, tusb_desc_interface_t const * p_interface uint8_t const *p_desc = (uint8_t const *) p_interface_desc; //------------- HID descriptor -------------// - p_desc += p_desc[DESCRIPTOR_OFFSET_LENGTH]; + p_desc += p_desc[DESC_OFFSET_LEN]; tusb_hid_descriptor_hid_t const *p_desc_hid = (tusb_hid_descriptor_hid_t const *) p_desc; TU_ASSERT(HID_DESC_TYPE_HID == p_desc_hid->bDescriptorType, TUSB_ERROR_HIDD_DESCRIPTOR_INTERFACE); //------------- Endpoint Descriptor -------------// - p_desc += p_desc[DESCRIPTOR_OFFSET_LENGTH]; + p_desc += p_desc[DESC_OFFSET_LEN]; tusb_desc_endpoint_t const *p_desc_endpoint = (tusb_desc_endpoint_t const *) p_desc; TU_ASSERT(TUSB_DESC_ENDPOINT == p_desc_endpoint->bDescriptorType, TUSB_ERROR_HIDD_DESCRIPTOR_INTERFACE); diff --git a/src/class/hid/hid_host.c b/src/class/hid/hid_host.c index 69f86ee0b..fe0b7748b 100644 --- a/src/class/hid/hid_host.c +++ b/src/class/hid/hid_host.c @@ -186,12 +186,12 @@ tusb_error_t hidh_open_subtask(uint8_t dev_addr, tusb_desc_interface_t const *p_ uint8_t const *p_desc = (uint8_t const *) p_interface_desc; //------------- HID descriptor -------------// - p_desc += p_desc[DESCRIPTOR_OFFSET_LENGTH]; + p_desc += p_desc[DESC_OFFSET_LEN]; tusb_hid_descriptor_hid_t const *p_desc_hid = (tusb_hid_descriptor_hid_t const *) p_desc; TU_ASSERT(HID_DESC_TYPE_HID == p_desc_hid->bDescriptorType, TUSB_ERROR_INVALID_PARA); //------------- Endpoint Descriptor -------------// - p_desc += p_desc[DESCRIPTOR_OFFSET_LENGTH]; + p_desc += p_desc[DESC_OFFSET_LEN]; tusb_desc_endpoint_t const * p_endpoint_desc = (tusb_desc_endpoint_t const *) p_desc; TU_ASSERT(TUSB_DESC_ENDPOINT == p_endpoint_desc->bDescriptorType, TUSB_ERROR_INVALID_PARA); diff --git a/src/common/tusb_common.h b/src/common/tusb_common.h index 2b45a50c9..ddfceabdb 100644 --- a/src/common/tusb_common.h +++ b/src/common/tusb_common.h @@ -144,12 +144,17 @@ static inline uint8_t const * descriptor_next(uint8_t const p_desc[]) { - return p_desc + p_desc[DESCRIPTOR_OFFSET_LENGTH]; + return p_desc + p_desc[DESC_OFFSET_LEN]; } -static inline uint8_t descriptor_typeof(uint8_t const p_desc[]) +static inline uint8_t descriptor_type(uint8_t const p_desc[]) { - return p_desc[DESCRIPTOR_OFFSET_TYPE]; + return p_desc[DESC_OFFSET_TYPE]; +} + +static inline uint8_t descriptor_len(uint8_t const p_desc[]) +{ + return p_desc[DESC_OFFSET_LEN]; } //------------- Conversion -------------// diff --git a/src/common/tusb_types.h b/src/common/tusb_types.h index 4b8ef899c..65e7cd999 100644 --- a/src/common/tusb_types.h +++ b/src/common/tusb_types.h @@ -203,8 +203,8 @@ typedef enum }tusb_event_t; enum { - DESCRIPTOR_OFFSET_LENGTH = 0, - DESCRIPTOR_OFFSET_TYPE = 1 + DESC_OFFSET_LEN = 0, + DESC_OFFSET_TYPE = 1 }; enum { diff --git a/src/device/usbd.c b/src/device/usbd.c index 504cdf77b..d795e4f9a 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -66,7 +66,10 @@ typedef struct { uint8_t config_num; // map interface number to driver (0xff is invalid) - uint8_t itf2drv[16]; + uint8_t itf2drv[16]; + + // map endpoint to driver ( 0xff is invalid ) + uint8_t ep2drv[2][8]; }usbd_device_t; CFG_TUSB_ATTR_USBRAM CFG_TUSB_MEM_ALIGN uint8_t _usbd_ctrl_buf[CFG_TUD_CTRL_BUFSIZE]; @@ -100,18 +103,6 @@ static usbd_class_driver_t const usbd_class_drivers[] = }, #endif - #if DEVICE_CLASS_HID - { - .class_code = TUSB_CLASS_HID, - .init = hidd_init, - .open = hidd_open, - .control_req_st = hidd_control_request_st, - .xfer_cb = hidd_xfer_cb, - .sof = NULL, - .reset = hidd_reset - }, - #endif - #if CFG_TUD_MSC { .class_code = TUSB_CLASS_MSC, @@ -124,6 +115,19 @@ static usbd_class_driver_t const usbd_class_drivers[] = }, #endif + + #if DEVICE_CLASS_HID + { + .class_code = TUSB_CLASS_HID, + .init = hidd_init, + .open = hidd_open, + .control_req_st = hidd_control_request_st, + .xfer_cb = hidd_xfer_cb, + .sof = NULL, + .reset = hidd_reset + }, + #endif + #if CFG_TUD_CUSTOM_CLASS { .class_code = TUSB_CLASS_VENDOR_SPECIFIC, @@ -191,6 +195,7 @@ static osal_semaphore_def_t _usbd_sem_def; //--------------------------------------------------------------------+ // INTERNAL FUNCTION //--------------------------------------------------------------------+ +static void mark_interface_endpoint(uint8_t const* p_desc, uint16_t desc_len, uint8_t driver_id); static tusb_error_t proc_set_config_req(uint8_t rhport, uint8_t config_number); static uint16_t get_descriptor(uint8_t rhport, tusb_control_request_t const * const p_request, uint8_t const ** pp_buffer); @@ -300,6 +305,7 @@ static void usbd_reset(uint8_t rhport) { varclr_(&_usbd_dev); memset(_usbd_dev.itf2drv, 0xff, sizeof(_usbd_dev.itf2drv)); // invalid mapping + memset(_usbd_dev.ep2drv , 0xff, sizeof(_usbd_dev.ep2drv )); // invalid mapping for (uint8_t i = 0; i < USBD_CLASS_DRIVER_COUNT; i++) { @@ -395,6 +401,7 @@ static tusb_error_t proc_control_request_st(uint8_t rhport, tusb_control_request OSAL_SUBTASK_END } +// Process Set Configure Request // TODO Host (windows) can get HID report descriptor before set configured // may need to open interface before set configured static tusb_error_t proc_set_config_req(uint8_t rhport, uint8_t config_number) @@ -418,33 +425,35 @@ static tusb_error_t proc_set_config_req(uint8_t rhport, uint8_t config_number) while( p_desc < desc_cfg + cfg_len ) { - if ( TUSB_DESC_INTERFACE_ASSOCIATION == p_desc[DESCRIPTOR_OFFSET_TYPE]) + if ( TUSB_DESC_INTERFACE_ASSOCIATION == descriptor_type(p_desc) ) { - p_desc += p_desc[DESCRIPTOR_OFFSET_LENGTH]; // ignore Interface Association + p_desc = descriptor_next(p_desc); // ignore Interface Association }else { - TU_ASSERT( TUSB_DESC_INTERFACE == p_desc[DESCRIPTOR_OFFSET_TYPE], TUSB_ERROR_NOT_SUPPORTED_YET ); + TU_ASSERT( TUSB_DESC_INTERFACE == descriptor_type(p_desc), TUSB_ERROR_NOT_SUPPORTED_YET ); tusb_desc_interface_t* p_desc_itf = (tusb_desc_interface_t*) p_desc; uint8_t const class_code = p_desc_itf->bInterfaceClass; // Check if class is supported - uint8_t drid; - for (drid = 0; drid < USBD_CLASS_DRIVER_COUNT; drid++) + uint8_t drv_id; + for (drv_id = 0; drv_id < USBD_CLASS_DRIVER_COUNT; drv_id++) { - if ( usbd_class_drivers[drid].class_code == class_code ) break; + if ( usbd_class_drivers[drv_id].class_code == class_code ) break; } - TU_ASSERT( drid < USBD_CLASS_DRIVER_COUNT, TUSB_ERROR_NOT_SUPPORTED_YET ); + TU_ASSERT( drv_id < USBD_CLASS_DRIVER_COUNT, TUSB_ERROR_NOT_SUPPORTED_YET ); // Interface number must not be used TU_ASSERT( 0xff == _usbd_dev.itf2drv[p_desc_itf->bInterfaceNumber], TUSB_ERROR_FAILED); - _usbd_dev.itf2drv[p_desc_itf->bInterfaceNumber] = drid; + _usbd_dev.itf2drv[p_desc_itf->bInterfaceNumber] = drv_id; + + uint16_t len=0; + TU_ASSERT_ERR( usbd_class_drivers[drv_id].open( rhport, p_desc_itf, &len ) ); + TU_ASSERT( len >= sizeof(tusb_desc_interface_t), TUSB_ERROR_FAILED ); - uint16_t length=0; - TU_ASSERT_ERR( usbd_class_drivers[drid].open( rhport, p_desc_itf, &length ) ); + mark_interface_endpoint(p_desc, len, drv_id); - TU_ASSERT( length >= sizeof(tusb_desc_interface_t), TUSB_ERROR_FAILED ); - p_desc += length; + p_desc += len; // next interface } } @@ -454,6 +463,7 @@ static tusb_error_t proc_set_config_req(uint8_t rhport, uint8_t config_number) return TUSB_ERROR_NONE; } +// return len of descriptor and change pointer to descriptor's buffer static uint16_t get_descriptor(uint8_t rhport, tusb_control_request_t const * const p_request, uint8_t const ** pp_buffer) { (void) rhport; @@ -514,6 +524,25 @@ static uint16_t get_descriptor(uint8_t rhport, tusb_control_request_t const * co return len; } +// Helper marking endpoint of interface belongs to class driver +static void mark_interface_endpoint(uint8_t const* p_desc, uint16_t desc_len, uint8_t driver_id) +{ + uint16_t len = 0; + + while( len < desc_len ) + { + if ( TUSB_DESC_ENDPOINT == descriptor_type(p_desc) ) + { + uint8_t const ep_addr = ((tusb_desc_endpoint_t const*) p_desc)->bEndpointAddress; + + _usbd_dev.ep2drv[ edpt_dir(ep_addr) ][ edpt_number(ep_addr) ] = driver_id; + } + + len += descriptor_len(p_desc); + p_desc = descriptor_next(p_desc); + } +} + //--------------------------------------------------------------------+ // USBD-DCD Callback API //--------------------------------------------------------------------+ diff --git a/src/host/usbh.c b/src/host/usbh.c index a67bd8d8c..6d1cd37ad 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -572,9 +572,9 @@ tusb_error_t enumeration_body_subtask(void) while( p_desc < enum_data_buffer + ((tusb_desc_configuration_t*)enum_data_buffer)->wTotalLength ) { // skip until we see interface descriptor - if ( TUSB_DESC_INTERFACE != p_desc[DESCRIPTOR_OFFSET_TYPE] ) + if ( TUSB_DESC_INTERFACE != p_desc[DESC_OFFSET_TYPE] ) { - p_desc += p_desc[DESCRIPTOR_OFFSET_LENGTH]; // skip the descriptor, increase by the descriptor's length + p_desc += p_desc[DESC_OFFSET_LEN]; // skip the descriptor, increase by the descriptor's length }else { static uint8_t class_index; // has to be static as it is used to call class's open_subtask @@ -600,11 +600,11 @@ tusb_error_t enumeration_body_subtask(void) p_desc += length; }else // Interface open failed, for example a subclass is not supported { - p_desc += p_desc[DESCRIPTOR_OFFSET_LENGTH]; // skip this interface, the rest will be skipped by the above loop + p_desc += p_desc[DESC_OFFSET_LEN]; // skip this interface, the rest will be skipped by the above loop } } else // unsupported class (not enable or yet implemented) { - p_desc += p_desc[DESCRIPTOR_OFFSET_LENGTH]; // skip this interface, the rest will be skipped by the above loop + p_desc += p_desc[DESC_OFFSET_LEN]; // skip this interface, the rest will be skipped by the above loop } } } -- cgit v1.3.1 From 361928f42983bed4d10443668d8eb3db69ade80f Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 23 Jul 2018 22:32:21 +0700 Subject: rename timeout_timer.h to tusb_timeout.h --- src/class/hid/hid_device.c | 2 +- src/common/timeout_timer.h | 85 ---------------------- src/common/tusb_timeout.h | 85 ++++++++++++++++++++++ src/host/ehci/ehci.c | 2 +- src/host/ohci/ohci.c | 2 +- .../nxp/lpc11xx_lpc13xx/dcd_lpc_11uxx_13uxx.c | 2 +- src/portable/nxp/lpc43xx_lpc18xx/dcd_lpc43xx.c | 2 +- 7 files changed, 90 insertions(+), 90 deletions(-) delete mode 100644 src/common/timeout_timer.h create mode 100644 src/common/tusb_timeout.h (limited to 'src/host') diff --git a/src/class/hid/hid_device.c b/src/class/hid/hid_device.c index 325485425..4ce927725 100644 --- a/src/class/hid/hid_device.c +++ b/src/class/hid/hid_device.c @@ -45,7 +45,7 @@ // INCLUDE //--------------------------------------------------------------------+ #include "common/tusb_common.h" -#include "common/timeout_timer.h" +#include "common/tusb_timeout.h" #include "hid_device.h" #include "device/usbd_pvt.h" diff --git a/src/common/timeout_timer.h b/src/common/timeout_timer.h deleted file mode 100644 index 5c62c6904..000000000 --- a/src/common/timeout_timer.h +++ /dev/null @@ -1,85 +0,0 @@ -/**************************************************************************/ -/*! - @file timeout_timer.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 Group_Common Common Files - * \defgroup Group_TimeoutTimer timeout timer - * @{ */ - - -#ifndef _TUSB_TIMEOUT_TTIMER_H_ -#define _TUSB_TIMEOUT_TTIMER_H_ - -#include "tusb_compiler.h" -#include "tusb_hal.h" - -#ifdef __cplusplus -extern "C" { -#endif - -typedef struct { - uint32_t start; - uint32_t interval; -}timeout_timer_t; - -static inline void timeout_set(timeout_timer_t* tt, uint32_t msec) -{ - tt->interval = msec; - tt->start = tusb_hal_millis(); -} - -static inline bool timeout_expired(timeout_timer_t* tt) -{ - return ( tusb_hal_millis() - tt->start ) >= tt->interval; -} - -static inline void timeout_blocking_wait(uint32_t msec) -{ - timeout_timer_t tt; - timeout_set(&tt, msec); - - // blocking delay - while ( !timeout_expired(&tt) ) { } -} - -#ifdef __cplusplus - } -#endif - -#endif /* _TUSB_TIMEOUT_TTIMER_H_ */ - -/** @} */ diff --git a/src/common/tusb_timeout.h b/src/common/tusb_timeout.h new file mode 100644 index 000000000..400434708 --- /dev/null +++ b/src/common/tusb_timeout.h @@ -0,0 +1,85 @@ +/**************************************************************************/ +/*! + @file tusb_timeout.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 Group_Common Common Files + * \defgroup Group_TimeoutTimer timeout timer + * @{ */ + + +#ifndef _TUSB_TIMEOUT_H_ +#define _TUSB_TIMEOUT_H_ + +#include "tusb_compiler.h" +#include "tusb_hal.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct { + uint32_t start; + uint32_t interval; +}timeout_timer_t; + +static inline void timeout_set(timeout_timer_t* tt, uint32_t msec) +{ + tt->interval = msec; + tt->start = tusb_hal_millis(); +} + +static inline bool timeout_expired(timeout_timer_t* tt) +{ + return ( tusb_hal_millis() - tt->start ) >= tt->interval; +} + +static inline void timeout_blocking_wait(uint32_t msec) +{ + timeout_timer_t tt; + timeout_set(&tt, msec); + + // blocking delay + while ( !timeout_expired(&tt) ) { } +} + +#ifdef __cplusplus + } +#endif + +#endif /* _TUSB_TIMEOUT_H_ */ + +/** @} */ diff --git a/src/host/ehci/ehci.c b/src/host/ehci/ehci.c index c9cd39378..9e326ec53 100644 --- a/src/host/ehci/ehci.c +++ b/src/host/ehci/ehci.c @@ -44,7 +44,7 @@ //--------------------------------------------------------------------+ #include "hal/hal.h" #include "osal/osal.h" -#include "common/timeout_timer.h" +#include "common/tusb_timeout.h" #include "../hcd.h" #include "../usbh_hcd.h" diff --git a/src/host/ohci/ohci.c b/src/host/ohci/ohci.c index 5788aac94..73e9d887e 100644 --- a/src/host/ohci/ohci.c +++ b/src/host/ohci/ohci.c @@ -44,7 +44,7 @@ //--------------------------------------------------------------------+ #include "hal/hal.h" #include "osal/osal.h" -#include "common/timeout_timer.h" +#include "common/tusb_timeout.h" #include "../hcd.h" #include "../usbh_hcd.h" diff --git a/src/portable/nxp/lpc11xx_lpc13xx/dcd_lpc_11uxx_13uxx.c b/src/portable/nxp/lpc11xx_lpc13xx/dcd_lpc_11uxx_13uxx.c index f0472f41d..0bb79090e 100644 --- a/src/portable/nxp/lpc11xx_lpc13xx/dcd_lpc_11uxx_13uxx.c +++ b/src/portable/nxp/lpc11xx_lpc13xx/dcd_lpc_11uxx_13uxx.c @@ -51,7 +51,7 @@ #include "common/tusb_common.h" #include "hal/hal.h" #include "osal/osal.h" -#include "common/timeout_timer.h" +#include "common/tusb_timeout.h" #include "device/dcd.h" #include "usbd_dcd.h" diff --git a/src/portable/nxp/lpc43xx_lpc18xx/dcd_lpc43xx.c b/src/portable/nxp/lpc43xx_lpc18xx/dcd_lpc43xx.c index a08e20a3f..6c076baa8 100644 --- a/src/portable/nxp/lpc43xx_lpc18xx/dcd_lpc43xx.c +++ b/src/portable/nxp/lpc43xx_lpc18xx/dcd_lpc43xx.c @@ -46,7 +46,7 @@ #include "common/tusb_common.h" #include "tusb_hal.h" #include "osal/osal.h" -#include "common/timeout_timer.h" +#include "common/tusb_timeout.h" #include "device/dcd.h" #include "dcd_lpc43xx.h" -- cgit v1.3.1 From 51903a60c51bd1006bec9266dbe1bfb35e282675 Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 23 Jul 2018 22:36:29 +0700 Subject: rename timeout_ API to tu_timeout API --- src/class/hid/hid_device.c | 6 +++--- src/common/tusb_timeout.h | 14 +++++++------- src/host/ehci/ehci.c | 8 ++++---- src/portable/nxp/lpc43xx_lpc18xx/hal_lpc43xx.c | 8 ++++---- 4 files changed, 18 insertions(+), 18 deletions(-) (limited to 'src/host') diff --git a/src/class/hid/hid_device.c b/src/class/hid/hid_device.c index 4ce927725..82c7e3d3f 100644 --- a/src/class/hid/hid_device.c +++ b/src/class/hid/hid_device.c @@ -142,14 +142,14 @@ bool tud_hid_keyboard_send_string(const char* str, uint32_t interval_ms) tud_hid_keyboard_send_char(ch); // Blocking delay - timeout_blocking_wait(interval_ms); + tu_timeout_wait(interval_ms); /* Only need to empty report if the next character is NULL or the same with * the current one, else no need to send */ if ( lookahead == ch || lookahead == 0 ) { tud_hid_keyboard_send_report(NULL); - timeout_blocking_wait(interval_ms); + tu_timeout_wait(interval_ms); } } @@ -170,7 +170,7 @@ bool tud_hid_mouse_busy(void) bool tud_hid_mouse_send(hid_mouse_report_t const *p_report) { - VERIFY( tud_mounted() && !tud_hid_mouse_is_busy() ); + VERIFY( tud_mounted() && !tud_hid_mouse_busy() ); hidd_interface_t * p_hid = &_mse_itf; memcpy(p_hid->report_buf, p_report, sizeof(hid_mouse_report_t)); diff --git a/src/common/tusb_timeout.h b/src/common/tusb_timeout.h index 400434708..7c51ff36f 100644 --- a/src/common/tusb_timeout.h +++ b/src/common/tusb_timeout.h @@ -54,26 +54,26 @@ extern "C" { typedef struct { uint32_t start; uint32_t interval; -}timeout_timer_t; +}tu_timeout_t; -static inline void timeout_set(timeout_timer_t* tt, uint32_t msec) +static inline void tu_timeout_set(tu_timeout_t* tt, uint32_t msec) { tt->interval = msec; tt->start = tusb_hal_millis(); } -static inline bool timeout_expired(timeout_timer_t* tt) +static inline bool tu_timeout_expired(tu_timeout_t* tt) { return ( tusb_hal_millis() - tt->start ) >= tt->interval; } -static inline void timeout_blocking_wait(uint32_t msec) +static inline void tu_timeout_wait(uint32_t msec) { - timeout_timer_t tt; - timeout_set(&tt, msec); + tu_timeout_t tt; + tu_timeout_set(&tt, msec); // blocking delay - while ( !timeout_expired(&tt) ) { } + while ( !tu_timeout_expired(&tt) ) { } } #ifdef __cplusplus diff --git a/src/host/ehci/ehci.c b/src/host/ehci/ehci.c index 9e326ec53..ba23319ca 100644 --- a/src/host/ehci/ehci.c +++ b/src/host/ehci/ehci.c @@ -268,14 +268,14 @@ static tusb_error_t hcd_controller_init(uint8_t hostid) static tusb_error_t hcd_controller_stop(uint8_t hostid) { ehci_registers_t* const regs = get_operational_register(hostid); - timeout_timer_t timeout; + tu_timeout_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)) {} + tu_timeout_set(&timeout, 2); // USB Spec: controller has to stop within 16 uframe = 2 frames + while( regs->usb_sts_bit.hc_halted == 0 && !tu_timeout_expired(&timeout)) {} - return timeout_expired(&timeout) ? TUSB_ERROR_OSAL_TIMEOUT : TUSB_ERROR_NONE; + return tu_timeout_expired(&timeout) ? TUSB_ERROR_OSAL_TIMEOUT : TUSB_ERROR_NONE; } //--------------------------------------------------------------------+ diff --git a/src/portable/nxp/lpc43xx_lpc18xx/hal_lpc43xx.c b/src/portable/nxp/lpc43xx_lpc18xx/hal_lpc43xx.c index 92f9f1cf0..18745d03e 100644 --- a/src/portable/nxp/lpc43xx_lpc18xx/hal_lpc43xx.c +++ b/src/portable/nxp/lpc43xx_lpc18xx/hal_lpc43xx.c @@ -72,11 +72,11 @@ static void hal_controller_reset(uint8_t rhport) // NXP chip powered with non-host mode --> sts bit is not correctly reflected (*p_reg_usbcmd) |= BIT_(1); -// timeout_timer_t timeout; -// timeout_set(&timeout, 2); // should not take longer the time to stop controller - while( ((*p_reg_usbcmd) & BIT_(1)) /*&& !timeout_expired(&timeout)*/) {} +// tu_timeout_t timeout; +// tu_timeout_set(&timeout, 2); // should not take longer the time to stop controller + while( ((*p_reg_usbcmd) & BIT_(1)) /*&& !tu_timeout_expired(&timeout)*/) {} // -// return timeout_expired(&timeout) ? TUSB_ERROR_OSAL_TIMEOUT : TUSB_ERROR_NONE; +// return tu_timeout_expired(&timeout) ? TUSB_ERROR_OSAL_TIMEOUT : TUSB_ERROR_NONE; } bool tusb_hal_init(void) -- cgit v1.3.1 From 5f6cd4903101b0486771efdb2bb435ddf6cf8e7a Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 23 Jul 2018 23:41:14 +0700 Subject: clean up include --- src/class/hid/hid_device.c | 1 - src/common/tusb_common.h | 6 ++---- src/common/tusb_timeout.h | 15 ++++++++++++++- src/host/ehci/ehci.c | 1 - src/host/ohci/ohci.c | 1 - src/portable/nxp/lpc11xx_lpc13xx/dcd_lpc_11uxx_13uxx.c | 1 - src/portable/nxp/lpc43xx_lpc18xx/dcd_lpc43xx.c | 1 - 7 files changed, 16 insertions(+), 10 deletions(-) (limited to 'src/host') diff --git a/src/class/hid/hid_device.c b/src/class/hid/hid_device.c index 82c7e3d3f..7aca8ef8e 100644 --- a/src/class/hid/hid_device.c +++ b/src/class/hid/hid_device.c @@ -45,7 +45,6 @@ // INCLUDE //--------------------------------------------------------------------+ #include "common/tusb_common.h" -#include "common/tusb_timeout.h" #include "hid_device.h" #include "device/usbd_pvt.h" diff --git a/src/common/tusb_common.h b/src/common/tusb_common.h index ddfceabdb..44f31ffe0 100644 --- a/src/common/tusb_common.h +++ b/src/common/tusb_common.h @@ -61,15 +61,13 @@ //------------- TUSB Option Header -------------// #include "tusb_option.h" -//------------- General Header -------------// +//------------- Common Header -------------// #include "tusb_compiler.h" #include "tusb_verify.h" #include "binary.h" #include "tusb_error.h" -#include "tusb_hal.h" #include "tusb_fifo.h" - -//------------- TUSB Header -------------// +#include "tusb_timeout.h" #include "tusb_types.h" //--------------------------------------------------------------------+ diff --git a/src/common/tusb_timeout.h b/src/common/tusb_timeout.h index 7c51ff36f..9d80f5fe7 100644 --- a/src/common/tusb_timeout.h +++ b/src/common/tusb_timeout.h @@ -45,7 +45,6 @@ #define _TUSB_TIMEOUT_H_ #include "tusb_compiler.h" -#include "tusb_hal.h" #ifdef __cplusplus extern "C" { @@ -56,6 +55,8 @@ typedef struct { uint32_t interval; }tu_timeout_t; +extern uint32_t tusb_hal_millis(void); + static inline void tu_timeout_set(tu_timeout_t* tt, uint32_t msec) { tt->interval = msec; @@ -67,6 +68,18 @@ static inline bool tu_timeout_expired(tu_timeout_t* tt) return ( tusb_hal_millis() - tt->start ) >= tt->interval; } +// For used with periodic event to prevent drift +static inline void tu_timeout_reset(tu_timeout_t* tt) +{ + tt->start += tt->interval; +} + +static inline void tu_timeout_restart(tu_timeout_t* tt) +{ + tt->start = tusb_hal_millis(); +} + + static inline void tu_timeout_wait(uint32_t msec) { tu_timeout_t tt; diff --git a/src/host/ehci/ehci.c b/src/host/ehci/ehci.c index ba23319ca..09f2f573a 100644 --- a/src/host/ehci/ehci.c +++ b/src/host/ehci/ehci.c @@ -44,7 +44,6 @@ //--------------------------------------------------------------------+ #include "hal/hal.h" #include "osal/osal.h" -#include "common/tusb_timeout.h" #include "../hcd.h" #include "../usbh_hcd.h" diff --git a/src/host/ohci/ohci.c b/src/host/ohci/ohci.c index 73e9d887e..644dbfa0f 100644 --- a/src/host/ohci/ohci.c +++ b/src/host/ohci/ohci.c @@ -44,7 +44,6 @@ //--------------------------------------------------------------------+ #include "hal/hal.h" #include "osal/osal.h" -#include "common/tusb_timeout.h" #include "../hcd.h" #include "../usbh_hcd.h" diff --git a/src/portable/nxp/lpc11xx_lpc13xx/dcd_lpc_11uxx_13uxx.c b/src/portable/nxp/lpc11xx_lpc13xx/dcd_lpc_11uxx_13uxx.c index 0bb79090e..68eef47e1 100644 --- a/src/portable/nxp/lpc11xx_lpc13xx/dcd_lpc_11uxx_13uxx.c +++ b/src/portable/nxp/lpc11xx_lpc13xx/dcd_lpc_11uxx_13uxx.c @@ -51,7 +51,6 @@ #include "common/tusb_common.h" #include "hal/hal.h" #include "osal/osal.h" -#include "common/tusb_timeout.h" #include "device/dcd.h" #include "usbd_dcd.h" diff --git a/src/portable/nxp/lpc43xx_lpc18xx/dcd_lpc43xx.c b/src/portable/nxp/lpc43xx_lpc18xx/dcd_lpc43xx.c index 6c076baa8..0b48ad1e6 100644 --- a/src/portable/nxp/lpc43xx_lpc18xx/dcd_lpc43xx.c +++ b/src/portable/nxp/lpc43xx_lpc18xx/dcd_lpc43xx.c @@ -46,7 +46,6 @@ #include "common/tusb_common.h" #include "tusb_hal.h" #include "osal/osal.h" -#include "common/tusb_timeout.h" #include "device/dcd.h" #include "dcd_lpc43xx.h" -- cgit v1.3.1 From e07b1acbed02fff395c91b421b7fdf6c7cda61a4 Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 13 Aug 2018 18:10:23 +0700 Subject: rename VERIFY to TU_VERIFY to avoid conflict with application --- examples/obsolete/host/src/cdc_serial_host_app.c | 2 +- examples/obsolete/host/src/keyboard_host_app.c | 2 +- examples/obsolete/host/src/mouse_host_app.c | 2 +- src/class/cdc/cdc.h | 6 +- src/class/cdc/cdc_device.c | 4 +- src/class/cdc/cdc_rndis.h | 4 +- src/class/cdc/cdc_rndis_host.c | 2 +- src/class/hid/hid_device.c | 12 ++-- src/class/hid/hid_host.c | 2 +- src/class/msc/msc.h | 32 ++++----- src/class/msc/msc_device.c | 2 +- src/class/msc/msc_device.h | 2 +- src/common/tusb_compiler.h | 6 +- src/common/tusb_types.h | 2 +- src/common/tusb_verify.h | 78 +++++++++++----------- src/device/usbd.c | 8 +-- src/host/ehci/ehci.c | 4 +- src/host/ehci/ehci.h | 10 +-- src/host/hub.h | 6 +- src/host/ohci/ohci.h | 10 +-- src/osal/osal.h | 8 +-- src/osal/osal_none.h | 8 +-- .../nxp/lpc11xx_lpc13xx/dcd_lpc_11uxx_13uxx.c | 2 +- src/portable/nxp/lpc17xx/dcd_lpc175x_6x.c | 6 +- src/portable/nxp/lpc17xx/dcd_lpc175x_6x.h | 2 +- src/portable/nxp/lpc43xx_lpc18xx/dcd_lpc43xx.c | 8 +-- src/portable/nxp/lpc43xx_lpc18xx/dcd_lpc43xx.h | 4 +- src/portable/nxp/lpc43xx_lpc18xx/hal_lpc43xx.c | 2 +- src/tusb.c | 2 +- 29 files changed, 119 insertions(+), 119 deletions(-) (limited to 'src/host') diff --git a/examples/obsolete/host/src/cdc_serial_host_app.c b/examples/obsolete/host/src/cdc_serial_host_app.c index 0782d0518..e21a3a67d 100644 --- a/examples/obsolete/host/src/cdc_serial_host_app.c +++ b/examples/obsolete/host/src/cdc_serial_host_app.c @@ -115,7 +115,7 @@ void cdc_serial_host_app_init(void) sem_hdl = osal_semaphore_create(1, 0); TU_ASSERT( sem_hdl, VOID_RETURN); - VERIFY( osal_task_create(cdc_serial_host_app_task, "cdc", 128, NULL, CDC_SERIAL_APP_TASK_PRIO), ); + TU_VERIFY( osal_task_create(cdc_serial_host_app_task, "cdc", 128, NULL, CDC_SERIAL_APP_TASK_PRIO), ); } //------------- main task -------------// diff --git a/examples/obsolete/host/src/keyboard_host_app.c b/examples/obsolete/host/src/keyboard_host_app.c index 130df0feb..26b1a0800 100644 --- a/examples/obsolete/host/src/keyboard_host_app.c +++ b/examples/obsolete/host/src/keyboard_host_app.c @@ -105,7 +105,7 @@ void keyboard_host_app_init(void) queue_kbd_hdl = osal_queue_create( QUEUE_KEYBOARD_REPORT_DEPTH, sizeof(hid_keyboard_report_t) ); TU_ASSERT( queue_kbd_hdl, VOID_RETURN ); - VERIFY( osal_task_create(keyboard_host_app_task, "kbd", 128, NULL, KEYBOARD_APP_TASK_PRIO), ); + TU_VERIFY( osal_task_create(keyboard_host_app_task, "kbd", 128, NULL, KEYBOARD_APP_TASK_PRIO), ); } //------------- main task -------------// diff --git a/examples/obsolete/host/src/mouse_host_app.c b/examples/obsolete/host/src/mouse_host_app.c index e9ee482d8..c326becb8 100644 --- a/examples/obsolete/host/src/mouse_host_app.c +++ b/examples/obsolete/host/src/mouse_host_app.c @@ -106,7 +106,7 @@ void mouse_host_app_init(void) queue_mouse_hdl = osal_queue_create( QUEUE_MOUSE_REPORT_DEPTH, sizeof(hid_mouse_report_t) ); TU_ASSERT( queue_mouse_hdl, VOID_RETURN); - VERIFY( osal_task_create(mouse_host_app_task, "mouse", 128, NULL, MOUSE_APP_TASK_PRIO), ); + TU_VERIFY( osal_task_create(mouse_host_app_task, "mouse", 128, NULL, MOUSE_APP_TASK_PRIO), ); } //------------- main task -------------// diff --git a/src/class/cdc/cdc.h b/src/class/cdc/cdc.h index b0c4f90d4..1b127ad28 100644 --- a/src/class/cdc/cdc.h +++ b/src/class/cdc/cdc.h @@ -300,7 +300,7 @@ typedef struct ATTR_PACKED uint8_t : 0; }cdc_acm_capability_t; -VERIFY_STATIC(sizeof(cdc_acm_capability_t) == 1, "mostly problem with compiler"); +TU_VERIFY_STATIC(sizeof(cdc_acm_capability_t) == 1, "mostly problem with compiler"); /// \brief Abstract Control Management Functional Descriptor /// \details This functional descriptor describes the commands supported by by the Communications Class interface with SubClass code of \ref CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL @@ -390,7 +390,7 @@ typedef struct ATTR_PACKED uint8_t data_bits; ///< can be 5, 6, 7, 8 or 16 } cdc_line_coding_t; -VERIFY_STATIC(sizeof(cdc_line_coding_t) == 7, "size is not correct"); +TU_VERIFY_STATIC(sizeof(cdc_line_coding_t) == 7, "size is not correct"); typedef struct ATTR_PACKED { @@ -399,7 +399,7 @@ typedef struct ATTR_PACKED uint16_t : 14; } cdc_line_control_state_t; -VERIFY_STATIC(sizeof(cdc_line_control_state_t) == 2, "size is not correct"); +TU_VERIFY_STATIC(sizeof(cdc_line_control_state_t) == 2, "size is not correct"); /** @} */ diff --git a/src/class/cdc/cdc_device.c b/src/class/cdc/cdc_device.c index bbf1c8ceb..175e78d2f 100644 --- a/src/class/cdc/cdc_device.c +++ b/src/class/cdc/cdc_device.c @@ -157,11 +157,11 @@ uint32_t tud_cdc_n_write(uint8_t itf, void const* buffer, uint32_t bufsize) bool tud_cdc_n_write_flush (uint8_t itf) { cdcd_interface_t* p_cdc = &_cdcd_itf[itf]; - VERIFY( !dcd_edpt_busy(TUD_OPT_RHPORT, p_cdc->ep_in) ); // skip if previous transfer not complete + TU_VERIFY( !dcd_edpt_busy(TUD_OPT_RHPORT, p_cdc->ep_in) ); // skip if previous transfer not complete uint16_t count = tu_fifo_read_n(&_cdcd_itf[itf].tx_ff, p_cdc->epout_buf, CFG_TUD_CDC_EPSIZE); - VERIFY( tud_cdc_n_connected(itf) ); // fifo is empty if not connected + TU_VERIFY( tud_cdc_n_connected(itf) ); // fifo is empty if not connected if ( count ) TU_ASSERT( dcd_edpt_xfer(TUD_OPT_RHPORT, p_cdc->ep_in, p_cdc->epout_buf, count) ); diff --git a/src/class/cdc/cdc_rndis.h b/src/class/cdc/cdc_rndis.h index 460477eb0..20da5660b 100644 --- a/src/class/cdc/cdc_rndis.h +++ b/src/class/cdc/cdc_rndis.h @@ -142,7 +142,7 @@ typedef struct { uint8_t oid_buffer[] ; ///< Flexible array contains the input data supplied by the host, required for the OID query request processing by the device, as per the host NDIS specification. } rndis_msg_query_t, rndis_msg_set_t; -VERIFY_STATIC(sizeof(rndis_msg_query_t) == 28, "Make sure flexible array member does not affect layout"); +TU_VERIFY_STATIC(sizeof(rndis_msg_query_t) == 28, "Make sure flexible array member does not affect layout"); /// \brief Query Complete Message /// \details This message MUST be sent by the device in response to a query OID message. @@ -156,7 +156,7 @@ typedef struct { uint8_t oid_buffer[] ; ///< Flexible array member contains the response data to the OID query request as specified by the host. } rndis_msg_query_cmplt_t; -VERIFY_STATIC(sizeof(rndis_msg_query_cmplt_t) == 24, "Make sure flexible array member does not affect layout"); +TU_VERIFY_STATIC(sizeof(rndis_msg_query_cmplt_t) == 24, "Make sure flexible array member does not affect layout"); //------------- Reset -------------// /// \brief Reset Message diff --git a/src/class/cdc/cdc_rndis_host.c b/src/class/cdc/cdc_rndis_host.c index 62361feb4..4d28b0e0c 100644 --- a/src/class/cdc/cdc_rndis_host.c +++ b/src/class/cdc/cdc_rndis_host.c @@ -75,7 +75,7 @@ static tusb_error_t send_message_get_response_subtask( uint8_t dev_addr, cdch_da tusb_error_t tusbh_cdc_rndis_get_mac_addr(uint8_t dev_addr, uint8_t mac_address[6]) { TU_ASSERT( tusbh_cdc_rndis_is_mounted(dev_addr), TUSB_ERROR_CDCH_DEVICE_NOT_MOUNTED); - VERIFY( mac_address, TUSB_ERROR_INVALID_PARA); + TU_VERIFY( mac_address, TUSB_ERROR_INVALID_PARA); memcpy(mac_address, rndish_data[dev_addr-1].mac_address, 6); diff --git a/src/class/hid/hid_device.c b/src/class/hid/hid_device.c index 0527c14bf..410359e6d 100644 --- a/src/class/hid/hid_device.c +++ b/src/class/hid/hid_device.c @@ -125,7 +125,7 @@ bool tud_hid_generic_ready(void) bool tud_hid_generic_report(uint8_t report_id, void const* report, uint8_t len) { - VERIFY( tud_hid_generic_ready() && (len < REPORT_BUFSIZE) ); + TU_VERIFY( tud_hid_generic_ready() && (len < REPORT_BUFSIZE) ); hidd_interface_t * p_hid = &_hidd_itf[ITF_IDX_GENERIC]; @@ -159,7 +159,7 @@ bool tud_hid_keyboard_is_boot_protocol(void) static bool hidd_kbd_report(hid_keyboard_report_t const *p_report) { - VERIFY( tud_hid_keyboard_ready() ); + TU_VERIFY( tud_hid_keyboard_ready() ); hidd_interface_t * p_hid = _kbd_rpt.itf; @@ -253,7 +253,7 @@ bool tud_hid_mouse_is_boot_protocol(void) static bool hidd_mouse_report(hid_mouse_report_t const *p_report) { - VERIFY( tud_hid_mouse_ready() ); + TU_VERIFY( tud_hid_mouse_ready() ); hidd_interface_t * p_hid = _mse_rpt.itf; memcpy(p_hid->report_buf, p_report, sizeof(hid_mouse_report_t)); @@ -277,7 +277,7 @@ bool tud_hid_mouse_data(uint8_t buttons, int8_t x, int8_t y, int8_t scroll, int8 bool tud_hid_mouse_move(int8_t x, int8_t y) { - VERIFY( tud_hid_mouse_ready() ); + TU_VERIFY( tud_hid_mouse_ready() ); hidd_interface_t * p_hid = _mse_rpt.itf; uint8_t prev_buttons = p_hid->report_buf[0]; @@ -287,7 +287,7 @@ bool tud_hid_mouse_move(int8_t x, int8_t y) bool tud_hid_mouse_scroll(int8_t vertical, int8_t horizontal) { - VERIFY( tud_hid_mouse_ready() ); + TU_VERIFY( tud_hid_mouse_ready() ); hidd_interface_t * p_hid = _mse_rpt.itf; uint8_t prev_buttons = p_hid->report_buf[0]; @@ -390,7 +390,7 @@ tusb_error_t hidd_open(uint8_t rhport, tusb_desc_interface_t const * desc_itf, u TU_ASSERT(p_hid, ERR_TUD_INVALID_DESCRIPTOR); } - VERIFY(p_hid->desc_report, ERR_TUD_INVALID_DESCRIPTOR); + TU_VERIFY(p_hid->desc_report, ERR_TUD_INVALID_DESCRIPTOR); TU_ASSERT( dcd_edpt_open(rhport, desc_edpt), ERR_TUD_EDPT_OPEN_FAILED ); p_hid->itf_num = desc_itf->bInterfaceNumber; diff --git a/src/class/hid/hid_host.c b/src/class/hid/hid_host.c index fa617c5b0..369dad638 100644 --- a/src/class/hid/hid_host.c +++ b/src/class/hid/hid_host.c @@ -77,7 +77,7 @@ tusb_error_t hidh_interface_get_report(uint8_t dev_addr, void * report, hidh_int //------------- parameters validation -------------// // TODO change to use is configured function TU_ASSERT (TUSB_DEVICE_STATE_CONFIGURED == tuh_device_get_state(dev_addr), TUSB_ERROR_DEVICE_NOT_READY); - VERIFY (report, TUSB_ERROR_INVALID_PARA); + TU_VERIFY (report, TUSB_ERROR_INVALID_PARA); TU_ASSSERT (!hcd_pipe_is_busy(p_hid->pipe_hdl), TUSB_ERROR_INTERFACE_IS_BUSY); TU_ASSERT_ERR( hcd_pipe_xfer(p_hid->pipe_hdl, report, p_hid->report_size, true) ) ; diff --git a/src/class/msc/msc.h b/src/class/msc/msc.h index ab8f066b3..ca5615055 100644 --- a/src/class/msc/msc.h +++ b/src/class/msc/msc.h @@ -109,7 +109,7 @@ typedef struct ATTR_PACKED uint8_t command[16] ; ///< The command block to be executed by the device. The device shall interpret the first cmd_len bytes in this field as a command block }msc_cbw_t; -VERIFY_STATIC(sizeof(msc_cbw_t) == 31, "size is not correct"); +TU_VERIFY_STATIC(sizeof(msc_cbw_t) == 31, "size is not correct"); /// Command Status Wrapper typedef struct ATTR_PACKED @@ -120,7 +120,7 @@ typedef struct ATTR_PACKED uint8_t status ; ///< indicates the success or failure of the command. Values from \ref msc_csw_status_t }msc_csw_t; -VERIFY_STATIC(sizeof(msc_csw_t) == 13, "size is not correct"); +TU_VERIFY_STATIC(sizeof(msc_csw_t) == 13, "size is not correct"); //--------------------------------------------------------------------+ // SCSI Constant @@ -173,7 +173,7 @@ typedef struct ATTR_PACKED uint8_t control ; } scsi_test_unit_ready_t; -VERIFY_STATIC(sizeof(scsi_test_unit_ready_t) == 6, "size is not correct"); +TU_VERIFY_STATIC(sizeof(scsi_test_unit_ready_t) == 6, "size is not correct"); /// SCSI Inquiry Command typedef struct ATTR_PACKED @@ -186,7 +186,7 @@ typedef struct ATTR_PACKED uint8_t control ; } scsi_inquiry_t, scsi_request_sense_t; -VERIFY_STATIC(sizeof(scsi_inquiry_t) == 6, "size is not correct"); +TU_VERIFY_STATIC(sizeof(scsi_inquiry_t) == 6, "size is not correct"); /// SCSI Inquiry Response Data typedef struct ATTR_PACKED @@ -232,7 +232,7 @@ typedef struct ATTR_PACKED uint8_t product_rev[4]; ///< 4 bytes of ASCII data defined by the vendor. } scsi_inquiry_resp_t; -VERIFY_STATIC(sizeof(scsi_inquiry_resp_t) == 36, "size is not correct"); +TU_VERIFY_STATIC(sizeof(scsi_inquiry_resp_t) == 36, "size is not correct"); typedef struct ATTR_PACKED @@ -259,7 +259,7 @@ typedef struct ATTR_PACKED } scsi_sense_fixed_resp_t; -VERIFY_STATIC(sizeof(scsi_sense_fixed_resp_t) == 18, "size is not correct"); +TU_VERIFY_STATIC(sizeof(scsi_sense_fixed_resp_t) == 18, "size is not correct"); typedef struct ATTR_PACKED { @@ -277,7 +277,7 @@ typedef struct ATTR_PACKED uint8_t control; } scsi_mode_sense6_t; -VERIFY_STATIC( sizeof(scsi_mode_sense6_t) == 6, "size is not correct"); +TU_VERIFY_STATIC( sizeof(scsi_mode_sense6_t) == 6, "size is not correct"); typedef struct ATTR_PACKED { @@ -287,7 +287,7 @@ typedef struct ATTR_PACKED uint8_t block_descriptor_len; } scsi_mode_sense6_resp_t; -VERIFY_STATIC( sizeof(scsi_mode_sense6_resp_t) == 4, "size is not correct"); +TU_VERIFY_STATIC( sizeof(scsi_mode_sense6_resp_t) == 4, "size is not correct"); typedef struct ATTR_PACKED { @@ -297,7 +297,7 @@ typedef struct ATTR_PACKED uint8_t control; } scsi_prevent_allow_medium_removal_t; -VERIFY_STATIC( sizeof(scsi_prevent_allow_medium_removal_t) == 6, "size is not correct"); +TU_VERIFY_STATIC( sizeof(scsi_prevent_allow_medium_removal_t) == 6, "size is not correct"); typedef struct ATTR_PACKED { @@ -320,7 +320,7 @@ typedef struct ATTR_PACKED uint8_t control; } scsi_start_stop_unit_t; -VERIFY_STATIC( sizeof(scsi_start_stop_unit_t) == 6, "size is not correct"); +TU_VERIFY_STATIC( sizeof(scsi_start_stop_unit_t) == 6, "size is not correct"); //--------------------------------------------------------------------+ // SCSI MMC @@ -334,7 +334,7 @@ typedef struct ATTR_PACKED uint8_t control; } scsi_read_format_capacity_t; -VERIFY_STATIC( sizeof(scsi_read_format_capacity_t) == 10, "size is not correct"); +TU_VERIFY_STATIC( sizeof(scsi_read_format_capacity_t) == 10, "size is not correct"); typedef struct ATTR_PACKED{ uint8_t reserved[3]; @@ -348,7 +348,7 @@ typedef struct ATTR_PACKED{ } scsi_read_format_capacity_data_t; -VERIFY_STATIC( sizeof(scsi_read_format_capacity_data_t) == 12, "size is not correct"); +TU_VERIFY_STATIC( sizeof(scsi_read_format_capacity_data_t) == 12, "size is not correct"); //--------------------------------------------------------------------+ // SCSI Block Command (SBC-3) @@ -366,7 +366,7 @@ typedef struct ATTR_PACKED uint8_t control ; } scsi_read_capacity10_t; -VERIFY_STATIC(sizeof(scsi_read_capacity10_t) == 10, "size is not correct"); +TU_VERIFY_STATIC(sizeof(scsi_read_capacity10_t) == 10, "size is not correct"); /// SCSI Read Capacity 10 Response Data typedef struct { @@ -374,7 +374,7 @@ typedef struct { uint32_t block_size ; ///< Block size in bytes } scsi_read_capacity10_resp_t; -VERIFY_STATIC(sizeof(scsi_read_capacity10_resp_t) == 8, "size is not correct"); +TU_VERIFY_STATIC(sizeof(scsi_read_capacity10_resp_t) == 8, "size is not correct"); /// SCSI Read 10 Command typedef struct ATTR_PACKED @@ -387,8 +387,8 @@ typedef struct ATTR_PACKED uint8_t control ; } scsi_read10_t, scsi_write10_t; -VERIFY_STATIC(sizeof(scsi_read10_t) == 10, "size is not correct"); -VERIFY_STATIC(sizeof(scsi_write10_t) == 10, "size is not correct"); +TU_VERIFY_STATIC(sizeof(scsi_read10_t) == 10, "size is not correct"); +TU_VERIFY_STATIC(sizeof(scsi_write10_t) == 10, "size is not correct"); #ifdef __cplusplus } diff --git a/src/class/msc/msc_device.c b/src/class/msc/msc_device.c index 27762805c..a11212c4b 100644 --- a/src/class/msc/msc_device.c +++ b/src/class/msc/msc_device.c @@ -152,7 +152,7 @@ void mscd_reset(uint8_t rhport) tusb_error_t mscd_open(uint8_t rhport, tusb_desc_interface_t const * p_desc_itf, uint16_t *p_len) { // only support SCSI's BOT protocol - VERIFY( ( MSC_SUBCLASS_SCSI == p_desc_itf->bInterfaceSubClass && + TU_VERIFY( ( MSC_SUBCLASS_SCSI == p_desc_itf->bInterfaceSubClass && MSC_PROTOCOL_BOT == p_desc_itf->bInterfaceProtocol ), TUSB_ERROR_MSC_UNSUPPORTED_PROTOCOL ); mscd_interface_t * p_msc = &_mscd_itf; diff --git a/src/class/msc/msc_device.h b/src/class/msc/msc_device.h index 6080b10df..8403dfed9 100644 --- a/src/class/msc/msc_device.h +++ b/src/class/msc/msc_device.h @@ -47,7 +47,7 @@ //--------------------------------------------------------------------+ // Class Driver Configuration //--------------------------------------------------------------------+ -VERIFY_STATIC(CFG_TUD_MSC_BUFSIZE < UINT16_MAX, "Size is not correct"); +TU_VERIFY_STATIC(CFG_TUD_MSC_BUFSIZE < UINT16_MAX, "Size is not correct"); #ifndef CFG_TUD_MSC_MAXLUN #define CFG_TUD_MSC_MAXLUN 1 diff --git a/src/common/tusb_compiler.h b/src/common/tusb_compiler.h index 35a4cc928..09cc59633 100644 --- a/src/common/tusb_compiler.h +++ b/src/common/tusb_compiler.h @@ -56,12 +56,12 @@ #endif //--------------------------------------------------------------------+ -// Compile-time Assert (use VERIFY_STATIC to avoid name conflict) +// Compile-time Assert (use TU_VERIFY_STATIC to avoid name conflict) //--------------------------------------------------------------------+ #if defined(__ICCARM__) || (__STDC_VERSION__ >= 201112L ) - #define VERIFY_STATIC static_assert + #define TU_VERIFY_STATIC static_assert #else - #define VERIFY_STATIC(const_expr, _mess) enum { XSTRING_CONCAT_(_verify_static_, _TU_COUNTER_) = 1/(!!(const_expr)) } + #define TU_VERIFY_STATIC(const_expr, _mess) enum { XSTRING_CONCAT_(_verify_static_, _TU_COUNTER_) = 1/(!!(const_expr)) } #endif // allow debugger to watch any module-wide variables anywhere diff --git a/src/common/tusb_types.h b/src/common/tusb_types.h index 1e8a5ef27..c3ed4f2bd 100644 --- a/src/common/tusb_types.h +++ b/src/common/tusb_types.h @@ -369,7 +369,7 @@ typedef struct ATTR_PACKED{ uint16_t wLength; } tusb_control_request_t; -VERIFY_STATIC( sizeof(tusb_control_request_t) == 8, "mostly compiler option issue"); +TU_VERIFY_STATIC( sizeof(tusb_control_request_t) == 8, "mostly compiler option issue"); // TODO move to somewhere suitable static inline uint8_t bm_request_type(uint8_t direction, uint8_t type, uint8_t recipient) diff --git a/src/common/tusb_verify.h b/src/common/tusb_verify.h index adcdfc97f..41c2b5be1 100644 --- a/src/common/tusb_verify.h +++ b/src/common/tusb_verify.h @@ -50,8 +50,8 @@ * * e.g * - * - VERIFY( cond ) will return false if cond is false - * - VERIFY( cond, err) will return err instead if cond is false + * - TU_VERIFY( cond ) will return false if cond is false + * - TU_VERIFY( cond, err) will return err instead if cond is false *------------------------------------------------------------------*/ #ifdef __cplusplus @@ -60,7 +60,7 @@ //--------------------------------------------------------------------+ -// VERIFY Helper +// TU_VERIFY Helper //--------------------------------------------------------------------+ #if CFG_TUSB_DEBUG >= 1 #include @@ -88,21 +88,21 @@ /* Macro Generator *------------------------------------------------------------------*/ -// Helper to implement optional parameter for VERIFY Macro family +// Helper to implement optional parameter for TU_VERIFY Macro family #define GET_3RD_ARG(arg1, arg2, arg3, ...) arg3 #define GET_4TH_ARG(arg1, arg2, arg3, arg4, ...) arg4 -/*------------- Generator for VERIFY and VERIFY_HDLR -------------*/ -#define VERIFY_DEFINE(_cond, _handler, _ret) do { if ( !(_cond) ) { _handler; return _ret; } } while(0) +/*------------- Generator for TU_VERIFY and TU_VERIFY_HDLR -------------*/ +#define TU_VERIFY_DEFINE(_cond, _handler, _ret) do { if ( !(_cond) ) { _handler; return _ret; } } while(0) -/*------------- Generator for VERIFY_ERR and VERIFY_ERR_HDLR -------------*/ -#define VERIFY_ERR_DEF2(_error, _handler) \ +/*------------- Generator for TU_VERIFY_ERR and TU_VERIFY_ERR_HDLR -------------*/ +#define TU_VERIFY_ERR_DEF2(_error, _handler) \ do { \ uint32_t _err = (uint32_t)(_error); \ if ( 0 != _err ) { _MESS_ERR(_err); _handler; return _err; }\ } while(0) -#define VERIFY_ERR_DEF3(_error, _handler, _ret) \ +#define TU_VERIFY_ERR_DEF3(_error, _handler, _ret) \ do { \ uint32_t _err = (uint32_t)(_error); \ if ( 0 != _err ) { _MESS_ERR(_err); _handler; return _ret; }\ @@ -112,66 +112,66 @@ /*------------------------------------------------------------------*/ -/* VERIFY - * - VERIFY_1ARGS : return false if failed - * - VERIFY_2ARGS : return provided value if failed +/* TU_VERIFY + * - TU_VERIFY_1ARGS : return false if failed + * - TU_VERIFY_2ARGS : return provided value if failed *------------------------------------------------------------------*/ -#define VERIFY_1ARGS(_cond) VERIFY_DEFINE(_cond, , false) -#define VERIFY_2ARGS(_cond, _ret) VERIFY_DEFINE(_cond, , _ret) +#define TU_VERIFY_1ARGS(_cond) TU_VERIFY_DEFINE(_cond, , false) +#define TU_VERIFY_2ARGS(_cond, _ret) TU_VERIFY_DEFINE(_cond, , _ret) -#define VERIFY(...) GET_3RD_ARG(__VA_ARGS__, VERIFY_2ARGS, VERIFY_1ARGS)(__VA_ARGS__) +#define TU_VERIFY(...) GET_3RD_ARG(__VA_ARGS__, TU_VERIFY_2ARGS, TU_VERIFY_1ARGS)(__VA_ARGS__) /*------------------------------------------------------------------*/ -/* VERIFY WITH HANDLER - * - VERIFY_HDLR_2ARGS : execute handler, return false if failed - * - VERIFY_HDLR_3ARGS : execute handler, return provided error if failed +/* TU_VERIFY WITH HANDLER + * - TU_VERIFY_HDLR_2ARGS : execute handler, return false if failed + * - TU_VERIFY_HDLR_3ARGS : execute handler, return provided error if failed *------------------------------------------------------------------*/ -#define VERIFY_HDLR_2ARGS(_cond, _handler) VERIFY_DEFINE(_cond, _handler, false) -#define VERIFY_HDLR_3ARGS(_cond, _handler, _ret) VERIFY_DEFINE(_cond, _handler, _ret) +#define TU_VERIFY_HDLR_2ARGS(_cond, _handler) TU_VERIFY_DEFINE(_cond, _handler, false) +#define TU_VERIFY_HDLR_3ARGS(_cond, _handler, _ret) TU_VERIFY_DEFINE(_cond, _handler, _ret) -#define VERIFY_HDLR(...) GET_4TH_ARG(__VA_ARGS__, VERIFY_HDLR_3ARGS, VERIFY_HDLR_2ARGS)(__VA_ARGS__) +#define TU_VERIFY_HDLR(...) GET_4TH_ARG(__VA_ARGS__, TU_VERIFY_HDLR_3ARGS, TU_VERIFY_HDLR_2ARGS)(__VA_ARGS__) /*------------------------------------------------------------------*/ -/* VERIFY STATUS - * - VERIFY_ERR_1ARGS : return status of condition if failed - * - VERIFY_ERR_2ARGS : return provided status code if failed +/* TU_VERIFY STATUS + * - TU_VERIFY_ERR_1ARGS : return status of condition if failed + * - TU_VERIFY_ERR_2ARGS : return provided status code if failed *------------------------------------------------------------------*/ -#define VERIFY_ERR_1ARGS(_error) VERIFY_ERR_DEF2(_error, ) -#define VERIFY_ERR_2ARGS(_error, _ret) VERIFY_ERR_DEF3(_error, ,_ret) +#define TU_VERIFY_ERR_1ARGS(_error) TU_VERIFY_ERR_DEF2(_error, ) +#define TU_VERIFY_ERR_2ARGS(_error, _ret) TU_VERIFY_ERR_DEF3(_error, ,_ret) -#define VERIFY_ERR(...) GET_3RD_ARG(__VA_ARGS__, VERIFY_ERR_2ARGS, VERIFY_ERR_1ARGS)(__VA_ARGS__) +#define TU_VERIFY_ERR(...) GET_3RD_ARG(__VA_ARGS__, TU_VERIFY_ERR_2ARGS, TU_VERIFY_ERR_1ARGS)(__VA_ARGS__) /*------------------------------------------------------------------*/ -/* VERIFY STATUS WITH HANDLER - * - VERIFY_ERR_HDLR_2ARGS : execute handler, return status if failed - * - VERIFY_ERR_HDLR_3ARGS : execute handler, return provided error if failed +/* TU_VERIFY STATUS WITH HANDLER + * - TU_VERIFY_ERR_HDLR_2ARGS : execute handler, return status if failed + * - TU_VERIFY_ERR_HDLR_3ARGS : execute handler, return provided error if failed *------------------------------------------------------------------*/ -#define VERIFY_ERR_HDLR_2ARGS(_error, _handler) VERIFY_ERR_DEF2(_error, _handler) -#define VERIFY_ERR_HDLR_3ARGS(_error, _handler, _ret) VERIFY_ERR_DEF3(_error, _handler, _ret) +#define TU_VERIFY_ERR_HDLR_2ARGS(_error, _handler) TU_VERIFY_ERR_DEF2(_error, _handler) +#define TU_VERIFY_ERR_HDLR_3ARGS(_error, _handler, _ret) TU_VERIFY_ERR_DEF3(_error, _handler, _ret) -#define VERIFY_ERR_HDLR(...) GET_4TH_ARG(__VA_ARGS__, VERIFY_ERR_HDLR_3ARGS, VERIFY_ERR_HDLR_2ARGS)(__VA_ARGS__) +#define TU_VERIFY_ERR_HDLR(...) GET_4TH_ARG(__VA_ARGS__, TU_VERIFY_ERR_HDLR_3ARGS, TU_VERIFY_ERR_HDLR_2ARGS)(__VA_ARGS__) /*------------------------------------------------------------------*/ /* ASSERT - * basically VERIFY with verify_breakpoint() as handler + * basically TU_VERIFY with verify_breakpoint() as handler * - 1 arg : return false if failed * - 2 arg : return error if failed *------------------------------------------------------------------*/ -#define ASSERT_1ARGS(_cond) VERIFY_DEFINE(_cond, _MESS_FAILED(); verify_breakpoint(), false) -#define ASSERT_2ARGS(_cond, _ret) VERIFY_DEFINE(_cond, _MESS_FAILED(); verify_breakpoint(), _ret) +#define ASSERT_1ARGS(_cond) TU_VERIFY_DEFINE(_cond, _MESS_FAILED(); verify_breakpoint(), false) +#define ASSERT_2ARGS(_cond, _ret) TU_VERIFY_DEFINE(_cond, _MESS_FAILED(); verify_breakpoint(), _ret) #define TU_ASSERT(...) GET_3RD_ARG(__VA_ARGS__, ASSERT_2ARGS, ASSERT_1ARGS)(__VA_ARGS__) /*------------------------------------------------------------------*/ /* ASSERT Error - * basically VERIFY Error with verify_breakpoint() as handler + * basically TU_VERIFY Error with verify_breakpoint() as handler *------------------------------------------------------------------*/ -#define ASERT_ERR_1ARGS(_error) VERIFY_ERR_DEF2(_error, verify_breakpoint()) -#define ASERT_ERR_2ARGS(_error, _ret) VERIFY_ERR_DEF3(_error, verify_breakpoint(), _ret) +#define ASERT_ERR_1ARGS(_error) TU_VERIFY_ERR_DEF2(_error, verify_breakpoint()) +#define ASERT_ERR_2ARGS(_error, _ret) TU_VERIFY_ERR_DEF3(_error, verify_breakpoint(), _ret) #define TU_ASSERT_ERR(...) GET_3RD_ARG(__VA_ARGS__, ASERT_ERR_2ARGS, ASERT_ERR_1ARGS)(__VA_ARGS__) diff --git a/src/device/usbd.c b/src/device/usbd.c index 219562fa6..79ad8ffa2 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -189,7 +189,7 @@ typedef struct ATTR_ALIGNED(4) }; } usbd_task_event_t; -VERIFY_STATIC(sizeof(usbd_task_event_t) <= 12, "size is not correct"); +TU_VERIFY_STATIC(sizeof(usbd_task_event_t) <= 12, "size is not correct"); OSAL_TASK_DEF(_usbd_task_def, "usbd", usbd_task, CFG_TUD_TASK_PRIO, CFG_TUD_TASK_STACK_SZ); @@ -234,10 +234,10 @@ tusb_error_t usbd_init (void) //------------- Task init -------------// _usbd_q = osal_queue_create(&_usbd_qdef); - VERIFY(_usbd_q, TUSB_ERROR_OSAL_QUEUE_FAILED); + TU_VERIFY(_usbd_q, TUSB_ERROR_OSAL_QUEUE_FAILED); _usbd_ctrl_sem = osal_semaphore_create(&_usbd_sem_def); - VERIFY(_usbd_q, TUSB_ERROR_OSAL_SEMAPHORE_FAILED); + TU_VERIFY(_usbd_q, TUSB_ERROR_OSAL_SEMAPHORE_FAILED); osal_task_create(&_usbd_task_def); @@ -507,7 +507,7 @@ static uint16_t get_descriptor(uint8_t rhport, tusb_control_request_t const * co if ( desc_index < tud_desc_set.string_count ) { desc_data = tud_desc_set.string_arr[desc_index]; - VERIFY( desc_data != NULL, 0 ); + TU_VERIFY( desc_data != NULL, 0 ); len = desc_data[0]; // first byte of descriptor is its size }else diff --git a/src/host/ehci/ehci.c b/src/host/ehci/ehci.c index 09f2f573a..32fcc8140 100644 --- a/src/host/ehci/ehci.c +++ b/src/host/ehci/ehci.c @@ -64,7 +64,7 @@ CFG_TUSB_ATTR_USBRAM STATIC_VAR ehci_data_t ehci_data; CFG_TUSB_ATTR_USBRAM ATTR_ALIGNED(4096) STATIC_VAR ehci_link_t period_frame_list0[EHCI_FRAMELIST_SIZE]; #ifndef __ICCARM__ // IAR cannot able to determine the alignment with datalignment pragma - VERIFY_STATIC( ALIGN_OF(period_frame_list0) == 4096, "Period Framelist must be 4k alginment"); // validation + TU_VERIFY_STATIC( ALIGN_OF(period_frame_list0) == 4096, "Period Framelist must be 4k alginment"); // validation #endif #endif @@ -72,7 +72,7 @@ CFG_TUSB_ATTR_USBRAM STATIC_VAR ehci_data_t ehci_data; CFG_TUSB_ATTR_USBRAM ATTR_ALIGNED(4096) STATIC_VAR ehci_link_t period_frame_list1[EHCI_FRAMELIST_SIZE]; #ifndef __ICCARM__ // IAR cannot able to determine the alignment with datalignment pragma - VERIFY_STATIC( ALIGN_OF(period_frame_list1) == 4096, "Period Framelist must be 4k alginment"); // validation + TU_VERIFY_STATIC( ALIGN_OF(period_frame_list1) == 4096, "Period Framelist must be 4k alginment"); // validation #endif #endif #endif diff --git a/src/host/ehci/ehci.h b/src/host/ehci/ehci.h index 250023ee5..f5180402b 100644 --- a/src/host/ehci/ehci.h +++ b/src/host/ehci/ehci.h @@ -81,7 +81,7 @@ enum { }; //------------- Validation -------------// -VERIFY_STATIC(EHCI_CFG_FRAMELIST_SIZE_BITS <= 7, "incorrect value"); +TU_VERIFY_STATIC(EHCI_CFG_FRAMELIST_SIZE_BITS <= 7, "incorrect value"); //--------------------------------------------------------------------+ // EHCI Data Structure @@ -150,7 +150,7 @@ typedef struct { uint32_t buffer[5]; } ehci_qtd_t; // XXX qtd is used to declare overlay in ehci_qhd_t -> cannot be declared with ATTR_ALIGNED(32) -VERIFY_STATIC( sizeof(ehci_qtd_t) == 32, "size is not correct" ); +TU_VERIFY_STATIC( sizeof(ehci_qtd_t) == 32, "size is not correct" ); /// Queue Head (section 3.6) typedef struct ATTR_ALIGNED(32) { @@ -202,7 +202,7 @@ typedef struct ATTR_ALIGNED(32) { ehci_qtd_t * volatile p_qtd_list_tail; // tail of the scheduled TD list } ehci_qhd_t; -VERIFY_STATIC( sizeof(ehci_qhd_t) == 64, "size is not correct" ); +TU_VERIFY_STATIC( sizeof(ehci_qhd_t) == 64, "size is not correct" ); /// Highspeed Isochronous Transfer Descriptor (section 3.3) typedef struct ATTR_ALIGNED(32) { @@ -234,7 +234,7 @@ typedef struct ATTR_ALIGNED(32) { // uint32_t reserved[6]; } ehci_itd_t; -VERIFY_STATIC( sizeof(ehci_itd_t) == 64, "size is not correct" ); +TU_VERIFY_STATIC( sizeof(ehci_itd_t) == 64, "size is not correct" ); /// Split (Full-Speed) Isochronous Transfer Descriptor typedef struct ATTR_ALIGNED(32) { @@ -298,7 +298,7 @@ typedef struct ATTR_ALIGNED(32) { uint8_t reserved2[2]; } ehci_sitd_t; -VERIFY_STATIC( sizeof(ehci_sitd_t) == 32, "size is not correct" ); +TU_VERIFY_STATIC( sizeof(ehci_sitd_t) == 32, "size is not correct" ); //--------------------------------------------------------------------+ // EHCI Operational Register diff --git a/src/host/hub.h b/src/host/hub.h index b8499275c..67c02f2e3 100644 --- a/src/host/hub.h +++ b/src/host/hub.h @@ -104,7 +104,7 @@ typedef struct ATTR_PACKED{ uint8_t PortPwrCtrlMask; // just for compatibility, should be 0xff } descriptor_hub_desc_t; -VERIFY_STATIC( sizeof(descriptor_hub_desc_t) == 9, "size is not correct"); +TU_VERIFY_STATIC( sizeof(descriptor_hub_desc_t) == 9, "size is not correct"); enum { HUB_REQUEST_GET_STATUS = 0 , @@ -157,7 +157,7 @@ typedef struct { } status, status_change; } hub_status_response_t; -VERIFY_STATIC( sizeof(hub_status_response_t) == 4, "size is not correct"); +TU_VERIFY_STATIC( sizeof(hub_status_response_t) == 4, "size is not correct"); // data in response of HUB_REQUEST_GET_STATUS, wIndex = Port num typedef struct { @@ -182,7 +182,7 @@ typedef struct { } status_current, status_change; } hub_port_status_response_t; -VERIFY_STATIC( sizeof(hub_port_status_response_t) == 4, "size is not correct"); +TU_VERIFY_STATIC( sizeof(hub_port_status_response_t) == 4, "size is not correct"); tusb_error_t hub_port_reset_subtask(uint8_t hub_addr, uint8_t hub_port); tusb_error_t hub_port_clear_feature_subtask(uint8_t hub_addr, uint8_t hub_port, uint8_t feature); diff --git a/src/host/ohci/ohci.h b/src/host/ohci/ohci.h index f49d85261..c407b8ac1 100644 --- a/src/host/ohci/ohci.h +++ b/src/host/ohci/ohci.h @@ -79,7 +79,7 @@ typedef struct { uint8_t reserved[116+4]; // TODO try to make use of this area if possible, extra 4 byte to make the whole struct size = 256 }ohci_hcca_t; // ATTR_ALIGNED(256) -VERIFY_STATIC( sizeof(ohci_hcca_t) == 256, "size is not correct" ); +TU_VERIFY_STATIC( sizeof(ohci_hcca_t) == 256, "size is not correct" ); typedef struct { uint32_t reserved[2]; @@ -112,7 +112,7 @@ typedef struct ATTR_ALIGNED(16) { uint8_t* buffer_end; } ohci_gtd_t; -VERIFY_STATIC( sizeof(ohci_gtd_t) == 16, "size is not correct" ); +TU_VERIFY_STATIC( sizeof(ohci_gtd_t) == 16, "size is not correct" ); typedef struct ATTR_ALIGNED(16) { //------------- Word 0 -------------// @@ -153,7 +153,7 @@ typedef struct ATTR_ALIGNED(16) { uint32_t next_ed; // 4 lsb bits are free to use } ohci_ed_t; -VERIFY_STATIC( sizeof(ohci_ed_t) == 16, "size is not correct" ); +TU_VERIFY_STATIC( sizeof(ohci_ed_t) == 16, "size is not correct" ); typedef struct ATTR_ALIGNED(32) { /*---------- Word 1 ----------*/ @@ -178,7 +178,7 @@ typedef struct ATTR_ALIGNED(32) { volatile uint16_t offset_packetstatus[8]; } ochi_itd_t; -VERIFY_STATIC( sizeof(ochi_itd_t) == 32, "size is not correct" ); +TU_VERIFY_STATIC( sizeof(ochi_itd_t) == 32, "size is not correct" ); // structure with member alignment required from large to small typedef struct ATTR_ALIGNED(256) { @@ -298,7 +298,7 @@ typedef volatile struct }; }ohci_registers_t; -VERIFY_STATIC( sizeof(ohci_registers_t) == 0x5c, "size is not correct"); +TU_VERIFY_STATIC( sizeof(ohci_registers_t) == 0x5c, "size is not correct"); #ifdef __cplusplus } diff --git a/src/osal/osal.h b/src/osal/osal.h index 7a8e6ecbf..3e0d9d5f1 100644 --- a/src/osal/osal.h +++ b/src/osal/osal.h @@ -81,11 +81,11 @@ typedef void (*osal_task_func_t)( void * ); #define STASK_INVOKE(_subtask, _status) (_status) = _subtask //------------- Sub Task Assert -------------// - #define STASK_ASSERT_ERR(_err) VERIFY_ERR(_err) - #define STASK_ASSERT_ERR_HDLR(_err, _func) VERIFY_ERR_HDLR(_err, _func) + #define STASK_ASSERT_ERR(_err) TU_VERIFY_ERR(_err) + #define STASK_ASSERT_ERR_HDLR(_err, _func) TU_VERIFY_ERR_HDLR(_err, _func) - #define STASK_ASSERT(_cond) VERIFY(_cond, TUSB_ERROR_OSAL_TASK_FAILED) - #define STASK_ASSERT_HDLR(_cond, _func) VERIFY_HDLR(_cond, _func) + #define STASK_ASSERT(_cond) TU_VERIFY(_cond, TUSB_ERROR_OSAL_TASK_FAILED) + #define STASK_ASSERT_HDLR(_cond, _func) TU_VERIFY_HDLR(_cond, _func) #endif #ifdef __cplusplus diff --git a/src/osal/osal_none.h b/src/osal/osal_none.h index b8cd2893c..3531686b4 100644 --- a/src/osal/osal_none.h +++ b/src/osal/osal_none.h @@ -121,11 +121,11 @@ static inline osal_task_t osal_task_create(osal_task_def_t* taskdef) //------------- Sub Task Assert -------------// #define STASK_RETURN(error) do { TASK_RESTART; return error; } while(0) -#define STASK_ASSERT_ERR(_err) VERIFY_ERR_HDLR(_err, verify_breakpoint(); TASK_RESTART, TUSB_ERROR_FAILED) -#define STASK_ASSERT_ERR_HDLR(_err, _func) VERIFY_ERR_HDLR(_err, verify_breakpoint(); _func; TASK_RESTART, TUSB_ERROR_FAILED ) +#define STASK_ASSERT_ERR(_err) TU_VERIFY_ERR_HDLR(_err, verify_breakpoint(); TASK_RESTART, TUSB_ERROR_FAILED) +#define STASK_ASSERT_ERR_HDLR(_err, _func) TU_VERIFY_ERR_HDLR(_err, verify_breakpoint(); _func; TASK_RESTART, TUSB_ERROR_FAILED ) -#define STASK_ASSERT(_cond) VERIFY_HDLR(_cond, verify_breakpoint(); TASK_RESTART, TUSB_ERROR_FAILED) -#define STASK_ASSERT_HDLR(_cond, _func) VERIFY_HDLR(_cond, verify_breakpoint(); _func; TASK_RESTART, TUSB_ERROR_FAILED) +#define STASK_ASSERT(_cond) TU_VERIFY_HDLR(_cond, verify_breakpoint(); TASK_RESTART, TUSB_ERROR_FAILED) +#define STASK_ASSERT_HDLR(_cond, _func) TU_VERIFY_HDLR(_cond, verify_breakpoint(); _func; TASK_RESTART, TUSB_ERROR_FAILED) //--------------------------------------------------------------------+ // QUEUE API diff --git a/src/portable/nxp/lpc11xx_lpc13xx/dcd_lpc_11uxx_13uxx.c b/src/portable/nxp/lpc11xx_lpc13xx/dcd_lpc_11uxx_13uxx.c index 68eef47e1..0eaecf1b8 100644 --- a/src/portable/nxp/lpc11xx_lpc13xx/dcd_lpc_11uxx_13uxx.c +++ b/src/portable/nxp/lpc11xx_lpc13xx/dcd_lpc_11uxx_13uxx.c @@ -104,7 +104,7 @@ typedef struct ATTR_PACKED volatile uint16_t active : 1 ; ///< The buffer is enabled. HW can use the buffer to store received OUT data or to transmit data on the IN endpoint. Software can only set this bit to ‘1’. As long as this bit is set to one, software is not allowed to update any of the values in this 32-bit word. In case software wants to deactivate the buffer, it must write a one to the corresponding “skip” bit in the USB Endpoint skip register. Hardware can only write this bit to zero. It will do this when it receives a short packet or when the NBytes field transitions to zero or when software has written a one to the “skip” bit. }dcd_11u_13u_qhd_t; -VERIFY_STATIC( sizeof(dcd_11u_13u_qhd_t) == 4, "size is not correct" ); +TU_VERIFY_STATIC( sizeof(dcd_11u_13u_qhd_t) == 4, "size is not correct" ); // NOTE data will be transferred as soon as dcd get request by dcd_pipe(_queue)_xfer using double buffering. // If there is another dcd_edpt_xfer request, the new request will be saved and executed when the first is done. diff --git a/src/portable/nxp/lpc17xx/dcd_lpc175x_6x.c b/src/portable/nxp/lpc17xx/dcd_lpc175x_6x.c index 948572129..a87e7d899 100644 --- a/src/portable/nxp/lpc17xx/dcd_lpc175x_6x.c +++ b/src/portable/nxp/lpc17xx/dcd_lpc175x_6x.c @@ -384,7 +384,7 @@ bool dcd_control_xfer(uint8_t rhport, tusb_dir_t dir, uint8_t * p_buffer, uint16 { (void) rhport; - VERIFY( !(length != 0 && p_buffer == NULL) ); + TU_VERIFY( !(length != 0 && p_buffer == NULL) ); // determine Endpoint where Data & Status phase occurred (IN or OUT) uint8_t const ep_data = (dir == TUSB_DIR_IN) ? 1 : 0; @@ -399,13 +399,13 @@ bool dcd_control_xfer(uint8_t rhport, tusb_dir_t dir, uint8_t * p_buffer, uint16 dcd_data.control_dma.remaining_bytes = length; // lpc17xx already received the first DATA OUT packet by now - VERIFY_ERR ( pipe_control_xfer(ep_data, p_buffer, length), false ); + TU_VERIFY_ERR ( pipe_control_xfer(ep_data, p_buffer, length), false ); } //------------- Status Phase (opposite direct to Data) -------------// if (dir == TUSB_DIR_OUT) { // only write for CONTROL OUT, CONTROL IN data will be retrieved in hal_dcd_isr // TODO ???? - VERIFY_ERR ( pipe_control_write(NULL, 0), false ); + TU_VERIFY_ERR ( pipe_control_write(NULL, 0), false ); } return true; diff --git a/src/portable/nxp/lpc17xx/dcd_lpc175x_6x.h b/src/portable/nxp/lpc17xx/dcd_lpc175x_6x.h index 1df1fcd30..4746b4acf 100644 --- a/src/portable/nxp/lpc17xx/dcd_lpc175x_6x.h +++ b/src/portable/nxp/lpc17xx/dcd_lpc175x_6x.h @@ -80,7 +80,7 @@ typedef struct ATTR_ALIGNED(4) // uint32_t iso_packet_size_addr; // iso only, can be omitted for non-iso }dcd_dma_descriptor_t; -VERIFY_STATIC( sizeof(dcd_dma_descriptor_t) == 16, "size is not correct"); // TODO not support ISO for now +TU_VERIFY_STATIC( sizeof(dcd_dma_descriptor_t) == 16, "size is not correct"); // TODO not support ISO for now //--------------------------------------------------------------------+ diff --git a/src/portable/nxp/lpc43xx_lpc18xx/dcd_lpc43xx.c b/src/portable/nxp/lpc43xx_lpc18xx/dcd_lpc43xx.c index 0b48ad1e6..61f829713 100644 --- a/src/portable/nxp/lpc43xx_lpc18xx/dcd_lpc43xx.c +++ b/src/portable/nxp/lpc43xx_lpc18xx/dcd_lpc43xx.c @@ -244,7 +244,7 @@ bool dcd_control_xfer(uint8_t rhport, tusb_dir_t dir, uint8_t * p_buffer, uint16 // wait until ENDPTSETUPSTAT before priming data/status in response TODO add time out while(lpc_usb->ENDPTSETUPSTAT & BIT_(0)) {} - VERIFY( !qhd->qtd_overlay.active ); + TU_VERIFY( !qhd->qtd_overlay.active ); dcd_qtd_t* qtd = &p_dcd->qtd[0]; qtd_init(qtd, p_buffer, length); @@ -295,7 +295,7 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc) { // TODO USB1 only has 4 non-control enpoint (USB0 has 5) // TODO not support ISO yet - VERIFY ( p_endpoint_desc->bmAttributes.xfer != TUSB_XFER_ISOCHRONOUS); + TU_VERIFY ( p_endpoint_desc->bmAttributes.xfer != TUSB_XFER_ISOCHRONOUS); tusb_dir_t dir = (p_endpoint_desc->bEndpointAddress & TUSB_DIR_IN_MASK) ? TUSB_DIR_IN : TUSB_DIR_OUT; @@ -313,7 +313,7 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc) volatile uint32_t * reg_control = get_reg_control_addr(rhport, ep_idx); // endpoint must not be already enabled - VERIFY( !( (*reg_control) & (ENDPTCTRL_MASK_ENABLE << (dir ? 16 : 0)) ) ); + TU_VERIFY( !( (*reg_control) & (ENDPTCTRL_MASK_ENABLE << (dir ? 16 : 0)) ) ); (*reg_control) |= ((p_endpoint_desc->bmAttributes.xfer << 2) | ENDPTCTRL_MASK_ENABLE | ENDPTCTRL_MASK_TOGGLE_RESET) << (dir ? 16 : 0); @@ -363,7 +363,7 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t { uint8_t ep_idx = edpt_addr2phy(ep_addr); - VERIFY ( pipe_add_xfer(rhport, ep_idx, buffer, total_bytes, true) ); + TU_VERIFY ( pipe_add_xfer(rhport, ep_idx, buffer, total_bytes, true) ); dcd_qhd_t* p_qhd = &dcd_data_ptr[rhport]->qhd[ ep_idx ]; dcd_qtd_t* p_qtd = &dcd_data_ptr[rhport]->qtd[ p_qhd->list_qtd_idx[0] ]; diff --git a/src/portable/nxp/lpc43xx_lpc18xx/dcd_lpc43xx.h b/src/portable/nxp/lpc43xx_lpc18xx/dcd_lpc43xx.h index 92e24c1fb..1476c0d30 100644 --- a/src/portable/nxp/lpc43xx_lpc18xx/dcd_lpc43xx.h +++ b/src/portable/nxp/lpc43xx_lpc18xx/dcd_lpc43xx.h @@ -122,7 +122,7 @@ typedef struct uint8_t reserved; } dcd_qtd_t; -VERIFY_STATIC( sizeof(dcd_qtd_t) == 32, "size is not correct"); +TU_VERIFY_STATIC( sizeof(dcd_qtd_t) == 32, "size is not correct"); typedef struct { @@ -153,7 +153,7 @@ typedef struct uint8_t reserved[16-DCD_QTD_PER_QHD_MAX]; } dcd_qhd_t; -VERIFY_STATIC( sizeof(dcd_qhd_t) == 64, "size is not correct"); +TU_VERIFY_STATIC( sizeof(dcd_qhd_t) == 64, "size is not correct"); #ifdef __cplusplus diff --git a/src/portable/nxp/lpc43xx_lpc18xx/hal_lpc43xx.c b/src/portable/nxp/lpc43xx_lpc18xx/hal_lpc43xx.c index 18745d03e..213b8dd99 100644 --- a/src/portable/nxp/lpc43xx_lpc18xx/hal_lpc43xx.c +++ b/src/portable/nxp/lpc43xx_lpc18xx/hal_lpc43xx.c @@ -86,7 +86,7 @@ bool tusb_hal_init(void) //------------- USB0 -------------// #if CFG_TUSB_RHPORT0_MODE CGU_EnableEntity(CGU_CLKSRC_PLL0, DISABLE); /* Disable PLL first */ - VERIFY( CGU_ERROR_SUCCESS == CGU_SetPLL0()); /* the usb core require output clock = 480MHz */ + TU_VERIFY( CGU_ERROR_SUCCESS == CGU_SetPLL0()); /* 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 */ diff --git a/src/tusb.c b/src/tusb.c index 0ef1301a4..b064d03f9 100644 --- a/src/tusb.c +++ b/src/tusb.c @@ -49,7 +49,7 @@ tusb_error_t tusb_init(void) // skip if already initialized if (_initialized) return TUSB_ERROR_NONE; - VERIFY( tusb_hal_init(), TUSB_ERROR_FAILED ) ; // hardware init + TU_VERIFY( tusb_hal_init(), TUSB_ERROR_FAILED ) ; // hardware init #if MODE_HOST_SUPPORTED TU_ASSERT_ERR( usbh_init() ); // host stack init -- cgit v1.3.1 From c5d2f661e76adbe2f047c2f3a405ed60262ecb9b Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 23 Aug 2018 20:09:28 +0700 Subject: rename common func to avoid conflict --- src/class/cdc/cdc_device.c | 4 +- src/class/cdc/cdc_host.c | 2 +- src/class/hid/hid_device.c | 14 ++--- src/class/msc/msc_device.c | 4 +- src/common/tusb_common.h | 64 +++++++--------------- src/common/tusb_fifo.c | 6 +- src/device/usbd.c | 16 +++--- src/host/ehci/ehci.c | 28 +++++----- src/host/ohci/ohci.c | 24 ++++---- src/host/usbh.c | 2 +- src/portable/nordic/nrf5x/dcd_nrf5x.c | 4 +- .../nxp/lpc11xx_lpc13xx/dcd_lpc_11uxx_13uxx.c | 2 +- src/portable/nxp/lpc17xx/dcd_lpc175x_6x.c | 4 +- src/portable/nxp/lpc43xx_lpc18xx/dcd_lpc43xx.c | 2 +- tests/lpc18xx_43xx/test/host/ehci/test_ehci_init.c | 4 +- .../test/host/ehci/test_pipe_bulk_open.c | 8 +-- .../test/host/ehci/test_pipe_bulk_xfer.c | 4 +- .../test/host/ehci/test_pipe_control_open.c | 6 +- .../test/host/ehci/test_pipe_interrupt_open.c | 24 ++++---- .../test/host/ehci/test_pipe_interrupt_xfer.c | 4 +- tests/support/ehci_controller_fake.c | 12 ++-- tests/support/type_helper.h | 6 +- 22 files changed, 109 insertions(+), 135 deletions(-) (limited to 'src/host') diff --git a/src/class/cdc/cdc_device.c b/src/class/cdc/cdc_device.c index 075a7f8db..2a598f051 100644 --- a/src/class/cdc/cdc_device.c +++ b/src/class/cdc/cdc_device.c @@ -208,7 +208,7 @@ tusb_error_t cdcd_open(uint8_t rhport, tusb_desc_interface_t const * p_interface { if ( CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL != p_interface_desc->bInterfaceSubClass) return TUSB_ERROR_CDC_UNSUPPORTED_SUBCLASS; - if ( !(is_in_range(CDC_COMM_PROTOCOL_ATCOMMAND, p_interface_desc->bInterfaceProtocol, CDC_COMM_PROTOCOL_ATCOMMAND_CDMA) || + if ( !(tu_within(CDC_COMM_PROTOCOL_ATCOMMAND, p_interface_desc->bInterfaceProtocol, CDC_COMM_PROTOCOL_ATCOMMAND_CDMA) || 0xff == p_interface_desc->bInterfaceProtocol) ) { return TUSB_ERROR_CDC_UNSUPPORTED_PROTOCOL; @@ -282,7 +282,7 @@ tusb_error_t cdcd_control_request_st(uint8_t rhport, tusb_control_request_t cons if ( (CDC_REQUEST_GET_LINE_CODING == p_request->bRequest) || (CDC_REQUEST_SET_LINE_CODING == p_request->bRequest) ) { - uint16_t len = min16_of(sizeof(cdc_line_coding_t), p_request->wLength); + uint16_t len = tu_min16(sizeof(cdc_line_coding_t), p_request->wLength); usbd_control_xfer_st(rhport, p_request->bmRequestType_bit.direction, &p_cdc->line_coding, len); // Invoke callback diff --git a/src/class/cdc/cdc_host.c b/src/class/cdc/cdc_host.c index 6950759d1..ca448ba5e 100644 --- a/src/class/cdc/cdc_host.c +++ b/src/class/cdc/cdc_host.c @@ -149,7 +149,7 @@ tusb_error_t cdch_open_subtask(uint8_t dev_addr, tusb_desc_interface_t const *p_ if ( CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL != p_interface_desc->bInterfaceSubClass) return TUSB_ERROR_CDC_UNSUPPORTED_SUBCLASS; - if ( !(is_in_range(CDC_COMM_PROTOCOL_ATCOMMAND, p_interface_desc->bInterfaceProtocol, CDC_COMM_PROTOCOL_ATCOMMAND_CDMA) || + if ( !(tu_within(CDC_COMM_PROTOCOL_ATCOMMAND, p_interface_desc->bInterfaceProtocol, CDC_COMM_PROTOCOL_ATCOMMAND_CDMA) || 0xff == p_interface_desc->bInterfaceProtocol) ) { return TUSB_ERROR_CDC_UNSUPPORTED_PROTOCOL; diff --git a/src/class/hid/hid_device.c b/src/class/hid/hid_device.c index 410359e6d..b1cd1d1bd 100644 --- a/src/class/hid/hid_device.c +++ b/src/class/hid/hid_device.c @@ -412,8 +412,8 @@ tusb_error_t hidd_control_request_st(uint8_t rhport, tusb_control_request_t cons //------------- STD Request -------------// if (p_request->bmRequestType_bit.type == TUSB_REQ_TYPE_STANDARD) { - uint8_t const desc_type = u16_high_u8(p_request->wValue); - uint8_t const desc_index = u16_low_u8 (p_request->wValue); + uint8_t const desc_type = tu_u16_high(p_request->wValue); + uint8_t const desc_index = tu_u16_low (p_request->wValue); (void) desc_index; if (p_request->bRequest == TUSB_REQ_GET_DESCRIPTOR && desc_type == HID_DESC_TYPE_REPORT) @@ -434,8 +434,8 @@ tusb_error_t hidd_control_request_st(uint8_t rhport, tusb_control_request_t cons if( HID_REQ_CONTROL_GET_REPORT == p_request->bRequest ) { // wValue = Report Type | Report ID - uint8_t const report_type = u16_high_u8(p_request->wValue); - uint8_t const report_id = u16_low_u8(p_request->wValue); + uint8_t const report_type = tu_u16_high(p_request->wValue); + uint8_t const report_id = tu_u16_low(p_request->wValue); uint16_t xferlen; if ( p_hid->get_report_cb ) @@ -455,8 +455,8 @@ tusb_error_t hidd_control_request_st(uint8_t rhport, tusb_control_request_t cons usbd_control_xfer_st(rhport, p_request->bmRequestType_bit.direction, _usbd_ctrl_buf, p_request->wLength); // wValue = Report Type | Report ID - uint8_t const report_type = u16_high_u8(p_request->wValue); - uint8_t const report_id = u16_low_u8(p_request->wValue); + uint8_t const report_type = tu_u16_high(p_request->wValue); + uint8_t const report_id = tu_u16_low(p_request->wValue); if ( p_hid->set_report_cb ) { @@ -466,7 +466,7 @@ tusb_error_t hidd_control_request_st(uint8_t rhport, tusb_control_request_t cons else if (HID_REQ_CONTROL_SET_IDLE == p_request->bRequest) { // TODO idle rate of report - p_hid->idle_rate = u16_high_u8(p_request->wValue); + p_hid->idle_rate = tu_u16_high(p_request->wValue); dcd_control_status(rhport, p_request->bmRequestType_bit.direction); } else if (HID_REQ_CONTROL_GET_IDLE == p_request->bRequest) diff --git a/src/class/msc/msc_device.c b/src/class/msc/msc_device.c index a11212c4b..3335ad9b3 100644 --- a/src/class/msc/msc_device.c +++ b/src/class/msc/msc_device.c @@ -531,7 +531,7 @@ static void proc_read10_cmd(uint8_t rhport, mscd_interface_t* p_msc) uint32_t const lba = rdwr10_get_lba(p_cbw->command) + (p_msc->xferred_len / block_sz); // remaining bytes capped at class buffer - int32_t nbytes = (int32_t) min32_of(sizeof(_mscd_buf), p_cbw->xfer_bytes-p_msc->xferred_len); + int32_t nbytes = (int32_t) tu_min32(sizeof(_mscd_buf), p_cbw->xfer_bytes-p_msc->xferred_len); // Application can consume smaller bytes nbytes = tud_msc_read10_cb(p_cbw->lun, lba, p_msc->xferred_len % block_sz, _mscd_buf, (uint32_t) nbytes); @@ -561,7 +561,7 @@ static void proc_write10_cmd(uint8_t rhport, mscd_interface_t* p_msc) msc_cbw_t const * p_cbw = &p_msc->cbw; // remaining bytes capped at class buffer - int32_t nbytes = (int32_t) min32_of(sizeof(_mscd_buf), p_cbw->xfer_bytes-p_msc->xferred_len); + int32_t nbytes = (int32_t) tu_min32(sizeof(_mscd_buf), p_cbw->xfer_bytes-p_msc->xferred_len); // Write10 callback will be called later when usb transfer complete TU_ASSERT( dcd_edpt_xfer(rhport, p_msc->ep_out, _mscd_buf, nbytes), ); diff --git a/src/common/tusb_common.h b/src/common/tusb_common.h index e8baa9de4..778e70676 100644 --- a/src/common/tusb_common.h +++ b/src/common/tusb_common.h @@ -151,119 +151,94 @@ static inline bool mem_all_zero(void const* buffer, uint32_t size) //------------- Conversion -------------// -/// form an uint32_t from 4 x uint8_t -static inline uint32_t u32_from_u8(uint8_t b1, uint8_t b2, uint8_t b3, uint8_t b4) ATTR_ALWAYS_INLINE ATTR_CONST; -static inline uint32_t u32_from_u8(uint8_t b1, uint8_t b2, uint8_t b3, uint8_t b4) +static inline uint32_t tu_u32_from_u8(uint8_t b1, uint8_t b2, uint8_t b3, uint8_t b4) { return ( ((uint32_t) b1) << 24) + ( ((uint32_t) b2) << 16) + ( ((uint32_t) b3) << 8) + b4; } -static inline uint8_t u16_high_u8(uint16_t u16) ATTR_CONST ATTR_ALWAYS_INLINE; -static inline uint8_t u16_high_u8(uint16_t u16) +static inline uint8_t tu_u16_high(uint16_t u16) { return (uint8_t) ( ((uint16_t) (u16 >> 8)) & 0x00ff); } -static inline uint8_t u16_low_u8(uint16_t u16) ATTR_CONST ATTR_ALWAYS_INLINE; -static inline uint8_t u16_low_u8(uint16_t u16) +static inline uint8_t tu_u16_low(uint16_t u16) { return (uint8_t) (u16 & 0x00ff); } -static inline uint16_t u16_le2be(uint16_t u16) ATTR_CONST ATTR_ALWAYS_INLINE; -static inline uint16_t u16_le2be(uint16_t u16) +static inline uint16_t tu_u16_le2be(uint16_t u16) { - return ((uint16_t)(u16_low_u8(u16) << 8)) | u16_high_u8(u16); + return ((uint16_t)(tu_u16_low(u16) << 8)) | tu_u16_high(u16); } //------------- Min -------------// -static inline uint8_t min8_of(uint8_t x, uint8_t y) ATTR_ALWAYS_INLINE ATTR_CONST; -static inline uint8_t min8_of(uint8_t x, uint8_t y) +static inline uint8_t tu_min8(uint8_t x, uint8_t y) { return (x < y) ? x : y; } -static inline uint16_t min16_of(uint16_t x, uint16_t y) ATTR_ALWAYS_INLINE ATTR_CONST; -static inline uint16_t min16_of(uint16_t x, uint16_t y) +static inline uint16_t tu_min16(uint16_t x, uint16_t y) { return (x < y) ? x : y; } -static inline uint32_t min32_of(uint32_t x, uint32_t y) ATTR_ALWAYS_INLINE ATTR_CONST; -static inline uint32_t min32_of(uint32_t x, uint32_t y) +static inline uint32_t tu_min32(uint32_t x, uint32_t y) { return (x < y) ? x : y; } //------------- Max -------------// -static inline uint32_t max32_of(uint32_t x, uint32_t y) ATTR_ALWAYS_INLINE ATTR_CONST; -static inline uint32_t max32_of(uint32_t x, uint32_t y) +static inline uint32_t tu_max32(uint32_t x, uint32_t y) { return (x > y) ? x : y; } -static inline uint16_t max16_of(uint16_t x, uint16_t y) ATTR_ALWAYS_INLINE ATTR_CONST; -static inline uint16_t max16_of(uint16_t x, uint16_t y) +static inline uint16_t tu_max16(uint16_t x, uint16_t y) { return (x > y) ? x : y; } //------------- Align -------------// -static inline uint32_t align32 (uint32_t value) ATTR_ALWAYS_INLINE ATTR_CONST; -static inline uint32_t align32 (uint32_t value) +static inline uint32_t tu_align32 (uint32_t value) { return (value & 0xFFFFFFE0UL); } -static inline uint32_t align16 (uint32_t value) ATTR_ALWAYS_INLINE ATTR_CONST; -static inline uint32_t align16 (uint32_t value) +static inline uint32_t tu_align16 (uint32_t value) { return (value & 0xFFFFFFF0UL); } -static inline uint32_t align_n (uint32_t alignment, uint32_t value) ATTR_ALWAYS_INLINE ATTR_CONST; -static inline uint32_t align_n (uint32_t alignment, uint32_t value) +static inline uint32_t tu_align_n (uint32_t alignment, uint32_t value) { return value & ((uint32_t) ~(alignment-1)); } -static inline uint32_t align4k (uint32_t value) ATTR_ALWAYS_INLINE ATTR_CONST; -static inline uint32_t align4k (uint32_t value) +static inline uint32_t tu_align4k (uint32_t value) { return (value & 0xFFFFF000UL); } -static inline uint32_t offset4k(uint32_t value) ATTR_ALWAYS_INLINE ATTR_CONST; -static inline uint32_t offset4k(uint32_t value) +static inline uint32_t tu_offset4k(uint32_t value) { return (value & 0xFFFUL); } //------------- Mathematics -------------// -static inline uint32_t abs_of(int32_t value) ATTR_ALWAYS_INLINE ATTR_CONST; -static inline uint32_t abs_of(int32_t value) +static inline uint32_t tu_abs(int32_t value) { return (value < 0) ? (-value) : value; } /// inclusive range checking -static inline bool is_in_range(uint32_t lower, uint32_t value, uint32_t upper) ATTR_ALWAYS_INLINE ATTR_CONST; -static inline bool is_in_range(uint32_t lower, uint32_t value, uint32_t upper) +static inline bool tu_within(uint32_t lower, uint32_t value, uint32_t upper) { return (lower <= value) && (value <= upper); } -/// exclusive range checking -static inline bool is_in_range_exclusive(uint32_t lower, uint32_t value, uint32_t upper) ATTR_ALWAYS_INLINE ATTR_CONST; -static inline bool is_in_range_exclusive(uint32_t lower, uint32_t value, uint32_t upper) -{ - return (lower < value) && (value < upper); -} - // TODO use clz -static inline uint8_t log2_of(uint32_t value) ATTR_ALWAYS_INLINE ATTR_CONST; -static inline uint8_t log2_of(uint32_t value) +static inline uint8_t tu_log2(uint32_t value) { uint8_t result = 0; // log2 of a value is its MSB's position @@ -275,8 +250,7 @@ static inline uint8_t log2_of(uint32_t value) } // return the number of set bits in value -static inline uint8_t cardinality_of(uint32_t value) ATTR_ALWAYS_INLINE ATTR_CONST; -static inline uint8_t cardinality_of(uint32_t value) +static inline uint8_t tu_cardof(uint32_t value) { // Brian Kernighan's method goes through as many iterations as there are set bits. So if we have a 32-bit word with only // the high bit set, then it will only go once through the loop diff --git a/src/common/tusb_fifo.c b/src/common/tusb_fifo.c index 09763bee0..e90264f8b 100644 --- a/src/common/tusb_fifo.c +++ b/src/common/tusb_fifo.c @@ -54,7 +54,7 @@ #endif -static inline uint16_t min16_of(uint16_t x, uint16_t y) +static inline uint16_t tu_min16(uint16_t x, uint16_t y) { return (x < y) ? x : y; } @@ -136,7 +136,7 @@ uint16_t tu_fifo_read_n (tu_fifo_t* f, void * p_buffer, uint16_t count) if( tu_fifo_empty(f) ) return 0; /* Limit up to fifo's count */ - count = min16_of(count, f->count); + count = tu_min16(count, f->count); if( count == 0 ) return 0; mutex_lock_if_needed(f); @@ -145,7 +145,7 @@ uint16_t tu_fifo_read_n (tu_fifo_t* f, void * p_buffer, uint16_t count) * case 1: ....RxxxxW....... * case 2: xxxxxW....Rxxxxxx */ -// uint16_t index2upper = min16_of(count, f->count-f->rd_idx); +// uint16_t index2upper = tu_min16(count, f->count-f->rd_idx); uint8_t* p_buf = (uint8_t*) p_buffer; uint16_t len = 0; diff --git a/src/device/usbd.c b/src/device/usbd.c index 79ad8ffa2..ea5e24884 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -377,9 +377,9 @@ static tusb_error_t proc_control_request_st(uint8_t rhport, tusb_control_request //------------- Class/Interface Specific Request -------------// else if ( TUSB_REQ_RCPT_INTERFACE == p_request->bmRequestType_bit.recipient ) { - if (_usbd_dev.itf2drv[ u16_low_u8(p_request->wIndex) ] < USBD_CLASS_DRIVER_COUNT) + if (_usbd_dev.itf2drv[ tu_u16_low(p_request->wIndex) ] < USBD_CLASS_DRIVER_COUNT) { - STASK_INVOKE( usbd_class_drivers[ _usbd_dev.itf2drv[ u16_low_u8(p_request->wIndex) ] ].control_req_st(rhport, p_request), error ); + STASK_INVOKE( usbd_class_drivers[ _usbd_dev.itf2drv[ tu_u16_low(p_request->wIndex) ] ].control_req_st(rhport, p_request), error ); }else { dcd_control_stall(rhport); // Stall unsupported request @@ -392,7 +392,7 @@ static tusb_error_t proc_control_request_st(uint8_t rhport, tusb_control_request { if (TUSB_REQ_GET_STATUS == p_request->bRequest ) { - uint16_t status = dcd_edpt_stalled(rhport, u16_low_u8(p_request->wIndex)) ? 0x0001 : 0x0000; + uint16_t status = dcd_edpt_stalled(rhport, tu_u16_low(p_request->wIndex)) ? 0x0001 : 0x0000; memcpy(_usbd_ctrl_buf, &status, 2); usbd_control_xfer_st(rhport, p_request->bmRequestType_bit.direction, _usbd_ctrl_buf, 2); @@ -400,13 +400,13 @@ static tusb_error_t proc_control_request_st(uint8_t rhport, tusb_control_request else if (TUSB_REQ_CLEAR_FEATURE == p_request->bRequest ) { // only endpoint feature is halted/stalled - dcd_edpt_clear_stall(rhport, u16_low_u8(p_request->wIndex)); + dcd_edpt_clear_stall(rhport, tu_u16_low(p_request->wIndex)); dcd_control_status(rhport, p_request->bmRequestType_bit.direction); } else if (TUSB_REQ_SET_FEATURE == p_request->bRequest ) { // only endpoint feature is halted/stalled - dcd_edpt_stall(rhport, u16_low_u8(p_request->wIndex)); + dcd_edpt_stall(rhport, tu_u16_low(p_request->wIndex)); dcd_control_status(rhport, p_request->bmRequestType_bit.direction); } else @@ -484,8 +484,8 @@ static uint16_t get_descriptor(uint8_t rhport, tusb_control_request_t const * co { (void) rhport; - tusb_desc_type_t const desc_type = (tusb_desc_type_t) u16_high_u8(p_request->wValue); - uint8_t const desc_index = u16_low_u8( p_request->wValue ); + tusb_desc_type_t const desc_type = (tusb_desc_type_t) tu_u16_high(p_request->wValue); + uint8_t const desc_index = tu_u16_low( p_request->wValue ); uint8_t const * desc_data = NULL ; uint16_t len = 0; @@ -532,7 +532,7 @@ static uint16_t get_descriptor(uint8_t rhport, tusb_control_request_t const * co TU_ASSERT( desc_data != NULL, 0); // up to Host's length - len = min16_of(p_request->wLength, len ); + len = tu_min16(p_request->wLength, len ); (*pp_buffer) = desc_data; return len; diff --git a/src/host/ehci/ehci.c b/src/host/ehci/ehci.c index 32fcc8140..84821e3f5 100644 --- a/src/host/ehci/ehci.c +++ b/src/host/ehci/ehci.c @@ -604,14 +604,14 @@ static void period_list_xfer_complete_isr(uint8_t hostid, uint8_t interval_ms) // TODO abstract max loop guard for period while( !next_item.terminate && - !(interval_ms > 1 && period_1ms_addr == align32(next_item.address)) && + !(interval_ms > 1 && period_1ms_addr == tu_align32(next_item.address)) && max_loop < (HCD_MAX_ENDPOINT + EHCI_MAX_ITD + EHCI_MAX_SITD)*CFG_TUSB_HOST_DEVICE_MAX) { switch ( next_item.type ) { case EHCI_QUEUE_ELEMENT_QHD: { - ehci_qhd_t *p_qhd_int = (ehci_qhd_t *) align32(next_item.address); + ehci_qhd_t *p_qhd_int = (ehci_qhd_t *) tu_align32(next_item.address); if ( !p_qhd_int->qtd_overlay.halted ) { qhd_xfer_complete_isr(p_qhd_int); @@ -653,7 +653,7 @@ static void qhd_xfer_error_isr(ehci_qhd_t * p_qhd) if ( TUSB_XFER_CONTROL == xfer_type ) { - p_qhd->total_xferred_bytes -= min8_of(8, p_qhd->total_xferred_bytes); // subtract setup size + p_qhd->total_xferred_bytes -= tu_min8(8, p_qhd->total_xferred_bytes); // subtract setup size // control cannot be halted --> clear all qtd list p_qhd->p_qtd_list_head = NULL; @@ -702,14 +702,14 @@ static void xfer_error_isr(uint8_t hostid) // TODO abstract max loop guard for period while( !next_item.terminate && - !(interval_ms > 1 && period_1ms_addr == align32(next_item.address)) && + !(interval_ms > 1 && period_1ms_addr == tu_align32(next_item.address)) && period_max_loop < (HCD_MAX_ENDPOINT + EHCI_MAX_ITD + EHCI_MAX_SITD)*CFG_TUSB_HOST_DEVICE_MAX) { switch ( next_item.type ) { case EHCI_QUEUE_ELEMENT_QHD: { - ehci_qhd_t *p_qhd_int = (ehci_qhd_t *) align32(next_item.address); + ehci_qhd_t *p_qhd_int = (ehci_qhd_t *) tu_align32(next_item.address); qhd_xfer_error_isr(p_qhd_int); } break; @@ -828,7 +828,7 @@ static inline ehci_qhd_t* get_async_head(uint8_t hostid) 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) ) ] ); + [ tu_log2( tu_min8(EHCI_FRAMELIST_SIZE, interval_ms) ) ] ); } #endif @@ -869,7 +869,7 @@ static inline tusb_xfer_type_t qhd_get_xfer_type(ehci_qhd_t const * p_qhd) static inline ehci_qhd_t* qhd_next(ehci_qhd_t const * p_qhd) { - return (ehci_qhd_t*) align32(p_qhd->next.address); + return (ehci_qhd_t*) tu_align32(p_qhd->next.address); } static inline ehci_qhd_t* qhd_get_from_pipe_handle(pipe_handle_t pipe_hdl) @@ -907,7 +907,7 @@ static inline ehci_qtd_t* qtd_find_free(uint8_t dev_addr) static inline ehci_qtd_t* qtd_next(ehci_qtd_t const * p_qtd ) { - return (ehci_qtd_t*) align32(p_qtd->next.address); + return (ehci_qtd_t*) tu_align32(p_qtd->next.address); } static inline void qtd_remove_1st_from_qhd(ehci_qhd_t *p_qhd) @@ -965,7 +965,7 @@ static void qhd_init(ehci_qhd_t *p_qhd, uint8_t dev_addr, uint16_t max_packet_si (interval == 2) ? BIN8(10101010) : BIN8(01000100); }else { - p_qhd->interval_ms = (uint8_t) min16_of( 1 << (interval-4), 255 ); + p_qhd->interval_ms = (uint8_t) tu_min16( 1 << (interval-4), 255 ); p_qhd->interrupt_smask = BIT_(interval % 8); } }else @@ -1019,7 +1019,7 @@ static void qtd_init(ehci_qtd_t* p_qtd, uint32_t data_ptr, uint16_t 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; + p_qtd->buffer[i] |= tu_align4k( p_qtd->buffer[i-1] ) + 4096; } } @@ -1032,15 +1032,15 @@ static inline void list_insert(ehci_link_t *current, ehci_link_t *new, uint8_t n static inline ehci_link_t* list_next(ehci_link_t *p_link_pointer) { - return (ehci_link_t*) align32(p_link_pointer->address); + return (ehci_link_t*) tu_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 + while( (tu_align32(p_prev->address) != (uint32_t) p_head) && // not loop around + (tu_align32(p_prev->address) != (uint32_t) p_current) && // not found yet !p_prev->terminate && // not advanceable max_loop < HCD_MAX_ENDPOINT) { @@ -1048,7 +1048,7 @@ static ehci_link_t* list_find_previous_item(ehci_link_t* p_head, ehci_link_t* p_ max_loop++; } - return (align32(p_prev->address) != (uint32_t) p_head) ? p_prev : NULL; + return (tu_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) diff --git a/src/host/ohci/ohci.c b/src/host/ohci/ohci.c index 644dbfa0f..1c9f3f293 100644 --- a/src/host/ohci/ohci.c +++ b/src/host/ohci/ohci.c @@ -389,15 +389,15 @@ static ohci_ed_t * ed_list_find_previous(ohci_ed_t const * p_head, ohci_ed_t con TU_ASSERT(p_prev, NULL); - while ( align16(p_prev->next_ed) != 0 && /* not reach null */ - align16(p_prev->next_ed) != (uint32_t) p_ed && /* not found yet */ + while ( tu_align16(p_prev->next_ed) != 0 && /* not reach null */ + tu_align16(p_prev->next_ed) != (uint32_t) p_ed && /* not found yet */ max_loop > 0) { - p_prev = (ohci_ed_t const *) align16(p_prev->next_ed); + p_prev = (ohci_ed_t const *) tu_align16(p_prev->next_ed); max_loop--; } - return ( align16(p_prev->next_ed) == (uint32_t) p_ed ) ? (ohci_ed_t*) p_prev : NULL; + return ( tu_align16(p_prev->next_ed) == (uint32_t) p_ed ) ? (ohci_ed_t*) p_prev : NULL; } static void ed_list_insert(ohci_ed_t * p_pre, ohci_ed_t * p_ed) @@ -410,7 +410,7 @@ static void ed_list_remove(ohci_ed_t * p_head, ohci_ed_t * p_ed) { ohci_ed_t * const p_prev = ed_list_find_previous(p_head, p_ed); - p_prev->next_ed = (p_prev->next_ed & 0x0fUL) | align16(p_ed->next_ed); + p_prev->next_ed = (p_prev->next_ed & 0x0fUL) | tu_align16(p_ed->next_ed); // point the removed ED's next pointer to list head to make sure HC can always safely move away from this ED p_ed->next_ed = (uint32_t) p_head; p_ed->used = 0; // free ED @@ -457,13 +457,13 @@ static ohci_gtd_t * gtd_find_free(uint8_t dev_addr) static void td_insert_to_ed(ohci_ed_t* p_ed, ohci_gtd_t * p_gtd) { // tail is always NULL - if ( align16(p_ed->td_head.address) == 0 ) + if ( tu_align16(p_ed->td_head.address) == 0 ) { // TD queue is empty --> head = TD p_ed->td_head.address |= (uint32_t) p_gtd; } else { // TODO currently only support queue up to 2 TD each endpoint at a time - ((ohci_gtd_t*) align16(p_ed->td_head.address))->next_td = (uint32_t) p_gtd; + ((ohci_gtd_t*) tu_align16(p_ed->td_head.address))->next_td = (uint32_t) p_gtd; } } @@ -520,7 +520,7 @@ tusb_error_t hcd_pipe_close(pipe_handle_t pipe_hdl) bool hcd_pipe_is_busy(pipe_handle_t pipe_hdl) { ohci_ed_t const * const p_ed = ed_from_pipe_handle(pipe_hdl); - return align16(p_ed->td_head.address) != align16(p_ed->td_tail.address); + return tu_align16(p_ed->td_head.address) != tu_align16(p_ed->td_tail.address); } bool hcd_pipe_is_error(pipe_handle_t pipe_hdl) @@ -601,8 +601,8 @@ static inline ohci_ed_t* gtd_get_ed(ohci_gtd_t const * const p_qtd) static inline uint32_t gtd_xfer_byte_left(uint32_t buffer_end, uint32_t current_buffer) ATTR_CONST ATTR_ALWAYS_INLINE; static inline uint32_t gtd_xfer_byte_left(uint32_t buffer_end, uint32_t current_buffer) { // 5.2.9 OHCI sample code - return (align4k(buffer_end ^ current_buffer) ? 0x1000 : 0) + - offset4k(buffer_end) - offset4k(current_buffer) + 1; + return (tu_align4k(buffer_end ^ current_buffer) ? 0x1000 : 0) + + tu_offset4k(buffer_end) - tu_offset4k(current_buffer) + 1; } static void done_queue_isr(uint8_t hostid) @@ -610,7 +610,7 @@ static void done_queue_isr(uint8_t hostid) uint8_t max_loop = (CFG_TUSB_HOST_DEVICE_MAX+1)*(HCD_MAX_XFER+OHCI_MAX_ITD); // done head is written in reversed order of completion --> need to reverse the done queue first - ohci_td_item_t* td_head = list_reverse ( (ohci_td_item_t*) align16(ohci_data.hcca.done_head) ); + ohci_td_item_t* td_head = list_reverse ( (ohci_td_item_t*) tu_align16(ohci_data.hcca.done_head) ); while( td_head != NULL && max_loop > 0) { @@ -637,7 +637,7 @@ static void done_queue_isr(uint8_t hostid) if ((event != TUSB_EVENT_XFER_COMPLETE)) { p_ed->td_tail.address &= 0x0Ful; - p_ed->td_tail.address |= align16(p_ed->td_head.address); // mark halted EP as empty queue + p_ed->td_tail.address |= tu_align16(p_ed->td_head.address); // mark halted EP as empty queue if ( event == TUSB_EVENT_XFER_STALLED ) p_ed->is_stalled = 1; } diff --git a/src/host/usbh.c b/src/host/usbh.c index 6d1cd37ad..8b858b2de 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -643,7 +643,7 @@ static inline uint8_t get_configure_number_for_device(tusb_desc_device_t* dev_de // invoke callback to ask user which configuration to select if (tuh_device_attached_cb) { - config_num = min8_of(1, tuh_device_attached_cb(dev_desc) ); + config_num = tu_min8(1, tuh_device_attached_cb(dev_desc) ); } return config_num; diff --git a/src/portable/nordic/nrf5x/dcd_nrf5x.c b/src/portable/nordic/nrf5x/dcd_nrf5x.c index 72cd8d0b1..1c91779a7 100644 --- a/src/portable/nordic/nrf5x/dcd_nrf5x.c +++ b/src/portable/nordic/nrf5x/dcd_nrf5x.c @@ -178,7 +178,7 @@ static void edpt_dma_end(void) static void xact_control_start(void) { // Each transaction is up to 64 bytes - uint8_t const xact_len = min16_of(_dcd.control.total_len-_dcd.control.actual_len, MAX_PACKET_SIZE); + uint8_t const xact_len = tu_min16(_dcd.control.total_len-_dcd.control.actual_len, MAX_PACKET_SIZE); if ( _dcd.control.dir == TUSB_DIR_OUT ) { @@ -274,7 +274,7 @@ static void xact_in_prepare(uint8_t epnum) nom_xfer_t* xfer = get_td(epnum, TUSB_DIR_IN); // Each transaction is up to Max Packet Size - uint8_t const xact_len = min16_of(xfer->total_len - xfer->actual_len, xfer->mps); + uint8_t const xact_len = tu_min16(xfer->total_len - xfer->actual_len, xfer->mps); NRF_USBD->EPIN[epnum].PTR = (uint32_t) xfer->buffer; NRF_USBD->EPIN[epnum].MAXCNT = xact_len; diff --git a/src/portable/nxp/lpc11xx_lpc13xx/dcd_lpc_11uxx_13uxx.c b/src/portable/nxp/lpc11xx_lpc13xx/dcd_lpc_11uxx_13uxx.c index 0eaecf1b8..3e536312a 100644 --- a/src/portable/nxp/lpc11xx_lpc13xx/dcd_lpc_11uxx_13uxx.c +++ b/src/portable/nxp/lpc11xx_lpc13xx/dcd_lpc_11uxx_13uxx.c @@ -497,7 +497,7 @@ bool dcd_edpt_busy(edpt_hdl_t edpt_hdl) static void queue_xfer_to_buffer(uint8_t ep_id, uint8_t buff_idx, uint16_t buff_addr_offset, uint16_t total_bytes) { - uint16_t const queued_bytes = min16_of(total_bytes, DCD_11U_13U_MAX_BYTE_PER_TD); + uint16_t const queued_bytes = tu_min16(total_bytes, DCD_11U_13U_MAX_BYTE_PER_TD); dcd_data.current_td[ep_id].queued_bytes_in_buff[buff_idx] = queued_bytes; dcd_data.current_td[ep_id].remaining_bytes -= queued_bytes; diff --git a/src/portable/nxp/lpc17xx/dcd_lpc175x_6x.c b/src/portable/nxp/lpc17xx/dcd_lpc175x_6x.c index a87e7d899..8c87984e8 100644 --- a/src/portable/nxp/lpc17xx/dcd_lpc175x_6x.c +++ b/src/portable/nxp/lpc17xx/dcd_lpc175x_6x.c @@ -312,7 +312,7 @@ static inline uint16_t length_byte2dword(uint16_t length_in_bytes) static tusb_error_t pipe_control_xfer(uint8_t ep_id, uint8_t* p_buffer, uint16_t length) { - uint16_t const packet_len = min16_of(length, CFG_TUD_ENDOINT0_SIZE); + uint16_t const packet_len = tu_min16(length, CFG_TUD_ENDOINT0_SIZE); if (ep_id) { @@ -355,7 +355,7 @@ static tusb_error_t pipe_control_read(void * buffer, uint16_t length) LPC_USB->USBCtrl = USBCTRL_READ_ENABLE_MASK; // logical endpoint = 0 while ((LPC_USB->USBRxPLen & USBRXPLEN_PACKET_READY_MASK) == 0) {} // TODO blocking, should have timeout - uint16_t actual_length = min16_of(length, (uint16_t) (LPC_USB->USBRxPLen & USBRXPLEN_PACKET_LENGTH_MASK) ); + uint16_t actual_length = tu_min16(length, (uint16_t) (LPC_USB->USBRxPLen & USBRXPLEN_PACKET_LENGTH_MASK) ); uint32_t *p_read_data = (uint32_t*) buffer; for( uint16_t count=0; count < length_byte2dword(actual_length); count++) { diff --git a/src/portable/nxp/lpc43xx_lpc18xx/dcd_lpc43xx.c b/src/portable/nxp/lpc43xx_lpc18xx/dcd_lpc43xx.c index 61f829713..792a009f2 100644 --- a/src/portable/nxp/lpc43xx_lpc18xx/dcd_lpc43xx.c +++ b/src/portable/nxp/lpc43xx_lpc18xx/dcd_lpc43xx.c @@ -209,7 +209,7 @@ static void qtd_init(dcd_qtd_t* p_qtd, void * data_ptr, uint16_t total_bytes) p_qtd->buffer[0] = (uint32_t) data_ptr; for(uint8_t i=1; i<5; i++) { - p_qtd->buffer[i] |= align4k( p_qtd->buffer[i-1] ) + 4096; + p_qtd->buffer[i] |= tu_align4k( p_qtd->buffer[i-1] ) + 4096; } } } diff --git a/tests/lpc18xx_43xx/test/host/ehci/test_ehci_init.c b/tests/lpc18xx_43xx/test/host/ehci/test_ehci_init.c index f31944338..69b7c1dd9 100644 --- a/tests/lpc18xx_43xx/test/host/ehci/test_ehci_init.c +++ b/tests/lpc18xx_43xx/test/host/ehci/test_ehci_init.c @@ -107,7 +107,7 @@ void test_hcd_init_async_list(void) TEST_ASSERT_EQUAL_HEX(async_head, regs->async_list_base); - TEST_ASSERT_EQUAL_HEX(async_head, align32( (uint32_t) async_head) ); + TEST_ASSERT_EQUAL_HEX(async_head, tu_align32( (uint32_t) async_head) ); TEST_ASSERT_EQUAL(EHCI_QUEUE_ELEMENT_QHD, async_head->next.type); TEST_ASSERT_FALSE(async_head->next.terminate); @@ -118,7 +118,7 @@ void test_hcd_init_async_list(void) void check_qhd_endpoint_link(ehci_link_t *p_prev, ehci_qhd_t *p_qhd) { //------------- period list check -------------// - TEST_ASSERT_EQUAL_HEX((uint32_t) p_qhd, align32(p_prev->address)); + TEST_ASSERT_EQUAL_HEX((uint32_t) p_qhd, tu_align32(p_prev->address)); TEST_ASSERT_FALSE(p_prev->terminate); TEST_ASSERT_EQUAL(EHCI_QUEUE_ELEMENT_QHD, p_prev->type); } diff --git a/tests/lpc18xx_43xx/test/host/ehci/test_pipe_bulk_open.c b/tests/lpc18xx_43xx/test/host/ehci/test_pipe_bulk_open.c index c2d52ce4c..a26b990d3 100644 --- a/tests/lpc18xx_43xx/test/host/ehci/test_pipe_bulk_open.c +++ b/tests/lpc18xx_43xx/test/host/ehci/test_pipe_bulk_open.c @@ -143,7 +143,7 @@ void verify_bulk_open_qhd(ehci_qhd_t *p_qhd, tusb_desc_endpoint_t const * desc_e TEST_ASSERT_EQUAL(class_code, p_qhd->class_code); //------------- async list check -------------// - TEST_ASSERT_EQUAL_HEX((uint32_t) p_qhd, align32(async_head->next.address)); + TEST_ASSERT_EQUAL_HEX((uint32_t) p_qhd, tu_align32(async_head->next.address)); TEST_ASSERT_FALSE(async_head->next.terminate); TEST_ASSERT_EQUAL(EHCI_QUEUE_ELEMENT_QHD, async_head->next.type); } @@ -164,7 +164,7 @@ void test_open_bulk_qhd_data(void) verify_bulk_open_qhd(p_qhd, desc_endpoint, TUSB_CLASS_MSC); //------------- async list check -------------// - TEST_ASSERT_EQUAL_HEX((uint32_t) p_qhd, align32(async_head->next.address)); + TEST_ASSERT_EQUAL_HEX((uint32_t) p_qhd, tu_align32(async_head->next.address)); TEST_ASSERT_FALSE(async_head->next.terminate); TEST_ASSERT_EQUAL(EHCI_QUEUE_ELEMENT_QHD, async_head->next.type); } @@ -194,7 +194,7 @@ void test_bulk_close(void) hcd_pipe_close(pipe_hdl); TEST_ASSERT(p_qhd->is_removing); - TEST_ASSERT( align32(async_head->next.address) != (uint32_t) p_qhd ); - TEST_ASSERT_EQUAL_HEX( (uint32_t) async_head, align32(p_qhd->next.address) ); + TEST_ASSERT( tu_align32(async_head->next.address) != (uint32_t) p_qhd ); + TEST_ASSERT_EQUAL_HEX( (uint32_t) async_head, tu_align32(p_qhd->next.address) ); TEST_ASSERT_EQUAL(EHCI_QUEUE_ELEMENT_QHD, p_qhd->next.type); } diff --git a/tests/lpc18xx_43xx/test/host/ehci/test_pipe_bulk_xfer.c b/tests/lpc18xx_43xx/test/host/ehci/test_pipe_bulk_xfer.c index e3d78f668..a52c721fe 100644 --- a/tests/lpc18xx_43xx/test/host/ehci/test_pipe_bulk_xfer.c +++ b/tests/lpc18xx_43xx/test/host/ehci/test_pipe_bulk_xfer.c @@ -140,7 +140,7 @@ void verify_qtd(ehci_qtd_t *p_qtd, uint8_t p_data[], uint16_t length) TEST_ASSERT_EQUAL_HEX( p_data, p_qtd->buffer[0] ); for(uint8_t i=1; i<5; i++) { - TEST_ASSERT_EQUAL_HEX( align4k((uint32_t) (p_data+4096*i)), align4k(p_qtd->buffer[i]) ); + TEST_ASSERT_EQUAL_HEX( tu_align4k((uint32_t) (p_data+4096*i)), tu_align4k(p_qtd->buffer[i]) ); } } @@ -193,7 +193,7 @@ void test_bulk_xfer_double(void) //------------- list tail -------------// TEST_ASSERT_NOT_NULL(p_tail); verify_qtd(p_tail, data2, sizeof(data2)); - TEST_ASSERT_EQUAL_HEX( align32(p_head->next.address), p_tail); + TEST_ASSERT_EQUAL_HEX( tu_align32(p_head->next.address), p_tail); TEST_ASSERT_EQUAL(EHCI_PID_IN, p_tail->pid); TEST_ASSERT_TRUE(p_tail->next.terminate); TEST_ASSERT_TRUE(p_tail->int_on_complete); diff --git a/tests/lpc18xx_43xx/test/host/ehci/test_pipe_control_open.c b/tests/lpc18xx_43xx/test/host/ehci/test_pipe_control_open.c index 1143b9faa..22cbf7569 100644 --- a/tests/lpc18xx_43xx/test/host/ehci/test_pipe_control_open.c +++ b/tests/lpc18xx_43xx/test/host/ehci/test_pipe_control_open.c @@ -142,7 +142,7 @@ void test_control_open_qhd_data(void) TEST_ASSERT_FALSE(p_control_qhd->head_list_flag); //------------- async list check -------------// - TEST_ASSERT_EQUAL_HEX((uint32_t) p_control_qhd, align32(async_head->next.address)); + TEST_ASSERT_EQUAL_HEX((uint32_t) p_control_qhd, tu_align32(async_head->next.address)); TEST_ASSERT_FALSE(async_head->next.terminate); TEST_ASSERT_EQUAL(EHCI_QUEUE_ELEMENT_QHD, async_head->next.type); } @@ -191,6 +191,6 @@ void test_control_close(void) TEST_ASSERT(p_control_qhd->is_removing); TEST_ASSERT(p_control_qhd->used); - TEST_ASSERT( align32(get_async_head(hostid)->next.address) != (uint32_t) p_control_qhd ); - TEST_ASSERT_EQUAL( get_async_head(hostid), align32(p_control_qhd->next.address)); + TEST_ASSERT( tu_align32(get_async_head(hostid)->next.address) != (uint32_t) p_control_qhd ); + TEST_ASSERT_EQUAL( get_async_head(hostid), tu_align32(p_control_qhd->next.address)); } diff --git a/tests/lpc18xx_43xx/test/host/ehci/test_pipe_interrupt_open.c b/tests/lpc18xx_43xx/test/host/ehci/test_pipe_interrupt_open.c index 1f8fc9a12..f39021ef2 100644 --- a/tests/lpc18xx_43xx/test/host/ehci/test_pipe_interrupt_open.c +++ b/tests/lpc18xx_43xx/test/host/ehci/test_pipe_interrupt_open.c @@ -136,7 +136,7 @@ void verify_int_qhd(ehci_qhd_t *p_qhd, tusb_desc_endpoint_t const * desc_endpoin void check_int_endpoint_link(ehci_qhd_t *p_prev, ehci_qhd_t *p_qhd) { //------------- period list check -------------// - TEST_ASSERT_EQUAL_HEX((uint32_t) p_qhd, align32(p_prev->next.address)); + TEST_ASSERT_EQUAL_HEX((uint32_t) p_qhd, tu_align32(p_prev->next.address)); TEST_ASSERT_FALSE(p_prev->next.terminate); TEST_ASSERT_EQUAL(EHCI_QUEUE_ELEMENT_QHD, p_prev->next.type); } @@ -181,7 +181,7 @@ void test_open_interrupt_hs_interval_2(void) p_int_qhd = &ehci_data.device[ pipe_hdl.dev_addr-1].qhd[ pipe_hdl.index ]; TEST_ASSERT_EQUAL(0 , p_int_qhd->interval_ms); - TEST_ASSERT_EQUAL(4 , cardinality_of(p_int_qhd->interrupt_smask)); // either 10101010 or 01010101 + TEST_ASSERT_EQUAL(4 , tu_cardof(p_int_qhd->interrupt_smask)); // either 10101010 or 01010101 check_int_endpoint_link(period_head_arr, p_int_qhd); } @@ -195,7 +195,7 @@ void test_open_interrupt_hs_interval_3(void) p_int_qhd = &ehci_data.device[ pipe_hdl.dev_addr-1].qhd[ pipe_hdl.index ]; TEST_ASSERT_EQUAL(0, p_int_qhd->interval_ms); - TEST_ASSERT_EQUAL(2, cardinality_of(p_int_qhd->interrupt_smask) ); + TEST_ASSERT_EQUAL(2, tu_cardof(p_int_qhd->interrupt_smask) ); check_int_endpoint_link(period_head_arr, p_int_qhd); } @@ -209,7 +209,7 @@ void test_open_interrupt_hs_interval_4(void) p_int_qhd = &ehci_data.device[ pipe_hdl.dev_addr-1].qhd[ pipe_hdl.index ]; TEST_ASSERT_EQUAL(1, p_int_qhd->interval_ms); - TEST_ASSERT_EQUAL(1, cardinality_of(p_int_qhd->interrupt_smask) ); + TEST_ASSERT_EQUAL(1, tu_cardof(p_int_qhd->interrupt_smask) ); check_int_endpoint_link(period_head_arr, p_int_qhd); } @@ -223,7 +223,7 @@ void test_open_interrupt_hs_interval_5(void) p_int_qhd = &ehci_data.device[ pipe_hdl.dev_addr-1].qhd[ pipe_hdl.index ]; TEST_ASSERT_EQUAL(2, p_int_qhd->interval_ms); - TEST_ASSERT_EQUAL(1, cardinality_of(p_int_qhd->interrupt_smask) ); + TEST_ASSERT_EQUAL(1, tu_cardof(p_int_qhd->interrupt_smask) ); check_int_endpoint_link( get_period_head(hostid, 2), p_int_qhd ); } @@ -237,7 +237,7 @@ void test_open_interrupt_hs_interval_6(void) p_int_qhd = &ehci_data.device[ pipe_hdl.dev_addr-1].qhd[ pipe_hdl.index ]; TEST_ASSERT_EQUAL(4, p_int_qhd->interval_ms); - TEST_ASSERT_EQUAL(1, cardinality_of(p_int_qhd->interrupt_smask) ); + TEST_ASSERT_EQUAL(1, tu_cardof(p_int_qhd->interrupt_smask) ); check_int_endpoint_link( get_period_head(hostid, 4), p_int_qhd); } @@ -251,7 +251,7 @@ void test_open_interrupt_hs_interval_7(void) p_int_qhd = &ehci_data.device[ pipe_hdl.dev_addr-1].qhd[ pipe_hdl.index ]; TEST_ASSERT_EQUAL(8, p_int_qhd->interval_ms); - TEST_ASSERT_EQUAL(1, cardinality_of(p_int_qhd->interrupt_smask) ); + TEST_ASSERT_EQUAL(1, tu_cardof(p_int_qhd->interrupt_smask) ); check_int_endpoint_link( get_period_head(hostid, 8), p_int_qhd); } @@ -265,7 +265,7 @@ void test_open_interrupt_hs_interval_8(void) p_int_qhd = &ehci_data.device[ pipe_hdl.dev_addr-1].qhd[ pipe_hdl.index ]; TEST_ASSERT_EQUAL(255, p_int_qhd->interval_ms); - TEST_ASSERT_EQUAL(1, cardinality_of(p_int_qhd->interrupt_smask) ); + TEST_ASSERT_EQUAL(1, tu_cardof(p_int_qhd->interrupt_smask) ); check_int_endpoint_link( get_period_head(hostid, 255), p_int_qhd); check_int_endpoint_link( get_period_head(hostid, 8) , p_int_qhd); } @@ -318,8 +318,8 @@ void test_interrupt_close(void) hcd_pipe_close(pipe_hdl) ); TEST_ASSERT(p_int_qhd->is_removing); - TEST_ASSERT( align32(period_head_arr->next.address) != (uint32_t) p_int_qhd ); - TEST_ASSERT_EQUAL_HEX( (uint32_t) period_head_arr, align32(p_int_qhd->next.address ) ); + TEST_ASSERT( tu_align32(period_head_arr->next.address) != (uint32_t) p_int_qhd ); + TEST_ASSERT_EQUAL_HEX( (uint32_t) period_head_arr, tu_align32(p_int_qhd->next.address ) ); TEST_ASSERT_EQUAL(EHCI_QUEUE_ELEMENT_QHD, p_int_qhd->next.type); } @@ -336,7 +336,7 @@ void test_interrupt_256ms_close(void) hcd_pipe_close(pipe_hdl) ); TEST_ASSERT(p_int_qhd->is_removing); - TEST_ASSERT( align32(get_period_head(hostid, 8)->address) != (uint32_t) p_int_qhd ); - TEST_ASSERT_EQUAL_HEX( (uint32_t) get_period_head(hostid, 8), align32(p_int_qhd->next.address ) ); + TEST_ASSERT( tu_align32(get_period_head(hostid, 8)->address) != (uint32_t) p_int_qhd ); + TEST_ASSERT_EQUAL_HEX( (uint32_t) get_period_head(hostid, 8), tu_align32(p_int_qhd->next.address ) ); TEST_ASSERT_EQUAL(EHCI_QUEUE_ELEMENT_QHD, p_int_qhd->next.type); } diff --git a/tests/lpc18xx_43xx/test/host/ehci/test_pipe_interrupt_xfer.c b/tests/lpc18xx_43xx/test/host/ehci/test_pipe_interrupt_xfer.c index cacc1e98c..aeb094932 100644 --- a/tests/lpc18xx_43xx/test/host/ehci/test_pipe_interrupt_xfer.c +++ b/tests/lpc18xx_43xx/test/host/ehci/test_pipe_interrupt_xfer.c @@ -142,7 +142,7 @@ void verify_qtd(ehci_qtd_t *p_qtd, uint8_t p_data[], uint16_t length) TEST_ASSERT_EQUAL_HEX( p_data, p_qtd->buffer[0] ); for(uint8_t i=1; i<5; i++) { - TEST_ASSERT_EQUAL_HEX( align4k((uint32_t) (p_data+4096*i)), align4k(p_qtd->buffer[i]) ); + TEST_ASSERT_EQUAL_HEX( tu_align4k((uint32_t) (p_data+4096*i)), tu_align4k(p_qtd->buffer[i]) ); } } @@ -182,7 +182,7 @@ void test_interrupt_xfer_double(void) //------------- list tail -------------// TEST_ASSERT_NOT_NULL(p_tail); verify_qtd(p_tail, data2, sizeof(data2)); - TEST_ASSERT_EQUAL_HEX( align32(p_head->next.address), p_tail); + TEST_ASSERT_EQUAL_HEX( tu_align32(p_head->next.address), p_tail); TEST_ASSERT_EQUAL(EHCI_PID_IN, p_tail->pid); TEST_ASSERT_TRUE(p_tail->next.terminate); TEST_ASSERT_TRUE(p_tail->int_on_complete); diff --git a/tests/support/ehci_controller_fake.c b/tests/support/ehci_controller_fake.c index 04d55172c..041e1dbb5 100644 --- a/tests/support/ehci_controller_fake.c +++ b/tests/support/ehci_controller_fake.c @@ -95,7 +95,7 @@ void complete_qtd_in_qhd(ehci_qhd_t *p_qhd) { while(!p_qhd->qtd_overlay.next.terminate) { - ehci_qtd_t* p_qtd = (ehci_qtd_t*) align32(p_qhd->qtd_overlay.next.address); + ehci_qtd_t* p_qtd = (ehci_qtd_t*) tu_align32(p_qhd->qtd_overlay.next.address); p_qtd->active = 0; p_qtd->total_bytes = 0; p_qhd->qtd_overlay = *p_qtd; @@ -110,7 +110,7 @@ bool complete_all_qtd_in_async(ehci_qhd_t *head) do { complete_qtd_in_qhd(p_qhd); - p_qhd = (ehci_qhd_t*) align32(p_qhd->next.address); + p_qhd = (ehci_qhd_t*) tu_align32(p_qhd->next.address); }while(p_qhd != head); // stop if loop around return true; @@ -121,7 +121,7 @@ bool complete_all_qtd_in_period(ehci_link_t *head) while(!head->terminate) { uint32_t queue_type = head->type; - head = (ehci_link_t*) align32(head->address); + head = (ehci_link_t*) tu_align32(head->address); if ( queue_type == EHCI_QUEUE_ELEMENT_QHD) { @@ -153,7 +153,7 @@ void complete_1st_qtd_with_error(ehci_qhd_t* p_qhd, bool halted, bool xact_err) { if(!p_qhd->qtd_overlay.next.terminate) // TODO add active check { - ehci_qtd_t* p_qtd = (ehci_qtd_t*) align32(p_qhd->qtd_overlay.next.address); + ehci_qtd_t* p_qtd = (ehci_qtd_t*) tu_align32(p_qhd->qtd_overlay.next.address); p_qtd->active = 0; p_qtd->halted = halted ? 1 : 0; p_qtd->xact_err = xact_err ? 1 : 0; @@ -172,7 +172,7 @@ void complete_list_with_error(uint8_t hostid, bool halted, bool xact_err) do { complete_1st_qtd_with_error(p_qhd, halted, xact_err); - p_qhd = (ehci_qhd_t*) align32(p_qhd->next.address); + p_qhd = (ehci_qhd_t*) tu_align32(p_qhd->next.address); }while(p_qhd != get_async_head(hostid)); // stop if loop around //------------- Period List -------------// @@ -183,7 +183,7 @@ void complete_list_with_error(uint8_t hostid, bool halted, bool xact_err) while(!head->terminate) { uint32_t queue_type = head->type; - head = (ehci_link_t*) align32(head->address); + head = (ehci_link_t*) tu_align32(head->address); if ( queue_type == EHCI_QUEUE_ELEMENT_QHD) { diff --git a/tests/support/type_helper.h b/tests/support/type_helper.h index d0712e4f0..3e27cef2e 100644 --- a/tests/support/type_helper.h +++ b/tests/support/type_helper.h @@ -70,7 +70,7 @@ #define TEST_ASSERT_STATUS( actual )\ TEST_ASSERT_EQUAL( TUSB_ERROR_NONE, (actual) ) -// log2_of a value is equivalent to its highest set bit's position +// tu_log2 a value is equivalent to its highest set bit's position #define BITFIELD_OFFSET_OF_MEMBER(struct_type, member, bitfield_member) \ ({\ uint32_t value=0;\ @@ -78,7 +78,7 @@ memclr_((void*)&str, sizeof(struct_type));\ str.member.bitfield_member = 1;\ memcpy(&value, (void*)&str.member, sizeof(str.member));\ - log2_of( value );\ + tu_log2( value );\ }) #define BITFIELD_OFFSET_OF_UINT32(struct_type, offset, bitfield_member) \ @@ -86,7 +86,7 @@ struct_type str;\ memclr_(&str, sizeof(struct_type));\ str.bitfield_member = 1;\ - log2_of( ((uint32_t*) &str)[offset] );\ + tu_log2( ((uint32_t*) &str)[offset] );\ }) #ifdef __cplusplus -- cgit v1.3.1 From c7340f4b0eb8dcf15fa93f6bf6589a94fb59dc95 Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 23 Oct 2018 12:19:32 +0700 Subject: clean up helper func --- examples/obsolete/device/src/mouse_device_app.c | 2 +- examples/obsolete/host/src/cdc_serial_host_app.c | 4 +-- examples/obsolete/host/src/keyboard_host_app.c | 2 +- examples/obsolete/host/src/mouse_host_app.c | 2 +- examples/obsolete/host/src/msc_cli.c | 6 ++-- src/class/cdc/cdc_device.c | 4 +-- src/class/cdc/cdc_host.c | 4 +-- src/class/cdc/cdc_rndis_host.c | 8 ++--- src/class/custom/custom_device.c | 2 +- src/class/custom/custom_host.c | 4 +-- src/class/hid/hid_device.c | 8 ++--- src/class/hid/hid_host.c | 6 ++-- src/class/msc/msc_device.c | 12 ++++---- src/class/msc/msc_host.c | 4 +-- src/common/tusb_common.h | 34 +++------------------- src/device/usbd.c | 4 +-- src/host/ehci/ehci.c | 8 ++--- src/host/hub.c | 4 +-- src/host/ohci/ohci.c | 6 ++-- src/host/usbh.c | 2 +- src/osal/osal_mynewt.h | 2 +- src/portable/nordic/nrf5x/dcd_nrf5x.c | 2 +- .../nxp/lpc11xx_lpc13xx/dcd_lpc_11uxx_13uxx.c | 4 +-- src/portable/nxp/lpc17xx/dcd_lpc175x_6x.c | 6 ++-- src/portable/nxp/lpc43xx_lpc18xx/dcd_lpc43xx.c | 8 ++--- tests/lpc175x_6x/test/test_dcd_lpc175x_6x.c | 8 ++--- tests/lpc18xx_43xx/test/host/cdc/test_cdc_host.c | 2 +- .../test/host/ehci/test_pipe_bulk_open.c | 2 +- .../test/host/ehci/test_pipe_bulk_xfer.c | 4 +-- .../test/host/ehci/test_pipe_control_open.c | 2 +- .../test/host/ehci/test_pipe_control_xfer.c | 4 +-- .../test/host/ehci/test_pipe_interrupt_open.c | 4 +-- .../test/host/ehci/test_pipe_interrupt_xfer.c | 4 +-- .../test/host/ehci/test_pipe_isochronous_open.c | 2 +- .../test/host/hid/test_hidh_keyboard.c | 2 +- tests/lpc18xx_43xx/test/host/hid/test_hidh_mouse.c | 2 +- tests/lpc18xx_43xx/test/host/usbh/test_enum_task.c | 2 +- tests/support/ehci_controller_fake.c | 4 +-- tests/support/type_helper.h | 4 +-- 39 files changed, 83 insertions(+), 111 deletions(-) (limited to 'src/host') diff --git a/examples/obsolete/device/src/mouse_device_app.c b/examples/obsolete/device/src/mouse_device_app.c index d6145026a..077cecc7c 100644 --- a/examples/obsolete/device/src/mouse_device_app.c +++ b/examples/obsolete/device/src/mouse_device_app.c @@ -126,7 +126,7 @@ void mouse_app_subtask(void) enum { MOUSE_RESOLUTION = 5 }; uint32_t button_mask = board_buttons(); - memclr_(&mouse_report, sizeof(hid_mouse_report_t)); + tu_memclr(&mouse_report, sizeof(hid_mouse_report_t)); if ( BIT_TEST_(button_mask, BUTTON_UP ) ) mouse_report.y = -MOUSE_RESOLUTION; if ( BIT_TEST_(button_mask, BUTTON_DOWN ) ) mouse_report.y = MOUSE_RESOLUTION; diff --git a/examples/obsolete/host/src/cdc_serial_host_app.c b/examples/obsolete/host/src/cdc_serial_host_app.c index e21a3a67d..30ed6698e 100644 --- a/examples/obsolete/host/src/cdc_serial_host_app.c +++ b/examples/obsolete/host/src/cdc_serial_host_app.c @@ -61,8 +61,8 @@ void tuh_cdc_mounted_cb(uint8_t dev_addr) { // application set-up printf("\na CDC device (address %d) is mounted\n", dev_addr); - memclr_(serial_in_buffer, sizeof(serial_in_buffer)); - memclr_(serial_out_buffer, sizeof(serial_out_buffer)); + tu_memclr(serial_in_buffer, sizeof(serial_in_buffer)); + tu_memclr(serial_out_buffer, sizeof(serial_out_buffer)); received_bytes = 0; osal_semaphore_reset(sem_hdl); diff --git a/examples/obsolete/host/src/keyboard_host_app.c b/examples/obsolete/host/src/keyboard_host_app.c index 26b1a0800..21ace3bbf 100644 --- a/examples/obsolete/host/src/keyboard_host_app.c +++ b/examples/obsolete/host/src/keyboard_host_app.c @@ -100,7 +100,7 @@ void tuh_hid_keyboard_isr(uint8_t dev_addr, tusb_event_t event) //--------------------------------------------------------------------+ void keyboard_host_app_init(void) { - memclr_(&usb_keyboard_report, sizeof(hid_keyboard_report_t)); + tu_memclr(&usb_keyboard_report, sizeof(hid_keyboard_report_t)); queue_kbd_hdl = osal_queue_create( QUEUE_KEYBOARD_REPORT_DEPTH, sizeof(hid_keyboard_report_t) ); TU_ASSERT( queue_kbd_hdl, VOID_RETURN ); diff --git a/examples/obsolete/host/src/mouse_host_app.c b/examples/obsolete/host/src/mouse_host_app.c index c326becb8..e242c7caa 100644 --- a/examples/obsolete/host/src/mouse_host_app.c +++ b/examples/obsolete/host/src/mouse_host_app.c @@ -101,7 +101,7 @@ void tuh_hid_mouse_isr(uint8_t dev_addr, tusb_event_t event) //--------------------------------------------------------------------+ void mouse_host_app_init(void) { - memclr_(&usb_mouse_report, sizeof(hid_mouse_report_t)); + tu_memclr(&usb_mouse_report, sizeof(hid_mouse_report_t)); queue_mouse_hdl = osal_queue_create( QUEUE_MOUSE_REPORT_DEPTH, sizeof(hid_mouse_report_t) ); TU_ASSERT( queue_mouse_hdl, VOID_RETURN); diff --git a/examples/obsolete/host/src/msc_cli.c b/examples/obsolete/host/src/msc_cli.c index 0182a6df9..1f7b1f5ec 100644 --- a/examples/obsolete/host/src/msc_cli.c +++ b/examples/obsolete/host/src/msc_cli.c @@ -176,12 +176,12 @@ void cli_command_prompt(void) (volume_label[0] !=0) ? volume_label : "No Label", cli_buffer); - memclr_(cli_buffer, CLI_MAX_BUFFER); + tu_memclr(cli_buffer, CLI_MAX_BUFFER); } void cli_init(void) { - memclr_(cli_buffer, CLI_MAX_BUFFER); + tu_memclr(cli_buffer, CLI_MAX_BUFFER); f_getlabel(NULL, volume_label, NULL); cli_command_prompt(); } @@ -197,7 +197,7 @@ void cli_poll(char ch) }else { puts("cli buffer overflows"); - memclr_(cli_buffer, CLI_MAX_BUFFER); + tu_memclr(cli_buffer, CLI_MAX_BUFFER); } } else if ( ch == ASCII_BACKSPACE && strlen(cli_buffer)) diff --git a/src/class/cdc/cdc_device.c b/src/class/cdc/cdc_device.c index 70d51c258..06530bc7a 100644 --- a/src/class/cdc/cdc_device.c +++ b/src/class/cdc/cdc_device.c @@ -185,7 +185,7 @@ bool tud_cdc_n_write_flush (uint8_t itf) //--------------------------------------------------------------------+ void cdcd_init(void) { - arrclr_( _cdcd_itf ); + tu_memclr(_cdcd_itf, sizeof(_cdcd_itf)); for(uint8_t i=0; ipipe_in); (void) hcd_pipe_close(p_cdc->pipe_out); - memclr_(p_cdc, sizeof(cdch_data_t)); + tu_memclr(p_cdc, sizeof(cdch_data_t)); tuh_cdc_unmounted_cb(dev_addr); diff --git a/src/class/cdc/cdc_rndis_host.c b/src/class/cdc/cdc_rndis_host.c index 4d28b0e0c..9b7684f77 100644 --- a/src/class/cdc/cdc_rndis_host.c +++ b/src/class/cdc/cdc_rndis_host.c @@ -117,7 +117,7 @@ static tusb_error_t rndis_body_subtask(void) //--------------------------------------------------------------------+ void rndish_init(void) { - memclr_(rndish_data, sizeof(rndish_data_t)*CFG_TUSB_HOST_DEVICE_MAX); + tu_memclr(rndish_data, sizeof(rndish_data_t)*CFG_TUSB_HOST_DEVICE_MAX); //------------- Task creation -------------// @@ -131,7 +131,7 @@ void rndish_init(void) void rndish_close(uint8_t dev_addr) { osal_semaphore_reset( rndish_data[dev_addr-1].sem_notification_hdl ); -// memclr_(&rndish_data[dev_addr-1], sizeof(rndish_data_t)); TODO need to move semaphore & its handle out before memclr +// tu_memclr(&rndish_data[dev_addr-1], sizeof(rndish_data_t)); TODO need to move semaphore & its handle out before memclr } @@ -189,7 +189,7 @@ tusb_error_t rndish_open_subtask(uint8_t dev_addr, cdch_data_t *p_cdc) //------------- Message Query 802.3 Permanent Address -------------// memcpy(msg_payload, &msg_query_permanent_addr, sizeof(rndis_msg_query_t)); - memclr_(msg_payload + sizeof(rndis_msg_query_t), 6); // 6 bytes for MAC address + tu_memclr(msg_payload + sizeof(rndis_msg_query_t), 6); // 6 bytes for MAC address STASK_INVOKE( send_message_get_response_subtask( dev_addr, p_cdc, @@ -205,7 +205,7 @@ tusb_error_t rndish_open_subtask(uint8_t dev_addr, cdch_data_t *p_cdc) //------------- Set OID_GEN_CURRENT_PACKET_FILTER to (DIRECTED | MULTICAST | BROADCAST) -------------// memcpy(msg_payload, &msg_set_packet_filter, sizeof(rndis_msg_set_t)); - memclr_(msg_payload + sizeof(rndis_msg_set_t), 4); // 4 bytes for filter flags + tu_memclr(msg_payload + sizeof(rndis_msg_set_t), 4); // 4 bytes for filter flags ((rndis_msg_set_t*) msg_payload)->oid_buffer[0] = (RNDIS_PACKET_TYPE_DIRECTED | RNDIS_PACKET_TYPE_MULTICAST | RNDIS_PACKET_TYPE_BROADCAST); STASK_INVOKE( diff --git a/src/class/custom/custom_device.c b/src/class/custom/custom_device.c index 2c3783e35..d43a86b14 100644 --- a/src/class/custom/custom_device.c +++ b/src/class/custom/custom_device.c @@ -68,7 +68,7 @@ static cusd_interface_t _cusd_itf; *------------------------------------------------------------------*/ void cusd_init(void) { - varclr_(&_cusd_itf); + tu_varclr(&_cusd_itf); } tusb_error_t cusd_open(uint8_t rhport, tusb_desc_interface_t const * p_desc_itf, uint16_t *p_len) diff --git a/src/class/custom/custom_host.c b/src/class/custom/custom_host.c index ad3315980..329012fda 100644 --- a/src/class/custom/custom_host.c +++ b/src/class/custom/custom_host.c @@ -104,7 +104,7 @@ tusb_error_t tusbh_custom_write(uint8_t dev_addr, uint16_t vendor_id, uint16_t p //--------------------------------------------------------------------+ void cush_init(void) { - memclr_(&custom_interface, sizeof(custom_interface_info_t) * CFG_TUSB_HOST_DEVICE_MAX); + tu_memclr(&custom_interface, sizeof(custom_interface_info_t) * CFG_TUSB_HOST_DEVICE_MAX); } tusb_error_t cush_open_subtask(uint8_t dev_addr, tusb_desc_interface_t const *p_interface_desc, uint16_t *p_length) @@ -152,7 +152,7 @@ void cush_close(uint8_t dev_addr) err2 = hcd_pipe_close( p_interface->pipe_out ); } - memclr_(p_interface, sizeof(custom_interface_info_t)); + tu_memclr(p_interface, sizeof(custom_interface_info_t)); TU_ASSERT(err1 == TUSB_ERROR_NONE && err2 == TUSB_ERROR_NONE, (void) 0 ); } diff --git a/src/class/hid/hid_device.c b/src/class/hid/hid_device.c index b1cd1d1bd..d8696f137 100644 --- a/src/class/hid/hid_device.c +++ b/src/class/hid/hid_device.c @@ -188,7 +188,7 @@ bool tud_hid_keyboard_keycode(uint8_t modifier, uint8_t keycode[6]) memcpy(report.keycode, keycode, 6); }else { - memclr_(report.keycode, 6); + tu_memclr(report.keycode, 6); } return hidd_kbd_report(&report); @@ -307,14 +307,14 @@ void hidd_init(void) void hidd_reset(uint8_t rhport) { - arrclr_(_hidd_itf); + tu_memclr(_hidd_itf, sizeof(_hidd_itf)); #if CFG_TUD_HID_KEYBOARD - varclr_(&_kbd_rpt); + tu_varclr(&_kbd_rpt); #endif #if CFG_TUD_HID_MOUSE - varclr_(&_mse_rpt); + tu_varclr(&_mse_rpt); #endif } diff --git a/src/class/hid/hid_host.c b/src/class/hid/hid_host.c index 369dad638..518297eec 100644 --- a/src/class/hid/hid_host.c +++ b/src/class/hid/hid_host.c @@ -68,7 +68,7 @@ static inline tusb_error_t hidh_interface_open(uint8_t dev_addr, uint8_t interfa static inline void hidh_interface_close(hidh_interface_info_t *p_hid) { (void) hcd_pipe_close(p_hid->pipe_hdl); - memclr_(p_hid, sizeof(hidh_interface_info_t)); + tu_memclr(p_hid, sizeof(hidh_interface_info_t)); } // called from public API need to validate parameters @@ -164,11 +164,11 @@ tusb_error_t tuh_hid_mouse_get_report(uint8_t dev_addr, void * report) void hidh_init(void) { #if CFG_TUSB_HOST_HID_KEYBOARD - memclr_(&keyboardh_data, sizeof(hidh_interface_info_t)*CFG_TUSB_HOST_DEVICE_MAX); + tu_memclr(&keyboardh_data, sizeof(hidh_interface_info_t)*CFG_TUSB_HOST_DEVICE_MAX); #endif #if CFG_TUSB_HOST_HID_MOUSE - memclr_(&mouseh_data, sizeof(hidh_interface_info_t)*CFG_TUSB_HOST_DEVICE_MAX); + tu_memclr(&mouseh_data, sizeof(hidh_interface_info_t)*CFG_TUSB_HOST_DEVICE_MAX); #endif #if CFG_TUSB_HOST_HID_GENERIC diff --git a/src/class/msc/msc_device.c b/src/class/msc/msc_device.c index 3335ad9b3..830ce85b7 100644 --- a/src/class/msc/msc_device.c +++ b/src/class/msc/msc_device.c @@ -62,9 +62,9 @@ enum typedef struct { CFG_TUSB_MEM_ALIGN msc_cbw_t cbw; -#if defined (__ICCARM__) && (CFG_TUSB_MCU == OPT_MCU_LPC11UXX || CFG_TUSB_MCU == OPT_MCU_LPC13UXX) - uint8_t padding1[64-sizeof(msc_cbw_t)]; // IAR cannot align struct's member -#endif +//#if defined (__ICCARM__) && (CFG_TUSB_MCU == OPT_MCU_LPC11UXX || CFG_TUSB_MCU == OPT_MCU_LPC13UXX) +// uint8_t padding1[64-sizeof(msc_cbw_t)]; // IAR cannot align struct's member +//#endif CFG_TUSB_MEM_ALIGN msc_csw_t csw; @@ -141,12 +141,12 @@ bool tud_msc_set_sense(uint8_t lun, uint8_t sense_key, uint8_t add_sense_code, u //--------------------------------------------------------------------+ void mscd_init(void) { - memclr_(&_mscd_itf, sizeof(mscd_interface_t)); + tu_memclr(&_mscd_itf, sizeof(mscd_interface_t)); } void mscd_reset(uint8_t rhport) { - memclr_(&_mscd_itf, sizeof(mscd_interface_t)); + tu_memclr(&_mscd_itf, sizeof(mscd_interface_t)); } tusb_error_t mscd_open(uint8_t rhport, tusb_desc_interface_t const * p_desc_itf, uint16_t *p_len) @@ -302,7 +302,6 @@ tusb_error_t mscd_xfer_cb(uint8_t rhport, uint8_t ep_addr, tusb_event_t event, u { case MSC_STAGE_CMD: //------------- new CBW received -------------// - // Complete IN while waiting for CMD is usually Status of previous SCSI op, ignore it if(ep_addr != p_msc->ep_out) return TUSB_ERROR_NONE; @@ -332,7 +331,6 @@ tusb_error_t mscd_xfer_cb(uint8_t rhport, uint8_t ep_addr, tusb_event_t event, u // 1. Zero : Invoke app callback, skip DATA and move to STATUS stage // 2. OUT : queue transfer (invoke app callback after done) // 3. IN : invoke app callback to get response - if ( p_cbw->xfer_bytes == 0) { int32_t const cb_result = tud_msc_scsi_cb(p_cbw->lun, p_cbw->command, NULL, 0); diff --git a/src/class/msc/msc_host.c b/src/class/msc/msc_host.c index 7e6396389..9250b8df7 100644 --- a/src/class/msc/msc_host.c +++ b/src/class/msc/msc_host.c @@ -288,7 +288,7 @@ tusb_error_t tuh_msc_write10(uint8_t dev_addr, uint8_t lun, void const * p_buffe //--------------------------------------------------------------------+ void msch_init(void) { - memclr_(msch_data, sizeof(msch_interface_t)*CFG_TUSB_HOST_DEVICE_MAX); + tu_memclr(msch_data, sizeof(msch_interface_t)*CFG_TUSB_HOST_DEVICE_MAX); msch_sem_hdl = osal_semaphore_create(1, 0); } @@ -416,7 +416,7 @@ void msch_close(uint8_t dev_addr) (void) hcd_pipe_close(msch_data[dev_addr-1].bulk_in); (void) hcd_pipe_close(msch_data[dev_addr-1].bulk_out); - memclr_(&msch_data[dev_addr-1], sizeof(msch_interface_t)); + tu_memclr(&msch_data[dev_addr-1], sizeof(msch_interface_t)); osal_semaphore_reset(msch_sem_hdl); tuh_msc_unmounted_cb(dev_addr); // invoke Application Callback diff --git a/src/common/tusb_common.h b/src/common/tusb_common.h index 778e70676..85bd15d43 100644 --- a/src/common/tusb_common.h +++ b/src/common/tusb_common.h @@ -73,8 +73,7 @@ //--------------------------------------------------------------------+ // MACROS //--------------------------------------------------------------------+ -#define MAX_OF(a, b) ( (a) > (b) ? (a) : (b) ) -#define MIN_OF(a, b) ( (a) < (b) ? (a) : (b) ) +#define TU_ARRAY_SZIE(_arr) ( sizeof(_arr) / sizeof(_arr[0]) ) #define U16_HIGH_U8(u16) ((uint8_t) (((u16) >> 8) & 0x00ff)) #define U16_LOW_U8(u16) ((uint8_t) ((u16) & 0x00ff)) @@ -137,12 +136,10 @@ //--------------------------------------------------------------------+ // INLINE FUNCTION //--------------------------------------------------------------------+ -#define memclr_(buffer, size) memset((buffer), 0, (size)) -#define varclr_(_var) memclr_(_var, sizeof(*(_var))) -#define arrclr_(_arr) memclr_(_arr, sizeof(_arr)) -#define arrcount_(_arr) ( sizeof(_arr) / sizeof(_arr[0]) ) +#define tu_memclr(buffer, size) memset((buffer), 0, (size)) +#define tu_varclr(_var) tu_memclr(_var, sizeof(*(_var))) -static inline bool mem_all_zero(void const* buffer, uint32_t size) +static inline bool tu_mem_test_zero (void const* buffer, uint32_t size) { uint8_t const* p_mem = (uint8_t const*) buffer; for(uint32_t i=0; i y) ? x : y; } -static inline uint16_t tu_max16(uint16_t x, uint16_t y) -{ - return (x > y) ? x : y; -} - //------------- Align -------------// static inline uint32_t tu_align32 (uint32_t value) { @@ -249,24 +241,6 @@ static inline uint8_t tu_log2(uint32_t value) return result; } -// return the number of set bits in value -static inline uint8_t tu_cardof(uint32_t value) -{ - // Brian Kernighan's method goes through as many iterations as there are set bits. So if we have a 32-bit word with only - // the high bit set, then it will only go once through the loop - // Published in 1988, the C Programming Language 2nd Ed. (by Brian W. Kernighan and Dennis M. Ritchie) - // mentions this in exercise 2-9. On April 19, 2006 Don Knuth pointed out to me that this method - // "was first published by Peter Wegner in CACM 3 (1960), 322. (Also discovered independently by Derrick Lehmer and - // published in 1964 in a book edited by Beckenbach.)" - uint8_t count; - for (count = 0; value; count++) - { - value &= value - 1; // clear the least significant bit set - } - - return count; -} - #ifdef __cplusplus } #endif diff --git a/src/device/usbd.c b/src/device/usbd.c index 89dd4b722..146f8ec89 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -274,7 +274,7 @@ static tusb_error_t usbd_main_st(void) tusb_error_t err; err = TUSB_ERROR_NONE; - memclr_(&event, sizeof(usbd_task_event_t)); + tu_memclr(&event, sizeof(usbd_task_event_t)); osal_queue_receive(_usbd_q, &event, OSAL_TIMEOUT_WAIT_FOREVER, &err); @@ -318,7 +318,7 @@ static tusb_error_t usbd_main_st(void) static void usbd_reset(uint8_t rhport) { - varclr_(&_usbd_dev); + tu_varclr(&_usbd_dev); memset(_usbd_dev.itf2drv, 0xff, sizeof(_usbd_dev.itf2drv)); // invalid mapping memset(_usbd_dev.ep2drv , 0xff, sizeof(_usbd_dev.ep2drv )); // invalid mapping diff --git a/src/host/ehci/ehci.c b/src/host/ehci/ehci.c index 84821e3f5..99e7fdb65 100644 --- a/src/host/ehci/ehci.c +++ b/src/host/ehci/ehci.c @@ -130,7 +130,7 @@ static tusb_error_t hcd_controller_stop(uint8_t hostid) ATTR_WARN_UNUSED_RESULT tusb_error_t hcd_init(void) { //------------- Data Structure init -------------// - memclr_(&ehci_data, sizeof(ehci_data_t)); + tu_memclr(&ehci_data, sizeof(ehci_data_t)); #if (CFG_TUSB_RHPORT0_MODE & OPT_MODE_HOST) TU_ASSERT_ERR (hcd_controller_init(0)); @@ -192,7 +192,7 @@ static tusb_error_t hcd_controller_init(uint8_t hostid) //------------- Asynchronous List -------------// ehci_qhd_t * const async_head = get_async_head(hostid); - memclr_(async_head, sizeof(ehci_qhd_t)); + tu_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; @@ -938,7 +938,7 @@ static void qhd_init(ehci_qhd_t *p_qhd, uint8_t dev_addr, uint16_t max_packet_si // address 0 is used as async head, which always on the list --> cannot be cleared (ehci halted otherwise) if (dev_addr != 0) { - memclr_(p_qhd, sizeof(ehci_qhd_t)); + tu_memclr(p_qhd, sizeof(ehci_qhd_t)); } p_qhd->device_address = dev_addr; @@ -1004,7 +1004,7 @@ static void qhd_init(ehci_qhd_t *p_qhd, uint8_t dev_addr, uint16_t max_packet_si static void qtd_init(ehci_qtd_t* p_qtd, uint32_t data_ptr, uint16_t total_bytes) { - memclr_(p_qtd, sizeof(ehci_qtd_t)); + tu_memclr(p_qtd, sizeof(ehci_qtd_t)); p_qtd->used = 1; diff --git a/src/host/hub.c b/src/host/hub.c index 063cef61a..624e43563 100644 --- a/src/host/hub.c +++ b/src/host/hub.c @@ -152,7 +152,7 @@ tusb_speed_t hub_port_get_speed(void) //--------------------------------------------------------------------+ void hub_init(void) { - memclr_(hub_data, CFG_TUSB_HOST_DEVICE_MAX*sizeof(usbh_hub_t)); + tu_memclr(hub_data, CFG_TUSB_HOST_DEVICE_MAX*sizeof(usbh_hub_t)); // hub_enum_sem_hdl = osal_semaphore_create( OSAL_SEM_REF(hub_enum_semaphore) ); } @@ -237,7 +237,7 @@ void hub_isr(pipe_handle_t pipe_hdl, tusb_event_t event, uint32_t xferred_bytes) void hub_close(uint8_t dev_addr) { (void) hcd_pipe_close(hub_data[dev_addr-1].pipe_status); - memclr_(&hub_data[dev_addr-1], sizeof(usbh_hub_t)); + tu_memclr(&hub_data[dev_addr-1], sizeof(usbh_hub_t)); // osal_semaphore_reset(hub_enum_sem_hdl); } diff --git a/src/host/ohci/ohci.c b/src/host/ohci/ohci.c index 1c9f3f293..b9183a025 100644 --- a/src/host/ohci/ohci.c +++ b/src/host/ohci/ohci.c @@ -164,7 +164,7 @@ static ohci_ed_t * ed_list_find_previous(ohci_ed_t const * p_head, ohci_ed_t con tusb_error_t hcd_init(void) { //------------- Data Structure init -------------// - memclr_(&ohci_data, sizeof(ohci_data_t)); + tu_memclr(&ohci_data, sizeof(ohci_data_t)); for(uint8_t i=0; i<32; i++) { // assign all interrupt pointes to period head ed ohci_data.hcca.interrupt_table[i] = (uint32_t) &ohci_data.period_head_ed; @@ -245,7 +245,7 @@ static void ed_init(ohci_ed_t *p_ed, uint8_t dev_addr, uint16_t max_packet_size, // address 0 is used as async head, which always on the list --> cannot be cleared if (dev_addr != 0) { - memclr_(p_ed, sizeof(ohci_ed_t)); + tu_memclr(p_ed, sizeof(ohci_ed_t)); } p_ed->device_address = dev_addr; @@ -261,7 +261,7 @@ static void ed_init(ohci_ed_t *p_ed, uint8_t dev_addr, uint16_t max_packet_size, static void gtd_init(ohci_gtd_t* p_td, void* data_ptr, uint16_t total_bytes) { - memclr_(p_td, sizeof(ohci_gtd_t)); + tu_memclr(p_td, sizeof(ohci_gtd_t)); p_td->used = 1; p_td->expected_bytes = total_bytes; diff --git a/src/host/usbh.c b/src/host/usbh.c index 8b858b2de..b849de9b9 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -142,7 +142,7 @@ uint32_t tuh_device_get_mounted_class_flag(uint8_t dev_addr) //--------------------------------------------------------------------+ tusb_error_t usbh_init(void) { - memclr_(usbh_devices, sizeof(usbh_device_info_t)*(CFG_TUSB_HOST_DEVICE_MAX+1)); + tu_memclr(usbh_devices, sizeof(usbh_device_info_t)*(CFG_TUSB_HOST_DEVICE_MAX+1)); TU_ASSERT_ERR( hcd_init() ); diff --git a/src/osal/osal_mynewt.h b/src/osal/osal_mynewt.h index db65ac553..59cd1b821 100644 --- a/src/osal/osal_mynewt.h +++ b/src/osal/osal_mynewt.h @@ -145,7 +145,7 @@ static inline bool osal_queue_send(osal_queue_t const queue_hdl, void const * da os_memblock_put(&queue_hdl->mpool, ptr); return false; } - memclr_(ev, sizeof(struct os_event)); + tu_memclr(ev, sizeof(struct os_event)); ev->ev_arg = ptr; os_eventq_put(&queue_hdl->evq, ev); diff --git a/src/portable/nordic/nrf5x/dcd_nrf5x.c b/src/portable/nordic/nrf5x/dcd_nrf5x.c index 01926c76e..371c291a3 100644 --- a/src/portable/nordic/nrf5x/dcd_nrf5x.c +++ b/src/portable/nordic/nrf5x/dcd_nrf5x.c @@ -108,7 +108,7 @@ void bus_reset(void) NRF_USBD->TASKS_STARTISOIN = 0; NRF_USBD->TASKS_STARTISOOUT = 0; - varclr_(&_dcd); + tu_varclr(&_dcd); } /*------------------------------------------------------------------*/ diff --git a/src/portable/nxp/lpc11xx_lpc13xx/dcd_lpc_11uxx_13uxx.c b/src/portable/nxp/lpc11xx_lpc13xx/dcd_lpc_11uxx_13uxx.c index 292d1fa6d..8e5a4d1aa 100644 --- a/src/portable/nxp/lpc11xx_lpc13xx/dcd_lpc_11uxx_13uxx.c +++ b/src/portable/nxp/lpc11xx_lpc13xx/dcd_lpc_11uxx_13uxx.c @@ -201,7 +201,7 @@ bool dcd_init(uint8_t rhport) static void bus_reset(void) { - memclr_(&dcd_data, sizeof(dcd_11u_13u_data_t)); + tu_memclr(&dcd_data, sizeof(dcd_11u_13u_data_t)); for(uint8_t ep_id = 2; ep_id < DCD_11U_13U_QHD_COUNT; ep_id++) { // disable all non-control endpoints on bus reset dcd_data.qhd[ep_id][0].disable = dcd_data.qhd[ep_id][1].disable = 1; @@ -473,7 +473,7 @@ edpt_hdl_t dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint TU_ASSERT( dcd_data.qhd[ep_id][0].disable && dcd_data.qhd[ep_id][1].disable, null_handle ); // endpoint must not previously opened, normally this means running out of endpoints - memclr_(dcd_data.qhd[ep_id], 2*sizeof(dcd_11u_13u_qhd_t)); + tu_memclr(dcd_data.qhd[ep_id], 2*sizeof(dcd_11u_13u_qhd_t)); dcd_data.qhd[ep_id][0].is_isochronous = dcd_data.qhd[ep_id][1].is_isochronous = (p_endpoint_desc->bmAttributes.xfer == TUSB_XFER_ISOCHRONOUS); dcd_data.class_code[ep_id] = class_code; diff --git a/src/portable/nxp/lpc17xx/dcd_lpc175x_6x.c b/src/portable/nxp/lpc17xx/dcd_lpc175x_6x.c index 4d3687830..189521d25 100644 --- a/src/portable/nxp/lpc17xx/dcd_lpc175x_6x.c +++ b/src/portable/nxp/lpc17xx/dcd_lpc175x_6x.c @@ -119,7 +119,7 @@ static void bus_reset(void) LPC_USB->USBNDDRIntClr = 0xFFFFFFFF; LPC_USB->USBSysErrIntClr = 0xFFFFFFFF; - memclr_(&dcd_data, sizeof(dcd_data_t)); + tu_memclr(&dcd_data, sizeof(dcd_data_t)); } bool dcd_init(uint8_t rhport) @@ -432,7 +432,7 @@ edpt_hdl_t dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint //------------- first DD prepare -------------// dcd_dma_descriptor_t* const p_dd = &dcd_data.dd[ep_id][0]; - memclr_(p_dd, sizeof(dcd_dma_descriptor_t)); + tu_memclr(p_dd, sizeof(dcd_dma_descriptor_t)); p_dd->is_isochronous = (p_endpoint_desc->bmAttributes.xfer == TUSB_XFER_ISOCHRONOUS) ? 1 : 0; p_dd->max_packet_size = p_endpoint_desc->wMaxPacketSize.size; @@ -498,7 +498,7 @@ tusb_error_t dcd_edpt_xfer(edpt_hdl_t edpt_hdl, uint8_t* buffer, uint16_t total_ { // setup new dd dcd_dma_descriptor_t* const p_dd = &dcd_data.dd[ edpt_hdl.index ][1]; - memclr_(p_dd, sizeof(dcd_dma_descriptor_t)); + tu_memclr(p_dd, sizeof(dcd_dma_descriptor_t)); dd_xfer_init(p_dd, buffer, total_bytes); diff --git a/src/portable/nxp/lpc43xx_lpc18xx/dcd_lpc43xx.c b/src/portable/nxp/lpc43xx_lpc18xx/dcd_lpc43xx.c index 7368542b8..5a7d61004 100644 --- a/src/portable/nxp/lpc43xx_lpc18xx/dcd_lpc43xx.c +++ b/src/portable/nxp/lpc43xx_lpc18xx/dcd_lpc43xx.c @@ -133,7 +133,7 @@ static void bus_reset(uint8_t rhport) //------------- Queue Head & Queue TD -------------// dcd_data_t* p_dcd = dcd_data_ptr[rhport]; - memclr_(p_dcd, sizeof(dcd_data_t)); + tu_memclr(p_dcd, sizeof(dcd_data_t)); //------------- Set up Control Endpoints (0 OUT, 1 IN) -------------// p_dcd->qhd[0].zero_length_termination = p_dcd->qhd[1].zero_length_termination = 1; @@ -149,7 +149,7 @@ bool dcd_init(uint8_t rhport) LPC_USB0_Type* const lpc_usb = LPC_USB[rhport]; dcd_data_t* p_dcd = dcd_data_ptr[rhport]; - memclr_(p_dcd, sizeof(dcd_data_t)); + tu_memclr(p_dcd, sizeof(dcd_data_t)); lpc_usb->ENDPOINTLISTADDR = (uint32_t) p_dcd->qhd; // Endpoint List Address has to be 2K alignment lpc_usb->USBSTS_D = lpc_usb->USBSTS_D; @@ -196,7 +196,7 @@ static inline uint8_t edpt_phy2log(uint8_t physical_endpoint) static void qtd_init(dcd_qtd_t* p_qtd, void * data_ptr, uint16_t total_bytes) { - memclr_(p_qtd, sizeof(dcd_qtd_t)); + tu_memclr(p_qtd, sizeof(dcd_qtd_t)); p_qtd->used = 1; @@ -303,7 +303,7 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc) uint8_t ep_idx = edpt_addr2phy(p_endpoint_desc->bEndpointAddress); dcd_qhd_t * p_qhd = &dcd_data_ptr[rhport]->qhd[ep_idx]; - memclr_(p_qhd, sizeof(dcd_qhd_t)); + tu_memclr(p_qhd, sizeof(dcd_qhd_t)); p_qhd->zero_length_termination = 1; p_qhd->max_package_size = p_endpoint_desc->wMaxPacketSize.size; diff --git a/tests/lpc175x_6x/test/test_dcd_lpc175x_6x.c b/tests/lpc175x_6x/test/test_dcd_lpc175x_6x.c index ef084fc77..31baa5f5c 100644 --- a/tests/lpc175x_6x/test/test_dcd_lpc175x_6x.c +++ b/tests/lpc175x_6x/test/test_dcd_lpc175x_6x.c @@ -51,9 +51,9 @@ extern dcd_dma_descriptor_t dcd_dd[DCD_MAX_DD]; void setUp(void) { - memclr_(dcd_udca, 32*4); - memclr_(dcd_dd, sizeof(dcd_dma_descriptor_t)*DCD_MAX_DD); - memclr_(&lpc_usb, sizeof(LPC_USB_TypeDef)); + tu_memclr(dcd_udca, 32*4); + tu_memclr(dcd_dd, sizeof(dcd_dma_descriptor_t)*DCD_MAX_DD); + tu_memclr(&lpc_usb, sizeof(LPC_USB_TypeDef)); } void tearDown(void) @@ -129,7 +129,7 @@ void test_dcd_configure_endpoint_in(void) }; dcd_init(); - memclr_(&lpc_usb, sizeof(LPC_USB_TypeDef)); // clear to examine register after CUT + tu_memclr(&lpc_usb, sizeof(LPC_USB_TypeDef)); // clear to examine register after CUT //------------- Code Under Test -------------// dcd_pipe_open(0, &desc_endpoint); diff --git a/tests/lpc18xx_43xx/test/host/cdc/test_cdc_host.c b/tests/lpc18xx_43xx/test/host/cdc/test_cdc_host.c index a74270e8b..5077eea93 100644 --- a/tests/lpc18xx_43xx/test/host/cdc/test_cdc_host.c +++ b/tests/lpc18xx_43xx/test/host/cdc/test_cdc_host.c @@ -71,7 +71,7 @@ void setUp(void) length = 0; dev_addr = 1; - memclr_(cdch_data, sizeof(cdch_data_t)*CFG_TUSB_HOST_DEVICE_MAX); + tu_memclr(cdch_data, sizeof(cdch_data_t)*CFG_TUSB_HOST_DEVICE_MAX); } void tearDown(void) diff --git a/tests/lpc18xx_43xx/test/host/ehci/test_pipe_bulk_open.c b/tests/lpc18xx_43xx/test/host/ehci/test_pipe_bulk_open.c index a26b990d3..581488d7d 100644 --- a/tests/lpc18xx_43xx/test/host/ehci/test_pipe_bulk_open.c +++ b/tests/lpc18xx_43xx/test/host/ehci/test_pipe_bulk_open.c @@ -70,7 +70,7 @@ void setUp(void) dev_addr = 1; hostid = RANDOM(CONTROLLER_HOST_NUMBER) + TEST_CONTROLLER_HOST_START_INDEX; - memclr_(usbh_devices, sizeof(usbh_device_info_t)*(CFG_TUSB_HOST_DEVICE_MAX+1)); + tu_memclr(usbh_devices, sizeof(usbh_device_info_t)*(CFG_TUSB_HOST_DEVICE_MAX+1)); helper_usbh_device_emulate(dev_addr, hub_addr, hub_port, hostid, TUSB_SPEED_HIGH); async_head = get_async_head( hostid ); diff --git a/tests/lpc18xx_43xx/test/host/ehci/test_pipe_bulk_xfer.c b/tests/lpc18xx_43xx/test/host/ehci/test_pipe_bulk_xfer.c index a52c721fe..2e9e29fdc 100644 --- a/tests/lpc18xx_43xx/test/host/ehci/test_pipe_bulk_xfer.c +++ b/tests/lpc18xx_43xx/test/host/ehci/test_pipe_bulk_xfer.c @@ -90,8 +90,8 @@ tusb_desc_endpoint_t const desc_ept_bulk_out = void setUp(void) { ehci_controller_init(); - memclr_(xfer_data, sizeof(xfer_data)); - memclr_(usbh_devices, sizeof(usbh_device_info_t)*(CFG_TUSB_HOST_DEVICE_MAX+1)); + tu_memclr(xfer_data, sizeof(xfer_data)); + tu_memclr(usbh_devices, sizeof(usbh_device_info_t)*(CFG_TUSB_HOST_DEVICE_MAX+1)); TEST_ASSERT_STATUS( hcd_init() ); diff --git a/tests/lpc18xx_43xx/test/host/ehci/test_pipe_control_open.c b/tests/lpc18xx_43xx/test/host/ehci/test_pipe_control_open.c index 22cbf7569..426fed9f2 100644 --- a/tests/lpc18xx_43xx/test/host/ehci/test_pipe_control_open.c +++ b/tests/lpc18xx_43xx/test/host/ehci/test_pipe_control_open.c @@ -67,7 +67,7 @@ static ehci_qhd_t *p_control_qhd; //--------------------------------------------------------------------+ void setUp(void) { - memclr_(usbh_devices, sizeof(usbh_device_info_t)*(CFG_TUSB_HOST_DEVICE_MAX+1)); + tu_memclr(usbh_devices, sizeof(usbh_device_info_t)*(CFG_TUSB_HOST_DEVICE_MAX+1)); TEST_ASSERT_STATUS( hcd_init() ); diff --git a/tests/lpc18xx_43xx/test/host/ehci/test_pipe_control_xfer.c b/tests/lpc18xx_43xx/test/host/ehci/test_pipe_control_xfer.c index 286aae113..ffd7ffb67 100644 --- a/tests/lpc18xx_43xx/test/host/ehci/test_pipe_control_xfer.c +++ b/tests/lpc18xx_43xx/test/host/ehci/test_pipe_control_xfer.c @@ -74,8 +74,8 @@ void setUp(void) { ehci_controller_init(); - memclr_(usbh_devices, sizeof(usbh_device_info_t)*(CFG_TUSB_HOST_DEVICE_MAX+1)); - memclr_(xfer_data, sizeof(xfer_data)); + tu_memclr(usbh_devices, sizeof(usbh_device_info_t)*(CFG_TUSB_HOST_DEVICE_MAX+1)); + tu_memclr(xfer_data, sizeof(xfer_data)); TEST_ASSERT_STATUS( hcd_init() ); diff --git a/tests/lpc18xx_43xx/test/host/ehci/test_pipe_interrupt_open.c b/tests/lpc18xx_43xx/test/host/ehci/test_pipe_interrupt_open.c index f39021ef2..b243a468e 100644 --- a/tests/lpc18xx_43xx/test/host/ehci/test_pipe_interrupt_open.c +++ b/tests/lpc18xx_43xx/test/host/ehci/test_pipe_interrupt_open.c @@ -67,7 +67,7 @@ static pipe_handle_t pipe_hdl; //--------------------------------------------------------------------+ void setUp(void) { - memclr_(usbh_devices, sizeof(usbh_device_info_t)*(CFG_TUSB_HOST_DEVICE_MAX+1)); + tu_memclr(usbh_devices, sizeof(usbh_device_info_t)*(CFG_TUSB_HOST_DEVICE_MAX+1)); hcd_init(); @@ -78,7 +78,7 @@ void setUp(void) period_head_arr = get_period_head( hostid, 1 ); p_int_qhd = NULL; - memclr_(&pipe_hdl, sizeof(pipe_handle_t)); + tu_memclr(&pipe_hdl, sizeof(pipe_handle_t)); } void tearDown(void) diff --git a/tests/lpc18xx_43xx/test/host/ehci/test_pipe_interrupt_xfer.c b/tests/lpc18xx_43xx/test/host/ehci/test_pipe_interrupt_xfer.c index aeb094932..827db2897 100644 --- a/tests/lpc18xx_43xx/test/host/ehci/test_pipe_interrupt_xfer.c +++ b/tests/lpc18xx_43xx/test/host/ehci/test_pipe_interrupt_xfer.c @@ -91,8 +91,8 @@ void setUp(void) { ehci_controller_init(); - memclr_(usbh_devices, sizeof(usbh_device_info_t)*(CFG_TUSB_HOST_DEVICE_MAX+1)); - memclr_(xfer_data, sizeof(xfer_data)); + tu_memclr(usbh_devices, sizeof(usbh_device_info_t)*(CFG_TUSB_HOST_DEVICE_MAX+1)); + tu_memclr(xfer_data, sizeof(xfer_data)); TEST_ASSERT_STATUS( hcd_init() ); diff --git a/tests/lpc18xx_43xx/test/host/ehci/test_pipe_isochronous_open.c b/tests/lpc18xx_43xx/test/host/ehci/test_pipe_isochronous_open.c index 584c44471..1feff94e5 100644 --- a/tests/lpc18xx_43xx/test/host/ehci/test_pipe_isochronous_open.c +++ b/tests/lpc18xx_43xx/test/host/ehci/test_pipe_isochronous_open.c @@ -63,7 +63,7 @@ static ehci_qhd_t *period_head_arr; //--------------------------------------------------------------------+ void setUp(void) { - memclr_(usbh_devices, sizeof(usbh_device_info_t)*(CFG_TUSB_HOST_DEVICE_MAX+1)); + tu_memclr(usbh_devices, sizeof(usbh_device_info_t)*(CFG_TUSB_HOST_DEVICE_MAX+1)); hcd_init(); diff --git a/tests/lpc18xx_43xx/test/host/hid/test_hidh_keyboard.c b/tests/lpc18xx_43xx/test/host/hid/test_hidh_keyboard.c index 75c8f8a90..b3b49c172 100644 --- a/tests/lpc18xx_43xx/test/host/hid/test_hidh_keyboard.c +++ b/tests/lpc18xx_43xx/test/host/hid/test_hidh_keyboard.c @@ -73,7 +73,7 @@ tusb_desc_endpoint_t const *p_kdb_endpoint_desc = &desc_configuration.keyboard void setUp(void) { hidh_init(); - memclr_(&report, sizeof(hid_keyboard_report_t)); + tu_memclr(&report, sizeof(hid_keyboard_report_t)); dev_addr = RANDOM(CFG_TUSB_HOST_DEVICE_MAX)+1; p_hidh_kbd = &keyboardh_data[dev_addr-1]; diff --git a/tests/lpc18xx_43xx/test/host/hid/test_hidh_mouse.c b/tests/lpc18xx_43xx/test/host/hid/test_hidh_mouse.c index 741f54428..b1a3558e6 100644 --- a/tests/lpc18xx_43xx/test/host/hid/test_hidh_mouse.c +++ b/tests/lpc18xx_43xx/test/host/hid/test_hidh_mouse.c @@ -62,7 +62,7 @@ void setUp(void) { hidh_init(); - memclr_(&report, sizeof(hid_mouse_report_t)); + tu_memclr(&report, sizeof(hid_mouse_report_t)); dev_addr = RANDOM(CFG_TUSB_HOST_DEVICE_MAX)+1; p_hidh_mouse = &mouseh_data[dev_addr-1]; diff --git a/tests/lpc18xx_43xx/test/host/usbh/test_enum_task.c b/tests/lpc18xx_43xx/test/host/usbh/test_enum_task.c index 7aeba21a0..a85c3c48a 100644 --- a/tests/lpc18xx_43xx/test/host/usbh/test_enum_task.c +++ b/tests/lpc18xx_43xx/test/host/usbh/test_enum_task.c @@ -73,7 +73,7 @@ enum { void setUp(void) { - memclr_(usbh_devices, sizeof(usbh_device_info_t)*(CFG_TUSB_HOST_DEVICE_MAX+1)); + tu_memclr(usbh_devices, sizeof(usbh_device_info_t)*(CFG_TUSB_HOST_DEVICE_MAX+1)); osal_queue_receive_StubWithCallback(queue_recv_stub); osal_semaphore_wait_StubWithCallback(semaphore_wait_success_stub); diff --git a/tests/support/ehci_controller_fake.c b/tests/support/ehci_controller_fake.c index 041e1dbb5..acd40cc0b 100644 --- a/tests/support/ehci_controller_fake.c +++ b/tests/support/ehci_controller_fake.c @@ -61,8 +61,8 @@ extern usbh_device_info_t usbh_devices[CFG_TUSB_HOST_DEVICE_MAX+1]; //--------------------------------------------------------------------+ void ehci_controller_init(void) { - memclr_(&lpc_usb0, sizeof(LPC_USB0_Type)); - memclr_(&lpc_usb1, sizeof(LPC_USB1_Type)); + tu_memclr(&lpc_usb0, sizeof(LPC_USB0_Type)); + tu_memclr(&lpc_usb1, sizeof(LPC_USB1_Type)); } void ehci_controller_control_xfer_proceed(uint8_t dev_addr, uint8_t p_data[]) diff --git a/tests/support/type_helper.h b/tests/support/type_helper.h index 3e27cef2e..36502ba35 100644 --- a/tests/support/type_helper.h +++ b/tests/support/type_helper.h @@ -75,7 +75,7 @@ ({\ uint32_t value=0;\ struct_type str;\ - memclr_((void*)&str, sizeof(struct_type));\ + tu_memclr((void*)&str, sizeof(struct_type));\ str.member.bitfield_member = 1;\ memcpy(&value, (void*)&str.member, sizeof(str.member));\ tu_log2( value );\ @@ -84,7 +84,7 @@ #define BITFIELD_OFFSET_OF_UINT32(struct_type, offset, bitfield_member) \ ({\ struct_type str;\ - memclr_(&str, sizeof(struct_type));\ + tu_memclr(&str, sizeof(struct_type));\ str.bitfield_member = 1;\ tu_log2( ((uint32_t*) &str)[offset] );\ }) -- cgit v1.3.1 From bfa10016ae353779f7b94da31156ac997062322a Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 24 Oct 2018 12:37:43 +0700 Subject: rename verify_breakpoint to TU_BREAKPOINT --- src/class/msc/msc_device.c | 2 +- src/common/tusb_verify.h | 16 ++++++++-------- src/device/usbd.c | 2 +- src/host/ehci/ehci.c | 2 +- src/osal/osal_none.h | 8 ++++---- 5 files changed, 15 insertions(+), 15 deletions(-) (limited to 'src/host') diff --git a/src/class/msc/msc_device.c b/src/class/msc/msc_device.c index b050ea705..5a047b016 100644 --- a/src/class/msc/msc_device.c +++ b/src/class/msc/msc_device.c @@ -468,7 +468,7 @@ tusb_error_t mscd_xfer_cb(uint8_t rhport, uint8_t ep_addr, tusb_event_t event, u }else { // No other command take more than one transfer yet -> unlikely error - verify_breakpoint(); + TU_BREAKPOINT(); } } break; diff --git a/src/common/tusb_verify.h b/src/common/tusb_verify.h index 41c2b5be1..1cb8443bc 100644 --- a/src/common/tusb_verify.h +++ b/src/common/tusb_verify.h @@ -74,14 +74,14 @@ // Halt CPU (breakpoint) when hitting error, only apply for Cortex M3, M4, M7 #if defined(__ARM_ARCH_7M__) || defined (__ARM_ARCH_7EM__) -#define verify_breakpoint() \ +#define TU_BREAKPOINT() \ do {\ volatile uint32_t* ARM_CM_DHCSR = ((volatile uint32_t*) 0xE000EDF0UL); /* Cortex M CoreDebug->DHCSR */ \ if ( (*ARM_CM_DHCSR) & 1UL ) __asm("BKPT #0\n"); /* Only halt mcu if debugger is attached */\ } while(0) #else -#define verify_breakpoint() +#define TU_BREAKPOINT() #endif /*------------------------------------------------------------------*/ @@ -157,21 +157,21 @@ /*------------------------------------------------------------------*/ /* ASSERT - * basically TU_VERIFY with verify_breakpoint() as handler + * basically TU_VERIFY with TU_BREAKPOINT() as handler * - 1 arg : return false if failed * - 2 arg : return error if failed *------------------------------------------------------------------*/ -#define ASSERT_1ARGS(_cond) TU_VERIFY_DEFINE(_cond, _MESS_FAILED(); verify_breakpoint(), false) -#define ASSERT_2ARGS(_cond, _ret) TU_VERIFY_DEFINE(_cond, _MESS_FAILED(); verify_breakpoint(), _ret) +#define ASSERT_1ARGS(_cond) TU_VERIFY_DEFINE(_cond, _MESS_FAILED(); TU_BREAKPOINT(), false) +#define ASSERT_2ARGS(_cond, _ret) TU_VERIFY_DEFINE(_cond, _MESS_FAILED(); TU_BREAKPOINT(), _ret) #define TU_ASSERT(...) GET_3RD_ARG(__VA_ARGS__, ASSERT_2ARGS, ASSERT_1ARGS)(__VA_ARGS__) /*------------------------------------------------------------------*/ /* ASSERT Error - * basically TU_VERIFY Error with verify_breakpoint() as handler + * basically TU_VERIFY Error with TU_BREAKPOINT() as handler *------------------------------------------------------------------*/ -#define ASERT_ERR_1ARGS(_error) TU_VERIFY_ERR_DEF2(_error, verify_breakpoint()) -#define ASERT_ERR_2ARGS(_error, _ret) TU_VERIFY_ERR_DEF3(_error, verify_breakpoint(), _ret) +#define ASERT_ERR_1ARGS(_error) TU_VERIFY_ERR_DEF2(_error, TU_BREAKPOINT()) +#define ASERT_ERR_2ARGS(_error, _ret) TU_VERIFY_ERR_DEF3(_error, TU_BREAKPOINT(), _ret) #define TU_ASSERT_ERR(...) GET_3RD_ARG(__VA_ARGS__, ASERT_ERR_2ARGS, ASERT_ERR_1ARGS)(__VA_ARGS__) diff --git a/src/device/usbd.c b/src/device/usbd.c index f35671f17..1e96983b1 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -274,7 +274,7 @@ static tusb_error_t usbd_main_st(void) } else { - verify_breakpoint(); + TU_BREAKPOINT(); } } diff --git a/src/host/ehci/ehci.c b/src/host/ehci/ehci.c index 99e7fdb65..c7ff70d70 100644 --- a/src/host/ehci/ehci.c +++ b/src/host/ehci/ehci.c @@ -646,7 +646,7 @@ static void qhd_xfer_error_isr(ehci_qhd_t * p_qhd) p_qhd->total_xferred_bytes += p_qhd->p_qtd_list_head->expected_bytes - p_qhd->p_qtd_list_head->total_bytes; -// if ( TUSB_EVENT_XFER_ERROR == error_event ) verify_breakpoint(); // TODO skip unplugged device +// if ( TUSB_EVENT_XFER_ERROR == error_event ) TU_BREAKPOINT(); // TODO skip unplugged device p_qhd->p_qtd_list_head->used = 0; // free QTD qtd_remove_1st_from_qhd(p_qhd); diff --git a/src/osal/osal_none.h b/src/osal/osal_none.h index 91848f221..783e4fd2e 100644 --- a/src/osal/osal_none.h +++ b/src/osal/osal_none.h @@ -113,11 +113,11 @@ static inline bool osal_task_create(osal_task_def_t* taskdef) //------------- Sub Task Assert -------------// #define STASK_RETURN(error) do { TASK_RESTART; return error; } while(0) -#define STASK_ASSERT_ERR(_err) TU_VERIFY_ERR_HDLR(_err, verify_breakpoint(); TASK_RESTART, TUSB_ERROR_FAILED) -#define STASK_ASSERT_ERR_HDLR(_err, _func) TU_VERIFY_ERR_HDLR(_err, verify_breakpoint(); _func; TASK_RESTART, TUSB_ERROR_FAILED ) +#define STASK_ASSERT_ERR(_err) TU_VERIFY_ERR_HDLR(_err, TU_BREAKPOINT(); TASK_RESTART, TUSB_ERROR_FAILED) +#define STASK_ASSERT_ERR_HDLR(_err, _func) TU_VERIFY_ERR_HDLR(_err, TU_BREAKPOINT(); _func; TASK_RESTART, TUSB_ERROR_FAILED ) -#define STASK_ASSERT(_cond) TU_VERIFY_HDLR(_cond, verify_breakpoint(); TASK_RESTART, TUSB_ERROR_FAILED) -#define STASK_ASSERT_HDLR(_cond, _func) TU_VERIFY_HDLR(_cond, verify_breakpoint(); _func; TASK_RESTART, TUSB_ERROR_FAILED) +#define STASK_ASSERT(_cond) TU_VERIFY_HDLR(_cond, TU_BREAKPOINT(); TASK_RESTART, TUSB_ERROR_FAILED) +#define STASK_ASSERT_HDLR(_cond, _func) TU_VERIFY_HDLR(_cond, TU_BREAKPOINT(); _func; TASK_RESTART, TUSB_ERROR_FAILED) //--------------------------------------------------------------------+ // QUEUE API -- cgit v1.3.1 From 10bf41f718ea867a3621e11b4c49e72605bbcc89 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 14 Nov 2018 16:31:28 +0700 Subject: change osal_queue_receive() signature - fix build issue with freertos --- .gitignore | 16 +++++++++++++++ .../device/nrf52840_freertos/src/msc_flash_qspi.c | 2 +- src/device/dcd.h | 2 -- src/device/usbd.c | 23 +++++++++++----------- src/host/usbh.c | 10 ++++++++-- src/osal/osal.h | 7 +------ src/osal/osal_freertos.h | 5 ++--- src/osal/osal_none.h | 11 ++++++----- 8 files changed, 46 insertions(+), 30 deletions(-) create mode 100644 .gitignore (limited to 'src/host') diff --git a/.gitignore b/.gitignore new file mode 100644 index 000000000..266cbe08f --- /dev/null +++ b/.gitignore @@ -0,0 +1,16 @@ +/.metadata +html +latex +test_old +tests/build +*.d +*.o +*.mk +*.ld +*.launch +*.map +*.axf +/tests/lpc175x_6x/build/ +/tests/lpc18xx_43xx/build/ +/demos/*/*/Board_* +/demos/*/*/KeilBuild/ diff --git a/examples/device/nrf52840_freertos/src/msc_flash_qspi.c b/examples/device/nrf52840_freertos/src/msc_flash_qspi.c index 53bdc5a71..30adf1d92 100644 --- a/examples/device/nrf52840_freertos/src/msc_flash_qspi.c +++ b/examples/device/nrf52840_freertos/src/msc_flash_qspi.c @@ -61,7 +61,7 @@ int32_t tud_msc_read10_cb(uint8_t lun, uint32_t lba, uint32_t offset, void* buff // Callback invoked when received WRITE10 command. // Process data in buffer to disk's storage and return number of written bytes -int32_t tud_msc_write10_cb(uint8_t lun, uint32_t lba, uint32_t offset, void* buffer, uint32_t bufsize) +int32_t tud_msc_write10_cb(uint8_t lun, uint32_t lba, uint32_t offset, uint8_t* buffer, uint32_t bufsize) { uint32_t addr = lba * CFG_TUD_MSC_BLOCK_SZ + offset; diff --git a/src/device/dcd.h b/src/device/dcd.h index 0c976edec..ff836f405 100644 --- a/src/device/dcd.h +++ b/src/device/dcd.h @@ -125,8 +125,6 @@ void dcd_event_xfer_complete (uint8_t rhport, uint8_t ep_addr, uint32_t xferred_ /*------------------------------------------------------------------*/ /* Endpoint API *------------------------------------------------------------------*/ - -//------------- Non-control Endpoints -------------// bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc); bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes); bool dcd_edpt_busy (uint8_t rhport, uint8_t ep_addr); diff --git a/src/device/usbd.c b/src/device/usbd.c index c9d5e5642..4a9b13a25 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -245,24 +245,25 @@ void usbd_task( void* param) { (void) param; - OSAL_TASK_BEGIN +#if CFG_TUSB_OS != OPT_OS_NONE + while (1) { +#endif + usbd_main_st(); - OSAL_TASK_END + +#if CFG_TUSB_OS != OPT_OS_NONE + } +#endif } static tusb_error_t usbd_main_st(void) { dcd_event_t event; - tusb_error_t err = TUSB_ERROR_NONE; + // Loop until there is no more events in the queue - while (_usbd_q->count > 0) + while (1) { - tu_memclr(&event, sizeof(dcd_event_t)); - - err = osal_queue_receive(_usbd_q, &event); - if (err != TUSB_ERROR_NONE) { - break; - } + if ( !osal_queue_receive(_usbd_q, &event) ) return TUSB_ERROR_NONE; if ( DCD_EVENT_SETUP_RECEIVED == event.event_id ) { @@ -312,7 +313,7 @@ static tusb_error_t usbd_main_st(void) } } - return err; + return TUSB_ERROR_NONE; } void tud_control_interface_control_complete_cb(uint8_t rhport, uint8_t interface, tusb_control_request_t const * const p_request) { diff --git a/src/host/usbh.c b/src/host/usbh.c index b849de9b9..f996d7a70 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -361,9 +361,15 @@ void usbh_enumeration_task(void* param) { (void) param; - OSAL_TASK_BEGIN +#if CFG_TUSB_OS != OPT_OS_NONE + while (1) { +#endif + enumeration_body_subtask(); - OSAL_TASK_END + +#if CFG_TUSB_OS != OPT_OS_NONE + } +#endif } tusb_error_t enumeration_body_subtask(void) diff --git a/src/osal/osal.h b/src/osal/osal.h index 2ca06f66e..6846b5757 100644 --- a/src/osal/osal.h +++ b/src/osal/osal.h @@ -62,10 +62,6 @@ typedef void (*osal_task_func_t)( void * ); #if CFG_TUSB_OS == OPT_OS_NONE #include "osal_none.h" - - #define OSAL_TASK_BEGIN - #define OSAL_TASK_END - #else /* RTOS Porting API * @@ -105,8 +101,7 @@ typedef void (*osal_task_func_t)( void * ); #error CFG_TUSB_OS is not defined or OS is not supported yet #endif - #define OSAL_TASK_BEGIN while(1) { - #define OSAL_TASK_END } + // TODO remove subtask related macros later //------------- Sub Task -------------// #define OSAL_SUBTASK_BEGIN diff --git a/src/osal/osal_freertos.h b/src/osal/osal_freertos.h index f29759225..52cadd798 100644 --- a/src/osal/osal_freertos.h +++ b/src/osal/osal_freertos.h @@ -159,10 +159,9 @@ static inline osal_queue_t osal_queue_create(osal_queue_def_t* qdef) return xQueueCreateStatic(qdef->depth, qdef->item_sz, (uint8_t*) qdef->buf, &qdef->sq); } -static inline void osal_queue_receive (osal_queue_t const queue_hdl, void *p_data, uint32_t msec, uint32_t *err) +static inline bool osal_queue_receive(osal_queue_t const queue_hdl, void* data) { - uint32_t const ticks = (msec == OSAL_TIMEOUT_WAIT_FOREVER) ? portMAX_DELAY : pdMS_TO_TICKS(msec); - (*err) = ( xQueueReceive(queue_hdl, p_data, ticks) ? TUSB_ERROR_NONE : TUSB_ERROR_OSAL_TIMEOUT); + return xQueueReceive(queue_hdl, data, portMAX_DELAY); } static inline bool osal_queue_send(osal_queue_t const queue_hdl, void const * data, bool in_isr) diff --git a/src/osal/osal_none.h b/src/osal/osal_none.h index 383809180..5ba246d5f 100644 --- a/src/osal/osal_none.h +++ b/src/osal/osal_none.h @@ -89,6 +89,7 @@ static inline osal_semaphore_t osal_semaphore_create(osal_semaphore_def_t* semde static inline bool osal_semaphore_post(osal_semaphore_t sem_hdl, bool in_isr) { + (void) in_isr; sem_hdl->count++; return true; } @@ -157,11 +158,11 @@ static inline void osal_queue_reset(osal_queue_t const queue_hdl) queue_hdl->count = queue_hdl->rd_idx = queue_hdl->wr_idx = 0; } -static inline tusb_error_t osal_queue_receive(osal_queue_t const queue_hdl, void* data) { - if (!tu_fifo_read(queue_hdl, data)) { - return TUSB_ERROR_OSAL_WAITING; - } - return TUSB_ERROR_NONE; + +static inline bool osal_queue_receive(osal_queue_t const queue_hdl, void* data) +{ + // osal none return immediately without blocking + return tu_fifo_read(queue_hdl, data); } -- cgit v1.3.1 From 60d8cde6951fa9fe9c43064ee701598e9da566f7 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 22 Nov 2018 17:21:07 +0700 Subject: rename CFG_TUSB_MEM_SECTION to CFG_TUSB_MEM_SECTION --- doxygen/configuration.txt | 6 +-- examples/device/cdc_msc_hid/src/tusb_config.h | 12 +++--- .../device/cdc_msc_hid_freertos/src/tusb_config.h | 2 +- .../device/device_virtual_com/src/tusb_config.h | 20 ++++----- .../device/device_virtual_com/xpresso/.cproject | 14 ++----- examples/obsolete/device/src/keyboard_device_app.c | 2 +- examples/obsolete/device/src/mouse_device_app.c | 2 +- examples/obsolete/device/src/msc_device_ramdisk.c | 2 +- examples/obsolete/device/src/tusb_config.h | 18 ++++----- examples/obsolete/host/src/cdc_serial_host_app.c | 4 +- examples/obsolete/host/src/keyboard_host_app.c | 2 +- examples/obsolete/host/src/mouse_host_app.c | 2 +- examples/obsolete/host/src/msc_cli.c | 2 +- examples/obsolete/host/src/msc_host_app.c | 2 +- examples/obsolete/host/src/tusb_config.h | 12 +++--- hw/bsp/ea4357/board_ea4357.c | 6 ++- src/class/cdc/cdc_device.c | 2 +- src/class/cdc/cdc_host.h | 8 ++-- src/class/cdc/cdc_rndis_host.c | 4 +- src/class/hid/hid_device.c | 2 +- src/class/hid/hid_device.h | 4 +- src/class/hid/hid_host.c | 2 +- src/class/hid/hid_host.h | 4 +- src/class/msc/msc_device.c | 4 +- src/class/msc/msc_host.c | 4 +- src/class/msc/msc_host.h | 6 +-- src/device/usbd_control.c | 2 +- src/host/ehci/ehci.c | 6 +-- src/host/hub.c | 4 +- src/host/ohci/ohci.c | 2 +- src/host/usbh.c | 4 +- .../nxp/lpc11xx_lpc13xx/dcd_lpc_11uxx_13uxx.c | 6 +-- src/portable/nxp/lpc17xx/dcd_lpc175x_6x.c | 2 +- src/portable/nxp/lpc43xx_lpc18xx/dcd_lpc43xx.c | 47 ++++++++++++++-------- src/tusb_option.h | 5 ++- tests/lpc18xx_43xx/test/host/cdc/descriptor_cdc.c | 4 +- tests/support/descriptor_test.c | 8 ++-- tests/support/tusb_config.h | 2 +- 38 files changed, 126 insertions(+), 114 deletions(-) (limited to 'src/host') diff --git a/doxygen/configuration.txt b/doxygen/configuration.txt index 5816826d7..da30786ed 100644 --- a/doxygen/configuration.txt +++ b/doxygen/configuration.txt @@ -10,13 +10,13 @@ #define CFG_TUSB_RHPORT0_MODE /** 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 CFG_TUSB_ATTR_USBRAM as empty macro. + into the USB RAM section as follows. if your mcu's usb controller has no such limit, define CFG_TUSB_MEM_SECTION as empty macro. @code - CFG_TUSB_ATTR_USBRAM uint8_t usb_xfer_buffer[10]; + CFG_TUSB_MEM_SECTION uint8_t usb_xfer_buffer[10]; @endcode */ -#define CFG_TUSB_ATTR_USBRAM +#define CFG_TUSB_MEM_SECTION #define CFG_TUSB_MCU ///< Select one of the supported MCU, the value must be from \ref group_mcu #define CFG_TUSB_OS ///< Select one of the supported RTOS, the value must be from \ref group_supported_os. diff --git a/examples/device/cdc_msc_hid/src/tusb_config.h b/examples/device/cdc_msc_hid/src/tusb_config.h index 29ed8a8e0..3af109188 100644 --- a/examples/device/cdc_msc_hid/src/tusb_config.h +++ b/examples/device/cdc_msc_hid/src/tusb_config.h @@ -58,6 +58,12 @@ #define CFG_TUSB_DEBUG 2 #define CFG_TUSB_OS OPT_OS_NONE +//-------------------------------------------------------------------- +// USB RAM PLACEMENT +//-------------------------------------------------------------------- +#define CFG_TUSB_ATTR_USBRAM +#define CFG_TUSB_MEM_ALIGN ATTR_ALIGNED(4) + //-------------------------------------------------------------------- // DEVICE CONFIGURATION //-------------------------------------------------------------------- @@ -132,12 +138,6 @@ */ #define CFG_TUD_HID_ASCII_TO_KEYCODE_LOOKUP 1 -//-------------------------------------------------------------------- -// USB RAM PLACEMENT -//-------------------------------------------------------------------- -#define CFG_TUSB_ATTR_USBRAM -#define CFG_TUSB_MEM_ALIGN ATTR_ALIGNED(4) - #ifdef __cplusplus } diff --git a/examples/device/cdc_msc_hid_freertos/src/tusb_config.h b/examples/device/cdc_msc_hid_freertos/src/tusb_config.h index a80680338..777930ba3 100644 --- a/examples/device/cdc_msc_hid_freertos/src/tusb_config.h +++ b/examples/device/cdc_msc_hid_freertos/src/tusb_config.h @@ -140,7 +140,7 @@ //-------------------------------------------------------------------- // USB RAM PLACEMENT //-------------------------------------------------------------------- -#define CFG_TUSB_ATTR_USBRAM +#define CFG_TUSB_MEM_SECTION #define CFG_TUSB_MEM_ALIGN ATTR_ALIGNED(4) diff --git a/examples/device/device_virtual_com/src/tusb_config.h b/examples/device/device_virtual_com/src/tusb_config.h index f7cde7848..fd3f41b01 100644 --- a/examples/device/device_virtual_com/src/tusb_config.h +++ b/examples/device/device_virtual_com/src/tusb_config.h @@ -93,36 +93,36 @@ #ifdef __CODE_RED // compiled with lpcxpresso #if (CFG_TUSB_MCU == OPT_MCU_LPC11UXX) || (CFG_TUSB_MCU == OPT_MCU_LPC13UXX) - #define CFG_TUSB_ATTR_USBRAM ATTR_SECTION(.data.$RAM2) ATTR_ALIGNED(64) // lp11u & lp13u requires data to be 64 byte aligned + #define CFG_TUSB_MEM_SECTION ATTR_SECTION(.data.$RAM2) ATTR_ALIGNED(64) // lp11u & lp13u requires data to be 64 byte aligned #elif CFG_TUSB_MCU == OPT_MCU_LPC175X_6X - #define CFG_TUSB_ATTR_USBRAM // LPC17xx USB DMA can access all + #define CFG_TUSB_MEM_SECTION // LPC17xx USB DMA can access all #elif (CFG_TUSB_MCU == OPT_MCU_LPC43XX) - #define CFG_TUSB_ATTR_USBRAM ATTR_SECTION(.data.$RAM3) + #define CFG_TUSB_MEM_SECTION ATTR_SECTION(.data.$RAM3) #endif #elif defined __CC_ARM // Compiled with Keil armcc, USBRAM_SECTION is defined in scatter files #if (CFG_TUSB_MCU == OPT_MCU_LPC11UXX) || (CFG_TUSB_MCU == OPT_MCU_LPC13UXX) - #define CFG_TUSB_ATTR_USBRAM ATTR_SECTION(USBRAM_SECTION) ATTR_ALIGNED(64) // lp11u & lp13u requires data to be 64 byte aligned + #define CFG_TUSB_MEM_SECTION ATTR_SECTION(USBRAM_SECTION) ATTR_ALIGNED(64) // lp11u & lp13u requires data to be 64 byte aligned #elif (CFG_TUSB_MCU == OPT_MCU_LPC175X_6X) - #define CFG_TUSB_ATTR_USBRAM // LPC17xx USB DMA can access all address + #define CFG_TUSB_MEM_SECTION // LPC17xx USB DMA can access all address #elif (CFG_TUSB_MCU == OPT_MCU_LPC43XX) - #define CFG_TUSB_ATTR_USBRAM // Use keil tool configure to have AHB SRAM as default memory + #define CFG_TUSB_MEM_SECTION // Use keil tool configure to have AHB SRAM as default memory #endif #elif defined __ICCARM__ // compiled with IAR #if (CFG_TUSB_MCU == OPT_MCU_LPC11UXX) || (CFG_TUSB_MCU == OPT_MCU_LPC13UXX) - #define CFG_TUSB_ATTR_USBRAM _Pragma("location=\"USB_PACKET_MEMORY\"") ATTR_ALIGNED(64) + #define CFG_TUSB_MEM_SECTION _Pragma("location=\"USB_PACKET_MEMORY\"") ATTR_ALIGNED(64) #elif (CFG_TUSB_MCU == OPT_MCU_LPC175X_6X) - #define CFG_TUSB_ATTR_USBRAM + #define CFG_TUSB_MEM_SECTION #elif (CFG_TUSB_MCU == OPT_MCU_LPC43XX) - #define CFG_TUSB_ATTR_USBRAM _Pragma("location=\".ahb_sram1\"") + #define CFG_TUSB_MEM_SECTION _Pragma("location=\".ahb_sram1\"") #endif #elif defined __SES_ARM -#define CFG_TUSB_ATTR_USBRAM ATTR_SECTION(.bss2) +#define CFG_TUSB_MEM_SECTION ATTR_SECTION(.bss2) #else diff --git a/examples/device/device_virtual_com/xpresso/.cproject b/examples/device/device_virtual_com/xpresso/.cproject index a9c1f03f7..1e76a688c 100644 --- a/examples/device/device_virtual_com/xpresso/.cproject +++ b/examples/device/device_virtual_com/xpresso/.cproject @@ -80,6 +80,9 @@