|
|
/*
* title: hidbattpnp.cpp * * purpose: support for plug and play routines * * 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"
NTSTATUS HidBattInitializeDevice (PDEVICE_OBJECT pBatteryFdo, PIRP pIrp) {
NTSTATUS ntStatus; CBatteryDevExt * pDevExt = (CBatteryDevExt *) pBatteryFdo->DeviceExtension; PIO_STACK_LOCATION pIrpStack = IoGetCurrentIrpStackLocation(pIrp); ULONG ulBatteryStatus; bool bResult; BATTERY_MINIPORT_INFO BattInit; UNICODE_STRING Name; ULONG ulBufferLength = 0; PWCHAR pBuffer = NULL; CBattery * pBattery; PFILE_OBJECT fileObject; OBJECT_ATTRIBUTES objectAttributes; HANDLE fileHandle; IO_STATUS_BLOCK ioStatus;
HIDDebugBreak(HIDBATT_BREAK_ALWAYS);
HidBattPrint (HIDBATT_PNP, ("HidBattInitializeDevice: Sending Irp (0x%x) to Pdo\n", pIrp));
// now get file object using KenRay's method from mouclass
ntStatus = IoGetDeviceProperty ( pDevExt->m_pHidPdo, DevicePropertyPhysicalDeviceObjectName, ulBufferLength, pBuffer, &ulBufferLength); if(ntStatus != STATUS_BUFFER_TOO_SMALL) { // only thing we expect with a zero buffer is this error,
// any other error must be fatal
return STATUS_UNSUCCESSFUL; }
pBuffer = (PWCHAR) ExAllocatePoolWithTag (NonPagedPool, ulBufferLength, HidBattTag);
if (NULL == pBuffer) { return STATUS_INSUFFICIENT_RESOURCES; }
ntStatus = IoGetDeviceProperty ( pDevExt->m_pHidPdo, DevicePropertyPhysicalDeviceObjectName, ulBufferLength, pBuffer, &ulBufferLength);
if(NT_ERROR(ntStatus)) { ExFreePool(pBuffer); return ntStatus;
}
Name.MaximumLength = (USHORT) ulBufferLength; Name.Length = (USHORT) ulBufferLength - sizeof (UNICODE_NULL); Name.Buffer = pBuffer;
pDevExt->m_OpeningThread = KeGetCurrentThread();
//
// Initialize the object attributes to open the device.
//
InitializeObjectAttributes( &objectAttributes, &Name, 0, (HANDLE) NULL, (PSECURITY_DESCRIPTOR) NULL );
ntStatus = ZwOpenFile( &fileHandle, FILE_ALL_ACCESS, &objectAttributes, &ioStatus, FILE_SHARE_WRITE | FILE_SHARE_READ, FILE_NON_DIRECTORY_FILE );
ExFreePool (pBuffer);
if (NT_SUCCESS( ntStatus )) {
//
// The open operation was successful. Dereference the file handle
// and obtain a pointer to the device object for the handle.
//
ntStatus = ObReferenceObjectByHandle( fileHandle, 0, *IoFileObjectType, KernelMode, (PVOID *) &pDevExt->m_pHidFileObject, NULL );
ZwClose( fileHandle ); }
pDevExt->m_OpeningThread = NULL; if(NT_ERROR(ntStatus)) { return ntStatus; }
// now init new hid deviceclass object for this device
CHidDevice * pHidDevice = new (NonPagedPool, HidBattTag) CHidDevice; // setup a new hid device
if (!pHidDevice) { HidBattPrint(HIDBATT_ERROR, ("HidBattInitializeDevice: error allocating CHidDevice")); return STATUS_UNSUCCESSFUL; }
pHidDevice->m_pFCB = pDevExt->m_pHidFileObject; // put usable file object into hid device
pHidDevice->m_pLowerDeviceObject = pDevExt->m_pLowerDeviceObject; pHidDevice->m_pDeviceObject = pDevExt->m_pBatteryFdo; pHidDevice->m_pReadIrp = NULL; bResult = pHidDevice->OpenHidDevice(pDevExt->m_pHidPdo); // initialize the members of this device
if(!bResult) { delete pHidDevice; return STATUS_UNSUCCESSFUL; }
// check if this has a power page, ups application collection
if(pHidDevice->m_UsagePage != UsagePowerPage || pHidDevice->m_UsageID != UsageUPS) { delete pHidDevice; return STATUS_UNSUCCESSFUL; }
//
// Initialize Fdo device extension data
//
// create the battery object
pBattery = new (NonPagedPool, HidBattTag) CBattery(pHidDevice);
if (!pBattery){ HidBattPrint(HIDBATT_ERROR, ("HidBattInitializeDevice: error allocating CBattery")); return STATUS_UNSUCCESSFUL; } // and initialize battery values
// now init in both new and replug states
pBattery->m_pCHidDevice = pHidDevice; // save init'ed hid device object
bResult = pBattery->InitValues(); if(!bResult) { return STATUS_UNSUCCESSFUL; }
// Attach to the Class Driver
RtlZeroMemory (&BattInit, sizeof(BattInit)); BattInit.MajorVersion = BATTERY_CLASS_MAJOR_VERSION; BattInit.MinorVersion = BATTERY_CLASS_MINOR_VERSION; BattInit.Context = pDevExt; BattInit.QueryTag = HidBattQueryTag; BattInit.QueryInformation = HidBattQueryInformation; BattInit.SetInformation = HidBattSetInformation; BattInit.QueryStatus = HidBattQueryStatus; BattInit.SetStatusNotify = HidBattSetStatusNotify; BattInit.DisableStatusNotify = HidBattDisableStatusNotify;
BattInit.Pdo = pDevExt->m_pHidPdo; BattInit.DeviceName = NULL;
pHidDevice->m_pEventHandler = HidBattNotifyHandler; pHidDevice->m_pEventContext = (PVOID) pDevExt;
//
// save battery in device extension
// This indicates that we are ready for IO.
//
pDevExt->m_pBattery = pBattery;
//
// Initialize stop lock
//
IoInitializeRemoveLock (&pDevExt->m_StopLock, HidBattTag, 10, 20);
// and finally we can now start actively polling the device
// start the read/notification process
ntStatus = pBattery->m_pCHidDevice->ActivateInput(); if(!NT_SUCCESS(ntStatus)) { delete pHidDevice; HidBattPrint(HIDBATT_ERROR, ("HidBattInitializeDevice: error (0x%x) in ActivateInput.\n", ntStatus)); return ntStatus; }
ntStatus = BatteryClassInitializeDevice (&BattInit, &pBattery->m_pBatteryClass); if (!NT_SUCCESS(ntStatus)) { //
// if we can't attach to class driver we're toast
//
delete pHidDevice; HidBattPrint(HIDBATT_ERROR, ("HidBattInitializeDevice: error (0x%x) registering with class\n", ntStatus)); return ntStatus; }
HidBattPrint(HIDBATT_TRACE, ("HidBattInitializeDevice: returned ok\n")); return ntStatus; }
NTSTATUS HidBattStopDevice( IN PDEVICE_OBJECT pBatteryFdo, IN PIRP pIrp ) /*++
Routine Description:
This routine is called when we receive a IRP_MN_STOP_DEVICE. It just sends the request down the chain of drivers to the Pdo and waits for a response.
Arguments:
Fdo - a pointer to the fdo for this driver Irp - Pointer to the request packet.
Return Value:
Status is returned.
--*/ { CBatteryDevExt * pDevExt = (CBatteryDevExt *) pBatteryFdo->DeviceExtension; KEVENT pdoStoppedEvent; PIO_STACK_LOCATION pIrpStack = IoGetCurrentIrpStackLocation(pIrp); NTSTATUS ntStatus;
HIDDebugBreak(HIDBATT_BREAK_ALWAYS); HidBattPrint ((HIDBATT_TRACE | HIDBATT_PNP), ("HidBattStopDevice\n"));
if (!NT_SUCCESS (IoAcquireRemoveLock (&pDevExt->m_StopLock, (PVOID) HidBattTag))) { //
// Don't release twice.
//
return STATUS_SUCCESS; }
pDevExt->m_bJustStarted = FALSE;
HidBattPrint (HIDBATT_PNP, ("HidBattStopDevice: Waiting to remove\n")); IoReleaseRemoveLockAndWait (&pDevExt->m_StopLock, (PVOID) HidBattTag);
if (pDevExt->m_pBattery && pDevExt->m_pBattery->m_pBatteryClass) { BatteryClassUnload(pDevExt->m_pBattery->m_pBatteryClass); }
if (pDevExt->m_pBattery && pDevExt->m_pBattery->m_pCHidDevice && pDevExt->m_pBattery->m_pCHidDevice->m_pReadIrp) { IoCancelIrp (pDevExt->m_pBattery->m_pCHidDevice->m_pReadIrp); }
if (pDevExt->m_pBattery && pDevExt->m_pBattery->m_pCHidDevice && pDevExt->m_pBattery->m_pCHidDevice->m_pThreadObject) {
//
// Clean up worker thread.
//
KeWaitForSingleObject ( pDevExt->m_pBattery->m_pCHidDevice->m_pThreadObject, Executive, KernelMode, FALSE, NULL ); HidBattPrint (HIDBATT_PNP, ("HidBattStopDevice: Done Waiting to remove\n"));
ObDereferenceObject (pDevExt->m_pBattery->m_pCHidDevice->m_pThreadObject); } else { return STATUS_UNSUCCESSFUL; // If we can't be sure the Read Thread has terminated, it is unsafe to
// stop or remove the device. This may cause a reboot to be needed.
}
if (pDevExt->m_pBattery && pDevExt->m_pBattery->m_pCHidDevice && pDevExt->m_pBattery->m_pCHidDevice->m_pReadIrp) { IoFreeIrp(pDevExt->m_pBattery->m_pCHidDevice->m_pReadIrp); // clean up irp
pDevExt->m_pBattery->m_pCHidDevice->m_pReadIrp = NULL; }
//
// Write default RemainingCapcitylimit back to UPS so the next time we enumerate
// the device, we'll read back the right data.
//
pDevExt->m_pBattery->GetSetValue(REMAINING_CAPACITY_LIMIT_INDEX, &pDevExt->m_ulDefaultAlert1,TRUE);
// dereference our file object, if present
if(pDevExt->m_pHidFileObject) { ObDereferenceObject(pDevExt->m_pHidFileObject); pDevExt->m_pBattery->m_pCHidDevice->m_pFCB = NULL; }
if (pDevExt->m_pBattery) { delete pDevExt->m_pBattery; pDevExt->m_pBattery = NULL; }
ntStatus = STATUS_SUCCESS;
pDevExt->m_bIsStarted = FALSE;
return STATUS_SUCCESS; }
|