1 /*
2 Copyright (c) 2006-2008 dogbert <dogber1@gmail.com>
3 All rights reserved.
4
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions
7 are met:
8 1. Redistributions of source code must retain the above copyright
9 notice, this list of conditions and the following disclaimer.
10 2. Redistributions in binary form must reproduce the above copyright
11 notice, this list of conditions and the following disclaimer in the
12 documentation and/or other materials provided with the distribution.
13 3. The name of the author may not be used to endorse or promote products
14 derived from this software without specific prior written permission.
15
16 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28 #include "minwave.hpp"
29 #include "minwavetables.hpp"
30 #include "ntddk.h"
31
32 #ifdef _MSC_VER
33 #pragma code_seg("PAGE")
34 #endif
35
CreateMiniportWaveCMI(PUNKNOWN * Unknown,REFCLSID,PUNKNOWN UnknownOuter,POOL_TYPE PoolType)36 NTSTATUS NTAPI CreateMiniportWaveCMI(PUNKNOWN *Unknown, REFCLSID, PUNKNOWN UnknownOuter, POOL_TYPE PoolType)
37 {
38 PAGED_CODE();
39 ASSERT(Unknown);
40 #ifdef WAVERT
41 STD_CREATE_BODY_(CMiniportWaveCMI,Unknown,UnknownOuter,PoolType,PMINIPORTWAVERT);
42 #else
43 STD_CREATE_BODY_(CMiniportWaveCMI,Unknown,UnknownOuter,PoolType,PMINIPORTWAVECYCLIC);
44 #endif
45 }
46
processResources(PRESOURCELIST resourceList)47 NTSTATUS CMiniportWaveCMI::processResources(PRESOURCELIST resourceList)
48 {
49 PAGED_CODE();
50 ASSERT (resourceList);
51 DBGPRINT(("CMiniportWaveCMI[%p]::ProcessResources(%p)", this, resourceList));
52
53 if (resourceList->NumberOfInterrupts() < 1) {
54 DBGPRINT(("Unknown configuration for wave miniport"));
55 return STATUS_DEVICE_CONFIGURATION_ERROR;
56 }
57 return STATUS_SUCCESS;
58 }
59
60 #ifndef WAVERT
newDMAChannel(PDMACHANNEL * dmaChannel,UInt32 bufferLength)61 NTSTATUS CMiniportWaveCMI::newDMAChannel(PDMACHANNEL *dmaChannel, UInt32 bufferLength)
62 {
63 PAGED_CODE();
64 ASSERT(dmaChannel);
65 DBGPRINT(("CMiniportWaveCMI[%p]::newDMAChannel(%p)", this, dmaChannel));
66
67 NTSTATUS ntStatus;
68
69 ntStatus = Port->NewMasterDmaChannel(dmaChannel, NULL, NULL, bufferLength, TRUE, FALSE, (DMA_WIDTH)(-1), (DMA_SPEED)(-1));
70 if (NT_SUCCESS(ntStatus)) {
71 ULONG lDMABufferLength = bufferLength;
72 do {
73 ntStatus = (*dmaChannel)->AllocateBuffer(lDMABufferLength, NULL);
74 lDMABufferLength >>= 1;
75 } while (!NT_SUCCESS(ntStatus) && (lDMABufferLength > (PAGE_SIZE / 2)));
76 }
77 return ntStatus;
78 }
79 #endif
80
81 //generic crap
NonDelegatingQueryInterface(REFIID Interface,PVOID * Object)82 STDMETHODIMP CMiniportWaveCMI::NonDelegatingQueryInterface(REFIID Interface, PVOID *Object)
83 {
84 PAGED_CODE();
85 ASSERT(Object);
86 DBGPRINT(("CMiniportWaveCMI[%p]::NonDelegatingQueryInterface", this));
87
88 if (IsEqualGUIDAligned(Interface,IID_IUnknown)) {
89 #ifdef WAVERT
90 *Object = PVOID(PUNKNOWN(PMINIPORTWAVERT(this)));
91 #else
92 *Object = PVOID(PUNKNOWN(PMINIPORTWAVECYCLIC(this)));
93 #endif
94 } else if (IsEqualGUIDAligned(Interface,IID_IMiniport)) {
95 *Object = PVOID(PMINIPORT(this));
96 #ifdef WAVERT
97 } else if (IsEqualGUIDAligned(Interface,IID_IMiniportWaveRT)) {
98 *Object = PVOID(PMINIPORTWAVERT(this));
99 #else
100 } else if (IsEqualGUIDAligned(Interface,IID_IMiniportWaveCyclic)) {
101 *Object = PVOID(PMINIPORTWAVECYCLIC(this));
102 #endif
103 } else {
104 *Object = NULL;
105 }
106
107 if (*Object) {
108 // We reference the interface for the caller.
109 PUNKNOWN(*Object)->AddRef();
110 return STATUS_SUCCESS;
111 }
112
113 return STATUS_INVALID_PARAMETER;
114 }
115
~CMiniportWaveCMI(void)116 CMiniportWaveCMI::~CMiniportWaveCMI(void)
117 {
118 PAGED_CODE();
119 DBGPRINT(("CMiniportWaveCMI[%p]::~CMiniportWaveCMI", this));
120
121 storeChannelConfigToRegistry(); //or not. during system shutdown, this doesn't seem to work.
122
123 if (CMIAdapter) {
124 CMIAdapter->Release();
125 CMIAdapter = NULL;
126 }
127
128 for (int i=0;i<3;i++) {
129 #ifndef WAVERT
130 if (DMAChannel[i]) {
131 DMAChannel[i]->Release();
132 DMAChannel[i] = NULL;
133 }
134 #endif
135 if (isStreamRunning[i]) {
136 isStreamRunning[i] = false;
137 stream[i]->Release();
138 stream[i] = NULL;
139 }
140 }
141
142 if (Port) {
143 Port->Release();
144 Port = NULL;
145 }
146 }
147
148 #ifdef WAVERT
Init(PUNKNOWN UnknownAdapter,PRESOURCELIST ResourceList,PPORTWAVERT Port_)149 STDMETHODIMP CMiniportWaveCMI::Init(PUNKNOWN UnknownAdapter, PRESOURCELIST ResourceList, PPORTWAVERT Port_)
150 #else
151 STDMETHODIMP CMiniportWaveCMI::Init(PUNKNOWN UnknownAdapter, PRESOURCELIST ResourceList, PPORTWAVECYCLIC Port_)
152 #endif
153 {
154 PAGED_CODE();
155
156 ASSERT(UnknownAdapter);
157 ASSERT(ResourceList);
158 ASSERT(Port_);
159
160 DBGPRINT(("CMiniportWaveCMI[%p]::Init(%p, %p, %p)", this, UnknownAdapter, ResourceList, Port_));
161
162 Port = Port_;
163 Port->AddRef();
164
165 NTSTATUS ntStatus = UnknownAdapter->QueryInterface(IID_ICMIAdapter, (PVOID *) &CMIAdapter);
166 if (!NT_SUCCESS(ntStatus)) {
167 DBGPRINT(("QueryInterface(CMIAdapter) failed"));
168 return ntStatus;
169 }
170
171 //check for Vista, set the AC3 stuff accordingly
172 if (IoIsWdmVersionAvailable(0x06,0x00)) {
173 WavePinDataRangesAC3Stream[1].MinimumSampleFrequency = MIN_SAMPLE_RATE;
174 WavePinDataRangesAC3Stream[1].MaximumSampleFrequency = MAX_SAMPLE_RATE;
175 WavePinDataRangesAC3Stream[1].DataRange.SubFormat = KSDATAFORMAT_SUBTYPE_PCM;
176 WavePinDataRangesAC3Stream[1].DataRange.Specifier = KSDATAFORMAT_SPECIFIER_WAVEFORMATEX;
177 }
178
179 cm = CMIAdapter->getCMI8738Info();
180 cm->regFUNCTRL0 = 0;
181 cm->WaveMiniport = this;
182
183 loadChannelConfigFromRegistry();
184
185 for (int i=0;i<3;i++)
186 {
187 isStreamRunning[i] = false;
188
189 #ifndef WAVERT
190 ntStatus = newDMAChannel(&DMAChannel[i], MAXLEN_DMA_BUFFER);
191 if (!NT_SUCCESS(ntStatus)) {
192 DBGPRINT(("NewDmaChannel() failed"));
193 return ntStatus;
194 }
195 #endif
196 }
197
198 KeInitializeMutex(&mutex, 1);
199
200 return processResources(ResourceList);
201 }
202
203 #ifdef WAVERT
STDMETHODIMP_(NTSTATUS)204 STDMETHODIMP_(NTSTATUS) CMiniportWaveCMI::GetDeviceDescription(PDEVICE_DESCRIPTION OutDeviceDescriptor)
205 {
206 PAGED_CODE();
207 ASSERT(OutDeviceDescriptor);
208 DBGPRINT(("CMiniportWaveCMI[%p]::GetDeviceDescription(%p)", this, OutDeviceDescriptor));
209
210 RtlZeroMemory(OutDeviceDescriptor, sizeof(DEVICE_DESCRIPTION));
211 OutDeviceDescriptor->ScatterGather = false;
212 OutDeviceDescriptor->Master = true;
213 OutDeviceDescriptor->Dma32BitAddresses = true;
214 OutDeviceDescriptor->InterfaceType = PCIBus;
215 OutDeviceDescriptor->MaximumLength = MAXLEN_DMA_BUFFER-2;
216
217 return STATUS_SUCCESS;
218 }
219 #endif
220
GetDescription(PPCFILTER_DESCRIPTOR * OutFilterDescriptor)221 STDMETHODIMP CMiniportWaveCMI::GetDescription(PPCFILTER_DESCRIPTOR *OutFilterDescriptor)
222 {
223 PAGED_CODE();
224 ASSERT(OutFilterDescriptor);
225 DBGPRINT(("CMiniportWaveCMI[%p]::GetDescription(%p)", this, OutFilterDescriptor));
226
227 *OutFilterDescriptor = &WaveMiniportFilterDescriptor;
228
229 return STATUS_SUCCESS;
230 }
231
loadChannelConfigFromRegistry()232 NTSTATUS CMiniportWaveCMI::loadChannelConfigFromRegistry()
233 {
234 PAGED_CODE();
235 PREGISTRYKEY DriverKey;
236 PREGISTRYKEY SettingsKey;
237 UNICODE_STRING KeyName;
238 DWORD ResultLength;
239 PVOID KeyInfo;
240
241 DBGPRINT(("CMiniportWaveCMI::loadChannelConfigFromRegistry()"));
242
243 if ((!CMIAdapter) || (!(CMIAdapter->getDeviceObject()))) {
244 return STATUS_UNSUCCESSFUL;
245 }
246
247 NTSTATUS ntStatus = PcNewRegistryKey(&DriverKey, NULL, DriverRegistryKey, KEY_ALL_ACCESS, CMIAdapter->getDeviceObject(), NULL, NULL, 0, NULL);
248
249 if(!NT_SUCCESS(ntStatus)) {
250 DBGPRINT(("PcNewRegistryKey() failed"));
251 return STATUS_UNSUCCESSFUL;
252 }
253
254 RtlInitUnicodeString(&KeyName, L"Settings");
255
256 ntStatus = DriverKey->NewSubKey(&SettingsKey, NULL, KEY_ALL_ACCESS, &KeyName, REG_OPTION_NON_VOLATILE, NULL);
257 if(!NT_SUCCESS(ntStatus)) {
258 DBGPRINT(("DriverKey->NewSubKey() failed"));
259 return STATUS_UNSUCCESSFUL;
260 }
261
262 KeyInfo = ExAllocatePoolWithTag(PagedPool, sizeof(KEY_VALUE_PARTIAL_INFORMATION) + sizeof(DWORD), 'gnaa');
263 if (KeyInfo) {
264 RtlInitUnicodeString(&KeyName, L"ChannelCount");
265 ntStatus = SettingsKey->QueryValueKey(&KeyName, KeyValuePartialInformation, KeyInfo, sizeof(KEY_VALUE_PARTIAL_INFORMATION) + sizeof(DWORD), &ResultLength);
266 if (NT_SUCCESS (ntStatus)) {
267 PKEY_VALUE_PARTIAL_INFORMATION PartialInfo = (PKEY_VALUE_PARTIAL_INFORMATION)KeyInfo;
268 if (PartialInfo->DataLength == sizeof(DWORD)) {
269 requestedChannelCount = (*(PLONG)PartialInfo->Data);
270 }
271 } else {
272 requestedChannelCount = 2;
273 }
274
275 RtlInitUnicodeString(&KeyName, L"ChannelMask");
276 ntStatus = SettingsKey->QueryValueKey(&KeyName, KeyValuePartialInformation, KeyInfo, sizeof(KEY_VALUE_PARTIAL_INFORMATION) + sizeof(DWORD), &ResultLength);
277 if (NT_SUCCESS (ntStatus)) {
278 PKEY_VALUE_PARTIAL_INFORMATION PartialInfo = (PKEY_VALUE_PARTIAL_INFORMATION)KeyInfo;
279 if (PartialInfo->DataLength == sizeof(DWORD)) {
280 requestedChannelMask = (*(PLONG)PartialInfo->Data);
281 }
282 } else {
283 requestedChannelMask = KSAUDIO_SPEAKER_STEREO;
284 }
285 }
286 ExFreePoolWithTag(KeyInfo,'gnaa');
287
288 SettingsKey->Release();
289 DriverKey->Release();
290
291 return STATUS_SUCCESS;
292 }
293
storeChannelConfigToRegistry()294 NTSTATUS CMiniportWaveCMI::storeChannelConfigToRegistry()
295 {
296 PAGED_CODE();
297 PREGISTRYKEY DriverKey;
298 PREGISTRYKEY SettingsKey;
299 UNICODE_STRING KeyName;
300 DWORD Value;
301 DBGPRINT(("CMiniportWaveCMI::storeChannelConfigToRegistry()"));
302
303 if ((!CMIAdapter) || (!(CMIAdapter->getDeviceObject()))) {
304 return STATUS_UNSUCCESSFUL;
305 }
306
307 NTSTATUS ntStatus = PcNewRegistryKey(&DriverKey, NULL, DriverRegistryKey, KEY_ALL_ACCESS, CMIAdapter->getDeviceObject(), NULL, NULL, 0, NULL);
308
309 if(!NT_SUCCESS(ntStatus)) {
310 DBGPRINT(("PcNewRegistryKey() failed"));
311 return STATUS_UNSUCCESSFUL;
312 }
313
314 RtlInitUnicodeString(&KeyName, L"Settings");
315
316 ntStatus = DriverKey->NewSubKey(&SettingsKey, NULL, KEY_ALL_ACCESS, &KeyName, REG_OPTION_NON_VOLATILE, NULL);
317 if(!NT_SUCCESS(ntStatus)) {
318 DBGPRINT(("DriverKey->NewSubKey() failed"));
319 return STATUS_UNSUCCESSFUL;
320 }
321
322 Value = requestedChannelCount;
323 RtlInitUnicodeString(&KeyName, L"ChannelCount");
324 ntStatus = SettingsKey->SetValueKey(&KeyName, REG_DWORD, PVOID(&Value), sizeof(DWORD));
325 if (!NT_SUCCESS(ntStatus)) {
326 DBGPRINT(("SetValueKey() failed"));
327 }
328 Value = requestedChannelMask;
329 RtlInitUnicodeString(&KeyName, L"ChannelMask");
330 ntStatus = SettingsKey->SetValueKey(&KeyName, REG_DWORD, PVOID(&Value), sizeof(DWORD));
331 if (!NT_SUCCESS(ntStatus)) {
332 DBGPRINT(("SetValueKey() failed"));
333 }
334
335 SettingsKey->Release();
336 DriverKey->Release();
337
338 return STATUS_SUCCESS;
339 }
340
341
STDMETHODIMP_(void)342 STDMETHODIMP_(void) CMiniportWaveCMI::powerUp(void)
343 {
344 PAGED_CODE();
345 DBGPRINT(("CMiniportWaveCMI[%p]::powerUp()", this));
346 KSSTATE oldState[3];
347
348 for (int i=0;i<3;i++) {
349 if (isStreamRunning[i]) {
350 oldState[i] = stream[i]->state;
351 stream[i]->SetState(KSSTATE_STOP);
352 }
353 }
354
355 if (cm->TopoMiniport) {
356 cm->TopoMiniport->loadMixerSettingsFromMemory();
357 }
358
359 for (int i=0;i<3;i++) {
360 if (isStreamRunning[i]) {
361 stream[i]->prepareStream();
362 stream[i]->SetState(KSSTATE_ACQUIRE);
363 stream[i]->SetState(oldState[i]);
364 }
365 }
366 }
367
STDMETHODIMP_(void)368 STDMETHODIMP_(void) CMiniportWaveCMI::powerDown(void)
369 {
370 PAGED_CODE();
371 DBGPRINT(("CMiniportWaveCMI[%p]::powerDown()", this));
372
373 if (cm->TopoMiniport) {
374 cm->TopoMiniport->storeMixerSettingsToMemory();
375 }
376
377 }
378
379
isFormatAllowed(UInt32 sampleRate,BOOLEAN multiChan,BOOLEAN AC3)380 NTSTATUS CMiniportWaveCMI::isFormatAllowed(UInt32 sampleRate, BOOLEAN multiChan, BOOLEAN AC3)
381 {
382 PAGED_CODE();
383 ASSERT(sampleRate);
384 DBGPRINT(("CMiniportWaveCMI[%p]::isFormatAllowed(%d, %d, %d)", this, sampleRate, multiChan, AC3));
385
386 if (multiChan) {
387 switch (sampleRate) {
388 case 44100: if (cm->formatMask & FMT_441_MULTI_PCM) return STATUS_SUCCESS; break;
389 case 48000: if (cm->formatMask & FMT_480_MULTI_PCM) return STATUS_SUCCESS; break;
390 case 88200: if (cm->formatMask & FMT_882_MULTI_PCM) return STATUS_SUCCESS; break;
391 case 96000: if (cm->formatMask & FMT_960_MULTI_PCM) return STATUS_SUCCESS; break;
392 }
393 return STATUS_INVALID_PARAMETER;
394 }
395 if (AC3) {
396 switch (sampleRate) {
397 case 44100: if (cm->formatMask & FMT_441_DOLBY) return STATUS_SUCCESS; break;
398 case 48000: if (cm->formatMask & FMT_480_DOLBY) return STATUS_SUCCESS; break;
399 case 88200: if (cm->formatMask & FMT_882_DOLBY) return STATUS_SUCCESS; break;
400 case 96000: if (cm->formatMask & FMT_960_DOLBY) return STATUS_SUCCESS; break;
401 }
402 return STATUS_INVALID_PARAMETER;
403 }
404 switch (sampleRate) {
405 case 44100: if (cm->formatMask & FMT_441_PCM) return STATUS_SUCCESS; break;
406 case 48000: if (cm->formatMask & FMT_480_PCM) return STATUS_SUCCESS; break;
407 case 88200: if (cm->formatMask & FMT_882_PCM) return STATUS_SUCCESS; break;
408 case 96000: if (cm->formatMask & FMT_960_PCM) return STATUS_SUCCESS; break;
409 }
410 return STATUS_INVALID_PARAMETER;
411 }
412
validateFormat(PKSDATAFORMAT format,ULONG PinID,BOOLEAN capture)413 NTSTATUS CMiniportWaveCMI::validateFormat(PKSDATAFORMAT format, ULONG PinID, BOOLEAN capture)
414 {
415 PAGED_CODE();
416 ASSERT(format);
417 DBGPRINT(("CMiniportWaveCMI[%p]::validateFormat(%p, %d, %d)", this, format, PinID, capture));
418
419 PWAVEFORMATEX waveFormat = PWAVEFORMATEX(format + 1);
420 DBGPRINT(("---channels: %d, resolution: %d, sample rate: %d, pin: %d, formatMask: %x", waveFormat->nChannels, waveFormat->wBitsPerSample, waveFormat->nSamplesPerSec, PinID, cm->formatMask));
421
422 //WaveFormatEx
423 if ( ( format->FormatSize >= sizeof(KSDATAFORMAT_WAVEFORMATEX))
424 && IsEqualGUIDAligned(format->MajorFormat,KSDATAFORMAT_TYPE_AUDIO)
425 && IsEqualGUIDAligned(format->Specifier,KSDATAFORMAT_SPECIFIER_WAVEFORMATEX) ) {
426 switch (EXTRACT_WAVEFORMATEX_ID(&format->SubFormat)) {
427 case WAVE_FORMAT_PCM:
428 if ((PinID != PIN_WAVE_RENDER_SINK) && (PinID != PIN_WAVE_CAPTURE_SOURCE) && (PinID != ((ULONG)-1))) {
429 if ((PinID == PIN_WAVE_AC3_RENDER_SINK) && !IoIsWdmVersionAvailable(6,0)) {
430 return STATUS_INVALID_PARAMETER;
431 }
432 }
433
434 if ( ((waveFormat->wBitsPerSample == 16) || (waveFormat->wBitsPerSample == 32))
435 && ((waveFormat->nSamplesPerSec == 44100) || (waveFormat->nSamplesPerSec == 48000) || (waveFormat->nSamplesPerSec == 88200) || (waveFormat->nSamplesPerSec == 96000))
436 && (waveFormat->nChannels == 2) ) {
437 if ((capture) && (waveFormat->nSamplesPerSec > 48000) ) {
438 return STATUS_INVALID_PARAMETER;
439 }
440 return isFormatAllowed(waveFormat->nSamplesPerSec, FALSE, FALSE);
441 }
442 if ( (waveFormat->wBitsPerSample == 16)
443 && ((waveFormat->nChannels >= 4) && (waveFormat->nChannels <= cm->maxChannels))
444 && ((waveFormat->nSamplesPerSec == 44100) || (waveFormat->nSamplesPerSec == 48000)) ) {
445 #if OUT_CHANNEL == 1
446 if ((PinID == PIN_WAVE_RENDER_SINK) || (PinID == ((ULONG)-1))) {
447 return isFormatAllowed(waveFormat->nSamplesPerSec, TRUE, FALSE);
448 }
449 #else
450 return STATUS_INVALID_PARAMETER;
451 #endif
452 }
453 break;
454 case WAVE_FORMAT_DOLBY_AC3_SPDIF:
455 if ((PinID != PIN_WAVE_AC3_RENDER_SINK) && (PinID != ((ULONG)-1))) {
456 return STATUS_INVALID_PARAMETER;
457 }
458 if ( ((waveFormat->wBitsPerSample >= MIN_BITS_PER_SAMPLE_AC3) && (waveFormat->wBitsPerSample <= MAX_BITS_PER_SAMPLE_AC3))
459 && ((waveFormat->nSamplesPerSec >= MIN_SAMPLE_RATE_AC3) && (waveFormat->nSamplesPerSec <= MAX_SAMPLE_RATE_AC3))
460 && (waveFormat->nChannels == MAX_CHANNELS_AC3) ) {
461 return isFormatAllowed(waveFormat->nSamplesPerSec, FALSE, TRUE);
462 }
463 break;
464 case WAVE_FORMAT_WMA_SPDIF:
465 if ((PinID != PIN_WAVE_AC3_RENDER_SINK) && (PinID != ((ULONG)-1))) {
466 return STATUS_INVALID_PARAMETER;
467 }
468 if ( ((waveFormat->wBitsPerSample >= MIN_BITS_PER_SAMPLE_WMA) && (waveFormat->wBitsPerSample <= MAX_BITS_PER_SAMPLE_WMA))
469 && ((waveFormat->nSamplesPerSec >= MIN_SAMPLE_RATE_WMA) && (waveFormat->nSamplesPerSec <= MAX_SAMPLE_RATE_WMA))
470 && (waveFormat->nChannels == MAX_CHANNELS_WMA) ) {
471 return isFormatAllowed(waveFormat->nSamplesPerSec, FALSE, TRUE);
472 }
473 break;
474 }
475 }
476
477 return STATUS_INVALID_PARAMETER;
478 }
479
480 // Tests a data range intersection
DataRangeIntersection(ULONG PinId,PKSDATARANGE ClientDataRange,PKSDATARANGE MyDataRange,ULONG OutputBufferLength,PVOID ResultantFormat,PULONG ResultantFormatLength)481 STDMETHODIMP CMiniportWaveCMI::DataRangeIntersection(ULONG PinId, PKSDATARANGE ClientDataRange, PKSDATARANGE MyDataRange, ULONG OutputBufferLength, PVOID ResultantFormat, PULONG ResultantFormatLength)
482 {
483 PAGED_CODE();
484 DBGPRINT(("CMiniportWaveCMI[%p]::DataRangeIntersection(%d, %p, %p, %d, %p, %p)", this, PinId, ClientDataRange, MyDataRange, OutputBufferLength, ResultantFormat, ResultantFormatLength));
485
486 if (PinId == PIN_WAVE_AC3_RENDER_SINK) {
487 bool isAC3Pin = true;
488 // Under Windows 2000 and XP, the client's DataRange should be AC3 only.
489 // The AC3 pin is the SPDIF pin in Windows Vista, so 2ch stereo is going to be allowed.
490
491 if (!IsEqualGUIDAligned(ClientDataRange->MajorFormat, KSDATAFORMAT_TYPE_AUDIO)
492 && !IsEqualGUIDAligned(ClientDataRange->MajorFormat, KSDATAFORMAT_TYPE_WILDCARD)) {
493 return STATUS_NO_MATCH;
494 }
495
496
497 if (!IsEqualGUIDAligned(ClientDataRange->SubFormat, KSDATAFORMAT_SUBTYPE_DOLBY_AC3_SPDIF)
498 && !IsEqualGUIDAligned(ClientDataRange->SubFormat, KSDATAFORMAT_SUBTYPE_WMA_SPDIF)
499 && !IsEqualGUIDAligned(ClientDataRange->SubFormat, KSDATAFORMAT_SUBTYPE_WILDCARD)) {
500 // check for Vista
501 isAC3Pin = false;
502 if (IoIsWdmVersionAvailable(0x06,0x00)) {
503 if (!IsEqualGUIDAligned(ClientDataRange->SubFormat, KSDATAFORMAT_SUBTYPE_PCM)
504 && !IsEqualGUIDAligned(ClientDataRange->SubFormat, KSDATAFORMAT_SUBTYPE_WILDCARD)) {
505 return STATUS_NO_MATCH;
506 }
507 } else {
508 return STATUS_NO_MATCH;
509 }
510 }
511
512 if (IsEqualGUIDAligned(ClientDataRange->Specifier, KSDATAFORMAT_SPECIFIER_WAVEFORMATEX)
513 || IsEqualGUIDAligned(ClientDataRange->Specifier, KSDATAFORMAT_SPECIFIER_WILDCARD)) {
514 *ResultantFormatLength = sizeof(KSDATAFORMAT_WAVEFORMATEX);
515 } else
516 if (IsEqualGUIDAligned(ClientDataRange->Specifier, KSDATAFORMAT_SPECIFIER_DSOUND)) {
517 *ResultantFormatLength = sizeof(KSDATAFORMAT_DSOUND);
518 } else {
519 return STATUS_NO_MATCH;
520 }
521
522 // Validate return buffer size, if the request is only for the
523 // size of the resultant structure, return it now.
524 if (!OutputBufferLength) {
525 *ResultantFormatLength = sizeof(KSDATAFORMAT_WAVEFORMATEX);
526 return STATUS_BUFFER_OVERFLOW;
527 } else
528 if (OutputBufferLength < sizeof(KSDATAFORMAT_WAVEFORMATEX)) {
529 return STATUS_BUFFER_TOO_SMALL;
530 }
531
532 PKSDATAFORMAT_WAVEFORMATEX resultantFormatWFX = (PKSDATAFORMAT_WAVEFORMATEX) ResultantFormat;
533 PWAVEFORMATEX pWaveFormatEx;
534
535 // Return the best (only) available format.
536 resultantFormatWFX->DataFormat.FormatSize = *ResultantFormatLength;
537 resultantFormatWFX->DataFormat.Flags = 0;
538 resultantFormatWFX->DataFormat.SampleSize = 4; // must match nBlockAlign
539 resultantFormatWFX->DataFormat.Reserved = 0;
540
541 resultantFormatWFX->DataFormat.MajorFormat = KSDATAFORMAT_TYPE_AUDIO;
542 INIT_WAVEFORMATEX_GUID(&resultantFormatWFX->DataFormat.SubFormat, WAVE_FORMAT_DOLBY_AC3_SPDIF);
543
544 // Extra space for the DSound specifier
545 if (IsEqualGUIDAligned(ClientDataRange->Specifier, KSDATAFORMAT_SPECIFIER_DSOUND)) {
546
547 PKSDATAFORMAT_DSOUND resultantFormatDSound = (PKSDATAFORMAT_DSOUND)ResultantFormat;
548
549 resultantFormatDSound->DataFormat.Specifier = KSDATAFORMAT_SPECIFIER_DSOUND;
550
551 // DSound format capabilities are not expressed
552 // this way in KS, so we express no capabilities.
553 resultantFormatDSound->BufferDesc.Flags = 0 ;
554 resultantFormatDSound->BufferDesc.Control = 0 ;
555
556 pWaveFormatEx = &resultantFormatDSound->BufferDesc.WaveFormatEx;
557 } else {
558 // WAVEFORMATEX or WILDCARD (WAVEFORMATEX)
559 resultantFormatWFX->DataFormat.Specifier = KSDATAFORMAT_SPECIFIER_WAVEFORMATEX;
560
561 pWaveFormatEx = (PWAVEFORMATEX)((PKSDATAFORMAT)resultantFormatWFX + 1);
562 }
563
564 pWaveFormatEx->nChannels = 2;
565 pWaveFormatEx->wBitsPerSample = 16; // SPDIF
566 pWaveFormatEx->cbSize = 0;
567 if (isAC3Pin) {
568 if (IsEqualGUIDAligned(ClientDataRange->SubFormat, KSDATAFORMAT_SUBTYPE_WMA_SPDIF)) {
569 pWaveFormatEx->wFormatTag = WAVE_FORMAT_WMA_SPDIF;
570 pWaveFormatEx->nSamplesPerSec = min( ((PKSDATARANGE_AUDIO)ClientDataRange)->MaximumSampleFrequency, MAX_SAMPLE_RATE_WMA);
571 } else {
572 pWaveFormatEx->wFormatTag = WAVE_FORMAT_DOLBY_AC3_SPDIF;
573 pWaveFormatEx->nSamplesPerSec = 48000;
574 }
575 } else {
576 pWaveFormatEx->wFormatTag = WAVE_FORMAT_PCM;
577 pWaveFormatEx->nSamplesPerSec = min( ((PKSDATARANGE_AUDIO)ClientDataRange)->MaximumSampleFrequency, MAX_SAMPLE_RATE);
578 }
579 pWaveFormatEx->nBlockAlign = pWaveFormatEx->nChannels * pWaveFormatEx->wBitsPerSample / 8;
580 pWaveFormatEx->nAvgBytesPerSec = pWaveFormatEx->nSamplesPerSec * pWaveFormatEx->nBlockAlign;
581
582 return STATUS_SUCCESS;
583 }
584 if ((PinId == PIN_WAVE_RENDER_SINK) || (PinId == PIN_WAVE_CAPTURE_SINK)) {
585
586 if (!IsEqualGUIDAligned(ClientDataRange->SubFormat, KSDATAFORMAT_SUBTYPE_PCM) &&
587 !IsEqualGUIDAligned(ClientDataRange->SubFormat, KSDATAFORMAT_SUBTYPE_WILDCARD)) {
588 return STATUS_NO_MATCH;
589 }
590
591 if (!IsEqualGUIDAligned(ClientDataRange->MajorFormat, KSDATAFORMAT_TYPE_AUDIO) &&
592 !IsEqualGUIDAligned(ClientDataRange->MajorFormat, KSDATAFORMAT_TYPE_WILDCARD)) {
593 return STATUS_NO_MATCH;
594 }
595
596 if (IsEqualGUIDAligned(ClientDataRange->Specifier, KSDATAFORMAT_SPECIFIER_WAVEFORMATEX) ||
597 IsEqualGUIDAligned(ClientDataRange->Specifier, KSDATAFORMAT_SPECIFIER_WILDCARD)) {
598 *ResultantFormatLength = sizeof(KSDATAFORMAT_WAVEFORMATEX);
599 } else
600 if (IsEqualGUIDAligned(ClientDataRange->Specifier, KSDATAFORMAT_SPECIFIER_DSOUND)) {
601 *ResultantFormatLength = sizeof(KSDATAFORMAT_DSOUND);
602 } else {
603 return STATUS_NO_MATCH;
604 }
605
606
607 ULONG sampleRate = 0;
608 ULONG nMaxChannels = min(((PKSDATARANGE_AUDIO)ClientDataRange)->MaximumChannels, requestedChannelCount);
609
610 // check for Vista
611 if (IoIsWdmVersionAvailable(6,0) && (PinId == PIN_WAVE_RENDER_SINK)) {
612 nMaxChannels = ((PKSDATARANGE_AUDIO)ClientDataRange)->MaximumChannels;
613 }
614 if (nMaxChannels & 0x01) {
615 nMaxChannels--;
616 }
617 if (!nMaxChannels) {
618 return STATUS_NO_MATCH;
619 }
620
621 if (isStreamRunning[PCM_OUT_STREAM]) {
622 sampleRate = stream[PCM_OUT_STREAM]->currentSampleRate;
623 } else
624 if (isStreamRunning[PCM_IN_STREAM]) {
625 sampleRate = stream[PCM_IN_STREAM]->currentSampleRate;
626 }
627 if (sampleRate == 0) {
628 if ((nMaxChannels > 2) && (((PKSDATARANGE_AUDIO)ClientDataRange)->MaximumSampleFrequency > MAX_SAMPLE_RATE_MULTI)) {
629 sampleRate = MAX_SAMPLE_RATE_MULTI;
630 } else
631 if ((nMaxChannels == 2) && (((PKSDATARANGE_AUDIO)ClientDataRange)->MaximumSampleFrequency > MAX_SAMPLE_RATE)) {
632 sampleRate = MAX_SAMPLE_RATE;
633 } else {
634 sampleRate = ((PKSDATARANGE_AUDIO)ClientDataRange)->MaximumSampleFrequency;
635 }
636 }
637
638 if ((((PKSDATARANGE_AUDIO)ClientDataRange)->MaximumSampleFrequency < sampleRate)
639 || (((PKSDATARANGE_AUDIO)ClientDataRange)->MinimumSampleFrequency > sampleRate)) {
640 return STATUS_NO_MATCH;
641 }
642
643 if (PinId == PIN_WAVE_RENDER_SINK) {
644 if (!OutputBufferLength) {
645 *ResultantFormatLength = sizeof(KSDATAFORMAT) + sizeof(WAVEFORMATPCMEX);
646 return STATUS_BUFFER_OVERFLOW;
647 } else
648 if (OutputBufferLength < sizeof(KSDATAFORMAT) + sizeof(WAVEFORMATPCMEX)) {
649 return STATUS_BUFFER_TOO_SMALL;
650 }
651
652 if (((PKSDATARANGE_AUDIO)ClientDataRange)->MaximumChannels < 2) {
653 DBGPRINT(("[[DataRangeIntersection] mono format not supported"));
654 return STATUS_NO_MATCH;
655 }
656
657 PWAVEFORMATPCMEX WaveFormat = (PWAVEFORMATPCMEX)((PKSDATAFORMAT)ResultantFormat + 1);
658 if (IsEqualGUIDAligned(ClientDataRange->Specifier, KSDATAFORMAT_SPECIFIER_DSOUND)) {
659 return STATUS_NOT_SUPPORTED;
660 }
661 *(PKSDATAFORMAT)ResultantFormat = *MyDataRange;
662 ((PKSDATAFORMAT)ResultantFormat)->FormatSize = sizeof(KSDATAFORMAT) + sizeof(WAVEFORMATPCMEX);
663
664
665 WaveFormat->Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE;
666 WaveFormat->SubFormat = KSDATAFORMAT_SUBTYPE_PCM;
667 WaveFormat->Format.nChannels = (WORD)nMaxChannels;
668 WaveFormat->Format.wBitsPerSample = 16;
669 WaveFormat->Format.nBlockAlign = (WaveFormat->Format.wBitsPerSample >> 3) * WaveFormat->Format.nChannels;
670 WaveFormat->Format.nAvgBytesPerSec = WaveFormat->Format.nSamplesPerSec * WaveFormat->Format.nBlockAlign;
671 WaveFormat->Format.cbSize = sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX);
672 WaveFormat->Format.nSamplesPerSec = sampleRate;
673 WaveFormat->Samples.wValidBitsPerSample = WaveFormat->Format.wBitsPerSample;
674 switch (nMaxChannels) {
675 case 8: WaveFormat->dwChannelMask = KSAUDIO_SPEAKER_7POINT1; break;
676 case 6: WaveFormat->dwChannelMask = KSAUDIO_SPEAKER_5POINT1; break;
677 case 4: WaveFormat->dwChannelMask = KSAUDIO_SPEAKER_QUAD; break;
678 case 2: WaveFormat->dwChannelMask = KSAUDIO_SPEAKER_STEREO; break;
679 }
680 if (nMaxChannels == requestedChannelCount) {
681 WaveFormat->dwChannelMask = requestedChannelMask;
682 }
683 ((PKSDATAFORMAT)ResultantFormat)->SampleSize = WaveFormat->Format.nBlockAlign;
684
685 *ResultantFormatLength = sizeof(KSDATAFORMAT) + sizeof(WAVEFORMATPCMEX);
686 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));
687 } else
688 if (PinId == PIN_WAVE_CAPTURE_SINK) {
689 PKSDATAFORMAT_WAVEFORMATEX resultantFormatWFX;
690 PWAVEFORMATEX pWaveFormatEx;
691
692 if (!OutputBufferLength) {
693 *ResultantFormatLength = sizeof(KSDATAFORMAT_WAVEFORMATEX);
694 return STATUS_BUFFER_OVERFLOW;
695 } else
696 if (OutputBufferLength < sizeof(KSDATAFORMAT_WAVEFORMATEX)) {
697 return STATUS_BUFFER_TOO_SMALL;
698 }
699
700 if (nMaxChannels > 2) {
701 nMaxChannels = 2;
702 }
703
704 resultantFormatWFX = (PKSDATAFORMAT_WAVEFORMATEX) ResultantFormat;
705 resultantFormatWFX->DataFormat.FormatSize = *ResultantFormatLength;
706 resultantFormatWFX->DataFormat.Flags = 0;
707 resultantFormatWFX->DataFormat.SampleSize = 4;
708 resultantFormatWFX->DataFormat.Reserved = 0;
709 resultantFormatWFX->DataFormat.MajorFormat = KSDATAFORMAT_TYPE_AUDIO;
710 INIT_WAVEFORMATEX_GUID(&resultantFormatWFX->DataFormat.SubFormat, WAVE_FORMAT_PCM);
711
712 if (IsEqualGUIDAligned(ClientDataRange->Specifier, KSDATAFORMAT_SPECIFIER_DSOUND)) {
713 PKSDATAFORMAT_DSOUND resultantFormatDSound;
714 resultantFormatDSound = (PKSDATAFORMAT_DSOUND)ResultantFormat;
715 resultantFormatDSound->DataFormat.Specifier = KSDATAFORMAT_SPECIFIER_DSOUND;
716 resultantFormatDSound->BufferDesc.Flags = 0 ;
717 resultantFormatDSound->BufferDesc.Control = 0 ;
718 pWaveFormatEx = &resultantFormatDSound->BufferDesc.WaveFormatEx;
719 } else {
720 resultantFormatWFX->DataFormat.Specifier = KSDATAFORMAT_SPECIFIER_WAVEFORMATEX;
721 pWaveFormatEx = (PWAVEFORMATEX)((PKSDATAFORMAT)resultantFormatWFX + 1);
722 }
723 pWaveFormatEx->wFormatTag = WAVE_FORMAT_PCM;
724 pWaveFormatEx->nChannels = nMaxChannels;
725 pWaveFormatEx->nSamplesPerSec = sampleRate;
726 pWaveFormatEx->wBitsPerSample = 16;
727 pWaveFormatEx->cbSize = 0;
728 pWaveFormatEx->nBlockAlign = 4;
729 pWaveFormatEx->nAvgBytesPerSec = 192000;
730 }
731 return STATUS_SUCCESS;
732 }
733 return STATUS_NO_MATCH;
734 }
735
736 //from IMiniportWaveCyclic::NewStream()
737 #ifdef WAVERT
NewStream(PMINIPORTWAVERTSTREAM * OutStream,PPORTWAVERTSTREAM OuterUnknown,ULONG PinID,BOOLEAN Capture,PKSDATAFORMAT DataFormat)738 STDMETHODIMP CMiniportWaveCMI::NewStream(PMINIPORTWAVERTSTREAM *OutStream, PPORTWAVERTSTREAM OuterUnknown, ULONG PinID, BOOLEAN Capture, PKSDATAFORMAT DataFormat)
739 #else
740 STDMETHODIMP CMiniportWaveCMI::NewStream(PMINIPORTWAVECYCLICSTREAM *OutStream, PUNKNOWN OuterUnknown, POOL_TYPE PoolType, ULONG PinID, BOOLEAN Capture, PKSDATAFORMAT DataFormat, PDMACHANNEL* OutDmaChannel, PSERVICEGROUP* OutServiceGroup)
741 #endif
742 {
743 PAGED_CODE();
744 ASSERT(OutStream);
745 ASSERT(DataFormat);
746 #ifdef WAVERT
747 DBGPRINT(("CMiniportWaveCMI[%p]::NewStream(%p, %p, %d, %d, %p)", this, OutStream, OuterUnknown, PinID, Capture, DataFormat));
748 #else
749 ASSERT(OutDmaChannel);
750 ASSERT(OutServiceGroup);
751 DBGPRINT(("CMiniportWaveCMI[%p]::NewStream(%p, %p, %p, %d, %d, %p, %p, %p)", this, OutStream, OuterUnknown, PoolType, PinID, Capture, DataFormat, OutDmaChannel, OutServiceGroup));
752 #endif
753
754 NTSTATUS ntStatus = STATUS_SUCCESS;
755 PWAVEFORMATEX waveFormat = PWAVEFORMATEX(DataFormat + 1);
756 UInt32 streamIndex = PCM_OUT_STREAM;
757
758 ntStatus = validateFormat(DataFormat, PinID, Capture);
759 if (!NT_SUCCESS(ntStatus)) {
760 DBGPRINT(("invalid stream format"));
761 return STATUS_UNSUCCESSFUL;
762 }
763 if (cm->enableSPDIFInMonitor) {
764 CMIAdapter->setUInt8Bit(REG_MIXER1, EN_SPDI2DAC);
765 }
766
767 if (Capture) {
768 streamIndex = PCM_IN_STREAM;
769 } else
770 if ( (WAVE_FORMAT_DOLBY_AC3_SPDIF == EXTRACT_WAVEFORMATEX_ID(&DataFormat->SubFormat)) || (WAVE_FORMAT_WMA_SPDIF == EXTRACT_WAVEFORMATEX_ID(&DataFormat->SubFormat))) {
771 streamIndex = AC3_OUT_STREAM;
772 }
773
774 // make sure the hardware is not already in use
775 if (isStreamRunning[streamIndex]) {
776 DBGPRINT(("Stream %d running, exiting...", streamIndex));
777 return STATUS_UNSUCCESSFUL;
778 }
779 if ((streamIndex == AC3_OUT_STREAM) && isStreamRunning[PCM_OUT_STREAM]) {
780 #ifdef WAVERT
781 stream[PCM_OUT_STREAM]->SetState(KSSTATE_STOP);
782 #else
783 stream[PCM_OUT_STREAM]->SetState(KSSTATE_STOP_AC3);
784 #endif
785 }
786 if ((streamIndex == PCM_OUT_STREAM) && isStreamRunning[AC3_OUT_STREAM]) {
787 return STATUS_UNSUCCESSFUL;
788 }
789
790 DBGPRINT(("---StreamNo: %d, Bits: %d, Sample Rate: %d, Channels: %d, AC3: %d", streamIndex,
791 waveFormat->wBitsPerSample, waveFormat->nSamplesPerSec, waveFormat->nChannels,
792 (WAVE_FORMAT_DOLBY_AC3_SPDIF == EXTRACT_WAVEFORMATEX_ID(&DataFormat->SubFormat)) || (WAVE_FORMAT_WMA_SPDIF == EXTRACT_WAVEFORMATEX_ID(&DataFormat->SubFormat)) ));
793
794 // the DAC and ADC can only run at the same sample rate simultaneously
795 if ((streamIndex == PCM_IN_STREAM) && isStreamRunning[PCM_OUT_STREAM]) {
796 if (waveFormat->nSamplesPerSec != stream[PCM_OUT_STREAM]->currentSampleRate) {
797 return STATUS_UNSUCCESSFUL;
798 }
799 }
800 if ((streamIndex == PCM_OUT_STREAM) && isStreamRunning[PCM_IN_STREAM]) {
801 if (waveFormat->nSamplesPerSec != stream[PCM_IN_STREAM]->currentSampleRate) {
802 return STATUS_UNSUCCESSFUL;
803 }
804 }
805
806 // instantiate a stream
807 #ifdef WAVERT
808 ntStatus = CreateMiniportWaveStreamCMI(&stream[streamIndex], OuterUnknown, NonPagedPool);
809 #else
810 ntStatus = CreateMiniportWaveStreamCMI(&stream[streamIndex], OuterUnknown, PoolType);
811 #endif
812 if (!NT_SUCCESS (ntStatus)) {
813 DBGPRINT(("Failed to create stream"));
814 return ntStatus;
815 }
816
817 // initialize it
818 #ifdef WAVERT
819 ntStatus = stream[streamIndex]->Init(this, streamIndex, Capture, DataFormat, OuterUnknown);
820 #else
821 ntStatus = stream[streamIndex]->Init(this, streamIndex, Capture, DataFormat, DMAChannel[streamIndex], OutServiceGroup);
822 #endif
823 if (!NT_SUCCESS(ntStatus)) {
824 DBGPRINT(("Failed to init stream"));
825 stream[streamIndex]->Release();
826 stream[streamIndex] = NULL;
827 *OutStream = NULL;
828 #ifndef WAVERT
829 *OutServiceGroup = NULL;
830 *OutDmaChannel = NULL;
831 #endif
832 return ntStatus;
833 }
834
835 #ifdef WAVERT
836 //this has been referenced in CreateMiniportWaveStreamCMI() already
837 *OutStream = (PMINIPORTWAVERTSTREAM)stream[streamIndex];
838 #else
839 *OutDmaChannel = DMAChannel[streamIndex];
840 DMAChannel[streamIndex]->AddRef();
841 *OutStream = (PMINIPORTWAVECYCLICSTREAM)stream[streamIndex];
842 #endif
843
844 return ntStatus;
845 }
846
PropertyHandler_ChannelConfig(PPCPROPERTY_REQUEST PropertyRequest)847 NTSTATUS NTAPI PropertyHandler_ChannelConfig(PPCPROPERTY_REQUEST PropertyRequest)
848 {
849 PAGED_CODE();
850 ASSERT(PropertyRequest);
851 DBGPRINT(("[PropertyHandler_ChannelConfig]"));
852
853 #ifdef WAVERT
854 CMiniportWaveCMI *that = (CMiniportWaveCMI *) ((PMINIPORTWAVERT)PropertyRequest->MajorTarget);
855 #else
856 CMiniportWaveCMI *that = (CMiniportWaveCMI *) ((PMINIPORTWAVECYCLIC)PropertyRequest->MajorTarget);
857 #endif
858
859 if (PropertyRequest->Node == KSNODE_WAVE_DAC) {
860
861 if (PropertyRequest->ValueSize == 0) {
862 PropertyRequest->ValueSize = sizeof(LONG);
863 return STATUS_BUFFER_OVERFLOW;
864 } else if (PropertyRequest->ValueSize < sizeof (LONG)) {
865 PropertyRequest->ValueSize = 0;
866 return STATUS_BUFFER_TOO_SMALL;
867 }
868
869 if (PropertyRequest->Verb & KSPROPERTY_TYPE_GET) {
870 *(PLONG)PropertyRequest->Value = that->requestedChannelMask;
871 PropertyRequest->ValueSize = sizeof(ULONG);
872 return STATUS_SUCCESS;
873 } else if (PropertyRequest->Verb & KSPROPERTY_TYPE_SET) {
874 if (*(PLONG)PropertyRequest->Value == KSAUDIO_SPEAKER_7POINT1) {
875 that->requestedChannelMask = *(PLONG)PropertyRequest->Value;
876 that->requestedChannelCount = 8;
877 return STATUS_SUCCESS;
878 }
879 if (*(PLONG)PropertyRequest->Value == KSAUDIO_SPEAKER_5POINT1) {
880 that->requestedChannelMask = *(PLONG)PropertyRequest->Value;
881 that->requestedChannelCount = 6;
882 return STATUS_SUCCESS;
883 }
884 if ((*(PLONG)PropertyRequest->Value == KSAUDIO_SPEAKER_QUAD) || (*(PLONG)PropertyRequest->Value == KSAUDIO_SPEAKER_SURROUND)) {
885 that->requestedChannelMask = *(PLONG)PropertyRequest->Value;
886 that->requestedChannelCount = 4;
887 return STATUS_SUCCESS;
888 }
889 if (*(PLONG)PropertyRequest->Value == KSAUDIO_SPEAKER_STEREO) {
890 that->requestedChannelMask = *(PLONG)PropertyRequest->Value;
891 that->requestedChannelCount = 2;
892 return STATUS_SUCCESS;
893 }
894 } else if (PropertyRequest->Verb & KSPROPERTY_TYPE_BASICSUPPORT) {
895 PULONG AccessFlags = PULONG(PropertyRequest->Value);
896 *AccessFlags = KSPROPERTY_TYPE_BASICSUPPORT | KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_SET;
897 PropertyRequest->ValueSize = sizeof(ULONG);
898 return STATUS_SUCCESS;
899 }
900 }
901 return STATUS_INVALID_PARAMETER;
902 }
903
904 ///////////////////////////
905
CreateMiniportWaveStreamCMI(CMiniportWaveStreamCMI ** MiniportWaveStreamCMI,PUNKNOWN pUnknownOuter,POOL_TYPE PoolType)906 NTSTATUS CreateMiniportWaveStreamCMI(CMiniportWaveStreamCMI **MiniportWaveStreamCMI, PUNKNOWN pUnknownOuter, POOL_TYPE PoolType)
907 {
908 PAGED_CODE();
909 DBGPRINT(("CreateMiniportWaveStreamCMI"));
910
911 #ifdef WAVERT
912 *MiniportWaveStreamCMI = new (PoolType, 'gnaa') CMiniportWaveStreamCMI(NULL);
913 #else
914 *MiniportWaveStreamCMI = new (PoolType, 'gnaa') CMiniportWaveStreamCMI(pUnknownOuter);
915 #endif
916 if (*MiniportWaveStreamCMI) {
917 (*MiniportWaveStreamCMI)->AddRef();
918 return STATUS_SUCCESS;
919 }
920
921 return STATUS_INSUFFICIENT_RESOURCES;
922 }
923
prepareStream()924 NTSTATUS CMiniportWaveStreamCMI::prepareStream()
925 {
926 PAGED_CODE();
927 DBGPRINT(("CMiniportWaveStreamCMI[%p]::prepareStream()", this));
928 DBGPRINT(("---streamIndex: %d, channelNumber: %d", streamIndex, channelNumber));
929
930 NTSTATUS ntStatus;
931 UInt32 val;
932
933 if (state == KSSTATE_RUN) {
934 return STATUS_INVALID_DEVICE_REQUEST;
935 }
936
937 if (!(Miniport->cm)) {
938 DBGPRINT(("Miniport not set"));
939 return STATUS_INVALID_DEVICE_REQUEST;
940 }
941
942 enableSPDIF = ((currentSampleRate == 44100 || currentSampleRate == 48000 || currentSampleRate == 88200 || currentSampleRate == 96000) &&
943 ((currentResolution == 16) || (currentResolution == 32)) && (currentChannelCount == 2)) &&
944 (Miniport->cm->enableSPDIFOut);
945
946 if (!isCaptureStream) {
947 ntStatus = setupSPDIFPlayback(enableSPDIF);
948 if (!NT_SUCCESS(ntStatus)) {
949 return ntStatus;
950 }
951 ntStatus = setDACChannels();
952 if (!NT_SUCCESS(ntStatus)) {
953 return ntStatus;
954 }
955 }
956
957 KeWaitForSingleObject(&Miniport->mutex, Executive, KernelMode, false, NULL);
958
959 val = channelNumber ? ADC_CH1 : ADC_CH0;
960 if (isCaptureStream) {
961 Miniport->cm->regFUNCTRL0 |= val; // 1->Recording
962 } else {
963 Miniport->cm->regFUNCTRL0 &= ~val; // 0->Playback
964 }
965 Miniport->CMIAdapter->writeUInt32(REG_FUNCTRL0, Miniport->cm->regFUNCTRL0);
966
967 //set sampling frequency
968 val = Miniport->CMIAdapter->readUInt32(REG_FUNCTRL1);
969 if ((currentSampleRate == 88200) || (currentSampleRate == 44100)) {
970 if (channelNumber) {
971 val &= ~SFC_CH1_MASK;
972 val |= SFC_44K_CH1;
973 } else {
974 val &= ~SFC_CH0_MASK;
975 val |= SFC_44K_CH0;
976 }
977 } else if ((currentSampleRate == 96000) || (currentSampleRate == 48000)) {
978 if (channelNumber) {
979 val &= ~SFC_CH1_MASK;
980 val |= SFC_48K_CH1;
981 } else {
982 val &= ~SFC_CH0_MASK;
983 val |= SFC_48K_CH0;
984 }
985 } else {
986 KeReleaseMutex(&Miniport->mutex, FALSE);
987 return STATUS_INVALID_DEVICE_REQUEST;
988 }
989 Miniport->CMIAdapter->writeUInt32(REG_FUNCTRL1, val);
990
991 //set resolution
992 val = Miniport->CMIAdapter->readUInt32(REG_CHFORMAT);
993 if (channelNumber) {
994 val |= FORMAT_CH1;
995 } else {
996 val |= FORMAT_CH0;
997 }
998 Miniport->CMIAdapter->writeUInt32(REG_CHFORMAT, val);
999
1000 KeReleaseMutex(&Miniport->mutex, false);
1001
1002 return STATUS_SUCCESS;
1003 }
1004
setDACChannels()1005 NTSTATUS CMiniportWaveStreamCMI::setDACChannels()
1006 {
1007 PAGED_CODE();
1008 DBGPRINT(("CMiniportWaveStreamCMI[%p]::setDACChannels()", this));
1009 NTSTATUS ntStatus = STATUS_SUCCESS;
1010
1011 if (currentChannelCount > 2) {
1012 if (Miniport->cm->maxChannels < currentChannelCount) {
1013 return STATUS_INVALID_DEVICE_REQUEST;
1014 }
1015 if ((currentResolution != 16) || (currentChannelCount < 2)) {
1016 return STATUS_INVALID_DEVICE_REQUEST;
1017 }
1018 #if OUT_CHANNEL == 0
1019 return STATUS_INVALID_DEVICE_REQUEST;
1020 #endif
1021 KeWaitForSingleObject(&Miniport->mutex, Executive, KernelMode, FALSE, NULL);
1022 Miniport->CMIAdapter->setUInt32Bit(REG_LEGACY, DWORD_MAPPING);
1023 Miniport->CMIAdapter->setUInt32Bit(REG_MISCCTRL, XCHG_DAC);
1024
1025 switch (currentChannelCount) {
1026 case 4:
1027 Miniport->CMIAdapter->setUInt32Bit(REG_CHFORMAT, EN_4CH_CH1);
1028 Miniport->CMIAdapter->clearUInt32Bit(REG_CHFORMAT, EN_5CH_CH1);
1029 Miniport->CMIAdapter->clearUInt32Bit(REG_LEGACY, EN_6CH_CH1);
1030 Miniport->CMIAdapter->clearUInt32Bit(REG_MISCCTRL, EN_CENTER);
1031 break;
1032 case 6:
1033 Miniport->CMIAdapter->clearUInt32Bit(REG_CHFORMAT, EN_4CH_CH1);
1034 Miniport->CMIAdapter->setUInt32Bit(REG_CHFORMAT, EN_5CH_CH1);
1035 Miniport->CMIAdapter->setUInt32Bit(REG_LEGACY, EN_6CH_CH1);
1036 Miniport->CMIAdapter->setUInt32Bit(REG_MISCCTRL, EN_CENTER);
1037 break;
1038 case 8:
1039 if (Miniport->cm->chipVersion == 68) {
1040 Miniport->CMIAdapter->clearUInt32Bit(REG_CHFORMAT, EN_4CH_CH1);
1041 Miniport->CMIAdapter->setUInt32Bit(REG_CHFORMAT, EN_5CH_CH1);
1042 Miniport->CMIAdapter->setUInt32Bit(REG_LEGACY, EN_6CH_CH1);
1043 Miniport->CMIAdapter->setUInt32Bit(REG_MISCCTRL, EN_CENTER);
1044 Miniport->CMIAdapter->setUInt32Bit(REG_MISCCTRL2, EN_8CH_CH1);
1045 break;
1046 } else {
1047 ntStatus = STATUS_INVALID_DEVICE_REQUEST;
1048 }
1049 default:
1050 ntStatus = STATUS_INVALID_DEVICE_REQUEST;
1051 }
1052 KeReleaseMutex(&Miniport->mutex, FALSE);
1053 } else {
1054 if (Miniport->cm->canMultiChannel) {
1055 KeWaitForSingleObject(&Miniport->mutex, Executive, KernelMode, FALSE, NULL);
1056 Miniport->CMIAdapter->clearUInt32Bit(REG_CHFORMAT, EN_5CH_CH1 | EN_4CH_CH1);
1057 Miniport->CMIAdapter->clearUInt32Bit(REG_LEGACY, EN_6CH_CH1 | DWORD_MAPPING);
1058 Miniport->CMIAdapter->clearUInt32Bit(REG_MISCCTRL, EN_CENTER);
1059 Miniport->CMIAdapter->clearUInt32Bit(REG_MISCCTRL, XCHG_DAC);
1060 if (Miniport->cm->chipVersion == 68) {
1061 Miniport->CMIAdapter->clearUInt32Bit(REG_MISCCTRL2, EN_8CH_CH1);
1062 }
1063 KeReleaseMutex(&Miniport->mutex, FALSE);
1064 }
1065 }
1066 return ntStatus;
1067 }
1068
setupSPDIFPlayback(bool enableSPDIF)1069 NTSTATUS CMiniportWaveStreamCMI::setupSPDIFPlayback(bool enableSPDIF)
1070 {
1071 PAGED_CODE();
1072 DBGPRINT(("CMiniportWaveStreamCMI[%p]::setupSPDIFPlayback(%d)", this, enableSPDIF));
1073
1074 KeWaitForSingleObject(&Miniport->mutex, Executive, KernelMode, false, NULL);
1075
1076 if (enableSPDIF) {
1077 Miniport->CMIAdapter->setUInt32Bit(REG_LEGACY, EN_SPDIF_OUT);
1078 Miniport->CMIAdapter->setUInt32Bit(REG_FUNCTRL1, SPDO2DAC);
1079 #if OUT_CHANNEL == 0
1080 Miniport->CMIAdapter->setUInt32Bit(REG_FUNCTRL1, SPDF_0);
1081 #else
1082 Miniport->CMIAdapter->setUInt32Bit(REG_FUNCTRL1, SPDF_1);
1083 #endif
1084 setupAC3Passthru();
1085
1086 if ( (currentSampleRate == 48000) || (currentSampleRate == 96000) ) {
1087 Miniport->CMIAdapter->setUInt32Bit(REG_MISCCTRL, EN_SPDIF_48);
1088 } else {
1089 Miniport->CMIAdapter->clearUInt32Bit(REG_MISCCTRL, EN_SPDIF_48);
1090 }
1091
1092 if (currentSampleRate == 96000) {
1093 #if OUT_CHANNEL == 0
1094 Miniport->CMIAdapter->setUInt32Bit(REG_CHFORMAT, SPD96_CH0);
1095 #else
1096 Miniport->CMIAdapter->setUInt32Bit(REG_CHFORMAT, SPD96_CH1);
1097 #endif
1098 Miniport->CMIAdapter->setUInt32Bit(REG_CHFORMAT, DBLSPDS);
1099 } else if (currentSampleRate == 88200) {
1100 #if OUT_CHANNEL == 0
1101 Miniport->CMIAdapter->setUInt32Bit(REG_CHFORMAT, SPD88_CH0);
1102 #else
1103 Miniport->CMIAdapter->setUInt32Bit(REG_CHFORMAT, SPD88_CH1);
1104 #endif
1105 Miniport->CMIAdapter->setUInt32Bit(REG_CHFORMAT, DBLSPDS);
1106 } else {
1107 #if OUT_CHANNEL == 0
1108 Miniport->CMIAdapter->clearUInt32Bit(REG_CHFORMAT, SPD88_CH0 | SPD96_CH0);
1109 #else
1110 Miniport->CMIAdapter->clearUInt32Bit(REG_CHFORMAT, SPD88_CH1 | SPD96_CH1);
1111 #endif
1112 Miniport->CMIAdapter->clearUInt32Bit(REG_CHFORMAT, DBLSPDS);
1113 }
1114
1115 } else {
1116 Miniport->CMIAdapter->clearUInt32Bit(REG_LEGACY, EN_SPDIF_OUT);
1117 Miniport->CMIAdapter->clearUInt32Bit(REG_FUNCTRL1, SPDO2DAC);
1118 #if OUT_CHANNEL == 0
1119 Miniport->CMIAdapter->clearUInt32Bit(REG_FUNCTRL1, SPDF_0);
1120 #else
1121 Miniport->CMIAdapter->clearUInt32Bit(REG_FUNCTRL1, SPDF_1);
1122 #endif
1123 #if OUT_CHANNEL == 0
1124 Miniport->CMIAdapter->clearUInt32Bit(REG_CHFORMAT, SPD88_CH0 | SPD96_CH0);
1125 #else
1126 Miniport->CMIAdapter->clearUInt32Bit(REG_CHFORMAT, SPD88_CH1 | SPD96_CH1);
1127 #endif
1128 Miniport->CMIAdapter->clearUInt32Bit(REG_CHFORMAT, DBLSPDS);
1129 setupAC3Passthru();
1130 }
1131
1132 KeReleaseMutex(&Miniport->mutex, false);
1133 return STATUS_SUCCESS;
1134 }
1135
setupAC3Passthru()1136 NTSTATUS CMiniportWaveStreamCMI::setupAC3Passthru()
1137 {
1138 PAGED_CODE();
1139 DBGPRINT(("CMiniportWaveStreamCMI[%p]::setupAC3Passthru() [enableAC3Passthru: %d]", this, enableAC3Passthru));
1140
1141 if (enableAC3Passthru) {
1142 Miniport->CMIAdapter->writeUInt8(REG_MIXER1, Miniport->CMIAdapter->readUInt8(REG_MIXER1) | MUTE_WAVE);
1143
1144 Miniport->CMIAdapter->setUInt32Bit(REG_CHFORMAT, EN_SPDO_AC3_1);
1145 Miniport->CMIAdapter->setUInt32Bit(REG_MISCCTRL, EN_SPDO_AC3_2);
1146
1147 if (Miniport->cm->canAC3HW) {
1148 Miniport->CMIAdapter->setUInt32Bit(REG_CHFORMAT, EN_SPDO_AC3_3);
1149 Miniport->CMIAdapter->clearUInt32Bit(REG_MISCCTRL, SPD32SEL);
1150 if (Miniport->cm->chipVersion >= 39) {
1151 Miniport->CMIAdapter->clearUInt8Bit(REG_MIXER1, EN_SPDI2DAC);
1152 }
1153 } else {
1154 Miniport->CMIAdapter->setUInt32Bit(REG_MISCCTRL, SPD32SEL);
1155 if (Miniport->cm->chipVersion == 33) {
1156 if (currentSampleRate >= 48000) {
1157 #if OUT_CHANNEL == 0
1158 Miniport->CMIAdapter->setUInt32Bit(REG_CHFORMAT, SPD96_CH0);
1159 #else
1160 Miniport->CMIAdapter->setUInt32Bit(REG_CHFORMAT, SPD96_CH1);
1161 #endif
1162 } else {
1163 #if OUT_CHANNEL == 0
1164 Miniport->CMIAdapter->clearUInt32Bit(REG_CHFORMAT, SPD96_CH0);
1165 #else
1166 Miniport->CMIAdapter->clearUInt32Bit(REG_CHFORMAT, SPD96_CH1);
1167 #endif
1168 }
1169 }
1170 }
1171 } else {
1172 if (Miniport->cm->enableSPDIFInMonitor) {
1173 Miniport->CMIAdapter->setUInt8Bit(REG_MIXER1, EN_SPDI2DAC);
1174 }
1175
1176 Miniport->CMIAdapter->clearUInt32Bit(REG_CHFORMAT, EN_SPDO_AC3_1);
1177 Miniport->CMIAdapter->clearUInt32Bit(REG_MISCCTRL, EN_SPDO_AC3_2);
1178
1179 if (Miniport->cm->canAC3HW) {
1180 Miniport->CMIAdapter->clearUInt32Bit(REG_CHFORMAT, EN_SPDO_AC3_3);
1181 if (currentResolution > 16) {
1182 Miniport->CMIAdapter->setUInt32Bit(REG_MISCCTRL, SPD32SEL);
1183 Miniport->CMIAdapter->setUInt32Bit(REG_CHFORMAT, SPD24SEL);
1184 } else {
1185 Miniport->CMIAdapter->clearUInt32Bit(REG_MISCCTRL, SPD32SEL);
1186 Miniport->CMIAdapter->clearUInt32Bit(REG_CHFORMAT, SPD24SEL);
1187 }
1188 } else {
1189 Miniport->CMIAdapter->clearUInt32Bit(REG_MISCCTRL, SPD32SEL);
1190 #if OUT_CHANNEL == 0
1191 Miniport->CMIAdapter->clearUInt32Bit(REG_CHFORMAT, SPD96_CH0);
1192 #else
1193 Miniport->CMIAdapter->clearUInt32Bit(REG_CHFORMAT, SPD96_CH1);
1194 #endif
1195 }
1196 }
1197 return STATUS_SUCCESS;
1198 }
1199
~CMiniportWaveStreamCMI(void)1200 CMiniportWaveStreamCMI::~CMiniportWaveStreamCMI(void)
1201 {
1202 PAGED_CODE();
1203
1204 DBGPRINT(("CMiniportWaveStreamCMI[%p]::~CMiniportWaveStreamCMI [streamIndex: %d]", this, streamIndex));
1205
1206 if (state != KSSTATE_STOP) {
1207 SetState(KSSTATE_STOP);
1208 }
1209
1210 #ifdef WAVERT
1211 if (Port) {
1212 Port->Release();
1213 Port = NULL;
1214 }
1215 #else
1216 if (DMAChannel) {
1217 DMAChannel->Release();
1218 DMAChannel = NULL;
1219 }
1220
1221 if (ServiceGroup) {
1222 ServiceGroup->Release();
1223 ServiceGroup = NULL;
1224 }
1225 #endif
1226
1227 Miniport->isStreamRunning[streamIndex] = false;
1228
1229 if ((streamIndex == AC3_OUT_STREAM) && Miniport->isStreamRunning[PCM_OUT_STREAM]) {
1230 KSSTATE temp = Miniport->stream[PCM_OUT_STREAM]->state;
1231 Miniport->stream[PCM_OUT_STREAM]->state = KSSTATE_STOP;
1232 Miniport->stream[PCM_OUT_STREAM]->prepareStream();
1233 Miniport->stream[PCM_OUT_STREAM]->SetState(KSSTATE_ACQUIRE);
1234 Miniport->stream[PCM_OUT_STREAM]->state = temp;
1235 Miniport->stream[PCM_OUT_STREAM]->SetState(KSSTATE_RUN_AC3);
1236 }
1237
1238 if (Miniport) {
1239 Miniport->Release();
1240 Miniport = NULL;
1241 }
1242 }
1243
NonDelegatingQueryInterface(REFIID Interface,PVOID * Object)1244 STDMETHODIMP CMiniportWaveStreamCMI::NonDelegatingQueryInterface(REFIID Interface, PVOID *Object)
1245 {
1246 PAGED_CODE();
1247 ASSERT(Object);
1248 DBGPRINT(("CMiniportWaveStreamCMI[%p]::NonDelegatingQueryInterface(%p, %p)", this, Interface, Object));
1249
1250 if (IsEqualGUIDAligned(Interface,IID_IUnknown)) {
1251 *Object = PVOID(PUNKNOWN(PMINIPORTWAVECYCLICSTREAM(this)));
1252 #ifdef WAVERT
1253 } else if (IsEqualGUIDAligned(Interface,IID_IMiniportWaveRTStream)) {
1254 *Object = PVOID(PMINIPORTWAVERTSTREAM(this));
1255 #else
1256 } else if (IsEqualGUIDAligned(Interface,IID_IMiniportWaveCyclicStream)) {
1257 *Object = PVOID(PMINIPORTWAVECYCLICSTREAM(this));
1258 #endif
1259 } else if (IsEqualGUIDAligned (Interface, IID_IDrmAudioStream)) {
1260 *Object = (PVOID)(PDRMAUDIOSTREAM(this));
1261 } else {
1262 *Object = NULL;
1263 }
1264
1265 if (*Object) {
1266 PUNKNOWN(*Object)->AddRef();
1267 return STATUS_SUCCESS;
1268 }
1269
1270 return STATUS_INVALID_PARAMETER;
1271 }
1272
1273 #ifdef WAVERT
Init(CMiniportWaveCMI * Miniport_,UInt32 streamIndex_,bool isCaptureStream_,PKSDATAFORMAT DataFormat,PPORTWAVERTSTREAM Port_)1274 NTSTATUS CMiniportWaveStreamCMI::Init(CMiniportWaveCMI* Miniport_, UInt32 streamIndex_, bool isCaptureStream_, PKSDATAFORMAT DataFormat, PPORTWAVERTSTREAM Port_)
1275 #else
1276 NTSTATUS CMiniportWaveStreamCMI::Init(CMiniportWaveCMI* Miniport_, UInt32 streamIndex_, bool isCaptureStream_, PKSDATAFORMAT DataFormat, PDMACHANNEL DMAChannel_, PSERVICEGROUP* OutServiceGroup)
1277 #endif
1278 {
1279 PAGED_CODE();
1280 ASSERT(Miniport_);
1281 ASSERT(DataFormat);
1282
1283 NTSTATUS ntStatus;
1284
1285 #ifdef WAVERT
1286 ASSERT(Port_);
1287 DBGPRINT(("CMiniportWaveStreamCMI[%p]::Init(%p, %d, %d, %p, %p)", this, Miniport_, streamIndex_, isCaptureStream_, DataFormat, Port_));
1288 Port = Port_;
1289 Port->AddRef();
1290 #else
1291 DBGPRINT(("CMiniportWaveStreamCMI[%p]::Init(%p, %d, %d, %p, %p, %p)", this, Miniport_, streamIndex_, isCaptureStream_, DataFormat, DMAChannel_, OutServiceGroup));
1292 DMAChannel = DMAChannel_;
1293 DMAChannel->AddRef();
1294 #endif
1295
1296 Miniport = Miniport_;
1297 Miniport->AddRef();
1298
1299 streamIndex = streamIndex_;
1300 isCaptureStream = isCaptureStream_;
1301 state = KSSTATE_STOP;
1302
1303 if ( (streamIndex == PCM_OUT_STREAM) || (streamIndex == AC3_OUT_STREAM) ) {
1304 channelNumber = OUT_CHANNEL;
1305 } else {
1306 channelNumber = IN_CHANNEL;
1307 }
1308
1309 #ifndef WAVERT
1310 ntStatus = PcNewServiceGroup(&ServiceGroup,NULL);
1311 if (!NT_SUCCESS(ntStatus)) {
1312 DBGPRINT(("PcNewServiceGroup() or NewMasterDmaChannel() failed"));
1313 return ntStatus;
1314 }
1315 *OutServiceGroup = ServiceGroup;
1316 ServiceGroup->AddRef();
1317 #endif
1318
1319 ntStatus = SetFormat(DataFormat);
1320 if (!NT_SUCCESS(ntStatus)) {
1321 DBGPRINT(("SetFormat() failed"));
1322 return ntStatus;
1323 }
1324
1325 Miniport->isStreamRunning[streamIndex] = true;
1326
1327 return ntStatus;
1328 }
1329
SetFormat(PKSDATAFORMAT Format)1330 NTSTATUS CMiniportWaveStreamCMI::SetFormat(PKSDATAFORMAT Format)
1331 {
1332 PAGED_CODE();
1333 DBGPRINT(("CMiniportWaveStreamCMI[%p]::SetFormat(%p)", this, Format));
1334 PWAVEFORMATEX waveFormat = PWAVEFORMATEX(Format + 1);
1335 NTSTATUS ntStatus = Miniport->validateFormat(Format, -1, isCaptureStream);
1336 if (!NT_SUCCESS(ntStatus)) {
1337 return ntStatus;
1338 }
1339 // the DAC and ADC can only run at the same sample rate simultaneously
1340 if ((streamIndex == PCM_IN_STREAM) && Miniport->isStreamRunning[PCM_OUT_STREAM]) {
1341 if (waveFormat->nSamplesPerSec != Miniport->stream[PCM_OUT_STREAM]->currentSampleRate) {
1342 return STATUS_UNSUCCESSFUL;
1343 }
1344 }
1345 if ((streamIndex == PCM_IN_STREAM) && Miniport->isStreamRunning[AC3_OUT_STREAM]) {
1346 if (waveFormat->nSamplesPerSec != Miniport->stream[AC3_OUT_STREAM]->currentSampleRate) {
1347 return STATUS_UNSUCCESSFUL;
1348 }
1349 }
1350 if ((streamIndex == PCM_OUT_STREAM) && Miniport->isStreamRunning[PCM_IN_STREAM]) {
1351 if (waveFormat->nSamplesPerSec != Miniport->stream[PCM_IN_STREAM]->currentSampleRate) {
1352 return STATUS_UNSUCCESSFUL;
1353 }
1354 }
1355 if ((streamIndex == PCM_OUT_STREAM) && Miniport->isStreamRunning[AC3_OUT_STREAM]) {
1356 return STATUS_UNSUCCESSFUL;
1357 }
1358
1359 KeWaitForSingleObject(&Miniport->mutex, Executive, KernelMode, false, NULL);
1360 currentSampleRate = waveFormat->nSamplesPerSec;
1361 currentChannelCount = waveFormat->nChannels;
1362 currentResolution = waveFormat->wBitsPerSample;
1363 enableAC3Passthru = (WAVE_FORMAT_DOLBY_AC3_SPDIF == EXTRACT_WAVEFORMATEX_ID(&Format->SubFormat)) || (WAVE_FORMAT_WMA_SPDIF == EXTRACT_WAVEFORMATEX_ID(&Format->SubFormat));
1364 KeReleaseMutex(&Miniport->mutex, false);
1365 ntStatus = prepareStream();
1366
1367 return ntStatus;
1368 }
1369
1370 // DRM crap - we're supposed to disable every digital interface here
STDMETHODIMP_(NTSTATUS)1371 STDMETHODIMP_(NTSTATUS) CMiniportWaveStreamCMI::SetContentId(ULONG contentId, PCDRMRIGHTS drmRights)
1372 {
1373 PAGED_CODE();
1374 DBGPRINT(("CMiniportWaveStreamCMI[%p]::SetContentId(%d, %p)", this, contentId, drmRights));
1375
1376 return STATUS_SUCCESS;
1377 }
1378
1379 #ifdef WAVERT
STDMETHODIMP_(NTSTATUS)1380 STDMETHODIMP_(NTSTATUS) CMiniportWaveStreamCMI::AllocateAudioBuffer(ULONG size, PMDL *userModeBuffer, ULONG *bufferSize, ULONG *bufferOffset, MEMORY_CACHING_TYPE *cacheType)
1381 {
1382 PAGED_CODE();
1383
1384 PHYSICAL_ADDRESS low;
1385 PHYSICAL_ADDRESS high;
1386 DBGPRINT(("CMiniportWaveStreamCMI[%p]::AllocateAudioBuffer(0x%x, %p, %p, %p, %p)", this, size, userModeBuffer, bufferSize, bufferOffset, cacheType));
1387
1388 if (size <= size % (currentChannelCount * 2)) {
1389 return STATUS_UNSUCCESSFUL;
1390 }
1391 size -= size % (currentChannelCount * 2);
1392
1393 if (size == 0) {
1394 return STATUS_UNSUCCESSFUL;
1395 }
1396
1397 low.HighPart = 0; low.LowPart = 0;
1398 high.HighPart = 0; high.LowPart = MAXULONG;
1399 if (size <= 4096) {
1400 audioBufferMDL = Port->AllocatePagesForMdl(high, size);
1401 } else {
1402 audioBufferMDL = Port->AllocateContiguousPagesForMdl(low, high, size);
1403 }
1404 if (!audioBufferMDL) {
1405 DBGPRINT(("AllocateContiguousPagesForMdl()/AllocatePagesForMdl() failed (size: 0x%x)", size));
1406 return STATUS_INSUFFICIENT_RESOURCES;
1407 }
1408
1409 dmaAddress = Port->GetPhysicalPageAddress(audioBufferMDL, 0).LowPart;
1410 dmaMemorySize = size;
1411
1412 *userModeBuffer = audioBufferMDL;
1413 *bufferSize = size;
1414 *bufferOffset = 0;
1415 *cacheType = MmCached;
1416
1417 return STATUS_SUCCESS;
1418 }
1419
1420
STDMETHODIMP_(VOID)1421 STDMETHODIMP_(VOID) CMiniportWaveStreamCMI::FreeAudioBuffer(PMDL Mdl, ULONG Size)
1422 {
1423 PAGED_CODE();
1424 DBGPRINT(("CMiniportWaveStreamCMI[%p]::FreeAudioBuffer(%p, %x)", this, Mdl, Size));
1425
1426 Port->FreePagesFromMdl(Mdl);
1427 audioBufferMDL = NULL;
1428 dmaAddress = 0;
1429 dmaMemorySize = 0;
1430 }
1431
STDMETHODIMP_(void)1432 STDMETHODIMP_(void) CMiniportWaveStreamCMI::GetHWLatency(PKSRTAUDIO_HWLATENCY hwLatency)
1433 {
1434 PAGED_CODE();
1435 DBGPRINT(("CMiniportWaveStreamCMI[%p]::GetHWLatency(%p)", this, hwLatency));
1436 hwLatency->FifoSize = 32;
1437 hwLatency->ChipsetDelay = 0;
1438 hwLatency->CodecDelay = 4;
1439 }
1440
STDMETHODIMP_(NTSTATUS)1441 STDMETHODIMP_(NTSTATUS) CMiniportWaveStreamCMI::GetPositionRegister(PKSRTAUDIO_HWREGISTER hwRegister)
1442 {
1443 PAGED_CODE();
1444 DBGPRINT(("CMiniportWaveStreamCMI[%p]::GetPositionRegister(%p)", this, hwRegister));
1445
1446 return STATUS_UNSUCCESSFUL;
1447 }
1448
STDMETHODIMP_(NTSTATUS)1449 STDMETHODIMP_(NTSTATUS) CMiniportWaveStreamCMI::GetClockRegister(PKSRTAUDIO_HWREGISTER hwRegister)
1450 {
1451 PAGED_CODE();
1452 DBGPRINT(("CMiniportWaveStreamCMI[%p]::GetClockRegister(%p)", this, hwRegister));
1453
1454 return STATUS_UNSUCCESSFUL;
1455 }
1456
1457 #endif // WAVERT
1458
1459 /*
1460 ** non-paged code below
1461 */
1462 #ifdef _MSC_VER
1463 #pragma code_seg()
1464 #endif
1465
SetState(KSSTATE NewState)1466 STDMETHODIMP CMiniportWaveStreamCMI::SetState(KSSTATE NewState)
1467 {
1468 DBGPRINT(("CMiniportWaveStreamCMI[%p]::SetState(%d) [streamIndex: %d, channelNumber: %d]", this, NewState, streamIndex, channelNumber));
1469
1470 UInt32 inthld, chen, reset, pause;
1471 UInt8 reg;
1472
1473 inthld = EN_CH0_INT << channelNumber;
1474 chen = EN_CH0 << channelNumber;
1475 reset = RST_CH0 << channelNumber;
1476 pause = PAUSE_CH0 << channelNumber;
1477
1478 NTSTATUS ntStatus = STATUS_SUCCESS;
1479
1480 if ((streamIndex == PCM_OUT_STREAM) && Miniport->isStreamRunning[AC3_OUT_STREAM]) {
1481 return STATUS_INVALID_PARAMETER;
1482 }
1483
1484 if (NewState == KSSTATE_RUN_AC3) {
1485 NewState = state;
1486 state = KSSTATE_STOP;
1487 }
1488
1489 // STOP -> ACQUIRE -> PAUSE -> PLAY -> PAUSE -> ACQUIRE -> STOP
1490 if (state != NewState) {
1491 switch (NewState) {
1492 case KSSTATE_ACQUIRE:
1493 DBGPRINT(("---KSSTATE_ACQUIRE: previous state: %d", state));
1494 if (state == KSSTATE_PAUSE) {
1495 break;
1496 }
1497
1498 #ifdef WAVERT
1499 if ((dmaMemorySize == 0) || (dmaAddress == 0)) {
1500 return STATUS_UNSUCCESSFUL;
1501 }
1502 dmaSize = (dmaMemorySize / (2 * (currentResolution >> 3)) );
1503 periodSize = dmaSize;
1504 DBGPRINT(("---dmaAddress: %x, dmaMemorySize: %x, dmaSize: %x", dmaAddress, dmaMemorySize, dmaSize));
1505 #else
1506 if (currentResolution == 32) {
1507 dmaSize = (DMAChannel->BufferSize() / (2 * (32 >> 3)) );
1508 } else {
1509 dmaSize = (DMAChannel->BufferSize() / (2 * (currentResolution >> 3)) );
1510 }
1511 #endif
1512 DBGPRINT(("---SampleRate: %d, Resolution: %d, Channels: %d", currentSampleRate, currentResolution, currentChannelCount));
1513
1514 if (periodSize > dmaSize) {
1515 periodSize = dmaSize;
1516 }
1517
1518 // set address of the DMA buffer
1519 KeWaitForSingleObject(&Miniport->mutex, Executive, KernelMode, FALSE, NULL);
1520 reg = channelNumber ? REG_CH1_FRAME1 : REG_CH0_FRAME1;
1521 #ifdef WAVERT
1522 Miniport->CMIAdapter->writeUInt32(reg, dmaAddress);
1523 #else
1524 Miniport->CMIAdapter->writeUInt32(reg, DMAChannel->PhysicalAddress().u.LowPart);
1525 DBGPRINT(("---DMA Address: HighPart: 0x%08X LowPart: 0x%08X", DMAChannel->PhysicalAddress().u.HighPart, DMAChannel->PhysicalAddress().u.LowPart));
1526 #endif
1527 // count of samples
1528 reg = channelNumber ? REG_CH1_FRAME2 : REG_CH0_FRAME2;
1529 Miniport->CMIAdapter->writeUInt16(reg, dmaSize-1);
1530 Miniport->CMIAdapter->writeUInt16(reg + 2, periodSize-1);
1531 DBGPRINT(("---DMA Size: 0x%04X, Period Size: 0x%04X, enableSPDIFIn: %d", dmaSize, periodSize, Miniport->cm->enableSPDIFIn));
1532 if (isCaptureStream) {
1533 if (Miniport->cm->enableSPDIFIn) {
1534 #if OUT_CHANNEL==0
1535 Miniport->CMIAdapter->setUInt32Bit(REG_FUNCTRL1, SPDF_1);
1536 #else
1537 Miniport->CMIAdapter->setUInt32Bit(REG_FUNCTRL1, SPDF_0);
1538 #endif
1539 } else {
1540 #if OUT_CHANNEL==0
1541 Miniport->CMIAdapter->clearUInt32Bit(REG_FUNCTRL1, SPDF_1);
1542 #else
1543 Miniport->CMIAdapter->clearUInt32Bit(REG_FUNCTRL1, SPDF_0);
1544 #endif
1545 }
1546 }
1547 KeReleaseMutex(&Miniport->mutex, false);
1548 break;
1549
1550 case KSSTATE_PAUSE:
1551 DBGPRINT(("---KSSTATE_PAUSE: previous state: %d", state));
1552 if (state == KSSTATE_RUN) {
1553 KeWaitForSingleObject(&Miniport->mutex, Executive, KernelMode, false, NULL);
1554 Miniport->cm->regFUNCTRL0 |= pause;
1555 Miniport->CMIAdapter->writeUInt32(REG_FUNCTRL0, Miniport->cm->regFUNCTRL0);
1556 KeReleaseMutex(&Miniport->mutex, FALSE);
1557 }
1558 if (state == KSSTATE_STOP) {
1559 KeWaitForSingleObject(&Miniport->mutex, Executive, KernelMode, false, NULL);
1560 Miniport->cm->regFUNCTRL0 &= ~pause;
1561 Miniport->CMIAdapter->writeUInt32(REG_FUNCTRL0, Miniport->cm->regFUNCTRL0);
1562 KeReleaseMutex(&Miniport->mutex, false);
1563 }
1564 break;
1565
1566 case KSSTATE_RUN:
1567 DBGPRINT(("---KSSTATE_RUN: previous state: %d", state));
1568
1569 KeWaitForSingleObject(&Miniport->mutex, Executive, KernelMode, FALSE, NULL);
1570 // set interrupt
1571 Miniport->CMIAdapter->setUInt32Bit(REG_INTHLDCLR, inthld);
1572 Miniport->cm->regFUNCTRL0 &= ~pause;
1573 Miniport->cm->regFUNCTRL0 |= chen;
1574 // and enable the channel
1575 Miniport->CMIAdapter->writeUInt32(REG_FUNCTRL0, Miniport->cm->regFUNCTRL0);
1576
1577 DBGPRINT(("---FUNCTRL0: 0x%08X", Miniport->cm->regFUNCTRL0));
1578 DBGPRINT(("---FUNCTRL1: 0x%08X", Miniport->CMIAdapter->readUInt32(REG_FUNCTRL1)));
1579 DBGPRINT(("---CHFORMAT: 0x%08X", Miniport->CMIAdapter->readUInt32(REG_CHFORMAT)));
1580 DBGPRINT(("---LEGACYCTRL: 0x%08X", Miniport->CMIAdapter->readUInt32(REG_LEGACY)));
1581 DBGPRINT(("---MISCCTRL: 0x%08X", Miniport->CMIAdapter->readUInt32(REG_MISCCTRL)));
1582 DBGPRINT(("---MIX1: 0x%02X", Miniport->CMIAdapter->readUInt8(REG_MIXER1)));
1583 DBGPRINT(("---MIX2: 0x%02X", Miniport->CMIAdapter->readUInt8(REG_MIXER2)));
1584 DBGPRINT(("---MIX3: 0x%02X", Miniport->CMIAdapter->readUInt8(REG_MIXER3)));
1585
1586 KeReleaseMutex(&Miniport->mutex, false);
1587 break;
1588
1589 case KSSTATE_STOP_AC3:
1590 case KSSTATE_STOP:
1591 DBGPRINT(("---KSSTATE_STOP: previous state: %d", state));
1592 KeWaitForSingleObject(&Miniport->mutex, Executive, KernelMode, FALSE, NULL);
1593 // clear interrupt
1594 Miniport->CMIAdapter->clearUInt32Bit(REG_INTHLDCLR, inthld);
1595 Miniport->cm->regFUNCTRL0 &= ~chen;
1596 // reset
1597 Miniport->CMIAdapter->writeUInt32(REG_FUNCTRL0, Miniport->cm->regFUNCTRL0 | reset);
1598 Miniport->CMIAdapter->writeUInt32(REG_FUNCTRL0, Miniport->cm->regFUNCTRL0 & ~reset);
1599 if (isCaptureStream && (Miniport->cm->enableSPDIFIn)) {
1600 #if OUT_CHANNEL==0
1601 Miniport->CMIAdapter->clearUInt32Bit(REG_FUNCTRL1, SPDF_1);
1602 #else
1603 Miniport->CMIAdapter->clearUInt32Bit(REG_FUNCTRL1, SPDF_0);
1604 #endif
1605 }
1606 KeReleaseMutex(&Miniport->mutex, FALSE);
1607 break;
1608 }
1609 if (NewState != KSSTATE_STOP_AC3) {
1610 state = NewState;
1611 }
1612 }
1613 return ntStatus;
1614 }
1615
1616 #ifdef WAVERT
1617
GetPosition(PKSAUDIO_POSITION Position)1618 STDMETHODIMP CMiniportWaveStreamCMI::GetPosition(PKSAUDIO_POSITION Position)
1619 {
1620 ASSERT(Position);
1621
1622 UInt32 reg;
1623
1624 if ((state == KSSTATE_RUN) && (dmaAddress)) {
1625 reg = (channelNumber) ? REG_CH1_FRAME1 : REG_CH0_FRAME1;
1626 Position->PlayOffset = Miniport->CMIAdapter->readUInt32(reg) - dmaAddress;
1627 Position->WriteOffset = Position->PlayOffset + currentChannelCount * 2 * 8;
1628 } else {
1629 Position->PlayOffset = 0;
1630 Position->WriteOffset = 0;
1631 }
1632
1633 return STATUS_SUCCESS;
1634 }
1635
1636 #else //WaveCyclic
1637
GetPosition(PULONG Position)1638 STDMETHODIMP CMiniportWaveStreamCMI::GetPosition(PULONG Position)
1639 {
1640 ASSERT(Position);
1641
1642 UInt32 reg;
1643
1644 if ((DMAChannel) && (state == KSSTATE_RUN)) {
1645 #if 0
1646 // this implementation messes with SPDIF-in recording
1647 reg = (channelNumber) ? REG_CH1_FRAME2 : REG_CH0_FRAME2;
1648 *Position = dmaSize - (Miniport->CMIAdapter->readUInt16(reg)-1);
1649 *Position *= 2 * (currentResolution >> 3);
1650 #else
1651 reg = (channelNumber) ? REG_CH1_FRAME1 : REG_CH0_FRAME1;
1652 *Position = Miniport->CMIAdapter->readUInt32(reg);
1653 if (*Position > DMAChannel->PhysicalAddress().u.LowPart) {
1654 *Position -= DMAChannel->PhysicalAddress().u.LowPart;
1655 } else {
1656 *Position = 0;
1657 }
1658 #endif
1659 } else {
1660 *Position = 0;
1661 }
1662
1663 return STATUS_SUCCESS;
1664 }
1665
STDMETHODIMP_(ULONG)1666 STDMETHODIMP_(ULONG) CMiniportWaveStreamCMI::SetNotificationFreq(ULONG Interval, PULONG FramingSize)
1667 {
1668 Miniport->notificationInterval = Interval;
1669
1670 if (state == KSSTATE_RUN) {
1671 return 0;
1672 }
1673 // periodSize [sample] = interval [ms] * sample rate [Hz] * 1e-3 [milli]
1674 periodSize = Interval * currentSampleRate / 1000;
1675 // FramingSize [byte] = periodSize [sample] * #Channels * resolution [byte];
1676 *FramingSize = periodSize * currentChannelCount * (currentResolution >> 3);
1677
1678 KeWaitForSingleObject(&Miniport->mutex, Executive, KernelMode, FALSE, NULL);
1679 Miniport->CMIAdapter->writeUInt16((channelNumber ? REG_CH1_FRAME2 : REG_CH0_FRAME2) + 2, periodSize-1);
1680 KeReleaseMutex(&Miniport->mutex, FALSE);
1681
1682 DBGPRINT(("periodSize: %x, FramingSize: %x", periodSize, *FramingSize));
1683 return Interval;
1684 }
1685
NormalizePhysicalPosition(PLONGLONG PhysicalPosition)1686 STDMETHODIMP CMiniportWaveStreamCMI::NormalizePhysicalPosition(PLONGLONG PhysicalPosition)
1687 {
1688 // time_pos [ns] = byte_pos [byte] / (1e-9 [nano] * #Channels * resolution [byte] * sample rate [Hz])
1689 *PhysicalPosition = (*PhysicalPosition * 10000000L) / (currentChannelCount * (currentResolution >> 3) * currentSampleRate);
1690 return STATUS_SUCCESS;
1691 }
1692
1693
STDMETHODIMP_(void)1694 STDMETHODIMP_(void) CMiniportWaveStreamCMI::Silence(PVOID Buffer, ULONG ByteCount)
1695 {
1696 RtlFillMemory(Buffer, ByteCount, 0x00);
1697 }
1698
1699 #endif //WAVERT
1700
STDMETHODIMP_(void)1701 STDMETHODIMP_(void) CMiniportWaveCMI::ServiceWaveISR(UInt32 streamIndex)
1702 {
1703 #ifndef WAVERT
1704 if ((streamIndex == PCM_OUT_STREAM) && isStreamRunning[AC3_OUT_STREAM]) {
1705 streamIndex = AC3_OUT_STREAM;
1706 }
1707 if (Port && stream[streamIndex]->ServiceGroup) {
1708 Port->Notify(stream[streamIndex]->ServiceGroup);
1709 }
1710 #endif
1711 }
1712