Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenminwave.cpp
Go to the documentation of this file.
00001 /* 00002 Copyright (c) 2006-2007 dogbert <dogber1@gmail.com> 00003 All rights reserved. 00004 00005 Redistribution and use in source and binary forms, with or without 00006 modification, are permitted provided that the following conditions 00007 are met: 00008 1. Redistributions of source code must retain the above copyright 00009 notice, this list of conditions and the following disclaimer. 00010 2. Redistributions in binary form must reproduce the above copyright 00011 notice, this list of conditions and the following disclaimer in the 00012 documentation and/or other materials provided with the distribution. 00013 3. The name of the author may not be used to endorse or promote products 00014 derived from this software without specific prior written permission. 00015 00016 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 00017 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 00018 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 00019 IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 00020 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 00021 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 00022 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 00023 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 00024 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 00025 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00026 */ 00027 00028 #include "minwave.hpp" 00029 #include "minwavetables.hpp" 00030 #include "ntddk.h" 00031 00032 #ifdef _MSC_VER 00033 #pragma code_seg("PAGE") /* warning - ignored by GCC compiler */ 00034 #endif 00035 00036 HRESULT NTAPI CreateMiniportWaveCMI(PUNKNOWN *Unknown, REFCLSID, PUNKNOWN UnknownOuter, POOL_TYPE PoolType) 00037 { 00038 //PAGED_CODE(); 00039 //ASSERT(Unknown); 00040 #ifdef WAVERT 00041 STD_CREATE_BODY_(CMiniportWaveCMI,Unknown,UnknownOuter,PoolType,PMINIPORTWAVERT); 00042 #else 00043 STD_CREATE_BODY_(CMiniportWaveCMI,Unknown,UnknownOuter,PoolType,PMINIPORTWAVECYCLIC); 00044 #endif 00045 } 00046 00047 NTSTATUS CMiniportWaveCMI::processResources(PRESOURCELIST resourceList) 00048 { 00049 //PAGED_CODE(); 00050 //ASSERT (resourceList); 00051 DBGPRINT(("CMiniportWaveCMI[%p]::ProcessResources(%p)", this, resourceList)); 00052 00053 if (resourceList->NumberOfInterrupts() < 1) { 00054 DBGPRINT(("Unknown configuration for wave miniport")); 00055 return STATUS_DEVICE_CONFIGURATION_ERROR; 00056 } 00057 return STATUS_SUCCESS; 00058 } 00059 00060 #ifndef WAVERT 00061 NTSTATUS CMiniportWaveCMI::newDMAChannel(PDMACHANNEL *dmaChannel, UInt32 bufferLength) 00062 { 00063 //PAGED_CODE(); 00064 //ASSERT(dmaChannel); 00065 DBGPRINT(("CMiniportWaveCMI[%p]::newDMAChannel(%p)", this, dmaChannel)); 00066 00067 NTSTATUS ntStatus; 00068 00069 ntStatus = Port->NewMasterDmaChannel(dmaChannel, NULL, NULL, bufferLength, TRUE, FALSE, (DMA_WIDTH)(-1), (DMA_SPEED)(-1)); 00070 if (NT_SUCCESS(ntStatus)) { 00071 ULONG lDMABufferLength = bufferLength; 00072 do { 00073 ntStatus = (*dmaChannel)->AllocateBuffer(lDMABufferLength,NULL); 00074 lDMABufferLength >>= 1; 00075 } while (!NT_SUCCESS(ntStatus) && (lDMABufferLength > (PAGE_SIZE / 2))); 00076 } 00077 return ntStatus; 00078 } 00079 #endif 00080 00081 //generic crap 00082 STDMETHODIMP CMiniportWaveCMI::QueryInterface(REFIID Interface, PVOID *Object) 00083 { 00084 //PAGED_CODE(); 00085 //ASSERT(Object); 00086 DBGPRINT(("CMiniportWaveCMI[%p]::NonDelegatingQueryInterface")); 00087 00088 if (IsEqualGUIDAligned(Interface,IID_IUnknown)) { 00089 #ifdef WAVERT 00090 *Object = PVOID(PUNKNOWN(PMINIPORTWAVERT(this))); 00091 #else 00092 *Object = PVOID(PUNKNOWN(PMINIPORTWAVECYCLIC(this))); 00093 #endif 00094 } else if (IsEqualGUIDAligned(Interface,IID_IMiniport)) { 00095 *Object = PVOID(PMINIPORT(this)); 00096 #ifdef WAVERT 00097 } else if (IsEqualGUIDAligned(Interface,IID_IMiniportWaveRT)) { 00098 *Object = PVOID(PMINIPORTWAVERT(this)); 00099 #else 00100 } else if (IsEqualGUIDAligned(Interface,IID_IMiniportWaveCyclic)) { 00101 *Object = PVOID(PMINIPORTWAVECYCLIC(this)); 00102 #endif 00103 } else { 00104 *Object = NULL; 00105 } 00106 00107 if (*Object) { 00108 // We reference the interface for the caller. 00109 PUNKNOWN(*Object)->AddRef(); 00110 return STATUS_SUCCESS; 00111 } 00112 00113 return STATUS_INVALID_PARAMETER; 00114 } 00115 00116 CMiniportWaveCMI::~CMiniportWaveCMI(void) 00117 { 00118 //PAGED_CODE(); 00119 DBGPRINT(("CMiniportWaveCMI[%p]::~CMiniportWaveCMI", this)); 00120 00121 storeChannelConfigToRegistry(); //or not. during system shutdown, this doesn't seem to work. 00122 00123 if (CMIAdapter) { 00124 CMIAdapter->Release(); 00125 CMIAdapter = NULL; 00126 } 00127 00128 for (int i=0;i<3;i++) { 00129 #ifndef WAVERT 00130 if (DMAChannel[i]) { 00131 DMAChannel[i]->Release(); 00132 DMAChannel[i] = NULL; 00133 } 00134 #endif 00135 if (isStreamRunning[i]) { 00136 isStreamRunning[i] = false; 00137 stream[i]->Release(); 00138 stream[i] = NULL; 00139 } 00140 } 00141 00142 if (Port) { 00143 Port->Release(); 00144 Port = NULL; 00145 } 00146 } 00147 00148 #ifdef WAVERT 00149 STDMETHODIMP CMiniportWaveCMI::Init(PUNKNOWN UnknownAdapter, PRESOURCELIST ResourceList, PPORTWAVERT Port_) 00150 #else 00151 STDMETHODIMP CMiniportWaveCMI::Init(PUNKNOWN UnknownAdapter, PRESOURCELIST ResourceList, PPORTWAVECYCLIC Port_) 00152 #endif 00153 { 00154 //PAGED_CODE(); 00155 00156 //ASSERT(UnknownAdapter); 00157 //ASSERT(ResourceList); 00158 //ASSERT(Port_); 00159 00160 DBGPRINT(("CMiniportWaveCMI[%p]::Init(%p, %p, %p)", this, UnknownAdapter, ResourceList, Port_)); 00161 00162 Port = Port_; 00163 Port->AddRef(); 00164 00165 NTSTATUS ntStatus = UnknownAdapter->QueryInterface(IID_ICMIAdapter, (PVOID *) &CMIAdapter); 00166 if (!NT_SUCCESS(ntStatus)) { 00167 DBGPRINT(("QueryInterface(CMIAdapter) failed")); 00168 return ntStatus; 00169 } 00170 00171 //check for Vista, set the AC3 stuff accordingly 00172 if (IoIsWdmVersionAvailable(0x06,0x00)) { 00173 WavePinDataRangesAC3Stream[1].MinimumSampleFrequency = MIN_SAMPLE_RATE; 00174 WavePinDataRangesAC3Stream[1].MaximumSampleFrequency = MAX_SAMPLE_RATE; 00175 WavePinDataRangesAC3Stream[1].DataRange.SubFormat = KSDATAFORMAT_SUBTYPE_PCM; 00176 WavePinDataRangesAC3Stream[1].DataRange.Specifier = KSDATAFORMAT_SPECIFIER_WAVEFORMATEX; 00177 } 00178 00179 cm = CMIAdapter->getCMI8738Info(); 00180 cm->regFUNCTRL0 = 0; 00181 cm->WaveMiniport = this; 00182 00183 loadChannelConfigFromRegistry(); 00184 00185 for (int i=0;i<3;i++) 00186 { 00187 isStreamRunning[i] = false; 00188 00189 #ifndef WAVERT 00190 ntStatus = newDMAChannel(&DMAChannel[i], MAXLEN_DMA_BUFFER); 00191 if (!NT_SUCCESS(ntStatus)) { 00192 DBGPRINT(("NewDmaChannel() failed")); 00193 return ntStatus; 00194 } 00195 #endif 00196 } 00197 00198 KeInitializeMutex(&mutex, 1); 00199 00200 return processResources(ResourceList); 00201 } 00202 00203 #ifdef WAVERT 00204 STDMETHODIMP_(NTSTATUS) CMiniportWaveCMI::GetDeviceDescription(PDEVICE_DESCRIPTION OutDeviceDescriptor) 00205 { 00206 //PAGED_CODE(); 00207 //ASSERT(OutDeviceDescriptor); 00208 DBGPRINT(("CMiniportWaveCMI[%p]::GetDeviceDescription(%p)", this, OutDeviceDescriptor)); 00209 00210 RtlZeroMemory(OutDeviceDescriptor, sizeof(DEVICE_DESCRIPTION)); 00211 OutDeviceDescriptor->ScatterGather = false; 00212 OutDeviceDescriptor->Master = true; 00213 OutDeviceDescriptor->Dma32BitAddresses = true; 00214 OutDeviceDescriptor->InterfaceType = PCIBus; 00215 OutDeviceDescriptor->MaximumLength = MAXLEN_DMA_BUFFER-2; 00216 00217 return STATUS_SUCCESS; 00218 } 00219 #endif 00220 00221 STDMETHODIMP CMiniportWaveCMI::GetDescription(PPCFILTER_DESCRIPTOR *OutFilterDescriptor) 00222 { 00223 //PAGED_CODE(); 00224 //ASSERT(OutFilterDescriptor); 00225 DBGPRINT(("CMiniportWaveCMI[%p]::GetDescription(%p)", this, OutFilterDescriptor)); 00226 00227 *OutFilterDescriptor = &WaveMiniportFilterDescriptor; 00228 00229 return STATUS_SUCCESS; 00230 } 00231 00232 NTSTATUS CMiniportWaveCMI::loadChannelConfigFromRegistry() 00233 { 00234 //PAGED_CODE(); 00235 PREGISTRYKEY DriverKey; 00236 PREGISTRYKEY SettingsKey; 00237 UNICODE_STRING KeyName; 00238 //DWORD Value, ResultLength; 00239 DWORD ResultLength; 00240 PVOID KeyInfo; 00241 00242 DBGPRINT(("CMiniportWaveCMI::loadChannelConfigFromRegistry()")); 00243 00244 if ((!CMIAdapter) || (!(CMIAdapter->getDeviceObject()))) { 00245 return STATUS_UNSUCCESSFUL; 00246 } 00247 00248 NTSTATUS ntStatus = PcNewRegistryKey(&DriverKey, NULL, DriverRegistryKey, KEY_ALL_ACCESS, CMIAdapter->getDeviceObject(), NULL, NULL, 0, NULL); 00249 00250 if(!NT_SUCCESS(ntStatus)) { 00251 DBGPRINT(("PcNewRegistryKey() failed")); 00252 return STATUS_UNSUCCESSFUL; 00253 } 00254 00255 RtlInitUnicodeString(&KeyName, L"Settings"); 00256 00257 ntStatus = DriverKey->NewSubKey(&SettingsKey, NULL, KEY_ALL_ACCESS, &KeyName, REG_OPTION_NON_VOLATILE, NULL); 00258 if(!NT_SUCCESS(ntStatus)) { 00259 DBGPRINT(("DriverKey->NewSubKey() failed")); 00260 return STATUS_UNSUCCESSFUL; 00261 } 00262 00263 KeyInfo = ExAllocatePoolWithTag(PagedPool, sizeof(KEY_VALUE_PARTIAL_INFORMATION) + sizeof(DWORD), 'gnaa'); 00264 if (KeyInfo) { 00265 RtlInitUnicodeString(&KeyName, L"ChannelCount"); 00266 ntStatus = SettingsKey->QueryValueKey(&KeyName, KeyValuePartialInformation, KeyInfo, sizeof(KEY_VALUE_PARTIAL_INFORMATION) + sizeof(DWORD), &ResultLength); 00267 if (NT_SUCCESS (ntStatus)) { 00268 PKEY_VALUE_PARTIAL_INFORMATION PartialInfo = (PKEY_VALUE_PARTIAL_INFORMATION)KeyInfo; 00269 if (PartialInfo->DataLength == sizeof(DWORD)) { 00270 requestedChannelCount = (*(PLONG)PartialInfo->Data); 00271 } 00272 } else { 00273 requestedChannelCount = 2; 00274 } 00275 00276 RtlInitUnicodeString(&KeyName, L"ChannelMask"); 00277 ntStatus = SettingsKey->QueryValueKey(&KeyName, KeyValuePartialInformation, KeyInfo, sizeof(KEY_VALUE_PARTIAL_INFORMATION) + sizeof(DWORD), &ResultLength); 00278 if (NT_SUCCESS (ntStatus)) { 00279 PKEY_VALUE_PARTIAL_INFORMATION PartialInfo = (PKEY_VALUE_PARTIAL_INFORMATION)KeyInfo; 00280 if (PartialInfo->DataLength == sizeof(DWORD)) { 00281 requestedChannelMask = (*(PLONG)PartialInfo->Data); 00282 } 00283 } else { 00284 requestedChannelMask = KSAUDIO_SPEAKER_STEREO; 00285 } 00286 } 00287 ExFreePoolWithTag(KeyInfo,'gnaa'); 00288 00289 SettingsKey->Release(); 00290 DriverKey->Release(); 00291 00292 return STATUS_SUCCESS; 00293 } 00294 00295 NTSTATUS CMiniportWaveCMI::storeChannelConfigToRegistry() 00296 { 00297 //PAGED_CODE(); 00298 PREGISTRYKEY DriverKey; 00299 PREGISTRYKEY SettingsKey; 00300 UNICODE_STRING KeyName; 00301 DWORD Value; 00302 DBGPRINT(("CMiniportWaveCMI::storeChannelConfigToRegistry()")); 00303 00304 if ((!CMIAdapter) || (!(CMIAdapter->getDeviceObject()))) { 00305 return STATUS_UNSUCCESSFUL; 00306 } 00307 00308 NTSTATUS ntStatus = PcNewRegistryKey(&DriverKey, NULL, DriverRegistryKey, KEY_ALL_ACCESS, CMIAdapter->getDeviceObject(), NULL, NULL, 0, NULL); 00309 00310 if(!NT_SUCCESS(ntStatus)) { 00311 DBGPRINT(("PcNewRegistryKey() failed")); 00312 return STATUS_UNSUCCESSFUL; 00313 } 00314 00315 RtlInitUnicodeString(&KeyName, L"Settings"); 00316 00317 ntStatus = DriverKey->NewSubKey(&SettingsKey, NULL, KEY_ALL_ACCESS, &KeyName, REG_OPTION_NON_VOLATILE, NULL); 00318 if(!NT_SUCCESS(ntStatus)) { 00319 DBGPRINT(("DriverKey->NewSubKey() failed")); 00320 return STATUS_UNSUCCESSFUL; 00321 } 00322 00323 Value = requestedChannelCount; 00324 RtlInitUnicodeString(&KeyName, L"ChannelCount"); 00325 ntStatus = SettingsKey->SetValueKey(&KeyName, REG_DWORD, PVOID(&Value), sizeof(DWORD)); 00326 if (!NT_SUCCESS(ntStatus)) { 00327 DBGPRINT(("SetValueKey() failed")); 00328 } 00329 Value = requestedChannelMask; 00330 RtlInitUnicodeString(&KeyName, L"ChannelMask"); 00331 ntStatus = SettingsKey->SetValueKey(&KeyName, REG_DWORD, PVOID(&Value), sizeof(DWORD)); 00332 if (!NT_SUCCESS(ntStatus)) { 00333 DBGPRINT(("SetValueKey() failed")); 00334 } 00335 00336 SettingsKey->Release(); 00337 DriverKey->Release(); 00338 00339 return STATUS_SUCCESS; 00340 } 00341 00342 00343 STDMETHODIMP_(void) CMiniportWaveCMI::powerUp(void) 00344 { 00345 //PAGED_CODE(); 00346 DBGPRINT(("CMiniportWaveCMI[%p]::powerUp()", this)); 00347 KSSTATE oldState[3]; 00348 00349 for (int i=0;i<3;i++) { 00350 if (isStreamRunning[i]) { 00351 oldState[i] = stream[i]->state; 00352 stream[i]->SetState(KSSTATE_STOP); 00353 } 00354 } 00355 00356 if (cm->TopoMiniport) { 00357 cm->TopoMiniport->loadMixerSettingsFromMemory(); 00358 } 00359 00360 for (int i=0;i<3;i++) { 00361 if (isStreamRunning[i]) { 00362 stream[i]->prepareStream(); 00363 stream[i]->SetState(KSSTATE_ACQUIRE); 00364 stream[i]->SetState(oldState[i]); 00365 } 00366 } 00367 } 00368 00369 STDMETHODIMP_(void) CMiniportWaveCMI::powerDown(void) 00370 { 00371 //PAGED_CODE(); 00372 DBGPRINT(("CMiniportWaveCMI[%p]::powerDown()", this)); 00373 00374 if (cm->TopoMiniport) { 00375 cm->TopoMiniport->storeMixerSettingsToMemory(); 00376 } 00377 00378 } 00379 00380 00381 NTSTATUS CMiniportWaveCMI::isFormatAllowed(UInt32 sampleRate, BOOLEAN multiChan, BOOLEAN AC3) 00382 { 00383 //PAGED_CODE(); 00384 //ASSERT(sampleRate); 00385 DBGPRINT(("CMiniportWaveCMI[%p]::isFormatAllowed(%d, %d, %d)", this, sampleRate, multiChan, AC3)); 00386 00387 if (multiChan) { 00388 switch (sampleRate) { 00389 case 44100: if (cm->formatMask & FMT_441_MULTI_PCM) return STATUS_SUCCESS; break; 00390 case 48000: if (cm->formatMask & FMT_480_MULTI_PCM) return STATUS_SUCCESS; break; 00391 case 88200: if (cm->formatMask & FMT_882_MULTI_PCM) return STATUS_SUCCESS; break; 00392 case 96000: if (cm->formatMask & FMT_960_MULTI_PCM) return STATUS_SUCCESS; break; 00393 } 00394 return STATUS_INVALID_PARAMETER; 00395 } 00396 if (AC3) { 00397 switch (sampleRate) { 00398 case 44100: if (cm->formatMask & FMT_441_DOLBY) return STATUS_SUCCESS; break; 00399 case 48000: if (cm->formatMask & FMT_480_DOLBY) return STATUS_SUCCESS; break; 00400 case 88200: if (cm->formatMask & FMT_882_DOLBY) return STATUS_SUCCESS; break; 00401 case 96000: if (cm->formatMask & FMT_960_DOLBY) return STATUS_SUCCESS; break; 00402 } 00403 return STATUS_INVALID_PARAMETER; 00404 } 00405 switch (sampleRate) { 00406 case 44100: if (cm->formatMask & FMT_441_PCM) return STATUS_SUCCESS; break; 00407 case 48000: if (cm->formatMask & FMT_480_PCM) return STATUS_SUCCESS; break; 00408 case 88200: if (cm->formatMask & FMT_882_PCM) return STATUS_SUCCESS; break; 00409 case 96000: if (cm->formatMask & FMT_960_PCM) return STATUS_SUCCESS; break; 00410 } 00411 return STATUS_INVALID_PARAMETER; 00412 } 00413 00414 NTSTATUS CMiniportWaveCMI::validateFormat(PKSDATAFORMAT format, ULONG PinID, BOOLEAN capture) 00415 { 00416 //PAGED_CODE(); 00417 //ASSERT(format); 00418 DBGPRINT(("CMiniportWaveCMI[%p]::validateFormat(%p, %d, %d)", this, format, PinID, capture)); 00419 00420 PWAVEFORMATEX waveFormat = PWAVEFORMATEX(format + 1); 00421 DBGPRINT(("---channels: %d, resolution: %d, sample rate: %d, pin: %d, formatMask: %x", waveFormat->nChannels, waveFormat->wBitsPerSample, waveFormat->nSamplesPerSec, PinID, cm->formatMask)); 00422 00423 //WaveFormatEx 00424 if ( ( (size_t) format->FormatSize >= sizeof(KSDATAFORMAT_WAVEFORMATEX)) 00425 && IsEqualGUIDAligned(format->MajorFormat,KSDATAFORMAT_TYPE_AUDIO) 00426 && IsEqualGUIDAligned(format->Specifier,KSDATAFORMAT_SPECIFIER_WAVEFORMATEX) ) { 00427 switch (EXTRACT_WAVEFORMATEX_ID(&format->SubFormat)) { 00428 case WAVE_FORMAT_PCM: 00429 if ((PinID != PIN_WAVE_RENDER_SINK) && (PinID != PIN_WAVE_CAPTURE_SOURCE) && ((int)PinID != -1)) { 00430 if ((PinID == PIN_WAVE_AC3_RENDER_SINK) && !IoIsWdmVersionAvailable(6,0)) { 00431 return STATUS_INVALID_PARAMETER; 00432 } 00433 } 00434 00435 if ( ((waveFormat->wBitsPerSample == 16) || (waveFormat->wBitsPerSample == 24)) 00436 && ((waveFormat->nSamplesPerSec == 44100) || (waveFormat->nSamplesPerSec == 48000) || (waveFormat->nSamplesPerSec == 88200) || (waveFormat->nSamplesPerSec == 96000)) 00437 && (waveFormat->nChannels == 2) ) { 00438 if ((capture) && (waveFormat->nSamplesPerSec > 48000) ) { 00439 return STATUS_INVALID_PARAMETER; 00440 } 00441 return isFormatAllowed(waveFormat->nSamplesPerSec, FALSE, FALSE); 00442 } 00443 if ( (waveFormat->wBitsPerSample == 16) 00444 && ((waveFormat->nChannels >= 4) && (waveFormat->nChannels <= (WORD) cm->maxChannels)) 00445 && ((waveFormat->nSamplesPerSec == 44100) || (waveFormat->nSamplesPerSec == 48000)) ) { 00446 #if OUT_CHANNEL == 1 00447 if ((PinID == PIN_WAVE_RENDER_SINK) || ((int)PinID == -1)) { 00448 return isFormatAllowed(waveFormat->nSamplesPerSec, TRUE, FALSE); 00449 } 00450 #else 00451 return STATUS_INVALID_PARAMETER; 00452 #endif 00453 } 00454 break; 00455 case WAVE_FORMAT_DOLBY_AC3_SPDIF: 00456 if ((PinID != PIN_WAVE_AC3_RENDER_SINK) && ((int)PinID != -1)) { 00457 return STATUS_INVALID_PARAMETER; 00458 } 00459 if ( ((waveFormat->wBitsPerSample >= MIN_BITS_PER_SAMPLE_AC3) && (waveFormat->wBitsPerSample <= MAX_BITS_PER_SAMPLE_AC3)) 00460 && ((waveFormat->nSamplesPerSec >= MIN_SAMPLE_RATE_AC3) && (waveFormat->nSamplesPerSec <= MAX_SAMPLE_RATE_AC3)) 00461 && (waveFormat->nChannels == MAX_CHANNELS_AC3) ) { 00462 return isFormatAllowed(waveFormat->nSamplesPerSec, FALSE, TRUE); 00463 } 00464 break; 00465 } 00466 } 00467 00468 return STATUS_INVALID_PARAMETER; 00469 } 00470 00471 // Tests a data range intersection 00472 STDMETHODIMP CMiniportWaveCMI::DataRangeIntersection(ULONG PinId, PKSDATARANGE ClientDataRange, PKSDATARANGE MyDataRange, ULONG OutputBufferLength, PVOID ResultantFormat, PULONG ResultantFormatLength) 00473 { 00474 //PAGED_CODE(); 00475 static const GUID KSDATAFORMAT_SUBTYPE_DOLBY_AC3_SPDIF = {0x00000092L, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}}; 00476 00477 00478 DBGPRINT(("CMiniportWaveCMI[%p]::DataRangeIntersection(%d, %p, %p, %d, %p, %p)", this, PinId, ClientDataRange, MyDataRange, OutputBufferLength, ResultantFormat, ResultantFormatLength)); 00479 00480 if (PinId == PIN_WAVE_AC3_RENDER_SINK) { 00481 bool isAC3Pin = true; 00482 // Under Windows 2000 and XP, the client's DataRange should be AC3 only. 00483 // The AC3 pin is the SPDIF pin in Windows Vista, so 2ch stereo is going to be allowed. 00484 00485 if (!IsEqualGUIDAligned(ClientDataRange->MajorFormat, KSDATAFORMAT_TYPE_AUDIO) 00486 && !IsEqualGUIDAligned(ClientDataRange->MajorFormat, KSDATAFORMAT_TYPE_WILDCARD)) { 00487 return STATUS_NO_MATCH; 00488 } 00489 00490 00491 if (!IsEqualGUIDAligned(ClientDataRange->SubFormat, KSDATAFORMAT_SUBTYPE_DOLBY_AC3_SPDIF) 00492 && !IsEqualGUIDAligned(ClientDataRange->SubFormat, KSDATAFORMAT_SUBTYPE_WILDCARD)) { 00493 // check for Vista 00494 isAC3Pin = false; 00495 if (IoIsWdmVersionAvailable(0x06,0x00)) { 00496 if (!IsEqualGUIDAligned(ClientDataRange->SubFormat, KSDATAFORMAT_SUBTYPE_PCM) 00497 && !IsEqualGUIDAligned(ClientDataRange->SubFormat, KSDATAFORMAT_SUBTYPE_WILDCARD)) { 00498 return STATUS_NO_MATCH; 00499 } 00500 } else { 00501 return STATUS_NO_MATCH; 00502 } 00503 } 00504 00505 if (IsEqualGUIDAligned(ClientDataRange->Specifier, KSDATAFORMAT_SPECIFIER_WAVEFORMATEX) 00506 || IsEqualGUIDAligned(ClientDataRange->Specifier, KSDATAFORMAT_SPECIFIER_WILDCARD)) { 00507 *ResultantFormatLength = sizeof(KSDATAFORMAT_WAVEFORMATEX); 00508 } else 00509 if (IsEqualGUIDAligned(ClientDataRange->Specifier, KSDATAFORMAT_SPECIFIER_DSOUND)) { 00510 *ResultantFormatLength = sizeof(KSDATAFORMAT_DSOUND); 00511 } else { 00512 return STATUS_NO_MATCH; 00513 } 00514 00515 // Validate return buffer size, if the request is only for the 00516 // size of the resultant structure, return it now. 00517 if (!OutputBufferLength) { 00518 *ResultantFormatLength = sizeof(KSDATAFORMAT_WAVEFORMATEX); 00519 return STATUS_BUFFER_OVERFLOW; 00520 } else 00521 if (OutputBufferLength < sizeof(KSDATAFORMAT_WAVEFORMATEX)) { 00522 return STATUS_BUFFER_TOO_SMALL; 00523 } 00524 00525 PKSDATAFORMAT_WAVEFORMATEX resultantFormatWFX = (PKSDATAFORMAT_WAVEFORMATEX) ResultantFormat; 00526 PWAVEFORMATEX pWaveFormatEx; 00527 00528 // Return the best (only) available format. 00529 resultantFormatWFX->DataFormat.FormatSize = *ResultantFormatLength; 00530 resultantFormatWFX->DataFormat.Flags = 0; 00531 resultantFormatWFX->DataFormat.SampleSize = 4; // must match nBlockAlign 00532 resultantFormatWFX->DataFormat.Reserved = 0; 00533 00534 resultantFormatWFX->DataFormat.MajorFormat = KSDATAFORMAT_TYPE_AUDIO; 00535 INIT_WAVEFORMATEX_GUID(&resultantFormatWFX->DataFormat.SubFormat, WAVE_FORMAT_DOLBY_AC3_SPDIF); 00536 00537 // Extra space for the DSound specifier 00538 if (IsEqualGUIDAligned(ClientDataRange->Specifier, KSDATAFORMAT_SPECIFIER_DSOUND)) { 00539 00540 PKSDATAFORMAT_DSOUND resultantFormatDSound = (PKSDATAFORMAT_DSOUND)ResultantFormat; 00541 00542 resultantFormatDSound->DataFormat.Specifier = KSDATAFORMAT_SPECIFIER_DSOUND; 00543 00544 // DSound format capabilities are not expressed 00545 // this way in KS, so we express no capabilities. 00546 resultantFormatDSound->BufferDesc.Flags = 0 ; 00547 resultantFormatDSound->BufferDesc.Control = 0 ; 00548 00549 pWaveFormatEx = &resultantFormatDSound->BufferDesc.WaveFormatEx; 00550 } else { 00551 // WAVEFORMATEX or WILDCARD (WAVEFORMATEX) 00552 resultantFormatWFX->DataFormat.Specifier = KSDATAFORMAT_SPECIFIER_WAVEFORMATEX; 00553 00554 pWaveFormatEx = (PWAVEFORMATEX)((PKSDATAFORMAT)resultantFormatWFX + 1); 00555 } 00556 00557 pWaveFormatEx->nChannels = 2; 00558 pWaveFormatEx->wBitsPerSample = 16; // SPDIF 00559 pWaveFormatEx->cbSize = 0; 00560 if (isAC3Pin) { 00561 pWaveFormatEx->wFormatTag = WAVE_FORMAT_DOLBY_AC3_SPDIF; 00562 pWaveFormatEx->nSamplesPerSec = 48000; 00563 } else { 00564 pWaveFormatEx->wFormatTag = WAVE_FORMAT_PCM; 00565 pWaveFormatEx->nSamplesPerSec = min( ((PKSDATARANGE_AUDIO)ClientDataRange)->MaximumSampleFrequency, MAX_SAMPLE_RATE); 00566 } 00567 pWaveFormatEx->nBlockAlign = pWaveFormatEx->nChannels * pWaveFormatEx->wBitsPerSample / 8; 00568 pWaveFormatEx->nAvgBytesPerSec = pWaveFormatEx->nSamplesPerSec * pWaveFormatEx->nBlockAlign; 00569 00570 return STATUS_SUCCESS; 00571 } 00572 if ((PinId == PIN_WAVE_RENDER_SINK) || (PinId == PIN_WAVE_CAPTURE_SINK)) { 00573 00574 if (!IsEqualGUIDAligned(ClientDataRange->SubFormat, KSDATAFORMAT_SUBTYPE_PCM) && 00575 !IsEqualGUIDAligned(ClientDataRange->SubFormat, KSDATAFORMAT_SUBTYPE_WILDCARD)) { 00576 return STATUS_NO_MATCH; 00577 } 00578 00579 if (!IsEqualGUIDAligned(ClientDataRange->MajorFormat, KSDATAFORMAT_TYPE_AUDIO) && 00580 !IsEqualGUIDAligned(ClientDataRange->MajorFormat, KSDATAFORMAT_TYPE_WILDCARD)) { 00581 return STATUS_NO_MATCH; 00582 } 00583 00584 if (IsEqualGUIDAligned(ClientDataRange->Specifier, KSDATAFORMAT_SPECIFIER_WAVEFORMATEX) || 00585 IsEqualGUIDAligned(ClientDataRange->Specifier, KSDATAFORMAT_SPECIFIER_WILDCARD)) { 00586 *ResultantFormatLength = sizeof(KSDATAFORMAT_WAVEFORMATEX); 00587 } else 00588 if (IsEqualGUIDAligned(ClientDataRange->Specifier, KSDATAFORMAT_SPECIFIER_DSOUND)) { 00589 *ResultantFormatLength = sizeof(KSDATAFORMAT_DSOUND); 00590 } else { 00591 return STATUS_NO_MATCH; 00592 } 00593 00594 00595 ULONG sampleRate = 0; 00596 ULONG nMaxChannels = min(((PKSDATARANGE_AUDIO)ClientDataRange)->MaximumChannels, requestedChannelCount); 00597 00598 // check for Vista 00599 if (IoIsWdmVersionAvailable(6,0) && (PinId == PIN_WAVE_RENDER_SINK)) { 00600 nMaxChannels = ((PKSDATARANGE_AUDIO)ClientDataRange)->MaximumChannels; 00601 } 00602 if (nMaxChannels & 0x01) { 00603 nMaxChannels--; 00604 } 00605 if (!nMaxChannels) { 00606 return STATUS_NO_MATCH; 00607 } 00608 00609 if (isStreamRunning[PCM_OUT_STREAM]) { 00610 sampleRate = stream[PCM_OUT_STREAM]->currentSampleRate; 00611 } else 00612 if (isStreamRunning[PCM_IN_STREAM]) { 00613 sampleRate = stream[PCM_IN_STREAM]->currentSampleRate; 00614 } 00615 if (sampleRate == 0) { 00616 if ((nMaxChannels > 2) && (((PKSDATARANGE_AUDIO)ClientDataRange)->MaximumSampleFrequency > MAX_SAMPLE_RATE_MULTI)) { 00617 sampleRate = MAX_SAMPLE_RATE_MULTI; 00618 } else 00619 if ((nMaxChannels == 2) && (((PKSDATARANGE_AUDIO)ClientDataRange)->MaximumSampleFrequency > MAX_SAMPLE_RATE)) { 00620 sampleRate = MAX_SAMPLE_RATE; 00621 } else { 00622 sampleRate = ((PKSDATARANGE_AUDIO)ClientDataRange)->MaximumSampleFrequency; 00623 } 00624 } 00625 00626 if ((((PKSDATARANGE_AUDIO)ClientDataRange)->MaximumSampleFrequency < sampleRate) 00627 || (((PKSDATARANGE_AUDIO)ClientDataRange)->MinimumSampleFrequency > sampleRate)) { 00628 return STATUS_NO_MATCH; 00629 } 00630 00631 if (PinId == PIN_WAVE_RENDER_SINK) { 00632 if (!OutputBufferLength) { 00633 *ResultantFormatLength = sizeof(KSDATAFORMAT) + sizeof(WAVEFORMATPCMEX); 00634 return STATUS_BUFFER_OVERFLOW; 00635 } else 00636 if (OutputBufferLength < sizeof(KSDATAFORMAT) + sizeof(WAVEFORMATPCMEX)) { 00637 return STATUS_BUFFER_TOO_SMALL; 00638 } 00639 00640 if (((PKSDATARANGE_AUDIO)ClientDataRange)->MaximumChannels < 2) { 00641 DBGPRINT(("[[DataRangeIntersection] mono format not supported")); 00642 return STATUS_NO_MATCH; 00643 } 00644 00645 PWAVEFORMATPCMEX WaveFormat = (PWAVEFORMATPCMEX)((PKSDATAFORMAT)ResultantFormat + 1); 00646 if (IsEqualGUIDAligned(ClientDataRange->Specifier, KSDATAFORMAT_SPECIFIER_DSOUND)) { 00647 return STATUS_NOT_SUPPORTED; 00648 } 00649 *(PKSDATAFORMAT)ResultantFormat = *MyDataRange; 00650 ((PKSDATAFORMAT)ResultantFormat)->FormatSize = sizeof(KSDATAFORMAT) + sizeof(WAVEFORMATPCMEX); 00651 00652 00653 WaveFormat->Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE; 00654 WaveFormat->SubFormat = KSDATAFORMAT_SUBTYPE_PCM; 00655 WaveFormat->Format.nChannels = (WORD)nMaxChannels; 00656 WaveFormat->Format.wBitsPerSample = 16; 00657 WaveFormat->Format.nBlockAlign = (WaveFormat->Format.wBitsPerSample >> 3) * WaveFormat->Format.nChannels; 00658 WaveFormat->Format.nAvgBytesPerSec = WaveFormat->Format.nSamplesPerSec * WaveFormat->Format.nBlockAlign; 00659 WaveFormat->Format.cbSize = sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX); 00660 WaveFormat->Format.nSamplesPerSec = sampleRate; 00661 WaveFormat->Samples.wValidBitsPerSample = WaveFormat->Format.wBitsPerSample; 00662 switch (nMaxChannels) { 00663 case 8: WaveFormat->dwChannelMask = KSAUDIO_SPEAKER_7POINT1; break; 00664 case 6: WaveFormat->dwChannelMask = KSAUDIO_SPEAKER_5POINT1; break; 00665 case 4: WaveFormat->dwChannelMask = KSAUDIO_SPEAKER_QUAD; break; 00666 case 2: WaveFormat->dwChannelMask = KSAUDIO_SPEAKER_STEREO; break; 00667 } 00668 if (nMaxChannels == requestedChannelCount) { 00669 WaveFormat->dwChannelMask = requestedChannelMask; 00670 } 00671 ((PKSDATAFORMAT)ResultantFormat)->SampleSize = WaveFormat->Format.nBlockAlign; 00672 00673 *ResultantFormatLength = sizeof(KSDATAFORMAT) + sizeof(WAVEFORMATPCMEX); 00674 DBGPRINT(("[DataRangeIntersection] MultiChannel Renderer: SampleRate: %d, ClientDataRange->MaxChans: %d, Channels: %d, BitPerSample: %d, BlockAlign: %d, AvgBytesPerSec: %d, ChannelMask: %08X", WaveFormat->Format.nSamplesPerSec, ((PKSDATARANGE_AUDIO)ClientDataRange)->MaximumChannels, WaveFormat->Format.nChannels, WaveFormat->Format.wBitsPerSample, WaveFormat->Format.nBlockAlign, WaveFormat->Format.nAvgBytesPerSec, WaveFormat->dwChannelMask)); 00675 } else 00676 if (PinId == PIN_WAVE_CAPTURE_SINK) { 00677 PKSDATAFORMAT_WAVEFORMATEX resultantFormatWFX; 00678 PWAVEFORMATEX pWaveFormatEx; 00679 00680 if (!OutputBufferLength) { 00681 *ResultantFormatLength = sizeof(KSDATAFORMAT_WAVEFORMATEX); 00682 return STATUS_BUFFER_OVERFLOW; 00683 } else 00684 if (OutputBufferLength < sizeof(KSDATAFORMAT_WAVEFORMATEX)) { 00685 return STATUS_BUFFER_TOO_SMALL; 00686 } 00687 00688 if (nMaxChannels > 2) { 00689 nMaxChannels = 2; 00690 } 00691 00692 resultantFormatWFX = (PKSDATAFORMAT_WAVEFORMATEX) ResultantFormat; 00693 resultantFormatWFX->DataFormat.FormatSize = *ResultantFormatLength; 00694 resultantFormatWFX->DataFormat.Flags = 0; 00695 resultantFormatWFX->DataFormat.SampleSize = 4; 00696 resultantFormatWFX->DataFormat.Reserved = 0; 00697 resultantFormatWFX->DataFormat.MajorFormat = KSDATAFORMAT_TYPE_AUDIO; 00698 INIT_WAVEFORMATEX_GUID(&resultantFormatWFX->DataFormat.SubFormat, WAVE_FORMAT_PCM); 00699 00700 if (IsEqualGUIDAligned(ClientDataRange->Specifier, KSDATAFORMAT_SPECIFIER_DSOUND)) { 00701 PKSDATAFORMAT_DSOUND resultantFormatDSound; 00702 resultantFormatDSound = (PKSDATAFORMAT_DSOUND)ResultantFormat; 00703 resultantFormatDSound->DataFormat.Specifier = KSDATAFORMAT_SPECIFIER_DSOUND; 00704 resultantFormatDSound->BufferDesc.Flags = 0 ; 00705 resultantFormatDSound->BufferDesc.Control = 0 ; 00706 pWaveFormatEx = &resultantFormatDSound->BufferDesc.WaveFormatEx; 00707 } else { 00708 resultantFormatWFX->DataFormat.Specifier = KSDATAFORMAT_SPECIFIER_WAVEFORMATEX; 00709 pWaveFormatEx = (PWAVEFORMATEX)((PKSDATAFORMAT)resultantFormatWFX + 1); 00710 } 00711 pWaveFormatEx->wFormatTag = WAVE_FORMAT_PCM; 00712 pWaveFormatEx->nChannels = nMaxChannels; 00713 pWaveFormatEx->nSamplesPerSec = sampleRate; 00714 pWaveFormatEx->wBitsPerSample = 16; 00715 pWaveFormatEx->cbSize = 0; 00716 pWaveFormatEx->nBlockAlign = 4; 00717 pWaveFormatEx->nAvgBytesPerSec = 192000; 00718 } 00719 return STATUS_SUCCESS; 00720 } 00721 return STATUS_NO_MATCH; 00722 } 00723 00724 //from IMiniportWaveCyclic::NewStream() 00725 #ifdef WAVERT 00726 STDMETHODIMP CMiniportWaveCMI::NewStream(PMINIPORTWAVERTSTREAM *OutStream, PPORTWAVERTSTREAM OuterUnknown, ULONG PinID, BOOLEAN Capture, PKSDATAFORMAT DataFormat) 00727 #else 00728 STDMETHODIMP CMiniportWaveCMI::NewStream(PMINIPORTWAVECYCLICSTREAM *OutStream, PUNKNOWN OuterUnknown, POOL_TYPE PoolType, ULONG PinID, BOOLEAN Capture, PKSDATAFORMAT DataFormat, PDMACHANNEL* OutDmaChannel, PSERVICEGROUP* OutServiceGroup) 00729 #endif 00730 { 00731 //PAGED_CODE(); 00732 //ASSERT(OutStream); 00733 //ASSERT(DataFormat); 00734 #ifdef WAVERT 00735 DBGPRINT(("CMiniportWaveCMI[%p]::NewStream(%p, %p, %d, %d, %p)", this, OutStream, OuterUnknown, PinID, Capture, DataFormat)); 00736 #else 00737 //ASSERT(OutDmaChannel); 00738 //ASSERT(OutServiceGroup); 00739 DBGPRINT(("CMiniportWaveCMI[%p]::NewStream(%p, %p, %p, %d, %d, %p, %p, %p)", this, OutStream, OuterUnknown, PoolType, PinID, Capture, DataFormat, OutDmaChannel, OutServiceGroup)); 00740 #endif 00741 00742 NTSTATUS ntStatus = STATUS_SUCCESS; 00743 PWAVEFORMATEX waveFormat = PWAVEFORMATEX(DataFormat + 1); 00744 UInt32 streamIndex = PCM_OUT_STREAM; 00745 00746 ntStatus = validateFormat(DataFormat, PinID, Capture); 00747 if (!NT_SUCCESS(ntStatus)) { 00748 DBGPRINT(("invalid stream format")); 00749 return STATUS_UNSUCCESSFUL; 00750 } 00751 00752 CMIAdapter->setUInt8Bit(REG_MIXER1, EN_SPDI2DAC); 00753 00754 if (Capture) { 00755 streamIndex = PCM_IN_STREAM; 00756 } else if (WAVE_FORMAT_DOLBY_AC3_SPDIF == EXTRACT_WAVEFORMATEX_ID(&DataFormat->SubFormat)) { 00757 streamIndex = AC3_OUT_STREAM; 00758 } 00759 00760 // make sure the hardware is not already in use 00761 if (isStreamRunning[streamIndex]) { 00762 DBGPRINT(("Stream %d running, exiting...", streamIndex)); 00763 return STATUS_UNSUCCESSFUL; 00764 } 00765 if ((streamIndex == AC3_OUT_STREAM) && isStreamRunning[PCM_OUT_STREAM]) { 00766 stream[PCM_OUT_STREAM]->SetState(KSSTATE_STOP_AC3); 00767 } 00768 if ((streamIndex == PCM_OUT_STREAM) && isStreamRunning[AC3_OUT_STREAM]) { 00769 return STATUS_UNSUCCESSFUL; 00770 } 00771 00772 DBGPRINT(("---StreamNo: %d, Bits: %d, Sample Rate: %d, Channels: %d, AC3: %d", streamIndex, 00773 waveFormat->wBitsPerSample, waveFormat->nSamplesPerSec, waveFormat->nChannels, 00774 (WAVE_FORMAT_DOLBY_AC3_SPDIF == EXTRACT_WAVEFORMATEX_ID(&DataFormat->SubFormat)))); 00775 00776 // the DAC and ADC can only run at the same sample rate simultaneously 00777 if ((streamIndex == PCM_IN_STREAM) && isStreamRunning[PCM_OUT_STREAM]) { 00778 if (waveFormat->nSamplesPerSec != stream[PCM_OUT_STREAM]->currentSampleRate) { 00779 return STATUS_UNSUCCESSFUL; 00780 } 00781 } 00782 if ((streamIndex == PCM_OUT_STREAM) && isStreamRunning[PCM_IN_STREAM]) { 00783 if (waveFormat->nSamplesPerSec != stream[PCM_IN_STREAM]->currentSampleRate) { 00784 return STATUS_UNSUCCESSFUL; 00785 } 00786 } 00787 00788 // instantiate a stream 00789 #ifdef WAVERT 00790 ntStatus = CreateMiniportWaveStreamCMI(&stream[streamIndex], OuterUnknown, NonPagedPool); 00791 #else 00792 ntStatus = CreateMiniportWaveStreamCMI(&stream[streamIndex], OuterUnknown, PoolType); 00793 #endif 00794 if (!NT_SUCCESS (ntStatus)) { 00795 DBGPRINT(("Failed to create stream")); 00796 return ntStatus; 00797 } 00798 00799 // initialize it 00800 #ifdef WAVERT 00801 ntStatus = stream[streamIndex]->Init(this, streamIndex, Capture, DataFormat, OuterUnknown); 00802 #else 00803 ntStatus = stream[streamIndex]->Init(this, streamIndex, Capture, DataFormat, DMAChannel[streamIndex], OutServiceGroup); 00804 #endif 00805 if (!NT_SUCCESS(ntStatus)) { 00806 DBGPRINT(("Failed to init stream")); 00807 stream[streamIndex]->Release(); 00808 stream[streamIndex] = NULL; 00809 *OutStream = NULL; 00810 #ifndef WAVERT 00811 *OutServiceGroup = NULL; 00812 *OutDmaChannel = NULL; 00813 #endif 00814 return ntStatus; 00815 } 00816 00817 #ifdef WAVERT 00818 //this has been referenced in CreateMiniportWaveStreamCMI() already 00819 *OutStream = (PMINIPORTWAVERTSTREAM)stream[streamIndex]; 00820 #else 00821 *OutDmaChannel = DMAChannel[streamIndex]; 00822 DMAChannel[streamIndex]->AddRef(); 00823 *OutStream = (PMINIPORTWAVECYCLICSTREAM)stream[streamIndex]; 00824 #endif 00825 00826 return ntStatus; 00827 } 00828 00829 NTSTATUS NTAPI PropertyHandler_ChannelConfig(PPCPROPERTY_REQUEST PropertyRequest) 00830 { 00831 //PAGED_CODE(); 00832 //ASSERT(PropertyRequest); 00833 DBGPRINT(("[PropertyHandler_ChannelConfig]")); 00834 00835 #ifdef WAVERT 00836 CMiniportWaveCMI *that = (CMiniportWaveCMI *) ((PMINIPORTWAVERT)PropertyRequest->MajorTarget); 00837 #else 00838 CMiniportWaveCMI *that = (CMiniportWaveCMI *) ((PMINIPORTWAVECYCLIC)PropertyRequest->MajorTarget); 00839 #endif 00840 00841 if (PropertyRequest->Node == KSNODE_WAVE_DAC) { 00842 00843 if (PropertyRequest->ValueSize == 0) { 00844 PropertyRequest->ValueSize = sizeof(LONG); 00845 return STATUS_BUFFER_OVERFLOW; 00846 } else if (PropertyRequest->ValueSize < sizeof (LONG)) { 00847 PropertyRequest->ValueSize = 0; 00848 return STATUS_BUFFER_TOO_SMALL; 00849 } 00850 00851 if (PropertyRequest->Verb & KSPROPERTY_TYPE_GET) { 00852 *(PLONG)PropertyRequest->Value = that->requestedChannelMask; 00853 PropertyRequest->ValueSize = sizeof(ULONG); 00854 return STATUS_SUCCESS; 00855 } else if (PropertyRequest->Verb & KSPROPERTY_TYPE_SET) { 00856 if (*(PLONG)PropertyRequest->Value == KSAUDIO_SPEAKER_7POINT1) { 00857 that->requestedChannelMask = *(PLONG)PropertyRequest->Value; 00858 that->requestedChannelCount = 8; 00859 return STATUS_SUCCESS; 00860 } 00861 if (*(PLONG)PropertyRequest->Value == KSAUDIO_SPEAKER_5POINT1) { 00862 that->requestedChannelMask = *(PLONG)PropertyRequest->Value; 00863 that->requestedChannelCount = 6; 00864 return STATUS_SUCCESS; 00865 } 00866 if ((*(PLONG)PropertyRequest->Value == KSAUDIO_SPEAKER_QUAD) || (*(PLONG)PropertyRequest->Value == KSAUDIO_SPEAKER_SURROUND)) { 00867 that->requestedChannelMask = *(PLONG)PropertyRequest->Value; 00868 that->requestedChannelCount = 4; 00869 return STATUS_SUCCESS; 00870 } 00871 if (*(PLONG)PropertyRequest->Value == KSAUDIO_SPEAKER_STEREO) { 00872 that->requestedChannelMask = *(PLONG)PropertyRequest->Value; 00873 that->requestedChannelCount = 2; 00874 return STATUS_SUCCESS; 00875 } 00876 } else if (PropertyRequest->Verb & KSPROPERTY_TYPE_BASICSUPPORT) { 00877 PULONG AccessFlags = PULONG(PropertyRequest->Value); 00878 *AccessFlags = KSPROPERTY_TYPE_BASICSUPPORT | KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_SET; 00879 PropertyRequest->ValueSize = sizeof(ULONG); 00880 return STATUS_SUCCESS; 00881 } 00882 } 00883 return STATUS_INVALID_PARAMETER; 00884 } 00885 00887 00888 NTSTATUS CreateMiniportWaveStreamCMI(CMiniportWaveStreamCMI **MiniportWaveStreamCMI, PUNKNOWN pUnknownOuter, POOL_TYPE PoolType) 00889 { 00890 //PAGED_CODE(); 00891 DBGPRINT(("CreateMiniportWaveStreamCMI")); 00892 00893 #ifdef WAVERT 00894 *MiniportWaveStreamCMI = new (PoolType, 'gnaa') CMiniportWaveStreamCMI(NULL); 00895 #else 00896 *MiniportWaveStreamCMI = new (PoolType, 'gnaa') CMiniportWaveStreamCMI(pUnknownOuter); 00897 #endif 00898 if (*MiniportWaveStreamCMI) { 00899 (*MiniportWaveStreamCMI)->AddRef(); 00900 return STATUS_SUCCESS; 00901 } 00902 00903 return STATUS_INSUFFICIENT_RESOURCES; 00904 } 00905 00906 NTSTATUS CMiniportWaveStreamCMI::prepareStream() 00907 { 00908 //PAGED_CODE(); 00909 DBGPRINT(("CMiniportWaveStreamCMI[%p]::prepareStream()", this)); 00910 DBGPRINT(("---streamIndex: %d, channelNumber: %d", streamIndex, channelNumber)); 00911 00912 NTSTATUS ntStatus; 00913 //UInt8 reg; 00914 UInt32 val; 00915 00916 if (state == KSSTATE_RUN) { 00917 return STATUS_INVALID_DEVICE_REQUEST; 00918 } 00919 00920 if (!(Miniport->cm)) { 00921 DBGPRINT(("Miniport not set")); 00922 return STATUS_INVALID_DEVICE_REQUEST; 00923 } 00924 00925 enableSPDIF = ((currentSampleRate == 44100 || currentSampleRate == 48000 || currentSampleRate == 88200 || currentSampleRate == 96000) && 00926 ((currentResolution == 16) || (currentResolution == 24)) && (currentChannelCount == 2)) && 00927 (Miniport->cm->enableSPDIFOut); 00928 00929 ntStatus = setupSPDIFPlayback(enableSPDIF); 00930 if (!NT_SUCCESS(ntStatus)) { 00931 return ntStatus; 00932 } 00933 00934 if (!isCaptureStream) { 00935 ntStatus = setDACChannels(); 00936 if (!NT_SUCCESS(ntStatus)) { 00937 return ntStatus; 00938 } 00939 } 00940 00941 KeWaitForSingleObject(&Miniport->mutex, Executive, KernelMode, false, NULL); 00942 00943 val = channelNumber ? ADC_CH1 : ADC_CH0; 00944 if (isCaptureStream) { 00945 Miniport->cm->regFUNCTRL0 |= val; // 1->Recording 00946 } else { 00947 Miniport->cm->regFUNCTRL0 &= ~val; // 0->Playback 00948 } 00949 Miniport->CMIAdapter->writeUInt32(REG_FUNCTRL0, Miniport->cm->regFUNCTRL0); 00950 00951 //set sampling frequency 00952 val = Miniport->CMIAdapter->readUInt32(REG_FUNCTRL1); 00953 if ((currentSampleRate == 88200) || (currentSampleRate == 44100)) { 00954 if (channelNumber) { 00955 val &= ~SFC_CH1_MASK; 00956 val |= SFC_44K_CH1; 00957 } else { 00958 val &= ~SFC_CH0_MASK; 00959 val |= SFC_44K_CH0; 00960 } 00961 } else if ((currentSampleRate == 96000) || (currentSampleRate == 48000)) { 00962 if (channelNumber) { 00963 val &= ~SFC_CH1_MASK; 00964 val |= SFC_48K_CH1; 00965 } else { 00966 val &= ~SFC_CH0_MASK; 00967 val |= SFC_48K_CH0; 00968 } 00969 } else { 00970 KeReleaseMutex(&Miniport->mutex, FALSE); 00971 return STATUS_INVALID_DEVICE_REQUEST; 00972 } 00973 Miniport->CMIAdapter->writeUInt32(REG_FUNCTRL1, val); 00974 00975 //set resolution 00976 val = Miniport->CMIAdapter->readUInt32(REG_CHFORMAT); 00977 if (channelNumber) { 00978 val |= FORMAT_CH1; 00979 } else { 00980 val |= FORMAT_CH0; 00981 } 00982 Miniport->CMIAdapter->writeUInt32(REG_CHFORMAT, val); 00983 00984 KeReleaseMutex(&Miniport->mutex, false); 00985 00986 return STATUS_SUCCESS; 00987 } 00988 00989 NTSTATUS CMiniportWaveStreamCMI::setDACChannels() 00990 { 00991 //PAGED_CODE(); 00992 DBGPRINT(("CMiniportWaveStreamCMI[%p]::setDACChannels()", this)); 00993 NTSTATUS ntStatus = STATUS_SUCCESS; 00994 00995 if (currentChannelCount > 2) { 00996 if ((WORD) Miniport->cm->maxChannels < currentChannelCount ) { 00997 return STATUS_INVALID_DEVICE_REQUEST; 00998 } 00999 if ((currentResolution != 16) || (currentChannelCount < 2)) { 01000 return STATUS_INVALID_DEVICE_REQUEST; 01001 } 01002 #if OUT_CHANNEL == 0 01003 return STATUS_INVALID_DEVICE_REQUEST; 01004 #endif 01005 KeWaitForSingleObject(&Miniport->mutex, Executive, KernelMode, FALSE, NULL); 01006 Miniport->CMIAdapter->setUInt32Bit(REG_LEGACY, DWORD_MAPPING); 01007 Miniport->CMIAdapter->setUInt32Bit(REG_MISCCTRL, XCHG_DAC); 01008 01009 switch (currentChannelCount) { 01010 case 4: 01011 Miniport->CMIAdapter->setUInt32Bit(REG_CHFORMAT, EN_4CH_CH1); 01012 Miniport->CMIAdapter->clearUInt32Bit(REG_CHFORMAT, EN_5CH_CH1); 01013 Miniport->CMIAdapter->clearUInt32Bit(REG_LEGACY, EN_6CH_CH1); 01014 Miniport->CMIAdapter->clearUInt32Bit(REG_MISCCTRL, EN_CENTER); 01015 break; 01016 case 6: 01017 Miniport->CMIAdapter->clearUInt32Bit(REG_CHFORMAT, EN_4CH_CH1); 01018 Miniport->CMIAdapter->setUInt32Bit(REG_CHFORMAT, EN_5CH_CH1); 01019 Miniport->CMIAdapter->setUInt32Bit(REG_LEGACY, EN_6CH_CH1); 01020 Miniport->CMIAdapter->setUInt32Bit(REG_MISCCTRL, EN_CENTER); 01021 break; 01022 case 8: 01023 if (Miniport->cm->chipVersion == 68) { 01024 Miniport->CMIAdapter->clearUInt32Bit(REG_CHFORMAT, EN_4CH_CH1); 01025 Miniport->CMIAdapter->setUInt32Bit(REG_CHFORMAT, EN_5CH_CH1); 01026 Miniport->CMIAdapter->setUInt32Bit(REG_LEGACY, EN_6CH_CH1); 01027 Miniport->CMIAdapter->setUInt32Bit(REG_MISCCTRL, EN_CENTER); 01028 Miniport->CMIAdapter->setUInt32Bit(REG_MISCCTRL2, EN_8CH_CH1); 01029 break; 01030 } else { 01031 ntStatus = STATUS_INVALID_DEVICE_REQUEST; 01032 } 01033 default: 01034 ntStatus = STATUS_INVALID_DEVICE_REQUEST; 01035 } 01036 KeReleaseMutex(&Miniport->mutex, FALSE); 01037 } else { 01038 if (Miniport->cm->canMultiChannel) { 01039 KeWaitForSingleObject(&Miniport->mutex, Executive, KernelMode, FALSE, NULL); 01040 Miniport->CMIAdapter->clearUInt32Bit(REG_CHFORMAT, EN_5CH_CH1 | EN_4CH_CH1); 01041 Miniport->CMIAdapter->clearUInt32Bit(REG_LEGACY, EN_6CH_CH1 | DWORD_MAPPING); 01042 Miniport->CMIAdapter->clearUInt32Bit(REG_MISCCTRL, EN_CENTER); 01043 Miniport->CMIAdapter->clearUInt32Bit(REG_MISCCTRL, XCHG_DAC); 01044 if (Miniport->cm->chipVersion == 68) { 01045 Miniport->CMIAdapter->clearUInt32Bit(REG_MISCCTRL2, EN_8CH_CH1); 01046 } 01047 KeReleaseMutex(&Miniport->mutex, FALSE); 01048 } 01049 } 01050 return ntStatus; 01051 } 01052 01053 NTSTATUS CMiniportWaveStreamCMI::setupSPDIFPlayback(bool enableSPDIF) 01054 { 01055 //PAGED_CODE(); 01056 DBGPRINT(("CMiniportWaveStreamCMI[%p]::setupSPDIFPlayback(%d)", this, enableSPDIF)); 01057 01058 //NTSTATUS ntStatus; 01059 01060 KeWaitForSingleObject(&Miniport->mutex, Executive, KernelMode, false, NULL); 01061 01062 if (enableSPDIF) { 01063 Miniport->CMIAdapter->setUInt32Bit(REG_LEGACY, EN_SPDIF_OUT); 01064 Miniport->CMIAdapter->setUInt32Bit(REG_FUNCTRL1, SPDO2DAC); 01065 #if OUT_CHANNEL == 0 01066 Miniport->CMIAdapter->setUInt32Bit(REG_FUNCTRL1, SPDF_0); 01067 #else 01068 Miniport->CMIAdapter->setUInt32Bit(REG_FUNCTRL1, SPDF_1); 01069 #endif 01070 setupAC3Passthru(); 01071 01072 if ( (currentSampleRate == 48000) || (currentSampleRate == 96000) ) { 01073 Miniport->CMIAdapter->setUInt32Bit(REG_MISCCTRL, EN_SPDIF_48); 01074 } else { 01075 Miniport->CMIAdapter->clearUInt32Bit(REG_MISCCTRL, EN_SPDIF_48); 01076 } 01077 01078 if (currentSampleRate == 96000) { 01079 #if OUT_CHANNEL == 0 01080 Miniport->CMIAdapter->setUInt32Bit(REG_CHFORMAT, SPD96_CH0); 01081 #else 01082 Miniport->CMIAdapter->setUInt32Bit(REG_CHFORMAT, SPD96_CH1); 01083 #endif 01084 Miniport->CMIAdapter->setUInt32Bit(REG_CHFORMAT, DBLSPDS); 01085 } else if (currentSampleRate == 88200) { 01086 #if OUT_CHANNEL == 0 01087 Miniport->CMIAdapter->setUInt32Bit(REG_CHFORMAT, SPD88_CH0); 01088 #else 01089 Miniport->CMIAdapter->setUInt32Bit(REG_CHFORMAT, SPD88_CH1); 01090 #endif 01091 Miniport->CMIAdapter->setUInt32Bit(REG_CHFORMAT, DBLSPDS); 01092 } else { 01093 #if OUT_CHANNEL == 0 01094 Miniport->CMIAdapter->clearUInt32Bit(REG_CHFORMAT, SPD88_CH0 | SPD96_CH0); 01095 #else 01096 Miniport->CMIAdapter->clearUInt32Bit(REG_CHFORMAT, SPD88_CH1 | SPD96_CH1); 01097 #endif 01098 Miniport->CMIAdapter->clearUInt32Bit(REG_CHFORMAT, DBLSPDS); 01099 } 01100 01101 } else { 01102 Miniport->CMIAdapter->clearUInt32Bit(REG_LEGACY, EN_SPDIF_OUT); 01103 Miniport->CMIAdapter->clearUInt32Bit(REG_FUNCTRL1, SPDO2DAC); 01104 #if OUT_CHANNEL == 0 01105 Miniport->CMIAdapter->clearUInt32Bit(REG_FUNCTRL1, SPDF_0); 01106 #else 01107 Miniport->CMIAdapter->clearUInt32Bit(REG_FUNCTRL1, SPDF_1); 01108 #endif 01109 #if OUT_CHANNEL == 0 01110 Miniport->CMIAdapter->clearUInt32Bit(REG_CHFORMAT, SPD88_CH0 | SPD96_CH0); 01111 #else 01112 Miniport->CMIAdapter->clearUInt32Bit(REG_CHFORMAT, SPD88_CH1 | SPD96_CH1); 01113 #endif 01114 Miniport->CMIAdapter->clearUInt32Bit(REG_CHFORMAT, DBLSPDS); 01115 setupAC3Passthru(); 01116 } 01117 01118 KeReleaseMutex(&Miniport->mutex, false); 01119 return STATUS_SUCCESS; 01120 } 01121 01122 NTSTATUS CMiniportWaveStreamCMI::setupAC3Passthru() 01123 { 01124 //PAGED_CODE(); 01125 DBGPRINT(("CMiniportWaveStreamCMI[%p]::setupAC3Passthru()")); 01126 01127 if (enableAC3Passthru) { 01128 Miniport->CMIAdapter->writeUInt8(REG_MIXER1, Miniport->CMIAdapter->readUInt8(REG_MIXER1) | MUTE_WAVE); 01129 01130 Miniport->CMIAdapter->setUInt32Bit(REG_CHFORMAT, EN_SPDO_AC3_1); 01131 Miniport->CMIAdapter->setUInt32Bit(REG_MISCCTRL, EN_SPDO_AC3_2); 01132 01133 if (Miniport->cm->canAC3HW) { 01134 Miniport->CMIAdapter->setUInt32Bit(REG_CHFORMAT, EN_SPDO_AC3_3); 01135 Miniport->CMIAdapter->clearUInt32Bit(REG_MISCCTRL, SPD32SEL); 01136 if (Miniport->cm->chipVersion >= 39) { 01137 Miniport->CMIAdapter->clearUInt8Bit(REG_MIXER1, EN_SPDI2DAC); 01138 } 01139 } else { 01140 Miniport->CMIAdapter->setUInt32Bit(REG_MISCCTRL, SPD32SEL); 01141 if (Miniport->cm->chipVersion == 33) { 01142 if (currentSampleRate >= 48000) { 01143 #if OUT_CHANNEL == 0 01144 Miniport->CMIAdapter->setUInt32Bit(REG_CHFORMAT, SPD96_CH0); 01145 #else 01146 Miniport->CMIAdapter->setUInt32Bit(REG_CHFORMAT, SPD96_CH1); 01147 #endif 01148 } else { 01149 #if OUT_CHANNEL == 0 01150 Miniport->CMIAdapter->clearUInt32Bit(REG_CHFORMAT, SPD96_CH0); 01151 #else 01152 Miniport->CMIAdapter->clearUInt32Bit(REG_CHFORMAT, SPD96_CH1); 01153 #endif 01154 } 01155 } 01156 } 01157 } else { 01158 Miniport->CMIAdapter->setUInt8Bit(REG_MIXER1, EN_SPDI2DAC); 01159 01160 Miniport->CMIAdapter->clearUInt32Bit(REG_CHFORMAT, EN_SPDO_AC3_1); 01161 Miniport->CMIAdapter->clearUInt32Bit(REG_MISCCTRL, EN_SPDO_AC3_2); 01162 01163 if (Miniport->cm->canAC3HW) { 01164 Miniport->CMIAdapter->clearUInt32Bit(REG_CHFORMAT, EN_SPDO_AC3_3); 01165 if (currentResolution > 16) { 01166 Miniport->CMIAdapter->setUInt32Bit(REG_MISCCTRL, SPD32SEL); 01167 Miniport->CMIAdapter->setUInt32Bit(REG_CHFORMAT, SPD24SEL); 01168 } else { 01169 Miniport->CMIAdapter->clearUInt32Bit(REG_MISCCTRL, SPD32SEL); 01170 Miniport->CMIAdapter->clearUInt32Bit(REG_CHFORMAT, SPD24SEL); 01171 } 01172 } else { 01173 Miniport->CMIAdapter->clearUInt32Bit(REG_MISCCTRL, SPD32SEL); 01174 #if OUT_CHANNEL == 0 01175 Miniport->CMIAdapter->clearUInt32Bit(REG_CHFORMAT, SPD96_CH0); 01176 #else 01177 Miniport->CMIAdapter->clearUInt32Bit(REG_CHFORMAT, SPD96_CH1); 01178 #endif 01179 } 01180 } 01181 return STATUS_SUCCESS; 01182 } 01183 01184 CMiniportWaveStreamCMI::~CMiniportWaveStreamCMI(void) 01185 { 01186 //PAGED_CODE(); 01187 01188 DBGPRINT(("CMiniportWaveStreamCMI[%p]::~CMiniportWaveStreamCMI", this)); 01189 01190 #ifdef WAVERT 01191 if (Port) { 01192 Port->Release(); 01193 Port = NULL; 01194 } 01195 #else 01196 if (DMAChannel) { 01197 DMAChannel->Release(); 01198 DMAChannel = NULL; 01199 } 01200 01201 if (ServiceGroup) { 01202 ServiceGroup->Release(); 01203 ServiceGroup = NULL; 01204 } 01205 #endif 01206 01207 Miniport->isStreamRunning[streamIndex] = false; 01208 01209 if ((streamIndex == AC3_OUT_STREAM) && Miniport->isStreamRunning[PCM_OUT_STREAM]) { 01210 KSSTATE temp = Miniport->stream[PCM_OUT_STREAM]->state; 01211 Miniport->stream[PCM_OUT_STREAM]->state = KSSTATE_STOP; 01212 Miniport->stream[PCM_OUT_STREAM]->prepareStream(); 01213 Miniport->stream[PCM_OUT_STREAM]->SetState(KSSTATE_ACQUIRE); 01214 Miniport->stream[PCM_OUT_STREAM]->state = temp; 01215 Miniport->stream[PCM_OUT_STREAM]->SetState(KSSTATE_RUN_AC3); 01216 } 01217 01218 if (Miniport) { 01219 Miniport->Release(); 01220 Miniport = NULL; 01221 } 01222 } 01223 01224 STDMETHODIMP CMiniportWaveStreamCMI::QueryInterface(REFIID Interface, PVOID *Object) 01225 { 01226 //PAGED_CODE(); 01227 //ASSERT(Object); 01228 DBGPRINT(("CMiniportWaveStreamCMI[%p]::NonDelegatingQueryInterface(%p, %p)", this, Interface, Object)); 01229 01230 if (IsEqualGUIDAligned(Interface,IID_IUnknown)) { 01231 *Object = PVOID(PUNKNOWN(PMINIPORTWAVECYCLICSTREAM(this))); 01232 #ifdef WAVERT 01233 } else if (IsEqualGUIDAligned(Interface,IID_IMiniportWaveRTStream)) { 01234 *Object = PVOID(PMINIPORTWAVERTSTREAM(this)); 01235 #else 01236 } else if (IsEqualGUIDAligned(Interface,IID_IMiniportWaveCyclicStream)) { 01237 *Object = PVOID(PMINIPORTWAVECYCLICSTREAM(this)); 01238 #endif 01239 } else if (IsEqualGUIDAligned (Interface, IID_IDrmAudioStream)) { 01240 *Object = (PVOID)(PDRMAUDIOSTREAM(this)); 01241 } else { 01242 *Object = NULL; 01243 } 01244 01245 if (*Object) { 01246 PUNKNOWN(*Object)->AddRef(); 01247 return STATUS_SUCCESS; 01248 } 01249 01250 return STATUS_INVALID_PARAMETER; 01251 } 01252 01253 #ifdef WAVERT 01254 NTSTATUS CMiniportWaveStreamCMI::Init(CMiniportWaveCMI* Miniport_, UInt32 streamIndex_, bool isCaptureStream_, PKSDATAFORMAT DataFormat, PPORTWAVERTSTREAM Port_) 01255 #else 01256 NTSTATUS CMiniportWaveStreamCMI::Init(CMiniportWaveCMI* Miniport_, UInt32 streamIndex_, bool isCaptureStream_, PKSDATAFORMAT DataFormat, PDMACHANNEL DMAChannel_, PSERVICEGROUP* OutServiceGroup) 01257 #endif 01258 { 01259 //PAGED_CODE(); 01260 //ASSERT(Miniport_); 01261 //ASSERT(DataFormat); 01262 01263 NTSTATUS ntStatus; 01264 01265 #ifdef WAVERT 01266 //ASSERT(Port_); 01267 DBGPRINT(("CMiniportWaveStreamCMI[%p]::Init(%p, %d, %d, %p, %p)", this, Miniport_, streamIndex_, isCaptureStream_, DataFormat, Port_)); 01268 Port = Port_; 01269 Port->AddRef(); 01270 #else 01271 DBGPRINT(("CMiniportWaveStreamCMI[%p]::Init(%p, %d, %d, %p, %p, %p)", this, Miniport_, streamIndex_, isCaptureStream_, DataFormat, DMAChannel_, OutServiceGroup)); 01272 DMAChannel = DMAChannel_; 01273 DMAChannel->AddRef(); 01274 #endif 01275 01276 Miniport = Miniport_; 01277 Miniport->AddRef(); 01278 01279 streamIndex = streamIndex_; 01280 isCaptureStream = isCaptureStream_; 01281 state = KSSTATE_STOP; 01282 01283 if ( (streamIndex == PCM_OUT_STREAM) || (streamIndex == AC3_OUT_STREAM) ) { 01284 channelNumber = OUT_CHANNEL; 01285 } else { 01286 channelNumber = IN_CHANNEL; 01287 } 01288 01289 #ifndef WAVERT 01290 ntStatus = PcNewServiceGroup(&ServiceGroup,NULL); 01291 if (!NT_SUCCESS(ntStatus)) { 01292 DBGPRINT(("PcNewServiceGroup() or NewMasterDmaChannel() failed")); 01293 return ntStatus; 01294 } 01295 *OutServiceGroup = ServiceGroup; 01296 ServiceGroup->AddRef(); 01297 #endif 01298 01299 ntStatus = SetFormat(DataFormat); 01300 if (!NT_SUCCESS(ntStatus)) { 01301 DBGPRINT(("SetFormat() failed")); 01302 return ntStatus; 01303 } 01304 01305 Miniport->isStreamRunning[streamIndex] = true; 01306 01307 return ntStatus; 01308 } 01309 01310 NTSTATUS CMiniportWaveStreamCMI::SetFormat(PKSDATAFORMAT Format) 01311 { 01312 //PAGED_CODE(); 01313 DBGPRINT(("CMiniportWaveStreamCMI[%p]::SetFormat(%p)", this, Format)); 01314 PWAVEFORMATEX waveFormat = PWAVEFORMATEX(Format + 1); 01315 NTSTATUS ntStatus = Miniport->validateFormat(Format, -1, isCaptureStream); 01316 if (!NT_SUCCESS(ntStatus)) { 01317 return ntStatus; 01318 } 01319 // the DAC and ADC can only run at the same sample rate simultaneously 01320 if ((streamIndex == PCM_IN_STREAM) && Miniport->isStreamRunning[PCM_OUT_STREAM]) { 01321 if (waveFormat->nSamplesPerSec != Miniport->stream[PCM_OUT_STREAM]->currentSampleRate) { 01322 return STATUS_UNSUCCESSFUL; 01323 } 01324 } 01325 if ((streamIndex == PCM_IN_STREAM) && Miniport->isStreamRunning[AC3_OUT_STREAM]) { 01326 if (waveFormat->nSamplesPerSec != Miniport->stream[AC3_OUT_STREAM]->currentSampleRate) { 01327 return STATUS_UNSUCCESSFUL; 01328 } 01329 } 01330 if ((streamIndex == PCM_OUT_STREAM) && Miniport->isStreamRunning[PCM_IN_STREAM]) { 01331 if (waveFormat->nSamplesPerSec != Miniport->stream[PCM_IN_STREAM]->currentSampleRate) { 01332 return STATUS_UNSUCCESSFUL; 01333 } 01334 } 01335 if ((streamIndex == PCM_OUT_STREAM) && Miniport->isStreamRunning[AC3_OUT_STREAM]) { 01336 return STATUS_UNSUCCESSFUL; 01337 } 01338 01339 KeWaitForSingleObject(&Miniport->mutex, Executive, KernelMode, false, NULL); 01340 currentSampleRate = waveFormat->nSamplesPerSec; 01341 currentChannelCount = waveFormat->nChannels; 01342 currentResolution = waveFormat->wBitsPerSample; 01343 enableAC3Passthru = (WAVE_FORMAT_DOLBY_AC3_SPDIF == EXTRACT_WAVEFORMATEX_ID(&Format->SubFormat)); 01344 KeReleaseMutex(&Miniport->mutex, false); 01345 ntStatus = prepareStream(); 01346 01347 return ntStatus; 01348 } 01349 01350 // DRM crap - we're supposed to disable every digital interface here 01351 STDMETHODIMP_(NTSTATUS) CMiniportWaveStreamCMI::SetContentId(ULONG contentId, PCDRMRIGHTS drmRights) 01352 { 01353 //PAGED_CODE(); 01354 DBGPRINT(("CMiniportWaveStreamCMI[%p]::SetContentId(%d, %p)", this, contentId, drmRights)); 01355 01356 return STATUS_SUCCESS; 01357 } 01358 01359 #ifdef WAVERT 01360 01361 STDMETHODIMP_(NTSTATUS) CMiniportWaveStreamCMI::AllocateAudioBuffer(ULONG size, PMDL *userModeBuffer, ULONG *bufferSize, ULONG *bufferOffset, MEMORY_CACHING_TYPE *cacheType) 01362 { 01363 //PAGED_CODE(); 01364 01365 PHYSICAL_ADDRESS low; 01366 PHYSICAL_ADDRESS high; 01367 DBGPRINT(("CMiniportWaveStreamCMI[%p]::AllocateAudioBuffer(%x, %p, %p, %p, %p)", this, size, userModeBuffer, bufferSize, bufferOffset, cacheType)); 01368 01369 if (size <= size % (currentChannelCount * 2)) { 01370 return STATUS_UNSUCCESSFUL; 01371 } 01372 size -= size % (currentChannelCount * 2); 01373 01374 if (size == 0) { 01375 return STATUS_UNSUCCESSFUL; 01376 } 01377 01378 low.QuadPart = 0; 01379 high.HighPart = 0, high.LowPart = MAXULONG; 01380 01381 audioBufferMDL = Port->AllocateContiguousPagesForMdl(low, high, size); 01382 01383 if (!audioBufferMDL) { 01384 DBGPRINT(("AllocateContiguousPagesForMdl() failed")); 01385 return STATUS_UNSUCCESSFUL; 01386 } 01387 01388 dmaAddress = Port->GetPhysicalPageAddress(audioBufferMDL, 0).LowPart; 01389 dmaMemorySize = size; 01390 01391 *userModeBuffer = audioBufferMDL; 01392 *bufferSize = size; 01393 *bufferOffset = 0; 01394 *cacheType = MmCached; 01395 01396 return STATUS_SUCCESS; 01397 } 01398 01399 01400 STDMETHODIMP_(VOID) CMiniportWaveStreamCMI::FreeAudioBuffer(PMDL Mdl, ULONG Size) 01401 { 01402 //PAGED_CODE(); 01403 DBGPRINT(("CMiniportWaveStreamCMI[%p]::FreeAudioBuffer(%p, %x)", this, Mdl, Size)); 01404 01405 Port->FreePagesFromMdl(Mdl); 01406 audioBufferMDL = NULL; 01407 dmaAddress = 0; 01408 dmaMemorySize = 0; 01409 } 01410 01411 STDMETHODIMP_(void) CMiniportWaveStreamCMI::GetHWLatency(PKSRTAUDIO_HWLATENCY hwLatency) { 01412 //PAGED_CODE(); 01413 DBGPRINT(("CMiniportWaveStreamCMI[%p]::GetHWLatency(%p)", this, hwLatency)); 01414 hwLatency->FifoSize = 32; 01415 hwLatency->ChipsetDelay = 0; 01416 hwLatency->CodecDelay = 4; 01417 } 01418 01419 STDMETHODIMP_(NTSTATUS) CMiniportWaveStreamCMI::GetPositionRegister(PKSRTAUDIO_HWREGISTER hwRegister) 01420 { 01421 //PAGED_CODE(); 01422 DBGPRINT(("CMiniportWaveStreamCMI[%p]::GetPositionRegister(%p)", this, hwRegister)); 01423 01424 return STATUS_UNSUCCESSFUL; 01425 } 01426 01427 STDMETHODIMP_(NTSTATUS) CMiniportWaveStreamCMI::GetClockRegister(PKSRTAUDIO_HWREGISTER hwRegister) 01428 { 01429 //PAGED_CODE(); 01430 DBGPRINT(("CMiniportWaveStreamCMI[%p]::GetClockRegister(%p)", this, hwRegister)); 01431 01432 return STATUS_UNSUCCESSFUL; 01433 } 01434 01435 #endif // WAVERT 01436 01437 /* 01438 ** non-paged code below 01439 */ 01440 #ifdef _MSC_VER 01441 #pragma code_seg() /* warning - ignored by GCC compiler */ 01442 #endif 01443 01444 STDMETHODIMP CMiniportWaveStreamCMI::SetState(KSSTATE NewState) 01445 { 01446 DBGPRINT(("CMiniportWaveStreamCMI[%p]::SetState(%d)", this, NewState)); 01447 01448 UInt32 inthld, chen, reset, pause; 01449 UInt8 reg; 01450 01451 inthld = EN_CH0_INT << channelNumber; 01452 chen = EN_CH0 << channelNumber; 01453 reset = RST_CH0 << channelNumber; 01454 pause = PAUSE_CH0 << channelNumber; 01455 01456 NTSTATUS ntStatus = STATUS_SUCCESS; 01457 01458 if ((streamIndex == PCM_OUT_STREAM) && Miniport->isStreamRunning[AC3_OUT_STREAM]) { 01459 return STATUS_INVALID_PARAMETER; 01460 } 01461 01462 if (NewState == KSSTATE_RUN_AC3) { 01463 NewState = state; 01464 state = KSSTATE_STOP; 01465 } 01466 01467 // STOP -> ACQUIRE -> PAUSE -> PLAY -> PAUSE -> ACQUIRE -> STOP 01468 if (state != NewState) { 01469 switch ((UINT) NewState) { 01470 // LN: The cast on NewState is to satisfy the compiler about 01471 // KSSTATE_STOP_AC3, which is not in the original enum KSSTATE. 01472 case KSSTATE_ACQUIRE: 01473 DBGPRINT(("---KSSTATE_ACQUIRE: previous state: %d", state)); 01474 if (state == KSSTATE_PAUSE) { 01475 break; 01476 } 01477 01478 #ifdef WAVERT 01479 if ((dmaMemorySize == 0) || (dmaAddress == 0)) { 01480 return STATUS_UNSUCCESSFUL; 01481 } 01482 dmaSize = (dmaMemorySize / (2 * (currentResolution >> 3)) ); 01483 periodSize = dmaSize; 01484 DBGPRINT(("---dmaAddress: %x, dmaMemorySize: %x, dmaSize: %x", dmaAddress, dmaMemorySize, dmaSize)); 01485 #else 01486 if (currentResolution == 24) { 01487 dmaSize = (DMAChannel->BufferSize() / (2 * (24 >> 3)) ); 01488 } else { 01489 dmaSize = (DMAChannel->BufferSize() / (2 * (currentResolution >> 3)) ); 01490 } 01491 #endif 01492 DBGPRINT(("---streamIndex: %d, channelNumber: %d", streamIndex, channelNumber)); 01493 DBGPRINT(("---SampleRate: %d, Resolution: %d, Channels: %d", currentSampleRate, currentResolution, currentChannelCount)); 01494 01495 if (periodSize > dmaSize) { 01496 periodSize = dmaSize; 01497 } 01498 01499 // set address of the DMA buffer 01500 KeWaitForSingleObject(&Miniport->mutex, Executive, KernelMode, FALSE, NULL); 01501 reg = channelNumber ? REG_CH1_FRAME1 : REG_CH0_FRAME1; 01502 #ifdef WAVERT 01503 Miniport->CMIAdapter->writeUInt32(reg, dmaAddress); 01504 #else 01505 Miniport->CMIAdapter->writeUInt32(reg, DMAChannel->PhysicalAddress().u.LowPart); 01506 #endif 01507 // count of samples 01508 reg = channelNumber ? REG_CH1_FRAME2 : REG_CH0_FRAME2; 01509 Miniport->CMIAdapter->writeUInt16(reg, dmaSize-1); 01510 Miniport->CMIAdapter->writeUInt16(reg + 2, periodSize-1); 01511 DBGPRINT(("---DMA Size: 0x%04X, Period Size: 0x%04X, enableSPDIFIn: %d", dmaSize, periodSize, Miniport->cm->enableSPDIFIn)); 01512 if (isCaptureStream && (Miniport->cm->enableSPDIFIn)) { 01513 #if OUT_CHANNEL==0 01514 Miniport->CMIAdapter->setUInt32Bit(REG_FUNCTRL1, SPDF_1); 01515 #else 01516 Miniport->CMIAdapter->setUInt32Bit(REG_FUNCTRL1, SPDF_0); 01517 #endif 01518 } 01519 KeReleaseMutex(&Miniport->mutex, false); 01520 break; 01521 01522 case KSSTATE_PAUSE: 01523 DBGPRINT(("---KSSTATE_PAUSE: previous state: %d", state)); 01524 if (state == KSSTATE_RUN) { 01525 KeWaitForSingleObject(&Miniport->mutex, Executive, KernelMode, false, NULL); 01526 Miniport->cm->regFUNCTRL0 |= pause; 01527 Miniport->CMIAdapter->writeUInt32(REG_FUNCTRL0, Miniport->cm->regFUNCTRL0); 01528 KeReleaseMutex(&Miniport->mutex, FALSE); 01529 } 01530 if (state == KSSTATE_STOP) { 01531 KeWaitForSingleObject(&Miniport->mutex, Executive, KernelMode, false, NULL); 01532 Miniport->cm->regFUNCTRL0 &= ~pause; 01533 Miniport->CMIAdapter->writeUInt32(REG_FUNCTRL0, Miniport->cm->regFUNCTRL0); 01534 KeReleaseMutex(&Miniport->mutex, false); 01535 } 01536 break; 01537 01538 case KSSTATE_RUN: 01539 DBGPRINT(("---KSSTATE_RUN: previous state: %d", state)); 01540 01541 KeWaitForSingleObject(&Miniport->mutex, Executive, KernelMode, FALSE, NULL); 01542 // set interrupt 01543 Miniport->CMIAdapter->setUInt32Bit(REG_INTHLDCLR, inthld); 01544 Miniport->cm->regFUNCTRL0 &= ~pause; 01545 Miniport->cm->regFUNCTRL0 |= chen; 01546 // and enable the channel 01547 Miniport->CMIAdapter->writeUInt32(REG_FUNCTRL0, Miniport->cm->regFUNCTRL0); 01548 01549 DBGPRINT(("---FUNCTRL0: 0x%08X", Miniport->cm->regFUNCTRL0)); 01550 DBGPRINT(("---FUNCTRL1: 0x%08X", Miniport->CMIAdapter->readUInt32(REG_FUNCTRL1))); 01551 DBGPRINT(("---CHFORMAT: 0x%08X", Miniport->CMIAdapter->readUInt32(REG_CHFORMAT))); 01552 DBGPRINT(("---LEGACYCTRL: 0x%08X", Miniport->CMIAdapter->readUInt32(REG_LEGACY))); 01553 DBGPRINT(("---MISCCTRL: 0x%08X", Miniport->CMIAdapter->readUInt32(REG_MISCCTRL))); 01554 DBGPRINT(("---MIX1: 0x%02X", Miniport->CMIAdapter->readUInt8(REG_MIXER1))); 01555 DBGPRINT(("---MIX2: 0x%02X", Miniport->CMIAdapter->readUInt8(REG_MIXER2))); 01556 DBGPRINT(("---MIX3: 0x%02X", Miniport->CMIAdapter->readUInt8(REG_MIXER3))); 01557 01558 KeReleaseMutex(&Miniport->mutex, false); 01559 break; 01560 01561 case KSSTATE_STOP_AC3: 01562 case KSSTATE_STOP: 01563 DBGPRINT(("---KSSTATE_STOP: previous state: %d", state)); 01564 KeWaitForSingleObject(&Miniport->mutex, Executive, KernelMode, FALSE, NULL); 01565 // clear interrupt 01566 Miniport->CMIAdapter->clearUInt32Bit(REG_INTHLDCLR, inthld); 01567 Miniport->cm->regFUNCTRL0 &= ~chen; 01568 // reset 01569 Miniport->CMIAdapter->writeUInt32(REG_FUNCTRL0, Miniport->cm->regFUNCTRL0 | reset); 01570 Miniport->CMIAdapter->writeUInt32(REG_FUNCTRL0, Miniport->cm->regFUNCTRL0 & ~reset); 01571 if (isCaptureStream && (Miniport->cm->enableSPDIFIn)) { 01572 #if OUT_CHANNEL==0 01573 Miniport->CMIAdapter->clearUInt32Bit(REG_FUNCTRL1, SPDF_1); 01574 #else 01575 Miniport->CMIAdapter->clearUInt32Bit(REG_FUNCTRL1, SPDF_0); 01576 #endif 01577 } 01578 KeReleaseMutex(&Miniport->mutex, FALSE); 01579 break; 01580 } 01581 if (NewState != KSSTATE_STOP_AC3) { 01582 state = NewState; 01583 } 01584 } 01585 return ntStatus; 01586 } 01587 01588 #ifdef WAVERT 01589 STDMETHODIMP CMiniportWaveStreamCMI::GetPosition(PKSAUDIO_POSITION Position) 01590 { 01591 //ASSERT(Position); 01592 01593 UInt32 reg; 01594 01595 if ((state == KSSTATE_RUN) && (dmaAddress)) { 01596 reg = (channelNumber) ? REG_CH1_FRAME1 : REG_CH0_FRAME1; 01597 Position->PlayOffset = Miniport->CMIAdapter->readUInt32(reg) - dmaAddress; 01598 Position->WriteOffset = Position->PlayOffset + currentChannelCount * 2 * 8; 01599 } else { 01600 Position->PlayOffset = 0; 01601 Position->WriteOffset = 0; 01602 } 01603 01604 return STATUS_SUCCESS; 01605 } 01606 01607 #else //WaveCyclic 01608 STDMETHODIMP CMiniportWaveStreamCMI::GetPosition(PULONG Position) 01609 { 01610 //ASSERT(Position); 01611 01612 UInt32 reg; 01613 01614 if ((DMAChannel) && (state == KSSTATE_RUN)) { 01615 #if 0 01616 // this implementation messes with SPDIF-in recording 01617 reg = (channelNumber) ? REG_CH1_FRAME2 : REG_CH0_FRAME2; 01618 *Position = dmaSize - (Miniport->CMIAdapter->readUInt16(reg)-1); 01619 *Position *= 2 * (currentResolution >> 3); 01620 #else 01621 reg = (channelNumber) ? REG_CH1_FRAME1 : REG_CH0_FRAME1; 01622 *Position = Miniport->CMIAdapter->readUInt32(reg); 01623 if (*Position > DMAChannel->PhysicalAddress().u.LowPart) { 01624 *Position -= DMAChannel->PhysicalAddress().u.LowPart; 01625 } else { 01626 *Position = 0; 01627 } 01628 #endif 01629 } else { 01630 *Position = 0; 01631 } 01632 01633 return STATUS_SUCCESS; 01634 } 01635 01636 STDMETHODIMP_(ULONG) CMiniportWaveStreamCMI::SetNotificationFreq(ULONG Interval, PULONG FramingSize) 01637 { 01638 Miniport->notificationInterval = Interval; 01639 01640 if (state == KSSTATE_RUN) { 01641 return 0; 01642 } 01643 periodSize = Interval * currentSampleRate/1000; 01644 *FramingSize = periodSize*currentChannelCount*(currentResolution >> 3); 01645 01646 KeWaitForSingleObject(&Miniport->mutex, Executive, KernelMode, FALSE, NULL); 01647 Miniport->CMIAdapter->writeUInt16((channelNumber ? REG_CH1_FRAME2 : REG_CH0_FRAME2) + 2, periodSize-1); 01648 KeReleaseMutex(&Miniport->mutex, FALSE); 01649 01650 DBGPRINT(("periodSize: %x, FramingSize: %x", periodSize, *FramingSize)); 01651 return Interval; 01652 } 01653 01654 STDMETHODIMP CMiniportWaveStreamCMI::NormalizePhysicalPosition(OUT PLONGLONG PhysicalPosition) 01655 { 01656 *PhysicalPosition = (_100NS_UNITS_PER_SECOND / currentChannelCount * (currentResolution >> 3) * *PhysicalPosition) / currentSampleRate; 01657 return STATUS_SUCCESS; 01658 } 01659 01660 01661 STDMETHODIMP_(void) CMiniportWaveStreamCMI::Silence(PVOID Buffer, ULONG ByteCount) 01662 { 01663 RtlFillMemory(Buffer, ByteCount, 0x00); 01664 } 01665 01666 #endif //WAVERT 01667 01668 STDMETHODIMP_(void) CMiniportWaveCMI::ServiceWaveISR(UInt32 streamIndex) 01669 { 01670 #ifndef WAVERT 01671 if ((streamIndex == PCM_OUT_STREAM) && isStreamRunning[AC3_OUT_STREAM]) { 01672 streamIndex = AC3_OUT_STREAM; 01673 } 01674 if (Port && stream[streamIndex]->ServiceGroup) { 01675 Port->Notify(stream[streamIndex]->ServiceGroup); 01676 } 01677 #endif 01678 } Generated on Sat May 26 2012 04:27:14 for ReactOS by
1.7.6.1
|