Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygencomppnp.c
Go to the documentation of this file.
00001 /* 00002 * PROJECT: ReactOS Composite Battery Driver 00003 * LICENSE: BSD - See COPYING.ARM in the top level directory 00004 * FILE: boot/drivers/bus/acpi/compbatt/comppnp.c 00005 * PURPOSE: Plug-and-Play IOCTL/IRP Handling 00006 * PROGRAMMERS: ReactOS Portable Systems Group 00007 */ 00008 00009 /* INCLUDES *******************************************************************/ 00010 00011 #include "compbatt.h" 00012 00013 /* FUNCTIONS ******************************************************************/ 00014 00015 NTSTATUS 00016 NTAPI 00017 CompBattPowerDispatch(IN PDEVICE_OBJECT DeviceObject, 00018 IN PIRP Irp) 00019 { 00020 PCOMPBATT_DEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension; 00021 if (CompBattDebug & 1) DbgPrint("CompBatt: PowerDispatch recieved power IRP.\n"); 00022 00023 /* Start the next IRP */ 00024 PoStartNextPowerIrp(Irp); 00025 00026 /* Call the next driver in the stack */ 00027 IoSkipCurrentIrpStackLocation(Irp); 00028 return PoCallDriver(DeviceExtension->AttachedDevice, Irp); 00029 } 00030 00031 PCOMPBATT_BATTERY_DATA 00032 NTAPI 00033 RemoveBatteryFromList(IN PCUNICODE_STRING BatteryName, 00034 IN PCOMPBATT_DEVICE_EXTENSION DeviceExtension) 00035 { 00036 PLIST_ENTRY ListHead, NextEntry; 00037 PCOMPBATT_BATTERY_DATA BatteryData; 00038 if (CompBattDebug & 1) 00039 DbgPrint("CompBatt: ENTERING RemoveBatteryFromList\n"); 00040 00041 /* Loop the battery list */ 00042 ExAcquireFastMutex(&DeviceExtension->Lock); 00043 ListHead = &DeviceExtension->BatteryList; 00044 NextEntry = ListHead->Flink; 00045 while (NextEntry != ListHead) 00046 { 00047 /* Get the battery information and compare the name */ 00048 BatteryData = CONTAINING_RECORD(NextEntry, COMPBATT_BATTERY_DATA, BatteryLink); 00049 if (!RtlCompareUnicodeString(BatteryName, &BatteryData->BatteryName, TRUE)) 00050 { 00051 /* Flush pending deletes and any lock waiters */ 00052 IoAcquireRemoveLock(&BatteryData->RemoveLock, 0); 00053 ExReleaseFastMutex(&DeviceExtension->Lock); 00054 IoReleaseRemoveLockAndWait(&BatteryData->RemoveLock, 0); 00055 00056 /* Remove the entry from the list */ 00057 ExAcquireFastMutex(&DeviceExtension->Lock); 00058 RemoveEntryList(&BatteryData->BatteryLink); 00059 ExReleaseFastMutex(&DeviceExtension->Lock); 00060 return BatteryData; 00061 } 00062 00063 /* Next */ 00064 NextEntry = NextEntry->Flink; 00065 } 00066 00067 /* Done */ 00068 ExReleaseFastMutex(&DeviceExtension->Lock); 00069 if (CompBattDebug & 1) DbgPrint("CompBatt: EXITING RemoveBatteryFromList\n"); 00070 return STATUS_SUCCESS; 00071 } 00072 00073 BOOLEAN 00074 NTAPI 00075 IsBatteryAlreadyOnList(IN PCUNICODE_STRING BatteryName, 00076 IN PCOMPBATT_DEVICE_EXTENSION DeviceExtension) 00077 { 00078 PLIST_ENTRY ListHead, NextEntry; 00079 PCOMPBATT_BATTERY_DATA BatteryData; 00080 BOOLEAN Found = FALSE; 00081 if (CompBattDebug & 1) 00082 DbgPrint("CompBatt: ENTERING IsBatteryAlreadyOnList\n"); 00083 00084 /* Loop the battery list */ 00085 ExAcquireFastMutex(&DeviceExtension->Lock); 00086 ListHead = &DeviceExtension->BatteryList; 00087 NextEntry = ListHead->Flink; 00088 while (NextEntry != ListHead) 00089 { 00090 /* Get the battery information and compare the name */ 00091 BatteryData = CONTAINING_RECORD(NextEntry, COMPBATT_BATTERY_DATA, BatteryLink); 00092 if (!RtlCompareUnicodeString(BatteryName, &BatteryData->BatteryName, TRUE)) 00093 { 00094 /* Got it */ 00095 Found = TRUE; 00096 break; 00097 } 00098 00099 /* Next */ 00100 NextEntry = NextEntry->Flink; 00101 } 00102 00103 /* Release the lock and return search status */ 00104 ExReleaseFastMutex(&DeviceExtension->Lock); 00105 if (CompBattDebug & 1) DbgPrint("CompBatt: EXITING IsBatteryAlreadyOnList\n"); 00106 return Found; 00107 } 00108 00109 NTSTATUS 00110 NTAPI 00111 CompBattAddNewBattery(IN PUNICODE_STRING BatteryName, 00112 IN PCOMPBATT_DEVICE_EXTENSION DeviceExtension) 00113 { 00114 NTSTATUS Status = STATUS_SUCCESS; 00115 PCOMPBATT_BATTERY_DATA BatteryData; 00116 PIRP Irp; 00117 PIO_STACK_LOCATION IoStackLocation; 00118 PFILE_OBJECT FileObject; 00119 PAGED_CODE(); 00120 if (CompBattDebug & 1) 00121 DbgPrint("CompBatt: ENTERING AddNewBattery \"%w\" \n", BatteryName->Buffer); 00122 00123 /* Is this a new battery? */ 00124 if (!IsBatteryAlreadyOnList(BatteryName, DeviceExtension)) 00125 { 00126 /* Allocate battery data */ 00127 BatteryData = ExAllocatePoolWithTag(NonPagedPool, 00128 sizeof(COMPBATT_BATTERY_DATA) + 00129 BatteryName->Length, 00130 'CtaB'); 00131 if (BatteryData) 00132 { 00133 /* Initialize the data and write the battery name */ 00134 RtlZeroMemory(BatteryData, sizeof(COMPBATT_BATTERY_DATA)); 00135 BatteryData->Tag = 0; 00136 BatteryData->BatteryName.MaximumLength = BatteryName->Length; 00137 BatteryData->BatteryName.Buffer = (PWCHAR)(BatteryData + 1); 00138 RtlCopyUnicodeString(&BatteryData->BatteryName, BatteryName); 00139 00140 /* Get the device object */ 00141 Status = CompBattGetDeviceObjectPointer(BatteryName, 00142 FILE_ALL_ACCESS, 00143 &FileObject, 00144 &BatteryData->DeviceObject); 00145 if (NT_SUCCESS(Status)) 00146 { 00147 /* Reference the DO and drop the FO */ 00148 ObReferenceObject(BatteryData->DeviceObject); 00149 ObDereferenceObject(FileObject); 00150 00151 /* Allocate the battery IRP */ 00152 Irp = IoAllocateIrp(BatteryData->DeviceObject->StackSize + 1, 0); 00153 if (Irp) 00154 { 00155 /* Save it */ 00156 BatteryData->Irp = Irp; 00157 00158 /* Setup the stack location */ 00159 IoStackLocation = IoGetNextIrpStackLocation(Irp); 00160 IoStackLocation->Parameters.Others.Argument1 = DeviceExtension; 00161 IoStackLocation->Parameters.Others.Argument2 = BatteryData; 00162 00163 /* Set IRP data */ 00164 IoSetNextIrpStackLocation(Irp); 00165 Irp->IoStatus.Status = STATUS_DEVICE_NOT_CONNECTED; 00166 BatteryData->WaitFlag = 0; 00167 00168 /* Insert this battery in the list */ 00169 ExAcquireFastMutex(&DeviceExtension->Lock); 00170 InsertTailList(&DeviceExtension->BatteryList, 00171 &BatteryData->BatteryLink); 00172 ExReleaseFastMutex(&DeviceExtension->Lock); 00173 00174 /* Initialize the work item and delete lock */ 00175 IoInitializeRemoveLock(&BatteryData->RemoveLock, 0, 0, 0); 00176 ExInitializeWorkItem(&BatteryData->WorkItem, 00177 (PVOID)CompBattMonitorIrpCompleteWorker, 00178 BatteryData); 00179 00180 /* Setup the IRP work entry */ 00181 CompBattMonitorIrpComplete(BatteryData->DeviceObject, Irp, 0); 00182 Status = STATUS_SUCCESS; 00183 } 00184 else 00185 { 00186 /* Fail, no memory */ 00187 if (CompBattDebug & 8) 00188 DbgPrint("CompBatt: Couldn't allocate new battery Irp\n"); 00189 Status = STATUS_INSUFFICIENT_RESOURCES; 00190 ObDereferenceObject(BatteryData->DeviceObject); 00191 } 00192 } 00193 else if (CompBattDebug & 8) 00194 { 00195 /* Fail */ 00196 DbgPrint("CompBattAddNewBattery: Failed to get device Object. status = %lx\n", 00197 Status); 00198 } 00199 00200 /* Free the battery data */ 00201 ExFreePool(BatteryData); 00202 } 00203 else 00204 { 00205 /* Fail, no memory */ 00206 if (CompBattDebug & 8) 00207 DbgPrint("CompBatt: Couldn't allocate new battery node\n"); 00208 Status = STATUS_INSUFFICIENT_RESOURCES; 00209 } 00210 } 00211 00212 /* We're done */ 00213 if (CompBattDebug & 1) DbgPrint("CompBatt: EXITING AddNewBattery\n"); 00214 return Status; 00215 } 00216 00217 NTSTATUS 00218 NTAPI 00219 CompBattRemoveBattery(IN PCUNICODE_STRING BatteryName, 00220 IN PCOMPBATT_DEVICE_EXTENSION DeviceExtension) 00221 { 00222 PCOMPBATT_BATTERY_DATA BatteryData; 00223 if (CompBattDebug & 1) DbgPrint("CompBatt: RemoveBattery\n"); 00224 00225 /* Remove the entry */ 00226 BatteryData = RemoveBatteryFromList(BatteryName, DeviceExtension); 00227 if (BatteryData) 00228 { 00229 /* Dereference and free it */ 00230 ObDereferenceObject(BatteryData->DeviceObject); 00231 ExFreePool(BatteryData); 00232 00233 /* Notify class driver */ 00234 DeviceExtension->Flags = 0; 00235 BatteryClassStatusNotify(DeviceExtension->ClassData); 00236 } 00237 00238 /* It's done */ 00239 return STATUS_SUCCESS; 00240 } 00241 00242 NTSTATUS 00243 NTAPI 00244 CompBattGetBatteries(IN PCOMPBATT_DEVICE_EXTENSION DeviceExtension) 00245 { 00246 PWCHAR p; 00247 NTSTATUS Status; 00248 PWCHAR LinkList; 00249 UNICODE_STRING LinkString; 00250 if (CompBattDebug & 1) DbgPrint("CompBatt: ENTERING GetBatteries\n"); 00251 00252 /* Get all battery links */ 00253 Status = IoGetDeviceInterfaces(&GUID_DEVICE_BATTERY, NULL, 0, &LinkList); 00254 p = LinkList; 00255 if (NT_SUCCESS(Status)) 00256 { 00257 /* Loop all strings inside */ 00258 while (TRUE) 00259 { 00260 /* Create the string */ 00261 RtlInitUnicodeString(&LinkString, p); 00262 if (!LinkString.Length) break; 00263 00264 /* Add this battery and move on */ 00265 Status = CompBattAddNewBattery(&LinkString, DeviceExtension); 00266 p += (LinkString.Length / sizeof(WCHAR)) + sizeof(UNICODE_NULL); 00267 } 00268 00269 /* Parsing complete, clean up buffer */ 00270 ExFreePool(LinkList); 00271 } 00272 else if (CompBattDebug & 8) 00273 { 00274 /* Fail */ 00275 DbgPrint("CompBatt: Couldn't get list of batteries\n"); 00276 } 00277 00278 /* Done */ 00279 if (CompBattDebug & 1) DbgPrint("CompBatt: EXITING GetBatteries\n"); 00280 return Status; 00281 } 00282 00283 NTSTATUS 00284 NTAPI 00285 CompBattPnpEventHandler(IN PDEVICE_INTERFACE_CHANGE_NOTIFICATION Notification, 00286 IN PCOMPBATT_DEVICE_EXTENSION DeviceExtension) 00287 { 00288 if (CompBattDebug & 1) DbgPrint("CompBatt: ENTERING PnpEventHandler\n"); 00289 if (CompBattDebug & 2) DbgPrint("CompBatt: Received device interface change notification\n"); 00290 00291 /* Check what happened */ 00292 if (IsEqualGUIDAligned(&Notification->Event, &GUID_DEVICE_INTERFACE_ARRIVAL)) 00293 { 00294 /* Add the new battery */ 00295 if (CompBattDebug & 2) 00296 DbgPrint("CompBatt: Received notification of battery arrival\n"); 00297 CompBattAddNewBattery(Notification->SymbolicLinkName, DeviceExtension); 00298 } 00299 else if (IsEqualGUIDAligned(&Notification->Event, &GUID_DEVICE_INTERFACE_REMOVAL)) 00300 { 00301 /* Don't do anything */ 00302 if (CompBattDebug & 2) 00303 DbgPrint("CompBatt: Received notification of battery removal\n"); 00304 } 00305 else 00306 { 00307 /* Shouldn't happen */ 00308 if (CompBattDebug & 2) DbgPrint("CompBatt: Received unhandled PnP event\n"); 00309 } 00310 00311 /* Done, return success */ 00312 if (CompBattDebug & 1) DbgPrint("CompBatt: EXITING PnpEventHandler\n"); 00313 return STATUS_SUCCESS; 00314 } 00315 00316 NTSTATUS 00317 NTAPI 00318 CompBattAddDevice(IN PDRIVER_OBJECT DriverObject, 00319 IN PDEVICE_OBJECT PdoDeviceObject) 00320 { 00321 NTSTATUS Status; 00322 UNICODE_STRING DeviceName; 00323 PCOMPBATT_DEVICE_EXTENSION DeviceExtension; 00324 PDEVICE_OBJECT DeviceObject; 00325 UNICODE_STRING SymbolicLinkName; 00326 BATTERY_MINIPORT_INFO MiniportInfo; 00327 if (CompBattDebug & 2) DbgPrint("CompBatt: Got an AddDevice - %x\n", PdoDeviceObject); 00328 00329 /* Create the device */ 00330 RtlInitUnicodeString(&DeviceName, L"\\Device\\CompositeBattery"); 00331 Status = IoCreateDevice(DriverObject, 00332 sizeof(COMPBATT_DEVICE_EXTENSION), 00333 &DeviceName, 00334 FILE_DEVICE_BATTERY, 00335 FILE_DEVICE_SECURE_OPEN, 00336 FALSE, 00337 &DeviceObject); 00338 if (!NT_SUCCESS(Status)) return Status; 00339 00340 /* Setup symbolic link for Win32 access */ 00341 RtlInitUnicodeString(&SymbolicLinkName, L"\\DosDevices\\CompositeBattery"); 00342 IoCreateSymbolicLink(&SymbolicLinkName, &DeviceName); 00343 00344 /* Initialize the device extension */ 00345 DeviceExtension = DeviceObject->DeviceExtension; 00346 RtlZeroMemory(DeviceExtension, 0x1B0u); 00347 00348 /* Attach to device stack and set DO pointers */ 00349 DeviceExtension->AttachedDevice = IoAttachDeviceToDeviceStack(DeviceObject, 00350 PdoDeviceObject); 00351 DeviceExtension->DeviceObject = DeviceObject; 00352 if (!DeviceExtension->AttachedDevice) 00353 { 00354 /* Fail */ 00355 if (CompBattDebug & 8) 00356 DbgPrint("CompBattAddDevice: Could not attach to LowerDevice.\n"); 00357 IoDeleteDevice(DeviceObject); 00358 return STATUS_UNSUCCESSFUL; 00359 } 00360 00361 /* Set device object flags */ 00362 DeviceObject->Flags |= (DO_POWER_PAGABLE | DO_BUFFERED_IO); 00363 DeviceObject->Flags &= ~DO_DEVICE_INITIALIZING; 00364 00365 /* Setup the device extension */ 00366 ExInitializeFastMutex(&DeviceExtension->Lock); 00367 InitializeListHead(&DeviceExtension->BatteryList); 00368 DeviceExtension->Flags = 0; 00369 DeviceExtension->NextTag = 1; 00370 00371 /* Setup the miniport data */ 00372 RtlZeroMemory(&MiniportInfo, sizeof(MiniportInfo)); 00373 MiniportInfo.MajorVersion = BATTERY_CLASS_MAJOR_VERSION; 00374 MiniportInfo.MinorVersion = BATTERY_CLASS_MINOR_VERSION; 00375 MiniportInfo.Context = DeviceExtension; 00376 MiniportInfo.DeviceName = &DeviceName; 00377 MiniportInfo.QueryTag = (BCLASS_QUERY_TAG)CompBattQueryTag; 00378 MiniportInfo.QueryInformation = (BCLASS_QUERY_INFORMATION)CompBattQueryInformation; 00379 MiniportInfo.SetInformation = NULL; 00380 MiniportInfo.QueryStatus = (BCLASS_QUERY_STATUS)CompBattQueryStatus; 00381 MiniportInfo.SetStatusNotify = (BCLASS_SET_STATUS_NOTIFY)CompBattSetStatusNotify; 00382 MiniportInfo.DisableStatusNotify = (BCLASS_DISABLE_STATUS_NOTIFY)CompBattDisableStatusNotify; 00383 MiniportInfo.Pdo = NULL; 00384 00385 /* Register with the class driver */ 00386 Status = BatteryClassInitializeDevice(&MiniportInfo, 00387 &DeviceExtension->ClassData); 00388 if (!NT_SUCCESS(Status)) 00389 { 00390 /* Undo everything */ 00391 IoDetachDevice(DeviceExtension->AttachedDevice); 00392 IoDeleteDevice(DeviceObject); 00393 } 00394 00395 /* Return status */ 00396 return Status; 00397 } 00398 00399 NTSTATUS 00400 NTAPI 00401 CompBattPnpDispatch(IN PDEVICE_OBJECT DeviceObject, 00402 IN PIRP Irp) 00403 { 00404 PIO_STACK_LOCATION IoStackLocation = IoGetCurrentIrpStackLocation(Irp); 00405 NTSTATUS Status; 00406 PCOMPBATT_DEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension; 00407 if (CompBattDebug & 1) DbgPrint("CompBatt: ENTERING PnpDispatch\n"); 00408 00409 /* Set default error */ 00410 Status = STATUS_NOT_SUPPORTED; 00411 00412 /* Check what kind of PnP function this is */ 00413 switch (IoStackLocation->MinorFunction) 00414 { 00415 case IRP_MN_START_DEVICE: 00416 00417 /* Device is starting, register for new batteries and pick up current ones */ 00418 Status = IoRegisterPlugPlayNotification(EventCategoryDeviceInterfaceChange, 00419 0, 00420 (PVOID)&GUID_DEVICE_BATTERY, 00421 DeviceObject->DriverObject, 00422 (PDRIVER_NOTIFICATION_CALLBACK_ROUTINE)CompBattPnpEventHandler, 00423 DeviceExtension, 00424 &DeviceExtension->NotificationEntry); 00425 if (NT_SUCCESS(Status)) 00426 { 00427 /* Now go get the batteries */ 00428 if (CompBattDebug & 2) 00429 DbgPrint("CompBatt: Successfully registered for PnP notification\n"); 00430 Status = CompBattGetBatteries(DeviceExtension); 00431 } 00432 else 00433 { 00434 /* We failed */ 00435 if (CompBattDebug & 8) 00436 DbgPrint("CompBatt: Couldn't register for PnP notification - %x\n", 00437 Status); 00438 } 00439 break; 00440 case IRP_MN_CANCEL_STOP_DEVICE: 00441 00442 /* Explicitly say ok */ 00443 Status = STATUS_SUCCESS; 00444 break; 00445 00446 case IRP_MN_CANCEL_REMOVE_DEVICE: 00447 00448 /* Explicitly say ok */ 00449 Status = STATUS_SUCCESS; 00450 break; 00451 00452 case IRP_MN_SURPRISE_REMOVAL: 00453 00454 /* Explicitly say ok */ 00455 Status = STATUS_SUCCESS; 00456 break; 00457 00458 case IRP_MN_QUERY_PNP_DEVICE_STATE: 00459 00460 /* Add this in */ 00461 Irp->IoStatus.Information |= PNP_DEVICE_NOT_DISABLEABLE; 00462 Status = STATUS_SUCCESS; 00463 break; 00464 00465 default: 00466 00467 /* Not supported */ 00468 Status = STATUS_INVALID_DEVICE_REQUEST; 00469 break; 00470 } 00471 00472 /* Set IRP status if we have one */ 00473 if (Status != STATUS_NOT_SUPPORTED) Irp->IoStatus.Status = Status; 00474 00475 /* Did someone pick it up? */ 00476 if ((NT_SUCCESS(Status)) || (Status == STATUS_NOT_SUPPORTED)) 00477 { 00478 /* Still unsupported, try ACPI */ 00479 IoSkipCurrentIrpStackLocation(Irp); 00480 Status = IoCallDriver(DeviceExtension->AttachedDevice, Irp); 00481 } 00482 else 00483 { 00484 /* Complete the request */ 00485 Status = Irp->IoStatus.Status; 00486 IoCompleteRequest(Irp, IO_NO_INCREMENT); 00487 } 00488 00489 /* Release the remove lock and return status */ 00490 if (CompBattDebug & 1) DbgPrint("CompBatt: EXITING PnpDispatch\n"); 00491 return Status; 00492 } 00493 00494 /* EOF */ Generated on Sun May 27 2012 04:27:25 for ReactOS by
1.7.6.1
|