📄 pnppower.c
字号:
BattPrint(BAT_TRACE, ("SmbBattRemoveDevice: EXITING\n"));
return status;
}
NTSTATUS
SmbBattQueryId(
IN PDEVICE_OBJECT Pdo,
IN PIRP Irp
)
/*++
Routine Description:
This routine handles the IRP_MN_QUERY_ID for the newly created battery PDOs.
Arguments:
Pdo - Battery PDO
Irp - The query Irp
Return Value:
NTSTATUS
--*/
{
UNICODE_STRING unicodeString;
WCHAR unicodeBuffer[MAX_DEVICE_NAME_LENGTH];
UNICODE_STRING numberString;
WCHAR numberBuffer[10];
PSMB_BATT_PDO pdoExt = (PSMB_BATT_PDO) Pdo->DeviceExtension;
NTSTATUS status = STATUS_SUCCESS;
PWCHAR idString = NULL;
PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp);
PAGED_CODE();
BattPrint(BAT_TRACE, ("SmbBattQueryId: ENTERING\n"));
RtlZeroMemory (unicodeBuffer, MAX_DEVICE_NAME_LENGTH);
unicodeString.MaximumLength = MAX_DEVICE_NAME_LENGTH;
unicodeString.Length = 0;
unicodeString.Buffer = unicodeBuffer;
switch (irpStack->Parameters.QueryId.IdType) {
case BusQueryDeviceID:
//
// This string has to have the form BUS\DEVICE.
//
// Use SMB as bus and SBS as device
//
RtlAppendUnicodeToString (&unicodeString, SubSystemIdentifier);
break;
case BusQueryInstanceID:
//
// Return the string "Batteryxx" where xx is the battery number
//
numberString.MaximumLength = 10;
numberString.Buffer = &numberBuffer[0];
RtlIntegerToUnicodeString (pdoExt->BatteryNumber, 10, &numberString);
RtlAppendUnicodeToString (&unicodeString, BatteryInstance);
RtlAppendUnicodeToString (&unicodeString, &numberString.Buffer[0]);
break;
case BusQueryHardwareIDs:
//
// This is the Pnp ID for the smart battery subsystem "ACPI0002".
// Make new hardware ID SMB\SBS, SmartBattery as a MULTIZ string
// so we have to add a NULL string to terminate.
//
RtlAppendUnicodeToString (&unicodeString, HidSmartBattery);
unicodeString.Length += sizeof (WCHAR);
break;
default:
//
// Unknown Query Type
//
status = STATUS_NOT_SUPPORTED;
}
if (status != STATUS_NOT_SUPPORTED) {
//
// If we created a string, allocate a buffer for it and copy it into the buffer.
// We need to make sure that we also copy the NULL terminator.
//
if (unicodeString.Length) {
idString = ExAllocatePoolWithTag (PagedPool, unicodeString.Length + sizeof (WCHAR), 'StaB');
if (!idString) {
BattPrint (BAT_ERROR, ("SmbBattQueryId: couldn't allocate id string buffer\n"));
return STATUS_INSUFFICIENT_RESOURCES;
}
RtlZeroMemory (idString, unicodeString.Length + sizeof (WCHAR));
RtlCopyMemory (idString, unicodeString.Buffer, unicodeString.Length);
}
Irp->IoStatus.Status = status;
Irp->IoStatus.Information = (ULONG_PTR) idString;
}
BattPrint(BAT_DATA, ("SmbBattQueryId: returning ID = %x\n", idString));
return status;
}
NTSTATUS
SmbBattQueryCapabilities(
IN PDEVICE_OBJECT Pdo,
IN PIRP Irp
)
/*++
Routine Description:
This routine handles the IRP_MN_QUERY_CAPABILITIES for the newly created
battery PDOs.
Arguments:
Pdo - Battery PDO
Irp - The query Irp
Return Value:
NTSTATUS
--*/
{
PDEVICE_CAPABILITIES deviceCaps;
PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp);
PAGED_CODE();
deviceCaps = irpStack->Parameters.DeviceCapabilities.Capabilities;
if (deviceCaps->Version != 1) {
return STATUS_NOT_SUPPORTED;
}
//
// Now set up the bits for the capabilities.
//
//All bits are initialized to false. Only set bits that we support
deviceCaps->SilentInstall = TRUE;
//
// Now fill in the po manager information.
//
deviceCaps->SystemWake = PowerSystemUnspecified;
deviceCaps->DeviceWake = PowerDeviceUnspecified;
deviceCaps->D1Latency = 1;
deviceCaps->D2Latency = 1;
deviceCaps->D3Latency = 1;
return STATUS_SUCCESS;
}
SmbBattBuildSelectorStruct(
IN PDEVICE_OBJECT SubsystemFdo
)
/*++
Routine Description:
This routine determines that address of the selector (whether it is a stand
alone selector of part of the charger) and builds a selector structure with
this information. It also reads the initial selector information and
caches this in the structure. This structure will be passed out to all of
the smart batteries in the system.
Arguments:
SubsystemFdo - Fdo for the smart battery subsystem
Return Value:
NTSTATUS
--*/
{
ULONG result;
UCHAR smbStatus;
PBATTERY_SELECTOR selector = NULL;
PSMB_BATT_SUBSYSTEM subsystemExt = (PSMB_BATT_SUBSYSTEM) SubsystemFdo->DeviceExtension;
ULONG numberOfBatteries;
PAGED_CODE();
if (subsystemExt->SelectorPresent) {
//
// Allocate the selector structure. This has to be from non-paged pool because
// it will be accessed as part of the alarm processing.
//
selector = ExAllocatePoolWithTag (NonPagedPool, sizeof (BATTERY_SELECTOR), 'StaB');
if (!selector) {
BattPrint (BAT_ERROR, ("SmbBattBuildSelectorStruct: Couldn't allocate selector structure\n"));
//
// Force Selector Not Present if allocation fails
//
subsystemExt->Selector = NULL;
subsystemExt->SelectorPresent = FALSE;
subsystemExt->NumberOfBatteries = 0;
return STATUS_INSUFFICIENT_RESOURCES;
}
//
// See if the selector is part of the charger. We do this by reading
// directly from the selector first. If this fails, then we verify
// the charger is implementing the selector.
//
smbStatus = SmbBattGenericRW (
subsystemExt->SmbHcFdo,
SMB_SELECTOR_ADDRESS,
SELECTOR_SELECTOR_STATE,
&result
);
if (smbStatus == SMB_STATUS_OK) {
//
// We have a stand alone selector
//
selector->SelectorAddress = SMB_SELECTOR_ADDRESS;
selector->SelectorStateCommand = SELECTOR_SELECTOR_STATE;
selector->SelectorPresetsCommand= SELECTOR_SELECTOR_PRESETS;
selector->SelectorInfoCommand = SELECTOR_SELECTOR_INFO;
BattPrint (BAT_NOTE, ("SmbBattBuildSelectorStruct: The selector is standalone\n"));
} else {
//
// Read the Charger Spec Info to check Selector Implemented Bit
// NOTE: We're doing this for verification and information purposes
//
smbStatus = SmbBattGenericRW (
subsystemExt->SmbHcFdo,
SMB_CHARGER_ADDRESS,
CHARGER_SPEC_INFO,
&result
);
if (smbStatus == SMB_STATUS_OK) {
if (result & CHARGER_SELECTOR_SUPPORT_BIT) {
// If Selector Support Bit is present, then Selector implemented in Charger
BattPrint (BAT_NOTE, ("SmbBattBuildSelectorStruct: ChargerSpecInfo indicates charger implementing selector\n"));
} else {
// If Charger says it doesn't implement Selector, let's double-check anyway
BattPrint (BAT_NOTE, ("SmbBattBuildSelectorStruct: ChargerSpecInfo indicates charger does not implement selector\n"));
}
} else {
// If it returns an error, let's double-check anyway
BattPrint (BAT_ERROR, ("SmbBattBuildSelectorStruct: Couldn't read ChargerSpecInfo - %x\n", smbStatus));
}
//
// Read SelectorState for Cache
//
smbStatus = SmbBattGenericRW (
subsystemExt->SmbHcFdo,
SMB_CHARGER_ADDRESS,
CHARGER_SELECTOR_STATE,
&result
);
if (smbStatus == SMB_STATUS_OK) {
BattPrint (BAT_DATA, ("SmbBattBuildSelectorStruct: Selector state %x\n", result));
} else {
BattPrint (BAT_ERROR, ("SmbBattBuildSelectorStruct: Couldn't read charger selector state - %x\n", smbStatus));
goto SelectorErrorExit;
}
//
// The charger is implementing the selector
//
selector->SelectorAddress = SMB_CHARGER_ADDRESS;
selector->SelectorStateCommand = CHARGER_SELECTOR_STATE;
selector->SelectorPresetsCommand= CHARGER_SELECTOR_PRESETS;
selector->SelectorInfoCommand = CHARGER_SELECTOR_INFO;
BattPrint (BAT_NOTE, ("SmbBattBuildSelectorStruct: Charger implements the selector\n"));
}
//
// Initialize the selector mutex
//
ExInitializeFastMutex (&selector->Mutex);
//
// Store SelectorState in Cache
//
selector->SelectorState = result;
//
// Read SelectorPresets for Cache
//
smbStatus = SmbBattGenericRW (
subsystemExt->SmbHcFdo,
selector->SelectorAddress,
selector->SelectorPresetsCommand,
&selector->SelectorPresets
);
if (smbStatus != SMB_STATUS_OK) {
BattPrint (BAT_ERROR, ("SmbBattBuildSelectorStruct: Couldn't read selector presets - %x\n", smbStatus));
//
// Should we really fail the whole thing, because of an error reading SelectorPresets?
// Let's Emulate the Information (Ok To Use All, Use Next A if available)
//
selector->SelectorPresets = (selector->SelectorState & SELECTOR_PRESETS_OKTOUSE_MASK);
if (selector->SelectorPresets & BATTERY_A_PRESENT) {
selector->SelectorPresets |= (BATTERY_A_PRESENT << SELECTOR_SHIFT_USENEXT);
}
BattPrint (BAT_ERROR, ("SmbBattBuildSelectorStruct: Emulating Selector Presets - %x\n", selector->SelectorPresets));
} else {
BattPrint (BAT_DATA, ("SmbBattBuildSelectorStruct: Selector presets %x\n", selector->SelectorPresets));
}
//
// Read Selector Info for Cache
//
smbStatus = SmbBattGenericRW (
subsystemExt->SmbHcFdo,
selector->SelectorAddress,
selector->SelectorInfoCommand,
&selector->SelectorInfo
);
if (smbStatus != SMB_STATUS_OK) {
BattPrint (BAT_ERROR, ("SmbBattBuildSelectorStruct: Couldn't read selector info - %x\n", smbStatus));
//
// Should we really fail the whole thing, because of an error reading SelectorInfo?
// Let's Emulate the Information (Specification 1.0, No Charge Indicator)
//
selector->SelectorInfo = 0x0010;
if (subsystemExt->NumberOfBatteries > 0) {
selector->SelectorInfo |= BATTERY_A_PRESENT;
}
if (subsystemExt->NumberOfBatteries > 1) {
selector->SelectorInfo |= BATTERY_B_PRESENT;
}
if (subsystemExt->NumberOfBatteries > 2) {
selector->SelectorInfo |= BATTERY_C_PRESENT;
}
if (subsystemExt->NumberOfBatteries > 3) {
selector->SelectorInfo |= BATTERY_D_PRESENT;
}
BattPrint (BAT_ERROR, ("SmbBattBuildSelectorStruct: Emulating Selector Info - %x\n", selector->SelectorInfo));
} else {
BattPrint (BAT_NOTE, ("SmbBattBuildSelectorStruct: Selector info %x\n", selector->SelectorInfo));
// Verify the Number of Batteries against the SelectorInfo
numberOfBatteries = 0;
result = (selector->SelectorInfo & SELECTOR_INFO_SUPPORT_MASK);
if (result & BATTERY_A_PRESENT) numberOfBatteries++;
if (result & BATTERY_B_PRESENT) numberOfBatteries++;
if (result & BATTERY_C_PRESENT) numberOfBatteries++;
if (result & BATTERY_D_PRESENT) numberOfBatteries++;
// Should we always override ACPI??
// Proposed Solution: if Selector supports less batteries than
// ACPI says, then Override ACPI with selector support. If
// Selector supports more than ACPI says, then don't override,
// unless ACPI was invalid and the # of batteries = 1
if (subsystemExt->NumberOfBatteries > numberOfBatteries) {
subsystemExt->NumberOfBatteries = numberOfBatteries;
} else if ((subsystemExt->NumberOfBatteries == 1) && (numberOfBatteries > 1)) {
subsystemExt->NumberOfBatteries = numberOfBatteries;
} else if (subsystemExt->NumberOfBatteries < numberOfBatteries) {
//subsystemExt->NumberOfBatteries = numberOfBatteries;
}
}
} // if (subsystemFdo->SelectorPresent)
//
// Everything was OK
//
subsystemExt->Selector = selector;
return STATUS_SUCCESS;
SelectorErrorExit:
//
// If a failure occurs, free the selector structure and don't creat any batery devices.
//
ExFreePool (selector);
subsystemExt->Selector = NULL;
subsystemExt->SelectorPresent = FALSE;
subsystemExt->NumberOfBatteries = 0;
return STATUS_UNSUCCESSFUL;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -