ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

beep.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 doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.