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 GetSysAudioDevicePnpName(
40 IN PDEVICE_OBJECT DeviceObject
,
47 PWDMAUD_DEVICE_EXTENSION DeviceExtension
;
49 /* first check if the device index is within bounds */
50 if (DeviceIndex
>= GetSysAudioDeviceCount(DeviceObject
))
51 return STATUS_INVALID_PARAMETER
;
53 /* setup the query request */
54 Pin
.Property
.Set
= KSPROPSETID_Sysaudio
;
55 Pin
.Property
.Id
= KSPROPERTY_SYSAUDIO_DEVICE_INTERFACE_NAME
;
56 Pin
.Property
.Flags
= KSPROPERTY_TYPE_GET
;
57 Pin
.PinId
= DeviceIndex
;
59 DeviceExtension
= (PWDMAUD_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
61 /* query sysaudio for the device path */
62 Status
= KsSynchronousIoControlDevice(DeviceExtension
->FileObject
, KernelMode
, IOCTL_KS_PROPERTY
, (PVOID
)&Pin
, sizeof(KSPROPERTY
) + sizeof(ULONG
), NULL
, 0, &BytesReturned
);
64 /* check if the request failed */
65 if (Status
!= STATUS_BUFFER_TOO_SMALL
|| BytesReturned
== 0)
66 return STATUS_UNSUCCESSFUL
;
68 /* allocate buffer for the device */
69 *Device
= ExAllocatePool(NonPagedPool
, BytesReturned
);
71 return STATUS_INSUFFICIENT_RESOURCES
;
73 /* query sysaudio again for the device path */
74 Status
= KsSynchronousIoControlDevice(DeviceExtension
->FileObject
, KernelMode
, IOCTL_KS_PROPERTY
, (PVOID
)&Pin
, sizeof(KSPROPERTY
) + sizeof(ULONG
), (PVOID
)*Device
, BytesReturned
, &BytesReturned
);
76 if (!NT_SUCCESS(Status
))
87 OpenSysAudioDeviceByIndex(
88 IN PDEVICE_OBJECT DeviceObject
,
90 IN PHANDLE DeviceHandle
,
91 IN PFILE_OBJECT
* FileObject
)
97 Status
= GetSysAudioDevicePnpName(DeviceObject
, DeviceIndex
, &Device
);
98 if (!NT_SUCCESS(Status
))
101 /* now open the device */
102 Status
= WdmAudOpenSysAudioDevice(Device
, &hDevice
);
104 /* free device buffer */
107 if (!NT_SUCCESS(Status
))
112 *DeviceHandle
= hDevice
;
116 Status
= ObReferenceObjectByHandle(hDevice
, FILE_READ_DATA
| FILE_WRITE_DATA
, IoFileObjectType
, KernelMode
, (PVOID
*)FileObject
, NULL
);
118 if (!NT_SUCCESS(Status
))
129 PFILE_OBJECT FileObject
,
130 PKSMULTIPLE_ITEM
* Item
)
134 PKSMULTIPLE_ITEM MultipleItem
;
137 /* setup query request */
138 Property
.Id
= KSPROPERTY_TOPOLOGY_NODES
;
139 Property
.Flags
= KSPROPERTY_TYPE_GET
;
140 Property
.Set
= KSPROPSETID_Topology
;
142 /* query for required size */
143 Status
= KsSynchronousIoControlDevice(FileObject
, KernelMode
, IOCTL_KS_PROPERTY
, (PVOID
)&Property
, sizeof(KSPROPERTY
), NULL
, 0, &BytesReturned
);
145 /* check for success */
146 if (Status
!= STATUS_MORE_ENTRIES
)
149 /* allocate buffer */
150 MultipleItem
= (PKSMULTIPLE_ITEM
)ExAllocatePool(NonPagedPool
, BytesReturned
);
152 return STATUS_INSUFFICIENT_RESOURCES
;
154 /* query for required size */
155 Status
= KsSynchronousIoControlDevice(FileObject
, KernelMode
, IOCTL_KS_PROPERTY
, (PVOID
)&Property
, sizeof(KSPROPERTY
), (PVOID
)MultipleItem
, BytesReturned
, &BytesReturned
);
157 if (!NT_SUCCESS(Status
))
160 ExFreePool(MultipleItem
);
164 *Item
= MultipleItem
;
170 PKSMULTIPLE_ITEM MultipleItem
,
178 Guid
= (LPGUID
)(MultipleItem
+1);
180 /* iterate through node type array */
181 for(Index
= 0; Index
< MultipleItem
->Count
; Index
++)
183 if (IsEqualGUIDAligned(NodeType
, Guid
))
185 /* found matching guid */
195 PKSMULTIPLE_ITEM MultipleItem
,
201 Guid
= (LPGUID
)(MultipleItem
+1);
203 /* iterate through node type array */
204 for(Index
= 0; Index
< MultipleItem
->Count
; Index
++)
206 if (IsEqualGUIDAligned(NodeType
, Guid
))
208 /* found matching guid */
217 GetNumOfMixerDevices(
218 IN PDEVICE_OBJECT DeviceObject
)
220 ULONG DeviceCount
, Index
, Count
;
223 PFILE_OBJECT FileObject
;
224 PKSMULTIPLE_ITEM MultipleItem
;
226 /* get number of devices */
227 DeviceCount
= GetSysAudioDeviceCount(DeviceObject
);
236 /* open the virtual audio device */
237 Status
= OpenSysAudioDeviceByIndex(DeviceObject
, Index
, &hDevice
, &FileObject
);
239 if (NT_SUCCESS(Status
))
241 /* retrieve all available node types */
242 Status
= GetFilterNodeTypes(FileObject
, &MultipleItem
);
243 if (NT_SUCCESS(Status
))
245 if (CountNodeType(MultipleItem
, (LPGUID
)&KSNODETYPE_DAC
))
247 /* increment (output) mixer count */
251 if (CountNodeType(MultipleItem
, (LPGUID
)&KSNODETYPE_ADC
))
253 /* increment (input) mixer count */
256 ExFreePool(MultipleItem
);
258 ObDereferenceObject(FileObject
);
263 }while(Index
< DeviceCount
);
270 IN PDEVICE_OBJECT DeviceObject
,
271 IN ULONG DeviceIndex
)
273 ULONG DeviceCount
, Index
, Count
;
276 PFILE_OBJECT FileObject
;
277 PKSMULTIPLE_ITEM MultipleItem
;
279 /* get number of devices */
280 DeviceCount
= GetSysAudioDeviceCount(DeviceObject
);
289 /* open the virtual audio device */
290 Status
= OpenSysAudioDeviceByIndex(DeviceObject
, Index
, &hDevice
, &FileObject
);
292 if (NT_SUCCESS(Status
))
294 /* retrieve all available node types */
295 Status
= GetFilterNodeTypes(FileObject
, &MultipleItem
);
296 if (NT_SUCCESS(Status
))
298 if (CountNodeType(MultipleItem
, (LPGUID
)&KSNODETYPE_DAC
))
300 /* increment (output) mixer count */
301 if (DeviceIndex
== Count
)
303 ExFreePool(MultipleItem
);
304 ObDereferenceObject(FileObject
);
312 if (CountNodeType(MultipleItem
, (LPGUID
)&KSNODETYPE_ADC
))
314 /* increment (input) mixer count */
315 if (DeviceIndex
== Count
)
317 ExFreePool(MultipleItem
);
318 ObDereferenceObject(FileObject
);
324 ExFreePool(MultipleItem
);
326 ObDereferenceObject(FileObject
);
331 }while(Index
< DeviceCount
);
342 WdmAudMixerCapabilities(
343 IN PDEVICE_OBJECT DeviceObject
,
344 IN PWDMAUD_DEVICE_INFO DeviceInfo
,
345 IN PWDMAUD_CLIENT ClientInfo
)
351 Status
= GetSysAudioDevicePnpName(DeviceObject
, DeviceInfo
->DeviceIndex
,&Device
);
352 if (!NT_SUCCESS(Status
))
354 DPRINT1("Failed to get device name %x\n", Status
);
358 DeviceInfo
->u
.MixCaps
.cDestinations
= 1; //FIXME
360 Status
= FindProductName(Device
, sizeof(Buffer
) / sizeof(WCHAR
), Buffer
);
362 /* check for success */
363 if (!NT_SUCCESS(Status
))
365 DeviceInfo
->u
.MixCaps
.szPname
[0] = L
'\0';
369 if (IsOutputMixer(DeviceObject
, DeviceInfo
->DeviceIndex
))
371 wcscat(Buffer
, L
" output");
375 wcscat(Buffer
, L
" Input");
377 RtlMoveMemory(DeviceInfo
->u
.MixCaps
.szPname
, Buffer
, min(MAXPNAMELEN
, wcslen(Buffer
)+1) * sizeof(WCHAR
));
378 DeviceInfo
->u
.MixCaps
.szPname
[MAXPNAMELEN
-1] = L
'\0';
386 WdmAudControlOpenMixer(
387 IN PDEVICE_OBJECT DeviceObject
,
389 IN PWDMAUD_DEVICE_INFO DeviceInfo
,
390 IN PWDMAUD_CLIENT ClientInfo
)
393 PWDMAUD_HANDLE Handels
;
395 DPRINT("WdmAudControlOpenMixer\n");
397 if (DeviceInfo
->DeviceIndex
>= GetNumOfMixerDevices(DeviceObject
))
399 /* mixer index doesnt exist */
400 return SetIrpIoStatus(Irp
, STATUS_UNSUCCESSFUL
, 0);
403 for(Index
= 0; Index
< ClientInfo
->NumPins
; Index
++)
405 if (ClientInfo
->hPins
[Index
].Handle
== (HANDLE
)DeviceInfo
->DeviceIndex
&& ClientInfo
->hPins
[Index
].Type
== MIXER_DEVICE_TYPE
)
407 /* re-use pseudo handle */
408 DeviceInfo
->hDevice
= (HANDLE
)DeviceInfo
->DeviceIndex
;
409 return SetIrpIoStatus(Irp
, STATUS_SUCCESS
, sizeof(WDMAUD_DEVICE_INFO
));
413 Handels
= ExAllocatePool(NonPagedPool
, sizeof(WDMAUD_HANDLE
) * (ClientInfo
->NumPins
+1));
417 if (ClientInfo
->NumPins
)
419 RtlMoveMemory(Handels
, ClientInfo
->hPins
, sizeof(WDMAUD_HANDLE
) * ClientInfo
->NumPins
);
420 ExFreePool(ClientInfo
->hPins
);
423 ClientInfo
->hPins
= Handels
;
424 ClientInfo
->hPins
[ClientInfo
->NumPins
].Handle
= (HANDLE
)DeviceInfo
->DeviceIndex
;
425 ClientInfo
->hPins
[ClientInfo
->NumPins
].Type
= MIXER_DEVICE_TYPE
;
426 ClientInfo
->NumPins
++;
430 return SetIrpIoStatus(Irp
, STATUS_UNSUCCESSFUL
, sizeof(WDMAUD_DEVICE_INFO
));
432 DeviceInfo
->hDevice
= (HANDLE
)DeviceInfo
->DeviceIndex
;
434 return SetIrpIoStatus(Irp
, STATUS_SUCCESS
, sizeof(WDMAUD_DEVICE_INFO
));
440 IN PDEVICE_OBJECT DeviceObject
,
442 IN PWDMAUD_DEVICE_INFO DeviceInfo
,
443 IN PWDMAUD_CLIENT ClientInfo
)
447 return SetIrpIoStatus(Irp
, STATUS_NOT_IMPLEMENTED
, 0);
453 WdmAudGetLineControls(
454 IN PDEVICE_OBJECT DeviceObject
,
456 IN PWDMAUD_DEVICE_INFO DeviceInfo
,
457 IN PWDMAUD_CLIENT ClientInfo
)
461 return SetIrpIoStatus(Irp
, STATUS_NOT_IMPLEMENTED
, 0);
467 WdmAudSetControlDetails(
468 IN PDEVICE_OBJECT DeviceObject
,
470 IN PWDMAUD_DEVICE_INFO DeviceInfo
,
471 IN PWDMAUD_CLIENT ClientInfo
)
475 return SetIrpIoStatus(Irp
, STATUS_NOT_IMPLEMENTED
, 0);
481 WdmAudGetControlDetails(
482 IN PDEVICE_OBJECT DeviceObject
,
484 IN PWDMAUD_DEVICE_INFO DeviceInfo
,
485 IN PWDMAUD_CLIENT ClientInfo
)
489 return SetIrpIoStatus(Irp
, STATUS_NOT_IMPLEMENTED
, 0);