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