69625c2cce005189d565768037ff3bc05fa3bf79
[reactos.git] / reactos / drivers / multimedia / audio / sb16_nt4.old / main.c
1 /*
2 ReactOS
3 Sound Blaster driver
4
5 Programmers:
6 Andrew Greenwood
7
8 Notes:
9 Compatible with NT4
10 */
11
12 #define NDEBUG
13 #include <sndblst.h>
14
15 #define TAG(A, B, C, D) (IN ULONG)(((A)<<0) + ((B)<<8) + ((C)<<16) + ((D)<<24))
16
17 /*
18 IRP DISPATCH ROUTINES
19 */
20
21 NTSTATUS NTAPI
22 CreateSoundBlaster(
23 PDEVICE_OBJECT DeviceObject,
24 PIRP Irp)
25 {
26 PSOUND_BLASTER_PARAMETERS sb_device = DeviceObject->DeviceExtension;
27
28 DPRINT("CreateSoundBlaster() called - extension 0x%x\n", sb_device);
29
30 EnableSpeaker(sb_device);
31 /*SetOutputSampleRate(sb_device, 22*/
32
33 Irp->IoStatus.Status = STATUS_SUCCESS;
34 Irp->IoStatus.Information = 0;
35
36 IoCompleteRequest(Irp, IO_NO_INCREMENT);
37
38 return STATUS_SUCCESS;
39 }
40
41 NTSTATUS NTAPI
42 CloseSoundBlaster(
43 PDEVICE_OBJECT DeviceObject,
44 PIRP Irp)
45 {
46 //PSOUND_BLASTER_PARAMETERS sb_device = DeviceObject->DeviceExtension;
47
48 DPRINT("CloseSoundBlaster() called\n");
49
50 Irp->IoStatus.Status = STATUS_SUCCESS;
51 Irp->IoStatus.Information = 0;
52
53 IoCompleteRequest(Irp, IO_NO_INCREMENT);
54
55 return STATUS_SUCCESS;
56 }
57
58 NTSTATUS NTAPI
59 CleanupSoundBlaster(
60 PDEVICE_OBJECT DeviceObject,
61 PIRP Irp)
62 {
63 //PSOUND_BLASTER_PARAMETERS sb_device = DeviceObject->DeviceExtension;
64
65 DPRINT("CleanupSoundBlaster() called\n");
66
67 Irp->IoStatus.Status = STATUS_SUCCESS;
68 Irp->IoStatus.Information = 0;
69
70 IoCompleteRequest(Irp, IO_NO_INCREMENT);
71
72 return STATUS_SUCCESS;
73 }
74
75 NTSTATUS NTAPI
76 ControlSoundBlaster(
77 PDEVICE_OBJECT DeviceObject,
78 PIRP Irp)
79 {
80 PIO_STACK_LOCATION stack;
81 //PSOUND_BLASTER_PARAMETERS sb_device = DeviceObject->DeviceExtension;
82
83 DPRINT("ControlSoundBlaster() called\n");
84
85 stack = IoGetCurrentIrpStackLocation(Irp);
86
87 switch ( stack->Parameters.DeviceIoControl.IoControlCode)
88 {
89 /* TODO */
90 };
91
92 Irp->IoStatus.Status = STATUS_SUCCESS;
93 Irp->IoStatus.Information = 0;
94
95 IoCompleteRequest(Irp, IO_NO_INCREMENT);
96
97 return STATUS_SUCCESS;
98 }
99
100 NTSTATUS NTAPI
101 WriteSoundBlaster(
102 PDEVICE_OBJECT DeviceObject,
103 PIRP Irp)
104 {
105 //PSOUND_BLASTER_PARAMETERS sb_device = DeviceObject->DeviceExtension;
106
107 DPRINT("WriteSoundBlaster() called\n");
108
109 Irp->IoStatus.Status = STATUS_SUCCESS;
110 Irp->IoStatus.Information = 0;
111
112 IoCompleteRequest(Irp, IO_NO_INCREMENT);
113
114 return STATUS_SUCCESS;
115 }
116
117 VOID NTAPI
118 UnloadSoundBlaster(
119 PDRIVER_OBJECT DriverObject)
120 {
121 DPRINT("Sound Blaster driver unload\n");
122 }
123
124 NTSTATUS NTAPI
125 OpenSubkey(
126 PUNICODE_STRING RegistryPath,
127 PWSTR Subkey,
128 ACCESS_MASK DesiredAccess,
129 OUT HANDLE* DevicesKeyHandle)
130 {
131 NTSTATUS status;
132 OBJECT_ATTRIBUTES attribs;
133 UNICODE_STRING subkey_name;
134 HANDLE key_handle;
135
136 /* TODO: Check for NULL ptr in DevicesKeyHandle */
137
138 InitializeObjectAttributes(&attribs,
139 RegistryPath,
140 OBJ_CASE_INSENSITIVE,
141 NULL,
142 (PSECURITY_DESCRIPTOR) NULL);
143
144 status = ZwOpenKey(&key_handle, KEY_READ, &attribs);
145
146 if ( ! NT_SUCCESS(status) )
147 {
148 DPRINT("Couldn't open subkey %wZ\n", Subkey);
149 return status;
150 }
151
152 RtlInitUnicodeString(&subkey_name, Subkey);
153
154 InitializeObjectAttributes(&attribs,
155 &subkey_name,
156 OBJ_CASE_INSENSITIVE,
157 key_handle,
158 (PSECURITY_DESCRIPTOR) NULL);
159
160 status = ZwOpenKey(*DevicesKeyHandle, DesiredAccess, &attribs);
161 ZwClose(key_handle);
162
163 return status;
164 }
165
166
167 PWSTR NTAPI
168 AllocateRegistryPathInfo(
169 PUNICODE_STRING BasePath,
170 PUNICODE_STRING ParametersPath,
171 PKEY_BASIC_INFORMATION KeyInfo)
172 {
173 PWSTR name;
174 PWSTR pos;
175
176 DPRINT("Allocating memory for path info\n");
177 name = ExAllocatePool(PagedPool,
178 BasePath->Length + sizeof(WCHAR) +
179 ParametersPath->Length + sizeof(WCHAR) +
180 KeyInfo->NameLength + sizeof(UNICODE_NULL));
181
182 if ( ! name )
183 return NULL;
184
185 DPRINT("Copying info\n");
186 pos = name;
187
188 RtlCopyMemory((PVOID)Pos, (PVOID)BasePath->Buffer, BasePath->Length);
189 pos += BasePath->Length / sizeof(WCHAR);
190 pos[0] = '\\';
191 pos ++;
192
193 RtlCopyMemory((PVOID)Pos, (PVOID)ParametersPath->Buffer, ParametersPath->Length);
194 pos += ParametersPath->Length / sizeof(WCHAR);
195 pos[0] = '\\';
196 pos ++;
197
198 RtlCopyMemory((PVOID)Pos, (PVOID)ParametersPath->Buffer, ParametersPath->Length);
199 pos += KeyInfo->NameLength / sizeof(WCHAR);
200 pos[0] = UNICODE_NULL;
201
202 DPRINT("All OK\n");
203 return name;
204 }
205
206 #define FreeRegistryPathInfo(ptr) \
207 ExFreePool(ptr)
208
209
210 #define TAG_REG_INFO TAG('I','g','e','R')
211 #define TAG_REG_NAME TAG('N','g','e','R')
212
213 NTSTATUS NTAPI
214 EnumerateSubkey(
215 PUNICODE_STRING RegistryPath,
216 PWSTR Subkey,
217 PREGISTRY_CALLBACK_ROUTINE Callback,
218 PDRIVER_OBJECT DriverObject)
219 {
220 NTSTATUS status;
221 UNICODE_STRING subkey_name;
222 HANDLE devices_key_handle;
223
224 ULONG key_index = 0;
225 ULONG result_length;
226
227 status = OpenSubkey(RegistryPath, Subkey, KEY_ENUMERATE_SUB_KEYS, &devices_key_handle);
228
229 if ( ! NT_SUCCESS(status) )
230 return status;
231
232 while ( TRUE )
233 {
234 KEY_BASIC_INFORMATION test_info;
235 PKEY_BASIC_INFORMATION info;
236 ULONG size;
237 PWSTR name;
238
239 status = ZwEnumerateKey(devices_key_handle,
240 key_index,
241 KeyBasicInformation,
242 &test_info,
243 sizeof(test_info),
244 &result_length);
245
246 if ( status == STATUS_NO_MORE_ENTRIES )
247 break;
248
249 size = result_length + FIELD_OFFSET(KEY_BASIC_INFORMATION, Name[0]);
250
251 info = (PKEY_BASIC_INFORMATION) ExAllocatePoolWithTag(PagedPool, size, TAG_REG_INFO);
252
253 if ( ! info )
254 {
255 DPRINT("Out of memory\n");
256 status = STATUS_INSUFFICIENT_RESOURCES;
257 break;
258 }
259
260 status = ZwEnumerateKey(devices_key_handle,
261 key_index,
262 KeyBasicInformation,
263 info,
264 size,
265 &result_length);
266
267 if ( ! NT_SUCCESS(status) )
268 {
269 DPRINT("Unable to enumerate keys\n");
270 ExFreePoolWithTag(info, TAG_REG_INFO);
271 status = STATUS_INTERNAL_ERROR;
272 break;
273 }
274
275 /* Is this ok? */
276 RtlInitUnicodeString(&subkey_name, Subkey);
277
278 name = AllocateRegistryPathInfo(RegistryPath, &subkey_name, info);
279
280 if ( ! name )
281 {
282 DPRINT("Out of memory\n");
283 ExFreePoolWithTag(info, TAG_REG_INFO);
284 status = STATUS_INSUFFICIENT_RESOURCES;
285 break;
286 }
287
288 ExFreePoolWithTag(info, TAG_REG_INFO);
289
290 /* Call the callback */
291 status = Callback(DriverObject, name);
292
293 FreeRegistryPathInfo(name);
294
295 if ( ! NT_SUCCESS(status) )
296 {
297 DPRINT("Callback FAILED\n");
298 break;
299 }
300
301 key_index ++;
302 }
303
304 ZwClose(devices_key_handle);
305
306 DPRINT("Found %d subkey entries\n", key_index);
307
308 if ( ( key_index == 0 ) && ( status == STATUS_NO_MORE_ENTRIES ) )
309 return STATUS_DEVICE_CONFIGURATION_ERROR;
310
311 if ( status == STATUS_NO_MORE_ENTRIES )
312 status = STATUS_SUCCESS;
313
314 return status;
315 }
316
317 #define EnumerateDeviceKeys(path, callback, driver_obj) \
318 EnumerateSubkey(path, L"Devices", callback, driver_obj)
319
320
321 NTSTATUS
322 CreateDeviceName(
323 PCWSTR PrePrefix,
324 PCWSTR Prefix,
325 UCHAR Index,
326 PUNICODE_STRING DeviceName)
327 {
328 UNICODE_STRING number;
329 WCHAR number_buffer[5];
330 UNICODE_STRING unicode_pre_prefix;
331 UNICODE_STRING unicode_prefix;
332 ULONG size;
333
334 RtlInitUnicodeString(&unicode_pre_prefix, PrePrefix);
335 RtlInitUnicodeString(&unicode_prefix, Prefix);
336
337 size = unicode_pre_prefix.Length +
338 unicode_prefix.Length +
339 sizeof(number_buffer) +
340 sizeof(UNICODE_NULL);
341
342 DeviceName->Buffer = ExAllocatePool(PagedPool, size);
343 DeviceName->MaximumLength = (USHORT) size;
344
345 if ( ! DeviceName->Buffer )
346 return STATUS_INSUFFICIENT_RESOURCES;
347
348 RtlCopyUnicodeString(DeviceName, &unicode_pre_prefix);
349 RtlAppendUnicodeStringToString(DeviceName, &unicode_prefix);
350
351 if ( Index != 255 )
352 {
353 number.Buffer = number_buffer;
354 number.MaximumLength = sizeof(number_buffer);
355
356 RtlIntegerToUnicodeString((ULONG) Index, 10, &number);
357 RtlAppendUnicodeStringToString(DeviceName, &number);
358 }
359
360 DeviceName->Buffer[DeviceName->Length / sizeof(UNICODE_NULL)] = UNICODE_NULL;
361
362 return STATUS_SUCCESS;
363 }
364
365 NTSTATUS NTAPI
366 InitializeSoundBlaster(
367 PDRIVER_OBJECT DriverObject,
368 PWSTR RegistryPath)
369 {
370 NTSTATUS status;
371 PDEVICE_OBJECT device_object;
372 PSOUND_BLASTER_PARAMETERS parameters = NULL;
373 UNICODE_STRING device_name;
374 UNICODE_STRING dos_device_name;
375
376 UCHAR device_index = 0;
377
378 DPRINT("Initializing a Sound Blaster device\n");
379
380 /* Change these later */
381 status = CreateDeviceName(L"",
382 L"\\Device\\WaveOut",
383 device_index,
384 &device_name);
385
386 if ( ! NT_SUCCESS(status) )
387 return status;
388
389 status = CreateDeviceName(L"\\DosDevices\\",
390 L"\\Device\\WaveOut" + wcslen(L"\\Device\\"),
391 device_index,
392 &dos_device_name);
393
394 if ( ! NT_SUCCESS(status) )
395 {
396 /* TODO */
397 return status;
398 }
399
400 DPRINT("Device: %wZ\n", device_name);
401 DPRINT("Symlink: %wZ\n", dos_device_name);
402
403 /*
404 Create the device and DOS symlink
405 */
406
407 status = IoCreateDevice(DriverObject,
408 sizeof(SOUND_BLASTER_PARAMETERS),
409 &device_name,
410 FILE_DEVICE_SOUND,
411 0,
412 FALSE,
413 &device_object);
414
415 if ( ! NT_SUCCESS(status) )
416 return status;
417
418 DPRINT("Created a device extension at 0x%x\n", device_object->DeviceExtension);
419 parameters = device_object->DeviceExtension;
420
421 status = IoCreateSymbolicLink(&dos_device_name, &device_name);
422
423 ExFreePool(dos_device_name.Buffer);
424 ExFreePool(device_name.Buffer);
425
426 if ( ! NT_SUCCESS(status) )
427 {
428 IoDeleteDevice(device_object);
429 device_object = NULL;
430 return status;
431 }
432
433 /* IoRegisterShutdownNotification( */
434
435 /*
436 Settings
437 */
438
439 device_object->AlignmentRequirement = FILE_BYTE_ALIGNMENT;
440
441 parameters->driver = DriverObject;
442 parameters->registry_path = RegistryPath;
443 parameters->port = DEFAULT_PORT;
444 parameters->irq = DEFAULT_IRQ;
445 parameters->dma = DEFAULT_DMA;
446 parameters->buffer_size = DEFAULT_BUFFER_SIZE;
447
448 /* TODO: Load the settings from the registry */
449
450 DPRINT("Port %x IRQ %d DMA %d\n", parameters->port, parameters->irq, parameters->dma);
451
452 DPRINT("Resetting the sound card\n");
453
454 if ( ! ResetSoundBlaster(parameters) )
455 {
456 /* TODO */
457 return STATUS_UNSUCCESSFUL;
458 }
459
460 /*
461 DPRINT("What kind of SB card is this?\n");
462 GetSoundBlasterModel(parameters);
463 */
464
465 return STATUS_SUCCESS;
466 }
467
468
469 NTSTATUS NTAPI
470 DriverEntry(
471 PDRIVER_OBJECT DriverObject,
472 PUNICODE_STRING RegistryPath)
473 {
474 NTSTATUS status;
475
476 DPRINT("Sound Blaster driver 0.1 by Silver Blade\n");
477
478 DriverObject->Flags = 0;
479 DriverObject->MajorFunction[IRP_MJ_CREATE] = CreateSoundBlaster;
480 DriverObject->MajorFunction[IRP_MJ_CLOSE] = CloseSoundBlaster;
481 DriverObject->MajorFunction[IRP_MJ_CLEANUP] = CleanupSoundBlaster;
482 DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = ControlSoundBlaster;
483 DriverObject->MajorFunction[IRP_MJ_WRITE] = WriteSoundBlaster;
484 DriverObject->DriverUnload = UnloadSoundBlaster;
485
486 DPRINT("Beginning device key enumeration\n");
487
488 status = EnumerateDeviceKeys(RegistryPath, *InitializeSoundBlaster, DriverObject);
489
490 return status;
491 }