|
|
/*
* title: HidBattIOCT.cpp * * purpose: Contains misc ioctl handlers for status and query info mainly * * Initial checkin for the hid to battery class driver. This should be * the same for both Win 98 and NT 5. Alpha level source. Requires * modified composite battery driver and modified battery class driver for * Windows 98 support * */
#include "hidbatt.h"
/*++
Routine Description:
IOCTL handler. As this is an exclusive battery device, send the Irp to the battery class driver to handle battery IOCTLs.
Arguments:
DeviceObject - Battery for request Irp - IO request
Return Value:
Status of request
--*/ NTSTATUS HidBattIoControl( IN PDEVICE_OBJECT pDeviceObject, IN PIRP pIrp ) { NTSTATUS ntStatus = STATUS_NOT_SUPPORTED; CBatteryDevExt * pDevExt; PIO_STACK_LOCATION irpSp; HIDDebugBreak(HIDBATT_BREAK_ALWAYS);
irpSp = IoGetCurrentIrpStackLocation(pIrp); HidBattPrint (HIDBATT_TRACE, ("HidBattIoctl = %x\n", irpSp->Parameters.DeviceIoControl.IoControlCode));
// PrintIoctl(irpSp->Parameters.DeviceIoControl.IoControlCode);
pDevExt = (CBatteryDevExt *) pDeviceObject->DeviceExtension;
if (NT_SUCCESS(IoAcquireRemoveLock (&pDevExt->m_StopLock, (PVOID) HidBattTag))) { if (pDevExt->m_pBattery && pDevExt->m_pBattery->m_pBatteryClass) { ntStatus = BatteryClassIoctl (pDevExt->m_pBattery->m_pBatteryClass, pIrp); } IoReleaseRemoveLock (&pDevExt->m_StopLock, (PVOID) HidBattTag); } else { ntStatus = STATUS_DEVICE_REMOVED; pIrp->IoStatus.Status = ntStatus; IoCompleteRequest(pIrp,IO_NO_INCREMENT); }
if (ntStatus == STATUS_NOT_SUPPORTED) { HidBattCallLowerDriver(ntStatus, pDevExt->m_pLowerDeviceObject, pIrp); }
return ntStatus; }
VOID HidBattNotifyHandler ( IN PVOID pContext, IN CUsage * pUsage ) { HIDDebugBreak(HIDBATT_BREAK_ALWAYS); NTSTATUS ntStatus; ULONG ulCapacityLimit = BATTERY_UNKNOWN_CAPACITY; BOOL bResult;
HidBattPrint (HIDBATT_TRACE, ("HidBattNotifyHandler\n")); // called by input routine whenever a value change is noted to
// a notificable usage
CBatteryDevExt * pDevExt = (CBatteryDevExt *) pContext;
HidBattPrint (HIDBATT_DATA, ("HidBattNotifyHandler: Usage: %x\n", pUsage->m_pProperties->m_Usage)); switch (pUsage->m_pProperties->m_Usage) { case REMAINING_CAPACITY_ID:
bResult = pDevExt->m_pBattery->GetSetValue(REMAINING_CAPACITY_LIMIT_INDEX,&ulCapacityLimit,FALSE); // Only send notification when capacity drops below notify level.
if ((bResult) && (ulCapacityLimit != BATTERY_UNKNOWN_CAPACITY) && (pUsage->m_Value != BATTERY_UNKNOWN_CAPACITY) && (pUsage->m_Value > ulCapacityLimit)) { HidBattPrint (HIDBATT_TRACE, ("HidBattNotifyHandler:Suppressing notify\n")); break; }
case AC_PRESENT_ID: // check for battery off/on line
case DISCHARGING_ID: case CHARGING_ID: case BELOW_REMAINING_CAPACITY_ID: case SHUTDOWN_IMMINENT_ID: { pDevExt->m_pBattery->m_bIsCacheValid=FALSE;
if (NT_SUCCESS (IoAcquireRemoveLock (&pDevExt->m_StopLock, (PVOID) HidBattTag))) { ntStatus = BatteryClassStatusNotify( pDevExt->m_pBattery->m_pBatteryClass); IoReleaseRemoveLock (&pDevExt->m_StopLock, (PVOID) HidBattTag); } break; } default: // nothing to notify
break; }
return; }
NTSTATUS HidBattQueryTag ( IN PVOID pContext, OUT PULONG pulBatteryTag ) {
HIDDebugBreak(HIDBATT_BREAK_ALWAYS); CBatteryDevExt * pDevExt = (CBatteryDevExt *) pContext;
if (!NT_SUCCESS(IoAcquireRemoveLock (&pDevExt->m_StopLock, (PVOID) HidBattTag)) ) { return STATUS_NO_SUCH_DEVICE; }
*pulBatteryTag = pDevExt->m_pBattery->m_Tag;
IoReleaseRemoveLock (&pDevExt->m_StopLock, (PVOID) HidBattTag); return STATUS_SUCCESS; }
NTSTATUS HidBattSetStatusNotify ( IN PVOID pContext, IN ULONG BatteryTag, IN PBATTERY_NOTIFY pBatteryNotify ) { bool bResult; ULONG CentiAmpSec; ULONG ulValue; HIDDebugBreak(HIDBATT_BREAK_ALWAYS); HidBattPrint (HIDBATT_TRACE, ("HidBattSetStatusNotify \n")); CBatteryDevExt * pDevExt = (CBatteryDevExt *) pContext; CBattery * pBattery = pDevExt->m_pBattery;
HidBattPrint (HIDBATT_DEBUG, ("HidBattSetStatusNotify->PowerState = %x\n", pBatteryNotify->PowerState)); HidBattPrint (HIDBATT_DEBUG, ("HidBattSetStatusNotify->LowCapacity = %x\n", pBatteryNotify->LowCapacity)); HidBattPrint (HIDBATT_DEBUG, ("HidBattSetStatusNotify->HighCapacity = %x\n", pBatteryNotify->HighCapacity));
if (!NT_SUCCESS(IoAcquireRemoveLock (&pDevExt->m_StopLock, (PVOID) HidBattTag))) { return STATUS_NO_SUCH_DEVICE; }
if (pBattery->m_Tag != BatteryTag) { IoReleaseRemoveLock (&pDevExt->m_StopLock, (PVOID) HidBattTag); return STATUS_NO_SUCH_DEVICE; }
if ((pBatteryNotify->HighCapacity == BATTERY_UNKNOWN_CAPACITY) || (pBatteryNotify->LowCapacity == BATTERY_UNKNOWN_CAPACITY)) { HidBattPrint (HIDBATT_DEBUG, ("HidBattSetStatusNotify failing because of BATTERY_UNKNOWN_CAPACITY.\n")); IoReleaseRemoveLock (&pDevExt->m_StopLock, (PVOID) HidBattTag); return STATUS_NOT_SUPPORTED; }
// first check for relative or absolute
if(pBattery->m_bRelative) { ulValue = pBatteryNotify->LowCapacity; // done
} else { // first check if setting to zero so that can skip below formula
if(pBatteryNotify->LowCapacity == 0) { ulValue = 0; } else { // first must covert value to whatever is being used by this HID device.
// currently we assume either MilliVolts consistant with battery class or
// AmpSecs consistant with power spec
ULONG ulUnit = pBattery->GetUnit(REMAINING_CAPACITY_INDEX); if(ulUnit) { short sExponent; ULONG lMilliVolts; long milliWattHours,CentiWattHours,CentiWattSecs;
sExponent = pBattery->GetExponent(REMAINING_CAPACITY_INDEX);
// conversion from millWattHours to AmpSecs
// formula = mWHs / 1000 / 3600 / volts ^ exponent correction
lMilliVolts = pBattery->m_BatteryStatus.Voltage; // stored as MilliVolts
if (lMilliVolts == 0) { HidBattPrint (HIDBATT_ERROR, ("HidBattSetStatusNotify: Error: voltage = 0, fudging with 24V.\n")); lMilliVolts = 24000; } milliWattHours = pBatteryNotify->LowCapacity; CentiWattHours = milliWattHours /10; CentiWattSecs = CentiWattHours / 3600; CentiAmpSec = (CentiWattSecs *1000)/ lMilliVolts; ulValue = CorrectExponent(CentiAmpSec,-2,sExponent); } else { ulValue = pBatteryNotify->LowCapacity; } } // end if LowCapacity
} // end if relative
// now set low
bResult = pBattery->GetSetValue(REMAINING_CAPACITY_LIMIT_INDEX,&ulValue,TRUE);
IoReleaseRemoveLock (&pDevExt->m_StopLock, (PVOID) HidBattTag);
return bResult ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL; }
NTSTATUS HidBattDisableStatusNotify ( IN PVOID pContext ) { HIDDebugBreak(HIDBATT_BREAK_ALWAYS); CBatteryDevExt * pDevExt = (CBatteryDevExt *) pContext; pDevExt->m_pBattery->m_pBatteryNotify = NULL; // remove notify procedure
return STATUS_SUCCESS; }
/*++
Routine Description:
Called by the class driver to retrieve the batteries current status
The battery class driver will serialize all requests it issues to the miniport for a given battery.
Arguments:
Context - Miniport context value for battery BatteryTag - Tag of current battery BatteryStatus - Pointer to structure to return the current battery status
Return Value:
Success if there is a battery currently installed, else no such device.
--*/
NTSTATUS HidBattQueryStatus ( IN PVOID pContext, IN ULONG BatteryTag, OUT PBATTERY_STATUS pBatteryStatus ) { HIDDebugBreak(HIDBATT_BREAK_ALWAYS); CBatteryDevExt * pDevExt = (CBatteryDevExt *) pContext; NTSTATUS ntStatus;
HidBattPrint (HIDBATT_TRACE, ("HidBattQueryStatus - Tag (%d)\n", BatteryTag));
if (!NT_SUCCESS(IoAcquireRemoveLock (&pDevExt->m_StopLock, (PVOID) HidBattTag)) ) { return STATUS_NO_SUCH_DEVICE; }
if ((BatteryTag == BATTERY_TAG_INVALID) || (pDevExt->m_pBattery->m_Tag == BATTERY_TAG_INVALID)) { ntStatus = STATUS_NO_SUCH_DEVICE; } else {
RtlZeroMemory (pBatteryStatus, sizeof(BATTERY_STATUS)); ntStatus = pDevExt->m_pBattery->RefreshStatus(); if (NT_SUCCESS(ntStatus)) { RtlCopyMemory (pBatteryStatus, &pDevExt->m_pBattery->m_BatteryStatus, sizeof(BATTERY_STATUS)); HidBattPrint (HIDBATT_DATA, ("HidBattQueryStatus - Data (%08x)(%08x)(%08x)(%08x)\n", pBatteryStatus->PowerState, pBatteryStatus->Capacity, pBatteryStatus->Rate, pBatteryStatus->Voltage ));
} else { ntStatus = STATUS_NO_SUCH_DEVICE; HidBattPrint (HIDBATT_DATA, ("HidBattQueryStatus - Error\n" )); } }
IoReleaseRemoveLock (&pDevExt->m_StopLock, (PVOID) HidBattTag);
return ntStatus;
}
/*++
Routine Description:
Called by the class driver to retrieve battery information
The battery class driver will serialize all requests it issues to the miniport for a given battery.
We return invalid parameter when we can't handle a request for a specific level of information. This is defined in the battery class spec.
Arguments:
Context - Miniport context value for battery BatteryTag - Tag of current battery Level - type of information required AtRate - Optional Parameter Buffer - Location for the information BufferLength - Length in bytes of the buffer ReturnedLength - Length in bytes of the returned data
Return Value:
Success if there is a battery currently installed, else no such device.
--*/
NTSTATUS HidBattQueryInformation ( IN PVOID Context, IN ULONG BatteryTag, IN BATTERY_QUERY_INFORMATION_LEVEL Level, IN LONG AtRate OPTIONAL, OUT PVOID Buffer, IN ULONG BufferLength, OUT PULONG ReturnedLength ) {
CBatteryDevExt * pDevExt = (CBatteryDevExt *) Context; ULONG ulResult; NTSTATUS ntStatus; PVOID pReturnBuffer; ULONG ulReturnBufferLength; WCHAR scratchBuffer[MAX_BATTERY_STRING_SIZE]; WCHAR buffer2[MAX_BATTERY_STRING_SIZE]; UNICODE_STRING tmpUnicodeString; UNICODE_STRING unicodeString; ANSI_STRING ansiString; bool bResult; BATTERY_REMAINING_SCALE ScalePtr[2]; ULONG ulReturn,ulNewValue; ULONG ulEstTimeStub = 5;
HIDDebugBreak(HIDBATT_BREAK_ALWAYS);
HidBattPrint (HIDBATT_TRACE, ("HidBattQueryInformation - Tag (%d)\n", BatteryTag));
if (!NT_SUCCESS(IoAcquireRemoveLock (&pDevExt->m_StopLock, (PVOID) HidBattTag)) ) { return STATUS_NO_SUCH_DEVICE; }
//
// If caller has the wrong ID give an error
//
if (BatteryTag == BATTERY_TAG_INVALID || pDevExt->m_pBattery->m_Tag == BATTERY_TAG_INVALID || BatteryTag != pDevExt->m_pBattery->m_Tag) { IoReleaseRemoveLock (&pDevExt->m_StopLock, (PVOID) HidBattTag); return STATUS_NO_SUCH_DEVICE; }
ulResult = 0; pReturnBuffer = NULL; ulReturnBufferLength = 0; ntStatus = STATUS_SUCCESS; CUString cUniqueID; SHORT sExponent; char * pTemp; //
// Get the info requested
//
switch (Level) { case BatteryInformation: //
// This data structure is populated by CmBattVerifyStaticInfo
//
HidBattPrint (HIDBATT_TRACE, ("HidBattQueryInformation - Battery Info\n")); pReturnBuffer = (PVOID) &pDevExt->m_pBattery->m_BatteryInfo; ulReturnBufferLength = sizeof (pDevExt->m_pBattery->m_BatteryInfo); break;
case BatteryGranularityInformation: //
// Get the granularity from the static info structure
// This data structure is populated by CmBattVerifyStaticInfo
//
{ HidBattPrint (HIDBATT_TRACE, ("HidBattQueryInformation - Granularity\n")); bResult = pDevExt->m_pBattery->GetSetValue(GRANULARITY1_INDEX, &ulReturn,FALSE); if(!pDevExt->m_pBattery->m_bRelative) { // convert from amps to watts
sExponent = pDevExt->m_pBattery->GetExponent(GRANULARITY1_INDEX); ulNewValue = CorrectExponent(ulReturn,sExponent,-2); ulReturn= CentiAmpSecsToMilliWattHours(ulNewValue,pDevExt->m_pBattery->m_BatteryStatus.Voltage); }
ScalePtr[0].Granularity = bResult ? ulReturn : 0; bResult = pDevExt->m_pBattery->GetSetValue(GRANULARITY2_INDEX, &ulReturn,FALSE); if(!pDevExt->m_pBattery->m_bRelative) { // convert from amps to watts
sExponent = pDevExt->m_pBattery->GetExponent(GRANULARITY2_INDEX); ulNewValue = CorrectExponent(ulReturn,sExponent,-2); ulReturn= CentiAmpSecsToMilliWattHours(ulNewValue,pDevExt->m_pBattery->m_BatteryStatus.Voltage); } ScalePtr[1].Granularity = bResult ? ulReturn : 0; bResult = pDevExt->m_pBattery->GetSetValue(WARNING_CAPACITY_LIMIT_INDEX, &ulReturn,FALSE); if(!pDevExt->m_pBattery->m_bRelative) { // convert from amps to watts
sExponent = pDevExt->m_pBattery->GetExponent(WARNING_CAPACITY_LIMIT_INDEX); ulNewValue = CorrectExponent(ulReturn,sExponent,-2); ulReturn= CentiAmpSecsToMilliWattHours(ulNewValue,pDevExt->m_pBattery->m_BatteryStatus.Voltage); } ScalePtr[0].Capacity = bResult ? ulReturn : 0; bResult = pDevExt->m_pBattery->GetSetValue(DESIGN_CAPACITY_INDEX, &ulReturn,FALSE); if(!pDevExt->m_pBattery->m_bRelative) { // convert from amps to watts
sExponent = pDevExt->m_pBattery->GetExponent(DESIGN_CAPACITY_INDEX); ulNewValue = CorrectExponent(ulReturn,sExponent,-2); ulReturn= CentiAmpSecsToMilliWattHours(ulNewValue,pDevExt->m_pBattery->m_BatteryStatus.Voltage); } ScalePtr[1].Capacity = bResult ? ulReturn : 0;
pReturnBuffer = ScalePtr; ulReturnBufferLength = 2 * sizeof (BATTERY_REMAINING_SCALE); } break;
case BatteryTemperature: HidBattPrint (HIDBATT_TRACE, ("HidBattQueryInformation - Temperature\n")); ntStatus = STATUS_INVALID_DEVICE_REQUEST; break;
case BatteryEstimatedTime: HidBattPrint (HIDBATT_TRACE, ("HidBattQueryInformation - Estimated time\n")); bResult = pDevExt->m_pBattery->GetSetValue(RUNTIME_TO_EMPTY_INDEX, &ulReturn,FALSE);
if(!bResult) { ntStatus = STATUS_INVALID_DEVICE_REQUEST; } else { SHORT exponent;
exponent = pDevExt->m_pBattery->GetExponent(RUNTIME_TO_EMPTY_INDEX); ulReturn = CorrectExponent (ulReturn, exponent, 0);
pReturnBuffer = &ulReturn; ulReturnBufferLength = sizeof (ULONG); } break;
case BatteryDeviceName: //
// Model Number must be returned as a wide string
//
HidBattPrint (HIDBATT_TRACE, ("HidBattQueryInformation - Device Name\n")); if(pDevExt->m_pBattery->m_pProduct) { pReturnBuffer = pDevExt->m_pBattery->m_pProduct->m_String.Buffer; ulReturnBufferLength = pDevExt->m_pBattery->m_pProduct->m_String.Length; } break;
case BatteryManufactureDate: HidBattPrint (HIDBATT_TRACE, ("HidBattQueryInformation - Mfr Date\n")); if(!pDevExt->m_pBattery->m_ManufactureDate.Day) { ntStatus = STATUS_INVALID_DEVICE_REQUEST; break; } pReturnBuffer = &pDevExt->m_pBattery->m_ManufactureDate; ulReturnBufferLength = sizeof(pDevExt->m_pBattery->m_ManufactureDate); break;
case BatteryManufactureName: //
// Oem Info must be returned as wide string
//
HidBattPrint (HIDBATT_TRACE, ("HidBattQueryInformation - Mfr Name\n")); if(pDevExt->m_pBattery->m_pManufacturer) { pReturnBuffer = pDevExt->m_pBattery->m_pManufacturer->m_String.Buffer; ulReturnBufferLength = pDevExt->m_pBattery->m_pManufacturer->m_String.Length; }
break;
case BatteryUniqueID: //
// Concatenate the serial #, manufacturer name, and Product //
// start off with serial number
HidBattPrint (HIDBATT_TRACE, ("HidBattQueryInformation - Unique ID\n")); if(pDevExt->m_pBattery->m_pSerialNumber) { HidBattPrint (HIDBATT_TRACE, ("HidBattQueryInformation - Serial = %s\n", pDevExt->m_pBattery->m_pSerialNumber));
cUniqueID.Append(pDevExt->m_pBattery->m_pSerialNumber); } else { HidBattPrint (HIDBATT_TRACE, ("HidBattQueryInformation - Serial = NULL\n")); CUString * pSTemp = new (NonPagedPool, HidBattTag) CUString(L"1000"); if (pSTemp) { cUniqueID.Append(pSTemp); delete pSTemp; } } if(pDevExt->m_pBattery->m_pManufacturer) cUniqueID.Append(pDevExt->m_pBattery->m_pManufacturer); // add mfr name
else { CUString * pSTemp = new (NonPagedPool, HidBattTag) CUString(L"Mfr"); if (pSTemp) { cUniqueID.Append(pSTemp); delete pSTemp; } } if(pDevExt->m_pBattery->m_pProduct) cUniqueID.Append(pDevExt->m_pBattery->m_pProduct); // add Product
else { CUString * pSTemp = new (NonPagedPool, HidBattTag) CUString(L"Prod"); if (pSTemp) { cUniqueID.Append(pSTemp); delete pSTemp; } } pReturnBuffer = cUniqueID.m_String.Buffer; ulReturnBufferLength = cUniqueID.m_String.Length; break; default: HidBattPrint (HIDBATT_TRACE, ("HidBattQueryInformation - Default\n")); ntStatus = STATUS_INVALID_PARAMETER; break; }
//
// Done, return buffer if needed
//
*ReturnedLength = ulReturnBufferLength; if (BufferLength < ulReturnBufferLength) { ntStatus = STATUS_BUFFER_TOO_SMALL; }
if (NT_SUCCESS(ntStatus) && pReturnBuffer) { RtlCopyMemory (Buffer, pReturnBuffer, ulReturnBufferLength); // Copy what's needed
}
HidBattPrint (HIDBATT_TRACE, ("HidBattQueryInformation - Status = %08x Buffer = %08x\n", ntStatus, *(PULONG)Buffer));
IoReleaseRemoveLock (&pDevExt->m_StopLock, (PVOID) HidBattTag);
return ntStatus; }
NTSTATUS HidBattIoCompletion( IN PDEVICE_OBJECT pDeviceObject, IN PIRP pIrp, IN PVOID pdoIoCompletedEvent ) { HidBattPrint (HIDBATT_TRACE, ("HidBattIoCompletion\n")); KeSetEvent((KEVENT *) pdoIoCompletedEvent,0, FALSE); return STATUS_MORE_PROCESSING_REQUIRED;
}
|