[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:
hathach 2013-06-21 13:11:16 +07:00
parent 743e5a7a93
commit 3924764dff
14 changed files with 303 additions and 66 deletions

View File

@ -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)

View File

@ -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_ */
/** @} */

View File

@ -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

View File

@ -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

View File

@ -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,40 +214,33 @@ 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)
{
switch(p_interface_desc->bInterfaceProtocol)
{
#if TUSB_CFG_HOST_HID_KEYBOARD
case HID_PROTOCOL_KEYBOARD:
ASSERT_STATUS ( hidh_interface_open(dev_addr, (tusb_descriptor_endpoint_t const *) p_desc, &keyboard_data[dev_addr-1]) );
if ( tusbh_hid_keyboard_isr )
{
tusbh_hid_keyboard_isr(dev_addr, 0, TUSB_EVENT_INTERFACE_OPEN);
}
break;
#endif
#if TUSB_CFG_HOST_HID_KEYBOARD
case HID_PROTOCOL_KEYBOARD:
ASSERT_STATUS ( hidh_interface_open(dev_addr, (tusb_descriptor_endpoint_t const *) p_desc, &keyboard_data[dev_addr-1]) );
if ( tusbh_hid_keyboard_isr )
{
tusbh_hid_keyboard_isr(dev_addr, 0, TUSB_EVENT_INTERFACE_OPEN);
}
break;
#endif
#if TUSB_CFG_HOST_HID_MOUSE
case HID_PROTOCOL_MOUSE:
ASSERT_STATUS ( hidh_interface_open(dev_addr, (tusb_descriptor_endpoint_t const *) p_desc, &mouse_data[dev_addr-1]) );
if (tusbh_hid_mouse_isr)
{
tusbh_hid_mouse_isr(dev_addr, 0, TUSB_EVENT_INTERFACE_OPEN);
}
break;
#endif
#if TUSB_CFG_HOST_HID_MOUSE
case HID_PROTOCOL_MOUSE:
ASSERT_STATUS ( hidh_interface_open(dev_addr, (tusb_descriptor_endpoint_t const *) p_desc, &mouse_data[dev_addr-1]) );
if (tusbh_hid_mouse_isr)
{
tusbh_hid_mouse_isr(dev_addr, 0, TUSB_EVENT_INTERFACE_OPEN);
}
break;
#endif
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;
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);
return TUSB_ERROR_NONE;
}

View File

@ -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 )\

View File

@ -70,10 +70,13 @@ typedef enum {
}tusb_transfer_type_t;
typedef enum {
TUSB_DIR_HOST_TO_DEV = 0,
TUSB_DIR_DEV_TO_HOST = 1
TUSB_DIR_HOST_TO_DEV = 0,
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 ,

View File

@ -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);

View File

@ -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 );

View File

@ -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

View File

@ -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

View File

@ -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)
{

View File

@ -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)
{

View File

@ -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 -------------//