Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenbeep.c
Go to the documentation of this file.
00001 /* 00002 * PROJECT: ReactOS Kernel 00003 * LICENSE: GPL - See COPYING in the top level directory 00004 * FILE: drivers/base/beep/beep.c 00005 * PURPOSE: Beep Device Driver 00006 * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org) 00007 * Eric Kohl 00008 */ 00009 00010 /* INCLUDES ******************************************************************/ 00011 00012 #include <ntddk.h> 00013 #include <ntddbeep.h> 00014 #ifndef NDEBUG 00015 #define NDEBUG 00016 #endif 00017 #include <debug.h> 00018 00019 /* TYPES *********************************************************************/ 00020 00021 typedef struct _BEEP_DEVICE_EXTENSION 00022 { 00023 LONG ReferenceCount; 00024 FAST_MUTEX Mutex; 00025 KTIMER Timer; 00026 LONG TimerActive; 00027 PVOID SectionHandle; 00028 } DEVICE_EXTENSION, *PDEVICE_EXTENSION; 00029 00030 /* FUNCTIONS *****************************************************************/ 00031 00032 VOID 00033 NTAPI 00034 BeepDPC(IN PKDPC Dpc, 00035 IN PDEVICE_OBJECT DeviceObject, 00036 IN PVOID SystemArgument1, 00037 IN PVOID SystemArgument2) 00038 { 00039 PDEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension; 00040 00041 /* Stop the beep */ 00042 HalMakeBeep(0); 00043 00044 /* Disable the timer */ 00045 InterlockedDecrement(&DeviceExtension->TimerActive); 00046 } 00047 00048 DRIVER_DISPATCH BeepCreate; 00049 NTSTATUS 00050 NTAPI 00051 BeepCreate(IN PDEVICE_OBJECT DeviceObject, 00052 IN PIRP Irp) 00053 { 00054 PDEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension; 00055 00056 /* Acquire the mutex and increase reference count */ 00057 ExAcquireFastMutex(&DeviceExtension->Mutex); 00058 if (++DeviceExtension->ReferenceCount == 1) 00059 { 00060 /* First reference, lock the data section */ 00061 DeviceExtension->SectionHandle = MmLockPagableDataSection(BeepCreate); 00062 } 00063 00064 /* Release it */ 00065 ExReleaseFastMutex(&DeviceExtension->Mutex); 00066 00067 /* Complete the request */ 00068 Irp->IoStatus.Status = STATUS_SUCCESS; 00069 Irp->IoStatus.Information = 0; 00070 IoCompleteRequest(Irp, IO_NO_INCREMENT); 00071 return STATUS_SUCCESS; 00072 } 00073 00074 DRIVER_DISPATCH BeepClose; 00075 NTSTATUS 00076 NTAPI 00077 BeepClose(IN PDEVICE_OBJECT DeviceObject, 00078 IN PIRP Irp) 00079 { 00080 PDEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension; 00081 00082 /* Acquire the mutex and decrease reference count */ 00083 ExAcquireFastMutex(&DeviceExtension->Mutex); 00084 if (!(--DeviceExtension->ReferenceCount)) 00085 { 00086 /* Check for active timer */ 00087 if (DeviceExtension->TimerActive) 00088 { 00089 /* Cancel it */ 00090 if (KeCancelTimer(&DeviceExtension->Timer)) 00091 { 00092 /* Mark it as cancelled */ 00093 InterlockedDecrement(&DeviceExtension->TimerActive); 00094 } 00095 } 00096 00097 /* Page the driver */ 00098 MmUnlockPagableImageSection(DeviceExtension->SectionHandle); 00099 } 00100 00101 /* Release the lock */ 00102 ExReleaseFastMutex(&DeviceExtension->Mutex); 00103 00104 /* Complete the request */ 00105 Irp->IoStatus.Status = STATUS_SUCCESS; 00106 Irp->IoStatus.Information = 0; 00107 IoCompleteRequest(Irp, IO_NO_INCREMENT); 00108 return STATUS_SUCCESS; 00109 } 00110 00111 DRIVER_CANCEL BeepCancel; 00112 VOID 00113 NTAPI 00114 BeepCancel(IN PDEVICE_OBJECT DeviceObject, 00115 IN PIRP Irp) 00116 { 00117 /* Check if this is the current request */ 00118 if (Irp == DeviceObject->CurrentIrp) 00119 { 00120 /* Clear it */ 00121 DeviceObject->CurrentIrp = NULL; 00122 00123 /* Release the cancel lock and start the next packet */ 00124 IoReleaseCancelSpinLock(Irp->CancelIrql); 00125 IoStartNextPacket(DeviceObject, TRUE); 00126 } 00127 else 00128 { 00129 /* Otherwise, remove the packet from the queue and relelase the lock */ 00130 KeRemoveEntryDeviceQueue(&DeviceObject->DeviceQueue, 00131 &Irp->Tail.Overlay.DeviceQueueEntry); 00132 IoReleaseCancelSpinLock(Irp->CancelIrql); 00133 } 00134 00135 /* Complete the request */ 00136 Irp->IoStatus.Status = STATUS_CANCELLED; 00137 Irp->IoStatus.Information = 0; 00138 IoCompleteRequest (Irp, IO_NO_INCREMENT); 00139 } 00140 00141 DRIVER_DISPATCH BeepCleanup; 00142 NTSTATUS 00143 NTAPI 00144 BeepCleanup(IN PDEVICE_OBJECT DeviceObject, 00145 IN PIRP Irp) 00146 { 00147 KIRQL OldIrql, CancelIrql; 00148 PKDEVICE_QUEUE_ENTRY Packet; 00149 PIRP CurrentIrp; 00150 00151 /* Raise IRQL and acquire the cancel lock */ 00152 KeRaiseIrql(DISPATCH_LEVEL, &OldIrql); 00153 IoAcquireCancelSpinLock(&CancelIrql); 00154 00155 /* Get the current IRP */ 00156 CurrentIrp = DeviceObject->CurrentIrp; 00157 DeviceObject->CurrentIrp = NULL; 00158 while (CurrentIrp) 00159 { 00160 /* Clear its cancel routine */ 00161 (VOID)IoSetCancelRoutine(CurrentIrp, NULL); 00162 00163 /* Cancel the IRP */ 00164 CurrentIrp->IoStatus.Status = STATUS_CANCELLED; 00165 CurrentIrp->IoStatus.Information = 0; 00166 00167 /* Release the cancel lock and complete it */ 00168 IoReleaseCancelSpinLock(CancelIrql); 00169 IoCompleteRequest(CurrentIrp, IO_NO_INCREMENT); 00170 00171 /* Reacquire the lock and get the next queue packet */ 00172 IoAcquireCancelSpinLock(&CancelIrql); 00173 Packet = KeRemoveDeviceQueue(&DeviceObject->DeviceQueue); 00174 if (Packet) 00175 { 00176 /* Get the IRP */ 00177 CurrentIrp = CONTAINING_RECORD(Packet, 00178 IRP, 00179 Tail.Overlay.DeviceQueueEntry); 00180 } 00181 else 00182 { 00183 /* No more IRPs */ 00184 CurrentIrp = NULL; 00185 } 00186 } 00187 00188 /* Release lock and go back to low IRQL */ 00189 IoReleaseCancelSpinLock(CancelIrql); 00190 KeLowerIrql(OldIrql); 00191 00192 /* Complete the IRP */ 00193 Irp->IoStatus.Status = STATUS_SUCCESS; 00194 Irp->IoStatus.Information = 0; 00195 IoCompleteRequest(Irp, IO_NO_INCREMENT); 00196 00197 /* Stop and beep and return */ 00198 HalMakeBeep(0); 00199 return STATUS_SUCCESS; 00200 } 00201 00202 DRIVER_DISPATCH BeepDeviceControl; 00203 NTSTATUS 00204 NTAPI 00205 BeepDeviceControl(IN PDEVICE_OBJECT DeviceObject, 00206 IN PIRP Irp) 00207 { 00208 PIO_STACK_LOCATION Stack; 00209 PBEEP_SET_PARAMETERS BeepParam; 00210 NTSTATUS Status; 00211 00212 /* Get the stack location and parameters */ 00213 Stack = IoGetCurrentIrpStackLocation(Irp); 00214 BeepParam = (PBEEP_SET_PARAMETERS)Irp->AssociatedIrp.SystemBuffer; 00215 00216 /* We only support one IOCTL */ 00217 if (Stack->Parameters.DeviceIoControl.IoControlCode != IOCTL_BEEP_SET) 00218 { 00219 /* Unsupported command */ 00220 Status = STATUS_NOT_IMPLEMENTED; 00221 } 00222 else 00223 { 00224 /* Validate the input buffer length */ 00225 if (Stack->Parameters.DeviceIoControl.InputBufferLength < 00226 sizeof(BEEP_SET_PARAMETERS)) 00227 { 00228 /* Invalid buffer */ 00229 Status = STATUS_INVALID_PARAMETER; 00230 } 00231 else if ((BeepParam->Frequency != 0) && !(BeepParam->Duration)) 00232 { 00233 /* No duration, return imemdiately */ 00234 Status = STATUS_SUCCESS; 00235 } 00236 else 00237 { 00238 /* We'll queue this request */ 00239 Status = STATUS_PENDING; 00240 } 00241 } 00242 00243 /* Set packet information */ 00244 Irp->IoStatus.Status = Status; 00245 Irp->IoStatus.Information = 0; 00246 00247 /* Check if we're completing or queuing a packet */ 00248 if (Status == STATUS_PENDING) 00249 { 00250 /* Start the queue */ 00251 IoMarkIrpPending(Irp); 00252 IoStartPacket(DeviceObject, Irp, NULL, BeepCancel); 00253 } 00254 else 00255 { 00256 /* Complete the request */ 00257 IoCompleteRequest(Irp, IO_NO_INCREMENT); 00258 } 00259 00260 /* Return */ 00261 return Status; 00262 } 00263 00264 DRIVER_UNLOAD BeepUnload; 00265 VOID 00266 NTAPI 00267 BeepUnload(IN PDRIVER_OBJECT DriverObject) 00268 { 00269 PDEVICE_EXTENSION DeviceExtension; 00270 PDEVICE_OBJECT DeviceObject; 00271 00272 /* Get DO and DE */ 00273 DeviceObject = DriverObject->DeviceObject; 00274 DeviceExtension = DeviceObject->DeviceExtension; 00275 00276 /* Check if the timer is active */ 00277 if (DeviceExtension->TimerActive) 00278 { 00279 /* Cancel it */ 00280 if (KeCancelTimer(&DeviceExtension->Timer)) 00281 { 00282 /* All done */ 00283 InterlockedDecrement(&DeviceExtension->TimerActive); 00284 } 00285 } 00286 00287 /* Delete the object */ 00288 IoDeleteDevice(DeviceObject); 00289 } 00290 00291 DRIVER_STARTIO BeepStartIo; 00292 VOID 00293 NTAPI 00294 BeepStartIo(IN PDEVICE_OBJECT DeviceObject, 00295 IN PIRP Irp) 00296 { 00297 PDEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension; 00298 KIRQL CancelIrql; 00299 PIO_STACK_LOCATION IoStack; 00300 PBEEP_SET_PARAMETERS BeepParam; 00301 LARGE_INTEGER DueTime; 00302 NTSTATUS Status; 00303 00304 /* Acquire the cancel lock and make sure the IRP is valid */ 00305 IoAcquireCancelSpinLock(&CancelIrql); 00306 if (!Irp) 00307 { 00308 /* It's not, release the lock and quit */ 00309 IoReleaseCancelSpinLock(CancelIrql); 00310 return; 00311 } 00312 00313 /* Remove the cancel routine and release the lock */ 00314 (VOID)IoSetCancelRoutine(Irp, NULL); 00315 IoReleaseCancelSpinLock(CancelIrql); 00316 00317 /* Get the I/O Stack and make sure the request is valid */ 00318 BeepParam = (PBEEP_SET_PARAMETERS)Irp->AssociatedIrp.SystemBuffer; 00319 IoStack = IoGetCurrentIrpStackLocation(Irp); 00320 if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_BEEP_SET) 00321 { 00322 /* Check if we have an active timer */ 00323 if (DeviceExtension->TimerActive) 00324 { 00325 /* Cancel it */ 00326 if (KeCancelTimer(&DeviceExtension->Timer)) 00327 { 00328 /* Set the state */ 00329 InterlockedDecrement(&DeviceExtension->TimerActive); 00330 } 00331 } 00332 00333 /* Make the beep */ 00334 if (HalMakeBeep(BeepParam->Frequency)) 00335 { 00336 /* Beep successful, queue a DPC to stop it */ 00337 Status = STATUS_SUCCESS; 00338 DueTime.QuadPart = BeepParam->Duration * -10000; 00339 InterlockedIncrement(&DeviceExtension->TimerActive); 00340 KeSetTimer(&DeviceExtension->Timer, DueTime, &DeviceObject->Dpc); 00341 } 00342 else 00343 { 00344 /* Beep has failed */ 00345 Status = STATUS_INVALID_PARAMETER; 00346 } 00347 } 00348 else 00349 { 00350 /* Invalid request */ 00351 Status = STATUS_INVALID_PARAMETER; 00352 } 00353 00354 /* Complete the request and start the next packet */ 00355 Irp->IoStatus.Status = Status; 00356 Irp->IoStatus.Information = 0; 00357 IoStartNextPacket(DeviceObject, TRUE); 00358 IoCompleteRequest(Irp, IO_NO_INCREMENT); 00359 } 00360 00361 NTSTATUS 00362 NTAPI 00363 DriverEntry(IN PDRIVER_OBJECT DriverObject, 00364 IN PUNICODE_STRING RegistryPath) 00365 { 00366 PDEVICE_EXTENSION DeviceExtension; 00367 PDEVICE_OBJECT DeviceObject; 00368 UNICODE_STRING DeviceName = RTL_CONSTANT_STRING(L"\\Device\\Beep"); 00369 NTSTATUS Status; 00370 00371 /* Create the device */ 00372 Status = IoCreateDevice(DriverObject, 00373 sizeof(DEVICE_EXTENSION), 00374 &DeviceName, 00375 FILE_DEVICE_BEEP, 00376 0, 00377 FALSE, 00378 &DeviceObject); 00379 if (!NT_SUCCESS(Status)) return Status; 00380 00381 /* Make it use buffered I/O */ 00382 DeviceObject->Flags |= DO_BUFFERED_IO; 00383 00384 /* Setup the Driver Object */ 00385 DriverObject->MajorFunction[IRP_MJ_CREATE] = BeepCreate; 00386 DriverObject->MajorFunction[IRP_MJ_CLOSE] = BeepClose; 00387 DriverObject->MajorFunction[IRP_MJ_CLEANUP] = BeepCleanup; 00388 DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = BeepDeviceControl; 00389 DriverObject->DriverUnload = BeepUnload; 00390 DriverObject->DriverStartIo = BeepStartIo; 00391 00392 /* Set up device extension */ 00393 DeviceExtension = DeviceObject->DeviceExtension; 00394 DeviceExtension->ReferenceCount = 0; 00395 DeviceExtension->TimerActive = FALSE; 00396 IoInitializeDpcRequest(DeviceObject, (PIO_DPC_ROUTINE)BeepDPC); 00397 KeInitializeTimer(&DeviceExtension->Timer); 00398 ExInitializeFastMutex(&DeviceExtension->Mutex); 00399 00400 /* Page the entire driver */ 00401 MmPageEntireDriver(DriverEntry); 00402 return STATUS_SUCCESS; 00403 } 00404 00405 /* EOF */ Generated on Sun May 27 2012 04:18:10 for ReactOS by
1.7.6.1
|