📄 cdevice.cpp
字号:
}
LeaveCriticalSection( &m_csDeviceLock );
if ( hubStatus.change.port.PortEnableChange &&
!hubStatus.status.port.PortEnabled &&
hubStatus.status.port.PortConnected ) {
// Connected device has become disabled. If the device was
// already successfully attached, let's try detach/reattach.
// It is important to check that the device was successfully
// attached - otherwise, we can get into an infinite loop
// of try attach, fail, disable port, retry attach.
BOOL fDeviceIsPresent;
EnterCriticalSection( &m_csDeviceLock );
DEBUGCHK( m_ppCDeviceOnPort != NULL );
fDeviceIsPresent = ( m_ppCDeviceOnPort[ port - 1 ] != NULL );
LeaveCriticalSection( &m_csDeviceLock );
if ( fDeviceIsPresent ) {
DEBUGMSG( ZONE_WARNING, (TEXT("CHub(%s tier %d)::HubStatusChangeThread - device on port %d is connected but has been disabled. Trying to detach & re-attach\n"), GetDeviceType(), m_tierNumber, port) );
DetachDevice( port );
// this will cause device attach below, since
// hubStatus.status.port.PortConnected is already set
hubStatus.change.port.ConnectStatusChange = 1;
DEBUGCHK( hubStatus.status.port.PortConnected );
}
} // we can ignore all other enabled changes
// now check for connect changes
if ( hubStatus.change.port.ConnectStatusChange ) {
EnterCriticalSection( &m_csDeviceLock );
BOOL fDeviceAlreadyExists = (m_ppCDeviceOnPort[ port - 1 ] != NULL);
LeaveCriticalSection( &m_csDeviceLock );
// we got a connect status change notification on this port, so...
if (fDeviceAlreadyExists) {
// ... a change when the device is already here must be a detach;
// if there's still something connected then it must be new.
DEBUGMSG( ZONE_ATTACH, (TEXT("CHub(%s tier %d)::HubStatusChangeThread - device detached on port %d\n"), GetDeviceType(), m_tierNumber, port ) );
DetachDevice(port);
#ifdef DEBUG
if ( hubStatus.status.port.PortConnected ) {
DEBUGMSG( (ZONE_WARNING && ZONE_VERBOSE) || ZONE_ATTACH,
(TEXT("CHub(%s tier %d)::HubStatusChangeThread -")
TEXT(" quick detach and re-attach on port %d\n"),
GetDeviceType(), m_tierNumber, port) );
}
#endif // DEBUG
}
// ... a change with no device present must be an attach
// but section 7.1.7.1 of the USB 1.1 spec says we're
// 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;
}
}
// We have to reset port and get speed infomation.
ResetAndEnablePort( port );
Sleep(20);
GetStatus(port , hubStatus);
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,
m_fIsHighSpeed?hubStatus.status.port.DeviceIsHighSpeed:FALSE );
}
} // end of ConnectStatusChange processing
}
DEBUGMSG( ZONE_HUB, (TEXT("-CHub(%s tier %d)::HubStatusChangeThread, THREAD EXITING, returning 0\n"), GetDeviceType(), m_tierNumber ) );
return 0;
}
// ******************************************************************
HCD_REQUEST_STATUS CDevice::DisableDevice( IN const UINT address,
IN const BOOL fReset )
//
// Purpose: Disable Downstream Device with address "address"
//
// Parameters: See description in CHcd::DisableDevice.
//
// Returns: requestOK - if Device Reset
//
// requestFailed - if device exists, but unable to disable it.
//
// requestIgnored - if no device found with matching address
//
// Notes:
// ******************************************************************
{
DEBUGMSG( ZONE_HUB && ZONE_VERBOSE, (TEXT("CHub(%s tier %d)::DisableDevice - address = %d, pipeIndex = %d\n"), GetDeviceType(), m_tierNumber, address, fReset) );
HCD_REQUEST_STATUS status = requestIgnored;
if (address == m_address ) { // If it is this device
m_pAttachedHub->DisableOffStreamDevice( address, fReset);
status = requestOK;
}
return status;
}
// ******************************************************************
HCD_REQUEST_STATUS CDevice::SuspendResume( IN const UINT address,
IN const BOOL fSuspend )
//
// Purpose: Suspend or Resume on device with address "address"
//
// Parameters: See description in CHcd::SuspendResume
//
// Returns: requestOK - if device suspend or resumed
//
// requestFailed - if device exists, but unable to reset it
//
// requestIgnored - if no device found with matching address
//
// Notes:
// ******************************************************************
{
DEBUGMSG( ZONE_HUB && ZONE_VERBOSE, (TEXT("+CHub(%s tier %d)::SuspendResume - address = %d, fSuspend = %d\n"), GetDeviceType(), m_tierNumber, address, fSuspend) );
HCD_REQUEST_STATUS status = requestIgnored;
EnterCriticalSection( &m_csDeviceLock );
if ( address == m_address ) {
if (m_pAttachedHub->SuspendResumeOffStreamDevice(address, fSuspend)) {
m_fIsSuspend=fSuspend;
status = requestOK;
}
else
status = requestFailed;
}
LeaveCriticalSection( &m_csDeviceLock );
DEBUGMSG( ZONE_HUB && ZONE_VERBOSE, (TEXT("-CHub(%s tier %d)::SuspendResume - address = %d, returing HCD_REQUEST_STATUS %d\n"), GetDeviceType(), m_tierNumber, address, status) );
return status;
}
#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
// ******************************************************************
{
PREFAST_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 ,
IN const BOOL fIsHighSpeed )
//
// 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:
{
// Create TT if it is neccessary.
if (m_fIsHighSpeed && !fIsHighSpeed && !m_pAddedTT[port-1]) { // Hi-Speed Hub and Low Speed device.
m_pAddedTT[port-1] = m_pDeviceGlobal->AddedTt(m_address,port);
}
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;
UCHAR uTTHubAddr= m_address;
UCHAR uTTHubPort= port;
GetUSB2TT(&uTTHubAddr,&uTTHubPort);
pControlPipe = CreateControlPipe( &usbEndpointZeroDescriptor,
fIsLowSpeed, fIsHighSpeed ,0,
uTTHubAddr,uTTHubPort,
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 pi
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -