:pserver:cvsanon@mok.lvcm.com:/CVS/ReactOS reactos
[reactos.git] / drivers / dd / beep / beep.c
1 /* $Id$
2  *
3  * COPYRIGHT:            See COPYING in the top level directory
4  * PROJECT:              ReactOS kernel
5  * FILE:                 services/dd/beep/beep.c
6  * PURPOSE:              BEEP device driver
7  * PROGRAMMER:           Eric Kohl (ekohl@rz-online.de)
8  * UPDATE HISTORY:
9  *                       30/01/99 Created
10  *                       16/10/99 Minor fixes
11  */
12
13 /* INCLUDES ****************************************************************/
14
15 #include <ddk/ntddk.h>
16 #include <ddk/ntddbeep.h>
17
18 #define NDEBUG
19 #include <debug.h>
20
21
22 /* TYEPEDEFS ***************************************************************/
23
24 typedef struct _BEEP_DEVICE_EXTENSION
25 {
26   KDPC Dpc;
27   KTIMER Timer;
28   KEVENT Event;
29   BOOLEAN BeepOn;
30 } DEVICE_EXTENSION, *PDEVICE_EXTENSION;
31
32
33 /* FUNCTIONS ***************************************************************/
34
35 static VOID STDCALL
36 BeepDPC(PKDPC Dpc,
37         PVOID DeferredContext,
38         PVOID SystemArgument1,
39         PVOID SystemArgument2)
40 {
41   PDEVICE_EXTENSION DeviceExtension = DeferredContext;
42
43   DPRINT("BeepDPC() called!\n");
44
45   HalMakeBeep(0);
46   DeviceExtension->BeepOn = FALSE;
47   KeSetEvent(&DeviceExtension->Event,
48              0,
49              FALSE);
50
51   DPRINT("BeepDPC() finished!\n");
52 }
53
54
55 static NTSTATUS STDCALL
56 BeepCreate(PDEVICE_OBJECT DeviceObject,
57            PIRP Irp)
58 /*
59  * FUNCTION: Handles user mode requests
60  * ARGUMENTS:
61  *                       DeviceObject = Device for request
62  *                       Irp = I/O request packet describing request
63  * RETURNS: Success or failure
64  */
65 {
66   DPRINT("BeepCreate() called!\n");
67
68   Irp->IoStatus.Status = STATUS_SUCCESS;
69   Irp->IoStatus.Information = 0;
70   IoCompleteRequest(Irp,
71                     IO_NO_INCREMENT);
72
73   return(STATUS_SUCCESS);
74 }
75
76
77 static NTSTATUS STDCALL
78 BeepClose(PDEVICE_OBJECT DeviceObject,
79           PIRP Irp)
80 /*
81  * FUNCTION: Handles user mode requests
82  * ARGUMENTS:
83  *                       DeviceObject = Device for request
84  *                       Irp = I/O request packet describing request
85  * RETURNS: Success or failure
86  */
87 {
88   PDEVICE_EXTENSION DeviceExtension;
89   NTSTATUS Status;
90
91   DPRINT("BeepClose() called!\n");
92
93   DeviceExtension = DeviceObject->DeviceExtension;
94   if (DeviceExtension->BeepOn == TRUE)
95     {
96       HalMakeBeep(0);
97       DeviceExtension->BeepOn = FALSE;
98       KeCancelTimer(&DeviceExtension->Timer);
99     }
100
101   Status = STATUS_SUCCESS;
102
103   Irp->IoStatus.Status = Status;
104   Irp->IoStatus.Information = 0;
105   IoCompleteRequest(Irp,
106                     IO_NO_INCREMENT);
107
108   return(Status);
109 }
110
111
112 static NTSTATUS STDCALL
113 BeepCleanup(PDEVICE_OBJECT DeviceObject,
114             PIRP Irp)
115 /*
116  * FUNCTION: Handles user mode requests
117  * ARGUMENTS:
118  *                       DeviceObject = Device for request
119  *                       Irp = I/O request packet describing request
120  * RETURNS: Success or failure
121  */
122 {
123   DPRINT("BeepCleanup() called!\n");
124
125   Irp->IoStatus.Status = STATUS_SUCCESS;
126   Irp->IoStatus.Information = 0;
127   IoCompleteRequest(Irp,
128                     IO_NO_INCREMENT);
129
130   return(STATUS_SUCCESS);
131 }
132
133
134 static NTSTATUS STDCALL
135 BeepDeviceControl(PDEVICE_OBJECT DeviceObject,
136                   PIRP Irp)
137 /*
138  * FUNCTION: Handles user mode requests
139  * ARGUMENTS:
140  *                       DeviceObject = Device for request
141  *                       Irp = I/O request packet describing request
142  * RETURNS: Success or failure
143  */
144 {
145   PIO_STACK_LOCATION Stack;
146   PDEVICE_EXTENSION DeviceExtension;
147   PBEEP_SET_PARAMETERS BeepParam;
148   LARGE_INTEGER DueTime;
149
150   DPRINT("BeepDeviceControl() called!\n");
151
152   DeviceExtension = DeviceObject->DeviceExtension;
153   Stack = IoGetCurrentIrpStackLocation(Irp);
154   BeepParam = (PBEEP_SET_PARAMETERS)Irp->AssociatedIrp.SystemBuffer;
155
156   Irp->IoStatus.Information = 0;
157
158   if (Stack->Parameters.DeviceIoControl.IoControlCode != IOCTL_BEEP_SET)
159     {
160       Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
161       IoCompleteRequest(Irp,
162                         IO_NO_INCREMENT);
163       return(STATUS_NOT_IMPLEMENTED);
164     }
165
166   if ((Stack->Parameters.DeviceIoControl.InputBufferLength != sizeof(BEEP_SET_PARAMETERS))
167       || (BeepParam->Frequency < BEEP_FREQUENCY_MINIMUM)
168       || (BeepParam->Frequency > BEEP_FREQUENCY_MAXIMUM))
169     {
170       Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
171       IoCompleteRequest(Irp,
172                         IO_NO_INCREMENT);
173       return(STATUS_INVALID_PARAMETER);
174     }
175
176   DueTime.QuadPart = 0;
177
178   /* do the beep!! */
179   DPRINT("Beep:\n  Freq: %lu Hz\n  Dur: %lu ms\n",
180          pbsp->Frequency,
181          pbsp->Duration);
182
183   if (BeepParam->Duration >= 0)
184     {
185       DueTime.QuadPart = (LONGLONG)BeepParam->Duration * -10000;
186
187       KeSetTimer(&DeviceExtension->Timer,
188                  DueTime,
189                  &DeviceExtension->Dpc);
190
191       HalMakeBeep(BeepParam->Frequency);
192       DeviceExtension->BeepOn = TRUE;
193       KeWaitForSingleObject(&DeviceExtension->Event,
194                             Executive,
195                             KernelMode,
196                             FALSE,
197                             NULL);
198     }
199   else if (BeepParam->Duration == (DWORD)-1)
200     {
201       if (DeviceExtension->BeepOn == TRUE)
202         {
203           HalMakeBeep(0);
204           DeviceExtension->BeepOn = FALSE;
205         }
206       else
207         {
208           HalMakeBeep(BeepParam->Frequency);
209           DeviceExtension->BeepOn = TRUE;
210         }
211     }
212
213   DPRINT("Did the beep!\n");
214
215   Irp->IoStatus.Status = STATUS_SUCCESS;
216   IoCompleteRequest(Irp,
217                     IO_NO_INCREMENT);
218   return(STATUS_SUCCESS);
219 }
220
221
222 static NTSTATUS STDCALL
223 BeepUnload(PDRIVER_OBJECT DriverObject)
224 {
225   DPRINT("BeepUnload() called!\n");
226   return(STATUS_SUCCESS);
227 }
228
229
230 NTSTATUS STDCALL
231 DriverEntry(PDRIVER_OBJECT DriverObject,
232             PUNICODE_STRING RegistryPath)
233 /*
234  * FUNCTION:  Called by the system to initalize the driver
235  * ARGUMENTS:
236  *            DriverObject = object describing this driver
237  *            RegistryPath = path to our configuration entries
238  * RETURNS:   Success or failure
239  */
240 {
241   PDEVICE_EXTENSION DeviceExtension;
242   PDEVICE_OBJECT DeviceObject;
243   UNICODE_STRING DeviceName = UNICODE_STRING_INITIALIZER(L"\\Device\\Beep");
244   UNICODE_STRING SymlinkName = UNICODE_STRING_INITIALIZER(L"\\??\\Beep");
245   NTSTATUS Status;
246
247   DPRINT("Beep Device Driver 0.0.3\n");
248
249   DriverObject->Flags = 0;
250   DriverObject->MajorFunction[IRP_MJ_CREATE] = BeepCreate;
251   DriverObject->MajorFunction[IRP_MJ_CLOSE] = BeepClose;
252   DriverObject->MajorFunction[IRP_MJ_CLEANUP] = BeepCleanup;
253   DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = BeepDeviceControl;
254   DriverObject->DriverUnload = BeepUnload;
255
256   Status = IoCreateDevice(DriverObject,
257                           sizeof(DEVICE_EXTENSION),
258                           &DeviceName,
259                           FILE_DEVICE_BEEP,
260                           0,
261                           FALSE,
262                           &DeviceObject);
263   if (!NT_SUCCESS(Status))
264     return Status;
265
266   /* set up device extension */
267   DeviceExtension = DeviceObject->DeviceExtension;
268   DeviceExtension->BeepOn = FALSE;
269
270   KeInitializeDpc(&DeviceExtension->Dpc,
271                   BeepDPC,
272                   DeviceExtension);
273   KeInitializeTimer(&DeviceExtension->Timer);
274   KeInitializeEvent(&DeviceExtension->Event,
275                     SynchronizationEvent,
276                     FALSE);
277
278   /* Create the dos device link */
279   IoCreateSymbolicLink(&SymlinkName,
280                        &DeviceName);
281
282   return(STATUS_SUCCESS);
283 }
284
285 /* EOF */