2 * PROJECT: ReactOS Sound System
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: dll/win32/wdmaud.drv/wdmaud.c
6 * PURPOSE: WDM Audio Driver (User-mode part)
7 * PROGRAMMERS: Andrew Greenwood (silverblade@reactos.org)
9 * NOTES: Looking for wodMessage & co? You won't find them here. Try
10 * the MME Buddy library, which is where these routines are
11 * actually implemented.
23 #include "interface.h"
25 #define KERNEL_DEVICE_NAME L"\\\\.\\wdmaud"
27 PWSTR UnknownWaveIn
= L
"Wave Input";
28 PWSTR UnknownWaveOut
= L
"Wave Output";
29 PWSTR UnknownMidiIn
= L
"Midi Input";
30 PWSTR UnknownMidiOut
= L
"Midi Output";
32 HANDLE KernelHandle
= INVALID_HANDLE_VALUE
;
39 IN MMDEVICE_TYPE DeviceType
,
40 OUT DWORD
* DeviceCount
)
43 WDMAUD_DEVICE_INFO DeviceInfo
;
45 VALIDATE_MMSYS_PARAMETER( Handle
!= INVALID_HANDLE_VALUE
);
46 VALIDATE_MMSYS_PARAMETER( IS_VALID_SOUND_DEVICE_TYPE(DeviceType
) );
47 VALIDATE_MMSYS_PARAMETER( DeviceCount
);
49 ZeroMemory(&DeviceInfo
, sizeof(WDMAUD_DEVICE_INFO
));
50 DeviceInfo
.DeviceType
= DeviceType
;
52 Result
= SyncOverlappedDeviceIoControl(Handle
,
53 IOCTL_GETNUMDEVS_TYPE
,
55 sizeof(WDMAUD_DEVICE_INFO
),
57 sizeof(WDMAUD_DEVICE_INFO
),
60 if ( ! MMSUCCESS( Result
) )
62 SND_ERR(L
"Call to IOCTL_GETNUMDEVS_TYPE failed\n");
64 return TranslateInternalMmResult(Result
);
67 *DeviceCount
= DeviceInfo
.DeviceCount
;
69 return MMSYSERR_NOERROR
;
73 GetWdmDeviceCapabilities(
74 IN PSOUND_DEVICE SoundDevice
,
75 OUT PVOID Capabilities
,
76 IN DWORD CapabilitiesSize
)
78 /* NOTE - At this time, WDMAUD does not support this properly */
81 MMDEVICE_TYPE DeviceType
;
82 WDMAUD_DEVICE_INFO DeviceInfo
;
84 SND_ASSERT( SoundDevice
);
85 SND_ASSERT( Capabilities
);
87 SND_TRACE(L
"WDMAUD - GetWdmDeviceCapabilities\n");
89 Result
= GetSoundDeviceType(SoundDevice
, &DeviceType
);
90 SND_ASSERT( Result
== MMSYSERR_NOERROR
);
92 if ( ! MMSUCCESS(Result
) )
96 ZeroMemory(&DeviceInfo
, sizeof(WDMAUD_DEVICE_INFO
));
97 DeviceInfo
.DeviceType
= DeviceType
;
98 DeviceInfo
.DeviceIndex
= 0; //FIXME
100 Result
= SyncOverlappedDeviceIoControl(KernelHandle
,
101 IOCTL_GETCAPABILITIES
,
102 (LPVOID
) &DeviceInfo
,
103 sizeof(WDMAUD_DEVICE_INFO
),
104 (LPVOID
) &DeviceInfo
,
105 sizeof(WDMAUD_DEVICE_INFO
),
108 if ( ! MMSUCCESS(Result
) )
110 return TranslateInternalMmResult(Result
);
114 /* This is pretty much a big hack right now */
115 switch ( DeviceType
)
117 case WAVE_OUT_DEVICE_TYPE
:
119 LPWAVEOUTCAPS WaveOutCaps
= (LPWAVEOUTCAPS
) Capabilities
;
120 WaveOutCaps
->wMid
= DeviceInfo
.u
.WaveOutCaps
.wMid
;
121 WaveOutCaps
->wPid
= DeviceInfo
.u
.WaveOutCaps
.wPid
;
123 WaveOutCaps
->vDriverVersion
= 0x0001;
124 CopyWideString(WaveOutCaps
->szPname
, UnknownWaveOut
);
126 WaveOutCaps
->dwFormats
= DeviceInfo
.u
.WaveOutCaps
.dwFormats
;
127 WaveOutCaps
->wChannels
= DeviceInfo
.u
.WaveOutCaps
.wChannels
;
128 WaveOutCaps
->dwSupport
= DeviceInfo
.u
.WaveOutCaps
.dwSupport
;
131 case WAVE_IN_DEVICE_TYPE
:
133 LPWAVEINCAPS WaveInCaps
= (LPWAVEINCAPS
) Capabilities
;
134 CopyWideString(WaveInCaps
->szPname
, UnknownWaveIn
);
135 /* TODO... other fields */
140 return MMSYSERR_NOERROR
;
146 IN
struct _SOUND_DEVICE
* SoundDevice
, /* NOT USED */
149 /* Only open this if it's not already open */
150 if ( KernelHandle
== INVALID_HANDLE_VALUE
)
152 SND_TRACE(L
"Opening wdmaud device\n");
153 KernelHandle
= CreateFileW(KERNEL_DEVICE_NAME
,
154 GENERIC_READ
| GENERIC_WRITE
,
158 FILE_FLAG_OVERLAPPED
,
162 if ( KernelHandle
== INVALID_HANDLE_VALUE
)
163 return MMSYSERR_ERROR
;
165 SND_ASSERT( Handle
);
167 *Handle
= KernelHandle
;
170 return MMSYSERR_NOERROR
;
175 IN
struct _SOUND_DEVICE_INSTANCE
* SoundDeviceInstance
,
178 WDMAUD_DEVICE_INFO DeviceInfo
;
180 MMDEVICE_TYPE DeviceType
;
181 PSOUND_DEVICE SoundDevice
;
183 Result
= GetSoundDeviceFromInstance(SoundDeviceInstance
, &SoundDevice
);
185 if ( ! MMSUCCESS(Result
) )
187 return TranslateInternalMmResult(Result
);
190 if ( OpenCount
== 0 )
192 return MMSYSERR_NOERROR
;
195 SND_ASSERT( KernelHandle
!= INVALID_HANDLE_VALUE
);
197 Result
= GetSoundDeviceType(SoundDevice
, &DeviceType
);
198 SND_ASSERT( Result
== MMSYSERR_NOERROR
);
200 if (SoundDeviceInstance
->Handle
!= (PVOID
)KernelHandle
)
202 ZeroMemory(&DeviceInfo
, sizeof(WDMAUD_DEVICE_INFO
));
204 DeviceInfo
.DeviceType
= DeviceType
;
205 DeviceInfo
.hDevice
= SoundDeviceInstance
->Handle
;
207 SyncOverlappedDeviceIoControl(KernelHandle
,
209 (LPVOID
) &DeviceInfo
,
210 sizeof(WDMAUD_DEVICE_INFO
),
211 (LPVOID
) &DeviceInfo
,
212 sizeof(WDMAUD_DEVICE_INFO
),
220 CloseHandle(KernelHandle
);
221 KernelHandle
= INVALID_HANDLE_VALUE
;
224 return MMSYSERR_NOERROR
;
229 QueryWdmWaveDeviceFormatSupport(
230 IN PSOUND_DEVICE Device
,
231 IN PWAVEFORMATEX WaveFormat
,
232 IN DWORD WaveFormatSize
)
235 return MMSYSERR_NOERROR
;
239 SetWdmWaveDeviceFormat(
240 IN PSOUND_DEVICE_INSTANCE Instance
,
242 IN PWAVEFORMATEX WaveFormat
,
243 IN DWORD WaveFormatSize
)
246 PSOUND_DEVICE SoundDevice
;
248 WDMAUD_DEVICE_INFO DeviceInfo
;
249 MMDEVICE_TYPE DeviceType
;
251 Result
= GetSoundDeviceFromInstance(Instance
, &SoundDevice
);
253 if ( ! MMSUCCESS(Result
) )
255 return TranslateInternalMmResult(Result
);
258 Result
= GetSoundDeviceIdentifier(SoundDevice
, &Identifier
);
260 if ( ! MMSUCCESS(Result
) )
262 return TranslateInternalMmResult(Result
);
265 if (Instance
->Handle
!= KernelHandle
)
267 /* device is already open */
268 return MMSYSERR_NOERROR
;
272 Result
= GetSoundDeviceType(SoundDevice
, &DeviceType
);
273 SND_ASSERT( Result
== MMSYSERR_NOERROR
);
275 ZeroMemory(&DeviceInfo
, sizeof(WDMAUD_DEVICE_INFO
));
276 DeviceInfo
.DeviceType
= DeviceType
;
277 DeviceInfo
.DeviceIndex
= DeviceId
;
278 DeviceInfo
.u
.WaveFormatEx
.cbSize
= WaveFormat
->cbSize
;
279 DeviceInfo
.u
.WaveFormatEx
.wFormatTag
= WaveFormat
->wFormatTag
;
280 DeviceInfo
.u
.WaveFormatEx
.nChannels
= WaveFormat
->nChannels
;
281 DeviceInfo
.u
.WaveFormatEx
.nSamplesPerSec
= WaveFormat
->nSamplesPerSec
;
282 DeviceInfo
.u
.WaveFormatEx
.nBlockAlign
= WaveFormat
->nBlockAlign
;
283 DeviceInfo
.u
.WaveFormatEx
.nAvgBytesPerSec
= WaveFormat
->nAvgBytesPerSec
;
284 DeviceInfo
.u
.WaveFormatEx
.wBitsPerSample
= WaveFormat
->wBitsPerSample
;
286 Result
= SyncOverlappedDeviceIoControl(KernelHandle
,
288 (LPVOID
) &DeviceInfo
,
289 sizeof(WDMAUD_DEVICE_INFO
),
290 (LPVOID
) &DeviceInfo
,
291 sizeof(WDMAUD_DEVICE_INFO
),
294 if ( ! MMSUCCESS(Result
) )
296 return TranslateInternalMmResult(Result
);
299 Instance
->Handle
= (PVOID
)DeviceInfo
.hDevice
;
301 return MMSYSERR_NOERROR
;
305 WriteFileEx_Committer2(
306 IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance
,
309 IN PSOUND_OVERLAPPED Overlap
,
310 IN LPOVERLAPPED_COMPLETION_ROUTINE CompletionRoutine
)
313 WDMAUD_DEVICE_INFO DeviceInfo
;
316 VALIDATE_MMSYS_PARAMETER( SoundDeviceInstance
);
317 VALIDATE_MMSYS_PARAMETER( OffsetPtr
);
318 VALIDATE_MMSYS_PARAMETER( Overlap
);
319 VALIDATE_MMSYS_PARAMETER( CompletionRoutine
);
321 GetSoundDeviceInstanceHandle(SoundDeviceInstance
, &Handle
);
325 ZeroMemory(&DeviceInfo
, sizeof(WDMAUD_DEVICE_INFO
));
326 DeviceInfo
.hDevice
= Handle
;
327 DeviceInfo
.DeviceType
= WAVE_OUT_DEVICE_TYPE
; //FIXME
328 DeviceInfo
.Buffer
= OffsetPtr
;
329 DeviceInfo
.BufferSize
= Length
;
331 Overlap
->Standard
.hEvent
= CreateEventW(NULL
, FALSE
, FALSE
, NULL
);
333 if ( ! WriteFileEx(KernelHandle
, &DeviceInfo
, sizeof(WDMAUD_DEVICE_INFO
), (LPOVERLAPPED
)Overlap
, CompletionRoutine
))
335 SND_TRACE(L
"WriteFileEx failed with %x\n", GetLastError());
339 WaitForSingleObjectEx (KernelHandle
, INFINITE
, TRUE
);
343 return MMSYSERR_NOERROR
;
348 IN
struct _SOUND_DEVICE_INSTANCE
* SoundDeviceInstance
,
352 PSOUND_DEVICE SoundDevice
;
353 WDMAUD_DEVICE_INFO DeviceInfo
;
354 MMDEVICE_TYPE DeviceType
;
357 Result
= GetSoundDeviceFromInstance(SoundDeviceInstance
, &SoundDevice
);
359 if ( ! MMSUCCESS(Result
) )
361 return TranslateInternalMmResult(Result
);
364 Result
= GetSoundDeviceType(SoundDevice
, &DeviceType
);
365 SND_ASSERT( Result
== MMSYSERR_NOERROR
);
367 Result
= GetSoundDeviceInstanceHandle(SoundDeviceInstance
, &Handle
);
368 SND_ASSERT( Result
== MMSYSERR_NOERROR
);
370 ZeroMemory(&DeviceInfo
, sizeof(WDMAUD_DEVICE_INFO
));
371 DeviceInfo
.hDevice
= Handle
;
372 DeviceInfo
.DeviceType
= DeviceType
;
374 Result
= SyncOverlappedDeviceIoControl(KernelHandle
,
376 (LPVOID
) &DeviceInfo
,
377 sizeof(WDMAUD_DEVICE_INFO
),
378 (LPVOID
) &DeviceInfo
,
379 sizeof(WDMAUD_DEVICE_INFO
),
382 if ( ! MMSUCCESS(Result
) )
384 return TranslateInternalMmResult(Result
);
387 Time
->wType
= TIME_BYTES
;
388 Time
->u
.cb
= (DWORD
)DeviceInfo
.u
.Position
;
390 return MMSYSERR_NOERROR
;
395 PopulateWdmDeviceList(
397 MMDEVICE_TYPE DeviceType
)
400 DWORD DeviceCount
= 0;
401 PSOUND_DEVICE SoundDevice
= NULL
;
402 MMFUNCTION_TABLE FuncTable
;
405 VALIDATE_MMSYS_PARAMETER( Handle
!= INVALID_HANDLE_VALUE
);
406 VALIDATE_MMSYS_PARAMETER( IS_VALID_SOUND_DEVICE_TYPE(DeviceType
) );
408 Result
= GetNumWdmDevs(Handle
, DeviceType
, &DeviceCount
);
410 if ( ! MMSUCCESS(Result
) )
412 SND_ERR(L
"Error %d while obtaining number of devices\n", Result
);
413 return TranslateInternalMmResult(Result
);
416 SND_TRACE(L
"%d devices of type %d found\n", DeviceCount
, DeviceType
);
419 for ( i
= 0; i
< DeviceCount
; ++ i
)
421 Result
= ListSoundDevice(DeviceType
, (PVOID
) i
, &SoundDevice
);
423 if ( ! MMSUCCESS(Result
) )
425 SND_ERR(L
"Failed to list sound device - error %d\n", Result
);
426 return TranslateInternalMmResult(Result
);
429 /* Set up our function table */
430 ZeroMemory(&FuncTable
, sizeof(MMFUNCTION_TABLE
));
431 FuncTable
.GetCapabilities
= GetWdmDeviceCapabilities
;
432 FuncTable
.QueryWaveFormatSupport
= QueryWdmWaveDeviceFormatSupport
;
433 FuncTable
.SetWaveFormat
= SetWdmWaveDeviceFormat
;
434 FuncTable
.Open
= OpenWdmSoundDevice
;
435 FuncTable
.Close
= CloseWdmSoundDevice
;
436 FuncTable
.CommitWaveBuffer
= WriteFileEx_Committer2
;
437 FuncTable
.GetPos
= GetWdmPosition
;
439 SetSoundDeviceFunctionTable(SoundDevice
, &FuncTable
);
442 return MMSYSERR_NOERROR
;
462 SND_TRACE(L
"DRV_LOAD\n");
464 Result
= InitEntrypointMutexes();
466 if ( ! MMSUCCESS(Result
) )
469 OpenWdmSoundDevice(NULL
, &Handle
);
471 if ( Handle
== INVALID_HANDLE_VALUE
)
473 SND_ERR(L
"Failed to open %s\n", KERNEL_DEVICE_NAME
);
474 CleanupEntrypointMutexes();
476 //UnlistAllSoundDevices();
481 /* Populate the device lists */
482 SND_TRACE(L
"Populating device lists\n");
483 PopulateWdmDeviceList(KernelHandle
, WAVE_OUT_DEVICE_TYPE
);
484 PopulateWdmDeviceList(KernelHandle
, WAVE_IN_DEVICE_TYPE
);
485 PopulateWdmDeviceList(KernelHandle
, MIDI_OUT_DEVICE_TYPE
);
486 PopulateWdmDeviceList(KernelHandle
, MIDI_IN_DEVICE_TYPE
);
487 PopulateWdmDeviceList(KernelHandle
, AUX_DEVICE_TYPE
);
488 PopulateWdmDeviceList(KernelHandle
, MIXER_DEVICE_TYPE
);
490 SND_TRACE(L
"Initialisation complete\n");
497 SND_TRACE(L
"DRV_FREE\n");
499 if ( KernelHandle
!= INVALID_HANDLE_VALUE
)
501 CloseHandle(KernelHandle
);
502 KernelHandle
= INVALID_HANDLE_VALUE
;
505 /* TODO: Clean up the path names! */
506 UnlistAllSoundDevices();
508 CleanupEntrypointMutexes();
510 SND_TRACE(L
"Unfreed memory blocks: %d\n",
511 GetMemoryAllocationCount());
519 SND_TRACE(L
"DRV_ENABLE / DRV_DISABLE\n");
526 SND_TRACE(L
"DRV_OPEN / DRV_CLOSE\n");
530 case DRV_QUERYCONFIGURE
:
532 SND_TRACE(L
"DRV_QUERYCONFIGURE\n");
539 SND_TRACE(L
"Unhandled message %d\n", Message
);
540 return DefDriverProc(DriverId
,
556 case DLL_PROCESS_ATTACH
:
557 SND_TRACE(L
"WDMAUD.DRV - Process attached\n");
559 case DLL_PROCESS_DETACH
:
560 SND_TRACE(L
"WDMAUD.DRV - Process detached\n");
562 case DLL_THREAD_ATTACH
:
563 SND_TRACE(L
"WDMAUD.DRV - Thread attached\n");
565 case DLL_THREAD_DETACH
:
566 SND_TRACE(L
"WDMAUD.DRV - Thread detached\n");