1*c2c66affSColin Finck /*
2*c2c66affSColin Finck * PROJECT: ReactOS Composite Battery Driver
3*c2c66affSColin Finck * LICENSE: BSD - See COPYING.ARM in the top level directory
4*c2c66affSColin Finck * FILE: boot/drivers/bus/acpi/compbatt/comppnp.c
5*c2c66affSColin Finck * PURPOSE: Plug-and-Play IOCTL/IRP Handling
6*c2c66affSColin Finck * PROGRAMMERS: ReactOS Portable Systems Group
7*c2c66affSColin Finck */
8*c2c66affSColin Finck
9*c2c66affSColin Finck /* INCLUDES *******************************************************************/
10*c2c66affSColin Finck
11*c2c66affSColin Finck #include "compbatt.h"
12*c2c66affSColin Finck
13*c2c66affSColin Finck #include <wdmguid.h>
14*c2c66affSColin Finck
15*c2c66affSColin Finck /* FUNCTIONS ******************************************************************/
16*c2c66affSColin Finck
17*c2c66affSColin Finck NTSTATUS
18*c2c66affSColin Finck NTAPI
CompBattPowerDispatch(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)19*c2c66affSColin Finck CompBattPowerDispatch(IN PDEVICE_OBJECT DeviceObject,
20*c2c66affSColin Finck IN PIRP Irp)
21*c2c66affSColin Finck {
22*c2c66affSColin Finck PCOMPBATT_DEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
23*c2c66affSColin Finck if (CompBattDebug & 1) DbgPrint("CompBatt: PowerDispatch received power IRP.\n");
24*c2c66affSColin Finck
25*c2c66affSColin Finck /* Start the next IRP */
26*c2c66affSColin Finck PoStartNextPowerIrp(Irp);
27*c2c66affSColin Finck
28*c2c66affSColin Finck /* Call the next driver in the stack */
29*c2c66affSColin Finck IoSkipCurrentIrpStackLocation(Irp);
30*c2c66affSColin Finck return PoCallDriver(DeviceExtension->AttachedDevice, Irp);
31*c2c66affSColin Finck }
32*c2c66affSColin Finck
33*c2c66affSColin Finck PCOMPBATT_BATTERY_DATA
34*c2c66affSColin Finck NTAPI
RemoveBatteryFromList(IN PCUNICODE_STRING BatteryName,IN PCOMPBATT_DEVICE_EXTENSION DeviceExtension)35*c2c66affSColin Finck RemoveBatteryFromList(IN PCUNICODE_STRING BatteryName,
36*c2c66affSColin Finck IN PCOMPBATT_DEVICE_EXTENSION DeviceExtension)
37*c2c66affSColin Finck {
38*c2c66affSColin Finck PLIST_ENTRY ListHead, NextEntry;
39*c2c66affSColin Finck PCOMPBATT_BATTERY_DATA BatteryData;
40*c2c66affSColin Finck if (CompBattDebug & 1)
41*c2c66affSColin Finck DbgPrint("CompBatt: ENTERING RemoveBatteryFromList\n");
42*c2c66affSColin Finck
43*c2c66affSColin Finck /* Loop the battery list */
44*c2c66affSColin Finck ExAcquireFastMutex(&DeviceExtension->Lock);
45*c2c66affSColin Finck ListHead = &DeviceExtension->BatteryList;
46*c2c66affSColin Finck NextEntry = ListHead->Flink;
47*c2c66affSColin Finck while (NextEntry != ListHead)
48*c2c66affSColin Finck {
49*c2c66affSColin Finck /* Get the battery information and compare the name */
50*c2c66affSColin Finck BatteryData = CONTAINING_RECORD(NextEntry, COMPBATT_BATTERY_DATA, BatteryLink);
51*c2c66affSColin Finck if (!RtlCompareUnicodeString(BatteryName, &BatteryData->BatteryName, TRUE))
52*c2c66affSColin Finck {
53*c2c66affSColin Finck /* Flush pending deletes and any lock waiters */
54*c2c66affSColin Finck IoAcquireRemoveLock(&BatteryData->RemoveLock, 0);
55*c2c66affSColin Finck ExReleaseFastMutex(&DeviceExtension->Lock);
56*c2c66affSColin Finck IoReleaseRemoveLockAndWait(&BatteryData->RemoveLock, 0);
57*c2c66affSColin Finck
58*c2c66affSColin Finck /* Remove the entry from the list */
59*c2c66affSColin Finck ExAcquireFastMutex(&DeviceExtension->Lock);
60*c2c66affSColin Finck RemoveEntryList(&BatteryData->BatteryLink);
61*c2c66affSColin Finck ExReleaseFastMutex(&DeviceExtension->Lock);
62*c2c66affSColin Finck return BatteryData;
63*c2c66affSColin Finck }
64*c2c66affSColin Finck
65*c2c66affSColin Finck /* Next */
66*c2c66affSColin Finck NextEntry = NextEntry->Flink;
67*c2c66affSColin Finck }
68*c2c66affSColin Finck
69*c2c66affSColin Finck /* Done */
70*c2c66affSColin Finck ExReleaseFastMutex(&DeviceExtension->Lock);
71*c2c66affSColin Finck if (CompBattDebug & 1) DbgPrint("CompBatt: EXITING RemoveBatteryFromList\n");
72*c2c66affSColin Finck return NULL;
73*c2c66affSColin Finck }
74*c2c66affSColin Finck
75*c2c66affSColin Finck BOOLEAN
76*c2c66affSColin Finck NTAPI
IsBatteryAlreadyOnList(IN PCUNICODE_STRING BatteryName,IN PCOMPBATT_DEVICE_EXTENSION DeviceExtension)77*c2c66affSColin Finck IsBatteryAlreadyOnList(IN PCUNICODE_STRING BatteryName,
78*c2c66affSColin Finck IN PCOMPBATT_DEVICE_EXTENSION DeviceExtension)
79*c2c66affSColin Finck {
80*c2c66affSColin Finck PLIST_ENTRY ListHead, NextEntry;
81*c2c66affSColin Finck PCOMPBATT_BATTERY_DATA BatteryData;
82*c2c66affSColin Finck BOOLEAN Found = FALSE;
83*c2c66affSColin Finck if (CompBattDebug & 1)
84*c2c66affSColin Finck DbgPrint("CompBatt: ENTERING IsBatteryAlreadyOnList\n");
85*c2c66affSColin Finck
86*c2c66affSColin Finck /* Loop the battery list */
87*c2c66affSColin Finck ExAcquireFastMutex(&DeviceExtension->Lock);
88*c2c66affSColin Finck ListHead = &DeviceExtension->BatteryList;
89*c2c66affSColin Finck NextEntry = ListHead->Flink;
90*c2c66affSColin Finck while (NextEntry != ListHead)
91*c2c66affSColin Finck {
92*c2c66affSColin Finck /* Get the battery information and compare the name */
93*c2c66affSColin Finck BatteryData = CONTAINING_RECORD(NextEntry, COMPBATT_BATTERY_DATA, BatteryLink);
94*c2c66affSColin Finck if (!RtlCompareUnicodeString(BatteryName, &BatteryData->BatteryName, TRUE))
95*c2c66affSColin Finck {
96*c2c66affSColin Finck /* Got it */
97*c2c66affSColin Finck Found = TRUE;
98*c2c66affSColin Finck break;
99*c2c66affSColin Finck }
100*c2c66affSColin Finck
101*c2c66affSColin Finck /* Next */
102*c2c66affSColin Finck NextEntry = NextEntry->Flink;
103*c2c66affSColin Finck }
104*c2c66affSColin Finck
105*c2c66affSColin Finck /* Release the lock and return search status */
106*c2c66affSColin Finck ExReleaseFastMutex(&DeviceExtension->Lock);
107*c2c66affSColin Finck if (CompBattDebug & 1) DbgPrint("CompBatt: EXITING IsBatteryAlreadyOnList\n");
108*c2c66affSColin Finck return Found;
109*c2c66affSColin Finck }
110*c2c66affSColin Finck
111*c2c66affSColin Finck NTSTATUS
112*c2c66affSColin Finck NTAPI
CompBattAddNewBattery(IN PUNICODE_STRING BatteryName,IN PCOMPBATT_DEVICE_EXTENSION DeviceExtension)113*c2c66affSColin Finck CompBattAddNewBattery(IN PUNICODE_STRING BatteryName,
114*c2c66affSColin Finck IN PCOMPBATT_DEVICE_EXTENSION DeviceExtension)
115*c2c66affSColin Finck {
116*c2c66affSColin Finck NTSTATUS Status = STATUS_SUCCESS;
117*c2c66affSColin Finck PCOMPBATT_BATTERY_DATA BatteryData;
118*c2c66affSColin Finck PIRP Irp;
119*c2c66affSColin Finck PIO_STACK_LOCATION IoStackLocation;
120*c2c66affSColin Finck PFILE_OBJECT FileObject;
121*c2c66affSColin Finck PAGED_CODE();
122*c2c66affSColin Finck if (CompBattDebug & 1)
123*c2c66affSColin Finck DbgPrint("CompBatt: ENTERING AddNewBattery \"%w\" \n", BatteryName->Buffer);
124*c2c66affSColin Finck
125*c2c66affSColin Finck /* Is this a new battery? */
126*c2c66affSColin Finck if (!IsBatteryAlreadyOnList(BatteryName, DeviceExtension))
127*c2c66affSColin Finck {
128*c2c66affSColin Finck /* Allocate battery data */
129*c2c66affSColin Finck BatteryData = ExAllocatePoolWithTag(NonPagedPool,
130*c2c66affSColin Finck sizeof(COMPBATT_BATTERY_DATA) +
131*c2c66affSColin Finck BatteryName->Length,
132*c2c66affSColin Finck 'CtaB');
133*c2c66affSColin Finck if (BatteryData)
134*c2c66affSColin Finck {
135*c2c66affSColin Finck /* Initialize the data and write the battery name */
136*c2c66affSColin Finck RtlZeroMemory(BatteryData, sizeof(COMPBATT_BATTERY_DATA));
137*c2c66affSColin Finck BatteryData->Tag = 0;
138*c2c66affSColin Finck BatteryData->BatteryName.MaximumLength = BatteryName->Length;
139*c2c66affSColin Finck BatteryData->BatteryName.Buffer = (PWCHAR)(BatteryData + 1);
140*c2c66affSColin Finck RtlCopyUnicodeString(&BatteryData->BatteryName, BatteryName);
141*c2c66affSColin Finck
142*c2c66affSColin Finck /* Get the device object */
143*c2c66affSColin Finck Status = CompBattGetDeviceObjectPointer(BatteryName,
144*c2c66affSColin Finck FILE_ALL_ACCESS,
145*c2c66affSColin Finck &FileObject,
146*c2c66affSColin Finck &BatteryData->DeviceObject);
147*c2c66affSColin Finck if (NT_SUCCESS(Status))
148*c2c66affSColin Finck {
149*c2c66affSColin Finck /* Reference the DO and drop the FO */
150*c2c66affSColin Finck ObReferenceObject(BatteryData->DeviceObject);
151*c2c66affSColin Finck ObDereferenceObject(FileObject);
152*c2c66affSColin Finck
153*c2c66affSColin Finck /* Allocate the battery IRP */
154*c2c66affSColin Finck Irp = IoAllocateIrp(BatteryData->DeviceObject->StackSize + 1, 0);
155*c2c66affSColin Finck if (Irp)
156*c2c66affSColin Finck {
157*c2c66affSColin Finck /* Save it */
158*c2c66affSColin Finck BatteryData->Irp = Irp;
159*c2c66affSColin Finck
160*c2c66affSColin Finck /* Setup the stack location */
161*c2c66affSColin Finck IoStackLocation = IoGetNextIrpStackLocation(Irp);
162*c2c66affSColin Finck IoStackLocation->Parameters.Others.Argument1 = DeviceExtension;
163*c2c66affSColin Finck IoStackLocation->Parameters.Others.Argument2 = BatteryData;
164*c2c66affSColin Finck
165*c2c66affSColin Finck /* Set IRP data */
166*c2c66affSColin Finck IoSetNextIrpStackLocation(Irp);
167*c2c66affSColin Finck Irp->IoStatus.Status = STATUS_DEVICE_NOT_CONNECTED;
168*c2c66affSColin Finck BatteryData->WaitFlag = 0;
169*c2c66affSColin Finck
170*c2c66affSColin Finck /* Insert this battery in the list */
171*c2c66affSColin Finck ExAcquireFastMutex(&DeviceExtension->Lock);
172*c2c66affSColin Finck InsertTailList(&DeviceExtension->BatteryList,
173*c2c66affSColin Finck &BatteryData->BatteryLink);
174*c2c66affSColin Finck ExReleaseFastMutex(&DeviceExtension->Lock);
175*c2c66affSColin Finck
176*c2c66affSColin Finck /* Initialize the work item and delete lock */
177*c2c66affSColin Finck IoInitializeRemoveLock(&BatteryData->RemoveLock, 0, 0, 0);
178*c2c66affSColin Finck ExInitializeWorkItem(&BatteryData->WorkItem,
179*c2c66affSColin Finck (PVOID)CompBattMonitorIrpCompleteWorker,
180*c2c66affSColin Finck BatteryData);
181*c2c66affSColin Finck
182*c2c66affSColin Finck /* Setup the IRP work entry */
183*c2c66affSColin Finck CompBattMonitorIrpComplete(BatteryData->DeviceObject, Irp, 0);
184*c2c66affSColin Finck Status = STATUS_SUCCESS;
185*c2c66affSColin Finck }
186*c2c66affSColin Finck else
187*c2c66affSColin Finck {
188*c2c66affSColin Finck /* Fail, no memory */
189*c2c66affSColin Finck if (CompBattDebug & 8)
190*c2c66affSColin Finck DbgPrint("CompBatt: Couldn't allocate new battery Irp\n");
191*c2c66affSColin Finck Status = STATUS_INSUFFICIENT_RESOURCES;
192*c2c66affSColin Finck ObDereferenceObject(BatteryData->DeviceObject);
193*c2c66affSColin Finck }
194*c2c66affSColin Finck }
195*c2c66affSColin Finck else if (CompBattDebug & 8)
196*c2c66affSColin Finck {
197*c2c66affSColin Finck /* Fail */
198*c2c66affSColin Finck DbgPrint("CompBattAddNewBattery: Failed to get device Object. status = %lx\n",
199*c2c66affSColin Finck Status);
200*c2c66affSColin Finck }
201*c2c66affSColin Finck
202*c2c66affSColin Finck /* Free the battery data */
203*c2c66affSColin Finck ExFreePool(BatteryData);
204*c2c66affSColin Finck }
205*c2c66affSColin Finck else
206*c2c66affSColin Finck {
207*c2c66affSColin Finck /* Fail, no memory */
208*c2c66affSColin Finck if (CompBattDebug & 8)
209*c2c66affSColin Finck DbgPrint("CompBatt: Couldn't allocate new battery node\n");
210*c2c66affSColin Finck Status = STATUS_INSUFFICIENT_RESOURCES;
211*c2c66affSColin Finck }
212*c2c66affSColin Finck }
213*c2c66affSColin Finck
214*c2c66affSColin Finck /* We're done */
215*c2c66affSColin Finck if (CompBattDebug & 1) DbgPrint("CompBatt: EXITING AddNewBattery\n");
216*c2c66affSColin Finck return Status;
217*c2c66affSColin Finck }
218*c2c66affSColin Finck
219*c2c66affSColin Finck NTSTATUS
220*c2c66affSColin Finck NTAPI
CompBattRemoveBattery(IN PCUNICODE_STRING BatteryName,IN PCOMPBATT_DEVICE_EXTENSION DeviceExtension)221*c2c66affSColin Finck CompBattRemoveBattery(IN PCUNICODE_STRING BatteryName,
222*c2c66affSColin Finck IN PCOMPBATT_DEVICE_EXTENSION DeviceExtension)
223*c2c66affSColin Finck {
224*c2c66affSColin Finck PCOMPBATT_BATTERY_DATA BatteryData;
225*c2c66affSColin Finck if (CompBattDebug & 1) DbgPrint("CompBatt: RemoveBattery\n");
226*c2c66affSColin Finck
227*c2c66affSColin Finck /* Remove the entry */
228*c2c66affSColin Finck BatteryData = RemoveBatteryFromList(BatteryName, DeviceExtension);
229*c2c66affSColin Finck if (BatteryData)
230*c2c66affSColin Finck {
231*c2c66affSColin Finck /* Dereference and free it */
232*c2c66affSColin Finck ObDereferenceObject(BatteryData->DeviceObject);
233*c2c66affSColin Finck ExFreePool(BatteryData);
234*c2c66affSColin Finck
235*c2c66affSColin Finck /* Notify class driver */
236*c2c66affSColin Finck DeviceExtension->Flags = 0;
237*c2c66affSColin Finck BatteryClassStatusNotify(DeviceExtension->ClassData);
238*c2c66affSColin Finck }
239*c2c66affSColin Finck
240*c2c66affSColin Finck /* It's done */
241*c2c66affSColin Finck return STATUS_SUCCESS;
242*c2c66affSColin Finck }
243*c2c66affSColin Finck
244*c2c66affSColin Finck NTSTATUS
245*c2c66affSColin Finck NTAPI
CompBattGetBatteries(IN PCOMPBATT_DEVICE_EXTENSION DeviceExtension)246*c2c66affSColin Finck CompBattGetBatteries(IN PCOMPBATT_DEVICE_EXTENSION DeviceExtension)
247*c2c66affSColin Finck {
248*c2c66affSColin Finck PWCHAR p;
249*c2c66affSColin Finck NTSTATUS Status;
250*c2c66affSColin Finck PWCHAR LinkList;
251*c2c66affSColin Finck UNICODE_STRING LinkString;
252*c2c66affSColin Finck if (CompBattDebug & 1) DbgPrint("CompBatt: ENTERING GetBatteries\n");
253*c2c66affSColin Finck
254*c2c66affSColin Finck /* Get all battery links */
255*c2c66affSColin Finck Status = IoGetDeviceInterfaces(&GUID_DEVICE_BATTERY, NULL, 0, &LinkList);
256*c2c66affSColin Finck p = LinkList;
257*c2c66affSColin Finck if (NT_SUCCESS(Status))
258*c2c66affSColin Finck {
259*c2c66affSColin Finck /* Loop all strings inside */
260*c2c66affSColin Finck while (TRUE)
261*c2c66affSColin Finck {
262*c2c66affSColin Finck /* Create the string */
263*c2c66affSColin Finck RtlInitUnicodeString(&LinkString, p);
264*c2c66affSColin Finck if (!LinkString.Length) break;
265*c2c66affSColin Finck
266*c2c66affSColin Finck /* Add this battery and move on */
267*c2c66affSColin Finck Status = CompBattAddNewBattery(&LinkString, DeviceExtension);
268*c2c66affSColin Finck p += (LinkString.Length / sizeof(WCHAR)) + sizeof(UNICODE_NULL);
269*c2c66affSColin Finck }
270*c2c66affSColin Finck
271*c2c66affSColin Finck /* Parsing complete, clean up buffer */
272*c2c66affSColin Finck ExFreePool(LinkList);
273*c2c66affSColin Finck }
274*c2c66affSColin Finck else if (CompBattDebug & 8)
275*c2c66affSColin Finck {
276*c2c66affSColin Finck /* Fail */
277*c2c66affSColin Finck DbgPrint("CompBatt: Couldn't get list of batteries\n");
278*c2c66affSColin Finck }
279*c2c66affSColin Finck
280*c2c66affSColin Finck /* Done */
281*c2c66affSColin Finck if (CompBattDebug & 1) DbgPrint("CompBatt: EXITING GetBatteries\n");
282*c2c66affSColin Finck return Status;
283*c2c66affSColin Finck }
284*c2c66affSColin Finck
285*c2c66affSColin Finck NTSTATUS
286*c2c66affSColin Finck NTAPI
CompBattPnpEventHandler(IN PDEVICE_INTERFACE_CHANGE_NOTIFICATION Notification,IN PCOMPBATT_DEVICE_EXTENSION DeviceExtension)287*c2c66affSColin Finck CompBattPnpEventHandler(IN PDEVICE_INTERFACE_CHANGE_NOTIFICATION Notification,
288*c2c66affSColin Finck IN PCOMPBATT_DEVICE_EXTENSION DeviceExtension)
289*c2c66affSColin Finck {
290*c2c66affSColin Finck if (CompBattDebug & 1) DbgPrint("CompBatt: ENTERING PnpEventHandler\n");
291*c2c66affSColin Finck if (CompBattDebug & 2) DbgPrint("CompBatt: Received device interface change notification\n");
292*c2c66affSColin Finck
293*c2c66affSColin Finck /* Check what happened */
294*c2c66affSColin Finck if (IsEqualGUIDAligned(&Notification->Event, &GUID_DEVICE_INTERFACE_ARRIVAL))
295*c2c66affSColin Finck {
296*c2c66affSColin Finck /* Add the new battery */
297*c2c66affSColin Finck if (CompBattDebug & 2)
298*c2c66affSColin Finck DbgPrint("CompBatt: Received notification of battery arrival\n");
299*c2c66affSColin Finck CompBattAddNewBattery(Notification->SymbolicLinkName, DeviceExtension);
300*c2c66affSColin Finck }
301*c2c66affSColin Finck else if (IsEqualGUIDAligned(&Notification->Event, &GUID_DEVICE_INTERFACE_REMOVAL))
302*c2c66affSColin Finck {
303*c2c66affSColin Finck /* Don't do anything */
304*c2c66affSColin Finck if (CompBattDebug & 2)
305*c2c66affSColin Finck DbgPrint("CompBatt: Received notification of battery removal\n");
306*c2c66affSColin Finck }
307*c2c66affSColin Finck else
308*c2c66affSColin Finck {
309*c2c66affSColin Finck /* Shouldn't happen */
310*c2c66affSColin Finck if (CompBattDebug & 2) DbgPrint("CompBatt: Received unhandled PnP event\n");
311*c2c66affSColin Finck }
312*c2c66affSColin Finck
313*c2c66affSColin Finck /* Done, return success */
314*c2c66affSColin Finck if (CompBattDebug & 1) DbgPrint("CompBatt: EXITING PnpEventHandler\n");
315*c2c66affSColin Finck return STATUS_SUCCESS;
316*c2c66affSColin Finck }
317*c2c66affSColin Finck
318*c2c66affSColin Finck NTSTATUS
319*c2c66affSColin Finck NTAPI
CompBattAddDevice(IN PDRIVER_OBJECT DriverObject,IN PDEVICE_OBJECT PdoDeviceObject)320*c2c66affSColin Finck CompBattAddDevice(IN PDRIVER_OBJECT DriverObject,
321*c2c66affSColin Finck IN PDEVICE_OBJECT PdoDeviceObject)
322*c2c66affSColin Finck {
323*c2c66affSColin Finck NTSTATUS Status;
324*c2c66affSColin Finck UNICODE_STRING DeviceName;
325*c2c66affSColin Finck PCOMPBATT_DEVICE_EXTENSION DeviceExtension;
326*c2c66affSColin Finck PDEVICE_OBJECT DeviceObject;
327*c2c66affSColin Finck UNICODE_STRING SymbolicLinkName;
328*c2c66affSColin Finck BATTERY_MINIPORT_INFO MiniportInfo;
329*c2c66affSColin Finck if (CompBattDebug & 2) DbgPrint("CompBatt: Got an AddDevice - %x\n", PdoDeviceObject);
330*c2c66affSColin Finck
331*c2c66affSColin Finck /* Create the device */
332*c2c66affSColin Finck RtlInitUnicodeString(&DeviceName, L"\\Device\\CompositeBattery");
333*c2c66affSColin Finck Status = IoCreateDevice(DriverObject,
334*c2c66affSColin Finck sizeof(COMPBATT_DEVICE_EXTENSION),
335*c2c66affSColin Finck &DeviceName,
336*c2c66affSColin Finck FILE_DEVICE_BATTERY,
337*c2c66affSColin Finck FILE_DEVICE_SECURE_OPEN,
338*c2c66affSColin Finck FALSE,
339*c2c66affSColin Finck &DeviceObject);
340*c2c66affSColin Finck if (!NT_SUCCESS(Status)) return Status;
341*c2c66affSColin Finck
342*c2c66affSColin Finck /* Setup symbolic link for Win32 access */
343*c2c66affSColin Finck RtlInitUnicodeString(&SymbolicLinkName, L"\\DosDevices\\CompositeBattery");
344*c2c66affSColin Finck IoCreateSymbolicLink(&SymbolicLinkName, &DeviceName);
345*c2c66affSColin Finck
346*c2c66affSColin Finck /* Initialize the device extension */
347*c2c66affSColin Finck DeviceExtension = DeviceObject->DeviceExtension;
348*c2c66affSColin Finck RtlZeroMemory(DeviceExtension, sizeof(COMPBATT_DEVICE_EXTENSION));
349*c2c66affSColin Finck
350*c2c66affSColin Finck /* Attach to device stack and set DO pointers */
351*c2c66affSColin Finck DeviceExtension->AttachedDevice = IoAttachDeviceToDeviceStack(DeviceObject,
352*c2c66affSColin Finck PdoDeviceObject);
353*c2c66affSColin Finck DeviceExtension->DeviceObject = DeviceObject;
354*c2c66affSColin Finck if (!DeviceExtension->AttachedDevice)
355*c2c66affSColin Finck {
356*c2c66affSColin Finck /* Fail */
357*c2c66affSColin Finck if (CompBattDebug & 8)
358*c2c66affSColin Finck DbgPrint("CompBattAddDevice: Could not attach to LowerDevice.\n");
359*c2c66affSColin Finck IoDeleteDevice(DeviceObject);
360*c2c66affSColin Finck return STATUS_UNSUCCESSFUL;
361*c2c66affSColin Finck }
362*c2c66affSColin Finck
363*c2c66affSColin Finck /* Set device object flags */
364*c2c66affSColin Finck DeviceObject->Flags |= (DO_POWER_PAGABLE | DO_BUFFERED_IO);
365*c2c66affSColin Finck DeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
366*c2c66affSColin Finck
367*c2c66affSColin Finck /* Setup the device extension */
368*c2c66affSColin Finck ExInitializeFastMutex(&DeviceExtension->Lock);
369*c2c66affSColin Finck InitializeListHead(&DeviceExtension->BatteryList);
370*c2c66affSColin Finck DeviceExtension->Flags = 0;
371*c2c66affSColin Finck DeviceExtension->NextTag = 1;
372*c2c66affSColin Finck
373*c2c66affSColin Finck /* Setup the miniport data */
374*c2c66affSColin Finck RtlZeroMemory(&MiniportInfo, sizeof(MiniportInfo));
375*c2c66affSColin Finck MiniportInfo.MajorVersion = BATTERY_CLASS_MAJOR_VERSION;
376*c2c66affSColin Finck MiniportInfo.MinorVersion = BATTERY_CLASS_MINOR_VERSION;
377*c2c66affSColin Finck MiniportInfo.Context = DeviceExtension;
378*c2c66affSColin Finck MiniportInfo.DeviceName = &DeviceName;
379*c2c66affSColin Finck MiniportInfo.QueryTag = (BCLASS_QUERY_TAG)CompBattQueryTag;
380*c2c66affSColin Finck MiniportInfo.QueryInformation = (BCLASS_QUERY_INFORMATION)CompBattQueryInformation;
381*c2c66affSColin Finck MiniportInfo.SetInformation = NULL;
382*c2c66affSColin Finck MiniportInfo.QueryStatus = (BCLASS_QUERY_STATUS)CompBattQueryStatus;
383*c2c66affSColin Finck MiniportInfo.SetStatusNotify = (BCLASS_SET_STATUS_NOTIFY)CompBattSetStatusNotify;
384*c2c66affSColin Finck MiniportInfo.DisableStatusNotify = (BCLASS_DISABLE_STATUS_NOTIFY)CompBattDisableStatusNotify;
385*c2c66affSColin Finck MiniportInfo.Pdo = NULL;
386*c2c66affSColin Finck
387*c2c66affSColin Finck /* Register with the class driver */
388*c2c66affSColin Finck Status = BatteryClassInitializeDevice(&MiniportInfo,
389*c2c66affSColin Finck &DeviceExtension->ClassData);
390*c2c66affSColin Finck if (!NT_SUCCESS(Status))
391*c2c66affSColin Finck {
392*c2c66affSColin Finck /* Undo everything */
393*c2c66affSColin Finck IoDetachDevice(DeviceExtension->AttachedDevice);
394*c2c66affSColin Finck IoDeleteDevice(DeviceObject);
395*c2c66affSColin Finck }
396*c2c66affSColin Finck
397*c2c66affSColin Finck /* Return status */
398*c2c66affSColin Finck return Status;
399*c2c66affSColin Finck }
400*c2c66affSColin Finck
401*c2c66affSColin Finck NTSTATUS
402*c2c66affSColin Finck NTAPI
CompBattPnpDispatch(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)403*c2c66affSColin Finck CompBattPnpDispatch(IN PDEVICE_OBJECT DeviceObject,
404*c2c66affSColin Finck IN PIRP Irp)
405*c2c66affSColin Finck {
406*c2c66affSColin Finck PIO_STACK_LOCATION IoStackLocation = IoGetCurrentIrpStackLocation(Irp);
407*c2c66affSColin Finck NTSTATUS Status;
408*c2c66affSColin Finck PCOMPBATT_DEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
409*c2c66affSColin Finck if (CompBattDebug & 1) DbgPrint("CompBatt: ENTERING PnpDispatch\n");
410*c2c66affSColin Finck
411*c2c66affSColin Finck /* Set default error */
412*c2c66affSColin Finck Status = STATUS_NOT_SUPPORTED;
413*c2c66affSColin Finck
414*c2c66affSColin Finck /* Check what kind of PnP function this is */
415*c2c66affSColin Finck switch (IoStackLocation->MinorFunction)
416*c2c66affSColin Finck {
417*c2c66affSColin Finck case IRP_MN_START_DEVICE:
418*c2c66affSColin Finck
419*c2c66affSColin Finck /* Device is starting, register for new batteries and pick up current ones */
420*c2c66affSColin Finck Status = IoRegisterPlugPlayNotification(EventCategoryDeviceInterfaceChange,
421*c2c66affSColin Finck 0,
422*c2c66affSColin Finck (PVOID)&GUID_DEVICE_BATTERY,
423*c2c66affSColin Finck DeviceObject->DriverObject,
424*c2c66affSColin Finck (PDRIVER_NOTIFICATION_CALLBACK_ROUTINE)CompBattPnpEventHandler,
425*c2c66affSColin Finck DeviceExtension,
426*c2c66affSColin Finck &DeviceExtension->NotificationEntry);
427*c2c66affSColin Finck if (NT_SUCCESS(Status))
428*c2c66affSColin Finck {
429*c2c66affSColin Finck /* Now go get the batteries */
430*c2c66affSColin Finck if (CompBattDebug & 2)
431*c2c66affSColin Finck DbgPrint("CompBatt: Successfully registered for PnP notification\n");
432*c2c66affSColin Finck Status = CompBattGetBatteries(DeviceExtension);
433*c2c66affSColin Finck }
434*c2c66affSColin Finck else
435*c2c66affSColin Finck {
436*c2c66affSColin Finck /* We failed */
437*c2c66affSColin Finck if (CompBattDebug & 8)
438*c2c66affSColin Finck DbgPrint("CompBatt: Couldn't register for PnP notification - %x\n",
439*c2c66affSColin Finck Status);
440*c2c66affSColin Finck }
441*c2c66affSColin Finck break;
442*c2c66affSColin Finck case IRP_MN_CANCEL_STOP_DEVICE:
443*c2c66affSColin Finck
444*c2c66affSColin Finck /* Explicitly say ok */
445*c2c66affSColin Finck Status = STATUS_SUCCESS;
446*c2c66affSColin Finck break;
447*c2c66affSColin Finck
448*c2c66affSColin Finck case IRP_MN_CANCEL_REMOVE_DEVICE:
449*c2c66affSColin Finck
450*c2c66affSColin Finck /* Explicitly say ok */
451*c2c66affSColin Finck Status = STATUS_SUCCESS;
452*c2c66affSColin Finck break;
453*c2c66affSColin Finck
454*c2c66affSColin Finck case IRP_MN_SURPRISE_REMOVAL:
455*c2c66affSColin Finck
456*c2c66affSColin Finck /* Explicitly say ok */
457*c2c66affSColin Finck Status = STATUS_SUCCESS;
458*c2c66affSColin Finck break;
459*c2c66affSColin Finck
460*c2c66affSColin Finck case IRP_MN_QUERY_PNP_DEVICE_STATE:
461*c2c66affSColin Finck
462*c2c66affSColin Finck /* Add this in */
463*c2c66affSColin Finck Irp->IoStatus.Information |= PNP_DEVICE_NOT_DISABLEABLE;
464*c2c66affSColin Finck Status = STATUS_SUCCESS;
465*c2c66affSColin Finck break;
466*c2c66affSColin Finck
467*c2c66affSColin Finck default:
468*c2c66affSColin Finck
469*c2c66affSColin Finck /* Not supported */
470*c2c66affSColin Finck Status = STATUS_INVALID_DEVICE_REQUEST;
471*c2c66affSColin Finck break;
472*c2c66affSColin Finck }
473*c2c66affSColin Finck
474*c2c66affSColin Finck /* Set IRP status if we have one */
475*c2c66affSColin Finck if (Status != STATUS_NOT_SUPPORTED) Irp->IoStatus.Status = Status;
476*c2c66affSColin Finck
477*c2c66affSColin Finck /* Did someone pick it up? */
478*c2c66affSColin Finck if ((NT_SUCCESS(Status)) || (Status == STATUS_NOT_SUPPORTED))
479*c2c66affSColin Finck {
480*c2c66affSColin Finck /* Still unsupported, try ACPI */
481*c2c66affSColin Finck IoSkipCurrentIrpStackLocation(Irp);
482*c2c66affSColin Finck Status = IoCallDriver(DeviceExtension->AttachedDevice, Irp);
483*c2c66affSColin Finck }
484*c2c66affSColin Finck else
485*c2c66affSColin Finck {
486*c2c66affSColin Finck /* Complete the request */
487*c2c66affSColin Finck Status = Irp->IoStatus.Status;
488*c2c66affSColin Finck IoCompleteRequest(Irp, IO_NO_INCREMENT);
489*c2c66affSColin Finck }
490*c2c66affSColin Finck
491*c2c66affSColin Finck /* Release the remove lock and return status */
492*c2c66affSColin Finck if (CompBattDebug & 1) DbgPrint("CompBatt: EXITING PnpDispatch\n");
493*c2c66affSColin Finck return Status;
494*c2c66affSColin Finck }
495*c2c66affSColin Finck
496*c2c66affSColin Finck /* EOF */
497