xref: /reactos/drivers/wdm/audio/sysaudio/main.c (revision 5b54477d)
1c2c66affSColin Finck /*
2c2c66affSColin Finck  * COPYRIGHT:       See COPYING in the top level directory
3c2c66affSColin Finck  * PROJECT:         ReactOS Kernel Streaming
4c2c66affSColin Finck  * FILE:            drivers/wdm/audio/sysaudio/main.c
5c2c66affSColin Finck  * PURPOSE:         System Audio graph builder
6c2c66affSColin Finck  * PROGRAMMER:      Andrew Greenwood
7c2c66affSColin Finck  *                  Johannes Anderwald
8c2c66affSColin Finck  * HISTORY:
9c2c66affSColin Finck  *                  8 Jul 07    Started basic implementation
10c2c66affSColin Finck  */
11c2c66affSColin Finck 
12c2c66affSColin Finck #include "sysaudio.h"
13c2c66affSColin Finck 
14c2c66affSColin Finck #define NDEBUG
15c2c66affSColin Finck #include <debug.h>
16c2c66affSColin Finck 
17*5b54477dSSerge Gautherie #define TAG_SYSAUDIO 'AsyS'
18*5b54477dSSerge Gautherie 
19c2c66affSColin Finck const GUID KSCATEGORY_SYSAUDIO                 = {0xA7C7A5B1L, 0x5AF3, 0x11D1, {0x9C, 0xED, 0x00, 0xA0, 0x24, 0xBF, 0x04, 0x07}};
20c2c66affSColin Finck const GUID KSCATEGORY_AUDIO_DEVICE             = {0xFBF6F530L, 0x07B9, 0x11D2, {0xA7, 0x1E, 0x00, 0x00, 0xF8, 0x00, 0x47, 0x88}};
21c2c66affSColin Finck const GUID KSCATEGORY_PREFERRED_WAVEOUT_DEVICE = {0xD6C5066EL, 0x72C1, 0x11D2, {0x97, 0x55, 0x00, 0x00, 0xF8, 0x00, 0x47, 0x88}};
22c2c66affSColin Finck const GUID KSCATEGORY_PREFERRED_WAVEIN_DEVICE  = {0xD6C50671L, 0x72C1, 0x11D2, {0x97, 0x55, 0x00, 0x00, 0xF8, 0x00, 0x47, 0x88}};
23c2c66affSColin Finck const GUID KSCATEGORY_PREFERRED_MIDIOUT_DEVICE = {0xD6C50674L, 0x72C1, 0x11D2, {0x97, 0x55, 0x00, 0x00, 0xF8, 0x00, 0x47, 0x88}};
24c2c66affSColin Finck 
25c2c66affSColin Finck PVOID
AllocateItem(IN POOL_TYPE PoolType,IN SIZE_T NumberOfBytes)26c2c66affSColin Finck AllocateItem(
27c2c66affSColin Finck     IN POOL_TYPE PoolType,
28c2c66affSColin Finck     IN SIZE_T NumberOfBytes)
29c2c66affSColin Finck {
30*5b54477dSSerge Gautherie     return ExAllocatePoolZero(PoolType, NumberOfBytes, TAG_SYSAUDIO);
31c2c66affSColin Finck }
32c2c66affSColin Finck 
33c2c66affSColin Finck VOID
FreeItem(IN PVOID Item)34c2c66affSColin Finck FreeItem(
35c2c66affSColin Finck     IN PVOID Item)
36c2c66affSColin Finck {
37*5b54477dSSerge Gautherie     ExFreePoolWithTag(Item, TAG_SYSAUDIO);
38c2c66affSColin Finck }
39c2c66affSColin Finck 
40c2c66affSColin Finck VOID
41c2c66affSColin Finck NTAPI
SysAudio_Unload(IN PDRIVER_OBJECT DriverObject)42c2c66affSColin Finck SysAudio_Unload(IN PDRIVER_OBJECT DriverObject)
43c2c66affSColin Finck {
44c2c66affSColin Finck     DPRINT("SysAudio_Unload called\n");
45c2c66affSColin Finck }
46c2c66affSColin Finck 
47c2c66affSColin Finck NTSTATUS
48c2c66affSColin Finck NTAPI
SysAudio_Shutdown(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)49c2c66affSColin Finck SysAudio_Shutdown(
50c2c66affSColin Finck     IN  PDEVICE_OBJECT DeviceObject,
51c2c66affSColin Finck     IN  PIRP Irp)
52c2c66affSColin Finck {
53c2c66affSColin Finck     PKSAUDIO_DEVICE_ENTRY DeviceEntry;
54c2c66affSColin Finck     PSYSAUDIODEVEXT DeviceExtension;
55c2c66affSColin Finck     PLIST_ENTRY Entry;
56c2c66affSColin Finck 
57c2c66affSColin Finck     DPRINT("SysAudio_Shutdown called\n");
58c2c66affSColin Finck 
59c2c66affSColin Finck     DeviceExtension = (PSYSAUDIODEVEXT)DeviceObject->DeviceExtension;
60c2c66affSColin Finck 
61c2c66affSColin Finck     while(!IsListEmpty(&DeviceExtension->KsAudioDeviceList))
62c2c66affSColin Finck     {
63c2c66affSColin Finck         Entry = RemoveHeadList(&DeviceExtension->KsAudioDeviceList);
64c2c66affSColin Finck         DeviceEntry = (PKSAUDIO_DEVICE_ENTRY)CONTAINING_RECORD(Entry, KSAUDIO_DEVICE_ENTRY, Entry);
65c2c66affSColin Finck 
66c2c66affSColin Finck         DPRINT("Freeing item %wZ\n", &DeviceEntry->DeviceName);
67c2c66affSColin Finck 
68c2c66affSColin Finck         /* dereference audio device file object */
69c2c66affSColin Finck         ObDereferenceObject(DeviceEntry->FileObject);
70c2c66affSColin Finck 
71c2c66affSColin Finck         /* close audio device handle */
72c2c66affSColin Finck         ZwClose(DeviceEntry->Handle);
73c2c66affSColin Finck 
74c2c66affSColin Finck         /* free device string */
75c2c66affSColin Finck         RtlFreeUnicodeString(&DeviceEntry->DeviceName);
76c2c66affSColin Finck 
77c2c66affSColin Finck         /* free audio device entry */
78c2c66affSColin Finck         FreeItem(DeviceEntry);
79c2c66affSColin Finck     }
80c2c66affSColin Finck 
81c2c66affSColin Finck     Irp->IoStatus.Information = 0;
82c2c66affSColin Finck     Irp->IoStatus.Status = STATUS_SUCCESS;
83c2c66affSColin Finck     IoCompleteRequest(Irp, IO_NO_INCREMENT);
84c2c66affSColin Finck     return STATUS_SUCCESS;
85c2c66affSColin Finck }
86c2c66affSColin Finck 
87c2c66affSColin Finck NTSTATUS
88c2c66affSColin Finck NTAPI
SysAudio_Pnp(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)89c2c66affSColin Finck SysAudio_Pnp(
90c2c66affSColin Finck     IN  PDEVICE_OBJECT DeviceObject,
91c2c66affSColin Finck     IN  PIRP Irp)
92c2c66affSColin Finck {
93c2c66affSColin Finck     PIO_STACK_LOCATION IrpStack;
94c2c66affSColin Finck     UNICODE_STRING SymlinkName = RTL_CONSTANT_STRING(L"\\DosDevices\\sysaudio");
95c2c66affSColin Finck     SYSAUDIODEVEXT *DeviceExtension;
96c2c66affSColin Finck 
97c2c66affSColin Finck     /* Get current irp stack */
98c2c66affSColin Finck     IrpStack = IoGetCurrentIrpStackLocation(Irp);
99c2c66affSColin Finck 
100c2c66affSColin Finck     /* Fetch the device extension */
101c2c66affSColin Finck     DeviceExtension = (SYSAUDIODEVEXT*)DeviceObject->DeviceExtension;
102c2c66affSColin Finck     ASSERT(DeviceExtension);
103c2c66affSColin Finck 
104c2c66affSColin Finck     if (IrpStack->MinorFunction == IRP_MN_REMOVE_DEVICE)
105c2c66affSColin Finck     {
106c2c66affSColin Finck         /* Unregister the echo cancel hook */
107c2c66affSColin Finck         if (DeviceExtension->EchoCancelNotificationEntry)
108c2c66affSColin Finck             IoUnregisterPlugPlayNotification(DeviceExtension->EchoCancelNotificationEntry);
109c2c66affSColin Finck 
110c2c66affSColin Finck         /* Unregister the ks audio hook */
111c2c66affSColin Finck         if (DeviceExtension->KsAudioNotificationEntry)
112c2c66affSColin Finck             IoUnregisterPlugPlayNotification(DeviceExtension->KsAudioNotificationEntry);
113c2c66affSColin Finck 
114c2c66affSColin Finck         /* Destroy our symbolic link */
115c2c66affSColin Finck         IoDeleteSymbolicLink(&SymlinkName);
116c2c66affSColin Finck     }
117c2c66affSColin Finck     else if (IrpStack->MinorFunction == IRP_MN_QUERY_PNP_DEVICE_STATE)
118c2c66affSColin Finck     {
119c2c66affSColin Finck         /* Sysaudio can not be disabled */
120c2c66affSColin Finck         Irp->IoStatus.Information |= PNP_DEVICE_NOT_DISABLEABLE;
121c2c66affSColin Finck     }
122c2c66affSColin Finck 
123c2c66affSColin Finck     /* Perform default pnp actions */
124c2c66affSColin Finck     return KsDefaultDispatchPnp(DeviceObject, Irp);
125c2c66affSColin Finck }
126c2c66affSColin Finck 
127c2c66affSColin Finck NTSTATUS
128c2c66affSColin Finck NTAPI
SysAudio_AddDevice(IN PDRIVER_OBJECT DriverObject,IN PDEVICE_OBJECT PhysicalDeviceObject)129c2c66affSColin Finck SysAudio_AddDevice(
130c2c66affSColin Finck     IN  PDRIVER_OBJECT DriverObject,
131c2c66affSColin Finck     IN PDEVICE_OBJECT PhysicalDeviceObject)
132c2c66affSColin Finck {
133c2c66affSColin Finck     NTSTATUS Status;
134c2c66affSColin Finck     UNICODE_STRING DeviceName = RTL_CONSTANT_STRING(L"\\Device\\sysaudio");
135c2c66affSColin Finck     UNICODE_STRING SymlinkName = RTL_CONSTANT_STRING(L"\\DosDevices\\sysaudio");
136c2c66affSColin Finck 	PDEVICE_OBJECT DeviceObject, NextDeviceObject;
137c2c66affSColin Finck     SYSAUDIODEVEXT *DeviceExtension;
138c2c66affSColin Finck 
139c2c66affSColin Finck     DPRINT("SysAudio_AddDevice called\n");
140c2c66affSColin Finck 
141c2c66affSColin Finck     /* Create the device */
142c2c66affSColin Finck     Status = IoCreateDevice(DriverObject,
143c2c66affSColin Finck                             sizeof(SYSAUDIODEVEXT),
144c2c66affSColin Finck                             &DeviceName,
145c2c66affSColin Finck                             FILE_DEVICE_KS,
146c2c66affSColin Finck                             0,
147c2c66affSColin Finck                             FALSE,
148c2c66affSColin Finck                             &DeviceObject);
149c2c66affSColin Finck 
150c2c66affSColin Finck     /* Check for success */
151c2c66affSColin Finck     if (!NT_SUCCESS(Status))
152c2c66affSColin Finck     {
153c2c66affSColin Finck         DPRINT("Failed to create \\Device\\sysaudio !\n");
154c2c66affSColin Finck         return Status;
155c2c66affSColin Finck     }
156c2c66affSColin Finck 
157c2c66affSColin Finck     /* Register device interfaces */
158c2c66affSColin Finck     Status = SysAudioRegisterDeviceInterfaces(PhysicalDeviceObject);
159c2c66affSColin Finck     if (!NT_SUCCESS(Status))
160c2c66affSColin Finck     {
161c2c66affSColin Finck         /* Failed to register
162c2c66affSColin Finck          * Create a hack interface
163c2c66affSColin Finck          */
164c2c66affSColin Finck         Status = IoCreateSymbolicLink(&SymlinkName, &DeviceName);
165c2c66affSColin Finck         if (!NT_SUCCESS(Status))
166c2c66affSColin Finck         {
167c2c66affSColin Finck             IoDeleteDevice(DeviceObject);
168c2c66affSColin Finck             DPRINT1("Failed to create sysaudio symlink!\n");
169c2c66affSColin Finck             return Status;
170c2c66affSColin Finck         }
171c2c66affSColin Finck     }
172c2c66affSColin Finck     /* Acquire device extension */
173c2c66affSColin Finck     DeviceExtension = (SYSAUDIODEVEXT*)DeviceObject->DeviceExtension;
174c2c66affSColin Finck     /* Initialize device extension */
175c2c66affSColin Finck     RtlZeroMemory(DeviceExtension, sizeof(SYSAUDIODEVEXT));
176c2c66affSColin Finck 
177c2c66affSColin Finck     /* Initialize the mutex */
178c2c66affSColin Finck     KeInitializeSpinLock(&DeviceExtension->Lock);
179c2c66affSColin Finck 
180c2c66affSColin Finck     /* Initialize the ks audio device list */
181c2c66affSColin Finck     InitializeListHead(&DeviceExtension->KsAudioDeviceList);
182c2c66affSColin Finck 
183c2c66affSColin Finck     /* Allocate kernel streaming device header */
184c2c66affSColin Finck     Status = SysAudioAllocateDeviceHeader(DeviceExtension);
185c2c66affSColin Finck     if (!NT_SUCCESS(Status))
186c2c66affSColin Finck     {
187c2c66affSColin Finck         DPRINT1("KsAllocateDeviceHeader failed with %x\n", Status);
188c2c66affSColin Finck         goto cleanup;
189c2c66affSColin Finck     }
190c2c66affSColin Finck 
191c2c66affSColin Finck     /* Register device notification hooks */
192c2c66affSColin Finck     Status = SysAudioRegisterNotifications(DriverObject,
193c2c66affSColin Finck                                            DeviceObject);
194c2c66affSColin Finck     if (!NT_SUCCESS(Status))
195c2c66affSColin Finck     {
196c2c66affSColin Finck         DPRINT1("Failed to register device notifications\n");
197c2c66affSColin Finck         goto cleanup;
198c2c66affSColin Finck     }
199c2c66affSColin Finck 
200c2c66affSColin Finck     /* Load kmixer */
201c2c66affSColin Finck     Status = SysAudioOpenKMixer(DeviceExtension);
202c2c66affSColin Finck     if (!NT_SUCCESS(Status))
203c2c66affSColin Finck     {
204c2c66affSColin Finck         DPRINT1("SysAudioOpenKMixer failed with %x\n", Status);
205c2c66affSColin Finck         goto cleanup;
206c2c66affSColin Finck     }
207c2c66affSColin Finck 
208c2c66affSColin Finck      /* set io flags */
209c2c66affSColin Finck      DeviceObject->Flags |= DO_DIRECT_IO | DO_POWER_PAGABLE;
210c2c66affSColin Finck      /* clear initializing flag */
211c2c66affSColin Finck      DeviceObject->Flags &= ~ DO_DEVICE_INITIALIZING;
212c2c66affSColin Finck 
213c2c66affSColin Finck      /* atttach to device stack */
214c2c66affSColin Finck      NextDeviceObject = IoAttachDeviceToDeviceStack(DeviceObject, PhysicalDeviceObject);
215c2c66affSColin Finck      KsSetDevicePnpAndBaseObject(DeviceExtension->KsDeviceHeader, NextDeviceObject, DeviceObject);
216c2c66affSColin Finck 
217c2c66affSColin Finck      /* register shutdown notification */
218c2c66affSColin Finck      IoRegisterShutdownNotification(DeviceObject);
219c2c66affSColin Finck 
220c2c66affSColin Finck     /* Done */
221c2c66affSColin Finck     return STATUS_SUCCESS;
222c2c66affSColin Finck 
223c2c66affSColin Finck cleanup:
224c2c66affSColin Finck 
225c2c66affSColin Finck     if (DeviceExtension->KsAudioNotificationEntry)
226c2c66affSColin Finck         IoUnregisterPlugPlayNotification(DeviceExtension->KsAudioNotificationEntry);
227c2c66affSColin Finck 
228c2c66affSColin Finck     if (DeviceExtension->EchoCancelNotificationEntry)
229c2c66affSColin Finck         IoUnregisterPlugPlayNotification(DeviceExtension->EchoCancelNotificationEntry);
230c2c66affSColin Finck 
231c2c66affSColin Finck     IoDeleteSymbolicLink(&SymlinkName);
232c2c66affSColin Finck     IoDeleteDevice(DeviceObject);
233c2c66affSColin Finck     return Status;
234c2c66affSColin Finck }
235c2c66affSColin Finck 
236c2c66affSColin Finck NTSTATUS
237c2c66affSColin Finck NTAPI
DriverEntry(IN PDRIVER_OBJECT DriverObject,IN PUNICODE_STRING RegistryPath)238c2c66affSColin Finck DriverEntry(
239c2c66affSColin Finck     IN  PDRIVER_OBJECT DriverObject,
240c2c66affSColin Finck     IN  PUNICODE_STRING RegistryPath)
241c2c66affSColin Finck {
242c2c66affSColin Finck     DPRINT("System audio graph builder (sysaudio) started\n");
243c2c66affSColin Finck 
244c2c66affSColin Finck     /* Let ks handle these */
245c2c66affSColin Finck     KsSetMajorFunctionHandler(DriverObject, IRP_MJ_CREATE);
246c2c66affSColin Finck     KsSetMajorFunctionHandler(DriverObject, IRP_MJ_CLOSE);
247c2c66affSColin Finck     KsSetMajorFunctionHandler(DriverObject, IRP_MJ_WRITE);
248c2c66affSColin Finck     KsSetMajorFunctionHandler(DriverObject, IRP_MJ_DEVICE_CONTROL);
249c2c66affSColin Finck 
250c2c66affSColin Finck     /* Let ks handle these */
251c2c66affSColin Finck     DriverObject->MajorFunction[IRP_MJ_POWER] = KsDefaultDispatchPower;
252c2c66affSColin Finck     DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = KsDefaultForwardIrp;
253c2c66affSColin Finck 
254c2c66affSColin Finck     /* Use provided ks unload function */
255c2c66affSColin Finck     DriverObject->DriverUnload = KsNullDriverUnload;
256c2c66affSColin Finck 
257c2c66affSColin Finck     /* Sysaudio needs to do work on pnp, so handle it */
258c2c66affSColin Finck     DriverObject->MajorFunction[IRP_MJ_PNP] = SysAudio_Pnp;
259c2c66affSColin Finck     DriverObject->MajorFunction[IRP_MJ_SHUTDOWN] = SysAudio_Shutdown;
260c2c66affSColin Finck     DriverObject->DriverExtension->AddDevice = SysAudio_AddDevice;
261c2c66affSColin Finck 
262c2c66affSColin Finck     /* done */
263c2c66affSColin Finck     return STATUS_SUCCESS;
264c2c66affSColin Finck }
265