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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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