669 lines
20 KiB
C++
669 lines
20 KiB
C++
|
/*
|
||
|
* title: hidbatt.c
|
||
|
*
|
||
|
* purpose: wdm kernel client interface between HID class and power class
|
||
|
*
|
||
|
* 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"
|
||
|
|
||
|
#ifdef ALLOC_PRAGMA
|
||
|
#pragma alloc_text(INIT,DriverEntry)
|
||
|
#endif
|
||
|
|
||
|
|
||
|
// Global
|
||
|
ULONG HidBattDebug = HIDBATT_PRINT_NEVER;
|
||
|
USHORT HidBreakFlag = HIDBATT_BREAK_NEVER;
|
||
|
USHORT gusInstance = 0;
|
||
|
//
|
||
|
// Device Names
|
||
|
//
|
||
|
#define HidBattDeviceName L"\\Device\\HIDBattery"
|
||
|
|
||
|
|
||
|
// local protos
|
||
|
NTSTATUS
|
||
|
HidBattSystemControl(
|
||
|
IN PDEVICE_OBJECT DeviceObject,
|
||
|
IN PIRP Irp
|
||
|
);
|
||
|
|
||
|
|
||
|
|
||
|
NTSTATUS
|
||
|
DriverEntry(
|
||
|
IN PDRIVER_OBJECT DriverObject,
|
||
|
IN PUNICODE_STRING RegistryPath
|
||
|
)
|
||
|
{
|
||
|
|
||
|
|
||
|
NTSTATUS status;
|
||
|
|
||
|
HidBattPrint (HIDBATT_TRACE, ("HidBatt:DriverEntry\n"));
|
||
|
HIDDebugBreak(HIDBATT_BREAK_FULL);
|
||
|
/************************************************************************************/
|
||
|
/* */
|
||
|
/* fill in the slots for the functions in */
|
||
|
/* the Driver object. */
|
||
|
/* */
|
||
|
/************************************************************************************/
|
||
|
|
||
|
DriverObject->MajorFunction[IRP_MJ_CREATE] = HidBattOpen;
|
||
|
DriverObject->MajorFunction[IRP_MJ_CLOSE] = HidBattClose;
|
||
|
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = HidBattIoControl;
|
||
|
DriverObject->MajorFunction[IRP_MJ_POWER] = HidBattPowerDispatch;
|
||
|
DriverObject->MajorFunction[IRP_MJ_PNP] = HidBattPnpDispatch;
|
||
|
DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = HidBattSystemControl; // pass down to hid class
|
||
|
DriverObject->DriverUnload = HidBattUnload; // this is unloadable with current rev of battery class
|
||
|
DriverObject->DriverExtension->AddDevice = HidBattAddDevice;
|
||
|
|
||
|
return STATUS_SUCCESS;
|
||
|
}
|
||
|
|
||
|
NTSTATUS
|
||
|
HidBattAddDevice(
|
||
|
IN PDRIVER_OBJECT DriverObject,
|
||
|
IN PDEVICE_OBJECT pHidPdo
|
||
|
)
|
||
|
{
|
||
|
|
||
|
BOOL bResult;
|
||
|
PUNICODE_STRING unicodeString;
|
||
|
PDEVICE_OBJECT pBatteryFdo = NULL;
|
||
|
NTSTATUS ntStatus;
|
||
|
CBatteryDevExt * pDevExt;
|
||
|
UNICODE_STRING numberString;
|
||
|
WCHAR numberBuffer[10];
|
||
|
CUString * pBatteryName;
|
||
|
// enters here with pdo of hidclass - power class object
|
||
|
|
||
|
HIDDebugBreak(HIDBATT_BREAK_ALWAYS);
|
||
|
HidBattPrint (HIDBATT_TRACE, ("HidBattAddDevice\n"));
|
||
|
|
||
|
|
||
|
/* sberard - Removed due to changes in hidclass.sys (bug #274422)
|
||
|
|
||
|
HID_COLLECTION_INFORMATION HidInfo;
|
||
|
|
||
|
|
||
|
RtlZeroMemory(&HidInfo,sizeof(HID_COLLECTION_INFORMATION));
|
||
|
|
||
|
ntStatus = DoIoctl(
|
||
|
pHidPdo,
|
||
|
IOCTL_HID_GET_COLLECTION_INFORMATION,
|
||
|
NULL,
|
||
|
0,
|
||
|
&HidInfo,
|
||
|
sizeof(HID_COLLECTION_INFORMATION),
|
||
|
(CHidDevice *) NULL
|
||
|
);
|
||
|
|
||
|
if(NT_ERROR(ntStatus))
|
||
|
{
|
||
|
HidBattPrint (HIDBATT_ERROR_ONLY, ("HidBattAddDevice: IOCTL_HID_GET_COLLECTION_INFORMATION failed 0x%08x\n", ntStatus));
|
||
|
return STATUS_UNSUCCESSFUL;
|
||
|
}
|
||
|
*/
|
||
|
// too early to communicate with device, stash hid pdo and complete
|
||
|
pBatteryName = new (NonPagedPool, HidBattTag) CUString(HidBattDeviceName);
|
||
|
|
||
|
if (!pBatteryName) {
|
||
|
return STATUS_INSUFFICIENT_RESOURCES;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
// Create the UPS PDO device name based on the battery instance
|
||
|
//
|
||
|
CUString * pInstanceNumber = new (NonPagedPool, HidBattTag) CUString(++gusInstance,10);
|
||
|
if (!pInstanceNumber) {
|
||
|
return STATUS_INSUFFICIENT_RESOURCES;
|
||
|
}
|
||
|
|
||
|
pBatteryName->Append(&pInstanceNumber->m_String);
|
||
|
delete pInstanceNumber;
|
||
|
ntStatus = IoCreateDevice(
|
||
|
DriverObject,
|
||
|
sizeof (CBatteryDevExt),
|
||
|
&pBatteryName->m_String,
|
||
|
FILE_DEVICE_BATTERY,
|
||
|
0,
|
||
|
FALSE,
|
||
|
&pBatteryFdo
|
||
|
);
|
||
|
|
||
|
if (ntStatus != STATUS_SUCCESS) {
|
||
|
HidBattPrint(HIDBATT_ERROR, ("HidBattCreateFdo: error (0x%x) creating device object\n", ntStatus));
|
||
|
delete pBatteryName;
|
||
|
--gusInstance; // reflect loss of device to instance
|
||
|
return(ntStatus);
|
||
|
}
|
||
|
|
||
|
|
||
|
// pBatteryFdo->DeviceExtension = new (NonPagedPool, HidBattTag) CBatteryDevExt;
|
||
|
|
||
|
|
||
|
// pBatteryFdo->StackSize++; // add one stack entry for battery class
|
||
|
// layer the battery pdo to the hid class pdo
|
||
|
// so that we begin to receive the device irps
|
||
|
PDEVICE_OBJECT pHidDeviceObject = IoAttachDeviceToDeviceStack(pBatteryFdo,pHidPdo);
|
||
|
|
||
|
pDevExt = (CBatteryDevExt *) pBatteryFdo->DeviceExtension;
|
||
|
pDevExt->m_RegistryPath.Length = 0;
|
||
|
pDevExt->m_RegistryPath.MaximumLength = sizeof(pDevExt->m_RegistryBuffer);
|
||
|
RtlZeroMemory(&pDevExt->m_RegistryBuffer, sizeof(pDevExt->m_RegistryBuffer));
|
||
|
pDevExt->m_RegistryPath.Buffer = &pDevExt->m_RegistryBuffer[0]; // set buffer pointer
|
||
|
pDevExt->m_pBattery = NULL;
|
||
|
|
||
|
pBatteryFdo->Flags |= DO_BUFFERED_IO | DO_POWER_PAGABLE;
|
||
|
pBatteryFdo->Flags &= ~DO_DEVICE_INITIALIZING;
|
||
|
pDevExt->m_pHidPdo = pHidPdo;
|
||
|
pDevExt->m_pBatteryFdo = pBatteryFdo;
|
||
|
pDevExt->m_pLowerDeviceObject = pHidDeviceObject;
|
||
|
pDevExt->m_eExtType = eBatteryDevice;
|
||
|
pDevExt->m_bFirstStart = TRUE;
|
||
|
pDevExt->m_bJustStarted = FALSE;
|
||
|
pDevExt->m_ulDefaultAlert1 = (ULONG)-1;
|
||
|
pDevExt->m_pBatteryName = pBatteryName;
|
||
|
|
||
|
IoInitializeRemoveLock (&pDevExt->m_RemoveLock, HidBattTag, 10, 20);
|
||
|
IoInitializeRemoveLock (&pDevExt->m_StopLock, HidBattTag, 10, 20);
|
||
|
IoAcquireRemoveLock (&pDevExt->m_StopLock, (PVOID) HidBattTag);
|
||
|
IoReleaseRemoveLockAndWait (&pDevExt->m_StopLock, (PVOID) HidBattTag);
|
||
|
|
||
|
return STATUS_SUCCESS;
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
NTSTATUS
|
||
|
HidBattOpen(
|
||
|
IN PDEVICE_OBJECT pDeviceObject,
|
||
|
IN PIRP pIrp
|
||
|
)
|
||
|
{
|
||
|
NTSTATUS ntStatus = STATUS_SUCCESS;
|
||
|
PIO_STACK_LOCATION irpSp;
|
||
|
|
||
|
|
||
|
HIDDebugBreak(HIDBATT_BREAK_ALWAYS);
|
||
|
HidBattPrint (HIDBATT_TRACE, ("HidBattOpen\n"));
|
||
|
CBatteryDevExt * pDevExt = (CBatteryDevExt *) pDeviceObject->DeviceExtension;
|
||
|
|
||
|
if (NT_SUCCESS (IoAcquireRemoveLock (&pDevExt->m_RemoveLock, (PVOID) HidBattTag))) {
|
||
|
IoSkipCurrentIrpStackLocation (pIrp);
|
||
|
ntStatus = IoCallDriver(pDevExt->m_pLowerDeviceObject, pIrp);
|
||
|
|
||
|
HidBattPrint (HIDBATT_NOTE, ("HidBattOpen: lower driver returned 0x%08x\n", ntStatus));
|
||
|
|
||
|
IoReleaseRemoveLock (&pDevExt->m_RemoveLock, (PVOID) HidBattTag);
|
||
|
} else {
|
||
|
ntStatus = STATUS_NO_SUCH_DEVICE;
|
||
|
pIrp->IoStatus.Status = ntStatus;
|
||
|
IoCompleteRequest (pIrp, IO_NO_INCREMENT);
|
||
|
}
|
||
|
|
||
|
return ntStatus;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
NTSTATUS
|
||
|
HidBattClose(
|
||
|
IN PDEVICE_OBJECT pDeviceObject,
|
||
|
IN PIRP pIrp
|
||
|
)
|
||
|
{
|
||
|
NTSTATUS ntStatus = STATUS_SUCCESS;
|
||
|
PIO_STACK_LOCATION irpSp;
|
||
|
|
||
|
HidBattPrint (HIDBATT_TRACE, ("HidBattClose\n"));
|
||
|
// get the device extension
|
||
|
CBatteryDevExt * pDevExt = (CBatteryDevExt *) pDeviceObject->DeviceExtension;
|
||
|
|
||
|
HidBattCallLowerDriver(ntStatus, pDevExt->m_pLowerDeviceObject, pIrp);
|
||
|
HidBattPrint (HIDBATT_NOTE, ("HidBattClose: lower driver returned 0x%08x\n", ntStatus));
|
||
|
|
||
|
return ntStatus;
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
NTSTATUS
|
||
|
HidBattSystemControl(
|
||
|
IN PDEVICE_OBJECT pDeviceObject,
|
||
|
IN PIRP pIrp
|
||
|
)
|
||
|
{
|
||
|
HidBattPrint (HIDBATT_TRACE, ("HidBattSystemControl\n"));
|
||
|
HIDDebugBreak(HIDBATT_BREAK_ALWAYS);
|
||
|
|
||
|
// all system control calls are passed down for now.
|
||
|
NTSTATUS ntStatus = STATUS_SUCCESS;
|
||
|
CBatteryDevExt * pDevExt = (CBatteryDevExt *) pDeviceObject->DeviceExtension;
|
||
|
HidBattCallLowerDriver(ntStatus,pDevExt->m_pLowerDeviceObject,pIrp);
|
||
|
return ntStatus;
|
||
|
}
|
||
|
|
||
|
|
||
|
VOID
|
||
|
HidBattUnload(
|
||
|
IN PDRIVER_OBJECT pDriverObject
|
||
|
)
|
||
|
{
|
||
|
HIDDebugBreak(HIDBATT_BREAK_ALWAYS);
|
||
|
// we can just return, no driver-only (non-device) resources were allocated
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
|
||
|
NTSTATUS
|
||
|
HidBattPnpDispatch(
|
||
|
IN PDEVICE_OBJECT pDeviceObject,
|
||
|
IN PIRP pIrp
|
||
|
)
|
||
|
{
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
This routine is the dispatch routine for plug and play requests.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
DeviceObject - Pointer to class device object.
|
||
|
Irp - Pointer to the request packet.
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
Status is returned.
|
||
|
|
||
|
--*/
|
||
|
|
||
|
HIDDebugBreak(HIDBATT_BREAK_ALWAYS);
|
||
|
|
||
|
PIO_STACK_LOCATION pIrpStack;
|
||
|
CBatteryDevExt * pDevExt;
|
||
|
NTSTATUS ntStatus;
|
||
|
BOOLEAN lockReleased = FALSE;
|
||
|
|
||
|
// PAGED_CODE();
|
||
|
|
||
|
|
||
|
ntStatus = STATUS_NOT_SUPPORTED;
|
||
|
|
||
|
//
|
||
|
// Get a pointer to the current parameters for this request. The
|
||
|
// information is contained in the current stack location.
|
||
|
//
|
||
|
|
||
|
pIrpStack = IoGetCurrentIrpStackLocation(pIrp);
|
||
|
pDevExt = (CBatteryDevExt *) pDeviceObject->DeviceExtension;
|
||
|
|
||
|
IoAcquireRemoveLock (&pDevExt->m_RemoveLock, (PVOID) HidBattTag);
|
||
|
|
||
|
//
|
||
|
// Dispatch minor function
|
||
|
//
|
||
|
switch (pIrpStack->MinorFunction)
|
||
|
{
|
||
|
|
||
|
case IRP_MN_STOP_DEVICE:
|
||
|
{
|
||
|
HidBattPrint (HIDBATT_PNP, ("HidBattPnpDispatch: IRP_MN_STOP_DEVICE\n"));
|
||
|
ntStatus = HidBattStopDevice(pDeviceObject, pIrp);
|
||
|
break;
|
||
|
} // IRP_MN_STOP_DEVICE
|
||
|
|
||
|
case IRP_MN_QUERY_DEVICE_RELATIONS:
|
||
|
{
|
||
|
HidBattPrint (HIDBATT_PNP, ("HidBattPnpDispatch: IRP_MN_QUERY_DEVICE_RELATIONS - type (%d)\n",
|
||
|
pIrpStack->Parameters.QueryDeviceRelations.Type));
|
||
|
|
||
|
break;
|
||
|
} // IRP_MN_QUERY_DEVICE_RELATIONS
|
||
|
|
||
|
case IRP_MN_FILTER_RESOURCE_REQUIREMENTS:
|
||
|
{
|
||
|
HidBattPrint (HIDBATT_PNP, ("HidBattPnpDispatch: IRP_MN_FILTER_RESOURCE_REQUIREMENTS - type (%d)\n",
|
||
|
pIrpStack->Parameters.QueryDeviceRelations.Type));
|
||
|
|
||
|
break;
|
||
|
} // IRP_MN_FILTER_RESOURCE_REQUIREMENTS
|
||
|
|
||
|
case IRP_MN_REMOVE_DEVICE:
|
||
|
|
||
|
{
|
||
|
HidBattPrint (HIDBATT_PNP, ("HidBattPnpDispatch: IRP_MN_REMOVE_DEVICE\n"));
|
||
|
|
||
|
HidBattPrint (HIDBATT_PNP, ("HidBattPnpDispatch: Waiting to remove\n"));
|
||
|
IoReleaseRemoveLockAndWait (&pDevExt->m_RemoveLock, (PVOID) HidBattTag);
|
||
|
lockReleased = TRUE;
|
||
|
|
||
|
// then remove device from device stack
|
||
|
IoDetachDevice(pDevExt->m_pLowerDeviceObject);
|
||
|
|
||
|
// delete our device
|
||
|
IoDeleteDevice(pDeviceObject);
|
||
|
|
||
|
ntStatus = STATUS_SUCCESS;
|
||
|
break;
|
||
|
} // IRP_MN_REMOVE_DEVICE
|
||
|
|
||
|
case IRP_MN_SURPRISE_REMOVAL:
|
||
|
case IRP_MN_QUERY_REMOVE_DEVICE:
|
||
|
|
||
|
{
|
||
|
HidBattPrint (HIDBATT_PNP, ("HidBattPnpDispatch: IRP_MN_QUERY_REMOVE_DEVICE\n"));
|
||
|
|
||
|
ntStatus = HidBattStopDevice(pDeviceObject, pIrp);
|
||
|
|
||
|
ntStatus = STATUS_SUCCESS;
|
||
|
break;
|
||
|
} // IRP_MN_QUERY_REMOVE_DEVICE
|
||
|
|
||
|
case IRP_MN_START_DEVICE:
|
||
|
{
|
||
|
HidBattPrint (HIDBATT_PNP, ("HidBattPnpDispatch: IRP_MN_START_DEVICE\n"));
|
||
|
if (pDevExt->m_bFirstStart) {
|
||
|
pDevExt->m_bJustStarted = TRUE;
|
||
|
pDevExt->m_bFirstStart = FALSE;
|
||
|
ntStatus = STATUS_SUCCESS;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
// else fall through and do the same thing as the cancel remove.
|
||
|
|
||
|
} // IRP_MN_START_DEVICE
|
||
|
|
||
|
case IRP_MN_CANCEL_REMOVE_DEVICE:
|
||
|
{
|
||
|
HidBattPrint (HIDBATT_PNP, ("HidBattPnpDispatch: IRP_MN_CANCEL_REMOVE_DEVICE\n"));
|
||
|
|
||
|
KEVENT cancelRemoveComplete;
|
||
|
|
||
|
KeInitializeEvent(&cancelRemoveComplete, SynchronizationEvent, FALSE);
|
||
|
IoCopyCurrentIrpStackLocationToNext (pIrp);
|
||
|
IoSetCompletionRoutine (pIrp, HidBattIoCompletion, &cancelRemoveComplete, TRUE, TRUE, TRUE);
|
||
|
pIrp->IoStatus.Status = STATUS_SUCCESS;
|
||
|
ntStatus = IoCallDriver (pDevExt->m_pLowerDeviceObject, pIrp);
|
||
|
HidBattPrint (HIDBATT_PNP, ("HidBattPnpDispatch: IRP_MN_CANCEL_REMOVE_DEVICE, Lower driver status: %08x\n", ntStatus));
|
||
|
|
||
|
if (ntStatus == STATUS_PENDING) {
|
||
|
KeWaitForSingleObject (&cancelRemoveComplete, Executive, KernelMode, FALSE, NULL);
|
||
|
ntStatus = pIrp->IoStatus.Status;
|
||
|
HidBattPrint (HIDBATT_PNP, ("HidBattPnpDispatch: IRP_MN_CANCEL_REMOVE_DEVICE, Lower driver 2nd status: %08x\n", ntStatus));
|
||
|
}
|
||
|
|
||
|
if (NT_SUCCESS (ntStatus)) {
|
||
|
ntStatus = HidBattInitializeDevice (pDeviceObject, pIrp);
|
||
|
HidBattPrint (HIDBATT_PNP, ("HidBattPnpDispatch: IRP_MN_CANCEL_REMOVE_DEVICE, Our status: %08x\n", ntStatus));
|
||
|
}
|
||
|
|
||
|
pIrp->IoStatus.Status = ntStatus;
|
||
|
|
||
|
IoCompleteRequest (pIrp, IO_NO_INCREMENT);
|
||
|
|
||
|
IoReleaseRemoveLock (&pDevExt->m_RemoveLock, (PVOID) HidBattTag);
|
||
|
|
||
|
return ntStatus;
|
||
|
} // IRP_MN_CANCEL_REMOVE_DEVICE
|
||
|
|
||
|
case IRP_MN_QUERY_STOP_DEVICE:
|
||
|
{
|
||
|
HidBattPrint (HIDBATT_PNP, ("HidBattPnpDispatch: IRP_MN_QUERY_STOP_DEVICE\n"));
|
||
|
ntStatus = STATUS_SUCCESS;
|
||
|
break;
|
||
|
} // IRP_MN_QUERY_STOP_DEVICE
|
||
|
|
||
|
case IRP_MN_CANCEL_STOP_DEVICE:
|
||
|
{
|
||
|
HidBattPrint (HIDBATT_PNP, ("HidBattPnpDispatch: IRP_MN_CANCEL_STOP_DEVICE\n"));
|
||
|
ntStatus = STATUS_SUCCESS;
|
||
|
break;
|
||
|
} // IRP_MN_CANCEL_STOP_DEVICE
|
||
|
|
||
|
case IRP_MN_QUERY_RESOURCES:
|
||
|
{
|
||
|
HidBattPrint (HIDBATT_PNP, ("HidBattPnpDispatch: IRP_MN_QUERY_RESOURCES\n"));
|
||
|
break;
|
||
|
} // IRP_MN_QUERY_RESOURCES
|
||
|
|
||
|
case IRP_MN_READ_CONFIG:
|
||
|
{
|
||
|
HidBattPrint (HIDBATT_PNP, ("HidBattPnpDispatch: IRP_MN_READ_CONFIG\n"));
|
||
|
break;
|
||
|
} // IRP_MN_READ_CONFIG
|
||
|
|
||
|
case IRP_MN_WRITE_CONFIG:
|
||
|
{
|
||
|
HidBattPrint (HIDBATT_PNP, ("HidBattPnpDispatch: IRP_MN_WRITE_CONFIG\n"));
|
||
|
break;
|
||
|
} // IRP_MN_WRITE_CONFIG
|
||
|
|
||
|
case IRP_MN_EJECT:
|
||
|
{
|
||
|
HidBattPrint (HIDBATT_PNP, ("HidBattPnpDispatch: IRP_MN_EJECT\n"));
|
||
|
break;
|
||
|
} // IRP_MN_EJECT
|
||
|
|
||
|
case IRP_MN_SET_LOCK:
|
||
|
{
|
||
|
HidBattPrint (HIDBATT_PNP, ("HidBattPnpDispatch: IRP_MN_SET_LOCK\n"));
|
||
|
break;
|
||
|
} // IRP_MN_SET_LOCK
|
||
|
|
||
|
case IRP_MN_QUERY_ID:
|
||
|
{
|
||
|
HidBattPrint (HIDBATT_PNP, ("HidBattPnpDispatch: IRP_MN_QUERY_ID\n"));
|
||
|
break;
|
||
|
} // IRP_MN_QUERY_ID
|
||
|
|
||
|
case IRP_MN_QUERY_CAPABILITIES:
|
||
|
{
|
||
|
PDEVICE_CAPABILITIES deviceCaps;
|
||
|
HidBattPrint (HIDBATT_PNP, ("HidBattPnpDispatch: IRP_MN_QUERY_CAPABILITIES\n"));
|
||
|
|
||
|
deviceCaps = pIrpStack->Parameters.DeviceCapabilities.Capabilities;
|
||
|
deviceCaps->Removable = TRUE;
|
||
|
deviceCaps->SurpriseRemovalOK = TRUE;
|
||
|
|
||
|
ntStatus = STATUS_SUCCESS;
|
||
|
break;
|
||
|
} // IRP_MN_QUERY_CAPABILITIES
|
||
|
|
||
|
case IRP_MN_QUERY_PNP_DEVICE_STATE:
|
||
|
{
|
||
|
HidBattPrint (HIDBATT_PNP, ("HidBattPnpDispatch: IRP_MN_PNP_DEVICE_STATE\n"));
|
||
|
|
||
|
if (pDevExt->m_bJustStarted == TRUE) {
|
||
|
|
||
|
pDevExt->m_bJustStarted = FALSE;
|
||
|
|
||
|
ntStatus = HidBattInitializeDevice (pDeviceObject, pIrp);
|
||
|
}
|
||
|
|
||
|
if (!NT_SUCCESS (ntStatus)) {
|
||
|
HidBattPrint (HIDBATT_PNP, ("HidBattPnpDispatch: HidBattInitializeDevice failed %0x\n", ntStatus));
|
||
|
pIrp->IoStatus.Information |= PNP_DEVICE_FAILED;
|
||
|
pIrp->IoStatus.Status = STATUS_SUCCESS;
|
||
|
}
|
||
|
|
||
|
break;
|
||
|
} // IRP_MN_PNP_DEVICE_STATE
|
||
|
|
||
|
default:
|
||
|
{
|
||
|
HidBattPrint (HIDBATT_PNP,
|
||
|
("HidBattPnpDispatch: Unimplemented minor %0x\n",
|
||
|
pIrpStack->MinorFunction));
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (ntStatus != STATUS_NOT_SUPPORTED) {
|
||
|
pIrp->IoStatus.Status = ntStatus;
|
||
|
}
|
||
|
|
||
|
if (NT_SUCCESS(ntStatus) || (ntStatus == STATUS_NOT_SUPPORTED)) {
|
||
|
HidBattCallLowerDriver (ntStatus, pDevExt->m_pLowerDeviceObject, pIrp);
|
||
|
|
||
|
} else {
|
||
|
IoCompleteRequest (pIrp, IO_NO_INCREMENT);
|
||
|
}
|
||
|
|
||
|
if (lockReleased == FALSE) {
|
||
|
IoReleaseRemoveLock (&pDevExt->m_RemoveLock, (PVOID) HidBattTag);
|
||
|
}
|
||
|
|
||
|
return ntStatus;
|
||
|
}
|
||
|
|
||
|
|
||
|
NTSTATUS
|
||
|
HidBattPowerDispatch(
|
||
|
IN PDEVICE_OBJECT pDeviceObject,
|
||
|
IN PIRP pIrp
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
This routine is the dispatch routine for power requests.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
DeviceObject - Pointer to class device object.
|
||
|
Irp - Pointer to the request packet.
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
Status is returned.
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
PIO_STACK_LOCATION pIrpStack;
|
||
|
CBatteryDevExt * pDevExt;
|
||
|
NTSTATUS ntStatus;
|
||
|
|
||
|
HIDDebugBreak(HIDBATT_BREAK_ALWAYS);
|
||
|
|
||
|
// PAGED_CODE();
|
||
|
|
||
|
HidBattPrint ((HIDBATT_TRACE | HIDBATT_POWER), ("HidBattPowerDispatch\n"));
|
||
|
|
||
|
//
|
||
|
// Never fail a power IRP, even if we don't do anything.
|
||
|
//
|
||
|
|
||
|
ntStatus = STATUS_SUCCESS;
|
||
|
pIrp->IoStatus.Information = 0;
|
||
|
|
||
|
//
|
||
|
// Get a pointer to the current parameters for this request. The
|
||
|
// information is contained in the current stack location.
|
||
|
//
|
||
|
|
||
|
pIrpStack = IoGetCurrentIrpStackLocation(pIrp);
|
||
|
pDevExt = (CBatteryDevExt *) pDeviceObject->DeviceExtension;
|
||
|
|
||
|
//
|
||
|
// Dispatch minor function
|
||
|
//
|
||
|
// this switch currently does no dispatches, and is expanded only for
|
||
|
// documentary purposes
|
||
|
switch (pIrpStack->MinorFunction) {
|
||
|
|
||
|
case IRP_MN_WAIT_WAKE: {
|
||
|
HidBattPrint (HIDBATT_POWER, ("HidBattPowerDispatch: IRP_MN_WAIT_WAKE\n"));
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
case IRP_MN_POWER_SEQUENCE: {
|
||
|
HidBattPrint (HIDBATT_POWER, ("HidBattPowerDispatch: IRP_MN_POWER_SEQUENCE\n"));
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
case IRP_MN_SET_POWER: {
|
||
|
HidBattPrint (HIDBATT_POWER, ("HidBattPowerDispatch: IRP_MN_SET_POWER\n"));
|
||
|
if (pIrpStack->Parameters.Power.Type == SystemPowerState &&
|
||
|
pIrpStack->Parameters.Power.State.SystemState >= PowerSystemShutdown) {
|
||
|
|
||
|
if (NT_SUCCESS(IoAcquireRemoveLock (&pDevExt->m_StopLock, (PVOID) HidBattTag)) )
|
||
|
{
|
||
|
//
|
||
|
// Write default RemainingCapcitylimit back to UPS so when the system reboots,
|
||
|
// the data returned by the device will be correct.
|
||
|
//
|
||
|
pDevExt->m_pBattery->GetSetValue(REMAINING_CAPACITY_LIMIT_INDEX,
|
||
|
&pDevExt->m_ulDefaultAlert1,TRUE);
|
||
|
|
||
|
IoReleaseRemoveLock (&pDevExt->m_StopLock, (PVOID) HidBattTag);
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
case IRP_MN_QUERY_POWER: {
|
||
|
HidBattPrint (HIDBATT_POWER, ("HidBattPowerDispatch: IRP_MN_QUERY_POWER\n"));
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
default: {
|
||
|
|
||
|
HidBattPrint(HIDBATT_LOW, ("HidBattPowerDispatch: minor %d\n",
|
||
|
pIrpStack->MinorFunction));
|
||
|
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
PoStartNextPowerIrp(pIrp); // inform system we are done with this irp
|
||
|
IoSkipCurrentIrpStackLocation(pIrp);
|
||
|
ntStatus = PoCallDriver(pDevExt->m_pLowerDeviceObject,pIrp);
|
||
|
|
||
|
return ntStatus;
|
||
|
}
|
||
|
|
||
|
NTSTATUS HidBattSetInformation(
|
||
|
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
|
||
|
|
||
|
--*/
|
||
|
// charge and discharge forcing not supported for UPS's
|
||
|
HidBattPrint (HIDBATT_TRACE, ("HidBattSetInformation\n"));
|
||
|
HIDDebugBreak(HIDBATT_BREAK_ALWAYS);
|
||
|
return STATUS_UNSUCCESSFUL;
|
||
|
}
|