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
,
76 OUT PVOID Capabilities
,
77 IN DWORD CapabilitiesSize
)
79 /* NOTE - At this time, WDMAUD does not support this properly */
82 MMDEVICE_TYPE DeviceType
;
83 WDMAUD_DEVICE_INFO DeviceInfo
;
85 SND_ASSERT( SoundDevice
);
86 SND_ASSERT( Capabilities
);
88 SND_TRACE(L
"WDMAUD - GetWdmDeviceCapabilities\n");
90 Result
= GetSoundDeviceType(SoundDevice
, &DeviceType
);
91 SND_ASSERT( Result
== MMSYSERR_NOERROR
);
93 if ( ! MMSUCCESS(Result
) )
97 ZeroMemory(&DeviceInfo
, sizeof(WDMAUD_DEVICE_INFO
));
98 DeviceInfo
.DeviceType
= DeviceType
;
99 DeviceInfo
.DeviceIndex
= DeviceId
;
101 Result
= SyncOverlappedDeviceIoControl(KernelHandle
,
102 IOCTL_GETCAPABILITIES
,
103 (LPVOID
) &DeviceInfo
,
104 sizeof(WDMAUD_DEVICE_INFO
),
105 (LPVOID
) &DeviceInfo
,
106 sizeof(WDMAUD_DEVICE_INFO
),
109 if ( ! MMSUCCESS(Result
) )
111 return TranslateInternalMmResult(Result
);
115 /* This is pretty much a big hack right now */
116 switch ( DeviceType
)
118 case WAVE_OUT_DEVICE_TYPE
:
120 LPWAVEOUTCAPS WaveOutCaps
= (LPWAVEOUTCAPS
) Capabilities
;
121 WaveOutCaps
->wMid
= DeviceInfo
.u
.WaveOutCaps
.wMid
;
122 WaveOutCaps
->wPid
= DeviceInfo
.u
.WaveOutCaps
.wPid
;
124 WaveOutCaps
->vDriverVersion
= 0x0001;
125 CopyWideString(WaveOutCaps
->szPname
, UnknownWaveOut
);
127 WaveOutCaps
->dwFormats
= DeviceInfo
.u
.WaveOutCaps
.dwFormats
;
128 WaveOutCaps
->wChannels
= DeviceInfo
.u
.WaveOutCaps
.wChannels
;
129 WaveOutCaps
->dwSupport
= DeviceInfo
.u
.WaveOutCaps
.dwSupport
;
132 case WAVE_IN_DEVICE_TYPE
:
134 LPWAVEINCAPS WaveInCaps
= (LPWAVEINCAPS
) Capabilities
;
135 CopyWideString(WaveInCaps
->szPname
, UnknownWaveIn
);
136 /* TODO... other fields */
141 return MMSYSERR_NOERROR
;
147 IN
struct _SOUND_DEVICE
* SoundDevice
, /* NOT USED */
150 /* Only open this if it's not already open */
151 if ( KernelHandle
== INVALID_HANDLE_VALUE
)
153 SND_TRACE(L
"Opening wdmaud device\n");
154 KernelHandle
= CreateFileW(KERNEL_DEVICE_NAME
,
155 GENERIC_READ
| GENERIC_WRITE
,
159 FILE_FLAG_OVERLAPPED
,
163 if ( KernelHandle
== INVALID_HANDLE_VALUE
)
164 return MMSYSERR_ERROR
;
166 SND_ASSERT( Handle
);
168 *Handle
= KernelHandle
;
171 return MMSYSERR_NOERROR
;
176 IN
struct _SOUND_DEVICE_INSTANCE
* SoundDeviceInstance
,
179 WDMAUD_DEVICE_INFO DeviceInfo
;
181 MMDEVICE_TYPE DeviceType
;
182 PSOUND_DEVICE SoundDevice
;
184 Result
= GetSoundDeviceFromInstance(SoundDeviceInstance
, &SoundDevice
);
186 if ( ! MMSUCCESS(Result
) )
188 return TranslateInternalMmResult(Result
);
191 if ( OpenCount
== 0 )
193 return MMSYSERR_NOERROR
;
196 SND_ASSERT( KernelHandle
!= INVALID_HANDLE_VALUE
);
198 Result
= GetSoundDeviceType(SoundDevice
, &DeviceType
);
199 SND_ASSERT( Result
== MMSYSERR_NOERROR
);
201 if (SoundDeviceInstance
->Handle
!= (PVOID
)KernelHandle
)
203 ZeroMemory(&DeviceInfo
, sizeof(WDMAUD_DEVICE_INFO
));
205 DeviceInfo
.DeviceType
= DeviceType
;
206 DeviceInfo
.hDevice
= SoundDeviceInstance
->Handle
;
208 SyncOverlappedDeviceIoControl(KernelHandle
,
210 (LPVOID
) &DeviceInfo
,
211 sizeof(WDMAUD_DEVICE_INFO
),
212 (LPVOID
) &DeviceInfo
,
213 sizeof(WDMAUD_DEVICE_INFO
),
221 CloseHandle(KernelHandle
);
222 KernelHandle
= INVALID_HANDLE_VALUE
;
225 return MMSYSERR_NOERROR
;
230 QueryWdmWaveDeviceFormatSupport(
231 IN PSOUND_DEVICE Device
,
232 IN PWAVEFORMATEX WaveFormat
,
233 IN DWORD WaveFormatSize
)
236 return MMSYSERR_NOERROR
;
240 SetWdmWaveDeviceFormat(
241 IN PSOUND_DEVICE_INSTANCE Instance
,
243 IN PWAVEFORMATEX WaveFormat
,
244 IN DWORD WaveFormatSize
)
247 PSOUND_DEVICE SoundDevice
;
249 WDMAUD_DEVICE_INFO DeviceInfo
;
250 MMDEVICE_TYPE DeviceType
;
252 Result
= GetSoundDeviceFromInstance(Instance
, &SoundDevice
);
254 if ( ! MMSUCCESS(Result
) )
256 return TranslateInternalMmResult(Result
);
259 Result
= GetSoundDeviceIdentifier(SoundDevice
, &Identifier
);
261 if ( ! MMSUCCESS(Result
) )
263 return TranslateInternalMmResult(Result
);
266 if (Instance
->Handle
!= KernelHandle
)
268 /* device is already open */
269 return MMSYSERR_NOERROR
;
273 Result
= GetSoundDeviceType(SoundDevice
, &DeviceType
);
274 SND_ASSERT( Result
== MMSYSERR_NOERROR
);
276 ZeroMemory(&DeviceInfo
, sizeof(WDMAUD_DEVICE_INFO
));
277 DeviceInfo
.DeviceType
= DeviceType
;
278 DeviceInfo
.DeviceIndex
= DeviceId
;
279 DeviceInfo
.u
.WaveFormatEx
.cbSize
= WaveFormat
->cbSize
;
280 DeviceInfo
.u
.WaveFormatEx
.wFormatTag
= WaveFormat
->wFormatTag
;
281 DeviceInfo
.u
.WaveFormatEx
.nChannels
= WaveFormat
->nChannels
;
282 DeviceInfo
.u
.WaveFormatEx
.nSamplesPerSec
= WaveFormat
->nSamplesPerSec
;
283 DeviceInfo
.u
.WaveFormatEx
.nBlockAlign
= WaveFormat
->nBlockAlign
;
284 DeviceInfo
.u
.WaveFormatEx
.nAvgBytesPerSec
= WaveFormat
->nAvgBytesPerSec
;
285 DeviceInfo
.u
.WaveFormatEx
.wBitsPerSample
= WaveFormat
->wBitsPerSample
;
287 Result
= SyncOverlappedDeviceIoControl(KernelHandle
,
289 (LPVOID
) &DeviceInfo
,
290 sizeof(WDMAUD_DEVICE_INFO
),
291 (LPVOID
) &DeviceInfo
,
292 sizeof(WDMAUD_DEVICE_INFO
),
295 if ( ! MMSUCCESS(Result
) )
297 return TranslateInternalMmResult(Result
);
300 Instance
->Handle
= (PVOID
)DeviceInfo
.hDevice
;
302 /* Now determine framing requirements */
303 Result
= SyncOverlappedDeviceIoControl(KernelHandle
,
305 (LPVOID
) &DeviceInfo
,
306 sizeof(WDMAUD_DEVICE_INFO
),
307 (LPVOID
) &DeviceInfo
,
308 sizeof(WDMAUD_DEVICE_INFO
),
311 if ( MMSUCCESS(Result
) )
313 if (DeviceInfo
.u
.FrameSize
)
315 Instance
->FrameSize
= DeviceInfo
.u
.FrameSize
;
316 Instance
->BufferCount
= WaveFormat
->nAvgBytesPerSec
/ Instance
->FrameSize
;
317 SND_TRACE(L
"FrameSize %u BufferCount %u\n", Instance
->FrameSize
, Instance
->BufferCount
);
322 return MMSYSERR_NOERROR
;
326 WriteFileEx_Committer2(
327 IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance
,
330 IN PSOUND_OVERLAPPED Overlap
,
331 IN LPOVERLAPPED_COMPLETION_ROUTINE CompletionRoutine
)
334 WDMAUD_DEVICE_INFO DeviceInfo
;
337 VALIDATE_MMSYS_PARAMETER( SoundDeviceInstance
);
338 VALIDATE_MMSYS_PARAMETER( OffsetPtr
);
339 VALIDATE_MMSYS_PARAMETER( Overlap
);
340 VALIDATE_MMSYS_PARAMETER( CompletionRoutine
);
342 GetSoundDeviceInstanceHandle(SoundDeviceInstance
, &Handle
);
346 ZeroMemory(&DeviceInfo
, sizeof(WDMAUD_DEVICE_INFO
));
347 DeviceInfo
.hDevice
= Handle
;
348 DeviceInfo
.DeviceType
= WAVE_OUT_DEVICE_TYPE
; //FIXME
349 DeviceInfo
.Buffer
= OffsetPtr
;
350 DeviceInfo
.BufferSize
= Length
;
352 Overlap
->Standard
.hEvent
= CreateEventW(NULL
, FALSE
, FALSE
, NULL
);
354 if ( ! WriteFileEx(KernelHandle
, &DeviceInfo
, sizeof(WDMAUD_DEVICE_INFO
), (LPOVERLAPPED
)Overlap
, CompletionRoutine
))
356 SND_TRACE(L
"WriteFileEx failed with %x\n", GetLastError());
360 WaitForSingleObjectEx (KernelHandle
, INFINITE
, TRUE
);
364 return MMSYSERR_NOERROR
;
369 IN
struct _SOUND_DEVICE_INSTANCE
* SoundDeviceInstance
,
373 PSOUND_DEVICE SoundDevice
;
374 WDMAUD_DEVICE_INFO DeviceInfo
;
375 MMDEVICE_TYPE DeviceType
;
378 Result
= GetSoundDeviceFromInstance(SoundDeviceInstance
, &SoundDevice
);
380 if ( ! MMSUCCESS(Result
) )
382 return TranslateInternalMmResult(Result
);
385 Result
= GetSoundDeviceType(SoundDevice
, &DeviceType
);
386 SND_ASSERT( Result
== MMSYSERR_NOERROR
);
388 Result
= GetSoundDeviceInstanceHandle(SoundDeviceInstance
, &Handle
);
389 SND_ASSERT( Result
== MMSYSERR_NOERROR
);
391 ZeroMemory(&DeviceInfo
, sizeof(WDMAUD_DEVICE_INFO
));
392 DeviceInfo
.hDevice
= Handle
;
393 DeviceInfo
.DeviceType
= DeviceType
;
395 Result
= SyncOverlappedDeviceIoControl(KernelHandle
,
397 (LPVOID
) &DeviceInfo
,
398 sizeof(WDMAUD_DEVICE_INFO
),
399 (LPVOID
) &DeviceInfo
,
400 sizeof(WDMAUD_DEVICE_INFO
),
403 if ( ! MMSUCCESS(Result
) )
405 return TranslateInternalMmResult(Result
);
408 Time
->wType
= TIME_BYTES
;
409 Time
->u
.cb
= (DWORD
)DeviceInfo
.u
.Position
;
411 return MMSYSERR_NOERROR
;
416 PopulateWdmDeviceList(
418 MMDEVICE_TYPE DeviceType
)
421 DWORD DeviceCount
= 0;
422 PSOUND_DEVICE SoundDevice
= NULL
;
423 MMFUNCTION_TABLE FuncTable
;
426 VALIDATE_MMSYS_PARAMETER( Handle
!= INVALID_HANDLE_VALUE
);
427 VALIDATE_MMSYS_PARAMETER( IS_VALID_SOUND_DEVICE_TYPE(DeviceType
) );
429 Result
= GetNumWdmDevs(Handle
, DeviceType
, &DeviceCount
);
431 if ( ! MMSUCCESS(Result
) )
433 SND_ERR(L
"Error %d while obtaining number of devices\n", Result
);
434 return TranslateInternalMmResult(Result
);
437 SND_TRACE(L
"%d devices of type %d found\n", DeviceCount
, DeviceType
);
440 for ( i
= 0; i
< DeviceCount
; ++ i
)
442 Result
= ListSoundDevice(DeviceType
, UlongToPtr(i
), &SoundDevice
);
444 if ( ! MMSUCCESS(Result
) )
446 SND_ERR(L
"Failed to list sound device - error %d\n", Result
);
447 return TranslateInternalMmResult(Result
);
450 /* Set up our function table */
451 ZeroMemory(&FuncTable
, sizeof(MMFUNCTION_TABLE
));
452 FuncTable
.GetCapabilities
= GetWdmDeviceCapabilities
;
453 FuncTable
.QueryWaveFormatSupport
= QueryWdmWaveDeviceFormatSupport
;
454 FuncTable
.SetWaveFormat
= SetWdmWaveDeviceFormat
;
455 FuncTable
.Open
= OpenWdmSoundDevice
;
456 FuncTable
.Close
= CloseWdmSoundDevice
;
457 FuncTable
.CommitWaveBuffer
= WriteFileEx_Committer2
;
458 FuncTable
.GetPos
= GetWdmPosition
;
460 SetSoundDeviceFunctionTable(SoundDevice
, &FuncTable
);
463 return MMSYSERR_NOERROR
;
483 SND_TRACE(L
"DRV_LOAD\n");
485 Result
= InitEntrypointMutexes();
487 if ( ! MMSUCCESS(Result
) )
490 OpenWdmSoundDevice(NULL
, &Handle
);
492 if ( Handle
== INVALID_HANDLE_VALUE
)
494 SND_ERR(L
"Failed to open %s\n", KERNEL_DEVICE_NAME
);
495 CleanupEntrypointMutexes();
497 //UnlistAllSoundDevices();
502 /* Populate the device lists */
503 SND_TRACE(L
"Populating device lists\n");
504 PopulateWdmDeviceList(KernelHandle
, WAVE_OUT_DEVICE_TYPE
);
505 PopulateWdmDeviceList(KernelHandle
, WAVE_IN_DEVICE_TYPE
);
506 PopulateWdmDeviceList(KernelHandle
, MIDI_OUT_DEVICE_TYPE
);
507 PopulateWdmDeviceList(KernelHandle
, MIDI_IN_DEVICE_TYPE
);
508 PopulateWdmDeviceList(KernelHandle
, AUX_DEVICE_TYPE
);
509 PopulateWdmDeviceList(KernelHandle
, MIXER_DEVICE_TYPE
);
511 SND_TRACE(L
"Initialisation complete\n");
518 SND_TRACE(L
"DRV_FREE\n");
520 if ( KernelHandle
!= INVALID_HANDLE_VALUE
)
522 CloseHandle(KernelHandle
);
523 KernelHandle
= INVALID_HANDLE_VALUE
;
526 /* TODO: Clean up the path names! */
527 UnlistAllSoundDevices();
529 CleanupEntrypointMutexes();
531 SND_TRACE(L
"Unfreed memory blocks: %d\n",
532 GetMemoryAllocationCount());
540 SND_TRACE(L
"DRV_ENABLE / DRV_DISABLE\n");
547 SND_TRACE(L
"DRV_OPEN / DRV_CLOSE\n");
551 case DRV_QUERYCONFIGURE
:
553 SND_TRACE(L
"DRV_QUERYCONFIGURE\n");
560 SND_TRACE(L
"Unhandled message %d\n", Message
);
561 return DefDriverProc(DriverId
,
577 case DLL_PROCESS_ATTACH
:
578 SND_TRACE(L
"WDMAUD.DRV - Process attached\n");
580 case DLL_PROCESS_DETACH
:
581 SND_TRACE(L
"WDMAUD.DRV - Process detached\n");
583 case DLL_THREAD_ATTACH
:
584 SND_TRACE(L
"WDMAUD.DRV - Thread attached\n");
586 case DLL_THREAD_DETACH
:
587 SND_TRACE(L
"WDMAUD.DRV - Thread detached\n");