⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cdevice.cpp

📁 嵌入式操作系统WINCE5.0下的USB驱动程序
💻 CPP
📖 第 1 页 / 共 5 页
字号:
//
// Notes: Used in debug mode only
//
//        See USB spec section 9.6.4
// ******************************************************************
{
    static const TCHAR* cszEndpointTypes[4] = {
        TEXT("CONTROL"),
        TEXT("ISOCHRONOUS"),
        TEXT("BULK"),
        TEXT("INTERRUPT")
    };
    DEBUGCHK( pDescriptor != NULL );
    DEBUGMSG( ZONE_DESCRIPTORS, (TEXT("+Dump USB_ENDPOINT_DESCRIPTOR\n")) );
    DEBUGMSG( ZONE_DESCRIPTORS, (TEXT("\tbLength = 0x%02x\n"), pDescriptor->bLength ));
    DEBUGMSG( ZONE_DESCRIPTORS, (TEXT("\tbDescriptorType = 0x%02x\n"), pDescriptor->bDescriptorType ));
    DEBUGMSG( ZONE_DESCRIPTORS, (TEXT("\tbEndpointAddress = 0x%02x\n"), pDescriptor->bEndpointAddress ));
    DEBUGMSG( ZONE_DESCRIPTORS, (TEXT("\t\tbEndpointAddress, endpoint # = %d\n"), pDescriptor->bEndpointAddress & TD_ENDPOINT_MASK ));
    DEBUGMSG( ZONE_DESCRIPTORS, (TEXT("\t\tbEndpointAddress, direction = %s\n"), (USB_ENDPOINT_DIRECTION_IN(pDescriptor->bEndpointAddress) ? TEXT("IN") : TEXT("OUT")) ));
    DEBUGMSG( ZONE_DESCRIPTORS, (TEXT("\tbmAttributes = 0x%02x\n"), pDescriptor->bmAttributes ));
    DEBUGCHK( (pDescriptor->bmAttributes & USB_ENDPOINT_TYPE_MASK) < 4 );
    DEBUGMSG( ZONE_DESCRIPTORS, (TEXT("\t\tbmAttributes, endpoint type = %s\n"), cszEndpointTypes[ pDescriptor->bmAttributes & USB_ENDPOINT_TYPE_MASK ] ));
    DEBUGMSG( ZONE_DESCRIPTORS, (TEXT("\twMaxPacketSize = 0x%04x\n"), pDescriptor->wMaxPacketSize ));
    DEBUGMSG( ZONE_DESCRIPTORS, (TEXT("\tbInterval = 0x%02x\n"), pDescriptor->bInterval ));
    DEBUGMSG( ZONE_DESCRIPTORS, (TEXT("-Dump USB_ENDPOINT_DESCRIPTOR\n")) );
}
#endif // DEBUG

#ifdef DEBUG
// ******************************************************************
void CDevice::DumpExtendedBytes( IN const PBYTE pByteArray, IN const DWORD dwSize ) const
//
// Purpose: print out the bytes of pByteArray
//
// Parameters: pByteArray - array of extended bytes for a descriptor
//
//             dwSize - number of entries in pByteArray
//
// Returns: Nothing.
//
// Notes: Used in debug mode only
// ******************************************************************
{
    DEBUGCHK( pByteArray != NULL && dwSize > 0 );
    DEBUGMSG( ZONE_DESCRIPTORS, (TEXT("+Dump extended bytes, size = %d\n"), dwSize) );
    for ( DWORD dwPrinted = 0; dwPrinted < dwSize; dwPrinted += 4 ) {
        DWORD dwFourBytes = 0;
        for ( UCHAR index = 0; index < 4; index++  ) {
            dwFourBytes <<= 8;
            if ( dwPrinted + index < dwSize ) {
                dwFourBytes |= pByteArray[ dwPrinted + index ];
            }
        }
        DEBUGMSG( ZONE_DESCRIPTORS, (TEXT("\tBytes %d to %d = 0x%08x\n"), dwPrinted + 1, dwPrinted + 4, dwFourBytes ) );
    }
    DEBUGMSG( ZONE_DESCRIPTORS, (TEXT("-Dump extended bytes, size = %d\n"), dwSize) );
}
#endif // DEBUG

// ******************************************************************
CHub::CHub( IN const UCHAR address,
            IN const USB_DEVICE_INFO& rDeviceInfo,
            IN const BOOL fIsLowSpeed,IN const BOOL fIsHighSpeed,
            IN const UCHAR tierNumber,
            IN const USB_HUB_DESCRIPTOR& rUsbHubDescriptor,
            IN CHcd * const pCHcd ,
            IN CHub * const pAttachedHub,const UCHAR uAttachedPort)
//
// Purpose: Constructor for CHub
//
// Parameters: address, rDeviceInfo, fIsLowSpeed, tierNumber - see CDevice::CDevice
//
//             rUsbHubDescriptor - USB descriptor for a hub
//
// Returns: Nothing.
//
// Notes: Do not initialize static variables here. Do that in
//        the Initialize() routine
// ******************************************************************
: CDevice( address, rDeviceInfo, fIsLowSpeed,fIsHighSpeed, tierNumber,pCHcd , pAttachedHub,uAttachedPort ) // call base class constructor
, m_pCHcd(pCHcd)
, m_usbHubDescriptor( rUsbHubDescriptor ) // USB descriptor of this hub
, m_ppCDeviceOnPort( NULL ) // dynamic array of pointers to the devices on this hub's ports
, m_fHubThreadClosing( FALSE )       // indicator to thread that it should close
, m_hHubStatusChangeEvent( NULL ) // event for hub status change thread
, m_hHubStatusChangeThread( NULL ) // checks for connect changes on the hub's ports
{
    DEBUGMSG( ZONE_HUB && ZONE_VERBOSE, (TEXT("+CHub::CHub\n")) );
    m_pDetachedDevice=NULL;
    m_pDetachedDeviceHandled = CreateEvent(NULL,TRUE,FALSE,NULL); // Manual Reset Event;
    m_hHubSuspendBlockEvent = CreateEvent(NULL,TRUE,TRUE,NULL); // Manual Reset Event;
    DEBUGCHK( rDeviceInfo.Descriptor.bDeviceClass == USB_DEVICE_CLASS_HUB &&
              rUsbHubDescriptor.bDescriptorType == USB_HUB_DESCRIPTOR_TYPE &&
              rUsbHubDescriptor.bDescriptorLength >= USB_HUB_DESCRIPTOR_MINIMUM_SIZE &&
              rUsbHubDescriptor.bNumberOfPorts > 0 &&
              tierNumber <= USB_MAXIMUM_HUB_TIER );

    DEBUGMSG( ZONE_HUB && ZONE_VERBOSE, (TEXT("-CHub::CHub\n")) );
}

// ******************************************************************
CHub::~CHub( )
//
// Purpose: Destructor for CHub
//
// Parameters: None
//
// Returns: Nothing.
//
// Notes: Do not delete static variables here. Do that in
//        DeInitialize();
// ******************************************************************
{
    DEBUGMSG( ZONE_HUB && ZONE_VERBOSE, (TEXT("+CHub::~CHub\n")) );

    // this should have been taken care of in HandleDetach,
    // or if EnterOperationalState failed.
    DEBUGCHK( m_hHubStatusChangeEvent == NULL );
    DEBUGCHK( m_hHubStatusChangeThread == NULL );
    DEBUGCHK( m_pDetachedDevice == NULL);

#ifdef DEBUG
    if ( m_ppCDeviceOnPort != NULL ) {
        for ( UCHAR port = 1; port <= m_usbHubDescriptor.bNumberOfPorts; port++ ) {
            // devices should have been freed by HandleDetach
            DEBUGCHK( m_ppCDeviceOnPort[ port - 1 ] == NULL );
        }
    }
#endif // DEBUG
    if (m_ppCDeviceOnPort){
        delete [] m_ppCDeviceOnPort;
        m_ppCDeviceOnPort = NULL;
    }
    if (m_pAddedTT){
        delete m_pAddedTT;
        m_pAddedTT = NULL;
    }
    if (m_pDetachedDeviceHandled)
        CloseHandle(m_pDetachedDeviceHandled );    
    // nothing to do with m_usbHubDescriptor
    // nothing to do with m_fHubThreadClosing

    // rest of work done in ~CDevice

    DEBUGMSG( ZONE_HUB && ZONE_VERBOSE, (TEXT("-CHub::~CHub\n")) );
}


// ******************************************************************
DWORD CALLBACK CHub::HubStatusChangeThreadStub( IN PVOID context )
//
// Purpose: Stub function for starting HubStatusChangeThread
//
// Parameters: context - pointer to descendant of CHub which contains
//                       the actual HubStatusChangeThread function
//
// Returns: Return value of HubStatusChangeThread
//
// Notes:
// ******************************************************************
{
    return ((CHub*)context)->HubStatusChangeThread();
}
// ******************************************************************
DWORD CHub::HubStatusChangeThread( void )
//
// Purpose: Main hub thread for handling changes to the hub's ports
//
// Parameters: None
//
// Returns: 0 on thread exit
//
// Notes: This routine needs to work for both root/external hubs
// ******************************************************************
{
    DEBUGMSG( ZONE_HUB && ZONE_VERBOSE, (TEXT("+CHub(%s tier %d)::HubStatusChangeThread\n"), GetDeviceType(), m_tierNumber ) );
    DEBUGCHK( m_hHubStatusChangeEvent != NULL && m_hHubStatusChangeThread != NULL );

    UCHAR                       port;
    USB_HUB_AND_PORT_STATUS     hubStatus;
    BOOL                        fSuccess = FALSE;

    // before we can process port changes, we need
    // to power all ports
    while ( !m_fHubThreadClosing && !fSuccess) {
        fSuccess = PowerAllHubPorts();
    }
    if ( !m_fHubThreadClosing ) {
#if 0
        Sleep( 2 * m_usbHubDescriptor.bPowerOnToPowerGood );
#else
        // According to the USB spec 1.1, section 7.1.7.1, there
        // is supposed to be a delay of up to 100ms (t2) before the device
        // can signal attach. I don't know if the software is
        // supposed to implement this delay. No harm in implementing
        // it though.
        Sleep( 100 + 2 * m_usbHubDescriptor.bPowerOnToPowerGood );
#endif
    }
    SetOrClearRemoteWakup(TRUE);
    while ( !m_fHubThreadClosing ) {
        
        fSuccess = (WaitForSingleObject(m_hHubSuspendBlockEvent,INFINITE) == WAIT_OBJECT_0);
        if (m_fHubThreadClosing || !fSuccess)
            break;
        
        fSuccess = WaitForPortStatusChange( port, hubStatus );
        if ( m_fHubThreadClosing || !fSuccess ) {
            if (!fSuccess && !m_fHubThreadClosing && (m_pCHcd->GetCapability() & HCD_SUSPEND_ON_REQUEST)!=0 ) { 
                // We need check to find out this hub need put into suspend mode.
                PREFAST_ASSERT(m_ppCDeviceOnPort!=NULL);
                EnterCriticalSection( &m_csDeviceLock );
                BOOL bDoSuspend = TRUE;
                for ( UCHAR port2 = 1; port2 <= m_usbHubDescriptor.bNumberOfPorts; port2++ ) {
                    if (m_ppCDeviceOnPort [port2 -1] != NULL) { // Can not.
                        bDoSuspend = FALSE;
                        break;
                    }
                }
                LeaveCriticalSection( &m_csDeviceLock );
                if (bDoSuspend) {
                    BOOL bSuspend =((m_pAttachedHub!=NULL)? 
                            (m_pAttachedHub->SuspendResumeOffStreamDevice(m_address, TRUE)==requestOK):
                            m_pCHcd->SuspendHC());
                    DEBUGMSG( ZONE_HUB, (TEXT("CHub(%s tier %d):: Suspend Device (%d) return %s!\n"), GetDeviceType(), m_tierNumber,m_address,bSuspend?TEXT("Success"):TEXT("FAIL")) );
                    if (bSuspend) {
                        m_fIsSuspend = TRUE;
                        ResetEvent(m_hHubSuspendBlockEvent);// Stop this thread.
                    }
                }
                
            }
            else
                DEBUGMSG( ZONE_ERROR && !m_fHubThreadClosing, (TEXT("CHub(%s tier %d)::HubStatusChangeThread - error reading port status change\n"), GetDeviceType(), m_tierNumber ));
            continue; // loop will exit if m_fHubThreadClosing is set
        }
        if ( port == 0 ) { // Port 0 indicate this is hub status.
            if (hubStatus.change.hub.OverCurrentIndicatorChange ) {
                if ( hubStatus.status.hub.OverCurrentIndicator ) {
                    RETAILMSG(1, (TEXT("CHub(tier %d)::HubStatusChangeThread - addr %d port %d over current!\n"),
                                  m_tierNumber, m_address, port));
                } else {
                    // hub is no longer over current - re-enumerate all ports
                    // todo - re-enumerate all hub ports during hub over-current recovery
                }
            }
            continue;
        }

        // we will get here if the status of port # "port" has changed.
        // the status information will be in "hubStatus"
        DEBUGCHK( port <= m_usbHubDescriptor.bNumberOfPorts );
        DEBUGMSG( ZONE_ATTACH, (TEXT("CHub(%s tier %d)::HubStatusChangeThread - port %d, change = 0x%04x, status = 0x%04x\n"), GetDeviceType(), m_tierNumber, port, hubStatus.change.word, hubStatus.status.word ) );

        if (hubStatus.change.port.OverCurrentChange ) {
            if ( hubStatus.status.port.PortOverCurrent ) {
                RETAILMSG(1, (TEXT("CHub(tier %d)::HubStatusChangeThread - addr %d port %d over current!\n"),
                              m_tierNumber, m_address, port));
                DetachDevice( port );
#if 1   // the "correct" thing to do, according to my reading of the USB spec
                SetOrClearFeature( port, USB_REQUEST_CLEAR_FEATURE, USB_HUB_FEATURE_PORT_POWER );
#else   // another approach
                do {
                    Sleep( 500 );
                    GetStatus( port, hubStatus );
                } while (hubStatus.status.port.PortOverCurrent && !m_fHubThreadClosing);
                hubStatus.change.port.ConnectStatusChange = 1;
#endif
            } else {
                // port is no longer over current - pretend this is a normal attach
                // simulate a connect status change. this has the undesirable but basically harmless
                // side effect of wasting 100 ms to needlessly debounce the power rail.
                hubStatus.change.port.ConnectStatusChange = 1;
            }
        }
        // Resume Notification.
        EnterCriticalSection( &m_csDeviceLock );
        if ( hubStatus.change.port.SuspendChange && !hubStatus.status.port.PortSuspended  && 
                m_ppCDeviceOnPort[port-1]!=NULL ) {
            m_ppCDeviceOnPort[port-1]->ResumeNotification();

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -