Files
E3_boot/middleware/usb/uC-USBH/Source/usbh_hub.c
2025-11-07 10:05:24 +08:00

2347 lines
95 KiB
C

/*
*********************************************************************************************************
* uC/USB-Host
* The Embedded USB Host Stack
*
* Copyright 2004-2021 Silicon Laboratories Inc. www.silabs.com
*
* SPDX-License-Identifier: APACHE-2.0
*
* This software is subject to an open source license and is distributed by
* Silicon Laboratories Inc. pursuant to the terms of the Apache License,
* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0.
*
*********************************************************************************************************
*/
/*
*********************************************************************************************************
* NOTICE
*
* Semidrive modified this file to adapt it for ssdk platform.
* The modifications are only intended for use with Semidrive chips.
* Copyright of all the modifications belongs to Semidrive Semiconductor.
*
*********************************************************************************************************
*/
/*
*********************************************************************************************************
*
* USB HOST HUB OPERATIONS
*
* Filename : usbh_hub.c
* Version : V3.42.01
*********************************************************************************************************
*/
/*
*********************************************************************************************************
* INCLUDE FILES
*********************************************************************************************************
*/
#define USBH_HUB_MODULE
#define MICRIUM_SOURCE
#include "usbh_hub.h"
#include "usbh_core.h"
#include "usbh_class.h"
/*
*********************************************************************************************************
* LOCAL DEFINES
*********************************************************************************************************
*/
/*
*********************************************************************************************************
* LOCAL CONSTANTS
*********************************************************************************************************
*/
/*
********************************************************************************************************
* ROOT HUB DEVICE DESCRIPTOR
********************************************************************************************************
*/
static const CPU_INT08U USBH_HUB_RH_DevDesc[18] = {
USBH_LEN_DESC_DEV, /* bLength */
USBH_DESC_TYPE_DEV, /* bDescriptorType: Device */
0x10u, 0x01u, /* bcdUSB: v1.1 */
USBH_CLASS_CODE_HUB, /* bDeviceClass: HUB_CLASSCODE */
USBH_SUBCLASS_CODE_USE_IF_DESC, /* bDeviceSubClass */
USBH_PROTOCOL_CODE_USE_IF_DESC, /* bDeviceProtocol */
0x40u, /* bMaxPacketSize0: 64 Bytes */
0x00u, 0x00u, /* idVendor */
0x00u, 0x00u, /* idProduct */
0x00u, 0x00u, /* bcdDevice */
0x00u, /* iManufacturer */
0x00u, /* iProduct */
0x00u, /* iSerialNumber */
0x01u /* bNumConfigurations */
};
/*
********************************************************************************************************
* ROOT HUB CONFIGURATION DESCRIPTOR
********************************************************************************************************
*/
static const CPU_INT08U USBH_HUB_RH_FS_CfgDesc[] = {
/* ------------- CONFIGURATION DESCRIPTOR ------------- */
USBH_LEN_DESC_CFG, /* bLength */
USBH_DESC_TYPE_CFG, /* bDescriptorType CONFIGURATION */
0x19u, 0x00u, /* le16 wTotalLength */
0x01u, /* bNumInterfaces */
0x01u, /* bConfigurationValue */
0x00u, /* iConfiguration */
0xC0u, /* bmAttributes -> Self-powered|Remote wakeup */
0x00u, /* bMaxPower */
/* --------------- INTERFACE DESCRIPTOR --------------- */
USBH_LEN_DESC_IF, /* bLength */
USBH_DESC_TYPE_IF, /* bDescriptorType: Interface */
0x00u, /* bInterfaceNumber */
0x00u, /* bAlternateSetting */
0x01u, /* bNumEndpoints */
USBH_CLASS_CODE_HUB, /* bInterfaceClass HUB_CLASSCODE */
0x00u, /* bInterfaceSubClass */
0x00u, /* bInterfaceProtocol */
0x00u, /* iInterface */
/* --------------- ENDPOINT DESCRIPTOR ---------------- */
USBH_LEN_DESC_EP, /* bLength */
USBH_DESC_TYPE_EP, /* bDescriptorType: Endpoint */
0x81u, /* bEndpointAddress: IN Endpoint 1 */
0x03u, /* bmAttributes Interrupt */
0x08u, 0x00u, /* wMaxPacketSize */
0x1u /* bInterval */
};
/*
********************************************************************************************************
* ROOT HUB STRING DESCRIPTOR
*
* Note(s): (1) A USB device can store strings in multiple languages. i.e. the string index defines which
* word or phrase should be communicated to the user and the LANGID code identifies to a
* device, which language to retrieve that word or phase for. The LANGIDs are defined in the
* document called "Language Identifiers (LANGIDs), 3/29/00, Version 1.0" available at
* http://www.usb.org/developers/docs/USB_LANGIDs.pdf.
********************************************************************************************************
*/
static const CPU_INT08U USBH_HUB_RH_LangID[] = {
0x04u,
USBH_DESC_TYPE_STR,
0x09u, 0x04u, /* Identifer for English (United States). See Note #1. */
};
/*
*********************************************************************************************************
* LOCAL DATA TYPES
*********************************************************************************************************
*/
/*
*********************************************************************************************************
* LOCAL TABLES
*********************************************************************************************************
*/
/*
*********************************************************************************************************
* LOCAL GLOBAL VARIABLES
*********************************************************************************************************
*/
static CPU_INT08U USBH_HUB_DescBuf[LEN_CACHE_ALIGN(USBH_HUB_MAX_DESC_LEN)] __CACHE_ALIGN;
static USBH_HUB_DEV USBH_HUB_Arr[USBH_CFG_MAX_HUBS];
static MEM_POOL USBH_HUB_Pool;
static volatile USBH_HUB_DEV *USBH_HUB_HeadPtr;
static volatile USBH_HUB_DEV *USBH_HUB_TailPtr;
static volatile USBH_HSEM USBH_HUB_EventSem;
/*
*********************************************************************************************************
* LOCAL FUNCTION PROTOTYPES
*********************************************************************************************************
*/
static void USBH_HUB_GlobalInit (USBH_ERR *p_err);
static void *USBH_HUB_IF_Probe (USBH_DEV *p_dev,
USBH_IF *p_if,
USBH_ERR *p_err);
static void USBH_HUB_Suspend (void *p_class_dev);
static void USBH_HUB_Resume (void *p_class_dev);
static void USBH_HUB_Disconn (void *p_class_dev);
static USBH_ERR USBH_HUB_Init (USBH_HUB_DEV *p_hub_dev);
static void USBH_HUB_Uninit (USBH_HUB_DEV *p_hub_dev);
static USBH_ERR USBH_HUB_EP_Open (USBH_HUB_DEV *p_hub_dev);
static void USBH_HUB_EP_Close (USBH_HUB_DEV *p_hub_dev);
static USBH_ERR USBH_HUB_EventReq (USBH_HUB_DEV *p_hub_dev);
static void USBH_HUB_ISR (USBH_EP *p_ep,
void *p_buf,
CPU_INT32U buf_len,
CPU_INT32U xfer_len,
void *p_arg,
USBH_ERR err);
static void USBH_HUB_EventProcess (void);
static USBH_ERR USBH_HUB_DescGet (USBH_HUB_DEV *p_hub_dev);
static USBH_ERR USBH_HUB_PortsInit (USBH_HUB_DEV *p_hub_dev);
static USBH_ERR USBH_HUB_PortStatusGet (USBH_HUB_DEV *p_hub_dev,
CPU_INT16U port_nbr,
USBH_HUB_PORT_STATUS *p_port_status);
static USBH_ERR USBH_HUB_PortResetSet (USBH_HUB_DEV *p_hub_dev,
CPU_INT16U port_nbr);
static USBH_ERR USBH_HUB_PortRstChngClr (USBH_HUB_DEV *p_hub_dev,
CPU_INT16U port_nbr);
static USBH_ERR USBH_HUB_PortEnChngClr (USBH_HUB_DEV *p_hub_dev,
CPU_INT16U port_nbr);
static USBH_ERR USBH_HUB_PortConnChngClr (USBH_HUB_DEV *p_hub_dev,
CPU_INT16U port_nbr);
static USBH_ERR USBH_HUB_PortPwrSet (USBH_HUB_DEV *p_hub_dev,
CPU_INT16U port_nbr);
static USBH_ERR USBH_HUB_PortSuspendClr (USBH_HUB_DEV *p_hub_dev,
CPU_INT16U port_nbr);
static USBH_ERR USBH_HUB_PortEnClr (USBH_HUB_DEV *p_hub_dev,
CPU_INT16U port_nbr);
static USBH_ERR USBH_HUB_PortEnSet (USBH_HUB_DEV *p_hub_dev,
CPU_INT16U port_nbr);
static void USBH_HUB_Clr (USBH_HUB_DEV *p_hub_dev);
static USBH_ERR USBH_HUB_RefAdd (USBH_HUB_DEV *p_hub_dev);
static USBH_ERR USBH_HUB_RefRel (USBH_HUB_DEV *p_hub_dev);
/*
*********************************************************************************************************
* LOCAL CONFIGURATION ERRORS
*********************************************************************************************************
*/
/*
*********************************************************************************************************
* HUB CLASS DRIVER
*********************************************************************************************************
*/
USBH_CLASS_DRV USBH_HUB_Drv = {
(CPU_INT08U *)"HUB",
USBH_HUB_GlobalInit,
0,
USBH_HUB_IF_Probe,
USBH_HUB_Suspend,
USBH_HUB_Resume,
USBH_HUB_Disconn
};
/*
*********************************************************************************************************
*********************************************************************************************************
* GLOBAL FUNCTION
*********************************************************************************************************
*********************************************************************************************************
*/
/*
*********************************************************************************************************
* USBH_HUB_EventTask()
*
* Description : Task that process HUB Events.
*
* Argument(s) : None.
*
* Return(s) : None.
*
* Note(s) : None.
*********************************************************************************************************
*/
void USBH_HUB_EventTask (void *p_arg)
{
(void)p_arg;
while (DEF_TRUE) {
(void)USBH_OS_SemWait(USBH_HUB_EventSem, 0u);
USBH_HUB_EventProcess();
}
}
/*
*********************************************************************************************************
* USBH_HUB_PortDis()
*
* Description : Disable given port on hub.
*
* Argument(s) : p_hub_dev Pointer to hub.
*
* port_nbr Port number.
*
* Return(s) : USBH_ERR_NONE, If port is successfully disabled.
* USBH_ERR_INVALID_ARG, If invalid parameter passed to 'p_hub_dev'.
*
* ----- RETURNED BY USBH_HUB_PortEnClr() : -----
* USBH_ERR_UNKNOWN, Unknown error occurred.
* USBH_ERR_INVALID_ARG, Invalid argument passed to 'p_ep'.
* USBH_ERR_EP_INVALID_STATE, Endpoint is not opened.
* USBH_ERR_HC_IO, Root hub input/output error.
* USBH_ERR_EP_STALL, Root hub does not support request.
* Host controller drivers error code, Otherwise.
*
* Note(s) : None
*********************************************************************************************************
*/
USBH_ERR USBH_HUB_PortDis (USBH_HUB_DEV *p_hub_dev,
CPU_INT16U port_nbr)
{
USBH_ERR err;
if (p_hub_dev == (USBH_HUB_DEV *)0) {
return (USBH_ERR_INVALID_ARG);
}
err = USBH_HUB_PortEnClr(p_hub_dev, port_nbr);
return (err);
}
/*
*********************************************************************************************************
* USBH_HUB_PortEn()
*
* Description : Enable given port on hub.
*
* Argument(s) : p_hub_dev Pointer to hub.
*
* port_nbr Port number.
*
* Return(s) : USBH_ERR_NONE, If port is successfully enabled.
* USBH_ERR_INVALID_ARG, If invalid parameter passed to 'p_hub_dev'.
*
* ----- RETURNED BY USBH_HUB_PortEnSet() : -----
* USBH_ERR_UNKNOWN, Unknown error occurred.
* USBH_ERR_INVALID_ARG, Invalid argument passed to 'p_ep'.
* USBH_ERR_EP_INVALID_STATE, Endpoint is not opened.
* USBH_ERR_HC_IO, Root hub input/output error.
* USBH_ERR_EP_STALL, Root hub does not support request.
* Host controller drivers error code, Otherwise.
*
* Note(s) : None.
*********************************************************************************************************
*/
USBH_ERR USBH_HUB_PortEn (USBH_HUB_DEV *p_hub_dev,
CPU_INT16U port_nbr)
{
USBH_ERR err;
if (p_hub_dev == (USBH_HUB_DEV *)0) {
return (USBH_ERR_INVALID_ARG);
}
err = USBH_HUB_PortEnSet(p_hub_dev, port_nbr);
return (err);
}
/*
*********************************************************************************************************
*********************************************************************************************************
* LOCAL FUNCTIONS
*********************************************************************************************************
*********************************************************************************************************
*/
/*
*********************************************************************************************************
* USBH_HUB_GlobalInit()
*
* Description : Initializes all USBH_HUB_DEV structures, device lists and HUB pool.
*
* Argument(s) : p_err Pointer to variable that will receive the return error code from this function :
*
* USBH_ERR_NONE If initialization is successful.
* USBH_ERR_ALLOC If failed to create hub memory pool.
*
* ----- RETURNED BY USBH_OS_SemCreate() : -----
* USBH_ERR_OS_SIGNAL_CREATE, If semaphore creation failed.
*
* Return(s) : None.
*
* Note(s) : None.
*********************************************************************************************************
*/
static void USBH_HUB_GlobalInit (USBH_ERR *p_err)
{
CPU_INT08U hub_ix;
CPU_SIZE_T octets_reqd;
LIB_ERR err_lib;
for (hub_ix = 0u; hub_ix < USBH_CFG_MAX_HUBS; hub_ix++) { /* Clr all HUB dev structs. */
USBH_HUB_Clr(&USBH_HUB_Arr[hub_ix]);
}
Mem_PoolCreate ( &USBH_HUB_Pool, /* POOL for managing hub dev structs. */
(void *)USBH_HUB_Arr,
sizeof(USBH_HUB_DEV) * USBH_CFG_MAX_HUBS,
USBH_CFG_MAX_HUBS,
sizeof(USBH_HUB_DEV),
sizeof(CPU_ALIGN),
&octets_reqd,
&err_lib);
if (err_lib != LIB_MEM_ERR_NONE) {
*p_err = USBH_ERR_ALLOC;
return;
}
*p_err = USBH_OS_SemCreate((USBH_HSEM *)&USBH_HUB_EventSem,
0u);
USBH_HUB_HeadPtr = (USBH_HUB_DEV *)0;
USBH_HUB_TailPtr = (USBH_HUB_DEV *)0;
Mem_Clr((void *)USBH_HUB_DescBuf,
USBH_HUB_MAX_DESC_LEN);
}
/*
*********************************************************************************************************
* USBH_HUB_IF_Probe()
*
* Description : Determine whether connected device implements hub class by examining it's interface
* descriptor.
*
* Argument(s) : p_dev Pointer to device.
*
* p_if Pointer to interface.
*
* p_err Pointer to variable that will receive the return error code from this function :
*
* USBH_ERR_NONE Device implements hub class.
* USBH_ERR_DEV_ALLOC No more space in hub memory pool.
* USBH_ERR_CLASS_DRV_NOT_FOUND Device does not implement hub class.
*
* ----- RETURNED BY USBH_IF_DescGet() : -----
* USBH_ERR_INVALID_ARG, Invalid argument passed to 'alt_ix'.
*
* ----- RETURNED BY USBH_HUB_Init() : -----
* USBH_ERR_DESC_INVALID, if hub descriptor is invalid.
* USBH_ERR_UNKNOWN, Unknown error occurred.
* USBH_ERR_INVALID_ARG, Invalid argument passed to 'p_ep'.
* USBH_ERR_EP_INVALID_STATE, Endpoint is not opened.
* USBH_ERR_HC_IO, Root hub input/output error.
* USBH_ERR_EP_STALL, Root hub does not support request.
* USBH_ERR_EP_ALLOC, If USBH_CFG_MAX_NBR_EPS reached.
* USBH_ERR_EP_NOT_FOUND, If endpoint with given type and direction not found.
* USBH_ERR_OS_SIGNAL_CREATE, if mutex or semaphore creation failed.
* USBH_ERR_UNKNOWN, Unknown error occurred.
* USBH_ERR_INVALID_ARG, Invalid argument passed to 'p_ep'.
* USBH_ERR_HC_IO, Root hub input/output error.
* USBH_ERR_EP_INVALID_TYPE If endpoint type is not interrupt or direction is not IN.
* USBH_ERR_ALLOC If URB cannot be allocated.
* Host controller drivers error code, Otherwise.
*
* Return(s) : Pointer to hub device structure, If probe is successful.
* 0, Otherwise.
*
* Note(s) : None.
*********************************************************************************************************
*/
static void *USBH_HUB_IF_Probe (USBH_DEV *p_dev,
USBH_IF *p_if,
USBH_ERR *p_err)
{
USBH_HUB_DEV *p_hub_dev;
USBH_IF_DESC if_desc;
LIB_ERR err_lib;
p_hub_dev = (USBH_HUB_DEV *)0;
*p_err = USBH_IF_DescGet(p_if, /* Get IF desc. */
0u,
&if_desc);
if (*p_err != USBH_ERR_NONE) {
return ((void *)0);
}
if (if_desc.bInterfaceClass == USBH_CLASS_CODE_HUB) { /* If IF is HUB, alloc HUB dev. */
p_hub_dev = (USBH_HUB_DEV *)Mem_PoolBlkGet(&USBH_HUB_Pool,
sizeof(USBH_HUB_DEV),
&err_lib);
if (err_lib != LIB_MEM_ERR_NONE) {
*p_err = USBH_ERR_DEV_ALLOC;
return ((void *)0);
}
USBH_HUB_Clr(p_hub_dev);
USBH_HUB_RefAdd(p_hub_dev);
p_hub_dev->State = (CPU_INT08U)USBH_CLASS_DEV_STATE_CONN;
p_hub_dev->DevPtr = p_dev;
p_hub_dev->IF_Ptr = p_if;
p_hub_dev->ErrCnt = 0u;
if ((p_dev->IsRootHub == DEF_TRUE) &&
(p_dev->HC_Ptr->IsVirRootHub == DEF_TRUE)) {
p_dev->HC_Ptr->RH_ClassDevPtr = p_hub_dev;
}
*p_err = USBH_HUB_Init(p_hub_dev); /* Init HUB. */
if (*p_err != USBH_ERR_NONE) {
USBH_HUB_RefRel(p_hub_dev);
}
} else {
*p_err = USBH_ERR_CLASS_DRV_NOT_FOUND;
}
return ((void *)p_hub_dev);
}
/*
*********************************************************************************************************
* USBH_HUB_Suspend()
*
* Description : Suspend given hub and all devices connected to it.
*
* Argument(s) : p_class_dev Pointer to hub structure.
*
* Return(s) : None.
*
* Note(s) : None.
*********************************************************************************************************
*/
static void USBH_HUB_Suspend (void *p_class_dev)
{
CPU_INT16U nbr_ports;
CPU_INT16U port_ix;
USBH_DEV *p_dev;
USBH_HUB_DEV *p_hub_dev;
p_hub_dev = (USBH_HUB_DEV *)p_class_dev;
nbr_ports = DEF_MIN(p_hub_dev->Desc.bNbrPorts,
USBH_CFG_MAX_HUB_PORTS);
for (port_ix = 0u; port_ix < nbr_ports; port_ix++) {
p_dev = (USBH_DEV *)p_hub_dev->DevPtrList[port_ix];
if (p_dev != (USBH_DEV *)0){
USBH_ClassSuspend(p_dev);
}
}
}
/*
*********************************************************************************************************
* USBH_HUB_Resume()
*
* Description : Resume given hub and all devices connected to it.
*
* Argument(s) : p_class_dev Pointer to hub device.
*
* Return(s) : None.
*
* Note(s) : (1) According to 'Universal Serial Bus Specification Revision 2.0', Section 11.5.1.10,
* "[the resuming state] is a timed state with a nominal duration of 20ms"
*********************************************************************************************************
*/
static void USBH_HUB_Resume (void *p_class_dev)
{
CPU_INT16U nbr_ports;
CPU_INT16U port_ix;
USBH_DEV *p_dev;
USBH_HUB_DEV *p_hub_dev;
USBH_HUB_PORT_STATUS port_status;
p_hub_dev = (USBH_HUB_DEV *)p_class_dev;
nbr_ports = DEF_MIN(p_hub_dev->Desc.bNbrPorts,
USBH_CFG_MAX_HUB_PORTS);
for (port_ix = 0u; port_ix < nbr_ports; port_ix++) {
USBH_HUB_PortSuspendClr(p_hub_dev, port_ix + 1u); /* En resume signaling on port. */
}
USBH_OS_DlyMS(20u + 12u); /* See Note (1). */
for (port_ix = 0u; port_ix < nbr_ports; port_ix++) {
p_dev = p_hub_dev->DevPtrList[port_ix];
if (p_dev != (USBH_DEV *)0){
USBH_ClassResume(p_dev);
} else { /* Get port status info. */
(void)USBH_HUB_PortStatusGet(p_hub_dev,
port_ix + 1u,
&port_status);
if ((port_status.wPortStatus & USBH_HUB_STATUS_PORT_CONN) != 0u) {
(void)USBH_HUB_PortResetSet(p_hub_dev,
port_ix + 1u);
}
}
}
}
/*
*********************************************************************************************************
* USBH_HUB_Disconn()
*
* Description : Disconnect given hub.
*
* Argument(s) : p_class_dev Pointer to hub device.
*
* Return(s) : None.
*
* Note(s) : None.
*********************************************************************************************************
*/
static void USBH_HUB_Disconn (void *p_class_dev)
{
USBH_HUB_DEV *p_hub_dev;
p_hub_dev = (USBH_HUB_DEV *)p_class_dev;
p_hub_dev->State = USBH_CLASS_DEV_STATE_DISCONN;
USBH_HUB_Uninit(p_hub_dev);
USBH_HUB_RefRel(p_hub_dev);
}
/*
*********************************************************************************************************
* USBH_HUB_Init()
*
* Description : Opens the endpoints, reads hub descriptor, initializes ports and submits request to
* start receiving hub events.
*
* Argument(s) : p_hub_dev Pointer to hub structure.
*
* Return(s) : USBH_ERR_NONE, If hub is successfully initialized.
*
* ----- RETURNED BY USBH_HUB_DescGet() : -----
* USBH_ERR_DESC_INVALID, if hub descriptor is invalid.
* USBH_ERR_UNKNOWN, Unknown error occurred.
* USBH_ERR_INVALID_ARG, Invalid argument passed to 'p_ep'.
* USBH_ERR_EP_INVALID_STATE, Endpoint is not opened.
* USBH_ERR_HC_IO, Root hub input/output error.
* USBH_ERR_EP_STALL, Root hub does not support request.
* Host controller drivers error code, Otherwise.
*
* ----- RETURNED BY USBH_HUB_EP_Open() : -----
* USBH_ERR_EP_ALLOC, If USBH_CFG_MAX_NBR_EPS reached.
* USBH_ERR_EP_NOT_FOUND, If endpoint with given type and direction not found.
* USBH_ERR_OS_SIGNAL_CREATE, if mutex or semaphore creation failed.
* Host controller drivers error, Otherwise.
*
* ----- RETURNED BY USBH_HUB_PortsInit() : -----
* USBH_ERR_UNKNOWN, Unknown error occurred.
* USBH_ERR_INVALID_ARG, Invalid argument passed to 'p_ep'.
* USBH_ERR_EP_INVALID_STATE, Endpoint is not opened.
* USBH_ERR_HC_IO, Root hub input/output error.
* USBH_ERR_EP_STALL, Root hub does not support request.
* Host controller drivers error code, Otherwise.
*
* ----- RETURNED BY USBH_HUB_EventReq() : -----
* USBH_ERR_INVALID_ARG If invalid argument passed to 'p_ep'.
* USBH_ERR_EP_INVALID_TYPE If endpoint type is not interrupt or direction is not IN.
* USBH_ERR_EP_INVALID_STATE If endpoint is not opened.
* USBH_ERR_ALLOC If URB cannot be allocated.
* USBH_ERR_UNKNOWN If unknown error occured.
* Host controller drivers error code, Otherwise.
*
* Note(s) : None.
*********************************************************************************************************
*/
static USBH_ERR USBH_HUB_Init (USBH_HUB_DEV *p_hub_dev)
{
USBH_ERR err;
err = USBH_HUB_EP_Open(p_hub_dev); /* Open intr EP. */
if (err != USBH_ERR_NONE) {
return (err);
}
err = USBH_HUB_DescGet(p_hub_dev); /* Get hub desc. */
if (err != USBH_ERR_NONE) {
return (err);
}
err = USBH_HUB_PortsInit(p_hub_dev); /* Init hub ports. */
if (err != USBH_ERR_NONE) {
return (err);
}
err = USBH_HUB_EventReq(p_hub_dev); /* Start receiving hub evts. */
return (err);
}
/*
*********************************************************************************************************
* USBH_HUB_Uninit()
*
* Description : Uninitialize given hub.
*
* Argument(s) : p_hub_dev Pointer to hub device.
*
* Return(s) : None.
*
* Note(s) : None.
*********************************************************************************************************
*/
static void USBH_HUB_Uninit (USBH_HUB_DEV *p_hub_dev)
{
CPU_INT16U nbr_ports;
CPU_INT16U port_ix;
USBH_DEV *p_dev;
LIB_ERR err;
USBH_HUB_EP_Close(p_hub_dev);
nbr_ports = DEF_MIN(p_hub_dev->Desc.bNbrPorts,
USBH_CFG_MAX_HUB_PORTS);
for (port_ix = 0u; port_ix < nbr_ports; port_ix++) {
p_dev = (USBH_DEV *)p_hub_dev->DevPtrList[port_ix];
if (p_dev != (USBH_DEV *)0){
USBH_DevDisconn(p_dev);
Mem_PoolBlkFree( &p_hub_dev->DevPtr->HC_Ptr->HostPtr->DevPool,
(void *)p_dev,
&err);
p_hub_dev->DevPtrList[port_ix] = (USBH_DEV *)0;
}
}
}
/*
*********************************************************************************************************
* USBH_HUB_EP_Open()
*
* Description : Open interrupt endpoint required to receive hub events.
*
* Argument(s) : p_hub_dev Pointer to hub device.
*
* Return(s) : USBH_ERR_NONE, if the endpoints are opened.
*
* ----- RETURNED BY USBH_IntrInOpen() : -----
* USBH_ERR_EP_ALLOC, If USBH_CFG_MAX_NBR_EPS reached.
* USBH_ERR_EP_NOT_FOUND, If endpoint with given type and direction not found.
* USBH_ERR_OS_SIGNAL_CREATE, if mutex or semaphore creation failed.
* Host controller drivers error, Otherwise.
*
* Note(s) : None.
*********************************************************************************************************
*/
static USBH_ERR USBH_HUB_EP_Open (USBH_HUB_DEV *p_hub_dev)
{
USBH_ERR err;
USBH_DEV *p_dev;
USBH_IF *p_if;
p_dev = p_hub_dev->DevPtr;
p_if = p_hub_dev->IF_Ptr;
err = USBH_IntrInOpen(p_dev, /* Find and open hub intr EP. */
p_if,
&p_hub_dev->IntrEP);
return (err);
}
/*
*********************************************************************************************************
* USBH_HUB_EP_Close()
*
* Description : Close interrupt endpoint.
*
* Argument(s) : p_hub_dev Pointer to hub device.
*
* Return(s) : None.
*
* Note(s) : None.
*********************************************************************************************************
*/
static void USBH_HUB_EP_Close (USBH_HUB_DEV *p_hub_dev)
{
USBH_EP_Close(&p_hub_dev->IntrEP); /* Close hub intr EP. */
}
/*
*********************************************************************************************************
* USBH_HUB_EventReq()
*
* Description : Issue an asynchronous interrupt request to receive hub events.
*
* Argument(s) : p_hub_dev Pointer to the hub device structure.
*
* Return(s) : USBH_ERR_NONE If hub events are started
*
* ----- RETURNED BY USBH_IntrRxAsync() : -----
* USBH_ERR_NONE If request is successfully submitted.
* USBH_ERR_INVALID_ARG If invalid argument passed to 'p_ep'.
* USBH_ERR_EP_INVALID_TYPE If endpoint type is not interrupt or direction is not IN.
* USBH_ERR_EP_INVALID_STATE If endpoint is not opened.
* USBH_ERR_ALLOC If URB cannot be allocated.
* USBH_ERR_UNKNOWN If unknown error occured.
* Host controller drivers error code, Otherwise.
*
* Note(s) : (1) Hub reports only as many bits as there are ports on the hub,
* subject to the byte-granularity requirement (i.e., round up to the nearest byte)
* (See section 11.12.4, USB 2.0 spec)
*********************************************************************************************************
*/
static USBH_ERR USBH_HUB_EventReq (USBH_HUB_DEV *p_hub_dev)
{
CPU_INT32U len;
CPU_BOOLEAN valid;
USBH_HC_RH_API *p_rh_api;
USBH_ERR err;
USBH_DEV *p_dev;
p_dev = p_hub_dev->DevPtr;
if ((p_dev->IsRootHub == DEF_TRUE) && /* Chk if RH fncts are supported before calling HCD. */
(p_dev->HC_Ptr->IsVirRootHub == DEF_TRUE)) {
p_rh_api = p_dev->HC_Ptr->HC_Drv.RH_API_Ptr;
valid = p_rh_api->IntEn(&p_dev->HC_Ptr->HC_Drv);
if (valid != DEF_OK) {
return (USBH_ERR_HC_IO);
} else {
return (USBH_ERR_NONE);
}
}
len = (p_hub_dev->Desc.bNbrPorts / 8u) + 1u; /* See Note (1). */
err = USBH_IntrRxAsync( &p_hub_dev->IntrEP, /* Start receiving hub events. */
(void *)p_hub_dev->HubIntrBuf,
len,
USBH_HUB_ISR,
(void *)p_hub_dev);
return (err);
}
/*
*********************************************************************************************************
* USBH_HUB_ISR()
*
* Description : Handles hub interrupt.
*
* Argument(s) : p_ep Pointer to endpoint.
*
* p_buf Pointer to data buffer.
*
* buf_len Buffer length in octets.
*
* xfer_len Transfered length.
*
* p_arg Context Pointer.
*
* err Error code.
*
* Return(s) : None.
*
* Note(s) : None.
*********************************************************************************************************
*/
static void USBH_HUB_ISR (USBH_EP *p_ep,
void *p_buf,
CPU_INT32U buf_len,
CPU_INT32U xfer_len,
void *p_arg,
USBH_ERR err)
{
USBH_HUB_DEV *p_hub_dev;
CPU_SR_ALLOC();
(void)buf_len;
(void)p_buf;
(void)p_ep;
(void)xfer_len;
p_hub_dev = (USBH_HUB_DEV *)p_arg;
if (err != USBH_ERR_NONE) {
if (p_hub_dev->State == USBH_CLASS_DEV_STATE_CONN) {
if (p_hub_dev->ErrCnt < 3u) {
#if (USBH_CFG_PRINT_LOG == DEF_ENABLED)
USBH_PRINT_LOG("USBH_HUB_ISR() fails. Err=%d errcnt=%d\r\n",
err,
p_hub_dev->ErrCnt);
#endif
p_hub_dev->ErrCnt++;
USBH_HUB_EventReq(p_hub_dev); /* Retry URB. */
}
}
return;
}
p_hub_dev->ErrCnt = 0u;
USBH_HUB_RefAdd(p_hub_dev);
CPU_CRITICAL_ENTER();
if (USBH_HUB_HeadPtr == (USBH_HUB_DEV *)0) {
USBH_HUB_HeadPtr = USBH_HUB_TailPtr = p_hub_dev;
} else {
USBH_HUB_TailPtr->NxtPtr = p_hub_dev;
USBH_HUB_TailPtr = p_hub_dev;
}
CPU_CRITICAL_EXIT();
(void)USBH_OS_SemPost(USBH_HUB_EventSem);
}
/*
*********************************************************************************************************
* USBH_HUB_EventProcess()
*
* Description : Determine status of each of hub ports. Newly connected device will be reset & configured.
* Appropriate notifications & cleanup will be performed if a device has been disconnected.
*
* Argument(s) : None.
*
* Return(s) : None.
*
* Note(s) : (1) Some device require a delay following connection detection. This is related to the
* debounce interval which ensures that power is stable at the device for at least 100 ms
* before any requests will be sent to the device (See section 11.8.2, USB 2.0 spec).
*
* (2) Open Host Controller Interface specification Release 1.0a states that Port Reset Status
* Change bit is set at the end of 10 ms port reset signal. See section 7.4.4, PRSC field.
*********************************************************************************************************
*/
static void USBH_HUB_EventProcess (void)
{
CPU_INT16U nbr_ports;
CPU_INT16U port_nbr;
MEM_POOL *p_dev_pool;
LIB_ERR err_lib;
USBH_DEV_SPD dev_spd;
USBH_HUB_DEV *p_hub_dev;
USBH_HUB_PORT_STATUS port_status;
USBH_DEV *p_dev;
USBH_ERR err;
CPU_SR_ALLOC();
CPU_CRITICAL_ENTER();
p_hub_dev = (USBH_HUB_DEV *)USBH_HUB_HeadPtr;
if (USBH_HUB_HeadPtr == USBH_HUB_TailPtr) {
USBH_HUB_HeadPtr = (USBH_HUB_DEV *)0;
USBH_HUB_TailPtr = (USBH_HUB_DEV *)0;
} else {
USBH_HUB_HeadPtr = USBH_HUB_HeadPtr->NxtPtr;
}
CPU_CRITICAL_EXIT();
if (p_hub_dev == (USBH_HUB_DEV *)0) {
return;
}
if (p_hub_dev->State == USBH_CLASS_DEV_STATE_DISCONN) {
err = USBH_HUB_RefRel(p_hub_dev);
if (err != USBH_ERR_NONE) {
USBH_PRINT_ERR(err);
}
return;
}
port_nbr = 1u;
p_dev_pool = &p_hub_dev->DevPtr->HC_Ptr->HostPtr->DevPool;
nbr_ports = DEF_MIN(p_hub_dev->Desc.bNbrPorts,
USBH_CFG_MAX_HUB_PORTS);
while (port_nbr <= nbr_ports) {
err = USBH_HUB_PortStatusGet(p_hub_dev, /* Get port status info.. */
port_nbr,
&port_status);
if (err != USBH_ERR_NONE) {
break;
}
/* ------------- CONNECTION STATUS CHANGE ------------- */
if (DEF_BIT_IS_SET(port_status.wPortChange, USBH_HUB_STATUS_C_PORT_CONN) == DEF_TRUE) {
err = USBH_HUB_PortConnChngClr(p_hub_dev, /* Clr port conn chng. */
port_nbr);
if (err != USBH_ERR_NONE) {
break;
}
/* -------------- DEV HAS BEEN CONNECTED -------------- */
if (DEF_BIT_IS_SET(port_status.wPortStatus, USBH_HUB_STATUS_PORT_CONN) == DEF_TRUE) {
#if (USBH_CFG_PRINT_LOG == DEF_ENABLED)
USBH_PRINT_LOG("Port %d.%d : Device Connected.\r\n", p_hub_dev->DevPtr->DevAddr, port_nbr);
#endif
p_hub_dev->ConnCnt = 0; /* Reset re-connection counter */
p_dev = p_hub_dev->DevPtrList[port_nbr - 1u];
if (p_dev != (USBH_DEV *)0) {
USBH_DevDisconn(p_dev);
Mem_PoolBlkFree( p_dev_pool,
(void *)p_dev,
&err_lib);
p_hub_dev->DevPtrList[port_nbr - 1u] = (USBH_DEV *)0;
}
USBH_OS_DlyMS(100u); /* See Notes #1. */
err = USBH_HUB_PortResetSet(p_hub_dev, /* Apply port reset. */
port_nbr);
if (err != USBH_ERR_NONE) {
break;
}
USBH_OS_DlyMS(USBH_HUB_DLY_DEV_RESET); /* See Notes #2. */
continue; /* Handle port reset status change. */
} else { /* --------------- DEV HAS BEEN REMOVED --------------- */
#if (USBH_CFG_PRINT_LOG == DEF_ENABLED)
USBH_PRINT_LOG("Port %d.%d : Device Removed.\r\n", p_hub_dev->DevPtr->DevAddr, port_nbr);
#endif
USBH_OS_DlyMS(10u); /* Wait for any pending I/O xfer to rtn err. */
p_dev = p_hub_dev->DevPtrList[port_nbr - 1u];
if (p_dev != (USBH_DEV *)0) {
USBH_DevDisconn(p_dev);
Mem_PoolBlkFree( p_dev_pool,
(void *)p_dev,
&err_lib);
p_hub_dev->DevPtrList[port_nbr - 1u] = (USBH_DEV *)0;
}
}
}
/* ------------- PORT RESET STATUS CHANGE ------------- */
if (DEF_BIT_IS_SET(port_status.wPortChange, USBH_HUB_STATUS_C_PORT_RESET) == DEF_TRUE) {
err = USBH_HUB_PortRstChngClr(p_hub_dev, port_nbr);
if (err != USBH_ERR_NONE) {
break;
}
/* Dev has been connected. */
if (DEF_BIT_IS_SET(port_status.wPortStatus, USBH_HUB_STATUS_PORT_CONN) == DEF_TRUE) {
err = USBH_HUB_PortStatusGet(p_hub_dev, /* Get port status info. */
port_nbr,
&port_status);
if (err != USBH_ERR_NONE) {
break;
}
/* Determine dev spd. */
if (DEF_BIT_IS_SET(port_status.wPortStatus, USBH_HUB_STATUS_PORT_LOW_SPD) == DEF_TRUE) {
dev_spd = USBH_DEV_SPD_LOW;
} else if (DEF_BIT_IS_SET(port_status.wPortStatus, USBH_HUB_STATUS_PORT_HIGH_SPD) == DEF_TRUE) {
dev_spd = USBH_DEV_SPD_HIGH;
} else {
dev_spd = USBH_DEV_SPD_FULL;
}
#if (USBH_CFG_PRINT_LOG == DEF_ENABLED)
USBH_PRINT_LOG("Port %d : Port Reset complete, device speed is %s\r\n", port_nbr,
(dev_spd == USBH_DEV_SPD_LOW) ? "LOW Speed(1.5 Mb/Sec)" :
(dev_spd == USBH_DEV_SPD_FULL) ? "FULL Speed(12 Mb/Sec)" :
"HIGH Speed(480 Mb/Sec)");
#endif
p_dev = p_hub_dev->DevPtrList[port_nbr - 1u];
if (p_dev != (USBH_DEV *)0) {
continue;
}
if (p_hub_dev->DevPtr->HC_Ptr->HostPtr->State == USBH_HOST_STATE_SUSPENDED) {
continue;
}
p_dev = (USBH_DEV *)Mem_PoolBlkGet(p_dev_pool,
sizeof(USBH_DEV),
&err_lib);
if (err_lib != LIB_MEM_ERR_NONE) {
USBH_HUB_PortDis(p_hub_dev, port_nbr);
USBH_HUB_RefRel(p_hub_dev);
#if (USBH_CFG_PRINT_LOG == DEF_ENABLED)
USBH_PRINT_LOG("ERROR: Cannot allocate device.\r\n");
#endif
USBH_HUB_EventReq(p_hub_dev); /* Retry URB. */
return;
}
p_dev->DevSpd = dev_spd;
p_dev->HubDevPtr = p_hub_dev->DevPtr;
p_dev->PortNbr = port_nbr;
p_dev->HC_Ptr = p_hub_dev->DevPtr->HC_Ptr;
if (dev_spd == USBH_DEV_SPD_HIGH) {
p_dev->HubHS_Ptr = p_hub_dev;
} else {
if (p_hub_dev->IntrEP.DevSpd == USBH_DEV_SPD_HIGH) {
p_dev->HubHS_Ptr = p_hub_dev;
} else {
p_dev->HubHS_Ptr = p_hub_dev->DevPtr->HubHS_Ptr;
}
}
USBH_OS_DlyMS(50u);
err = USBH_DevConn(p_dev); /* Conn dev. */
if (err != USBH_ERR_NONE) {
USBH_PRINT_ERR(err);
USBH_HUB_PortDis(p_hub_dev, port_nbr);
USBH_DevDisconn(p_dev);
Mem_PoolBlkFree( p_dev_pool,
(void *)p_dev,
&err_lib);
if (p_hub_dev->ConnCnt < USBH_CFG_MAX_NUM_DEV_RECONN) {
/*This condition may happen due to EP_STALL return */
err = USBH_HUB_PortResetSet(p_hub_dev, /* Apply port reset. */
port_nbr);
if (err != USBH_ERR_NONE) {
break;
}
USBH_OS_DlyMS(USBH_HUB_DLY_DEV_RESET); /* See Notes #2. */
p_hub_dev->ConnCnt++;;
continue; /* Handle port reset status change. */
} else {
p_hub_dev->DevPtrList[port_nbr - 1u] = (USBH_DEV *)0;
}
} else {
p_hub_dev->DevPtrList[port_nbr - 1u] = p_dev;
}
}
}
/* ------------ PORT ENABLE STATUS CHANGE ------------- */
if (DEF_BIT_IS_SET(port_status.wPortChange, USBH_HUB_STATUS_C_PORT_EN) == DEF_TRUE) {
err = USBH_HUB_PortEnChngClr(p_hub_dev, port_nbr);
if (err != USBH_ERR_NONE) {
break;
}
}
port_nbr++;
}
USBH_HUB_EventReq(p_hub_dev); /* Retry URB. */
USBH_HUB_RefRel(p_hub_dev);
}
/*
*********************************************************************************************************
* USBH_HUB_DescGet()
*
* Description : Retrieve hub descriptor.
*
* Argument(s) : p_hub_dev Pointer to hub device.
*
* Return(s) : USBH_ERR_NONE, if descriptor is successfully obtained.
* USBH_ERR_DESC_INVALID, if hub descriptor is invalid.
*
* ----- RETURNED BY USBH_CtrlRx() : -----
* USBH_ERR_UNKNOWN, Unknown error occurred.
* USBH_ERR_INVALID_ARG, Invalid argument passed to 'p_ep'.
* USBH_ERR_EP_INVALID_STATE, Endpoint is not opened.
* USBH_ERR_HC_IO, Root hub input/output error.
* USBH_ERR_EP_STALL, Root hub does not support request.
* Host controller drivers error code, Otherwise.
*
* Note(s) : (1) GET HUB DESCRIPTOR standard request is defined in USB2.0 specification,
* section 11.24.2.5. Read 2 bytes of hub descriptor. Offset 0 of Hub Descriptor
* contains total length of descriptor and offset 1 represents descriptor type.
*********************************************************************************************************
*/
static USBH_ERR USBH_HUB_DescGet (USBH_HUB_DEV *p_hub_dev)
{
USBH_ERR err;
CPU_INT32U len;
CPU_INT32U i;
USBH_DESC_HDR hdr;
for (i = 0u; i < USBH_CFG_STD_REQ_RETRY; i++) { /* Attempt to get desc hdr 3 times. */
len = USBH_CtrlRx( p_hub_dev->DevPtr,
USBH_REQ_GET_DESC, /* See Note (1). */
(USBH_REQ_DIR_DEV_TO_HOST | USBH_REQ_TYPE_CLASS),
(USBH_HUB_DESC_TYPE_HUB << 8u),
0u,
(void *) USBH_HUB_DescBuf,
USBH_LEN_DESC_HDR,
USBH_HUB_TIMEOUT,
&err);
if ((err == USBH_ERR_EP_STALL) ||
(len == 0u )) {
USBH_EP_Reset( p_hub_dev->DevPtr,
(USBH_EP *)0);
} else {
break;
}
}
if (len != USBH_LEN_DESC_HDR) {
return (USBH_ERR_DESC_INVALID);
}
hdr.bLength = USBH_HUB_DescBuf[0];
hdr.bDescriptorType = USBH_HUB_DescBuf[1];
if ((hdr.bLength == 0u ) ||
(hdr.bLength > USBH_HUB_MAX_DESC_LEN ) ||
(hdr.bDescriptorType != USBH_HUB_DESC_TYPE_HUB)) {
return (USBH_ERR_DESC_INVALID);
}
for (i = 0u; i < USBH_CFG_STD_REQ_RETRY; i++) { /* Attempt to get full desc 3 times. */
len = USBH_CtrlRx( p_hub_dev->DevPtr,
USBH_REQ_GET_DESC,
(USBH_REQ_DIR_DEV_TO_HOST | USBH_REQ_TYPE_CLASS),
(USBH_HUB_DESC_TYPE_HUB << 8),
0u,
(void *)USBH_HUB_DescBuf,
hdr.bLength,
USBH_HUB_TIMEOUT,
&err);
if ((err == USBH_ERR_EP_STALL) ||
(len < hdr.bLength )) {
USBH_EP_Reset( p_hub_dev->DevPtr,
(USBH_EP *)0);
} else {
break;
}
}
USBH_HUB_ParseHubDesc(&p_hub_dev->Desc,
USBH_HUB_DescBuf);
if (p_hub_dev->Desc.bNbrPorts > USBH_CFG_MAX_HUB_PORTS) { /* Warns limit on hub port nbr to max cfg'd. */
#if (USBH_CFG_PRINT_LOG == DEF_ENABLED)
USBH_PRINT_LOG("Only ports [1..%d] are active.\r\n", USBH_CFG_MAX_HUB_PORTS);
#endif
}
return (err);
}
/*
*********************************************************************************************************
* USBH_HUB_PortsInit()
*
* Description : Enable power on each hub port & initialize device on each port.
*
* Argument(s) : p_hub_dev Pointer to the hub.
*
* Return(s) : USBH_ERR_NONE, if ports were successfully initialized.
*
* ----- RETURNED BY USBH_HUB_PortPwrSet() : -----
* USBH_ERR_UNKNOWN, Unknown error occurred.
* USBH_ERR_INVALID_ARG, Invalid argument passed to 'p_ep'.
* USBH_ERR_EP_INVALID_STATE, Endpoint is not opened.
* USBH_ERR_HC_IO, Root hub input/output error.
* USBH_ERR_EP_STALL, Root hub does not support request.
* Host controller drivers error code, Otherwise.
*
* Note(s) : (1) USB2.0 specification states that the host must wait for (bPwrOn2PwrGood * 2) ms
* before accessing a powered port. See section 11.23.2.1, bPwrOn2PwrGood field in hub
* descriptor.
*********************************************************************************************************
*/
static USBH_ERR USBH_HUB_PortsInit (USBH_HUB_DEV *p_hub_dev)
{
USBH_ERR err;
CPU_INT32U i;
CPU_INT16U nbr_ports;
nbr_ports = DEF_MIN(p_hub_dev->Desc.bNbrPorts,
USBH_CFG_MAX_HUB_PORTS);
for (i = 0u; i < nbr_ports; i++) {
err = USBH_HUB_PortPwrSet(p_hub_dev, i + 1u); /* Set port pwr. */
if (err != USBH_ERR_NONE) {
USBH_PRINT_ERR(err);
return (err);
}
USBH_OS_DlyMS(p_hub_dev->Desc.bPwrOn2PwrGood * 2u); /* See Note (1). */
}
return (USBH_ERR_NONE);
}
/*
*********************************************************************************************************
* USBH_HUB_PortStatusGet()
*
* Description : Get port status on given hub.
*
* Argument(s) : p_ep Pointer to hub device.
*
* port_nbr Port number.
*
* p_port_status Variable that will receive port status.
*
* Return(s) : USBH_ERR_NONE, if request was successfully sent.
*
* ----- RETURNED BY USBH_CtrlRx() : -----
* USBH_ERR_UNKNOWN, Unknown error occurred.
* USBH_ERR_INVALID_ARG, Invalid argument passed to 'p_ep'.
* USBH_ERR_EP_INVALID_STATE, Endpoint is not opened.
* USBH_ERR_HC_IO, Root hub input/output error.
* USBH_ERR_EP_STALL, Root hub does not support request.
* Host controller drivers error code, Otherwise.
*
* Note(s) : (1) HUB class specific request GET PORT STATUS is defined in USB2.0 specification in
* section 11.24.2.7.
*********************************************************************************************************
*/
static USBH_ERR USBH_HUB_PortStatusGet (USBH_HUB_DEV *p_hub_dev,
CPU_INT16U port_nbr,
USBH_HUB_PORT_STATUS *p_port_status)
{
CPU_INT08U *p_buf;
ALLOC_CACHE_ALIGN_BUFFER(USBH_HUB_PORT_STATUS, port_status, 1);
USBH_ERR err;
p_buf = (CPU_INT08U *)port_status;
(void)USBH_CtrlRx( p_hub_dev->DevPtr, /* See Note (1). */
USBH_REQ_GET_STATUS,
(USBH_REQ_DIR_DEV_TO_HOST | USBH_REQ_TYPE_CLASS | USBH_REQ_RECIPIENT_OTHER),
0u,
port_nbr,
(void *)p_buf,
USBH_HUB_LEN_HUB_PORT_STATUS,
USBH_HUB_TIMEOUT,
&err);
if (err != USBH_ERR_NONE) {
USBH_EP_Reset(p_hub_dev->DevPtr, (USBH_EP *)0);
} else {
p_port_status->wPortStatus = MEM_VAL_GET_INT16U_LITTLE(&port_status->wPortStatus);
p_port_status->wPortChange = MEM_VAL_GET_INT16U_LITTLE(&port_status->wPortChange);
}
return (err);
}
/*
*********************************************************************************************************
* USBH_HUB_PortResetSet()
*
* Description : Set port reset on given hub.
*
* Argument(s) : p_hub_dev Pointer to hub device.
*
* port_nbr Port number.
*
* Return(s) : USBH_ERR_NONE, if the request was successfully sent.
*
* ----- RETURNED BY USBH_CtrlTx() : -----
* USBH_ERR_UNKNOWN, Unknown error occurred.
* USBH_ERR_INVALID_ARG, Invalid argument passed to 'p_ep'.
* USBH_ERR_EP_INVALID_STATE, Endpoint is not opened.
* USBH_ERR_HC_IO, Root hub input/output error.
* USBH_ERR_EP_STALL, Root hub does not support request.
* Host controller drivers error code, Otherwise.
*
* Note(s) : (1) The HUB class specific request SET PORT FEATURE is defined in USB2.0 specification in
* section 11.24.2.13
*********************************************************************************************************
*/
static USBH_ERR USBH_HUB_PortResetSet (USBH_HUB_DEV *p_hub_dev,
CPU_INT16U port_nbr)
{
USBH_ERR err;
(void)USBH_CtrlTx( p_hub_dev->DevPtr, /* See Note (1). */
USBH_REQ_SET_FEATURE,
(USBH_REQ_DIR_HOST_TO_DEV | USBH_REQ_TYPE_CLASS | USBH_REQ_RECIPIENT_OTHER),
USBH_HUB_FEATURE_SEL_PORT_RESET,
port_nbr,
(void *)0,
0u,
USBH_HUB_TIMEOUT,
&err);
if (err != USBH_ERR_NONE) {
USBH_EP_Reset(p_hub_dev->DevPtr, (USBH_EP *)0);
}
return (err);
}
/*
*********************************************************************************************************
* USBH_HUB_PortRstChngClr()
*
* Description : Clear port reset change on given hub.
*
* Argument(s) : p_hub_dev Pointer to hub device.
*
* port_nbr Port number.
*
* Return(s) : USBH_ERR_NONE, If request was successfully sent.
*
* ----- RETURNED BY USBH_CtrlTx() : -----
* USBH_ERR_UNKNOWN, Unknown error occurred.
* USBH_ERR_INVALID_ARG, Invalid argument passed to 'p_ep'.
* USBH_ERR_EP_INVALID_STATE, Endpoint is not opened.
* USBH_ERR_HC_IO, Root hub input/output error.
* USBH_ERR_EP_STALL, Root hub does not support request.
* Host controller drivers error code, Otherwise.
*
* Note(s) : (1) HUB class specific request CLEAR PORT FEATURE is defined in USB2.0 specification in
* section 11.24.2.2.
*********************************************************************************************************
*/
static USBH_ERR USBH_HUB_PortRstChngClr (USBH_HUB_DEV *p_hub_dev,
CPU_INT16U port_nbr)
{
USBH_ERR err;
(void)USBH_CtrlTx( p_hub_dev->DevPtr, /* See Note (1). */
USBH_REQ_CLR_FEATURE,
(USBH_REQ_DIR_HOST_TO_DEV | USBH_REQ_TYPE_CLASS | USBH_REQ_RECIPIENT_OTHER),
USBH_HUB_FEATURE_SEL_C_PORT_RESET,
port_nbr,
(void *)0,
0u,
USBH_HUB_TIMEOUT,
&err);
if (err != USBH_ERR_NONE) {
USBH_EP_Reset(p_hub_dev->DevPtr, (USBH_EP *)0);
}
return (err);
}
/*
*********************************************************************************************************
* USBH_HUB_PortEnChngClr()
*
* Description : Clear port enable change on given hub.
*
* Argument(s) : p_hub_dev Pointer to hub device.
*
* port_nbr Port number.
*
* Return(s) : USBH_ERR_NONE, if the request was successfully sent.
*
* ----- RETURNED BY USBH_CtrlTx() : -----
* USBH_ERR_UNKNOWN Unknown error occurred.
* USBH_ERR_INVALID_ARG Invalid argument passed to 'p_ep'.
* USBH_ERR_EP_INVALID_STATE Endpoint is not opened.
* USBH_ERR_HC_IO, Root hub input/output error.
* USBH_ERR_EP_STALL, Root hub does not support request.
* Host controller drivers error code, Otherwise.
*
* Note(s) : (1) HUB class specific request CLEAR PORT FEATURE is defined in USB2.0 specification in
* section 11.24.2.2.
*********************************************************************************************************
*/
static USBH_ERR USBH_HUB_PortEnChngClr (USBH_HUB_DEV *p_hub_dev,
CPU_INT16U port_nbr)
{
USBH_ERR err;
(void)USBH_CtrlTx( p_hub_dev->DevPtr, /* See Note (1). */
USBH_REQ_CLR_FEATURE,
(USBH_REQ_DIR_HOST_TO_DEV | USBH_REQ_TYPE_CLASS | USBH_REQ_RECIPIENT_OTHER),
USBH_HUB_FEATURE_SEL_C_PORT_EN,
port_nbr,
(void *)0,
0u,
USBH_HUB_TIMEOUT,
&err);
if (err != USBH_ERR_NONE) {
USBH_EP_Reset(p_hub_dev->DevPtr, (USBH_EP *)0);
}
return (err);
}
/*
*********************************************************************************************************
* USBH_HUB_PortConnChngClr()
*
* Description : Clear port connection change on given hub.
*
* Argument(s) : p_hub_dev Pointer to hub device.
*
* port_nbr Port number.
*
* Return(s) : USBH_ERR_NONE, if the request was successfully sent.
*
* ----- RETURNED BY USBH_CtrlTx() : -----
* USBH_ERR_UNKNOWN Unknown error occurred.
* USBH_ERR_INVALID_ARG Invalid argument passed to 'p_ep'.
* USBH_ERR_EP_INVALID_STATE Endpoint is not opened.
* USBH_ERR_HC_IO, Root hub input/output error.
* USBH_ERR_EP_STALL, Root hub does not support request.
* Host controller drivers error code, Otherwise.
*
* Note(s) : (1) The HUB class specific request CLEAR PORT FEATURE is defined in USB2.0 specification in
* section 11.24.2.2.
*********************************************************************************************************
*/
static USBH_ERR USBH_HUB_PortConnChngClr (USBH_HUB_DEV *p_hub_dev,
CPU_INT16U port_nbr)
{
USBH_ERR err;
(void)USBH_CtrlTx( p_hub_dev->DevPtr, /* See Note #1. */
USBH_REQ_CLR_FEATURE,
(USBH_REQ_DIR_HOST_TO_DEV | USBH_REQ_TYPE_CLASS | USBH_REQ_RECIPIENT_OTHER),
USBH_HUB_FEATURE_SEL_C_PORT_CONN,
port_nbr,
(void *)0,
0u,
USBH_HUB_TIMEOUT,
&err);
if (err != USBH_ERR_NONE) {
USBH_EP_Reset(p_hub_dev->DevPtr, (USBH_EP *)0);
}
return (err);
}
/*
*********************************************************************************************************
* USBH_HUB_PortPwrSet()
*
* Description : Set power on given hub and port.
*
* Argument(s) : p_hub_dev Pointer to hub device.
*
* port_nbr Port number.
*
* Return(s) : USBH_ERR_NONE, if the request was successfully sent.
*
* ----- RETURNED BY USBH_CtrlTx() : -----
* USBH_ERR_UNKNOWN, Unknown error occurred.
* USBH_ERR_INVALID_ARG, Invalid argument passed to 'p_ep'.
* USBH_ERR_EP_INVALID_STATE, Endpoint is not opened.
* USBH_ERR_HC_IO, Root hub input/output error.
* USBH_ERR_EP_STALL, Root hub does not support request.
* Host controller drivers error code, Otherwise.
*
* Note(s) : (1) The HUB class specific request SET PORT FEATURE is defined in USB2.0 specification in
* section 11.24.2.13.
*********************************************************************************************************
*/
static USBH_ERR USBH_HUB_PortPwrSet (USBH_HUB_DEV *p_hub_dev,
CPU_INT16U port_nbr)
{
USBH_ERR err;
(void)USBH_CtrlTx( p_hub_dev->DevPtr, /* See Note #1. */
USBH_REQ_SET_FEATURE,
(USBH_REQ_DIR_HOST_TO_DEV | USBH_REQ_TYPE_CLASS | USBH_REQ_RECIPIENT_OTHER),
USBH_HUB_FEATURE_SEL_PORT_PWR,
port_nbr,
(void *)0,
0u,
USBH_HUB_TIMEOUT,
&err);
if (err != USBH_ERR_NONE) {
USBH_EP_Reset(p_hub_dev->DevPtr, (USBH_EP *)0);
}
return (err);
}
/*
*********************************************************************************************************
* USBH_HUB_PortSuspendClr()
*
* Description : Clear port suspend on given hub.
*
* Argument(s) : p_hub_dev Pointer to hub device.
*
* port_nbr Port number.
*
* Return(s) : USBH_ERR_NONE, if the request was successfully sent.
*
* ----- RETURNED BY USBH_CtrlTx() : -----
* USBH_ERR_UNKNOWN, Unknown error occurred.
* USBH_ERR_INVALID_ARG, Invalid argument passed to 'p_ep'.
* USBH_ERR_EP_INVALID_STATE, Endpoint is not opened.
* USBH_ERR_HC_IO, Root hub input/output error.
* USBH_ERR_EP_STALL, Root hub does not support request.
* Host controller drivers error code, Otherwise.
*
* Note(s) : (1) The HUB class specific request CLEAR PORT FEATURE is defined in USB2.0 specification in
* section 11.24.2.2.
*********************************************************************************************************
*/
static USBH_ERR USBH_HUB_PortSuspendClr (USBH_HUB_DEV *p_hub_dev,
CPU_INT16U port_nbr)
{
USBH_ERR err;
(void)USBH_CtrlTx( p_hub_dev->DevPtr, /* See Note #1. */
USBH_REQ_CLR_FEATURE,
(USBH_REQ_DIR_HOST_TO_DEV | USBH_REQ_TYPE_CLASS | USBH_REQ_RECIPIENT_OTHER),
USBH_HUB_FEATURE_SEL_C_PORT_SUSPEND,
port_nbr,
(void *)0,
0u,
USBH_HUB_TIMEOUT,
&err);
if (err != USBH_ERR_NONE) {
USBH_EP_Reset(p_hub_dev->DevPtr, (USBH_EP *)0);
}
return (err);
}
/*
*********************************************************************************************************
* USBH_HUB_PortEnClr()
*
* Description : Clear port enable on given hub.
*
* Argument(s) : p_hub_dev Pointer to hub device.
*
* port_nbr Port number.
*
* Return(s) : USBH_ERR_NONE, if the request was successfully sent.
*
* ----- RETURNED BY USBH_CtrlTx() : -----
* USBH_ERR_UNKNOWN Unknown error occurred.
* USBH_ERR_INVALID_ARG Invalid argument passed to 'p_ep'.
* USBH_ERR_EP_INVALID_STATE Endpoint is not opened.
* USBH_ERR_HC_IO, Root hub input/output error.
* USBH_ERR_EP_STALL, Root hub does not support request.
* Host controller drivers error code, Otherwise.
*
* Note(s) : (1) The HUB class specific request CLEAR PORT FEATURE is defined in USB2.0 specification in
* section 11.24.2.2
*********************************************************************************************************
*/
static USBH_ERR USBH_HUB_PortEnClr (USBH_HUB_DEV *p_hub_dev,
CPU_INT16U port_nbr)
{
USBH_ERR err;
(void)USBH_CtrlTx( p_hub_dev->DevPtr, /* See Note #1. */
USBH_REQ_CLR_FEATURE,
(USBH_REQ_DIR_HOST_TO_DEV | USBH_REQ_TYPE_CLASS | USBH_REQ_RECIPIENT_OTHER),
USBH_HUB_FEATURE_SEL_PORT_EN,
port_nbr,
(void *)0,
0u,
USBH_HUB_TIMEOUT,
&err);
if (err != USBH_ERR_NONE) {
USBH_EP_Reset(p_hub_dev->DevPtr, (USBH_EP *)0);
}
return (err);
}
/*
*********************************************************************************************************
* USBH_HUB_PortEnSet()
*
* Description : Set port enable on given hub.
*
* Argument(s) : p_hub_dev Pointer to hub device.
*
* port_nbr Port number.
*
* Return(s) : USBH_ERR_NONE, if the request was successfully sent.
*
* ----- RETURNED BY USBH_CtrlTx() : -----
* USBH_ERR_UNKNOWN, Unknown error occurred.
* USBH_ERR_INVALID_ARG, Invalid argument passed to 'p_ep'.
* USBH_ERR_EP_INVALID_STATE, Endpoint is not opened.
* USBH_ERR_HC_IO, Root hub input/output error.
* USBH_ERR_EP_STALL, Root hub does not support request.
* Host controller drivers error code, Otherwise.
*
* Note(s) : (1) The HUB class specific request SET PORT FEATURE is defined in USB2.0 specification in
* section 11.24.2.13.
*********************************************************************************************************
*/
static USBH_ERR USBH_HUB_PortEnSet (USBH_HUB_DEV *p_hub_dev,
CPU_INT16U port_nbr)
{
USBH_ERR err;
(void)USBH_CtrlTx( p_hub_dev->DevPtr, /* See Note #1. */
USBH_REQ_SET_FEATURE,
(USBH_REQ_DIR_HOST_TO_DEV | USBH_REQ_TYPE_CLASS | USBH_REQ_RECIPIENT_OTHER),
USBH_HUB_FEATURE_SEL_PORT_EN,
port_nbr,
(void *)0,
0u,
USBH_HUB_TIMEOUT,
&err);
if (err != USBH_ERR_NONE) {
USBH_EP_Reset(p_hub_dev->DevPtr, (USBH_EP *)0);
}
return (err);
}
/*
*********************************************************************************************************
* USBH_HUB_PortSuspendSet()
*
* Description : Set port suspend on given hub.
*
* Argument(s) : p_hub_dev Pointer to hub device.
*
* port_nbr Port number.
*
* Return(s) : USBH_ERR_NONE, if the request was successfully sent.
*
* ----- RETURNED BY USBH_CtrlTx() : -----
* USBH_ERR_UNKNOWN, Unknown error occurred.
* USBH_ERR_INVALID_ARG, Invalid argument passed to 'p_ep'.
* USBH_ERR_EP_INVALID_STATE, Endpoint is not opened.
* USBH_ERR_HC_IO, Root hub input/output error.
* USBH_ERR_EP_STALL, Root hub does not support request.
* Host controller drivers error code, Otherwise.
*
* Note(s) : (1) The HUB class specific request SET PORT FEATURE is defined in USB2.0 specification in
* section 11.24.2.13.
*********************************************************************************************************
*/
USBH_ERR USBH_HUB_PortSuspendSet (USBH_HUB_DEV *p_hub_dev,
CPU_INT16U port_nbr)
{
USBH_ERR err;
(void)USBH_CtrlTx( p_hub_dev->DevPtr, /* See Note #1. */
USBH_REQ_SET_FEATURE,
(USBH_REQ_DIR_HOST_TO_DEV | USBH_REQ_TYPE_CLASS | USBH_REQ_RECIPIENT_OTHER),
USBH_HUB_FEATURE_SEL_PORT_SUSPEND,
port_nbr,
(void *)0,
0u,
USBH_HUB_TIMEOUT,
&err);
if (err != USBH_ERR_NONE) {
USBH_EP_Reset(p_hub_dev->DevPtr, (USBH_EP *)0);
}
return (err);
}
/*
*********************************************************************************************************
* USBH_HUB_Clr()
*
* Description : Initializes USBH_HUB_DEV structure.
*
* Argument(s) : p_hub_dev Pointer to hub device.
*
* Return(s) : None
*
* Note(s) : None.
*********************************************************************************************************
*/
static void USBH_HUB_Clr (USBH_HUB_DEV *p_hub_dev)
{
CPU_INT08U dev_ix;
p_hub_dev->DevPtr = (USBH_DEV *)0;
p_hub_dev->IF_Ptr = (USBH_IF *)0;
/* Clr dev ptr lst. */
for (dev_ix = 0u; dev_ix < USBH_CFG_MAX_HUB_PORTS; dev_ix++) {
p_hub_dev->DevPtrList[dev_ix] = (USBH_DEV *)0;
}
p_hub_dev->RefCnt = 0u;
p_hub_dev->State = USBH_CLASS_DEV_STATE_NONE;
p_hub_dev->NxtPtr = 0u;
}
/*
*********************************************************************************************************
* USBH_HUB_RefAdd()
*
* Description : Increment access reference count to a hub device.
*
* Argument(s) : p_hub_dev Pointer to hub device.
*
* Return(s) : USBH_ERR_NONE, if access is successful.
* USBH_ERR_INVALID_ARG, if invalid argument passed to 'p_hub_dev'.
*
* Note(s) : None.
*********************************************************************************************************
*/
static USBH_ERR USBH_HUB_RefAdd (USBH_HUB_DEV *p_hub_dev)
{
CPU_SR_ALLOC();
if (p_hub_dev == (USBH_HUB_DEV *)0) {
return (USBH_ERR_INVALID_ARG);
}
CPU_CRITICAL_ENTER();
p_hub_dev->RefCnt++; /* Increment access ref cnt to hub dev. */
CPU_CRITICAL_EXIT();
return (USBH_ERR_NONE);
}
/*
*********************************************************************************************************
* USBH_HUB_RefRel()
*
* Description : Increment the access reference count to a hub device.
*
* Argument(s) : p_hub_dev Pointer to hub device.
*
* Return(s) : USBH_ERR_NONE, if access is successful.
* USBH_ERR_INVALID_ARG, if invalid argument passed to 'p_hub_dev'.
*
* Note(s) : None.
*********************************************************************************************************
*/
static USBH_ERR USBH_HUB_RefRel (USBH_HUB_DEV *p_hub_dev)
{
LIB_ERR err;
CPU_SR_ALLOC();
if (p_hub_dev == (USBH_HUB_DEV *)0) {
return (USBH_ERR_INVALID_ARG);
}
CPU_CRITICAL_ENTER();
if (p_hub_dev->RefCnt > 0u) {
p_hub_dev->RefCnt--; /* Decrement access ref cnt to hub dev. */
if (p_hub_dev->RefCnt == 0u) {
Mem_PoolBlkFree( &USBH_HUB_Pool, /* Ref count is 0, dev is removed, release HUB dev. */
(void *)p_hub_dev,
&err);
}
}
CPU_CRITICAL_EXIT();
return (USBH_ERR_NONE);
}
/*
*********************************************************************************************************
* USBH_HUB_RH_CtrlReq()
*
* Description : Process hub request from core layer.
*
* Argument(s) : p_hc Pointer to host controller.
*
* b_req Setup packet b_request.
*
* bm_req_type Setup packet bm_request_type.
*
* w_val Setup packet w_value.
*
* w_ix Setup packet w_index.
*
* p_buf Data buffer pointer.
*
* buf_len Size of data buffer in bytes.
*
* p_err Pointer to variable that will receive the return error code from this function :
*
* USBH_ERR_NONE, Root hub control request completed successfully.
* USBH_ERR_HC_IO, Root hub input/output error.
* USBH_ERR_EP_STALL, Root hub does not support request.
*
* Return(s) : Buffer length in octets.
*
* Note(s) : None.
*********************************************************************************************************
*/
CPU_INT32U USBH_HUB_RH_CtrlReq (USBH_HC *p_hc,
CPU_INT08U b_req,
CPU_INT08U bm_req_type,
CPU_INT16U w_val,
CPU_INT16U w_ix,
void *p_buf,
CPU_INT32U buf_len,
USBH_ERR *p_err)
{
CPU_INT32U len;
USBH_HC_DRV *p_hc_drv;
USBH_HC_RH_API *p_hc_rh_api;
CPU_BOOLEAN valid;
p_hc_drv = &p_hc->HC_Drv;
p_hc_rh_api = p_hc_drv->RH_API_Ptr;
*p_err = USBH_ERR_NONE;
len = 0u;
valid = DEF_OK;
switch (b_req) {
case USBH_REQ_GET_STATUS:
/* Only port status is supported. */
if ((bm_req_type & USBH_REQ_RECIPIENT_OTHER) == USBH_REQ_RECIPIENT_OTHER) {
valid = p_hc_rh_api->PortStatusGet( p_hc_drv,
w_ix,
(USBH_HUB_PORT_STATUS *)p_buf);
} else {
len = buf_len;
Mem_Clr(p_buf, len); /* Return 0 for other reqs. */
}
break;
case USBH_REQ_CLR_FEATURE:
switch (w_val) {
case USBH_HUB_FEATURE_SEL_PORT_EN:
valid = p_hc_rh_api->PortEnClr(p_hc_drv, w_ix);
break;
case USBH_HUB_FEATURE_SEL_PORT_PWR:
valid = p_hc_rh_api->PortPwrClr(p_hc_drv, w_ix);
break;
case USBH_HUB_FEATURE_SEL_C_PORT_CONN:
valid = p_hc_rh_api->PortConnChngClr(p_hc_drv, w_ix);
break;
case USBH_HUB_FEATURE_SEL_C_PORT_RESET:
valid = p_hc_rh_api->PortResetChngClr(p_hc_drv, w_ix);
break;
case USBH_HUB_FEATURE_SEL_C_PORT_EN:
valid = p_hc_rh_api->PortEnChngClr(p_hc_drv, w_ix);
break;
case USBH_HUB_FEATURE_SEL_PORT_INDICATOR:
case USBH_HUB_FEATURE_SEL_PORT_SUSPEND:
case USBH_HUB_FEATURE_SEL_C_PORT_SUSPEND:
valid = p_hc_rh_api->PortSuspendClr(p_hc_drv, w_ix);
break;
case USBH_HUB_FEATURE_SEL_C_PORT_OVER_CUR:
*p_err = USBH_ERR_EP_STALL;
break;
default:
break;
}
break;
case USBH_REQ_SET_FEATURE:
switch (w_val) {
case USBH_HUB_FEATURE_SEL_PORT_EN:
valid = p_hc_rh_api->PortEnSet(p_hc_drv, w_ix);
break;
case USBH_HUB_FEATURE_SEL_PORT_RESET:
valid = p_hc_rh_api->PortResetSet(p_hc_drv, w_ix);
break;
case USBH_HUB_FEATURE_SEL_PORT_PWR:
valid = p_hc_rh_api->PortPwrSet(p_hc_drv, w_ix);
break;
/* Not supported reqs. */
case USBH_HUB_FEATURE_SEL_PORT_SUSPEND:
case USBH_HUB_FEATURE_SEL_PORT_TEST:
case USBH_HUB_FEATURE_SEL_PORT_INDICATOR:
case USBH_HUB_FEATURE_SEL_C_PORT_CONN:
case USBH_HUB_FEATURE_SEL_C_PORT_RESET:
case USBH_HUB_FEATURE_SEL_C_PORT_EN:
case USBH_HUB_FEATURE_SEL_C_PORT_SUSPEND:
case USBH_HUB_FEATURE_SEL_C_PORT_OVER_CUR:
*p_err = USBH_ERR_EP_STALL;
break;
default:
break;
}
break;
case USBH_REQ_SET_ADDR:
break;
case USBH_REQ_GET_DESC:
switch (w_val >> 8u) { /* Desc type. */
case USBH_DESC_TYPE_DEV:
if (buf_len > sizeof(USBH_HUB_RH_DevDesc)) {
len = sizeof(USBH_HUB_RH_DevDesc);
} else {
len = buf_len;
}
Mem_Copy((void *)p_buf,
(void *)USBH_HUB_RH_DevDesc,
len);
break;
case USBH_DESC_TYPE_CFG: /* Return cfg desc. */
if (buf_len > sizeof(USBH_HUB_RH_FS_CfgDesc)) {
len = sizeof(USBH_HUB_RH_FS_CfgDesc);
} else {
len = buf_len;
}
Mem_Copy((void *)p_buf,
(void *)USBH_HUB_RH_FS_CfgDesc,
len);
break;
case USBH_HUB_DESC_TYPE_HUB: /* Return hub desc. */
len = buf_len;
valid = p_hc_rh_api->HubDescGet( p_hc_drv,
(USBH_HUB_DESC *)p_buf,
len);
break;
case USBH_DESC_TYPE_STR:
if ((w_val & 0x00FF) == 0u) {
if (buf_len > sizeof(USBH_HUB_RH_LangID)) {
len = sizeof(USBH_HUB_RH_LangID);
} else {
len = buf_len;
}
Mem_Copy((void *)p_buf,
(void *)USBH_HUB_RH_LangID,
len);
} else {
*p_err = USBH_ERR_EP_STALL;
break;
}
break;
default:
break;
}
break;
case USBH_REQ_SET_CFG:
break;
case USBH_REQ_GET_CFG:
case USBH_REQ_GET_IF:
case USBH_REQ_SET_IF:
case USBH_REQ_SET_DESC:
case USBH_REQ_SYNCH_FRAME:
*p_err = USBH_ERR_EP_STALL;
break;
default:
break;
}
if ((valid != DEF_OK) &&
(*p_err == USBH_ERR_NONE)) {
*p_err = USBH_ERR_HC_IO;
}
return (len);
}
/*
*********************************************************************************************************
* USBH_HUB_RH_Event()
*
* Description : Queue a root hub event.
*
* Argument(s) : p_dev Pointer to hub device.
*
* Return(s) : None.
*
* Note(s) : None.
*********************************************************************************************************
*/
void USBH_HUB_RH_Event (USBH_DEV *p_dev)
{
USBH_HUB_DEV *p_hub_dev;
USBH_HC_DRV *p_hc_drv;
USBH_HC_RH_API *p_rh_drv_api;
CPU_SR_ALLOC();
p_hub_dev = p_dev->HC_Ptr->RH_ClassDevPtr;
p_hc_drv = &p_dev->HC_Ptr->HC_Drv;
p_rh_drv_api = p_hc_drv->RH_API_Ptr;
if (p_hub_dev == (USBH_HUB_DEV *)0) {
(void)p_rh_drv_api->IntDis(p_hc_drv);
return;
}
(void)p_rh_drv_api->IntDis(p_hc_drv);
USBH_HUB_RefAdd(p_hub_dev);
CPU_CRITICAL_ENTER();
if (USBH_HUB_HeadPtr == (USBH_HUB_DEV *)0) {
USBH_HUB_HeadPtr = p_hub_dev;
USBH_HUB_TailPtr = p_hub_dev;
} else {
USBH_HUB_TailPtr->NxtPtr = p_hub_dev;
USBH_HUB_TailPtr = p_hub_dev;
}
CPU_CRITICAL_EXIT();
(void)USBH_OS_SemPost(USBH_HUB_EventSem);
}
/*
**************************************************************************************************************
* USBH_HUB_ClassNotify()
*
* Description : Handle device state change notification for hub class devices.
*
* Argument(s) : p_class_dev Pointer to class device.
*
* state State of device.
*
* p_ctx Pointer to context.
*
* Return(s) : None.
*
* Note(s) : None.
**************************************************************************************************************
*/
void USBH_HUB_ClassNotify (void *p_class_dev,
CPU_INT08U state,
void *p_ctx)
{
USBH_HUB_DEV *p_hub_dev;
USBH_DEV *p_dev;
(void)p_ctx;
p_hub_dev = (USBH_HUB_DEV *)p_class_dev;
p_dev = p_hub_dev->DevPtr;
if(p_dev->IsRootHub == DEF_TRUE) { /* If RH, return immediately. */
return;
}
switch (state) { /* External hub has been identified. */
case USBH_CLASS_DEV_STATE_CONN:
#if (USBH_CFG_PRINT_LOG == DEF_ENABLED)
USBH_PRINT_LOG("Ext HUB (Addr# %i) connected\r\n", p_dev->DevAddr);
#endif
break;
case USBH_CLASS_DEV_STATE_DISCONN:
#if (USBH_CFG_PRINT_LOG == DEF_ENABLED)
USBH_PRINT_LOG("Ext HUB (Addr# %i) disconnected\r\n", p_dev->DevAddr);
#endif
break;
default:
break;
}
}
/*
*********************************************************************************************************
* USBH_HUB_ParseHubDesc()
*
* Description : Parse hub descriptor into hub descriptor structure.
*
* Argument(s) : p_hub_desc Variable that will hold the parsed hub descriptor.
*
* p_buf_src Pointer to buffer that holds hub descriptor.
*
* Return(s) : None.
*
* Note(s) : None.
*********************************************************************************************************
*/
void USBH_HUB_ParseHubDesc (USBH_HUB_DESC *p_hub_desc,
void *p_buf_src)
{
USBH_HUB_DESC *p_buf_src_desc;
CPU_INT08U i;
p_buf_src_desc = (USBH_HUB_DESC *)p_buf_src;
p_hub_desc->bDescLength = p_buf_src_desc->bDescLength;
p_hub_desc->bDescriptorType = p_buf_src_desc->bDescriptorType;
p_hub_desc->bNbrPorts = p_buf_src_desc->bNbrPorts;
p_hub_desc->wHubCharacteristics = MEM_VAL_GET_INT16U_LITTLE(&p_buf_src_desc->wHubCharacteristics);
p_hub_desc->bPwrOn2PwrGood = p_buf_src_desc->bPwrOn2PwrGood;
p_hub_desc->bHubContrCurrent = p_buf_src_desc->bHubContrCurrent;
p_hub_desc->DeviceRemovable = p_buf_src_desc->DeviceRemovable;
for (i = 0u; i < USBH_CFG_MAX_HUB_PORTS; i++) {
p_hub_desc->PortPwrCtrlMask[i] = MEM_VAL_GET_INT32U_LITTLE(&p_buf_src_desc->PortPwrCtrlMask[i]);
}
}
/*
*********************************************************************************************************
* USBH_HUB_FmtHubDesc()
*
* Description : Format hub descriptor from hub descriptor structure.
*
* Argument(s) : p_hub_desc Variable that holds hub descriptor information.
*
* p_buf_dest Pointer to buffer that will contain hub descriptor.
*
* Return(s) : None.
*
* Note(s) : None.
*********************************************************************************************************
*/
void USBH_HUB_FmtHubDesc (USBH_HUB_DESC *p_hub_desc,
void *p_buf_dest)
{
USBH_HUB_DESC *p_buf_dest_desc;
CPU_INT08U i;
p_buf_dest_desc = (USBH_HUB_DESC *)p_buf_dest;
p_buf_dest_desc->bDescLength = p_hub_desc->bDescLength;
p_buf_dest_desc->bDescriptorType = p_hub_desc->bDescriptorType;
p_buf_dest_desc->bNbrPorts = p_hub_desc->bNbrPorts;
p_buf_dest_desc->wHubCharacteristics = MEM_VAL_GET_INT16U_LITTLE(&p_hub_desc->wHubCharacteristics);
p_buf_dest_desc->bPwrOn2PwrGood = p_hub_desc->bPwrOn2PwrGood;
p_buf_dest_desc->bHubContrCurrent = p_hub_desc->bHubContrCurrent;
p_buf_dest_desc->DeviceRemovable = p_hub_desc->DeviceRemovable;
for (i = 0u; i < USBH_CFG_MAX_HUB_PORTS; i++) {
p_buf_dest_desc->PortPwrCtrlMask[i] = p_hub_desc->PortPwrCtrlMask[i];
}
}