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 Johannes Anderwald
9 *
10 * NOTES: Looking for wodMessage & co? You won't find them here. Try
11 * the MME Buddy library, which is where these routines are
12 * actually implemented.
13 *
14 */
15
16 #include "wdmaud.h"
17
18 #define NDEBUG
19 #include <debug.h>
20 #include <mmebuddy_debug.h>
21
22 #define KERNEL_DEVICE_NAME L"\\\\.\\wdmaud"
23
24 HANDLE KernelHandle = INVALID_HANDLE_VALUE;
25 DWORD OpenCount = 0;
26
27 DWORD
28 WINAPI
MixerEventThreadRoutine(LPVOID Parameter)29 MixerEventThreadRoutine(
30 LPVOID Parameter)
31 {
32 HANDLE WaitObjects[2];
33 DWORD dwResult;
34 MMRESULT Result;
35 WDMAUD_DEVICE_INFO DeviceInfo;
36 PSOUND_DEVICE_INSTANCE Instance = (PSOUND_DEVICE_INSTANCE)Parameter;
37
38 /* setup wait objects */
39 WaitObjects[0] = Instance->hNotifyEvent;
40 WaitObjects[1] = Instance->hStopEvent;
41
42 /* zero device info */
43 ZeroMemory(&DeviceInfo, sizeof(WDMAUD_DEVICE_INFO));
44
45 DeviceInfo.hDevice = Instance->Handle;
46 DeviceInfo.DeviceType = MIXER_DEVICE_TYPE;
47
48 do
49 {
50 dwResult = WaitForMultipleObjects(2, WaitObjects, FALSE, INFINITE);
51
52 if (dwResult == WAIT_OBJECT_0 + 1)
53 {
54 /* stop event was signalled */
55 break;
56 }
57
58 do
59 {
60 Result = SyncOverlappedDeviceIoControl(KernelHandle,
61 IOCTL_GET_MIXER_EVENT,
62 (LPVOID) &DeviceInfo,
63 sizeof(WDMAUD_DEVICE_INFO),
64 (LPVOID) &DeviceInfo,
65 sizeof(WDMAUD_DEVICE_INFO),
66 NULL);
67
68 if (Result == MMSYSERR_NOERROR)
69 {
70 DriverCallback(Instance->WinMM.ClientCallback,
71 HIWORD(Instance->WinMM.Flags),
72 Instance->WinMM.Handle,
73 DeviceInfo.u.MixerEvent.NotificationType,
74 Instance->WinMM.ClientCallbackInstanceData,
75 (DWORD_PTR)DeviceInfo.u.MixerEvent.Value,
76 0);
77 }
78 }while(Result == MMSYSERR_NOERROR);
79 }while(TRUE);
80
81 /* done */
82 return 0;
83 }
84
85 MMRESULT
WdmAudCleanupByLegacy()86 WdmAudCleanupByLegacy()
87 {
88 if (KernelHandle != INVALID_HANDLE_VALUE)
89 {
90 CloseHandle(KernelHandle);
91 KernelHandle = INVALID_HANDLE_VALUE;
92 }
93
94 return MMSYSERR_NOERROR;
95 }
96
97 MMRESULT
WdmAudGetNumWdmDevsByLegacy(IN MMDEVICE_TYPE DeviceType,OUT DWORD * DeviceCount)98 WdmAudGetNumWdmDevsByLegacy(
99 IN MMDEVICE_TYPE DeviceType,
100 OUT DWORD* DeviceCount)
101 {
102 MMRESULT Result;
103 WDMAUD_DEVICE_INFO DeviceInfo;
104
105 VALIDATE_MMSYS_PARAMETER( KernelHandle != INVALID_HANDLE_VALUE );
106 VALIDATE_MMSYS_PARAMETER( IS_VALID_SOUND_DEVICE_TYPE(DeviceType) );
107 VALIDATE_MMSYS_PARAMETER( DeviceCount );
108
109 ZeroMemory(&DeviceInfo, sizeof(WDMAUD_DEVICE_INFO));
110 DeviceInfo.DeviceType = DeviceType;
111
112 Result = SyncOverlappedDeviceIoControl(KernelHandle,
113 IOCTL_GETNUMDEVS_TYPE,
114 (LPVOID) &DeviceInfo,
115 sizeof(WDMAUD_DEVICE_INFO),
116 (LPVOID) &DeviceInfo,
117 sizeof(WDMAUD_DEVICE_INFO),
118 NULL);
119
120 if ( ! MMSUCCESS( Result ) )
121 {
122 SND_ERR(L"Call to IOCTL_GETNUMDEVS_TYPE failed\n");
123 *DeviceCount = 0;
124 return TranslateInternalMmResult(Result);
125 }
126
127 *DeviceCount = DeviceInfo.DeviceCount;
128
129 return MMSYSERR_NOERROR;
130 }
131
132 MMRESULT
WdmAudGetCapabilitiesByLegacy(IN PSOUND_DEVICE SoundDevice,IN DWORD DeviceId,OUT PVOID Capabilities,IN DWORD CapabilitiesSize)133 WdmAudGetCapabilitiesByLegacy(
134 IN PSOUND_DEVICE SoundDevice,
135 IN DWORD DeviceId,
136 OUT PVOID Capabilities,
137 IN DWORD CapabilitiesSize)
138 {
139 MMRESULT Result;
140 MMDEVICE_TYPE DeviceType;
141 WDMAUD_DEVICE_INFO DeviceInfo;
142
143 SND_ASSERT( SoundDevice );
144 SND_ASSERT( Capabilities );
145
146 Result = GetSoundDeviceType(SoundDevice, &DeviceType);
147 SND_ASSERT( Result == MMSYSERR_NOERROR );
148
149 if ( ! MMSUCCESS(Result) )
150 return Result;
151
152 SND_TRACE(L"WDMAUD - GetWdmDeviceCapabilities DeviceType %u DeviceId %u\n", DeviceType, DeviceId);
153
154 ZeroMemory(&DeviceInfo, sizeof(WDMAUD_DEVICE_INFO));
155 DeviceInfo.DeviceType = DeviceType;
156 DeviceInfo.DeviceIndex = DeviceId;
157
158 Result = SyncOverlappedDeviceIoControl(KernelHandle,
159 IOCTL_GETCAPABILITIES,
160 (LPVOID) &DeviceInfo,
161 sizeof(WDMAUD_DEVICE_INFO),
162 (LPVOID) &DeviceInfo,
163 sizeof(WDMAUD_DEVICE_INFO),
164 NULL);
165
166 if ( ! MMSUCCESS(Result) )
167 {
168 return TranslateInternalMmResult(Result);
169 }
170
171 /* This is pretty much a big hack right now */
172 switch ( DeviceType )
173 {
174 case MIXER_DEVICE_TYPE:
175 {
176 LPMIXERCAPSW MixerCaps = (LPMIXERCAPSW) Capabilities;
177
178 DeviceInfo.u.MixCaps.szPname[MAXPNAMELEN-1] = L'\0';
179 CopyWideString(MixerCaps->szPname, DeviceInfo.u.MixCaps.szPname);
180
181 MixerCaps->cDestinations = DeviceInfo.u.MixCaps.cDestinations;
182 MixerCaps->fdwSupport = DeviceInfo.u.MixCaps.fdwSupport;
183 MixerCaps->vDriverVersion = DeviceInfo.u.MixCaps.vDriverVersion;
184 MixerCaps->wMid = DeviceInfo.u.MixCaps.wMid;
185 MixerCaps->wPid = DeviceInfo.u.MixCaps.wPid;
186 break;
187 }
188 case WAVE_OUT_DEVICE_TYPE :
189 {
190 LPWAVEOUTCAPSW WaveOutCaps = (LPWAVEOUTCAPSW) Capabilities;
191
192 DeviceInfo.u.WaveOutCaps.szPname[MAXPNAMELEN-1] = L'\0';
193 WaveOutCaps->wMid = DeviceInfo.u.WaveOutCaps.wMid;
194 WaveOutCaps->wPid = DeviceInfo.u.WaveOutCaps.wPid;
195
196 WaveOutCaps->vDriverVersion = DeviceInfo.u.WaveOutCaps.vDriverVersion;
197 CopyWideString(WaveOutCaps->szPname, DeviceInfo.u.WaveOutCaps.szPname);
198
199 WaveOutCaps->dwFormats = DeviceInfo.u.WaveOutCaps.dwFormats;
200 WaveOutCaps->wChannels = DeviceInfo.u.WaveOutCaps.wChannels;
201 WaveOutCaps->dwSupport = DeviceInfo.u.WaveOutCaps.dwSupport;
202 break;
203 }
204 case WAVE_IN_DEVICE_TYPE :
205 {
206 LPWAVEINCAPSW WaveInCaps = (LPWAVEINCAPSW) Capabilities;
207
208 DeviceInfo.u.WaveInCaps.szPname[MAXPNAMELEN-1] = L'\0';
209
210 WaveInCaps->wMid = DeviceInfo.u.WaveInCaps.wMid;
211 WaveInCaps->wPid = DeviceInfo.u.WaveInCaps.wPid;
212
213 WaveInCaps->vDriverVersion = DeviceInfo.u.WaveInCaps.vDriverVersion;
214 CopyWideString(WaveInCaps->szPname, DeviceInfo.u.WaveInCaps.szPname);
215
216 WaveInCaps->dwFormats = DeviceInfo.u.WaveInCaps.dwFormats;
217 WaveInCaps->wChannels = DeviceInfo.u.WaveInCaps.wChannels;
218 WaveInCaps->wReserved1 = 0;
219 break;
220 }
221 case MIDI_IN_DEVICE_TYPE :
222 {
223 LPMIDIINCAPSW MidiInCaps = (LPMIDIINCAPSW)Capabilities;
224
225 DeviceInfo.u.MidiInCaps.szPname[MAXPNAMELEN-1] = L'\0';
226
227 MidiInCaps->vDriverVersion = DeviceInfo.u.MidiInCaps.vDriverVersion;
228 MidiInCaps->wMid = DeviceInfo.u.MidiInCaps.wMid;
229 MidiInCaps->wPid = DeviceInfo.u.MidiInCaps.wPid;
230 MidiInCaps->dwSupport = DeviceInfo.u.MidiInCaps.dwSupport;
231
232 CopyWideString(MidiInCaps->szPname, DeviceInfo.u.MidiInCaps.szPname);
233 break;
234 }
235 case MIDI_OUT_DEVICE_TYPE :
236 {
237 LPMIDIOUTCAPSW MidiOutCaps = (LPMIDIOUTCAPSW)Capabilities;
238
239 DeviceInfo.u.MidiOutCaps.szPname[MAXPNAMELEN-1] = L'\0';
240
241 MidiOutCaps->vDriverVersion = DeviceInfo.u.MidiOutCaps.vDriverVersion;
242 MidiOutCaps->wMid = DeviceInfo.u.MidiOutCaps.wMid;
243 MidiOutCaps->wPid = DeviceInfo.u.MidiOutCaps.wPid;
244 MidiOutCaps->dwSupport = DeviceInfo.u.MidiOutCaps.dwSupport;
245
246 CopyWideString(MidiOutCaps->szPname, DeviceInfo.u.MidiOutCaps.szPname);
247 break;
248 }
249 }
250
251 return MMSYSERR_NOERROR;
252 }
253
254 MMRESULT
WdmAudOpenSoundDeviceByLegacy(IN PSOUND_DEVICE SoundDevice,OUT PVOID * Handle)255 WdmAudOpenSoundDeviceByLegacy(
256 IN PSOUND_DEVICE SoundDevice,
257 OUT PVOID *Handle)
258 {
259 HDEVINFO hDevInfo;
260 SP_DEVICE_INTERFACE_DATA DeviceInterfaceData;
261 GUID SWBusGuid = {STATIC_KSCATEGORY_WDMAUD};
262 PSP_DEVICE_INTERFACE_DETAIL_DATA_W DeviceInterfaceDetailData;
263
264 if ( KernelHandle == INVALID_HANDLE_VALUE )
265 {
266 hDevInfo = SetupDiGetClassDevsW(&SWBusGuid, NULL, NULL, DIGCF_DEVICEINTERFACE| DIGCF_PRESENT);
267 if (!hDevInfo)
268 {
269 // failed
270 return MMSYSERR_ERROR;
271 }
272
273 DeviceInterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
274 if (!SetupDiEnumDeviceInterfaces(hDevInfo, NULL, &SWBusGuid, 0, &DeviceInterfaceData))
275 {
276 // failed
277 SetupDiDestroyDeviceInfoList(hDevInfo);
278 return MMSYSERR_ERROR;
279 }
280
281 DeviceInterfaceDetailData = (PSP_DEVICE_INTERFACE_DETAIL_DATA_W)HeapAlloc(GetProcessHeap(), 0, MAX_PATH * sizeof(WCHAR) + sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W));
282 if (!DeviceInterfaceDetailData)
283 {
284 // failed
285 SetupDiDestroyDeviceInfoList(hDevInfo);
286 return MMSYSERR_ERROR;
287 }
288
289 DeviceInterfaceDetailData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W);
290 if (!SetupDiGetDeviceInterfaceDetailW(hDevInfo, &DeviceInterfaceData, DeviceInterfaceDetailData,MAX_PATH * sizeof(WCHAR) + sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W), NULL, NULL))
291 {
292 // failed
293 HeapFree(GetProcessHeap(), 0, DeviceInterfaceDetailData);
294 SetupDiDestroyDeviceInfoList(hDevInfo);
295 return MMSYSERR_ERROR;
296 }
297 SND_TRACE(L"Opening wdmaud device '%s'\n",DeviceInterfaceDetailData->DevicePath);
298 KernelHandle = CreateFileW(DeviceInterfaceDetailData->DevicePath,
299 GENERIC_READ | GENERIC_WRITE,
300 0,
301 NULL,
302 OPEN_EXISTING,
303 FILE_FLAG_OVERLAPPED,
304 NULL);
305
306 HeapFree(GetProcessHeap(), 0, DeviceInterfaceDetailData);
307 SetupDiDestroyDeviceInfoList(hDevInfo);
308 }
309
310
311 if ( KernelHandle == INVALID_HANDLE_VALUE )
312 return MMSYSERR_ERROR;
313
314 ++ OpenCount;
315 return MMSYSERR_NOERROR;
316
317 }
318
319 MMRESULT
WdmAudCloseSoundDeviceByLegacy(IN struct _SOUND_DEVICE_INSTANCE * SoundDeviceInstance,IN PVOID Handle)320 WdmAudCloseSoundDeviceByLegacy(
321 IN struct _SOUND_DEVICE_INSTANCE* SoundDeviceInstance,
322 IN PVOID Handle)
323 {
324 WDMAUD_DEVICE_INFO DeviceInfo;
325 MMRESULT Result;
326 MMDEVICE_TYPE DeviceType;
327 PSOUND_DEVICE SoundDevice;
328
329 Result = GetSoundDeviceFromInstance(SoundDeviceInstance, &SoundDevice);
330
331 if ( ! MMSUCCESS(Result) )
332 {
333 return TranslateInternalMmResult(Result);
334 }
335
336 if ( OpenCount == 0 )
337 {
338 return MMSYSERR_NOERROR;
339 }
340
341 SND_ASSERT( KernelHandle != INVALID_HANDLE_VALUE );
342
343 Result = GetSoundDeviceType(SoundDevice, &DeviceType);
344 SND_ASSERT( Result == MMSYSERR_NOERROR );
345
346 if (SoundDeviceInstance->Handle != (PVOID)KernelHandle)
347 {
348 ZeroMemory(&DeviceInfo, sizeof(WDMAUD_DEVICE_INFO));
349
350 DeviceInfo.DeviceType = DeviceType;
351 DeviceInfo.hDevice = SoundDeviceInstance->Handle;
352
353 /* First stop the stream */
354 if (DeviceType != MIXER_DEVICE_TYPE)
355 {
356 DeviceInfo.u.State = KSSTATE_PAUSE;
357 SyncOverlappedDeviceIoControl(KernelHandle,
358 IOCTL_SETDEVICE_STATE,
359 (LPVOID) &DeviceInfo,
360 sizeof(WDMAUD_DEVICE_INFO),
361 (LPVOID) &DeviceInfo,
362 sizeof(WDMAUD_DEVICE_INFO),
363 NULL);
364
365 DeviceInfo.u.State = KSSTATE_ACQUIRE;
366 SyncOverlappedDeviceIoControl(KernelHandle,
367 IOCTL_SETDEVICE_STATE,
368 (LPVOID) &DeviceInfo,
369 sizeof(WDMAUD_DEVICE_INFO),
370 (LPVOID) &DeviceInfo,
371 sizeof(WDMAUD_DEVICE_INFO),
372 NULL);
373
374
375 DeviceInfo.u.State = KSSTATE_STOP;
376 SyncOverlappedDeviceIoControl(KernelHandle,
377 IOCTL_SETDEVICE_STATE,
378 (LPVOID) &DeviceInfo,
379 sizeof(WDMAUD_DEVICE_INFO),
380 (LPVOID) &DeviceInfo,
381 sizeof(WDMAUD_DEVICE_INFO),
382 NULL);
383 }
384
385 SyncOverlappedDeviceIoControl(KernelHandle,
386 IOCTL_CLOSE_WDMAUD,
387 (LPVOID) &DeviceInfo,
388 sizeof(WDMAUD_DEVICE_INFO),
389 (LPVOID) &DeviceInfo,
390 sizeof(WDMAUD_DEVICE_INFO),
391 NULL);
392 }
393
394 if (DeviceType == MIXER_DEVICE_TYPE)
395 {
396 SetEvent(SoundDeviceInstance->hStopEvent);
397 CloseHandle(SoundDeviceInstance->hStopEvent);
398 CloseHandle(SoundDeviceInstance->hNotifyEvent);
399 }
400
401 --OpenCount;
402
403 if ( OpenCount < 1 )
404 {
405 CloseHandle(KernelHandle);
406 KernelHandle = INVALID_HANDLE_VALUE;
407 }
408
409 return MMSYSERR_NOERROR;
410 }
411
412 MMRESULT
WdmAudSetMixerDeviceFormatByLegacy(IN PSOUND_DEVICE_INSTANCE Instance,IN DWORD DeviceId,IN PWAVEFORMATEX WaveFormat,IN DWORD WaveFormatSize)413 WdmAudSetMixerDeviceFormatByLegacy(
414 IN PSOUND_DEVICE_INSTANCE Instance,
415 IN DWORD DeviceId,
416 IN PWAVEFORMATEX WaveFormat,
417 IN DWORD WaveFormatSize)
418 {
419 MMRESULT Result;
420 WDMAUD_DEVICE_INFO DeviceInfo;
421 HANDLE hThread;
422
423 Instance->hNotifyEvent = CreateEventW(NULL, FALSE, FALSE, NULL);
424 if ( ! Instance->hNotifyEvent )
425 return MMSYSERR_NOMEM;
426
427 if (Instance->Handle != NULL)
428 {
429 /* device is already open */
430 return MMSYSERR_NOERROR;
431 }
432
433 Instance->hStopEvent = CreateEventW(NULL, FALSE, FALSE, NULL);
434 if ( ! Instance->hStopEvent )
435 return MMSYSERR_NOMEM;
436
437 ZeroMemory(&DeviceInfo, sizeof(WDMAUD_DEVICE_INFO));
438 DeviceInfo.DeviceType = MIXER_DEVICE_TYPE;
439 DeviceInfo.DeviceIndex = DeviceId;
440 DeviceInfo.u.hNotifyEvent = Instance->hNotifyEvent;
441
442 Result = SyncOverlappedDeviceIoControl(KernelHandle,
443 IOCTL_OPEN_WDMAUD,
444 (LPVOID) &DeviceInfo,
445 sizeof(WDMAUD_DEVICE_INFO),
446 (LPVOID) &DeviceInfo,
447 sizeof(WDMAUD_DEVICE_INFO),
448 NULL);
449
450 if ( ! MMSUCCESS(Result) )
451 {
452 CloseHandle(Instance->hNotifyEvent);
453 CloseHandle(Instance->hStopEvent);
454 return TranslateInternalMmResult(Result);
455 }
456
457 hThread = CreateThread(NULL, 0, MixerEventThreadRoutine, (LPVOID)Instance, 0, NULL);
458 if ( hThread )
459 {
460 CloseHandle(hThread);
461 }
462
463 /* Store sound device handle instance handle */
464 Instance->Handle = (PVOID)DeviceInfo.hDevice;
465
466 return MMSYSERR_NOERROR;
467 }
468
469 MMRESULT
WdmAudSetWaveDeviceFormatByLegacy(IN PSOUND_DEVICE_INSTANCE Instance,IN DWORD DeviceId,IN PWAVEFORMATEX WaveFormat,IN DWORD WaveFormatSize)470 WdmAudSetWaveDeviceFormatByLegacy(
471 IN PSOUND_DEVICE_INSTANCE Instance,
472 IN DWORD DeviceId,
473 IN PWAVEFORMATEX WaveFormat,
474 IN DWORD WaveFormatSize)
475 {
476 MMRESULT Result;
477 PSOUND_DEVICE SoundDevice;
478 PVOID Identifier;
479 WDMAUD_DEVICE_INFO DeviceInfo;
480 MMDEVICE_TYPE DeviceType;
481
482 Result = GetSoundDeviceFromInstance(Instance, &SoundDevice);
483
484 if ( ! MMSUCCESS(Result) )
485 {
486 return TranslateInternalMmResult(Result);
487 }
488
489 Result = GetSoundDeviceIdentifier(SoundDevice, &Identifier);
490
491 if ( ! MMSUCCESS(Result) )
492 {
493 return TranslateInternalMmResult(Result);
494 }
495
496 if (Instance->Handle != NULL)
497 {
498 /* device is already open */
499 return MMSYSERR_NOERROR;
500 }
501
502 Result = GetSoundDeviceType(SoundDevice, &DeviceType);
503
504 SND_ASSERT( Result == MMSYSERR_NOERROR );
505
506 ZeroMemory(&DeviceInfo, sizeof(WDMAUD_DEVICE_INFO));
507 DeviceInfo.DeviceType = DeviceType;
508 DeviceInfo.DeviceIndex = DeviceId;
509 DeviceInfo.u.WaveFormatEx.cbSize = WaveFormat->cbSize;
510 DeviceInfo.u.WaveFormatEx.wFormatTag = WaveFormat->wFormatTag;
511 #ifdef USERMODE_MIXER
512 DeviceInfo.u.WaveFormatEx.nChannels = 2;
513 DeviceInfo.u.WaveFormatEx.nSamplesPerSec = 44100;
514 DeviceInfo.u.WaveFormatEx.nBlockAlign = 4;
515 DeviceInfo.u.WaveFormatEx.nAvgBytesPerSec = 176400;
516 DeviceInfo.u.WaveFormatEx.wBitsPerSample = 16;
517 #else
518 DeviceInfo.u.WaveFormatEx.nChannels = WaveFormat->nChannels;
519 DeviceInfo.u.WaveFormatEx.nSamplesPerSec = WaveFormat->nSamplesPerSec;
520 DeviceInfo.u.WaveFormatEx.nBlockAlign = WaveFormat->nBlockAlign;
521 DeviceInfo.u.WaveFormatEx.nAvgBytesPerSec = WaveFormat->nAvgBytesPerSec;
522 DeviceInfo.u.WaveFormatEx.wBitsPerSample = (DeviceInfo.u.WaveFormatEx.nAvgBytesPerSec * 8) / (DeviceInfo.u.WaveFormatEx.nSamplesPerSec * DeviceInfo.u.WaveFormatEx.nChannels);
523 #endif
524
525 Result = SyncOverlappedDeviceIoControl(KernelHandle,
526 IOCTL_OPEN_WDMAUD,
527 (LPVOID) &DeviceInfo,
528 sizeof(WDMAUD_DEVICE_INFO),
529 (LPVOID) &DeviceInfo,
530 sizeof(WDMAUD_DEVICE_INFO),
531 NULL);
532
533 if ( ! MMSUCCESS(Result) )
534 {
535 return TranslateInternalMmResult(Result);
536 }
537
538 if (WaveFormatSize >= sizeof(WAVEFORMAT))
539 {
540 /* Store format */
541 Instance->WaveFormatEx.wFormatTag = WaveFormat->wFormatTag;
542 Instance->WaveFormatEx.nChannels = WaveFormat->nChannels;
543 Instance->WaveFormatEx.nSamplesPerSec = WaveFormat->nSamplesPerSec;
544 Instance->WaveFormatEx.nBlockAlign = WaveFormat->nBlockAlign;
545 Instance->WaveFormatEx.nAvgBytesPerSec = WaveFormat->nAvgBytesPerSec;
546 }
547
548 /* store details */
549 Instance->WaveFormatEx.cbSize = WaveFormat->cbSize;
550 Instance->WaveFormatEx.wBitsPerSample = (DeviceInfo.u.WaveFormatEx.nAvgBytesPerSec * 8) / (DeviceInfo.u.WaveFormatEx.nSamplesPerSec * DeviceInfo.u.WaveFormatEx.nChannels);
551
552 /* Store sound device handle instance handle */
553 Instance->Handle = (PVOID)DeviceInfo.hDevice;
554
555 /* Now determine framing requirements */
556 Result = SyncOverlappedDeviceIoControl(KernelHandle,
557 IOCTL_GETFRAMESIZE,
558 (LPVOID) &DeviceInfo,
559 sizeof(WDMAUD_DEVICE_INFO),
560 (LPVOID) &DeviceInfo,
561 sizeof(WDMAUD_DEVICE_INFO),
562 NULL);
563
564 if ( MMSUCCESS(Result) )
565 {
566 if (DeviceInfo.u.FrameSize)
567 {
568 Instance->FrameSize = DeviceInfo.u.FrameSize * 2;
569 Instance->BufferCount = WaveFormat->nAvgBytesPerSec / Instance->FrameSize;
570 SND_TRACE(L"FrameSize %u BufferCount %u\n", Instance->FrameSize, Instance->BufferCount);
571 }
572 }
573 else
574 {
575 // use a default of 100 buffers
576 Instance->BufferCount = 100;
577 }
578
579 /* Now acquire resources */
580 DeviceInfo.u.State = KSSTATE_ACQUIRE;
581 SyncOverlappedDeviceIoControl(KernelHandle, IOCTL_SETDEVICE_STATE, (LPVOID) &DeviceInfo, sizeof(WDMAUD_DEVICE_INFO), (LPVOID) &DeviceInfo, sizeof(WDMAUD_DEVICE_INFO), NULL);
582
583 /* pause the pin */
584 DeviceInfo.u.State = KSSTATE_PAUSE;
585 SyncOverlappedDeviceIoControl(KernelHandle, IOCTL_SETDEVICE_STATE, (LPVOID) &DeviceInfo, sizeof(WDMAUD_DEVICE_INFO), (LPVOID) &DeviceInfo, sizeof(WDMAUD_DEVICE_INFO), NULL);
586
587 /* start the pin */
588 DeviceInfo.u.State = KSSTATE_RUN;
589 SyncOverlappedDeviceIoControl(KernelHandle, IOCTL_SETDEVICE_STATE, (LPVOID) &DeviceInfo, sizeof(WDMAUD_DEVICE_INFO), (LPVOID) &DeviceInfo, sizeof(WDMAUD_DEVICE_INFO), NULL);
590
591
592 return MMSYSERR_NOERROR;
593 }
594
595 VOID
596 CALLBACK
LegacyCompletionRoutine(IN DWORD dwErrorCode,IN DWORD dwNumberOfBytesTransferred,IN LPOVERLAPPED lpOverlapped)597 LegacyCompletionRoutine(
598 IN DWORD dwErrorCode,
599 IN DWORD dwNumberOfBytesTransferred,
600 IN LPOVERLAPPED lpOverlapped)
601 {
602 PSOUND_OVERLAPPED Overlap;
603 PWDMAUD_DEVICE_INFO DeviceInfo;
604
605 Overlap = (PSOUND_OVERLAPPED)lpOverlapped;
606 DeviceInfo = (PWDMAUD_DEVICE_INFO)Overlap->CompletionContext;
607
608 /* Call mmebuddy overlap routine */
609 Overlap->OriginalCompletionRoutine(dwErrorCode, DeviceInfo->Header.DataUsed, lpOverlapped);
610
611 HeapFree(GetProcessHeap(), 0, DeviceInfo);
612 }
613
614 MMRESULT
WdmAudCommitWaveBufferByLegacy(IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance,IN PVOID OffsetPtr,IN DWORD Length,IN PSOUND_OVERLAPPED Overlap,IN LPOVERLAPPED_COMPLETION_ROUTINE CompletionRoutine)615 WdmAudCommitWaveBufferByLegacy(
616 IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance,
617 IN PVOID OffsetPtr,
618 IN DWORD Length,
619 IN PSOUND_OVERLAPPED Overlap,
620 IN LPOVERLAPPED_COMPLETION_ROUTINE CompletionRoutine)
621 {
622 HANDLE Handle;
623 MMRESULT Result;
624 PWDMAUD_DEVICE_INFO DeviceInfo;
625 PSOUND_DEVICE SoundDevice;
626 MMDEVICE_TYPE DeviceType;
627 BOOL Ret;
628
629 VALIDATE_MMSYS_PARAMETER( SoundDeviceInstance );
630 VALIDATE_MMSYS_PARAMETER( OffsetPtr );
631 VALIDATE_MMSYS_PARAMETER( Overlap );
632 VALIDATE_MMSYS_PARAMETER( CompletionRoutine );
633
634 GetSoundDeviceInstanceHandle(SoundDeviceInstance, &Handle);
635 SND_ASSERT(Handle);
636
637 Result = GetSoundDeviceFromInstance(SoundDeviceInstance, &SoundDevice);
638
639 if ( ! MMSUCCESS(Result) )
640 {
641 return TranslateInternalMmResult(Result);
642 }
643
644 Result = GetSoundDeviceType(SoundDevice, &DeviceType);
645 SND_ASSERT( Result == MMSYSERR_NOERROR );
646
647 DeviceInfo = (PWDMAUD_DEVICE_INFO)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(WDMAUD_DEVICE_INFO));
648 if (!DeviceInfo)
649 {
650 // no memory
651 return MMSYSERR_NOMEM;
652 }
653
654 DeviceInfo->Header.FrameExtent = Length;
655 if (DeviceType == WAVE_OUT_DEVICE_TYPE)
656 {
657 DeviceInfo->Header.DataUsed = Length;
658 }
659 DeviceInfo->Header.Data = OffsetPtr;
660 DeviceInfo->Header.Size = sizeof(WDMAUD_DEVICE_INFO);
661 DeviceInfo->Header.PresentationTime.Numerator = 1;
662 DeviceInfo->Header.PresentationTime.Denominator = 1;
663 DeviceInfo->hDevice = Handle;
664 DeviceInfo->DeviceType = DeviceType;
665
666
667 // create completion event
668 Overlap->Standard.hEvent = Handle = CreateEventW(NULL, FALSE, FALSE, NULL);
669 if (Overlap->Standard.hEvent == NULL)
670 {
671 // no memory
672 HeapFree(GetProcessHeap(), 0, DeviceInfo);
673 return MMSYSERR_NOMEM;
674 }
675
676 Overlap->OriginalCompletionRoutine = CompletionRoutine;
677 Overlap->CompletionContext = (PVOID)DeviceInfo;
678
679 if (DeviceType == WAVE_OUT_DEVICE_TYPE)
680 {
681 Ret = WriteFileEx(KernelHandle, DeviceInfo, sizeof(WDMAUD_DEVICE_INFO), (LPOVERLAPPED)Overlap, LegacyCompletionRoutine);
682 if (Ret)
683 WaitForSingleObjectEx (KernelHandle, INFINITE, TRUE);
684 }
685 else if (DeviceType == WAVE_IN_DEVICE_TYPE)
686 {
687 Ret = ReadFileEx(KernelHandle, DeviceInfo, sizeof(WDMAUD_DEVICE_INFO), (LPOVERLAPPED)Overlap, LegacyCompletionRoutine);
688 if (Ret)
689 WaitForSingleObjectEx (KernelHandle, INFINITE, TRUE);
690 }
691
692 // close event handle
693 CloseHandle(Handle);
694
695 return MMSYSERR_NOERROR;
696 }
697
698 MMRESULT
WdmAudSetWaveStateByLegacy(IN struct _SOUND_DEVICE_INSTANCE * SoundDeviceInstance,IN BOOL bStart)699 WdmAudSetWaveStateByLegacy(
700 IN struct _SOUND_DEVICE_INSTANCE* SoundDeviceInstance,
701 IN BOOL bStart)
702 {
703 MMRESULT Result;
704 PSOUND_DEVICE SoundDevice;
705 WDMAUD_DEVICE_INFO DeviceInfo;
706 MMDEVICE_TYPE DeviceType;
707 HANDLE Handle;
708
709 Result = GetSoundDeviceFromInstance(SoundDeviceInstance, &SoundDevice);
710
711 if ( ! MMSUCCESS(Result) )
712 {
713 return TranslateInternalMmResult(Result);
714 }
715
716 Result = GetSoundDeviceType(SoundDevice, &DeviceType);
717 SND_ASSERT( Result == MMSYSERR_NOERROR );
718
719 Result = GetSoundDeviceInstanceHandle(SoundDeviceInstance, &Handle);
720 SND_ASSERT( Result == MMSYSERR_NOERROR );
721
722 ZeroMemory(&DeviceInfo, sizeof(WDMAUD_DEVICE_INFO));
723 DeviceInfo.hDevice = Handle;
724 DeviceInfo.DeviceType = DeviceType;
725
726 if (bStart)
727 DeviceInfo.u.State = KSSTATE_RUN;
728 else
729 DeviceInfo.u.State = KSSTATE_PAUSE;
730 Result = SyncOverlappedDeviceIoControl(KernelHandle,
731 IOCTL_SETDEVICE_STATE,
732 (LPVOID) &DeviceInfo,
733 sizeof(WDMAUD_DEVICE_INFO),
734 (LPVOID) &DeviceInfo,
735 sizeof(WDMAUD_DEVICE_INFO),
736 NULL);
737
738 return Result;
739 }
740
741 MMRESULT
WdmAudGetDeviceInterfaceStringByLegacy(IN MMDEVICE_TYPE DeviceType,IN DWORD DeviceId,IN LPWSTR Interface,IN DWORD InterfaceLength,OUT DWORD * InterfaceSize)742 WdmAudGetDeviceInterfaceStringByLegacy(
743 IN MMDEVICE_TYPE DeviceType,
744 IN DWORD DeviceId,
745 IN LPWSTR Interface,
746 IN DWORD InterfaceLength,
747 OUT DWORD * InterfaceSize)
748 {
749 WDMAUD_DEVICE_INFO DeviceInfo;
750 MMRESULT Result;
751
752 ZeroMemory(&DeviceInfo, sizeof(WDMAUD_DEVICE_INFO));
753 DeviceInfo.DeviceType = DeviceType;
754 DeviceInfo.DeviceIndex = DeviceId;
755
756
757 Result = SyncOverlappedDeviceIoControl(KernelHandle,
758 IOCTL_QUERYDEVICEINTERFACESTRING,
759 (LPVOID) &DeviceInfo,
760 sizeof(WDMAUD_DEVICE_INFO),
761 (LPVOID) &DeviceInfo,
762 sizeof(WDMAUD_DEVICE_INFO),
763 NULL);
764
765
766 if ( ! MMSUCCESS(Result) )
767 {
768 return TranslateInternalMmResult(Result);
769 }
770
771
772 if (!Interface)
773 {
774 SND_ASSERT(InterfaceSize);
775
776 *InterfaceSize = DeviceInfo.u.Interface.DeviceInterfaceStringSize;
777 return MMSYSERR_NOERROR;
778 }
779
780 if (InterfaceLength < DeviceInfo.u.Interface.DeviceInterfaceStringSize)
781 {
782 /* buffer is too small */
783 return MMSYSERR_MOREDATA;
784 }
785
786 DeviceInfo.u.Interface.DeviceInterfaceStringSize = InterfaceLength;
787 DeviceInfo.u.Interface.DeviceInterfaceString = Interface;
788
789 Result = SyncOverlappedDeviceIoControl(KernelHandle,
790 IOCTL_QUERYDEVICEINTERFACESTRING,
791 (LPVOID) &DeviceInfo,
792 sizeof(WDMAUD_DEVICE_INFO),
793 (LPVOID) &DeviceInfo,
794 sizeof(WDMAUD_DEVICE_INFO),
795 NULL);
796
797 if ( MMSUCCESS(Result) && InterfaceLength > 2)
798 {
799 Interface[1] = L'\\';
800 Interface[InterfaceLength-1] = L'\0';
801 }
802
803 return Result;
804 }
805
806 MMRESULT
WdmAudGetWavePositionByLegacy(IN struct _SOUND_DEVICE_INSTANCE * SoundDeviceInstance,IN MMTIME * Time)807 WdmAudGetWavePositionByLegacy(
808 IN struct _SOUND_DEVICE_INSTANCE* SoundDeviceInstance,
809 IN MMTIME* Time)
810 {
811 MMRESULT Result;
812 PSOUND_DEVICE SoundDevice;
813 WDMAUD_DEVICE_INFO DeviceInfo;
814 MMDEVICE_TYPE DeviceType;
815 HANDLE Handle;
816
817 Result = GetSoundDeviceFromInstance(SoundDeviceInstance, &SoundDevice);
818
819 if ( ! MMSUCCESS(Result) )
820 {
821 return TranslateInternalMmResult(Result);
822 }
823
824 Result = GetSoundDeviceType(SoundDevice, &DeviceType);
825 SND_ASSERT( Result == MMSYSERR_NOERROR );
826
827 Result = GetSoundDeviceInstanceHandle(SoundDeviceInstance, &Handle);
828 SND_ASSERT( Result == MMSYSERR_NOERROR );
829
830 ZeroMemory(&DeviceInfo, sizeof(WDMAUD_DEVICE_INFO));
831 DeviceInfo.hDevice = Handle;
832 DeviceInfo.DeviceType = DeviceType;
833
834 Result = SyncOverlappedDeviceIoControl(KernelHandle,
835 IOCTL_GETPOS,
836 (LPVOID) &DeviceInfo,
837 sizeof(WDMAUD_DEVICE_INFO),
838 (LPVOID) &DeviceInfo,
839 sizeof(WDMAUD_DEVICE_INFO),
840 NULL);
841
842 if ( ! MMSUCCESS(Result) )
843 {
844 return TranslateInternalMmResult(Result);
845 }
846
847 Time->wType = TIME_BYTES;
848 Time->u.cb = (DWORD)DeviceInfo.u.Position;
849
850 return MMSYSERR_NOERROR;
851 }
852
853 MMRESULT
WdmAudGetVolumeByLegacy(_In_ PSOUND_DEVICE_INSTANCE SoundDeviceInstance,_In_ DWORD DeviceId,_Out_ PDWORD pdwVolume)854 WdmAudGetVolumeByLegacy(
855 _In_ PSOUND_DEVICE_INSTANCE SoundDeviceInstance,
856 _In_ DWORD DeviceId,
857 _Out_ PDWORD pdwVolume)
858 {
859 /* FIXME */
860 return MMSYSERR_NOTSUPPORTED;
861 }
862
863 MMRESULT
WdmAudSetVolumeByLegacy(_In_ PSOUND_DEVICE_INSTANCE SoundDeviceInstance,_In_ DWORD DeviceId,_In_ DWORD dwVolume)864 WdmAudSetVolumeByLegacy(
865 _In_ PSOUND_DEVICE_INSTANCE SoundDeviceInstance,
866 _In_ DWORD DeviceId,
867 _In_ DWORD dwVolume)
868 {
869 /* FIXME */
870 return MMSYSERR_NOTSUPPORTED;
871 }
872
873 MMRESULT
WdmAudResetStreamByLegacy(IN struct _SOUND_DEVICE_INSTANCE * SoundDeviceInstance,IN MMDEVICE_TYPE DeviceType,IN BOOLEAN bStartReset)874 WdmAudResetStreamByLegacy(
875 IN struct _SOUND_DEVICE_INSTANCE* SoundDeviceInstance,
876 IN MMDEVICE_TYPE DeviceType,
877 IN BOOLEAN bStartReset)
878 {
879 MMRESULT Result;
880 HANDLE Handle;
881 WDMAUD_DEVICE_INFO DeviceInfo;
882
883 Result = GetSoundDeviceInstanceHandle(SoundDeviceInstance, &Handle);
884 SND_ASSERT( Result == MMSYSERR_NOERROR );
885
886 ZeroMemory(&DeviceInfo, sizeof(WDMAUD_DEVICE_INFO));
887 DeviceInfo.hDevice = Handle;
888 DeviceInfo.DeviceType = DeviceType;
889 DeviceInfo.u.ResetStream = (bStartReset ? KSRESET_BEGIN : KSRESET_END);
890
891 Result = SyncOverlappedDeviceIoControl(KernelHandle,
892 IOCTL_RESET_STREAM,
893 (LPVOID) &DeviceInfo,
894 sizeof(WDMAUD_DEVICE_INFO),
895 (LPVOID) &DeviceInfo,
896 sizeof(WDMAUD_DEVICE_INFO),
897 NULL);
898 return Result;
899 }
900
901 MMRESULT
WdmAudQueryMixerInfoByLegacy(IN struct _SOUND_DEVICE_INSTANCE * SoundDeviceInstance,IN DWORD DeviceId,IN UINT uMsg,IN LPVOID Parameter,IN DWORD Flags)902 WdmAudQueryMixerInfoByLegacy(
903 IN struct _SOUND_DEVICE_INSTANCE* SoundDeviceInstance,
904 IN DWORD DeviceId,
905 IN UINT uMsg,
906 IN LPVOID Parameter,
907 IN DWORD Flags)
908 {
909 MMRESULT Result;
910 WDMAUD_DEVICE_INFO DeviceInfo;
911 HANDLE Handle;
912 DWORD IoControlCode;
913 LPMIXERLINEW MixLine;
914 LPMIXERLINECONTROLSW MixControls;
915 LPMIXERCONTROLDETAILS MixDetails;
916
917 SND_TRACE(L"uMsg %x Flags %x\n", uMsg, Flags);
918
919 Result = GetSoundDeviceInstanceHandle(SoundDeviceInstance, &Handle);
920 SND_ASSERT( Result == MMSYSERR_NOERROR );
921
922 ZeroMemory(&DeviceInfo, sizeof(WDMAUD_DEVICE_INFO));
923 DeviceInfo.hDevice = Handle;
924 DeviceInfo.DeviceIndex = DeviceId;
925 DeviceInfo.DeviceType = MIXER_DEVICE_TYPE;
926 DeviceInfo.Flags = Flags;
927
928 MixLine = (LPMIXERLINEW)Parameter;
929 MixControls = (LPMIXERLINECONTROLSW)Parameter;
930 MixDetails = (LPMIXERCONTROLDETAILS)Parameter;
931
932 switch(uMsg)
933 {
934 case MXDM_GETLINEINFO:
935 RtlCopyMemory(&DeviceInfo.u.MixLine, MixLine, sizeof(MIXERLINEW));
936 IoControlCode = IOCTL_GETLINEINFO;
937 break;
938 case MXDM_GETLINECONTROLS:
939 RtlCopyMemory(&DeviceInfo.u.MixControls, MixControls, sizeof(MIXERLINECONTROLSW));
940 IoControlCode = IOCTL_GETLINECONTROLS;
941 break;
942 case MXDM_SETCONTROLDETAILS:
943 RtlCopyMemory(&DeviceInfo.u.MixDetails, MixDetails, sizeof(MIXERCONTROLDETAILS));
944 IoControlCode = IOCTL_SETCONTROLDETAILS;
945 break;
946 case MXDM_GETCONTROLDETAILS:
947 RtlCopyMemory(&DeviceInfo.u.MixDetails, MixDetails, sizeof(MIXERCONTROLDETAILS));
948 IoControlCode = IOCTL_GETCONTROLDETAILS;
949 break;
950 default:
951 SND_ASSERT(0);
952 return MMSYSERR_NOTSUPPORTED;
953 }
954
955 Result = SyncOverlappedDeviceIoControl(KernelHandle,
956 IoControlCode,
957 (LPVOID) &DeviceInfo,
958 sizeof(WDMAUD_DEVICE_INFO),
959 (LPVOID) &DeviceInfo,
960 sizeof(WDMAUD_DEVICE_INFO),
961 NULL);
962
963 if ( ! MMSUCCESS(Result) )
964 {
965 return Result;
966 }
967
968 switch(uMsg)
969 {
970 case MXDM_GETLINEINFO:
971 {
972 RtlCopyMemory(MixLine, &DeviceInfo.u.MixLine, sizeof(MIXERLINEW));
973 break;
974 }
975 }
976
977 return Result;
978 }
979