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 if ( OpenCount
== 0 )
180 return MMSYSERR_NOERROR
;
183 SND_ASSERT( KernelHandle
!= INVALID_HANDLE_VALUE
);
185 if (SoundDeviceInstance
->Handle
!= (PVOID
)KernelHandle
)
187 CloseHandle((HANDLE
)SoundDeviceInstance
->Handle
);
194 CloseHandle(KernelHandle
);
195 KernelHandle
= INVALID_HANDLE_VALUE
;
198 return MMSYSERR_NOERROR
;
203 QueryWdmWaveDeviceFormatSupport(
204 IN PSOUND_DEVICE Device
,
205 IN PWAVEFORMATEX WaveFormat
,
206 IN DWORD WaveFormatSize
)
209 return MMSYSERR_NOERROR
;
213 SetWdmWaveDeviceFormat(
214 IN PSOUND_DEVICE_INSTANCE Instance
,
215 IN PWAVEFORMATEX WaveFormat
,
216 IN DWORD WaveFormatSize
)
219 PSOUND_DEVICE SoundDevice
;
221 WDMAUD_DEVICE_INFO DeviceInfo
;
222 MMDEVICE_TYPE DeviceType
;
224 Result
= GetSoundDeviceFromInstance(Instance
, &SoundDevice
);
226 if ( ! MMSUCCESS(Result
) )
228 return TranslateInternalMmResult(Result
);
231 Result
= GetSoundDeviceIdentifier(SoundDevice
, &Identifier
);
233 if ( ! MMSUCCESS(Result
) )
235 return TranslateInternalMmResult(Result
);
238 if (Instance
->Handle
!= KernelHandle
)
240 /* device is already open */
241 return MMSYSERR_NOERROR
;
245 Result
= GetSoundDeviceType(SoundDevice
, &DeviceType
);
246 SND_ASSERT( Result
== MMSYSERR_NOERROR
);
248 ZeroMemory(&DeviceInfo
, sizeof(WDMAUD_DEVICE_INFO
));
249 DeviceInfo
.DeviceType
= DeviceType
;
250 DeviceInfo
.DeviceIndex
= 0; //FIXME
251 DeviceInfo
.u
.WaveFormatEx
.cbSize
= WaveFormat
->cbSize
;
252 DeviceInfo
.u
.WaveFormatEx
.wFormatTag
= WaveFormat
->wFormatTag
;
253 DeviceInfo
.u
.WaveFormatEx
.nChannels
= WaveFormat
->nChannels
;
254 DeviceInfo
.u
.WaveFormatEx
.nSamplesPerSec
= WaveFormat
->nSamplesPerSec
;
255 DeviceInfo
.u
.WaveFormatEx
.nBlockAlign
= WaveFormat
->nBlockAlign
;
256 DeviceInfo
.u
.WaveFormatEx
.nAvgBytesPerSec
= WaveFormat
->nAvgBytesPerSec
;
257 DeviceInfo
.u
.WaveFormatEx
.wBitsPerSample
= WaveFormat
->wBitsPerSample
;
259 Result
= SyncOverlappedDeviceIoControl(KernelHandle
,
261 (LPVOID
) &DeviceInfo
,
262 sizeof(WDMAUD_DEVICE_INFO
),
263 (LPVOID
) &DeviceInfo
,
264 sizeof(WDMAUD_DEVICE_INFO
),
267 if ( ! MMSUCCESS(Result
) )
269 return TranslateInternalMmResult(Result
);
272 Instance
->Handle
= (PVOID
)DeviceInfo
.hDevice
;
274 return MMSYSERR_NOERROR
;
278 WriteFileEx_Committer2(
279 IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance
,
282 IN PSOUND_OVERLAPPED Overlap
,
283 IN LPOVERLAPPED_COMPLETION_ROUTINE CompletionRoutine
)
286 WDMAUD_DEVICE_INFO DeviceInfo
;
289 VALIDATE_MMSYS_PARAMETER( SoundDeviceInstance
);
290 VALIDATE_MMSYS_PARAMETER( OffsetPtr
);
291 VALIDATE_MMSYS_PARAMETER( Overlap
);
292 VALIDATE_MMSYS_PARAMETER( CompletionRoutine
);
294 GetSoundDeviceInstanceHandle(SoundDeviceInstance
, &Handle
);
298 ZeroMemory(&DeviceInfo
, sizeof(WDMAUD_DEVICE_INFO
));
299 DeviceInfo
.hDevice
= Handle
;
300 DeviceInfo
.DeviceType
= WAVE_OUT_DEVICE_TYPE
; //FIXME
301 DeviceInfo
.Buffer
= OffsetPtr
;
302 DeviceInfo
.BufferSize
= Length
;
304 Overlap
->Standard
.hEvent
= CreateEventW(NULL
, FALSE
, FALSE
, NULL
);
306 if ( ! WriteFileEx(KernelHandle
, &DeviceInfo
, sizeof(WDMAUD_DEVICE_INFO
), (LPOVERLAPPED
)Overlap
, CompletionRoutine
))
308 SND_TRACE(L
"WriteFileEx failed with %x\n", GetLastError());
312 WaitForSingleObjectEx (KernelHandle
, INFINITE
, TRUE
);
316 return MMSYSERR_NOERROR
;
321 PopulateWdmDeviceList(
323 MMDEVICE_TYPE DeviceType
)
326 DWORD DeviceCount
= 0;
327 PSOUND_DEVICE SoundDevice
= NULL
;
328 MMFUNCTION_TABLE FuncTable
;
331 VALIDATE_MMSYS_PARAMETER( Handle
!= INVALID_HANDLE_VALUE
);
332 VALIDATE_MMSYS_PARAMETER( IS_VALID_SOUND_DEVICE_TYPE(DeviceType
) );
334 Result
= GetNumWdmDevs(Handle
, DeviceType
, &DeviceCount
);
336 if ( ! MMSUCCESS(Result
) )
338 SND_ERR(L
"Error %d while obtaining number of devices\n", Result
);
339 return TranslateInternalMmResult(Result
);
342 SND_TRACE(L
"%d devices of type %d found\n", DeviceCount
, DeviceType
);
345 for ( i
= 0; i
< DeviceCount
; ++ i
)
347 Result
= ListSoundDevice(DeviceType
, (PVOID
) i
, &SoundDevice
);
349 if ( ! MMSUCCESS(Result
) )
351 SND_ERR(L
"Failed to list sound device - error %d\n", Result
);
352 return TranslateInternalMmResult(Result
);
355 /* Set up our function table */
356 ZeroMemory(&FuncTable
, sizeof(MMFUNCTION_TABLE
));
357 FuncTable
.GetCapabilities
= GetWdmDeviceCapabilities
;
358 FuncTable
.QueryWaveFormatSupport
= QueryWdmWaveDeviceFormatSupport
;
359 FuncTable
.SetWaveFormat
= SetWdmWaveDeviceFormat
;
360 FuncTable
.Open
= OpenWdmSoundDevice
;
361 FuncTable
.Close
= CloseWdmSoundDevice
;
362 FuncTable
.CommitWaveBuffer
= WriteFileEx_Committer2
;
364 SetSoundDeviceFunctionTable(SoundDevice
, &FuncTable
);
367 return MMSYSERR_NOERROR
;
387 SND_TRACE(L
"DRV_LOAD\n");
389 Result
= InitEntrypointMutexes();
391 if ( ! MMSUCCESS(Result
) )
394 OpenWdmSoundDevice(NULL
, &Handle
);
396 if ( Handle
== INVALID_HANDLE_VALUE
)
398 SND_ERR(L
"Failed to open %s\n", KERNEL_DEVICE_NAME
);
399 CleanupEntrypointMutexes();
401 //UnlistAllSoundDevices();
406 /* Populate the device lists */
407 SND_TRACE(L
"Populating device lists\n");
408 PopulateWdmDeviceList(KernelHandle
, WAVE_OUT_DEVICE_TYPE
);
409 PopulateWdmDeviceList(KernelHandle
, WAVE_IN_DEVICE_TYPE
);
410 PopulateWdmDeviceList(KernelHandle
, MIDI_OUT_DEVICE_TYPE
);
411 PopulateWdmDeviceList(KernelHandle
, MIDI_IN_DEVICE_TYPE
);
412 PopulateWdmDeviceList(KernelHandle
, AUX_DEVICE_TYPE
);
413 PopulateWdmDeviceList(KernelHandle
, MIXER_DEVICE_TYPE
);
415 SND_TRACE(L
"Initialisation complete\n");
422 SND_TRACE(L
"DRV_FREE\n");
424 if ( KernelHandle
!= INVALID_HANDLE_VALUE
)
426 CloseHandle(KernelHandle
);
427 KernelHandle
= INVALID_HANDLE_VALUE
;
430 /* TODO: Clean up the path names! */
431 UnlistAllSoundDevices();
433 CleanupEntrypointMutexes();
435 SND_TRACE(L
"Unfreed memory blocks: %d\n",
436 GetMemoryAllocationCount());
444 SND_TRACE(L
"DRV_ENABLE / DRV_DISABLE\n");
451 SND_TRACE(L
"DRV_OPEN / DRV_CLOSE\n");
455 case DRV_QUERYCONFIGURE
:
457 SND_TRACE(L
"DRV_QUERYCONFIGURE\n");
464 SND_TRACE(L
"Unhandled message %d\n", Message
);
465 return DefDriverProc(DriverId
,
481 case DLL_PROCESS_ATTACH
:
482 SND_TRACE(L
"WDMAUD.DRV - Process attached\n");
484 case DLL_PROCESS_DETACH
:
485 SND_TRACE(L
"WDMAUD.DRV - Process detached\n");
487 case DLL_THREAD_ATTACH
:
488 SND_TRACE(L
"WDMAUD.DRV - Thread attached\n");
490 case DLL_THREAD_DETACH
:
491 SND_TRACE(L
"WDMAUD.DRV - Thread detached\n");