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