📄 smbbatt.c
字号:
status = SmbBattResetSelectorComm (SmbBatt, oldSelectorState);
if (!NT_SUCCESS (status)) {
BattPrint(BAT_ERROR, ("SmbBattQueryTag: can't reset selector communications path\n"));
}
} else {
//
// Ignore the return value from ResetSelectorComm because we already
// have an error here.
//
SmbBattResetSelectorComm (SmbBatt, oldSelectorState);
}
SmbBattUnlockDevice (SmbBatt);
SmbBattUnlockSelector (SmbBatt->Selector);
BattPrint(BAT_TRACE, ("SmbBattQueryTag: EXITING\n"));
return status;
}
NTSTATUS
SmbBattQueryInformation (
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
)
{
PSMB_BATT SmbBatt;
ULONG ResultData;
BOOLEAN IoCheck;
NTSTATUS status, st;
PVOID ReturnBuffer;
ULONG ReturnBufferLength;
WCHAR scratchBuffer[SMB_MAX_DATA_SIZE+1]; // +1 for UNICODE_NULL
UNICODE_STRING unicodeString;
UNICODE_STRING tmpUnicodeString;
ANSI_STRING ansiString;
ULONG oldSelectorState;
BATTERY_REPORTING_SCALE granularity;
PAGED_CODE();
BattPrint(BAT_TRACE, ("SmbBattQueryInformation: ENTERING\n"));
if (BatteryTag == BATTERY_TAG_INVALID) {
return STATUS_NO_SUCH_DEVICE;
}
//
// Get device lock and make sure the selector is set up to talk to us.
// Since multiple people may be doing this, always lock the selector
// first followed by the battery.
//
SmbBatt = (PSMB_BATT) Context;
SmbBattLockSelector (SmbBatt->Selector);
SmbBattLockDevice (SmbBatt);
status = SmbBattSetSelectorComm (SmbBatt, &oldSelectorState);
if (!NT_SUCCESS (status)) {
BattPrint(BAT_ERROR, ("SmbBattQueryInformation: can't set selector communications path\n"));
} else {
do {
ResultData = 0;
ReturnBuffer = NULL;
ReturnBufferLength = 0;
status = STATUS_SUCCESS;
//
// If no device, or caller has the wrong ID give an error
//
if (BatteryTag != SmbBatt->Info.Tag) {
status = STATUS_NO_SUCH_DEVICE;
break;
}
//
// Get the info requested
//
switch (Level) {
case BatteryInformation:
ReturnBuffer = &SmbBatt->Info.Info;
ReturnBufferLength = sizeof (SmbBatt->Info.Info);
break;
case BatteryGranularityInformation:
SmbBattRW(SmbBatt, BAT_FULL_CHARGE_CAPACITY, &granularity.Capacity);
granularity.Capacity *= SmbBatt->Info.PowerScale;
granularity.Granularity = SmbBatt->Info.PowerScale;
ReturnBuffer = &granularity;
ReturnBufferLength = sizeof (granularity);
break;
case BatteryTemperature:
SmbBattRW(SmbBatt, BAT_TEMPERATURE, &ResultData);
ReturnBuffer = &ResultData;
ReturnBufferLength = sizeof(ULONG);
break;
case BatteryEstimatedTime:
//
// If an AtRate has been specified, then we will use the AtRate
// functions to get this information (AtRateTimeToEmpty()).
// Otherwise, we will return the AVERAGE_TIME_TO_EMPTY.
//
BattPrint(BAT_DATA, ("SmbBattQueryInformation: EstimatedTime: AtRate: %08x\n", AtRate));
if (AtRate != 0) {
//
// Currently we only support the time to empty functions.
//
ASSERT (AtRate < 0);
//
// The smart battery input value for AtRate is in 10mW increments
//
AtRate /= (LONG)SmbBatt->Info.PowerScale;
BattPrint(BAT_DATA, ("SmbBattQueryInformation: EstimatedTime: AtRate scaled to: %08x\n", AtRate));
SmbBattWW(SmbBatt, BAT_AT_RATE, AtRate);
SmbBattRW(SmbBatt, BAT_RATE_TIME_TO_EMPTY, &ResultData);
BattPrint(BAT_DATA, ("SmbBattQueryInformation: EstimatedTime: AT_RATE_TIME_TO_EMPTY: %08x\n", ResultData));
} else {
SmbBattRW(SmbBatt, BAT_AVERAGE_TIME_TO_EMPTY, &ResultData);
BattPrint(BAT_DATA, ("SmbBattQueryInformation: EstimatedTime: AVERAGE_TIME_TO_EMPTY: %08x\n", ResultData));
}
if (ResultData == 0xffff) {
ResultData = BATTERY_UNKNOWN_TIME;
} else {
ResultData *= 60;
}
BattPrint(BAT_DATA, ("SmbBattQueryInformation: (%01x) EstimatedTime: %08x seconds\n", SmbBatt->SelectorBitPosition, ResultData));
ReturnBuffer = &ResultData;
ReturnBufferLength = sizeof(ULONG);
break;
case BatteryDeviceName:
//
// This has to be returned as a WCHAR string but is kept internally
// as a character string. Have to convert it.
//
unicodeString.Buffer = Buffer;
unicodeString.MaximumLength = BufferLength > (USHORT)-1 ? (USHORT) -1 : (USHORT)BufferLength;
ansiString.Length = SmbBatt->Info.DeviceNameLength;
ansiString.MaximumLength = sizeof(SmbBatt->Info.DeviceName);
ansiString.Buffer = SmbBatt->Info.DeviceName;
status = RtlAnsiStringToUnicodeString (&unicodeString, &ansiString, FALSE);
if (NT_SUCCESS(status)) {
ReturnBuffer = Buffer;
ReturnBufferLength = unicodeString.Length;
}
break;
case BatteryManufactureDate:
ReturnBuffer = &SmbBatt->Info.ManufacturerDate;
ReturnBufferLength = sizeof (SmbBatt->Info.ManufacturerDate);
break;
case BatteryManufactureName:
//
// This has to be returned as a WCHAR string but is kept internally
// as a character string. Have to convert it.
//
unicodeString.Buffer = Buffer;
unicodeString.MaximumLength = BufferLength > (USHORT)-1 ? (USHORT) -1 : (USHORT)BufferLength;
ansiString.Length = SmbBatt->Info.ManufacturerNameLength;
ansiString.MaximumLength = sizeof(SmbBatt->Info.ManufacturerName);
ansiString.Buffer = SmbBatt->Info.ManufacturerName;
status = RtlAnsiStringToUnicodeString (&unicodeString, &ansiString, FALSE);
if (NT_SUCCESS(status)) {
ReturnBuffer = Buffer;
ReturnBufferLength = unicodeString.Length;
}
break;
case BatteryUniqueID:
//
// The unique ID is a character string consisting of the serial
// number, the manufacturer name, and the device name.
//
unicodeString.Buffer = Buffer;
unicodeString.MaximumLength = BufferLength > (USHORT)-1 ? (USHORT) -1 : (USHORT)BufferLength;
tmpUnicodeString.Buffer = scratchBuffer;
tmpUnicodeString.MaximumLength = sizeof (scratchBuffer);
RtlIntegerToUnicodeString(SmbBatt->Info.SerialNumber, 10, &unicodeString);
ansiString.Length = SmbBatt->Info.ManufacturerNameLength;
ansiString.MaximumLength = sizeof(SmbBatt->Info.ManufacturerName);
ansiString.Buffer = SmbBatt->Info.ManufacturerName;
status = RtlAnsiStringToUnicodeString (&tmpUnicodeString, &ansiString, FALSE);
if (!NT_SUCCESS(status)) break;
status = RtlAppendUnicodeStringToString (&unicodeString, &tmpUnicodeString);
if (!NT_SUCCESS(status)) break;
ansiString.Length = SmbBatt->Info.DeviceNameLength;
ansiString.MaximumLength = sizeof(SmbBatt->Info.DeviceName);
ansiString.Buffer = SmbBatt->Info.DeviceName;
status = RtlAnsiStringToUnicodeString (&tmpUnicodeString, &ansiString, FALSE);
if (!NT_SUCCESS(status)) break;
status = RtlAppendUnicodeStringToString (&unicodeString, &tmpUnicodeString);
if (!NT_SUCCESS(status)) break;
ReturnBuffer = Buffer;
ReturnBufferLength = unicodeString.Length;
break;
case BatterySerialNumber:
//
// This has to be returned as a WCHAR string but is kept internally
// as a character string. Have to convert it.
//
unicodeString.Buffer = Buffer;
unicodeString.MaximumLength = BufferLength > (USHORT)-1 ? (USHORT) -1 : (USHORT)BufferLength;
status = RtlIntegerToUnicodeString(SmbBatt->Info.SerialNumber, 10, &unicodeString);
if (NT_SUCCESS(status)) {
ReturnBuffer = Buffer;
ReturnBufferLength = unicodeString.Length;
}
break;
default:
status = STATUS_INVALID_DEVICE_REQUEST;
break;
}
//
// Re-verify static info in case there's been an IO error
//
//IoCheck = SmbBattVerifyStaticInfo (SmbBatt, BatteryTag);
IoCheck = FALSE;
} while (IoCheck);
}
if (NT_SUCCESS (status)) {
//
// Done, return buffer if needed
//
*ReturnedLength = ReturnBufferLength;
if (ReturnBuffer != Buffer) {
// ReturnBuffer == Buffer indicates that data is already copied.
//
if (BufferLength < ReturnBufferLength) {
status = STATUS_BUFFER_TOO_SMALL;
}
if (NT_SUCCESS(status) && ReturnBuffer) {
memcpy (Buffer, ReturnBuffer, ReturnBufferLength);
}
}
//
// Unlock the device and reset the selector state
//
st = SmbBattResetSelectorComm (SmbBatt, oldSelectorState);
if (!NT_SUCCESS (st)) {
BattPrint(BAT_ERROR, ("SmbBattQueryInformation: can't reset selector communications path\n"));
status = st;
}
} else {
*ReturnedLength = 0;
//
// Ignore the return value from ResetSelectorComm because we already
// have an error here.
//
SmbBattResetSelectorComm (SmbBatt, oldSelectorState);
}
SmbBattUnlockDevice (SmbBatt);
SmbBattUnlockSelector (SmbBatt->Selector);
BattPrint(BAT_TRACE, ("SmbBattQueryInformation: EXITING\n"));
return status;
}
NTSTATUS
SmbBattSetInformation (
IN PVOID Context,
IN ULONG BatteryTag,
IN BATTERY_SET_INFORMATION_LEVEL Level,
IN PVOID Buffer OPTIONAL
)
/*++
Routine Description:
Called by the class driver to set the battery's charge/discharge state.
The smart battery does not support the critical bias function of this
call.
Arguments:
Context - Miniport context value for battery
BatteryTag - Tag of current battery
Level - Action being asked for
Return Value:
NTSTATUS
--*/
{
PSMB_BATT SmbBatt;
ULONG newSelectorState;
ULONG selectorState;
UCHAR smbStatus;
ULONG tmp;
NTSTATUS status = STATUS_NOT_SUPPORTED;
PAGED_CODE();
BattPrint(BAT_TRACE, ("SmbBattSetInformation: ENTERING\n"));
SmbBatt = (PSMB_BATT) Context;
//
// See if this is for our battery
//
if ((BatteryTag == BATTERY_TAG_INVALID) || (BatteryTag != SmbBatt->Info.Tag)) {
return STATUS_NO_SUCH_DEVICE;
}
//
// We can only do this if there is a selector in the system
//
if ((SmbBatt->SelectorPresent) && (SmbBatt->Selector)) {
//
// Get a lock on the selector
//
SmbBattLockSelector (SmbBatt->Selector);
switch (Level) {
case BatteryCharge:
BattPrint(BAT_IRPS, ("SmbBattSetInformation: Got SetInformation for BatteryCharge\n"));
//
// Set the appropriate bit in the selector state charge nibble
//
newSelectorState = SELECTOR_SET_CHARGE_MASK;
newSelectorState |= (SmbBatt->SelectorBitPosition << SELECTOR_SHIFT_CHARGE);
//
// Write the new selector state, then read it back. The system
// may or may not let us do this.
//
smbStatus = SmbBattGenericWW (
SmbBatt->SmbHcFdo,
SmbBatt->Selector->SelectorAddress,
SmbBatt->Selector->SelectorStateCommand,
newSelectorState
);
if (smbStatus != SMB_STATUS_OK) {
BattPrint(BAT_ERROR,
("SmbBattSetInformation: couldn't write selector state - %x\n",
smbStatus)
);
status = STATUS_UNSUCCESSFUL;
break;
}
smbStatus = SmbBattGenericRW (
SmbBatt->SmbHcFdo,
SmbBatt->Selector->SelectorAddress,
SmbBatt->Selector->SelectorStateCommand,
&selectorState
);
if ((smbStatus != SMB_STATUS_OK)) {
BattPrint(BAT_ERROR,
("SmbBattSetInformation: couldn't read selector state - %x\n",
smbStatus)
);
status = STATUS_UNSUCCESSFUL;
break;
}
//
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -