3378be68c0f4a48038888557cbe2cb78c4fc5e5c
[reactos.git] / reactos / dll / win32 / wdmaud.drv / wdmaud.c
1 /*
2 * PROJECT: ReactOS Sound System
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: dll/win32/wdmaud.drv/wdmaud.c
5 *
6 * PURPOSE: WDM Audio Driver (User-mode part)
7 * PROGRAMMERS: Andrew Greenwood (silverblade@reactos.org)
8 *
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.
12 *
13 */
14
15 #include <windows.h>
16 #include <ntddsnd.h>
17 #include <sndtypes.h>
18 #include <mmddk.h>
19 #include <mmebuddy.h>
20
21 #include <ks.h>
22 #include <ksmedia.h>
23 #include "interface.h"
24
25 #define KERNEL_DEVICE_NAME L"\\\\.\\wdmaud"
26
27 PWSTR UnknownWaveIn = L"Wave Input";
28 PWSTR UnknownWaveOut = L"Wave Output";
29 PWSTR UnknownMidiIn = L"Midi Input";
30 PWSTR UnknownMidiOut = L"Midi Output";
31
32 HANDLE KernelHandle = INVALID_HANDLE_VALUE;
33 DWORD OpenCount = 0;
34
35 MMRESULT
36 WriteFileEx_Remixer(
37 IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance,
38 IN PVOID OffsetPtr,
39 IN DWORD Length,
40 IN PSOUND_OVERLAPPED Overlap,
41 IN LPOVERLAPPED_COMPLETION_ROUTINE CompletionRoutine);
42
43
44
45 MMRESULT
46 GetNumWdmDevs(
47 IN HANDLE Handle,
48 IN MMDEVICE_TYPE DeviceType,
49 OUT DWORD* DeviceCount)
50 {
51 MMRESULT Result;
52 WDMAUD_DEVICE_INFO DeviceInfo;
53
54 VALIDATE_MMSYS_PARAMETER( Handle != INVALID_HANDLE_VALUE );
55 VALIDATE_MMSYS_PARAMETER( IS_VALID_SOUND_DEVICE_TYPE(DeviceType) );
56 VALIDATE_MMSYS_PARAMETER( DeviceCount );
57
58 ZeroMemory(&DeviceInfo, sizeof(WDMAUD_DEVICE_INFO));
59 DeviceInfo.DeviceType = DeviceType;
60
61 Result = SyncOverlappedDeviceIoControl(Handle,
62 IOCTL_GETNUMDEVS_TYPE,
63 (LPVOID) &DeviceInfo,
64 sizeof(WDMAUD_DEVICE_INFO),
65 (LPVOID) &DeviceInfo,
66 sizeof(WDMAUD_DEVICE_INFO),
67 NULL);
68
69 if ( ! MMSUCCESS( Result ) )
70 {
71 SND_ERR(L"Call to IOCTL_GETNUMDEVS_TYPE failed\n");
72 *DeviceCount = 0;
73 return TranslateInternalMmResult(Result);
74 }
75
76 *DeviceCount = DeviceInfo.DeviceCount;
77
78 return MMSYSERR_NOERROR;
79 }
80
81 MMRESULT
82 GetWdmDeviceCapabilities(
83 IN PSOUND_DEVICE SoundDevice,
84 IN DWORD DeviceId,
85 OUT PVOID Capabilities,
86 IN DWORD CapabilitiesSize)
87 {
88 /* NOTE - At this time, WDMAUD does not support this properly */
89
90 MMRESULT Result;
91 MMDEVICE_TYPE DeviceType;
92 WDMAUD_DEVICE_INFO DeviceInfo;
93
94 SND_ASSERT( SoundDevice );
95 SND_ASSERT( Capabilities );
96
97 Result = GetSoundDeviceType(SoundDevice, &DeviceType);
98 SND_ASSERT( Result == MMSYSERR_NOERROR );
99
100 if ( ! MMSUCCESS(Result) )
101 return Result;
102
103 SND_TRACE(L"WDMAUD - GetWdmDeviceCapabilities DeviceType %u DeviceId %u\n", DeviceType, DeviceId);
104
105 ZeroMemory(&DeviceInfo, sizeof(WDMAUD_DEVICE_INFO));
106 DeviceInfo.DeviceType = DeviceType;
107 DeviceInfo.DeviceIndex = DeviceId;
108
109 Result = SyncOverlappedDeviceIoControl(KernelHandle,
110 IOCTL_GETCAPABILITIES,
111 (LPVOID) &DeviceInfo,
112 sizeof(WDMAUD_DEVICE_INFO),
113 (LPVOID) &DeviceInfo,
114 sizeof(WDMAUD_DEVICE_INFO),
115 NULL);
116
117 if ( ! MMSUCCESS(Result) )
118 {
119 return TranslateInternalMmResult(Result);
120 }
121
122 /* This is pretty much a big hack right now */
123 switch ( DeviceType )
124 {
125 case MIXER_DEVICE_TYPE:
126 {
127 LPMIXERCAPS MixerCaps = (LPMIXERCAPS) Capabilities;
128
129 DeviceInfo.u.MixCaps.szPname[MAXPNAMELEN-1] = L'\0';
130 CopyWideString(MixerCaps->szPname, DeviceInfo.u.MixCaps.szPname);
131
132 MixerCaps->cDestinations = DeviceInfo.u.MixCaps.cDestinations;
133 MixerCaps->fdwSupport = DeviceInfo.u.MixCaps.fdwSupport;
134 MixerCaps->vDriverVersion = DeviceInfo.u.MixCaps.vDriverVersion;
135 MixerCaps->wMid = DeviceInfo.u.MixCaps.wMid;
136 MixerCaps->wPid = DeviceInfo.u.MixCaps.wPid;
137 break;
138 }
139 case WAVE_OUT_DEVICE_TYPE :
140 {
141 LPWAVEOUTCAPS WaveOutCaps = (LPWAVEOUTCAPS) Capabilities;
142
143 DeviceInfo.u.WaveOutCaps.szPname[MAXPNAMELEN-1] = L'\0';
144 WaveOutCaps->wMid = DeviceInfo.u.WaveOutCaps.wMid;
145 WaveOutCaps->wPid = DeviceInfo.u.WaveOutCaps.wPid;
146
147 WaveOutCaps->vDriverVersion = 0x0001;
148 CopyWideString(WaveOutCaps->szPname, DeviceInfo.u.WaveOutCaps.szPname);
149
150 WaveOutCaps->dwFormats = DeviceInfo.u.WaveOutCaps.dwFormats;
151 WaveOutCaps->wChannels = DeviceInfo.u.WaveOutCaps.wChannels;
152 WaveOutCaps->dwSupport = DeviceInfo.u.WaveOutCaps.dwSupport;
153 break;
154 }
155 case WAVE_IN_DEVICE_TYPE :
156 {
157 LPWAVEINCAPSW WaveInCaps = (LPWAVEINCAPSW) Capabilities;
158
159 DeviceInfo.u.WaveInCaps.szPname[MAXPNAMELEN-1] = L'\0';
160
161 WaveInCaps->wMid = DeviceInfo.u.WaveInCaps.wMid;
162 WaveInCaps->wPid = DeviceInfo.u.WaveInCaps.wPid;
163
164 WaveInCaps->vDriverVersion = 0x0001;
165 CopyWideString(WaveInCaps->szPname, DeviceInfo.u.WaveInCaps.szPname);
166
167 WaveInCaps->dwFormats = DeviceInfo.u.WaveInCaps.dwFormats;
168 WaveInCaps->wChannels = DeviceInfo.u.WaveInCaps.wChannels;
169 WaveInCaps->wReserved1 = 0;
170 break;
171 }
172 }
173
174 return MMSYSERR_NOERROR;
175 }
176
177
178 MMRESULT
179 OpenWdmSoundDevice(
180 IN struct _SOUND_DEVICE* SoundDevice, /* NOT USED */
181 OUT PVOID* Handle)
182 {
183 /* Only open this if it's not already open */
184 if ( KernelHandle == INVALID_HANDLE_VALUE )
185 {
186 SND_TRACE(L"Opening wdmaud device\n");
187 KernelHandle = CreateFileW(KERNEL_DEVICE_NAME,
188 GENERIC_READ | GENERIC_WRITE,
189 0,
190 NULL,
191 OPEN_EXISTING,
192 FILE_FLAG_OVERLAPPED,
193 NULL);
194 }
195
196 if ( KernelHandle == INVALID_HANDLE_VALUE )
197 return MMSYSERR_ERROR;
198
199 SND_ASSERT( Handle );
200
201 *Handle = KernelHandle;
202 ++ OpenCount;
203
204 return MMSYSERR_NOERROR;
205 }
206
207 MMRESULT
208 CloseWdmSoundDevice(
209 IN struct _SOUND_DEVICE_INSTANCE* SoundDeviceInstance,
210 IN PVOID Handle)
211 {
212 WDMAUD_DEVICE_INFO DeviceInfo;
213 MMRESULT Result;
214 MMDEVICE_TYPE DeviceType;
215 PSOUND_DEVICE SoundDevice;
216
217 Result = GetSoundDeviceFromInstance(SoundDeviceInstance, &SoundDevice);
218
219 if ( ! MMSUCCESS(Result) )
220 {
221 return TranslateInternalMmResult(Result);
222 }
223
224 if ( OpenCount == 0 )
225 {
226 return MMSYSERR_NOERROR;
227 }
228
229 SND_ASSERT( KernelHandle != INVALID_HANDLE_VALUE );
230
231 Result = GetSoundDeviceType(SoundDevice, &DeviceType);
232 SND_ASSERT( Result == MMSYSERR_NOERROR );
233
234 if (SoundDeviceInstance->Handle != (PVOID)KernelHandle)
235 {
236 ZeroMemory(&DeviceInfo, sizeof(WDMAUD_DEVICE_INFO));
237
238 DeviceInfo.DeviceType = DeviceType;
239 DeviceInfo.hDevice = SoundDeviceInstance->Handle;
240
241 /* First stop the stream */
242 if (DeviceType != MIXER_DEVICE_TYPE)
243 {
244 DeviceInfo.u.State = KSSTATE_STOP;
245 SyncOverlappedDeviceIoControl(KernelHandle,
246 IOCTL_SETDEVICE_STATE,
247 (LPVOID) &DeviceInfo,
248 sizeof(WDMAUD_DEVICE_INFO),
249 (LPVOID) &DeviceInfo,
250 sizeof(WDMAUD_DEVICE_INFO),
251 NULL);
252 }
253
254 SyncOverlappedDeviceIoControl(KernelHandle,
255 IOCTL_CLOSE_WDMAUD,
256 (LPVOID) &DeviceInfo,
257 sizeof(WDMAUD_DEVICE_INFO),
258 (LPVOID) &DeviceInfo,
259 sizeof(WDMAUD_DEVICE_INFO),
260 NULL);
261 }
262
263 --OpenCount;
264
265 if ( OpenCount < 1 )
266 {
267 CloseHandle(KernelHandle);
268 KernelHandle = INVALID_HANDLE_VALUE;
269 }
270
271 return MMSYSERR_NOERROR;
272 }
273
274
275 MMRESULT
276 QueryWdmWaveDeviceFormatSupport(
277 IN PSOUND_DEVICE Device,
278 IN PWAVEFORMATEX WaveFormat,
279 IN DWORD WaveFormatSize)
280 {
281 /* Whatever... */
282 return MMSYSERR_NOERROR;
283 }
284
285
286 MMRESULT
287 SetWdmMixerDeviceFormat(
288 IN PSOUND_DEVICE_INSTANCE Instance,
289 IN DWORD DeviceId,
290 IN PWAVEFORMATEX WaveFormat,
291 IN DWORD WaveFormatSize)
292 {
293 MMRESULT Result;
294 WDMAUD_DEVICE_INFO DeviceInfo;
295
296 if (Instance->Handle != KernelHandle)
297 {
298 /* device is already open */
299 return MMSYSERR_NOERROR;
300 }
301
302
303 ZeroMemory(&DeviceInfo, sizeof(WDMAUD_DEVICE_INFO));
304 DeviceInfo.DeviceType = MIXER_DEVICE_TYPE;
305 DeviceInfo.DeviceIndex = DeviceId;
306
307 Result = SyncOverlappedDeviceIoControl(KernelHandle,
308 IOCTL_OPEN_WDMAUD,
309 (LPVOID) &DeviceInfo,
310 sizeof(WDMAUD_DEVICE_INFO),
311 (LPVOID) &DeviceInfo,
312 sizeof(WDMAUD_DEVICE_INFO),
313 NULL);
314
315 if ( ! MMSUCCESS(Result) )
316 {
317 return TranslateInternalMmResult(Result);
318 }
319
320 /* Store sound device handle instance handle */
321 Instance->Handle = (PVOID)DeviceInfo.hDevice;
322
323 return MMSYSERR_NOERROR;
324 }
325
326 MMRESULT
327 SetWdmWaveDeviceFormat(
328 IN PSOUND_DEVICE_INSTANCE Instance,
329 IN DWORD DeviceId,
330 IN PWAVEFORMATEX WaveFormat,
331 IN DWORD WaveFormatSize)
332 {
333 MMRESULT Result;
334 PSOUND_DEVICE SoundDevice;
335 PVOID Identifier;
336 WDMAUD_DEVICE_INFO DeviceInfo;
337 MMDEVICE_TYPE DeviceType;
338
339 Result = GetSoundDeviceFromInstance(Instance, &SoundDevice);
340
341 if ( ! MMSUCCESS(Result) )
342 {
343 return TranslateInternalMmResult(Result);
344 }
345
346 Result = GetSoundDeviceIdentifier(SoundDevice, &Identifier);
347
348 if ( ! MMSUCCESS(Result) )
349 {
350 return TranslateInternalMmResult(Result);
351 }
352
353 if (Instance->Handle != KernelHandle)
354 {
355 /* device is already open */
356 return MMSYSERR_NOERROR;
357 }
358
359
360 Result = GetSoundDeviceType(SoundDevice, &DeviceType);
361 SND_ASSERT( Result == MMSYSERR_NOERROR );
362
363 ZeroMemory(&DeviceInfo, sizeof(WDMAUD_DEVICE_INFO));
364 DeviceInfo.DeviceType = DeviceType;
365 DeviceInfo.DeviceIndex = DeviceId;
366 DeviceInfo.u.WaveFormatEx.cbSize = WaveFormat->cbSize;
367 DeviceInfo.u.WaveFormatEx.wFormatTag = WaveFormat->wFormatTag;
368 #ifdef USERMODE_MIXER
369 DeviceInfo.u.WaveFormatEx.nChannels = 2;
370 DeviceInfo.u.WaveFormatEx.nSamplesPerSec = 44100;
371 DeviceInfo.u.WaveFormatEx.nBlockAlign = 4;
372 DeviceInfo.u.WaveFormatEx.nAvgBytesPerSec = 176400;
373 DeviceInfo.u.WaveFormatEx.wBitsPerSample = 16;
374 #else
375 DeviceInfo.u.WaveFormatEx.nChannels = WaveFormat->nChannels;
376 DeviceInfo.u.WaveFormatEx.nSamplesPerSec = WaveFormat->nSamplesPerSec;
377 DeviceInfo.u.WaveFormatEx.nBlockAlign = WaveFormat->nBlockAlign;
378 DeviceInfo.u.WaveFormatEx.nAvgBytesPerSec = WaveFormat->nAvgBytesPerSec;
379 DeviceInfo.u.WaveFormatEx.wBitsPerSample = WaveFormat->wBitsPerSample;
380 #endif
381
382 Result = SyncOverlappedDeviceIoControl(KernelHandle,
383 IOCTL_OPEN_WDMAUD,
384 (LPVOID) &DeviceInfo,
385 sizeof(WDMAUD_DEVICE_INFO),
386 (LPVOID) &DeviceInfo,
387 sizeof(WDMAUD_DEVICE_INFO),
388 NULL);
389
390 if ( ! MMSUCCESS(Result) )
391 {
392 return TranslateInternalMmResult(Result);
393 }
394
395 /* Store format */
396 Instance->WaveFormatEx.cbSize = WaveFormat->cbSize;
397 Instance->WaveFormatEx.wFormatTag = WaveFormat->wFormatTag;
398 Instance->WaveFormatEx.nChannels = WaveFormat->nChannels;
399 Instance->WaveFormatEx.nSamplesPerSec = WaveFormat->nSamplesPerSec;
400 Instance->WaveFormatEx.nBlockAlign = WaveFormat->nBlockAlign;
401 Instance->WaveFormatEx.nAvgBytesPerSec = WaveFormat->nAvgBytesPerSec;
402 Instance->WaveFormatEx.wBitsPerSample = WaveFormat->wBitsPerSample;
403
404 /* Store sound device handle instance handle */
405 Instance->Handle = (PVOID)DeviceInfo.hDevice;
406
407 /* Now determine framing requirements */
408 Result = SyncOverlappedDeviceIoControl(KernelHandle,
409 IOCTL_GETFRAMESIZE,
410 (LPVOID) &DeviceInfo,
411 sizeof(WDMAUD_DEVICE_INFO),
412 (LPVOID) &DeviceInfo,
413 sizeof(WDMAUD_DEVICE_INFO),
414 NULL);
415
416 if ( MMSUCCESS(Result) )
417 {
418 if (DeviceInfo.u.FrameSize)
419 {
420 Instance->FrameSize = DeviceInfo.u.FrameSize * 2;
421 Instance->BufferCount = WaveFormat->nAvgBytesPerSec / Instance->FrameSize;
422 SND_TRACE(L"FrameSize %u BufferCount %u\n", Instance->FrameSize, Instance->BufferCount);
423 }
424 }
425 else
426 {
427 // use a default of 100 buffers
428 Instance->BufferCount = 100;
429 }
430
431 if (DeviceType == WAVE_OUT_DEVICE_TYPE)
432 {
433 /* Now start the stream */
434 DeviceInfo.u.State = KSSTATE_RUN;
435 SyncOverlappedDeviceIoControl(KernelHandle,
436 IOCTL_SETDEVICE_STATE,
437 (LPVOID) &DeviceInfo,
438 sizeof(WDMAUD_DEVICE_INFO),
439 (LPVOID) &DeviceInfo,
440 sizeof(WDMAUD_DEVICE_INFO),
441 NULL);
442 }
443
444 return MMSYSERR_NOERROR;
445 }
446
447 MMRESULT
448 WriteFileEx_Committer2(
449 IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance,
450 IN PVOID OffsetPtr,
451 IN DWORD Length,
452 IN PSOUND_OVERLAPPED Overlap,
453 IN LPOVERLAPPED_COMPLETION_ROUTINE CompletionRoutine)
454 {
455 HANDLE Handle;
456 MMRESULT Result;
457 WDMAUD_DEVICE_INFO DeviceInfo;
458 PSOUND_DEVICE SoundDevice;
459 MMDEVICE_TYPE DeviceType;
460 BOOL Ret;
461
462 VALIDATE_MMSYS_PARAMETER( SoundDeviceInstance );
463 VALIDATE_MMSYS_PARAMETER( OffsetPtr );
464 VALIDATE_MMSYS_PARAMETER( Overlap );
465 VALIDATE_MMSYS_PARAMETER( CompletionRoutine );
466
467 GetSoundDeviceInstanceHandle(SoundDeviceInstance, &Handle);
468
469
470 Result = GetSoundDeviceFromInstance(SoundDeviceInstance, &SoundDevice);
471
472 if ( ! MMSUCCESS(Result) )
473 {
474 return TranslateInternalMmResult(Result);
475 }
476
477 Result = GetSoundDeviceType(SoundDevice, &DeviceType);
478 SND_ASSERT( Result == MMSYSERR_NOERROR );
479
480 SND_ASSERT(Handle);
481
482 ZeroMemory(&DeviceInfo, sizeof(WDMAUD_DEVICE_INFO));
483
484 DeviceInfo.Header.FrameExtent = Length;
485 if (DeviceType == WAVE_OUT_DEVICE_TYPE)
486 {
487 DeviceInfo.Header.DataUsed = Length;
488 }
489 DeviceInfo.Header.Data = OffsetPtr;
490 DeviceInfo.Header.Size = sizeof(WDMAUD_DEVICE_INFO);
491 DeviceInfo.Header.PresentationTime.Numerator = 1;
492 DeviceInfo.Header.PresentationTime.Denominator = 1;
493 DeviceInfo.hDevice = Handle;
494 DeviceInfo.DeviceType = DeviceType;
495
496 Overlap->Standard.hEvent = CreateEventW(NULL, FALSE, FALSE, NULL);
497
498 if (DeviceType == WAVE_OUT_DEVICE_TYPE)
499 {
500 Ret = WriteFileEx(KernelHandle, &DeviceInfo, sizeof(WDMAUD_DEVICE_INFO), (LPOVERLAPPED)Overlap, CompletionRoutine);
501 if (Ret)
502 WaitForSingleObjectEx (KernelHandle, INFINITE, TRUE);
503 }
504 else if (DeviceType == WAVE_IN_DEVICE_TYPE)
505 {
506 Ret = ReadFileEx(KernelHandle, &DeviceInfo, sizeof(WDMAUD_DEVICE_INFO), (LPOVERLAPPED)Overlap, CompletionRoutine);
507 //if (Ret)
508 // WaitForSingleObjectEx (KernelHandle, INFINITE, TRUE);
509 }
510
511 return MMSYSERR_NOERROR;
512 }
513
514 MMRESULT
515 SetWdmWaveState(
516 IN struct _SOUND_DEVICE_INSTANCE* SoundDeviceInstance,
517 IN BOOL bStart)
518 {
519 MMRESULT Result;
520 PSOUND_DEVICE SoundDevice;
521 WDMAUD_DEVICE_INFO DeviceInfo;
522 MMDEVICE_TYPE DeviceType;
523 HANDLE Handle;
524
525 Result = GetSoundDeviceFromInstance(SoundDeviceInstance, &SoundDevice);
526
527 if ( ! MMSUCCESS(Result) )
528 {
529 return TranslateInternalMmResult(Result);
530 }
531
532 Result = GetSoundDeviceType(SoundDevice, &DeviceType);
533 SND_ASSERT( Result == MMSYSERR_NOERROR );
534
535 Result = GetSoundDeviceInstanceHandle(SoundDeviceInstance, &Handle);
536 SND_ASSERT( Result == MMSYSERR_NOERROR );
537
538 ZeroMemory(&DeviceInfo, sizeof(WDMAUD_DEVICE_INFO));
539 DeviceInfo.hDevice = Handle;
540 DeviceInfo.DeviceType = DeviceType;
541
542 if (bStart)
543 DeviceInfo.u.State = KSSTATE_RUN;
544 else
545 DeviceInfo.u.State = KSSTATE_PAUSE;
546 Result = SyncOverlappedDeviceIoControl(KernelHandle,
547 IOCTL_SETDEVICE_STATE,
548 (LPVOID) &DeviceInfo,
549 sizeof(WDMAUD_DEVICE_INFO),
550 (LPVOID) &DeviceInfo,
551 sizeof(WDMAUD_DEVICE_INFO),
552 NULL);
553
554 return Result;
555 }
556
557 MMRESULT
558 GetDeviceInterfaceString(
559 IN MMDEVICE_TYPE DeviceType,
560 IN DWORD DeviceId,
561 IN LPWSTR Interface,
562 IN DWORD InterfaceLength,
563 OUT DWORD * InterfaceSize)
564 {
565 WDMAUD_DEVICE_INFO DeviceInfo;
566 MMRESULT Result;
567
568 ZeroMemory(&DeviceInfo, sizeof(WDMAUD_DEVICE_INFO));
569 DeviceInfo.DeviceType = DeviceType;
570 DeviceInfo.DeviceIndex = DeviceId;
571
572
573 Result = SyncOverlappedDeviceIoControl(KernelHandle,
574 IOCTL_QUERYDEVICEINTERFACESTRING,
575 (LPVOID) &DeviceInfo,
576 sizeof(WDMAUD_DEVICE_INFO),
577 (LPVOID) &DeviceInfo,
578 sizeof(WDMAUD_DEVICE_INFO),
579 NULL);
580
581
582 if ( ! MMSUCCESS(Result) )
583 {
584 return TranslateInternalMmResult(Result);
585 }
586
587
588 if (!Interface)
589 {
590 SND_ASSERT(InterfaceSize);
591
592 *InterfaceSize = DeviceInfo.u.Interface.DeviceInterfaceStringSize;
593 return MMSYSERR_NOERROR;
594 }
595
596 if (InterfaceLength < DeviceInfo.u.Interface.DeviceInterfaceStringSize)
597 {
598 /* buffer is too small */
599 return MMSYSERR_MOREDATA;
600 }
601
602 DeviceInfo.u.Interface.DeviceInterfaceStringSize = InterfaceLength;
603 DeviceInfo.u.Interface.DeviceInterfaceString = Interface;
604
605 Result = SyncOverlappedDeviceIoControl(KernelHandle,
606 IOCTL_QUERYDEVICEINTERFACESTRING,
607 (LPVOID) &DeviceInfo,
608 sizeof(WDMAUD_DEVICE_INFO),
609 (LPVOID) &DeviceInfo,
610 sizeof(WDMAUD_DEVICE_INFO),
611 NULL);
612 return Result;
613 }
614
615 MMRESULT
616 GetWdmPosition(
617 IN struct _SOUND_DEVICE_INSTANCE* SoundDeviceInstance,
618 IN MMTIME* Time)
619 {
620 MMRESULT Result;
621 PSOUND_DEVICE SoundDevice;
622 WDMAUD_DEVICE_INFO DeviceInfo;
623 MMDEVICE_TYPE DeviceType;
624 HANDLE Handle;
625
626 Result = GetSoundDeviceFromInstance(SoundDeviceInstance, &SoundDevice);
627
628 if ( ! MMSUCCESS(Result) )
629 {
630 return TranslateInternalMmResult(Result);
631 }
632
633 Result = GetSoundDeviceType(SoundDevice, &DeviceType);
634 SND_ASSERT( Result == MMSYSERR_NOERROR );
635
636 Result = GetSoundDeviceInstanceHandle(SoundDeviceInstance, &Handle);
637 SND_ASSERT( Result == MMSYSERR_NOERROR );
638
639 ZeroMemory(&DeviceInfo, sizeof(WDMAUD_DEVICE_INFO));
640 DeviceInfo.hDevice = Handle;
641 DeviceInfo.DeviceType = DeviceType;
642
643 Result = SyncOverlappedDeviceIoControl(KernelHandle,
644 IOCTL_OPEN_WDMAUD,
645 (LPVOID) &DeviceInfo,
646 sizeof(WDMAUD_DEVICE_INFO),
647 (LPVOID) &DeviceInfo,
648 sizeof(WDMAUD_DEVICE_INFO),
649 NULL);
650
651 if ( ! MMSUCCESS(Result) )
652 {
653 return TranslateInternalMmResult(Result);
654 }
655
656 Time->wType = TIME_BYTES;
657 Time->u.cb = (DWORD)DeviceInfo.u.Position;
658
659 return MMSYSERR_NOERROR;
660 }
661
662 MMRESULT
663 QueryMixerInfo(
664 IN struct _SOUND_DEVICE_INSTANCE* SoundDeviceInstance,
665 IN UINT uMsg,
666 IN LPVOID Parameter,
667 IN DWORD Flags)
668 {
669 MMRESULT Result;
670 WDMAUD_DEVICE_INFO DeviceInfo;
671 HANDLE Handle;
672 DWORD IoControlCode;
673 LPMIXERLINEW MixLine;
674 LPMIXERLINECONTROLSW MixControls;
675 LPMIXERCONTROLDETAILS MixDetails;
676
677 SND_TRACE(L"uMsg %x Flags %x\n", uMsg, Flags);
678
679 Result = GetSoundDeviceInstanceHandle(SoundDeviceInstance, &Handle);
680 SND_ASSERT( Result == MMSYSERR_NOERROR );
681
682 ZeroMemory(&DeviceInfo, sizeof(WDMAUD_DEVICE_INFO));
683 DeviceInfo.hDevice = Handle;
684 DeviceInfo.DeviceType = MIXER_DEVICE_TYPE;
685 DeviceInfo.Flags = Flags;
686
687 MixLine = (LPMIXERLINEW)Parameter;
688 MixControls = (LPMIXERLINECONTROLSW)Parameter;
689 MixDetails = (LPMIXERCONTROLDETAILS)Parameter;
690
691 switch(uMsg)
692 {
693 case MXDM_GETLINEINFO:
694 RtlCopyMemory(&DeviceInfo.u.MixLine, MixLine, sizeof(MIXERLINEW));
695 IoControlCode = IOCTL_GETLINEINFO;
696 break;
697 case MXDM_GETLINECONTROLS:
698 RtlCopyMemory(&DeviceInfo.u.MixControls, MixControls, sizeof(MIXERLINECONTROLSW));
699 IoControlCode = IOCTL_GETLINECONTROLS;
700 break;
701 case MXDM_SETCONTROLDETAILS:
702 RtlCopyMemory(&DeviceInfo.u.MixDetails, MixDetails, sizeof(MIXERCONTROLDETAILS));
703 IoControlCode = IOCTL_SETCONTROLDETAILS;
704 break;
705 case MXDM_GETCONTROLDETAILS:
706 RtlCopyMemory(&DeviceInfo.u.MixDetails, MixDetails, sizeof(MIXERCONTROLDETAILS));
707 IoControlCode = IOCTL_GETCONTROLDETAILS;
708 break;
709 default:
710 SND_ASSERT(0);
711 }
712
713 Result = SyncOverlappedDeviceIoControl(KernelHandle,
714 IoControlCode,
715 (LPVOID) &DeviceInfo,
716 sizeof(WDMAUD_DEVICE_INFO),
717 (LPVOID) &DeviceInfo,
718 sizeof(WDMAUD_DEVICE_INFO),
719 NULL);
720
721 if ( ! MMSUCCESS(Result) )
722 {
723 return TranslateInternalMmResult(Result);
724 }
725
726 switch(uMsg)
727 {
728 case MXDM_GETLINEINFO:
729 {
730 RtlCopyMemory(MixLine, &DeviceInfo.u.MixLine, sizeof(MIXERLINEW));
731 break;
732 }
733 }
734
735 return Result;
736 }
737
738
739 MMRESULT
740 PopulateWdmDeviceList(
741 HANDLE Handle,
742 MMDEVICE_TYPE DeviceType)
743 {
744 MMRESULT Result;
745 DWORD DeviceCount = 0;
746 PSOUND_DEVICE SoundDevice = NULL;
747 MMFUNCTION_TABLE FuncTable;
748 DWORD i;
749
750 VALIDATE_MMSYS_PARAMETER( Handle != INVALID_HANDLE_VALUE );
751 VALIDATE_MMSYS_PARAMETER( IS_VALID_SOUND_DEVICE_TYPE(DeviceType) );
752
753 Result = GetNumWdmDevs(Handle, DeviceType, &DeviceCount);
754
755 if ( ! MMSUCCESS(Result) )
756 {
757 SND_ERR(L"Error %d while obtaining number of devices\n", Result);
758 return TranslateInternalMmResult(Result);
759 }
760
761 SND_TRACE(L"%d devices of type %d found\n", DeviceCount, DeviceType);
762
763
764 for ( i = 0; i < DeviceCount; ++ i )
765 {
766 Result = ListSoundDevice(DeviceType, (PVOID) i, &SoundDevice);
767
768 if ( ! MMSUCCESS(Result) )
769 {
770 SND_ERR(L"Failed to list sound device - error %d\n", Result);
771 return TranslateInternalMmResult(Result);
772 }
773
774 /* Set up our function table */
775 ZeroMemory(&FuncTable, sizeof(MMFUNCTION_TABLE));
776 FuncTable.GetCapabilities = GetWdmDeviceCapabilities;
777 FuncTable.QueryWaveFormatSupport = QueryWdmWaveDeviceFormatSupport;
778 if (DeviceType == MIXER_DEVICE_TYPE)
779 {
780 FuncTable.SetWaveFormat = SetWdmMixerDeviceFormat;
781 FuncTable.QueryMixerInfo = QueryMixerInfo;
782 }
783 else
784 {
785 FuncTable.SetWaveFormat = SetWdmWaveDeviceFormat;
786 }
787
788 if (DeviceType == WAVE_IN_DEVICE_TYPE || DeviceType == WAVE_OUT_DEVICE_TYPE)
789 {
790 FuncTable.SetState = SetWdmWaveState;
791 }
792
793 FuncTable.Open = OpenWdmSoundDevice;
794 FuncTable.Close = CloseWdmSoundDevice;
795 FuncTable.GetDeviceInterfaceString = GetDeviceInterfaceString;
796 #ifndef USERMODE_MIXER
797 FuncTable.CommitWaveBuffer = WriteFileEx_Committer2;
798 #else
799 FuncTable.CommitWaveBuffer = WriteFileEx_Remixer;
800 #endif
801 FuncTable.GetPos = GetWdmPosition;
802
803 SetSoundDeviceFunctionTable(SoundDevice, &FuncTable);
804 }
805
806 return MMSYSERR_NOERROR;
807 }
808
809
810
811 LONG
812 APIENTRY
813 DriverProc(
814 DWORD DriverId,
815 HANDLE DriverHandle,
816 UINT Message,
817 LONG Parameter1,
818 LONG Parameter2)
819 {
820 MMRESULT Result;
821
822 switch ( Message )
823 {
824 case DRV_LOAD :
825 {
826 HANDLE Handle;
827 SND_TRACE(L"DRV_LOAD\n");
828
829 Result = InitEntrypointMutexes();
830
831 if ( ! MMSUCCESS(Result) )
832 return 0L;
833
834 OpenWdmSoundDevice(NULL, &Handle);
835
836 if ( Handle == INVALID_HANDLE_VALUE )
837 {
838 SND_ERR(L"Failed to open %s\n", KERNEL_DEVICE_NAME);
839 CleanupEntrypointMutexes();
840
841 //UnlistAllSoundDevices();
842
843 return 0L;
844 }
845
846 /* Populate the device lists */
847 SND_TRACE(L"Populating device lists\n");
848 PopulateWdmDeviceList(KernelHandle, WAVE_OUT_DEVICE_TYPE);
849 PopulateWdmDeviceList(KernelHandle, WAVE_IN_DEVICE_TYPE);
850 PopulateWdmDeviceList(KernelHandle, MIDI_OUT_DEVICE_TYPE);
851 PopulateWdmDeviceList(KernelHandle, MIDI_IN_DEVICE_TYPE);
852 PopulateWdmDeviceList(KernelHandle, AUX_DEVICE_TYPE);
853 PopulateWdmDeviceList(KernelHandle, MIXER_DEVICE_TYPE);
854
855 SND_TRACE(L"Initialisation complete\n");
856
857 return 1L;
858 }
859
860 case DRV_FREE :
861 {
862 SND_TRACE(L"DRV_FREE\n");
863
864 if ( KernelHandle != INVALID_HANDLE_VALUE )
865 {
866 CloseHandle(KernelHandle);
867 KernelHandle = INVALID_HANDLE_VALUE;
868 }
869
870 /* TODO: Clean up the path names! */
871 UnlistAllSoundDevices();
872
873 CleanupEntrypointMutexes();
874
875 SND_TRACE(L"Unfreed memory blocks: %d\n",
876 GetMemoryAllocationCount());
877
878 return 1L;
879 }
880
881 case DRV_ENABLE :
882 case DRV_DISABLE :
883 {
884 SND_TRACE(L"DRV_ENABLE / DRV_DISABLE\n");
885 return 1L;
886 }
887
888 case DRV_OPEN :
889 case DRV_CLOSE :
890 {
891 SND_TRACE(L"DRV_OPEN / DRV_CLOSE\n");
892 return 1L;
893 }
894
895 case DRV_QUERYCONFIGURE :
896 {
897 SND_TRACE(L"DRV_QUERYCONFIGURE\n");
898 return 0L;
899 }
900 case DRV_CONFIGURE :
901 return DRVCNF_OK;
902
903 default :
904 SND_TRACE(L"Unhandled message %d\n", Message);
905 return DefDriverProc(DriverId,
906 DriverHandle,
907 Message,
908 Parameter1,
909 Parameter2);
910 }
911 }
912
913
914 BOOL WINAPI DllMain(
915 HINSTANCE hinstDLL,
916 DWORD fdwReason,
917 LPVOID lpvReserved)
918 {
919 switch ( fdwReason )
920 {
921 case DLL_PROCESS_ATTACH :
922 SND_TRACE(L"WDMAUD.DRV - Process attached\n");
923 break;
924 case DLL_PROCESS_DETACH :
925 SND_TRACE(L"WDMAUD.DRV - Process detached\n");
926 break;
927 case DLL_THREAD_ATTACH :
928 SND_TRACE(L"WDMAUD.DRV - Thread attached\n");
929 break;
930 case DLL_THREAD_DETACH :
931 SND_TRACE(L"WDMAUD.DRV - Thread detached\n");
932 break;
933 }
934
935 return TRUE;
936 }