?? cdevice.cpp
字號:
// responsible for de-bouncing the attach signalling.
//
// we do the de-bouncing by waiting until a 100 ms interval
// (t3 on figure 7-19 in the spec) elapses with no connection
// status change on the port. Then we can examine the current
// connect status reliably.
BOOL fPoll = TRUE;
while (fPoll) {
USB_HUB_AND_PORT_STATUS hubStatus2;
Sleep( 100 );
if ( GetStatus( port, hubStatus2 ) == FALSE ) {
// failed to get status; probably power-cycle or upper-level detach
hubStatus.status.port.PortConnected = FALSE;
fPoll = FALSE;
}
else if ( hubStatus2.change.port.ConnectStatusChange ) {
// ack the status change and wait again
SetOrClearFeature( port, USB_REQUEST_CLEAR_FEATURE,
USB_HUB_FEATURE_C_PORT_CONNECTION );
}
else {
// ah, stability.
hubStatus.status.word = hubStatus2.status.word;
fPoll = FALSE;
}
}
if ( hubStatus.status.port.PortConnected ) {
// device attach
DEBUGMSG( ZONE_ATTACH, (TEXT("CHub(%s tier %d)::HubStatusChangeThread - device attached on port %d\n"), GetDeviceType(), m_tierNumber, port ) );
AttachDevice( port,
hubStatus.status.port.DeviceIsLowSpeed );
}
} // end of ConnectStatusChange processing
}
DEBUGMSG( ZONE_HUB, (TEXT("-CHub(%s tier %d)::HubStatusChangeThread, THREAD EXITING, returning 0\n"), GetDeviceType(), m_tierNumber ) );
return 0;
}
#ifdef DEBUG
// ******************************************************************
void CHub::DumpHubDescriptor( IN const PUSB_HUB_DESCRIPTOR pDescriptor )
//
// Purpose: print out the contents of the descriptor via DEBUGMSG
//
// Parameters: pDescriptor - pointer to descriptor
//
// Returns: Nothing.
//
// Notes: Used in debug mode only
//
// Refer to USB spec 1.1, Section 11.15.2.1
// ******************************************************************
{
DEBUGCHK( pDescriptor != NULL );
DEBUGMSG( ZONE_DESCRIPTORS, (TEXT("+Dump USB_HUB_DESCRIPTOR\n")) );
DEBUGMSG( ZONE_DESCRIPTORS, (TEXT("\tbDescriptorLength = 0x%02x\n"), pDescriptor->bDescriptorLength ));
DEBUGMSG( ZONE_DESCRIPTORS, (TEXT("\tbDescriptorType = 0x%02x\n"), pDescriptor->bDescriptorType ));
DEBUGMSG( ZONE_DESCRIPTORS, (TEXT("\tbNumberOfPorts = 0x%02x\n"), pDescriptor->bNumberOfPorts ));
DEBUGMSG( ZONE_DESCRIPTORS, (TEXT("\twHubCharacteristics = 0x%04x\n"), pDescriptor->wHubCharacteristics ));
if ( pDescriptor->wHubCharacteristics & USB_HUB_CHARACTERISTIC_NO_POWER_SWITCHING ) {
DEBUGMSG( ZONE_DESCRIPTORS, (TEXT("\t\twHubCharacteristics, No Port Power Switching\n")));
} else if ( pDescriptor->wHubCharacteristics & USB_HUB_CHARACTERISTIC_INDIVIDUAL_POWER_SWITCHING ) {
DEBUGMSG( ZONE_DESCRIPTORS, (TEXT("\t\twHubCharacteristics, Individual Port Power Switching\n")));
} else {
DEBUGMSG( ZONE_DESCRIPTORS, (TEXT("\t\twHubCharacteristics, Ganged Port Power Switching\n")));
}
DEBUGMSG( ZONE_DESCRIPTORS, (TEXT("\t\twHubCharacteristics, Hub %s part of compound device\n"), ((pDescriptor->wHubCharacteristics & USB_HUB_CHARACTERISTIC_PART_OF_COMPOUND_DEVICE) ? TEXT("IS") : TEXT("IS NOT")) ));
if ( pDescriptor->wHubCharacteristics & USB_HUB_CHARACTERISTIC_NO_OVER_CURRENT_PROTECTION ) {
DEBUGMSG( ZONE_DESCRIPTORS, (TEXT("\t\twHubCharacteristics, No Over Current Protection\n")));
} else if ( pDescriptor->wHubCharacteristics & USB_HUB_CHARACTERISTIC_INDIVIDUAL_OVER_CURRENT_PROTECTION ) {
DEBUGMSG( ZONE_DESCRIPTORS, (TEXT("\t\twHubCharacteristics, Individual Over Current Protection\n")));
} else {
DEBUGMSG( ZONE_DESCRIPTORS, (TEXT("\t\twHubCharacteristics, Global Over Current Protection\n")));
}
DEBUGMSG( ZONE_DESCRIPTORS, (TEXT("\tbPowerOnToPowerGood = 0x%02x\n"), pDescriptor->bPowerOnToPowerGood ));
DEBUGMSG( ZONE_DESCRIPTORS, (TEXT("\tbHubControlCurrent = 0x%02x\n"), pDescriptor->bHubControlCurrent ));
const UCHAR numBytes = 1 + (pDescriptor->bNumberOfPorts >> 3);
for ( UCHAR offset = 0; offset < numBytes; offset++ ) {
DEBUGMSG( ZONE_DESCRIPTORS, (TEXT("\tDeviceRemovable bitmask byte #%d = 0x%02x\n"), offset + 1, pDescriptor->bRemoveAndPowerMask[ offset ] ) );
}
for ( offset = numBytes; offset < 2 * numBytes; offset++ ) {
DEBUGMSG( ZONE_DESCRIPTORS, (TEXT("\tPortPwrCtrlMask bitmask byte #%d = 0x%02x\n"), offset - numBytes + 1, pDescriptor->bRemoveAndPowerMask[ offset ] ) );
}
DEBUGMSG( ZONE_DESCRIPTORS, (TEXT("-Dump USB_HUB_DESCRIPTOR\n")) );
}
#endif // DEBUG
// ******************************************************************
void CHub::AttachDevice( IN const UCHAR port,
IN const BOOL fIsLowSpeed )
//
// Purpose: This function is called when a new device is attached
// on port "port". After this procedure finishes, a configured
// device will be added to the hub's port array
//
// Parameters: port - indicates hub port on which device was attached
//
// fIsLowSpeed - indicates if new device is low speed
//
// Returns: Nothing
//
// Notes: If this function fails, the port will be disabled
// ******************************************************************
{
DEBUGMSG( ZONE_ATTACH, (TEXT("+CHub(%s tier %d)::AttachDevice - port = %d, fIsLowSpeed = %d\n"), GetDeviceType(), m_tierNumber, port, fIsLowSpeed ) );
DEBUGCHK( port > 0 && port <= m_usbHubDescriptor.bNumberOfPorts );
// device related variables
CDevice* pNewDevice = NULL;
UCHAR address = 0xff; // illegal address
USB_DEVICE_INFO deviceInfo;
USB_HUB_DESCRIPTOR usbHubDescriptor;
CPipeAbs* pControlPipe = NULL; // pipe to device's endpoint 0
// setup process related varibles
BOOL fUsingAddr0 = FALSE;
DEVICE_CONFIG_STATUS configStatus = DEVICE_CONFIG_STATUS_OPENING_ENDPOINT0_PIPE;
UCHAR configFailures = 0;
UINT currentConfigDescriptorIndex = 0;
BOOL fPipeHalted = FALSE;
deviceInfo.dwCount = sizeof( USB_DEVICE_INFO );
deviceInfo.lpActiveConfig = NULL;
deviceInfo.lpConfigs = NULL;
if ( !ReserveAddress( address ) ) {
DEBUGMSG( ZONE_WARNING, (TEXT("CHub(%s tier %d)::AttachDevice - all USB addresses are in use!\n"), GetDeviceType(), m_tierNumber) );
// don't do any attach processing
configStatus = DEVICE_CONFIG_STATUS_DONE;
}
while ( configStatus != DEVICE_CONFIG_STATUS_DONE ) {
if ( m_fHubThreadClosing || fPipeHalted || configFailures > 2 ) {
configStatus = DEVICE_CONFIG_STATUS_FAILED;
}
DEBUGMSG( ZONE_ATTACH, (TEXT("CHub(%s tier %d)::AttachDevice - status = %s, failures = %d\n"), GetDeviceType(), m_tierNumber, STATUS_TO_STRING( configStatus ), configFailures ) );
switch ( configStatus ) {
case DEVICE_CONFIG_STATUS_OPENING_ENDPOINT0_PIPE:
{
DEBUGCHK( pControlPipe == NULL );
USB_ENDPOINT_DESCRIPTOR usbEndpointZeroDescriptor;
usbEndpointZeroDescriptor.bDescriptorType = USB_ENDPOINT_DESCRIPTOR_TYPE;
usbEndpointZeroDescriptor.bEndpointAddress = 0;
// usbEndpointZeroDescriptor.bInterval = ; <- ignored for control pipes
usbEndpointZeroDescriptor.bLength = sizeof( USB_ENDPOINT_DESCRIPTOR );
usbEndpointZeroDescriptor.bmAttributes = USB_ENDPOINT_TYPE_CONTROL;
usbEndpointZeroDescriptor.wMaxPacketSize = ENDPOINT_ZERO_MIN_MAXPACKET_SIZE;
pControlPipe = CreateControlPipe( &usbEndpointZeroDescriptor,
fIsLowSpeed,0,
m_pCHcd);
if ( pControlPipe != NULL && pControlPipe->OpenPipe() == requestOK ) {
// success
configStatus = DEVICE_CONFIG_STATUS_USING_ADDRESS0;
} else {
DEBUGMSG( ZONE_ATTACH && ZONE_ERROR, (TEXT("CHub(%s tier %d)::AttachDevice - failure on %s step, unable to open control pipe\n"), GetDeviceType(), m_tierNumber, STATUS_TO_STRING( configStatus ) ) );
configFailures++;
delete pControlPipe;
pControlPipe = NULL;
}
break;
}
case DEVICE_CONFIG_STATUS_USING_ADDRESS0:
{
DEBUGCHK( !fUsingAddr0 );
fUsingAddr0 = TRUE;
//if (EnterCritSec_Ex( &m_csAddress0Lock, INFINITE ) != CSS_SUCCESS) {
if (m_pDeviceGlobal->Addr0LockEntry(INFINITE )!= CSS_SUCCESS) {
DEBUGMSG( ZONE_ATTACH, (TEXT("CHub(%s tier %d)::AttachDevice - shutdown signalled during enumeration\n"), GetDeviceType(), m_tierNumber) );
fUsingAddr0 = FALSE;
configStatus = DEVICE_CONFIG_STATUS_FAILED;
} else
// successfully acquired the Address0Lock
configStatus = DEVICE_CONFIG_STATUS_RESET_AND_ENABLE_PORT;
break;
}
case DEVICE_CONFIG_STATUS_RESET_AND_ENABLE_PORT:
{
DEBUGCHK( fUsingAddr0 );
if ( ResetAndEnablePort( port ) ) {
configStatus = DEVICE_CONFIG_STATUS_SCHEDULING_SET_ADDRESS;
} else {
DEBUGMSG( ZONE_ATTACH && ZONE_ERROR, (TEXT("CHub(%s tier %d)::AttachDevice - failure on %s step, unable to reset/enable port\n"), GetDeviceType(), m_tierNumber, STATUS_TO_STRING( configStatus ) ) );
configFailures++;
}
break;
}
case DEVICE_CONFIG_STATUS_SCHEDULING_SET_ADDRESS:
{
DEBUGCHK( fUsingAddr0 &&
pControlPipe != NULL &&
address > 0 );
BOOL fTransferDone = FALSE;
DWORD dwBytesTransferred = 0;
DWORD dwErrorFlags = USB_NOT_COMPLETE_ERROR;
HCD_REQUEST_STATUS status = requestFailed;
USB_DEVICE_REQUEST usbRequest;
usbRequest.bmRequestType = USB_REQUEST_HOST_TO_DEVICE | USB_REQUEST_STANDARD | USB_REQUEST_FOR_DEVICE;
usbRequest.bRequest = USB_REQUEST_SET_ADDRESS;
usbRequest.wValue = address; // new address
usbRequest.wIndex = 0;
usbRequest.wLength = 0;
// Note - at this point, the device is listening on address 0,
// so we pass 0, not "address", to the IssueTransfer function
if ( !m_fHubThreadClosing ) {
status = pControlPipe->IssueTransfer(
0, // device address (addr0)
TransferDoneCallbackSetEvent, // callback func
m_hHubStatusChangeEvent, // callback param
USB_OUT_TRANSFER | USB_SEND_TO_DEVICE, // transfer params
&usbRequest, // control request
0, // dwStartingFrame (not used)
0, // dwFrames (not used)
NULL, // aLengths (not used)
0, // buffer size
NULL, // buffer
0, // phys addr of buffer (not used)
this, // cancel id
NULL, // adwIsochErrors (not used)
NULL, // adwIsochLengths (not used)
&fTransferDone, // OUT status param
&dwBytesTransferred, // OUT status param
&dwErrorFlags ); // OUT status param
if ( status == requestOK ) {
WaitForSingleObject( m_hHubStatusChangeEvent, INFINITE );
if ( m_fHubThreadClosing ) {
pControlPipe->AbortTransfer( NULL, // callback function
NULL, // callback parameter
this ); // cancel ID
}
}
DEBUGCHK( fTransferDone );
}
if ( status == requestOK &&
fTransferDone &&
dwBytesTransferred == 0 &&
dwErrorFlags == USB_NO_ERROR ) {
configStatus = DEVICE_CONFIG_STATUS_LEAVE_ADDRESS0;
} else {
DEBUGMSG( ZONE_ATTACH && ZONE_ERROR, (TEXT("CHub(%s tier %d)::AttachDevice - failure on %s step, fTransferDone = %d, dwBytesTrans = 0x%x, dwErrorFlags = 0x%x\n"), GetDeviceType(), m_tierNumber, STATUS_TO_STRING( configStatus ), fTransferDone, dwBytesTransferred, dwErrorFlags ) );
configFailures++;
pControlPipe->IsPipeHalted( &fPipeHalted );
configStatus = DEVICE_CONFIG_STATUS_RESET_AND_ENABLE_PORT;
}
break;
}
case DEVICE_CONFIG_STATUS_LEAVE_ADDRESS0:
{
DEBUGCHK( fUsingAddr0 );
// it can take some time for SetAddress to
// take effect. In the OHCD code, there is a comment
// that some devices (i.e. Andromeda hub) need a
// delay here
Sleep( 10 );
//LeaveCritSec_Ex( &m_csAddress0Lock );
m_pDeviceGlobal->Addr0LockLeave();
fUsingAddr0 = FALSE;
configStatus = DEVICE_CONFIG_STATUS_SCHEDULING_GET_INITIAL_DEVICE_DESCRIPTOR;
break;
}
case DEVICE_CONFIG_STATUS_SCHEDULING_GET_INITIAL_DEVICE_DESCRIPTOR:
{
if ( GetDescriptor( pControlPipe,
address,
USB_DEVICE_DESCRIPTOR_TYPE,
0, // descriptor index
ENDPOINT_ZERO_MIN_MAXPACKET_SIZE,
&deviceInfo.Descriptor ) ) {
DEBUGCHK( m_tierNumber <= USB_MAXIMUM_HUB_TIER );
if ( m_tierNumber == USB_MAXIMUM_HUB_TIER &&
deviceInfo.
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -