2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Kernel Streaming
4 * FILE: drivers/wdm/audio/legacy/wdmaud/mixer.c
5 * PURPOSE: System Audio graph builder
6 * PROGRAMMER: Andrew Greenwood
11 const GUID KSNODETYPE_DAC
= {0x507AE360L
, 0xC554, 0x11D0, {0x8A, 0x2B, 0x00, 0xA0, 0xC9, 0x25, 0x5A, 0xC1}};
12 const GUID KSNODETYPE_ADC
= {0x4D837FE0L
, 0xC555, 0x11D0, {0x8A, 0x2B, 0x00, 0xA0, 0xC9, 0x25, 0x5A, 0xC1}};
15 GetSysAudioDeviceCount(
16 IN PDEVICE_OBJECT DeviceObject
)
18 PWDMAUD_DEVICE_EXTENSION DeviceExtension
;
20 ULONG Count
, BytesReturned
;
23 /* setup the query request */
24 Pin
.Set
= KSPROPSETID_Sysaudio
;
25 Pin
.Id
= KSPROPERTY_SYSAUDIO_DEVICE_COUNT
;
26 Pin
.Flags
= KSPROPERTY_TYPE_GET
;
28 DeviceExtension
= (PWDMAUD_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
30 /* query sysaudio for the device count */
31 Status
= KsSynchronousIoControlDevice(DeviceExtension
->FileObject
, KernelMode
, IOCTL_KS_PROPERTY
, (PVOID
)&Pin
, sizeof(KSPROPERTY
), (PVOID
)&Count
, sizeof(ULONG
), &BytesReturned
);
32 if (!NT_SUCCESS(Status
))
39 OpenSysAudioDeviceByIndex(
40 IN PDEVICE_OBJECT DeviceObject
,
42 IN PHANDLE DeviceHandle
,
43 IN PFILE_OBJECT
* FileObject
)
50 PWDMAUD_DEVICE_EXTENSION DeviceExtension
;
52 /* first check if the device index is within bounds */
53 if (DeviceIndex
>= GetSysAudioDeviceCount(DeviceObject
))
54 return STATUS_INVALID_PARAMETER
;
56 /* setup the query request */
57 Pin
.Property
.Set
= KSPROPSETID_Sysaudio
;
58 Pin
.Property
.Id
= KSPROPERTY_SYSAUDIO_DEVICE_INTERFACE_NAME
;
59 Pin
.Property
.Flags
= KSPROPERTY_TYPE_GET
;
60 Pin
.PinId
= DeviceIndex
;
63 DeviceExtension
= (PWDMAUD_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
65 /* query sysaudio for the device path */
66 Status
= KsSynchronousIoControlDevice(DeviceExtension
->FileObject
, KernelMode
, IOCTL_KS_PROPERTY
, (PVOID
)&Pin
, sizeof(KSPROPERTY
) + sizeof(ULONG
), NULL
, 0, &BytesReturned
);
68 /* check if the request failed */
69 if (Status
!= STATUS_BUFFER_TOO_SMALL
|| BytesReturned
== 0)
70 return STATUS_UNSUCCESSFUL
;
72 /* allocate buffer for the device */
73 Device
= ExAllocatePool(NonPagedPool
, BytesReturned
);
75 return STATUS_INSUFFICIENT_RESOURCES
;
77 /* query sysaudio again for the device path */
78 Status
= KsSynchronousIoControlDevice(DeviceExtension
->FileObject
, KernelMode
, IOCTL_KS_PROPERTY
, (PVOID
)&Pin
, sizeof(KSPROPERTY
) + sizeof(ULONG
), (PVOID
)Device
, BytesReturned
, &BytesReturned
);
80 if (!NT_SUCCESS(Status
))
87 /* now open the device */
88 Status
= WdmAudOpenSysAudioDevice(Device
, &hDevice
);
90 /* free device buffer */
93 if (!NT_SUCCESS(Status
))
98 *DeviceHandle
= hDevice
;
102 Status
= ObReferenceObjectByHandle(hDevice
, FILE_READ_DATA
| FILE_WRITE_DATA
, IoFileObjectType
, KernelMode
, (PVOID
*)FileObject
, NULL
);
104 if (!NT_SUCCESS(Status
))
115 PFILE_OBJECT FileObject
,
116 PKSMULTIPLE_ITEM
* Item
)
120 PKSMULTIPLE_ITEM MultipleItem
;
123 /* setup query request */
124 Property
.Id
= KSPROPERTY_TOPOLOGY_NODES
;
125 Property
.Flags
= KSPROPERTY_TYPE_GET
;
126 Property
.Set
= KSPROPSETID_Topology
;
128 /* query for required size */
129 Status
= KsSynchronousIoControlDevice(FileObject
, KernelMode
, IOCTL_KS_PROPERTY
, (PVOID
)&Property
, sizeof(KSPROPERTY
), NULL
, 0, &BytesReturned
);
131 /* check for success */
132 if (Status
!= STATUS_MORE_ENTRIES
)
135 /* allocate buffer */
136 MultipleItem
= (PKSMULTIPLE_ITEM
)ExAllocatePool(NonPagedPool
, BytesReturned
);
138 return STATUS_INSUFFICIENT_RESOURCES
;
140 /* query for required size */
141 Status
= KsSynchronousIoControlDevice(FileObject
, KernelMode
, IOCTL_KS_PROPERTY
, (PVOID
)&Property
, sizeof(KSPROPERTY
), (PVOID
)MultipleItem
, BytesReturned
, &BytesReturned
);
143 if (!NT_SUCCESS(Status
))
146 ExFreePool(MultipleItem
);
150 *Item
= MultipleItem
;
156 PKSMULTIPLE_ITEM MultipleItem
,
164 Guid
= (LPGUID
)(MultipleItem
+1);
166 /* iterate through node type array */
167 for(Index
= 0; Index
< MultipleItem
->Count
; Index
++)
169 if (IsEqualGUIDAligned(NodeType
, Guid
))
171 /* found matching guid */
180 GetNumOfMixerDevices(
181 IN PDEVICE_OBJECT DeviceObject
)
183 ULONG DeviceCount
, Index
, Count
;
186 PFILE_OBJECT FileObject
;
187 PKSMULTIPLE_ITEM MultipleItem
;
189 /* get number of devices */
190 DeviceCount
= GetSysAudioDeviceCount(DeviceObject
);
199 /* open the virtual audio device */
200 Status
= OpenSysAudioDeviceByIndex(DeviceObject
, Index
, &hDevice
, &FileObject
);
202 if (NT_SUCCESS(Status
))
204 /* retrieve all available node types */
205 Status
= GetFilterNodeTypes(FileObject
, &MultipleItem
);
206 if (NT_SUCCESS(Status
))
208 if (CountNodeType(MultipleItem
, (LPGUID
)&KSNODETYPE_DAC
))
210 /* increment (output) mixer count */
214 if (CountNodeType(MultipleItem
, (LPGUID
)&KSNODETYPE_ADC
))
216 /* increment (input) mixer count */
219 ExFreePool(MultipleItem
);
221 ObDereferenceObject(FileObject
);
226 }while(Index
< DeviceCount
);
232 WdmAudControlOpenMixer(
233 IN PDEVICE_OBJECT DeviceObject
,
235 IN PWDMAUD_DEVICE_INFO DeviceInfo
,
236 IN PWDMAUD_CLIENT ClientInfo
)
239 PWDMAUD_HANDLE Handels
;
241 DPRINT("WdmAudControlOpenMixer\n");
243 if (DeviceInfo
->DeviceIndex
>= GetNumOfMixerDevices(DeviceObject
))
245 /* mixer index doesnt exist */
246 return SetIrpIoStatus(Irp
, STATUS_UNSUCCESSFUL
, 0);
249 for(Index
= 0; Index
< ClientInfo
->NumPins
; Index
++)
251 if (ClientInfo
->hPins
[Index
].Handle
== (HANDLE
)DeviceInfo
->DeviceIndex
&& ClientInfo
->hPins
[Index
].Type
== MIXER_DEVICE_TYPE
)
253 /* re-use pseudo handle */
254 DeviceInfo
->hDevice
= (HANDLE
)DeviceInfo
->DeviceIndex
;
255 return SetIrpIoStatus(Irp
, STATUS_SUCCESS
, sizeof(WDMAUD_DEVICE_INFO
));
259 Handels
= ExAllocatePool(NonPagedPool
, sizeof(WDMAUD_HANDLE
) * (ClientInfo
->NumPins
+1));
263 if (ClientInfo
->NumPins
)
265 RtlMoveMemory(Handels
, ClientInfo
->hPins
, sizeof(WDMAUD_HANDLE
) * ClientInfo
->NumPins
);
266 ExFreePool(ClientInfo
->hPins
);
269 ClientInfo
->hPins
= Handels
;
270 ClientInfo
->hPins
[ClientInfo
->NumPins
].Handle
= (HANDLE
)DeviceInfo
->DeviceIndex
;
271 ClientInfo
->hPins
[ClientInfo
->NumPins
].Type
= MIXER_DEVICE_TYPE
;
272 ClientInfo
->NumPins
++;
276 return SetIrpIoStatus(Irp
, STATUS_UNSUCCESSFUL
, sizeof(WDMAUD_DEVICE_INFO
));
278 DeviceInfo
->hDevice
= (HANDLE
)DeviceInfo
->DeviceIndex
;
280 return SetIrpIoStatus(Irp
, STATUS_SUCCESS
, sizeof(WDMAUD_DEVICE_INFO
));