ReactOS 0.4.15-dev-7887-g64a59a1
beep.c
Go to the documentation of this file.
1/*
2 * PROJECT: ReactOS Kernel
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: drivers/base/beep/beep.c
5 * PURPOSE: Beep Device Driver
6 * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
7 * Eric Kohl
8 */
9
10/* INCLUDES ******************************************************************/
11
12#include <ntddk.h>
13#include <ntddbeep.h>
14#ifndef NDEBUG
15#define NDEBUG
16#endif
17#include <debug.h>
18
19/* TYPES *********************************************************************/
20
22{
29
30/* FUNCTIONS *****************************************************************/
31
32VOID
38{
39 PDEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
40
44
45 /* Stop the beep */
46 HalMakeBeep(0);
47
48 /* Disable the timer */
49 InterlockedDecrement(&DeviceExtension->TimerActive);
50}
51
56 IN PIRP Irp)
57{
58 PDEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
59
60 /* Acquire the mutex and increase reference count */
61 ExAcquireFastMutex(&DeviceExtension->Mutex);
62 if (++DeviceExtension->ReferenceCount == 1)
63 {
64 /* First reference, lock the data section */
65 DeviceExtension->SectionHandle = MmLockPagableDataSection(BeepCreate);
66 }
67
68 /* Release it */
69 ExReleaseFastMutex(&DeviceExtension->Mutex);
70
71 /* Complete the request */
72 Irp->IoStatus.Status = STATUS_SUCCESS;
73 Irp->IoStatus.Information = 0;
75 return STATUS_SUCCESS;
76}
77
82 IN PIRP Irp)
83{
84 PDEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
85
86 /* Acquire the mutex and decrease reference count */
87 ExAcquireFastMutex(&DeviceExtension->Mutex);
88 if (!(--DeviceExtension->ReferenceCount))
89 {
90 /* Check for active timer */
91 if (DeviceExtension->TimerActive)
92 {
93 /* Cancel it */
94 if (KeCancelTimer(&DeviceExtension->Timer))
95 {
96 /* Mark it as cancelled */
97 InterlockedDecrement(&DeviceExtension->TimerActive);
98 }
99 }
100
101 /* Page the driver */
102 MmUnlockPagableImageSection(DeviceExtension->SectionHandle);
103 }
104
105 /* Release the lock */
106 ExReleaseFastMutex(&DeviceExtension->Mutex);
107
108 /* Complete the request */
109 Irp->IoStatus.Status = STATUS_SUCCESS;
110 Irp->IoStatus.Information = 0;
112 return STATUS_SUCCESS;
113}
114
115DRIVER_CANCEL BeepCancel;
116VOID
117NTAPI
119 IN PIRP Irp)
120{
121 /* Check if this is the current request */
122 if (Irp == DeviceObject->CurrentIrp)
123 {
124 /* Clear it */
125 DeviceObject->CurrentIrp = NULL;
126
127 /* Release the cancel lock and start the next packet */
128 IoReleaseCancelSpinLock(Irp->CancelIrql);
130 }
131 else
132 {
133 /* Otherwise, remove the packet from the queue and release the lock */
135 &Irp->Tail.Overlay.DeviceQueueEntry);
136 IoReleaseCancelSpinLock(Irp->CancelIrql);
137 }
138
139 /* Complete the request */
140 Irp->IoStatus.Status = STATUS_CANCELLED;
141 Irp->IoStatus.Information = 0;
143}
144
147NTAPI
149 IN PIRP Irp)
150{
151 KIRQL OldIrql, CancelIrql;
153 PIRP CurrentIrp;
154
155 /* Raise IRQL and acquire the cancel lock */
157 IoAcquireCancelSpinLock(&CancelIrql);
158
159 /* Get the current IRP */
160 CurrentIrp = DeviceObject->CurrentIrp;
161 DeviceObject->CurrentIrp = NULL;
162 while (CurrentIrp)
163 {
164 /* Clear its cancel routine */
165 (VOID)IoSetCancelRoutine(CurrentIrp, NULL);
166
167 /* Cancel the IRP */
168 CurrentIrp->IoStatus.Status = STATUS_CANCELLED;
169 CurrentIrp->IoStatus.Information = 0;
170
171 /* Release the cancel lock and complete it */
172 IoReleaseCancelSpinLock(CancelIrql);
174
175 /* Reacquire the lock and get the next queue packet */
176 IoAcquireCancelSpinLock(&CancelIrql);
177 Packet = KeRemoveDeviceQueue(&DeviceObject->DeviceQueue);
178 if (Packet)
179 {
180 /* Get the IRP */
181 CurrentIrp = CONTAINING_RECORD(Packet,
182 IRP,
183 Tail.Overlay.DeviceQueueEntry);
184 }
185 else
186 {
187 /* No more IRPs */
188 CurrentIrp = NULL;
189 }
190 }
191
192 /* Release lock and go back to low IRQL */
193 IoReleaseCancelSpinLock(CancelIrql);
195
196 /* Complete the IRP */
197 Irp->IoStatus.Status = STATUS_SUCCESS;
198 Irp->IoStatus.Information = 0;
200
201 /* Stop and beep and return */
202 HalMakeBeep(0);
203 return STATUS_SUCCESS;
204}
205
208NTAPI
210 IN PIRP Irp)
211{
213 PBEEP_SET_PARAMETERS BeepParam;
215
216 /* Get the stack location and parameters */
218 BeepParam = (PBEEP_SET_PARAMETERS)Irp->AssociatedIrp.SystemBuffer;
219
220 /* We only support one IOCTL */
221 if (Stack->Parameters.DeviceIoControl.IoControlCode != IOCTL_BEEP_SET)
222 {
223 /* Unsupported command */
225 }
226 else
227 {
228 /* Validate the input buffer length */
229 if (Stack->Parameters.DeviceIoControl.InputBufferLength <
230 sizeof(BEEP_SET_PARAMETERS))
231 {
232 /* Invalid buffer */
234 }
235 else if ((BeepParam->Frequency != 0) && !(BeepParam->Duration))
236 {
237 /* No duration, return immediately */
239 }
240 else
241 {
242 /* We'll queue this request */
244 }
245 }
246
247 /* Set packet information */
248 Irp->IoStatus.Status = Status;
249 Irp->IoStatus.Information = 0;
250
251 /* Check if we're completing or queuing a packet */
252 if (Status == STATUS_PENDING)
253 {
254 /* Start the queue */
257 }
258 else
259 {
260 /* Complete the request */
262 }
263
264 /* Return */
265 return Status;
266}
267
268DRIVER_UNLOAD BeepUnload;
269VOID
270NTAPI
272{
273 PDEVICE_EXTENSION DeviceExtension;
275
276 /* Get DO and DE */
277 DeviceObject = DriverObject->DeviceObject;
278 DeviceExtension = DeviceObject->DeviceExtension;
279
280 /* Check if the timer is active */
281 if (DeviceExtension->TimerActive)
282 {
283 /* Cancel it */
284 if (KeCancelTimer(&DeviceExtension->Timer))
285 {
286 /* All done */
287 InterlockedDecrement(&DeviceExtension->TimerActive);
288 }
289 }
290
291 /* Delete the object */
293}
294
295DRIVER_STARTIO BeepStartIo;
296VOID
297NTAPI
299 IN PIRP Irp)
300{
301 PDEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
302 KIRQL CancelIrql;
303 PIO_STACK_LOCATION IoStack;
304 PBEEP_SET_PARAMETERS BeepParam;
307
308 /* Acquire the cancel lock and make sure the IRP is valid */
309 IoAcquireCancelSpinLock(&CancelIrql);
310 if (!Irp)
311 {
312 /* It's not, release the lock and quit */
313 IoReleaseCancelSpinLock(CancelIrql);
314 return;
315 }
316
317 /* Remove the cancel routine and release the lock */
319 IoReleaseCancelSpinLock(CancelIrql);
320
321 /* Get the I/O Stack and make sure the request is valid */
322 BeepParam = (PBEEP_SET_PARAMETERS)Irp->AssociatedIrp.SystemBuffer;
324 if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_BEEP_SET)
325 {
326 /* Check if we have an active timer */
327 if (DeviceExtension->TimerActive)
328 {
329 /* Cancel it */
330 if (KeCancelTimer(&DeviceExtension->Timer))
331 {
332 /* Set the state */
333 InterlockedDecrement(&DeviceExtension->TimerActive);
334 }
335 }
336
337 /* Make the beep */
338 if (HalMakeBeep(BeepParam->Frequency))
339 {
340 /* Beep successful, queue a DPC to stop it */
342 DueTime.QuadPart = BeepParam->Duration * -10000LL;
343 InterlockedIncrement(&DeviceExtension->TimerActive);
344 KeSetTimer(&DeviceExtension->Timer, DueTime, &DeviceObject->Dpc);
345 }
346 else
347 {
348 /* Beep has failed */
350 }
351 }
352 else
353 {
354 /* Invalid request */
356 }
357
358 /* Complete the request and start the next packet */
359 Irp->IoStatus.Status = Status;
360 Irp->IoStatus.Information = 0;
363}
364
366NTAPI
369{
370 PDEVICE_EXTENSION DeviceExtension;
374
376
377 /* Create the device */
379 sizeof(DEVICE_EXTENSION),
380 &DeviceName,
382 0,
383 FALSE,
384 &DeviceObject);
385 if (!NT_SUCCESS(Status)) return Status;
386
387 /* Make it use buffered I/O */
389
390 /* Setup the Driver Object */
391 DriverObject->MajorFunction[IRP_MJ_CREATE] = BeepCreate;
392 DriverObject->MajorFunction[IRP_MJ_CLOSE] = BeepClose;
393 DriverObject->MajorFunction[IRP_MJ_CLEANUP] = BeepCleanup;
395 DriverObject->DriverUnload = BeepUnload;
396 DriverObject->DriverStartIo = BeepStartIo;
397
398 /* Set up device extension */
399 DeviceExtension = DeviceObject->DeviceExtension;
400 DeviceExtension->ReferenceCount = 0;
401 DeviceExtension->TimerActive = FALSE;
403 KeInitializeTimer(&DeviceExtension->Timer);
404 ExInitializeFastMutex(&DeviceExtension->Mutex);
405
406 /* Page the entire driver */
408 return STATUS_SUCCESS;
409}
410
411/* EOF */
static PIO_STACK_LOCATION IoGetCurrentIrpStackLocation(PIRP Irp)
#define VOID
Definition: acefi.h:82
#define InterlockedIncrement
Definition: armddk.h:53
#define InterlockedDecrement
Definition: armddk.h:52
LONG NTSTATUS
Definition: precomp.h:26
_In_ PIRP Irp
Definition: csq.h:116
PKDEVICE_QUEUE_ENTRY NTAPI KeRemoveDeviceQueue(IN PKDEVICE_QUEUE DeviceQueue)
Definition: devqueue.c:153
BOOLEAN NTAPI KeRemoveEntryDeviceQueue(IN PKDEVICE_QUEUE DeviceQueue, IN PKDEVICE_QUEUE_ENTRY DeviceQueueEntry)
Definition: devqueue.c:348
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
DRIVER_STARTIO BeepStartIo
Definition: beep.c:295
struct _BEEP_DEVICE_EXTENSION * PDEVICE_EXTENSION
VOID NTAPI BeepDPC(IN PKDPC Dpc, IN PDEVICE_OBJECT DeviceObject, IN PVOID SystemArgument1, IN PVOID SystemArgument2)
Definition: beep.c:34
DRIVER_DISPATCH BeepClose
Definition: beep.c:78
struct _BEEP_DEVICE_EXTENSION DEVICE_EXTENSION
DRIVER_DISPATCH BeepCleanup
Definition: beep.c:145
DRIVER_UNLOAD BeepUnload
Definition: beep.c:268
DRIVER_DISPATCH BeepCreate
Definition: beep.c:52
DRIVER_DISPATCH BeepDeviceControl
Definition: beep.c:206
DRIVER_CANCEL BeepCancel
Definition: beep.c:115
DRIVER_INITIALIZE DriverEntry
Definition: condrv.c:21
UCHAR KIRQL
Definition: env_spec_w32.h:591
#define DO_BUFFERED_IO
Definition: env_spec_w32.h:394
#define KeRaiseIrql(irql, oldIrql)
Definition: env_spec_w32.h:597
#define KeLowerIrql(oldIrql)
Definition: env_spec_w32.h:602
#define DISPATCH_LEVEL
Definition: env_spec_w32.h:696
Status
Definition: gdiplustypes.h:25
BOOLEAN NTAPI HalMakeBeep(IN ULONG Frequency)
Definition: beep.c:22
VOID FASTCALL ExAcquireFastMutex(IN PFAST_MUTEX FastMutex)
Definition: fmutex.c:23
VOID FASTCALL ExReleaseFastMutex(IN PFAST_MUTEX FastMutex)
Definition: fmutex.c:31
IoMarkIrpPending(Irp)
IoSetCancelRoutine(Irp, CancelRoutine)
if(dx< 0)
Definition: linetemp.h:194
_In_ NDIS_HANDLE _In_ PNDIS_PACKET Packet
Definition: ndis.h:1549
DRIVER_DISPATCH(nfs41_FsdDispatch)
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:317
#define IOCTL_BEEP_SET
Definition: ntddbeep.h:31
struct _BEEP_SET_PARAMETERS * PBEEP_SET_PARAMETERS
NTSTATUS NTAPI IoCreateDevice(IN PDRIVER_OBJECT DriverObject, IN ULONG DeviceExtensionSize, IN PUNICODE_STRING DeviceName, IN DEVICE_TYPE DeviceType, IN ULONG DeviceCharacteristics, IN BOOLEAN Exclusive, OUT PDEVICE_OBJECT *DeviceObject)
Definition: device.c:1031
VOID NTAPI IoStartPacket(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PULONG Key, IN PDRIVER_CANCEL CancelFunction)
Definition: device.c:1876
VOID NTAPI IoDeleteDevice(IN PDEVICE_OBJECT DeviceObject)
Definition: device.c:1251
VOID NTAPI IoStartNextPacket(IN PDEVICE_OBJECT DeviceObject, IN BOOLEAN Cancelable)
Definition: device.c:1847
#define IoCompleteRequest
Definition: irp.c:1240
VOID NTAPI IoReleaseCancelSpinLock(IN KIRQL Irql)
Definition: util.c:150
VOID NTAPI IoAcquireCancelSpinLock(OUT PKIRQL Irql)
Definition: util.c:56
#define STATUS_PENDING
Definition: ntstatus.h:82
#define STATUS_NOT_IMPLEMENTED
Definition: ntstatus.h:239
#define L(x)
Definition: ntvdm.h:50
long LONG
Definition: pedump.c:60
#define FILE_DEVICE_BEEP
Definition: winioctl.h:107
#define IRP_MJ_CLOSE
Definition: rdpdr.c:45
#define IRP_MJ_DEVICE_CONTROL
Definition: rdpdr.c:52
#define IRP_MJ_CREATE
Definition: rdpdr.c:44
#define STATUS_SUCCESS
Definition: shellext.h:65
FAST_MUTEX Mutex
Definition: beep.c:24
PVOID SectionHandle
Definition: beep.c:27
struct _IO_STACK_LOCATION::@1564::@1565 DeviceIoControl
union _IO_STACK_LOCATION::@1564 Parameters
IO_STATUS_BLOCK IoStatus
Definition: ketypes.h:578
Definition: ketypes.h:699
struct _KDPC * Dpc
Definition: ketypes.h:855
PVOID NTAPI MmPageEntireDriver(IN PVOID AddressWithinSection)
Definition: sysldr.c:3557
BOOLEAN NTAPI KeSetTimer(IN OUT PKTIMER Timer, IN LARGE_INTEGER DueTime, IN PKDPC Dpc OPTIONAL)
Definition: timerobj.c:281
BOOLEAN NTAPI KeCancelTimer(IN OUT PKTIMER Timer)
Definition: timerobj.c:206
VOID NTAPI KeInitializeTimer(OUT PKTIMER Timer)
Definition: timerobj.c:233
#define RTL_CONSTANT_STRING(s)
Definition: tunneltest.c:14
#define NTAPI
Definition: typedefs.h:36
#define IN
Definition: typedefs.h:39
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
#define STATUS_CANCELLED
Definition: udferr_usr.h:170
_In_ PDEVICE_OBJECT DeviceObject
Definition: wdfdevice.h:2055
_Must_inspect_result_ _In_ PWDFDEVICE_INIT _In_opt_ PCUNICODE_STRING DeviceName
Definition: wdfdevice.h:3275
_Must_inspect_result_ _In_ PWDF_DPC_CONFIG _In_ PWDF_OBJECT_ATTRIBUTES _Out_ WDFDPC * Dpc
Definition: wdfdpc.h:112
_Must_inspect_result_ _In_ PDRIVER_OBJECT _In_ PCUNICODE_STRING RegistryPath
Definition: wdfdriver.h:215
_Must_inspect_result_ _In_ PDRIVER_OBJECT DriverObject
Definition: wdfdriver.h:213
_In_ WDFREQUEST _In_ PIO_STACK_LOCATION Stack
Definition: wdfrequest.h:639
_In_ WDFTIMER _In_ LONGLONG DueTime
Definition: wdftimer.h:190
FORCEINLINE VOID ExInitializeFastMutex(_Out_ PFAST_MUTEX FastMutex)
Definition: exfuncs.h:274
FAST_MUTEX
Definition: extypes.h:17
FORCEINLINE VOID IoInitializeDpcRequest(_In_ PDEVICE_OBJECT DeviceObject, _In_ PIO_DPC_ROUTINE DpcRoutine)
Definition: iofuncs.h:2840
#define IO_NO_INCREMENT
Definition: iotypes.h:598
IO_DPC_ROUTINE * PIO_DPC_ROUTINE
Definition: iotypes.h:2847
#define IRP_MJ_CLEANUP
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:778
_In_opt_ PVOID _In_opt_ PVOID SystemArgument1
Definition: ketypes.h:688
_In_opt_ PVOID _In_opt_ PVOID _In_opt_ PVOID SystemArgument2
Definition: ketypes.h:689