📄 pmdevice.cpp
字号:
}
}
}
}
// have we read all the configuration information we need from
// the new device
if(!fOk) {
// no, delete the device
DeviceStateRemList(pds);
} else {
// See if the device supports multiple handles. Power manageable devices
// should allow multiple open handles, but if they don't we will have to open
// one before each access.
HANDLE hDevice = pds->pInterface->pfnOpenDevice(pds);
if(hDevice == INVALID_HANDLE_VALUE) {
PMLOGMSG(ZONE_WARN, (_T("%s: WARNING: '%s' does not support multiple handles\r\n"),
pszFname));
pds->pInterface->pfnCloseDevice(pds->hDevice);
pds->hDevice = INVALID_HANDLE_VALUE;
} else {
// close the second handle, since we don't need it
pds->pInterface->pfnCloseDevice(hDevice);
}
// initialize the new device's power state variables
UpdateDeviceState(pds);
}
}
}
// we are done with the device pointer
if(pds != NULL) {
DeviceStateDecRef(pds);
}
} else {
PMLOGMSG(ZONE_WARN, (_T("%s: class for device '%s' not supported\r\n"),
pszFname, pszName));
}
}
// this routine removes a device from the list of managed devices. When
// the device's reference count goes to zero it will be deallocated.
VOID
RemoveDevice(LPCGUID guidDevClass, LPCTSTR pszName)
{
SETFNAME(_T("RemoveDevice"));
PMLOGMSG(ZONE_DEVICE, (_T("%s: removing '%s' from %08x-%04x-%04x-%04x-%02x%02x%02x%02x%02x%02x\r\n"),
pszFname, pszName, 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);
if(pds == NULL) {
PMLOGMSG(ZONE_WARN, (_T("%s: '%s' not in class list\r\n"),
pszFname, pszName));
} else {
// disconnect the device from the list
DeviceStateRemList(pds);
// if we are a child device, decrement the parent pointer's
// reference count
if(pds->pParent != NULL) {
DeviceStateDecRef(pds->pParent);
pds->pParent = NULL;
}
// if we are a parent device, remove child devices (if any)
if((pds->caps.Flags & POWER_CAP_PARENT) != 0) {
// look for a match across all lists, since the child may not
// be of the same class
for(pdl = gpDeviceLists; pdl != NULL; pdl = pdl->pNext) {
PDEVICE_STATE pCur, pNext;
pCur = pdl->pList;
while(pCur != NULL) {
pNext = pCur->pNext;
if(pCur->pParent == pds) {
RemoveDevice(pdl->pGuid, pCur->pszName);
}
pCur = pNext;
}
}
}
// we're done with the device pointer
DeviceStateDecRef(pds);
}
}
}
// This routine looks up a given device and passes back its current power state
// via the pCurDx pointer. It returns the following error codes:
// ERROR_SUCCESS - device found, *pCurDx updated successfully
// ERROR_FILE_NOT_FOUND - device not found
// ERROR_INVALID_PARAMETER - bad device ID, flags, or pCurDx pointer.
EXTERN_C DWORD WINAPI
PmGetDevicePower(PVOID pvDevice, DWORD dwDeviceFlags, PCEDEVICE_POWER_STATE pCurDx)
{
DWORD dwStatus = ERROR_FILE_NOT_FOUND;
PDEVICEID pdi = NULL;
SETFNAME(_T("PmGetDevicePower"));
PMLOGMSG(ZONE_API || ZONE_DEVICE, (_T("+%s: device %s, flags 0x%08x\r\n"),
pszFname, (dwDeviceFlags & POWER_NAME) != 0 ? (LPTSTR) pvDevice : _T("<UNKNOWN>"),
dwDeviceFlags));
// sanity check parameters
if(pvDevice == NULL
|| pCurDx == NULL
|| (pdi = DeviceIdParseNameString((LPCTSTR) pvDevice, dwDeviceFlags)) == NULL) {
dwStatus = ERROR_INVALID_PARAMETER;
} else {
PDEVICE_LIST pdl;
// look for the device list and the device
pdl = GetDeviceListFromClass(pdi->pGuid);
if(pdl != NULL) {
PDEVICE_STATE pds = DeviceStateFindList(pdl, pdi->pszName);
if(pds != NULL) {
CEDEVICE_POWER_STATE curDx = PwrDeviceUnspecified;
// how are we supposed to obtain the data?
if((dwDeviceFlags & POWER_FORCE) == 0) {
// use our cached value
PMLOCK();
curDx = pds->curDx;
PMUNLOCK();
dwStatus = ERROR_SUCCESS;
} else {
// request the device's power status
dwStatus = GetDevicePower(pds, &curDx);
}
// do we have a value to pass back?
if(dwStatus == ERROR_SUCCESS) {
__try {
// yes, update the caller's parameter
*pCurDx = curDx;
}
__except(EXCEPTION_EXECUTE_HANDLER) {
PMLOGMSG(ZONE_WARN, (_T("%s: exception updating pCurDx 0x%08x\r\n"),
pszFname, pCurDx));
dwStatus = ERROR_INVALID_PARAMETER;
}
}
// done with its pointer
DeviceStateDecRef(pds);
}
}
}
// release resources
if(pdi != NULL) DeviceIdDestroy(pdi);
PMLOGMSG(ZONE_API || ZONE_DEVICE || (dwStatus != ERROR_SUCCESS && ZONE_WARN),
(_T("-%s: returning dwStatus %d\r\n"), pszFname, dwStatus));
// return our status
return dwStatus;
}
// This routine looks up a given device and sets its device power state to the
// value in dwState. It returns the following values:
// ERROR_SUCCESS - device found and power state updated
// ERROR_FILE_NOT_FOUND - device not found
// ERROR_WRITE_FAULT - attempt to update the device power failed
// ERROR_INVALID_PARAMETER - bad device ID, flags, or dwState value.
EXTERN_C DWORD WINAPI
PmSetDevicePower(PVOID pvDevice, DWORD dwDeviceFlags, CEDEVICE_POWER_STATE newDx)
{
DWORD dwStatus = ERROR_FILE_NOT_FOUND;
PDEVICEID pdi = NULL;
SETFNAME(_T("PmSetDevicePower"));
PMLOGMSG(ZONE_API || ZONE_DEVICE, (_T("+%s: device %s, flags 0x%08x, new Dx %d\r\n"),
pszFname, (dwDeviceFlags & POWER_NAME) != 0 ? (LPTSTR) pvDevice : _T("<UNKNOWN>"),
dwDeviceFlags, newDx));
PMENTERUPDATE();
// sanity check parameters
if(pvDevice == NULL
|| ((newDx < D0 || newDx > D4) && newDx != PwrDeviceUnspecified)
|| (pdi = DeviceIdParseNameString((LPCTSTR) pvDevice, dwDeviceFlags)) == NULL) {
dwStatus = ERROR_INVALID_PARAMETER;
} else {
PDEVICE_LIST pdl;
BOOL fOk = TRUE;
// look for the device list and the device
pdl = GetDeviceListFromClass(pdi->pGuid);
if(pdl != NULL) {
PDEVICE_STATE pds = DeviceStateFindList(pdl, pdi->pszName);
if(pds != NULL) {
// are we imposing a set value or are we removing a set value?
if(newDx == PwrDeviceUnspecified) {
// remove the set value
PMLOCK();
pds->setDx = PwrDeviceUnspecified;
PMUNLOCK();
// let the device find its own power level
UpdateDeviceState(pds);
// we've removed the set constraint, no matter what UpdateDeviceStatus() did
dwStatus = ERROR_SUCCESS;
} else {
// found the device, now try to update it
PMLOCK();
pds->setDx = newDx;
PMUNLOCK();
fOk = UpdateDeviceState(pds);
if(!fOk) {
PMLOCK();
pds->setDx = PwrDeviceUnspecified;
PMUNLOCK();
dwStatus = ERROR_WRITE_FAULT;
} else {
dwStatus = ERROR_SUCCESS;
}
}
// done with the device pointer
DeviceStateDecRef(pds);
}
}
}
PMLEAVEUPDATE();
// release resources
if(pdi != NULL) DeviceIdDestroy(pdi);
PMLOGMSG(ZONE_API || ZONE_DEVICE || (dwStatus != ERROR_SUCCESS && ZONE_WARN),
(_T("-%s: returning dwStatus %d\r\n"), pszFname, dwStatus));
// return our status
return dwStatus;
}
// This routine is invoked when a device driver wants to have the power manager
// adjust its power state. Power manager will attempt to honor the request
// within the constraints imposed on it by the current system power state,
// application requirements, and user set operations.
EXTERN_C DWORD WINAPI
PmDevicePowerNotify(PVOID pvDevice, CEDEVICE_POWER_STATE reqDx,
DWORD dwDeviceFlags)
{
DWORD dwStatus = ERROR_SUCCESS;
PDEVICEID pdi = NULL;
SETFNAME(_T("PmDevicePowerNotify"));
PMLOGMSG(ZONE_API, (_T("+%s: device '%s' req %d, flags 0x%08x\r\n"), pszFname,
(dwDeviceFlags & POWER_NAME) != 0 ? (LPTSTR) pvDevice : _T("<UNKNOWN>"),
reqDx, dwDeviceFlags));
// sanity check parameters
if(pvDevice == NULL
|| (reqDx < D0 || reqDx > D4)
|| (pdi = DeviceIdParseNameString((LPCTSTR) pvDevice, dwDeviceFlags)) == NULL) {
dwStatus = ERROR_INVALID_PARAMETER;
} else {
PDEVICE_LIST pdl;
BOOL fOk = TRUE;
// look for the device list and the device
pdl = GetDeviceListFromClass(pdi->pGuid);
if(pdl == NULL) {
dwStatus = ERROR_FILE_NOT_FOUND;
} else {
PDEVICE_STATE pds = DeviceStateFindList(pdl, pdi->pszName);
if(pds == NULL) {
dwStatus = ERROR_FILE_NOT_FOUND;
} else {
PMLOCK();
PMLOGMSG(ZONE_DEVICE,
(_T("%s: device '%s' request for D%d, curDx D%d, floorDx D%d, ceilingDx D%d, setDx %d\r\n"),
pszFname, pds->pszName, reqDx, pds->curDx, pds->floorDx, pds->ceilingDx, pds->setDx));
// record this state change request
pds->lastReqDx = reqDx;
PMUNLOCK();
// change the device power state if necessary
fOk = UpdateDeviceState(pds);
if(!fOk) {
PMLOGMSG(ZONE_WARN,
(_T("%s: SetDevicePower('%s') failed when requesting D%d\r\n"),
pszFname, pds->pszName, reqDx));
dwStatus = ERROR_WRITE_FAULT;
}
// done with the device state pointer
DeviceStateDecRef(pds);
}
}
}
// release resources
if(pdi != NULL) DeviceIdDestroy(pdi);
PMLOGMSG((dwStatus != ERROR_SUCCESS && ZONE_WARN) || ZONE_API,
(_T("%s: returning %d\r\n"), pszFname, dwStatus));
return dwStatus;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -