ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

minwave.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 doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.