[host lpc43xx] adding support for host custom class
refractor usbh class driver indexing opt out periodic list code in EHCI (need to refractor/group later) [device lpc176x] rename dcd_endpoint_configure to dcd_pipe_open add usbd_pipe_open to manage pipe
This commit is contained in:
parent
743e5a7a93
commit
3924764dff
|
@ -94,7 +94,7 @@ void led_blinking_task(void * p_para)
|
|||
void keyboard_device_app_task(void * p_para)
|
||||
{
|
||||
#if 0
|
||||
if (tusb_device_is_configured())
|
||||
if (tusbd_is_configured())
|
||||
{
|
||||
static uint32_t count =0;
|
||||
if (count < 4)
|
||||
|
|
|
@ -0,0 +1,79 @@
|
|||
/**************************************************************************/
|
||||
/*!
|
||||
@file custom_class.h
|
||||
@author hathach (tinyusb.org)
|
||||
|
||||
@section LICENSE
|
||||
|
||||
Software License Agreement (BSD License)
|
||||
|
||||
Copyright (c) 2013, hathach (tinyusb.org)
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
3. Neither the name of the copyright holders nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
|
||||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
This file is part of the tinyusb stack.
|
||||
*/
|
||||
/**************************************************************************/
|
||||
|
||||
/** \ingroup TBD
|
||||
* \defgroup TBD
|
||||
* \brief TBD
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef _TUSB_CUSTOM_CLASS_H_
|
||||
#define _TUSB_CUSTOM_CLASS_H_
|
||||
|
||||
#include "common/common.h"
|
||||
#include "host/usbh.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
pipe_handle_t pipe_in;
|
||||
pipe_handle_t pipe_out;
|
||||
}custom_interface_info_t;
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// USBH-CLASS DRIVER API
|
||||
//--------------------------------------------------------------------+
|
||||
#ifdef _TINY_USB_SOURCE_FILE_
|
||||
|
||||
void cush_init(void);
|
||||
tusb_error_t cush_open_subtask(uint8_t dev_addr, tusb_descriptor_interface_t const *p_interface_desc, uint16_t *p_length) ATTR_WARN_UNUSED_RESULT;
|
||||
void cush_isr(pipe_handle_t pipe_hdl, tusb_event_t event);
|
||||
void cush_close(uint8_t dev_addr);
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _TUSB_CUSTOM_CLASS_H_ */
|
||||
|
||||
/** @} */
|
|
@ -0,0 +1,115 @@
|
|||
/**************************************************************************/
|
||||
/*!
|
||||
@file custom_class_host.c
|
||||
@author hathach (tinyusb.org)
|
||||
|
||||
@section LICENSE
|
||||
|
||||
Software License Agreement (BSD License)
|
||||
|
||||
Copyright (c) 2013, hathach (tinyusb.org)
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
3. Neither the name of the copyright holders nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
|
||||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
This file is part of the tinyusb stack.
|
||||
*/
|
||||
/**************************************************************************/
|
||||
|
||||
#include "tusb_option.h"
|
||||
|
||||
#if (MODE_HOST_SUPPORTED && TUSB_CFG_HOST_CUSTOM_CLASS)
|
||||
|
||||
#define _TINY_USB_SOURCE_FILE_
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// INCLUDE
|
||||
//--------------------------------------------------------------------+
|
||||
#include "common/common.h"
|
||||
#include "custom_class.h"
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// MACRO CONSTANT TYPEDEF
|
||||
//--------------------------------------------------------------------+
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// INTERNAL OBJECT & FUNCTION DECLARATION
|
||||
//--------------------------------------------------------------------+
|
||||
custom_interface_info_t custom_interface[TUSB_CFG_HOST_DEVICE_MAX];
|
||||
//--------------------------------------------------------------------+
|
||||
// IMPLEMENTATION
|
||||
//--------------------------------------------------------------------+
|
||||
void cush_init(void)
|
||||
{
|
||||
memclr_(&custom_interface, sizeof(custom_interface_info_t) * TUSB_CFG_HOST_DEVICE_MAX);
|
||||
}
|
||||
|
||||
tusb_error_t cush_open_subtask(uint8_t dev_addr, tusb_descriptor_interface_t const *p_interface_desc, uint16_t *p_length)
|
||||
{
|
||||
// FIXME quick hack to test lpc1k custom class with 2 bulk endpoints
|
||||
uint8_t const *p_desc = (uint8_t const *) p_interface_desc;
|
||||
|
||||
//------------- 1st Bulk Endpiont Descriptor -------------//
|
||||
for(uint32_t i=0; i<2; i++)
|
||||
{
|
||||
p_desc += p_desc[DESCRIPTOR_OFFSET_LENGTH];
|
||||
tusb_descriptor_endpoint_t const *p_endpoint = (tusb_descriptor_endpoint_t const *) p_desc;
|
||||
ASSERT_INT(TUSB_DESC_TYPE_ENDPOINT, p_endpoint->bDescriptorType, TUSB_ERROR_INVALID_PARA);
|
||||
|
||||
pipe_handle_t * pipe_hdl = ( p_endpoint->bEndpointAddress & TUSB_DIR_DEV_TO_HOST_MASK ) ?
|
||||
&custom_interface[dev_addr-1].pipe_in : &custom_interface[dev_addr-1].pipe_out;
|
||||
*pipe_hdl = hcd_pipe_open(dev_addr, p_endpoint, TUSB_CLASS_VENDOR_SPECIFIC);
|
||||
ASSERT ( pipehandle_is_valid(*pipe_hdl), TUSB_ERROR_HCD_OPEN_PIPE_FAILED );
|
||||
}
|
||||
|
||||
(*p_length) = sizeof(tusb_descriptor_interface_t) + 2*sizeof(tusb_descriptor_endpoint_t);
|
||||
return TUSB_ERROR_NONE;
|
||||
}
|
||||
|
||||
void cush_isr(pipe_handle_t pipe_hdl, tusb_event_t event)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void cush_close(uint8_t dev_addr)
|
||||
{
|
||||
tusb_error_t err1, err2;
|
||||
custom_interface_info_t * p_interface = &custom_interface[dev_addr-1];
|
||||
|
||||
// TODO re-consider to check pipe valid before calling pipe_close
|
||||
if( pipehandle_is_valid( p_interface->pipe_in ) )
|
||||
{
|
||||
err1 = hcd_pipe_close( p_interface->pipe_in );
|
||||
}
|
||||
|
||||
if ( pipehandle_is_valid( p_interface->pipe_out ) )
|
||||
{
|
||||
err2 = hcd_pipe_close( p_interface->pipe_out );
|
||||
}
|
||||
|
||||
memclr_(p_interface, sizeof(custom_interface_info_t));
|
||||
|
||||
ASSERT(err1 == TUSB_ERROR_NONE && err2 == TUSB_ERROR_NONE, (void) 0 );
|
||||
}
|
||||
|
||||
#endif
|
|
@ -136,7 +136,7 @@ tusb_error_t hidd_init(uint8_t coreid, tusb_descriptor_interface_t const * p_int
|
|||
{
|
||||
#if TUSB_CFG_DEVICE_HID_KEYBOARD
|
||||
case HID_PROTOCOL_KEYBOARD:
|
||||
ASSERT_STATUS( dcd_endpoint_configure(coreid, p_desc_endpoint) );
|
||||
ASSERT_STATUS( dcd_pipe_open(coreid, p_desc_endpoint) );
|
||||
break;
|
||||
#endif
|
||||
|
||||
|
|
|
@ -38,7 +38,7 @@
|
|||
|
||||
#include "tusb_option.h"
|
||||
|
||||
#if (MODE_HOST_SUPPORTED && defined HOST_CLASS_HID)
|
||||
#if (MODE_HOST_SUPPORTED && HOST_CLASS_HID)
|
||||
|
||||
#define _TINY_USB_SOURCE_FILE_
|
||||
//--------------------------------------------------------------------+
|
||||
|
@ -214,8 +214,6 @@ tusb_error_t hidh_open_subtask(uint8_t dev_addr, tusb_descriptor_interface_t con
|
|||
p_desc += p_desc[DESCRIPTOR_OFFSET_LENGTH];
|
||||
ASSERT_INT(TUSB_DESC_TYPE_ENDPOINT, p_desc[DESCRIPTOR_OFFSET_TYPE], TUSB_ERROR_INVALID_PARA);
|
||||
|
||||
if (p_interface_desc->bInterfaceSubClass == HID_SUBCLASS_BOOT)
|
||||
{
|
||||
switch(p_interface_desc->bInterfaceProtocol)
|
||||
{
|
||||
#if TUSB_CFG_HOST_HID_KEYBOARD
|
||||
|
@ -241,13 +239,8 @@ tusb_error_t hidh_open_subtask(uint8_t dev_addr, tusb_descriptor_interface_t con
|
|||
default: // TODO unknown, unsupported protocol --> skip this interface
|
||||
return TUSB_ERROR_NONE;
|
||||
}
|
||||
*p_length = sizeof(tusb_descriptor_interface_t) + sizeof(tusb_hid_descriptor_hid_t) + sizeof(tusb_descriptor_endpoint_t);
|
||||
}else
|
||||
{
|
||||
// open generic
|
||||
*p_length = 0;
|
||||
}
|
||||
|
||||
*p_length = sizeof(tusb_descriptor_interface_t) + sizeof(tusb_hid_descriptor_hid_t) + sizeof(tusb_descriptor_endpoint_t);
|
||||
return TUSB_ERROR_NONE;
|
||||
}
|
||||
|
||||
|
|
|
@ -64,6 +64,7 @@
|
|||
ENTRY(TUSB_ERROR_DEVICE_NOT_READY )\
|
||||
ENTRY(TUSB_ERROR_INTERFACE_IS_BUSY )\
|
||||
ENTRY(TUSB_ERROR_HCD_FAILED )\
|
||||
ENTRY(TUSB_ERROR_HCD_OPEN_PIPE_FAILED )\
|
||||
ENTRY(TUSB_ERROR_USBH_MOUNT_DEVICE_NOT_RESPOND )\
|
||||
ENTRY(TUSB_ERROR_USBH_MOUNT_CONFIG_DESC_TOO_LONG )\
|
||||
ENTRY(TUSB_ERROR_OSAL_TIMEOUT )\
|
||||
|
|
|
@ -71,9 +71,12 @@ typedef enum {
|
|||
|
||||
typedef enum {
|
||||
TUSB_DIR_HOST_TO_DEV = 0,
|
||||
TUSB_DIR_DEV_TO_HOST = 1
|
||||
TUSB_DIR_DEV_TO_HOST = 1,
|
||||
|
||||
TUSB_DIR_DEV_TO_HOST_MASK = 0x80
|
||||
}tusb_direction_t;
|
||||
|
||||
|
||||
/// USB Descriptor Types (section 9.4 table 9-5)
|
||||
typedef enum {
|
||||
TUSB_DESC_TYPE_DEVICE =1 , ///< 1
|
||||
|
@ -137,7 +140,8 @@ typedef enum {
|
|||
TUSB_CLASS_PERSONAL_HEALTHCARE = 15 , ///< 15
|
||||
TUSB_CLASS_AUDIO_VIDEO = 16 , ///< 16
|
||||
|
||||
TUSB_CLASS_MAX_CONSEC_NUMBER = 17 , // TODO compact & minimize this number
|
||||
TUSB_CLASS_MAPPED_INDEX_START = 17 , // TODO compact & minimize this number
|
||||
TUSB_CLASS_MAPPED_INDEX_END = TUSB_CLASS_MAPPED_INDEX_START + 5,
|
||||
|
||||
TUSB_CLASS_DIAGNOSTIC = 0xDC ,
|
||||
TUSB_CLASS_WIRELESS_CONTROLLER = 0xE0 ,
|
||||
|
|
|
@ -66,7 +66,7 @@ tusb_error_t dcd_pipe_control_write(uint8_t coreid, void const * buffer, uint16_
|
|||
tusb_error_t dcd_pipe_control_read(uint8_t coreid, void * buffer, uint16_t length);
|
||||
|
||||
void dcd_pipe_control_write_zero_length(uint8_t coreid);
|
||||
tusb_error_t dcd_endpoint_configure(uint8_t coreid, tusb_descriptor_endpoint_t const * p_endpoint_desc) ATTR_WARN_UNUSED_RESULT;
|
||||
tusb_error_t dcd_pipe_open(uint8_t coreid, tusb_descriptor_endpoint_t const * p_endpoint_desc) ATTR_WARN_UNUSED_RESULT;
|
||||
void dcd_device_set_address(uint8_t coreid, uint8_t dev_addr);
|
||||
void dcd_device_set_configuration(uint8_t coreid, uint8_t config_num);
|
||||
|
||||
|
|
|
@ -297,7 +297,7 @@ static inline uint8_t endpoint_address_to_physical_index(uint8_t ep_address)
|
|||
return (ep_address << 1) + (ep_address & 0x80 ? 1 : 0 );
|
||||
}
|
||||
|
||||
tusb_error_t dcd_endpoint_configure(uint8_t coreid, tusb_descriptor_endpoint_t const * p_endpoint_desc)
|
||||
tusb_error_t dcd_pipe_open(uint8_t coreid, tusb_descriptor_endpoint_t const * p_endpoint_desc)
|
||||
{
|
||||
uint8_t phy_ep = endpoint_address_to_physical_index( p_endpoint_desc->bEndpointAddress );
|
||||
|
||||
|
|
|
@ -55,7 +55,7 @@
|
|||
usbd_device_info_t usbd_devices[CONTROLLER_DEVICE_NUMBER];
|
||||
|
||||
// TODO fix/compress number of class driver
|
||||
static device_class_driver_t const usbd_class_drivers[TUSB_CLASS_MAX_CONSEC_NUMBER] =
|
||||
static device_class_driver_t const usbd_class_drivers[TUSB_CLASS_MAPPED_INDEX_START] =
|
||||
{
|
||||
#if DEVICE_CLASS_HID
|
||||
[TUSB_CLASS_HID] = {
|
||||
|
@ -78,6 +78,9 @@ bool tusbd_is_configured(uint8_t coreid)
|
|||
return usbd_devices[coreid].state == TUSB_DEVICE_STATE_CONFIGURED;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// IMPLEMENTATION
|
||||
//--------------------------------------------------------------------+
|
||||
void usbd_bus_reset(uint32_t coreid)
|
||||
{
|
||||
memclr_(usbd_devices, sizeof(usbd_device_info_t)*CONTROLLER_DEVICE_NUMBER);
|
||||
|
@ -166,9 +169,6 @@ void usbd_setup_received(uint8_t coreid)
|
|||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// IMPLEMENTATION
|
||||
//--------------------------------------------------------------------+
|
||||
tusb_error_t usbd_init (void)
|
||||
{
|
||||
ASSERT_STATUS ( usbd_string_descriptor_init() );
|
||||
|
@ -197,9 +197,16 @@ tusb_error_t usbd_init (void)
|
|||
return TUSB_ERROR_NONE;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// USBD-CLASS API
|
||||
//--------------------------------------------------------------------+
|
||||
tusb_error_t usbd_pipe_open(uint8_t coreid, tusb_descriptor_interface_t const * p_interfacae, tusb_descriptor_endpoint_t const * p_endpoint_desc)
|
||||
{
|
||||
return TUSB_ERROR_NONE;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// callback from DCD ISR
|
||||
//--------------------------------------------------------------------+
|
||||
|
@ -252,3 +259,5 @@ static tusb_error_t usbd_string_descriptor_init(void)
|
|||
|
||||
return TUSB_ERROR_NONE;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -86,6 +86,7 @@ bool tusbd_is_configured(uint8_t coreid) ATTR_WARN_UNUSED_RESULT;
|
|||
#ifdef _TINY_USB_SOURCE_FILE_
|
||||
|
||||
tusb_error_t usbd_init(void);
|
||||
tusb_error_t usbd_pipe_open(uint8_t coreid, tusb_descriptor_interface_t const * p_interfacae, tusb_descriptor_endpoint_t const * p_endpoint_desc);
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -373,10 +373,13 @@ pipe_handle_t hcd_pipe_open(uint8_t dev_addr, tusb_descriptor_endpoint_t const *
|
|||
if (p_endpoint_desc->bmAttributes.xfer == TUSB_XFER_BULK)
|
||||
{
|
||||
list_head = (ehci_link_t*) get_async_head(usbh_devices[dev_addr].core_id);
|
||||
}else if (p_endpoint_desc->bmAttributes.xfer == TUSB_XFER_INTERRUPT)
|
||||
}
|
||||
#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,
|
||||
|
@ -428,12 +431,15 @@ tusb_error_t hcd_pipe_close(pipe_handle_t pipe_hdl)
|
|||
ASSERT_STATUS( list_remove_qhd(
|
||||
(ehci_link_t*) get_async_head( usbh_devices[pipe_hdl.dev_addr].core_id ),
|
||||
(ehci_link_t*) p_qhd) );
|
||||
}else
|
||||
}
|
||||
#if EHCI_PERIODIC_LIST // TODO refractor/group this together
|
||||
else
|
||||
{
|
||||
ASSERT_STATUS( list_remove_qhd(
|
||||
get_period_head( usbh_devices[pipe_hdl.dev_addr].core_id, p_qhd->interval_ms ),
|
||||
(ehci_link_t*) p_qhd) );
|
||||
}
|
||||
#endif
|
||||
|
||||
return TUSB_ERROR_NONE;
|
||||
}
|
||||
|
@ -530,6 +536,7 @@ void async_list_process_isr(ehci_qhd_t * const async_head)
|
|||
// TODO abstract max loop guard for async
|
||||
}
|
||||
|
||||
#if EHCI_PERIODIC_LIST // TODO refractor/group this together
|
||||
void period_list_process_isr(uint8_t hostid, uint8_t interval_ms)
|
||||
{
|
||||
uint8_t max_loop = 0;
|
||||
|
@ -585,6 +592,7 @@ void period_list_process_isr(uint8_t hostid, uint8_t interval_ms)
|
|||
max_loop++;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void xfer_error_isr(uint8_t hostid)
|
||||
{
|
||||
|
@ -653,6 +661,7 @@ void hcd_isr(uint8_t hostid)
|
|||
async_list_process_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)
|
||||
|
@ -660,6 +669,7 @@ void hcd_isr(uint8_t hostid)
|
|||
period_list_process_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
|
||||
|
@ -676,6 +686,7 @@ 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)
|
||||
|
@ -693,6 +704,7 @@ STATIC_ INLINE_ ehci_link_t* get_period_frame_list(uint8_t hostid)
|
|||
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
STATIC_ INLINE_ uint8_t hostid_to_data_idx(uint8_t hostid)
|
||||
{
|
||||
|
@ -710,11 +722,13 @@ 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)
|
||||
{
|
||||
|
|
|
@ -54,7 +54,7 @@
|
|||
#define ENUM_QUEUE_DEPTH 5
|
||||
|
||||
// TODO fix/compress number of class driver
|
||||
static host_class_driver_t const usbh_class_drivers[TUSB_CLASS_MAX_CONSEC_NUMBER] =
|
||||
static host_class_driver_t const usbh_class_drivers[TUSB_CLASS_MAPPED_INDEX_END] =
|
||||
{
|
||||
#if HOST_CLASS_HID
|
||||
[TUSB_CLASS_HID] = {
|
||||
|
@ -83,6 +83,14 @@ static host_class_driver_t const usbh_class_drivers[TUSB_CLASS_MAX_CONSEC_NUMBER
|
|||
}
|
||||
#endif
|
||||
|
||||
#if TUSB_CFG_HOST_CUSTOM_CLASS
|
||||
[TUSB_CLASS_MAPPED_INDEX_END-1] = {
|
||||
.init = cush_init,
|
||||
.open_subtask = cush_open_subtask,
|
||||
.isr = cush_isr,
|
||||
.close = cush_close
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
|
@ -102,6 +110,17 @@ STATIC_ uint8_t enum_data_buffer[TUSB_CFG_HOST_ENUM_BUFFER_SIZE] TUSB_CFG_ATTR_U
|
|||
static inline uint8_t get_new_address(void) ATTR_ALWAYS_INLINE;
|
||||
static inline uint8_t get_configure_number_for_device(tusb_descriptor_device_t* dev_desc) ATTR_ALWAYS_INLINE;
|
||||
|
||||
static inline uint8_t std_class_code_to_index(uint8_t std_class_code) ATTR_CONST ATTR_ALWAYS_INLINE;
|
||||
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;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// PUBLIC API (Parameter Verification is required)
|
||||
//--------------------------------------------------------------------+
|
||||
|
@ -133,7 +152,7 @@ tusb_error_t usbh_init(void)
|
|||
ASSERT_PTR(enum_queue_hdl, TUSB_ERROR_OSAL_QUEUE_FAILED);
|
||||
|
||||
//------------- class init -------------//
|
||||
for (uint8_t class_code = 1; class_code < TUSB_CLASS_MAX_CONSEC_NUMBER; class_code++)
|
||||
for (uint8_t class_code = 1; class_code < TUSB_CLASS_MAPPED_INDEX_END; class_code++)
|
||||
{
|
||||
if (usbh_class_drivers[class_code].init)
|
||||
usbh_class_drivers[class_code].init();
|
||||
|
@ -229,12 +248,12 @@ void usbh_device_unplugged_isr(uint8_t hostid)
|
|||
if (dev_addr > 0) // device can still be unplugged when not set new address
|
||||
{
|
||||
// if device unplugged is not a hub TODO handle hub unplugged
|
||||
for (uint8_t class_code = 1; class_code < TUSB_CLASS_MAX_CONSEC_NUMBER; class_code++)
|
||||
for (uint8_t class_index = 1; class_index < TUSB_CLASS_MAPPED_INDEX_END; class_index++)
|
||||
{
|
||||
if ((usbh_devices[dev_addr].flag_supported_class & BIT_(class_code)) &&
|
||||
usbh_class_drivers[class_code].close)
|
||||
if ((usbh_devices[dev_addr].flag_supported_class & BIT_(class_index)) &&
|
||||
usbh_class_drivers[class_index].close)
|
||||
{
|
||||
usbh_class_drivers[class_code].close(dev_addr);
|
||||
usbh_class_drivers[class_index].close(dev_addr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -434,29 +453,27 @@ tusb_error_t enumeration_body_subtask(void)
|
|||
p_desc += p_desc[DESCRIPTOR_OFFSET_LENGTH]; // skip the descriptor, increase by the descriptor's length
|
||||
}else
|
||||
{
|
||||
uint8_t class_code = ((tusb_descriptor_interface_t*) p_desc)->bInterfaceClass;
|
||||
if (class_code == 0)
|
||||
{
|
||||
SUBTASK_ASSERT( false ); // corrupted data, abort enumeration
|
||||
}
|
||||
// supported class TODO custom class
|
||||
else if ( class_code < TUSB_CLASS_MAX_CONSEC_NUMBER && usbh_class_drivers[class_code].open_subtask)
|
||||
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_descriptor_interface_t*) p_desc)->bInterfaceClass );
|
||||
SUBTASK_ASSERT( class_index != 0); // class_code == 0 means corrupted data, abort enumeration
|
||||
|
||||
if (usbh_class_drivers[class_index].open_subtask) // supported class
|
||||
{
|
||||
uint16_t length=0;
|
||||
OSAL_SUBTASK_INVOKED_AND_WAIT ( // parameters in task/sub_task must be static storage (static or global)
|
||||
usbh_class_drivers[ ((tusb_descriptor_interface_t*) p_desc)->bInterfaceClass ].open_subtask(
|
||||
new_addr, (tusb_descriptor_interface_t*) p_desc, &length),
|
||||
usbh_class_drivers[class_index].open_subtask( new_addr, (tusb_descriptor_interface_t*) p_desc, &length ),
|
||||
error
|
||||
);
|
||||
|
||||
if (error != TUSB_ERROR_NONE || length == 0) // Interface open failed, for example a subclass is not supported
|
||||
if (error == TUSB_ERROR_NONE) // 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
|
||||
// TODO can optimize the length --> open_subtask return a OPEN FAILED status
|
||||
SUBTASK_ASSERT( length >= sizeof(tusb_descriptor_interface_t) );
|
||||
usbh_devices[new_addr].flag_supported_class |= BIT_(class_index);
|
||||
p_desc += length;
|
||||
}else
|
||||
{
|
||||
usbh_devices[new_addr].flag_supported_class |= BIT_(((tusb_descriptor_interface_t*) p_desc)->bInterfaceClass);
|
||||
p_desc += length;
|
||||
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)
|
||||
{
|
||||
|
|
|
@ -59,15 +59,19 @@
|
|||
#if MODE_HOST_SUPPORTED
|
||||
#include "host/usbh.h"
|
||||
|
||||
#ifdef HOST_CLASS_HID
|
||||
#if HOST_CLASS_HID
|
||||
#include "class/hid_host.h"
|
||||
#endif
|
||||
|
||||
#define HOST_CLASS_MSC
|
||||
// #define HOST_CLASS_MSC // FIXME hack to test massstorage class
|
||||
#ifdef HOST_CLASS_MSC
|
||||
#include "class/msc_host.h"
|
||||
#endif
|
||||
|
||||
#if TUSB_CFG_HOST_CUSTOM_CLASS
|
||||
#include "class/custom_class.h"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
//------------- DEVICE -------------//
|
||||
|
|
Loading…
Reference in New Issue