📄 usbh_hcds_vhub.c
字号:
//
// Initialize the virtual route hub
//
// argument : None
//
// return : None
===============================================================================================*/
void USBH_HCDS_VHUBInit( void )
{
memset(&VHUBStatus, 0, sizeof(VHUBStatus));
}
/*=============================================================================================
// Function_Name: USBH_HCDS_VHUBRegisterCBR
//
// description : Register for notification target of port status changing
//
// Register the callback function of notification used when the port status of the virtual route hub changed
//
// argument : pfnCallback (in)Pointer of callback function
//
// return : None
===============================================================================================*/
void USBH_HCDS_VHUBRegisterCBR( CALLBACK_PROC pfnCallback )
{
unsigned long vhubStatus;
VHUBStatus.pfnCallback = pfnCallback;
vhubStatus = 0;
if( VHUBStatus.sHubStatus.changeStatus != 0 ){
/* Do notification if there is already a hub status change when registering */
vhubStatus = USBH_HCDS_VHUB_HUB_STATUS;
}
if( VHUBStatus.sPortStatus.changeStatus != 0 ){
/* Do notification if there is already a port status change when registering */
vhubStatus |= USBH_HCDS_VHUB_PORT_STATUS;
}
USBH_HCDS_ExecCallback(VHUBStatus.pfnCallback, vhubStatus, 0, NULL);
}
/*=============================================================================================
// Function_Name: USBH_HCDS_VHUBRequest
//
// description : USB request process for the virtual route hub address
//
// Process the USB request for the virtual route hub address
//
// argument : None
//
// return : STATUS_SUCCESS Processing completed successfully
// STATUS_INVALID_PARAMETER Parameter error
===============================================================================================*/
long USBH_HCDS_VHUBRequest( USBH_HCD_URB *psUrb )
{
DEVICE_REQUEST *psDeviceRequest;
unsigned short reqDataLength;
long retValue;
psUrb->actualLength = 0;
psDeviceRequest = (DEVICE_REQUEST *)psUrb->pSetupPacket;
reqDataLength = MAKEWORD(psDeviceRequest->wLengthL, psDeviceRequest->wLengthH);
if( reqDataLength > psUrb->transBufLength ){
/* The data buffer is not enough for the data size required by the request */
return STATUS_INVALID_PARAMETER;
}
VHUBStatus.psUrb = psUrb;
switch( psDeviceRequest->bmRequestType & BMREQ_TYPE_MASK ){
case TYPE_STANDARD:
retValue = StandardRequest(psDeviceRequest);
break;
case TYPE_CLASS:
retValue = ClassRequest(psDeviceRequest);
break;
default:
retValue = STATUS_INVALID_PARAMETER;
}
if( retValue != STATUS_SUCCESS ){
/* For request error */
psUrb->status = USBH_HCD_URBSTS_PIPE;
} else {
/* When request terminated normally */
psUrb->status = USBH_HCD_URBSTS_SUCCESS;
}
return STATUS_SUCCESS;
}
/*=============================================================================================
// Function_Name: NotifyPortStateChanged
//
// description : Notification of Port state changing
//
// Notify the changing of the port state of the virtual route hub
//
// argument : (in)Pointer of callback function
//
// return : None
===============================================================================================*/
//Inline long NotifyPortStateChanged( unsigned long portState, unsigned long portSpeed, void *pParam )
long NotifyPortStateChanged( unsigned long portState, unsigned long portSpeed, void *pParam )
{
unsigned long vhubStatus;
switch( portState ){
case USBH_HCDS_PORT_ST_DISCONNECTED:
/* When device is unplugged */
/* Clear the Port Connection of port status */
/* Clear the Port Enable of port status */
/* Clear the Port High Speed, Port Low Speed of port status */
/* Set the change of Port Connection in the port change status */
VHUBStatus.sPortStatus.status &= ~(PORTSTS_PORT_CONNECTION | PORTSTS_PORT_ENABLE
| PORTSTS_PORT_HIGH_SPEED | PORTSTS_PORT_LOW_SPEED);
VHUBStatus.sPortStatus.changeStatus |= PORTSTS_C_PORT_CONNECTION;
/* Clear the Port Suspend of port status */
VHUBStatus.sPortStatus.status &= ~PORTSTS_PORT_SUSPEND;
break;
case USBH_HCDS_PORT_ST_DISABLED:
/* when device is connected, or when port error occurred/when ClearPortFeatuer(PORT_ENABLE) */
if( (VHUBStatus.sPortStatus.status & PORTSTS_PORT_ENABLE) == 0 ){
/* Device is connected */
/* Set the port Connection of port status */
/* Set the change of Port Connection in the port change status */
VHUBStatus.sPortStatus.status |= PORTSTS_PORT_CONNECTION;
VHUBStatus.sPortStatus.changeStatus |= PORTSTS_C_PORT_CONNECTION;
} else {
/* When port error occurred/when ClearPortFeatuer(PORT_ENABLE) */
/* Clear the Port Enable of port status */
/* Clear the Port High Speed, Port Low Speed of port status */
/* Set the change of Port Enable in the port change status */
VHUBStatus.sPortStatus.status &= ~(PORTSTS_PORT_ENABLE | PORTSTS_PORT_HIGH_SPEED | PORTSTS_PORT_LOW_SPEED);
VHUBStatus.sPortStatus.changeStatus |= PORTSTS_C_PORT_ENABLE;
}
break;
case USBH_HCDS_PORT_ST_ENABLED:
/* When USB reset is completed, or USB resume is completed */
if( (VHUBStatus.sPortStatus.status & PORTSTS_PORT_SUSPEND) == 0 ){
/* The port is out of suspending */
/* Clear the Port Reset of port change status */
VHUBStatus.sPortStatus.status &= ~PORTSTS_PORT_RESET;
/* Set the Port Enable of port status */
VHUBStatus.sPortStatus.status |= PORTSTS_PORT_ENABLE;
/* Set the Port Low Speed/Port High Speed of port status */
switch( portSpeed ){
case USBH_HCDS_PORT_SPEED_MODE_HIGH:
/* Clear PORT_LOW_SPEED, set PORT_HIGH_SPEED */
VHUBStatus.sPortStatus.status &= ~PORTSTS_PORT_LOW_SPEED;
VHUBStatus.sPortStatus.status |= PORTSTS_PORT_HIGH_SPEED;
break;
case USBH_HCDS_PORT_SPEED_MODE_FULL:
/* Clear PORT_LOW_SPEED, clear PORT_HIGH_SPEED */
VHUBStatus.sPortStatus.status &= ~PORTSTS_PORT_LOW_SPEED;
VHUBStatus.sPortStatus.status &= ~PORTSTS_PORT_HIGH_SPEED;
break;
case USBH_HCDS_PORT_SPEED_MODE_LOW:
/* Set PORT_LOW_SPEED, clear PORT_HIGH_SPEED */
VHUBStatus.sPortStatus.status |= PORTSTS_PORT_LOW_SPEED;
VHUBStatus.sPortStatus.status &= ~PORTSTS_PORT_HIGH_SPEED;
break;
}
/* Set the change of Port Reset in the port change status */
VHUBStatus.sPortStatus.changeStatus |= PORTSTS_C_PORT_RESET;
} else {
/* When the port is under suspending */
/* Clear the Port Suspend of port status */
/* Set the change of Port Suspend in the port change status */
VHUBStatus.sPortStatus.status &= ~PORTSTS_PORT_SUSPEND;
VHUBStatus.sPortStatus.changeStatus |= PORTSTS_C_PORT_SUSPEND;
}
break;
case USBH_HCDS_PORT_ST_SUSPENDED:
/* Transferring to Suspend is completed */
/* Set the Port SUSPEND of port status */
VHUBStatus.sPortStatus.status |= PORTSTS_PORT_SUSPEND;
break;
case USBH_HCDS_PORT_ST_VBUS_OVER_CURRENT:
/* Overcurrent occurred in VBUS */
/* Clear all the port status and port change status */
VHUBStatus.sPortStatus.status = 0;
VHUBStatus.sPortStatus.changeStatus = 0;
/* Set the Hub Over-Current of hub status */
/* Set the change of Hub Over-Current in the hub change status */
VHUBStatus.sHubStatus.status |= HUBSTS_HUB_OVER_CURRENT;
VHUBStatus.sHubStatus.changeStatus |= HUBSTS_C_HUB_OVER_CURRENT;
break;
case USBH_HCDS_PORT_ST_VBUS_OVER_CURRENT_CLR:
/* VBUS recovery from the overcurrent */
/* Clear the Hub Over-Current of hub status */
/* Set the change of Hub Over-Current in the hub change status */
VHUBStatus.sHubStatus.status &= ~HUBSTS_HUB_OVER_CURRENT;
VHUBStatus.sHubStatus.changeStatus |= HUBSTS_C_HUB_OVER_CURRENT;
break;
}
vhubStatus = 0;
if( VHUBStatus.sHubStatus.changeStatus != 0 ){
/* Do notification if there is already a hub status change when registering */
vhubStatus = USBH_HCDS_VHUB_HUB_STATUS;
}
if( VHUBStatus.sPortStatus.changeStatus != 0 ){
/* Do notification if there is already a port status change when registering */
vhubStatus |= USBH_HCDS_VHUB_PORT_STATUS;
}
USBH_HCDS_ExecCallback(VHUBStatus.pfnCallback, vhubStatus, 0, NULL);
return STATUS_SUCCESS;
}
/*=============================================================================================
// Function_Name: StandardRequest
//
// description : Process for standard request
//
// Analyze the passed request data, and process an appropriate standard request
//
// argument : *psDeviceRequest (in)Pointer to request data
//
// return : STATUS_SUCCESS Processing completed successfully
===============================================================================================*/
Inline long StandardRequest( DEVICE_REQUEST *psDeviceRequest )
{
long retValue;
switch( psDeviceRequest->bRequest ){
case SREQ_GET_STATUS:
retValue = GetStatus(psDeviceRequest);
break;
case SREQ_CLEAR_FEATURE:
retValue = ClearFeature(psDeviceRequest);
break;
case SREQ_SET_FEATURE:
retValue = SetFeature(psDeviceRequest);
break;
case SREQ_SET_ADDRESS:
retValue = SetAddress(psDeviceRequest);
break;
case SREQ_GET_DESCRIPTOR:
retValue = GetDescriptor(psDeviceRequest);
break;
case SREQ_GET_CONFIGURATION:
retValue = GetConfiguration(psDeviceRequest);
break;
case SREQ_SET_CONFIGURATION:
retValue = SetConfiguration(psDeviceRequest);
break;
case SREQ_GET_INTERFACE:
retValue = GetInterface(psDeviceRequest);
break;
case SREQ_SET_INTERFACE:
retValue = SetInterface(psDeviceRequest);
break;
default:
retValue = STATUS_INVALID_PARAMETER;
}
return retValue;
}
/*======================================================================
// Function_Name: GetStatus
//
// description : Get Status request
//
// Process for Get Status request
//
// argument : *psDeviceRequest Pointer of device request
//
// return : STATUS_SUCCESS Success
// STATUS_INVALID_PARAMETER Error
// STATUS_INVALID_PARAMETER Parameter error
========================================================================*/
Inline long GetStatus( DEVICE_REQUEST *psDeviceRequest )
{
USBH_HCD_URB *psUrb;
unsigned char *pBufAdrs;
psUrb = VHUBStatus.psUrb;
pBufAdrs = (unsigned char *)psUrb->pTransBuf;
if( VHUBStatus.bmFlags.usbState == DEFAULT_STATE ){
return STATUS_INVALID_PARAMETER;
}
if( (psDeviceRequest->bmRequestType & BMREQ_DIR_MASK) != DIR_DEVICE_TO_HOST ){
/* Direction of transfer is different */
return STATUS_INVALID_PARAMETER;
}
if( psDeviceRequest->wValueH || psDeviceRequest->wValueL ){
/* wValue != 0 */
return STATUS_INVALID_PARAMETER;
}
if( psDeviceRequest->wLengthH || psDeviceRequest->wLengthL != GET_STATUS_DATA_LENGTH ){
/* wLength != GET_STATUS_DATA_LENGTH */
return STATUS_INVALID_PARAMETER;
}
switch( psDeviceRequest->bmRequestType & BMREQ_RECIPIENT_MASK ){
case RECIPIENT_DEVICE:
if( psDeviceRequest->wIndexH || psDeviceRequest->wIndexL ){
/* wIndex != 0*/
return STATUS_INVALID_PARAMETER;
}
/*===========================/
Set the replying data/
/===========================*/
pBufAdrs[0] = (VHUBStatus.bmFlags.remoteWakeup << 1)
+ ((StdConfigDesc[OFFSET_BMATTRIBUTES] & ATTRIB_SELF_POWERED) >> 6);
pBufAdrs[1] = 0x00;
break;
case RECIPIENT_INTERFACE:
if( VHUBStatus.bmFlags.usbState == ADDRESSED_STATE ){
return STATUS_INVALID_PARAMETER;
}
if( psDeviceRequest->wIndexH ){
/* wIndex != 0*/
return STATUS_INVALID_PARAMETER;
}
/*===========================================/
Check whether specified Interface Number is effective/
/===========================================*/
if( psDeviceRequest->wIndexL != 0 ){
/* Invalid Interface Number */
return STATUS_INVALID_PARAMETER;
}
/*===========================/
Set the replying data /
/===========================*/
pBufAdrs[0] = 0x00;
pBufAdrs[1] = 0x00;
break;
case RECIPIENT_ENDPOINT:
if( psDeviceRequest->wIndexH ){
/* wIndex.h != 0 */
return STATUS_INVALID_PARAMETER;
}
if(VHUBStatus.bmFlags.usbState == ADDRESSED_STATE && psDeviceRequest->wIndexL != 0x00){
return STATUS_INVALID_PARAMETER;
}
if( psDeviceRequest->wIndexL != 0 && psDeviceRequest->wIndexL != INT_EP_ADDRESS ){
/* There are neither Endpoint 0 nor Interrupt IN Endpoint */
return STATUS_INVALID_PARAMETER;
}
/*===========================/
Set the replying data /
/===========================*/
if( psDeviceRequest->wIndexL != 0x00 ){
/* For Interrupt IN Endpoint */
pBufAdrs[0] = (unsigned char)VHUBStatus.bmFlags.epHalt;
} else {
/* For Endpoint 0 */
pBufAdrs[0] = 0x00;
}
pBufAdrs[1] = 0x00;
break;
default:
return STATUS_INVALID_PARAMETER;
}
psUrb->actualLength = GET_STATUS_DATA_LENGTH;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -