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

📄 pmdevice.cpp

📁 此代码为WCE5.0下电源管理的源代码
💻 CPP
📖 第 1 页 / 共 4 页
字号:
QueryDeviceStateUpdate(PDEVICE_STATE pds, PSYSTEM_POWER_STATE psps, 
                       PDEVICE_POWER_RESTRICTION pFloorDx, 
                       PDEVICE_POWER_RESTRICTION pCeilingDx)
{
    BOOL fOk = TRUE;
    CEDEVICE_POWER_STATE floorDx, ceilingDx;
    CEDEVICE_POWER_STATE newDx = PwrDeviceUnspecified;
    SETFNAME(_T("QueryDeviceState"));

    PMLOCK();
    // get the new device power state (based on the last device power state
    // the device wanted -- this value is initialized to D0 in case the 
    // device never makes any power requests on its own.
    fOk = GetNewDeviceStateInfo(&floorDx, &ceilingDx, pds, psps, pFloorDx, pCeilingDx);
    if(fOk) {
        newDx = GetNewDeviceDx(pds->lastReqDx, pds->curDx, pds->setDx, floorDx, ceilingDx);
        PMLOGMSG(ZONE_DEVICE, 
            (_T("%s: new state for '%s' is %d (current %d, req %d, set %d, floor %d, ceiling %d, actual %d)\r\n"),
            pszFname, pds->pszName, newDx, pds->curDx, pds->lastReqDx, pds->setDx, pds->floorDx, pds->ceilingDx, pds->actualDx));
    }
    PMUNLOCK();

    // do we need to update the device?
    if(fOk && newDx != PwrDeviceUnspecified) {
        // yes, see if the device is able to update its power state to the new value
        fOk = QueryDevicePowerUpdate(pds, newDx);
    }

    return fOk;
}

// This routine asks all registered devices if they are ready to make device
// power state transitions to a new system power state.  It returns TRUE if all
// responses are positive, FALSE otherwise.
BOOL 
QueryClassDevices(PDEVICE_LIST pdl, PSYSTEM_POWER_STATE psps, PDEVICE_POWER_RESTRICTION pdprCeiling,
                     PDEVICE_POWER_RESTRICTION pdprFloor)
{
    BOOL fOk = TRUE;
    BOOL fDeviceRemoved;
    PDEVICE_STATE pds;
    SETFNAME(_T("QueryClassDevices"));

    DEBUGCHK(pdl != NULL);

    PMLOCK();

    // Since it's possible that the device list may be modified
    // while we are not holding the PM critical section we need
    // to watch out for the device we are working on getting removed.
    // We increment the reference count to keep the device data 
    // structure from being deallocated out from under us.  Once
    // the device update is complete and we have the critical section
    // again, we check to see if it's still part of the device list.
    // If it's not, we start again at the top of the list.
    do {
        fDeviceRemoved = FALSE;
        pds = pdl->pList;
        while(fOk && !fDeviceRemoved && pds != NULL) {
            PDEVICE_STATE pdsNext;
            DeviceStateAddRef(pds);     // keep the device pointer alive
            
            PMUNLOCK();
            fOk = QueryDeviceStateUpdate(pds, psps, pdprFloor, pdprCeiling);
            PMLOCK();
            
            // is the device still on the list?
            if(pds->pListHead == NULL) {
                // device disappeared while we were accessing it
                PMLOGMSG(ZONE_WARN || ZONE_DEVICE, 
                    (_T("%s: device '%s' removed during update\r\n"), pszFname,
                    pds->pszName));
                fDeviceRemoved = TRUE;
            } else {
                // save the next pointer so we don't try to
                // dereference pds after decrementing its use count.
                pdsNext = pds->pNext;
            }
            DeviceStateDecRef(pds);     // done with the device pointer
            if(!fDeviceRemoved) pds = pdsNext;  // on to the next
        }
    } while(fOk && (fDeviceRemoved || pds != NULL));

    PMUNLOCK();

    PMLOGMSG(!fOk && ZONE_WARN, (_T("%s: returning %d\r\n"), pszFname, fOk));
    return fOk;
}

// This routine asks all registered devices if they are ready to make device
// power state transitions to a new system power state.  It returns TRUE if all
// responses are positive, FALSE otherwise.
BOOL 
QueryAllDevices(PSYSTEM_POWER_STATE psps, PDEVICE_POWER_RESTRICTION pdprCeiling,
                     PDEVICE_POWER_RESTRICTION pdprFloor)
{
    PDEVICE_LIST pdl;
    BOOL fOk = TRUE;
    SETFNAME(_T("QueryAllDevices"));

    // update all devices of all classes
    for(pdl = gpDeviceLists; fOk && pdl != NULL; pdl = pdl->pNext) {
        fOk = QueryClassDevices(pdl, psps, pdprCeiling, pdprFloor);
    }

    PMLOGMSG(!fOk && ZONE_WARN, (_T("%s: returning %d\r\n"), pszFname, fOk));
    return fOk;
}

#endif  // PM_SUPPORTS_DEVICE_QUERIES

// This routine updates state for all devices.  It should be called during
// system power state transitions so that device power states can be
// adjusted appropriately.
VOID
UpdateClassDeviceStates(PDEVICE_LIST pdl)
{
    BOOL fDeviceRemoved;
    PDEVICE_STATE pds;
    SETFNAME(_T("UpdateClassDeviceStates"));

    PREFAST_DEBUGCHK(pdl != NULL);

    PMLOCK();

    // Since it's possible that the device list may be modified
    // while we are not holding the PM critical section we need
    // to watch out for the device we are working on getting removed.
    // We increment the reference count to keep the device data 
    // structure from being deallocated out from under us.  Once
    // the device update is complete and we have the critical section
    // again, we check to see if it's still part of the device list.
    // If it's not, we start again at the top of the list.  This should
    // be harmless since devices that are at the right power state
    // already won't be updated.
    do {
        fDeviceRemoved = FALSE;
        pds = pdl->pList;
        while(!fDeviceRemoved && pds != NULL) {
            PDEVICE_STATE pdsNext;
            DeviceStateAddRef(pds);     // keep the device pointer alive
            
            PMUNLOCK();
            UpdateDeviceState(pds);
            PMLOCK();
            
            // is the device still on the list?
            if(pds->pListHead == NULL) {
                // device disappeared while we were accessing it
                PMLOGMSG(ZONE_WARN || ZONE_DEVICE, 
                    (_T("%s: device '%s' removed during update\r\n"), pszFname,
                    pds->pszName));
                fDeviceRemoved = TRUE;
            } else {
                // save the next pointer so we don't try to
                // dereference pds after decrementing its use count.
                pdsNext = pds->pNext;
            }
            DeviceStateDecRef(pds);     // done with the device pointer
            if(!fDeviceRemoved) pds = pdsNext;  // on to the next
        }
    } while(fDeviceRemoved || pds != NULL);

    PMUNLOCK();
}

// This routine updates state for all devices of all classes.  It can be called during
// system power state transitions so that device power states can be
// adjusted appropriately.
VOID
UpdateAllDeviceStates(VOID)
{
    PDEVICE_LIST pdl;

    // update all devices of all classes
    for(pdl = gpDeviceLists; pdl != NULL; pdl = pdl->pNext) {
        UpdateClassDeviceStates(pdl);
    }
}

// this routine checks to see if a device pointer is actually on a 
// list someplace.  If it finds it, it increments its reference
// count and returns true.
BOOL
CheckDevicePointer(PDEVICE_STATE pds)
{
    PDEVICE_LIST pdl;
    BOOL fFound = FALSE;

    // look for a match
    DEBUGCHK(pds != NULL);
    PMLOCK();
    for(pdl = gpDeviceLists; pdl != NULL && !fFound; pdl = pdl->pNext) {
        PDEVICE_STATE pdsTraveller;
        for(pdsTraveller = pdl->pList; pdsTraveller != NULL; 
        pdsTraveller = pdsTraveller->pNext) {
            if(pdsTraveller == pds) {
                fFound = TRUE;
                break;
            }
        }
    }

    // did we find the device?
    if(fFound) {
        // yes, update its reference count
        DeviceStateAddRef(pds);
    }
    PMUNLOCK();

    return fFound;
}

// This routine adds a device to the list associated with its device class.
// This routine does not return a value; it will either create a new
// device state structure and add it to a list or it will not.  If the new
// device duplicates an existing one this routine won't create a new node.
// This routine executes in the context of the PnP thread, which handles
// device interface additions and removals.
VOID
AddDevice(LPCGUID guidDevClass, LPCTSTR pszName, PDEVICE_STATE pdsParent, 
          PPOWER_CAPABILITIES pCaps)
{
    SETFNAME(_T("AddDevice"));

    PMLOGMSG(ZONE_DEVICE, 
        (_T("%s: adding '%s', pdsParent 0x%08x, pCaps 0x%08x to class %08x-%04x-%04x-%04x-%02x%02x%02x%02x%02x%02x\r\n"), 
        pszFname, pszName, pdsParent, pCaps,
        guidDevClass->Data1, guidDevClass->Data2, guidDevClass->Data3,
        (guidDevClass->Data4[0] << 8) + guidDevClass->Data4[1], guidDevClass->Data4[2], guidDevClass->Data4[3], 
        guidDevClass->Data4[4], guidDevClass->Data4[5], guidDevClass->Data4[6], guidDevClass->Data4[7]));

    // figure out onto which list this device should be added
    PDEVICE_LIST pdl = GetDeviceListFromClass(guidDevClass);
    
    // did we find the list?
    if(pdl != NULL) {
        // check for duplicates
        PDEVICE_STATE pds = DeviceStateFindList(pdl, pszName);
        
        // create the device if it doesn't already exist
        if(pds == NULL) {
            BOOL fOk = FALSE;
            pds = DeviceStateCreate(pszName);
            if(pds != NULL) {
                // if we are passed the device's capabilities, just copy them
                // into the structure
                if(pCaps != NULL) {
                    __try {
                        pds->caps = *pCaps;
                    }
                    __except(EXCEPTION_EXECUTE_HANDLER) {
                        PMLOGMSG(ZONE_WARN, 
                            (_T("%s: exception during capabilities copy from 0x%08x\r\n"),
                            pszFname, pCaps));
                        pCaps = NULL;
                    }
                }
                
                // update the device's parent pointer
                if(pdsParent != NULL) {
                    DeviceStateAddRef(pdsParent);
                }
                pds->pParent = pdsParent;
                
                // add the new device to its class list
                if(!DeviceStateAddList(pdl, pds)) {
                    // deallocate the node, reference count isn't incremented
                    DeviceStateDecRef(pds);
                    pds = NULL;
                } else {
                    PREFAST_DEBUGCHK(pds->pInterface != NULL);
                    PREFAST_DEBUGCHK(pds->pInterface->pfnOpenDevice != NULL);
                    PREFAST_DEBUGCHK(pds->pInterface->pfnRequestDevice != NULL);
                    PREFAST_DEBUGCHK(pds->pInterface->pfnCloseDevice != NULL);
                    pds->hDevice = pds->pInterface->pfnOpenDevice(pds);
                    if(pds->hDevice == INVALID_HANDLE_VALUE) {
                        PMLOGMSG(ZONE_WARN, (_T("%s: couldn't open device '%s'\r\n"),
                            pszFname, pszName != NULL ? _T("<NULL>") : pszName));
                    } else {
                        // do we need to request capabilities?
                        fOk = TRUE;             // assume success
                        if(pCaps == NULL) {
                            DWORD dwBytesReturned;
                            POWER_RELATIONSHIP pr;
                            PPOWER_RELATIONSHIP ppr = NULL;
                            memset(&pr, 0, sizeof(pr));
                            if(pds->pParent != NULL) {
                                PMLOGMSG(ZONE_DEVICE, (_T("%s: parent of '%s' is '%s'\r\n"), 
                                    pszFname, pds->pszName, pds->pParent->pszName));
                                pr.hParent = (HANDLE) pds->pParent;
                                pr.pwsParent = pds->pParent->pszName;
                                pr.hChild = (HANDLE) pds;
                                pr.pwsChild = pds->pszName;
                                ppr = &pr;
                            }                        
                            
                            // get the device's capabilities structure
                            fOk = pds->pInterface->pfnRequestDevice(pds->hDevice, IOCTL_POWER_CAPABILITIES, 
                                ppr, ppr == NULL ? 0 : sizeof(*ppr), 
                                &pds->caps, sizeof(pds->caps), &dwBytesReturned);
                            
                            // sanity check the size in case a device is just returning
                            // a good status on all ioctls for some reason
                            if(fOk && dwBytesReturned != sizeof(pds->caps)) {
                                PMLOGMSG(ZONE_WARN, 
                                    (_T("%s: invalid size returned from IOCTL_POWER_CAPABILITIES\r\n"),
                                    pszFname));
                                fOk = FALSE;
                            }
                        }

                        // any problems so far?
                        if(fOk) {
                            // determine whether we should request power relationships from a parent device
                            if((pds->caps.Flags & POWER_CAP_PARENT) != 0) {
                                pds->pInterface->pfnRequestDevice(pds->hDevice, IOCTL_REGISTER_POWER_RELATIONSHIP,
                                    NULL, 0, NULL, 0, NULL);

⌨️ 快捷键说明

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