/* ********************************************************************************************************* * 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]; } }