[KS]
[reactos.git] / reactos / drivers / wdm / audio / drivers / CMIDriver / mintopo.cpp
1 /*
2 Copyright (c) 2006-2007 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 "limits.h"
29 #include "mintopo.hpp"
30 #include "mintopotables.hpp"
31 #define NTSTRSAFE_LIB //for Windows 2000 compatibility
32 #include "NtStrsafe.h"
33
34 #pragma code_seg("PAGE")
35
36 const GUID KSPROPSETID_CMI = {0x2B81CDBB, 0xEE6C, 0x4ECC, {0x8A, 0xA5, 0x9A, 0x18, 0x8B, 0x02, 0x3D, 0xFF}};
37
38 HRESULT NTAPI CreateMiniportTopologyCMI(PUNKNOWN* Unknown, REFCLSID, PUNKNOWN UnknownOuter, POOL_TYPE PoolType)
39 {
40 //PAGED_CODE();
41 //ASSERT(Unknown);
42 STD_CREATE_BODY_(CCMITopology,Unknown,UnknownOuter,PoolType,PMINIPORTTOPOLOGY);
43 }
44
45 STDMETHODIMP CCMITopology::QueryInterface(REFIID Interface, PVOID* Object)
46 {
47 //PAGED_CODE();
48 //ASSERT(Object);
49 DBGPRINT(("CCMITopology::NonDelegatingQueryInterface"));
50
51 if (IsEqualGUIDAligned(Interface, IID_IUnknown)) {
52 *Object = PVOID(PUNKNOWN(PMINIPORTTOPOLOGY(this)));
53 } else if (IsEqualGUIDAligned(Interface,IID_IMiniport)) {
54 *Object = PVOID(PMINIPORT(this));
55 } else if (IsEqualGUIDAligned(Interface,IID_IMiniportTopology)) {
56 *Object = PVOID(PMINIPORTTOPOLOGY(this));
57 } else if (IsEqualGUIDAligned (Interface, IID_ICMITopolgy)) {
58 *Object = (PVOID)(PMINIPORTTOPOLOGY)this;
59 } else {
60 *Object = NULL;
61 }
62
63 if (*Object) {
64 PUNKNOWN(*Object)->AddRef();
65 return STATUS_SUCCESS;
66 }
67
68 return STATUS_INVALID_PARAMETER;
69 }
70
71 CCMITopology::~CCMITopology()
72 {
73 //PAGED_CODE();
74
75 DBGPRINT(("CCMITopology::~CCMITopology"));
76
77 storeMixerSettingsToRegistry(); //or not. during system shutdown, this doesn't seem to work.
78 cm->TopoMiniport = NULL;
79
80 if (CMIAdapter) {
81 CMIAdapter->Release();
82 }
83 }
84
85 STDMETHODIMP CCMITopology::Init(PUNKNOWN UnknownAdapter, PRESOURCELIST ResourceList, PPORTTOPOLOGY Port)
86 {
87 //PAGED_CODE();
88 //ASSERT(UnknownAdapter);
89 //ASSERT(Port);
90 DBGPRINT(("CCMITopology::Init"));
91
92 NTSTATUS ntStatus = UnknownAdapter->QueryInterface(IID_ICMIAdapter, (PVOID *)&CMIAdapter);
93
94 if (!NT_SUCCESS(ntStatus)) {
95 DBGPRINT(("UnknownAdapter->QueryInterface() failed"));
96 return STATUS_INVALID_PARAMETER;
97 }
98
99 CMIAdapter->resetMixer();
100 auxVolumeRegister = CMIAdapter->readUInt8(REG_MIXER3);
101 micVolumeRegister = CMIAdapter->readUInt8(REG_MIXER2);
102 functrl1Register = 0;
103 chformatRegister = 0;
104 legacyRegister = 0;
105 miscctrlRegister = 0;
106
107 cm = CMIAdapter->getCMI8738Info();
108 cm->TopoMiniport = this; //this is not really nice
109 loadMixerSettingsFromRegistry();
110
111 return STATUS_SUCCESS;
112 }
113
114 STDMETHODIMP CCMITopology::GetDescription(PPCFILTER_DESCRIPTOR* OutFilterDescriptor)
115 {
116 //PAGED_CODE();
117 //ASSERT(OutFilterDescriptor);
118 DBGPRINT(("CCMITopology::GetDescription"));
119
120 *OutFilterDescriptor = &MiniportFilterDescriptor;
121
122 return STATUS_SUCCESS;
123 }
124
125 STDMETHODIMP CCMITopology::loadMixerSettingsFromRegistry()
126 {
127 //PAGED_CODE();
128 DBGPRINT(("CCMITopology::loadMixerSettingsFromRegistry"));
129
130 PREGISTRYKEY DriverKey;
131 PREGISTRYKEY SettingsKey;
132 UNICODE_STRING KeyName;
133 PCPROPERTY_REQUEST PropertyRequest;
134 PCPROPERTY_ITEM PropertyItem;
135 DWORD Channel;
136 PVOID KeyInfo;
137 ULONG ResultLength;
138 WCHAR buffer[128];
139
140 if ((!CMIAdapter) || (!(CMIAdapter->getDeviceObject()))) {
141 DBGPRINT(("CMIAdapter->getDeviceObject() failed"));
142 return STATUS_UNSUCCESSFUL;
143 }
144
145 settingsLoaded = FALSE;
146
147 NTSTATUS ntStatus = PcNewRegistryKey(&DriverKey, NULL, DriverRegistryKey, KEY_ALL_ACCESS, CMIAdapter->getDeviceObject(), NULL, NULL, 0, NULL);
148
149 if(!NT_SUCCESS(ntStatus)) {
150 DBGPRINT(("PcNewRegistryKey() failed"));
151 return STATUS_UNSUCCESSFUL;
152 }
153
154 RtlInitUnicodeString(&KeyName, L"Settings");
155
156 ntStatus = DriverKey->NewSubKey(&SettingsKey, NULL, KEY_ALL_ACCESS, &KeyName, REG_OPTION_NON_VOLATILE, NULL);
157 if(!NT_SUCCESS(ntStatus)) {
158 DBGPRINT(("DriverKey->NewSubKey() failed"));
159 return STATUS_UNSUCCESSFUL;
160 }
161
162 KeyInfo = ExAllocatePoolWithTag(PagedPool, sizeof(KEY_VALUE_PARTIAL_INFORMATION) + sizeof(DWORD), 'dbrt');
163 if(KeyInfo == NULL) {
164 DBGPRINT(("ExAllocatePoolWithTag() failed"));
165 return STATUS_UNSUCCESSFUL;
166 }
167
168 PropertyRequest.MajorTarget = this;
169 PropertyRequest.Verb = KSPROPERTY_TYPE_SET;
170 PropertyRequest.Instance = &Channel;
171 PropertyRequest.InstanceSize = sizeof(DWORD);
172 PropertyRequest.Value = &(PKEY_VALUE_PARTIAL_INFORMATION(KeyInfo)->Data);
173 PropertyRequest.ValueSize = sizeof(DWORD);
174 PropertyRequest.PropertyItem = &PropertyItem;
175
176 for (int i=0;i < SIZEOF_ARRAY(TopologyNodes); i++) {
177 PropertyRequest.Node = i;
178
179 Channel = CHAN_LEFT;
180 ntStatus = RtlStringCbPrintfW(buffer, sizeof(buffer), L"Node%dLeft", i);
181 if (!NT_SUCCESS(ntStatus)) {
182 DBGPRINT(("RtlStringCbPrintfW() failed"));
183 }
184 RtlInitUnicodeString(&KeyName, buffer);
185 ntStatus = SettingsKey->QueryValueKey(&KeyName, KeyValuePartialInformation, KeyInfo, sizeof(KEY_VALUE_PARTIAL_INFORMATION) + sizeof(DWORD), &ResultLength);
186 if (NT_SUCCESS(ntStatus)) {
187 if(PKEY_VALUE_PARTIAL_INFORMATION(KeyInfo)->DataLength == sizeof(DWORD)) {
188 if (IsEqualGUIDAligned(*(TopologyNodes[i].Type), KSNODETYPE_VOLUME)) {
189 PropertyItem.Id = KSPROPERTY_AUDIO_VOLUMELEVEL;
190 PropertyHandler_Level(&PropertyRequest);
191 }
192 if (IsEqualGUIDAligned(*(TopologyNodes[i].Type), KSNODETYPE_MUTE)) {
193 PropertyItem.Id = KSPROPERTY_AUDIO_MUTE;
194 PropertyHandler_OnOff(&PropertyRequest);
195 }
196 if (IsEqualGUIDAligned(*(TopologyNodes[i].Type), KSNODETYPE_LOUDNESS)) {
197 PropertyItem.Id = KSPROPERTY_AUDIO_LOUDNESS;
198 PropertyHandler_OnOff(&PropertyRequest);
199 }
200 }
201 } else {
202 // default values
203 if (i == KSNODE_TOPO_IEC_OUT) {
204 PropertyItem.Id = KSPROPERTY_AUDIO_LOUDNESS;
205 *(PBOOL(PropertyRequest.Value)) = true;
206 PropertyHandler_OnOff(&PropertyRequest);
207 }
208 if (i == KSNODE_TOPO_WAVEOUT_MUTE_IN) {
209 PropertyItem.Id = KSPROPERTY_AUDIO_MUTE;
210 *(PBOOL(PropertyRequest.Value)) = true;
211 PropertyHandler_OnOff(&PropertyRequest);
212 }
213 if (i == KSNODE_TOPO_CENTER2MIC) {
214 PropertyItem.Id = KSPROPERTY_AUDIO_LOUDNESS;
215 *(PBOOL(PropertyRequest.Value)) = false;
216 PropertyHandler_OnOff(&PropertyRequest);
217 }
218 }
219
220 Channel = CHAN_RIGHT;
221 ntStatus = RtlStringCbPrintfW(buffer, sizeof(buffer), L"Node%dRight", i);
222 if (!NT_SUCCESS(ntStatus)) {
223 DBGPRINT(("RtlStringCbPrintfW() failed"));
224 }
225 RtlInitUnicodeString(&KeyName, buffer);
226 ntStatus = SettingsKey->QueryValueKey(&KeyName, KeyValuePartialInformation, KeyInfo, sizeof(KEY_VALUE_PARTIAL_INFORMATION) + sizeof(DWORD), &ResultLength);
227 if (NT_SUCCESS(ntStatus)) {
228 if(PKEY_VALUE_PARTIAL_INFORMATION(KeyInfo)->DataLength == sizeof(DWORD)) {
229 if (IsEqualGUIDAligned(*(TopologyNodes[i].Type), KSNODETYPE_VOLUME)) {
230 PropertyItem.Id = KSPROPERTY_AUDIO_VOLUMELEVEL;
231 PropertyHandler_Level(&PropertyRequest);
232 }
233 if (IsEqualGUIDAligned(*(TopologyNodes[i].Type), KSNODETYPE_MUTE)) {
234 PropertyItem.Id = KSPROPERTY_AUDIO_MUTE;
235 PropertyHandler_OnOff(&PropertyRequest);
236 }
237 if (IsEqualGUIDAligned(*(TopologyNodes[i].Type), KSNODETYPE_LOUDNESS)) {
238 PropertyItem.Id = KSPROPERTY_AUDIO_LOUDNESS;
239 PropertyHandler_OnOff(&PropertyRequest);
240 }
241 }
242 } else {
243 if (i == KSNODE_TOPO_WAVEOUT_MUTE_IN) {
244 PropertyItem.Id = KSPROPERTY_AUDIO_MUTE;
245 *(PBOOL(PropertyRequest.Value)) = true;
246 PropertyHandler_OnOff(&PropertyRequest);
247 }
248 }
249
250 }
251 RtlInitUnicodeString(&KeyName, L"FormatMask");
252 ntStatus = SettingsKey->QueryValueKey(&KeyName, KeyValuePartialInformation, KeyInfo, sizeof(KEY_VALUE_PARTIAL_INFORMATION) + sizeof(DWORD), &ResultLength);
253 if (NT_SUCCESS (ntStatus)) {
254 PKEY_VALUE_PARTIAL_INFORMATION PartialInfo = (PKEY_VALUE_PARTIAL_INFORMATION)KeyInfo;
255 if (PartialInfo->DataLength == sizeof(DWORD)) {
256 cm->formatMask = (*(PLONG)PartialInfo->Data);
257 }
258 } else {
259 cm->formatMask = 0xFFFFFFFF;
260 }
261
262 ExFreePoolWithTag (KeyInfo,'dbrt');
263
264 SettingsKey->Release();
265 DriverKey->Release();
266
267 settingsLoaded = TRUE;
268
269 return STATUS_SUCCESS;
270 }
271
272 STDMETHODIMP CCMITopology::storeMixerSettingsToRegistry()
273 {
274 //PAGED_CODE();
275 DBGPRINT(("CCMITopology::storeMixerSettingsToRegistry"));
276
277 PREGISTRYKEY DriverKey;
278 PREGISTRYKEY SettingsKey;
279 UNICODE_STRING KeyName;
280 PCPROPERTY_REQUEST PropertyRequest;
281 PCPROPERTY_ITEM PropertyItem;
282 DWORD Value,Channel;
283 WCHAR buffer[128];
284
285 if ((!CMIAdapter) || (!(CMIAdapter->getDeviceObject()))) {
286 return STATUS_UNSUCCESSFUL;
287 }
288
289 NTSTATUS ntStatus = PcNewRegistryKey(&DriverKey, NULL, DriverRegistryKey, KEY_ALL_ACCESS, CMIAdapter->getDeviceObject(), NULL, NULL, 0, NULL);
290
291 if(!NT_SUCCESS(ntStatus)) {
292 DBGPRINT(("PcNewRegistryKey() failed"));
293 return STATUS_UNSUCCESSFUL;
294 }
295
296 RtlInitUnicodeString(&KeyName, L"Settings");
297
298 ntStatus = DriverKey->NewSubKey(&SettingsKey, NULL, KEY_ALL_ACCESS, &KeyName, REG_OPTION_NON_VOLATILE, NULL);
299
300 if(!NT_SUCCESS(ntStatus)) {
301 DBGPRINT(("DriverKey->NewSubKey() failed"));
302 return STATUS_UNSUCCESSFUL;
303 }
304
305 PropertyRequest.MajorTarget = this;
306 PropertyRequest.Verb = KSPROPERTY_TYPE_GET;
307 PropertyRequest.Instance = &Channel;
308 PropertyRequest.InstanceSize = sizeof(DWORD);
309 PropertyRequest.Value = &Value;
310 PropertyRequest.ValueSize = sizeof(DWORD);
311 PropertyRequest.PropertyItem = &PropertyItem;
312
313 for (int i=0;i < SIZEOF_ARRAY(TopologyNodes); i++) {
314 PropertyRequest.Node = i;
315 if (IsEqualGUIDAligned(*(TopologyNodes[i].Type), KSNODETYPE_VOLUME)) {
316 PropertyRequest.Node = i;
317 PropertyItem.Id = KSPROPERTY_AUDIO_VOLUMELEVEL;
318
319 ntStatus = RtlStringCbPrintfW(buffer, sizeof(buffer), L"Node%dLeft", i);
320 if (!NT_SUCCESS(ntStatus)) {
321 DBGPRINT(("RtlStringCbPrintfW() failed"));
322 }
323 RtlInitUnicodeString(&KeyName, buffer);
324 Channel = CHAN_LEFT;
325 ntStatus = PropertyHandler_Level(&PropertyRequest);
326 if (NT_SUCCESS(ntStatus)) {
327 ntStatus = SettingsKey->SetValueKey(&KeyName, REG_DWORD, PVOID(&Value), sizeof(DWORD));
328 if(!NT_SUCCESS(ntStatus)) {
329 DBGPRINT(("SetValueKey() failed"));
330 break;
331 }
332 }
333
334 ntStatus = RtlStringCbPrintfW(buffer, sizeof(buffer), L"Node%dRight", i);
335 if (!NT_SUCCESS(ntStatus)) {
336 DBGPRINT(("RtlStringCbPrintfW() failed"));
337 }
338 RtlInitUnicodeString(&KeyName, buffer);
339 Channel = CHAN_RIGHT;
340 ntStatus = PropertyHandler_Level(&PropertyRequest);
341 if (NT_SUCCESS(ntStatus)) {
342 ntStatus = SettingsKey->SetValueKey(&KeyName, REG_DWORD, PVOID(&Value), sizeof(DWORD));
343 if(!NT_SUCCESS(ntStatus)) {
344 DBGPRINT(("SetValueKey() failed"));
345 break;
346 }
347 }
348
349 }
350 if (IsEqualGUIDAligned(*(TopologyNodes[i].Type), KSNODETYPE_MUTE)) {
351 PropertyItem.Id = KSPROPERTY_AUDIO_MUTE;
352 PropertyHandler_OnOff(&PropertyRequest);
353
354 ntStatus = RtlStringCbPrintfW(buffer, sizeof(buffer), L"Node%dLeft", i);
355 if (!NT_SUCCESS(ntStatus)) {
356 DBGPRINT(("RtlStringCbPrintfW() failed"));
357 }
358 RtlInitUnicodeString(&KeyName, buffer);
359 Channel = CHAN_LEFT;
360 ntStatus = PropertyHandler_OnOff(&PropertyRequest);
361 if (NT_SUCCESS(ntStatus)) {
362 ntStatus = SettingsKey->SetValueKey(&KeyName, REG_DWORD, PVOID(&Value), sizeof(DWORD));
363 if(!NT_SUCCESS(ntStatus)) {
364 DBGPRINT(("SetValueKey() failed"));
365 break;
366 }
367 }
368
369 ntStatus = RtlStringCbPrintfW(buffer, sizeof(buffer), L"Node%dRight", i);
370 if (!NT_SUCCESS(ntStatus)) {
371 DBGPRINT(("RtlStringCbPrintfW() failed"));
372 }
373 RtlInitUnicodeString(&KeyName, buffer);
374 Channel = CHAN_RIGHT;
375 ntStatus = PropertyHandler_OnOff(&PropertyRequest);
376 if (NT_SUCCESS(ntStatus)) {
377 ntStatus = SettingsKey->SetValueKey(&KeyName, REG_DWORD, PVOID(&Value), sizeof(DWORD));
378 if(!NT_SUCCESS(ntStatus)) {
379 DBGPRINT(("SetValueKey() failed"));
380 break;
381 }
382 }
383 }
384 if (IsEqualGUIDAligned(*(TopologyNodes[i].Type), KSNODETYPE_LOUDNESS)) {
385 PropertyItem.Id = KSPROPERTY_AUDIO_LOUDNESS;
386 PropertyHandler_OnOff(&PropertyRequest);
387
388 ntStatus = RtlStringCbPrintfW(buffer, sizeof(buffer), L"Node%dLeft", i);
389 if (!NT_SUCCESS(ntStatus)) {
390 DBGPRINT(("RtlStringCbPrintfW() failed"));
391 }
392 RtlInitUnicodeString(&KeyName, buffer);
393 Channel = CHAN_LEFT;
394 ntStatus = PropertyHandler_OnOff(&PropertyRequest);
395 if (NT_SUCCESS(ntStatus)) {
396 ntStatus = SettingsKey->SetValueKey(&KeyName, REG_DWORD, PVOID(&Value), sizeof(DWORD));
397 if(!NT_SUCCESS(ntStatus)) {
398 DBGPRINT(("SetValueKey() failed"));
399 break;
400 }
401 }
402
403 ntStatus = RtlStringCbPrintfW(buffer, sizeof(buffer), L"Node%dRight", i);
404 if (!NT_SUCCESS(ntStatus)) {
405 DBGPRINT(("RtlStringCbPrintfW() failed"));
406 }
407 RtlInitUnicodeString(&KeyName, buffer);
408 Channel = CHAN_RIGHT;
409 ntStatus = PropertyHandler_OnOff(&PropertyRequest);
410 if (NT_SUCCESS(ntStatus)) {
411 ntStatus = SettingsKey->SetValueKey(&KeyName, REG_DWORD, PVOID(&Value), sizeof(DWORD));
412 if(!NT_SUCCESS(ntStatus)) {
413 DBGPRINT(("SetValueKey() failed"));
414 break;
415 }
416 }
417 }
418 }
419 Value = cm->formatMask;
420 RtlInitUnicodeString(&KeyName, L"FormatMask");
421 ntStatus = SettingsKey->SetValueKey(&KeyName, REG_DWORD, PVOID(&Value), sizeof(DWORD));
422 if (!NT_SUCCESS(ntStatus)) {
423 DBGPRINT(("SetValueKey() failed"));
424 }
425
426 SettingsKey->Release();
427 DriverKey->Release();
428
429 return STATUS_SUCCESS;
430 }
431
432 STDMETHODIMP CCMITopology::loadMixerSettingsFromMemory()
433 {
434 //PAGED_CODE();
435 DBGPRINT(("CCMITopology::loadMixerSettingsFromMemory"));
436
437 CMIAdapter->resetMixer();
438 CMIAdapter->loadSBMixerFromMemory();
439 CMIAdapter->writeUInt8(REG_MIXER1, mixer1Register);
440 CMIAdapter->writeUInt8(REG_MIXER2, auxVolumeRegister);
441 CMIAdapter->writeUInt8(REG_MIXER3, micVolumeRegister);
442 CMIAdapter->writeUInt8(REG_MIXER4, mixer4Register);
443
444 CMIAdapter->setUInt32Bit(REG_FUNCTRL1, functrl1Register);
445 CMIAdapter->setUInt32Bit(REG_CHFORMAT, chformatRegister);
446 CMIAdapter->setUInt32Bit(REG_LEGACY, legacyRegister);
447 CMIAdapter->setUInt32Bit(REG_MISCCTRL, miscctrlRegister);
448
449 return STATUS_SUCCESS;
450 }
451
452 STDMETHODIMP CCMITopology::storeMixerSettingsToMemory()
453 {
454 //PAGED_CODE();
455 DBGPRINT(("CCMITopology::storeMixerSettingsToMemory"));
456
457 mixer1Register = CMIAdapter->readUInt8(REG_MIXER1);
458 mixer4Register = CMIAdapter->readUInt8(REG_MIXER4);
459 functrl1Register = CMIAdapter->readUInt32(REG_FUNCTRL1) & LOOP_SPDF ;
460 chformatRegister = CMIAdapter->readUInt32(REG_CHFORMAT) & (INV_SPDIFI1 | SEL_SPDIFI1 | POLVALID);
461 legacyRegister = CMIAdapter->readUInt32(REG_LEGACY) & (BASS2LINE | CENTER2LINE | EN_SPDCOPYRHT);
462 miscctrlRegister = CMIAdapter->readUInt32(REG_MISCCTRL) & (EN_SPDO5V | SEL_SPDIFI2);
463
464 return STATUS_SUCCESS;
465 }
466
467 NTSTATUS NTAPI PropertyHandler_OnOff(PPCPROPERTY_REQUEST PropertyRequest)
468 {
469 //PAGED_CODE();
470 //ASSERT(PropertyRequest);
471 DBGPRINT(("[PropertyHandler_OnOff]"));
472
473 CCMITopology *that = (CCMITopology *) ((PMINIPORTTOPOLOGY) PropertyRequest->MajorTarget);
474
475 NTSTATUS ntStatus = STATUS_INVALID_PARAMETER;
476 UInt8 data, mask, reg;
477 LONG channel;
478
479 if (PropertyRequest->Node == ULONG(-1)) {
480 return ntStatus;
481 }
482
483 if ( ((PropertyRequest->Verb & KSPROPERTY_TYPE_GET) || (PropertyRequest->Verb & KSPROPERTY_TYPE_SET)) && (PropertyRequest->InstanceSize >= sizeof(LONG)) ) {
484 channel = *(PLONG(PropertyRequest->Instance));
485 if (PropertyRequest->ValueSize >= sizeof(BOOL)) {
486
487 if (PropertyRequest->PropertyItem->Id == KSPROPERTY_AUDIO_MUTE) {
488 PBOOL Muted = PBOOL(PropertyRequest->Value);
489 switch (PropertyRequest->Node) {
490
491 case KSNODE_TOPO_WAVEOUT_MUTE:
492 if (PropertyRequest->Verb & KSPROPERTY_TYPE_GET) {
493 *Muted = (that->CMIAdapter->readUInt8(REG_MIXER1) & MUTE_WAVE);
494 }
495 if (PropertyRequest->Verb & KSPROPERTY_TYPE_SET) {
496 if (*Muted) {
497 that->CMIAdapter->setUInt8Bit(REG_MIXER1, MUTE_WAVE);
498 } else {
499 that->CMIAdapter->clearUInt8Bit(REG_MIXER1, MUTE_WAVE);
500 }
501 }
502 ntStatus = STATUS_SUCCESS;
503 break;
504
505 case KSNODE_TOPO_AUX_MUTE:
506 switch (channel) {
507 case CHAN_LEFT: mask = MUTE_AUX_L; break;
508 case CHAN_RIGHT: mask = MUTE_AUX_R; break;
509 default: return ntStatus;
510 }
511
512 if (PropertyRequest->Verb & KSPROPERTY_TYPE_GET) {
513 *Muted = !(that->micVolumeRegister & mask);
514 }
515 if (PropertyRequest->Verb & KSPROPERTY_TYPE_SET) {
516 if (*Muted) {
517 that->micVolumeRegister &= ~mask;
518 } else {
519 that->micVolumeRegister |= mask;
520 }
521 that->CMIAdapter->writeUInt8(REG_MIXER2, that->micVolumeRegister);
522 }
523 ntStatus = STATUS_SUCCESS;
524 break;
525
526 case KSNODE_TOPO_MICOUT_MUTE:
527 if (channel != CHAN_LEFT) {
528 return ntStatus;
529 }
530
531 if (PropertyRequest->Verb & KSPROPERTY_TYPE_GET) {
532 *Muted = !(that->CMIAdapter->readMixer(SBREG_OUTPUTCTRL) & EN_MIC);
533 }
534 if (PropertyRequest->Verb & KSPROPERTY_TYPE_SET) {
535 if (*Muted) {
536 that->CMIAdapter->clearMixerBit(SBREG_OUTPUTCTRL, EN_MIC);
537 } else {
538 that->CMIAdapter->setMixerBit(SBREG_OUTPUTCTRL, EN_MIC);
539 }
540 }
541 ntStatus = STATUS_SUCCESS;
542 break;
543
544 case KSNODE_TOPO_CD_MUTE:
545 switch (channel) {
546 case CHAN_LEFT: mask = EN_CD_L; break;
547 case CHAN_RIGHT: mask = EN_CD_R; break;
548 default: return ntStatus;
549 }
550 if (PropertyRequest->Verb & KSPROPERTY_TYPE_GET) {
551 *Muted = !(that->CMIAdapter->readMixer(SBREG_OUTPUTCTRL) & mask);
552 }
553 if (PropertyRequest->Verb & KSPROPERTY_TYPE_SET) {
554 if (*Muted) {
555 that->CMIAdapter->clearMixerBit(SBREG_OUTPUTCTRL, mask);
556 } else {
557 that->CMIAdapter->setMixerBit(SBREG_OUTPUTCTRL, mask);
558 }
559 }
560 ntStatus = STATUS_SUCCESS;
561 break;
562
563 case KSNODE_TOPO_LINEIN_MUTE:
564 switch (channel) {
565 case CHAN_LEFT: mask = EN_LINEIN_L; break;
566 case CHAN_RIGHT: mask = EN_LINEIN_R; break;
567 default: return ntStatus;
568 }
569 if (PropertyRequest->Verb & KSPROPERTY_TYPE_GET) {
570 *Muted = !(that->CMIAdapter->readMixer(SBREG_OUTPUTCTRL) & mask);
571 }
572 if (PropertyRequest->Verb & KSPROPERTY_TYPE_SET) {
573 if (*Muted) {
574 that->CMIAdapter->clearMixerBit(SBREG_OUTPUTCTRL, mask);
575 } else {
576 that->CMIAdapter->setMixerBit(SBREG_OUTPUTCTRL, mask);
577 }
578 }
579 ntStatus = STATUS_SUCCESS;
580 break;
581
582 case KSNODE_TOPO_MIC_MUTE_IN:
583 if (channel != CHAN_LEFT) {
584 return ntStatus;
585 }
586 if (PropertyRequest->Verb & KSPROPERTY_TYPE_GET) {
587 *Muted = !(that->CMIAdapter->readMixer(SBREG_IN_CTRL_L) & EN_MIC);
588 }
589 if (PropertyRequest->Verb & KSPROPERTY_TYPE_SET) {
590 if (*Muted) {
591 that->CMIAdapter->clearMixerBit(SBREG_IN_CTRL_L, EN_MIC);
592 that->CMIAdapter->clearMixerBit(SBREG_IN_CTRL_R, EN_MIC);
593 } else {
594 that->CMIAdapter->setMixerBit(SBREG_IN_CTRL_L, EN_MIC);
595 that->CMIAdapter->setMixerBit(SBREG_IN_CTRL_R, EN_MIC);
596 }
597 }
598 ntStatus = STATUS_SUCCESS;
599 break;
600
601 case KSNODE_TOPO_CD_MUTE_IN:
602 switch (channel) {
603 case CHAN_LEFT: mask = EN_LINEIN_L; reg = EN_CD_L; break;
604 case CHAN_RIGHT: mask = EN_LINEIN_R; reg = EN_CD_R; break;
605 default: return ntStatus;
606 }
607 if (PropertyRequest->Verb & KSPROPERTY_TYPE_GET) {
608 *Muted = !(that->CMIAdapter->readMixer(reg) & mask);
609 }
610 if (PropertyRequest->Verb & KSPROPERTY_TYPE_SET) {
611 if (*Muted) {
612 that->CMIAdapter->clearMixerBit(reg, mask);
613 } else {
614 that->CMIAdapter->setMixerBit(reg, mask);
615 }
616 }
617 ntStatus = STATUS_SUCCESS;
618 break;
619
620 case KSNODE_TOPO_LINEIN_MUTE_IN:
621 switch (channel) {
622 case CHAN_LEFT: mask = EN_LINEIN_L; reg = SBREG_IN_CTRL_L; break;
623 case CHAN_RIGHT: mask = EN_LINEIN_R; reg = SBREG_IN_CTRL_R; break;
624 default: return ntStatus;
625 }
626 if (PropertyRequest->Verb & KSPROPERTY_TYPE_GET) {
627 *Muted = !(that->CMIAdapter->readMixer(reg) & mask);
628 }
629 if (PropertyRequest->Verb & KSPROPERTY_TYPE_SET) {
630 if (*Muted) {
631 that->CMIAdapter->clearMixerBit(reg, mask);
632 } else {
633 that->CMIAdapter->setMixerBit(reg, mask);
634 }
635 }
636 ntStatus = STATUS_SUCCESS;
637 break;
638
639
640 case KSNODE_TOPO_AUX_MUTE_IN:
641 switch (channel) {
642 case CHAN_LEFT: mask = MUTE_RAUX_L; break;
643 case CHAN_RIGHT: mask = MUTE_RAUX_R; break;
644 default: return ntStatus;
645 }
646 if (PropertyRequest->Verb & KSPROPERTY_TYPE_GET) {
647 *Muted = (that->micVolumeRegister & mask) ;
648 }
649 if (PropertyRequest->Verb & KSPROPERTY_TYPE_SET) {
650 if (*Muted) {
651 that->micVolumeRegister |= mask;
652 } else {
653 that->micVolumeRegister &= ~mask;
654 }
655 that->CMIAdapter->writeUInt8(REG_MIXER2, that->micVolumeRegister);
656 }
657 ntStatus = STATUS_SUCCESS;
658 break;
659
660 case KSNODE_TOPO_WAVEOUT_MUTE_IN:
661 switch (channel) {
662 case CHAN_LEFT: mask = EN_WAVEIN_L; break;
663 case CHAN_RIGHT: mask = EN_WAVEIN_R; break;
664 default: return ntStatus;
665 }
666 if (PropertyRequest->Verb & KSPROPERTY_TYPE_GET) {
667 // *Muted = !(that->CMIAdapter->readUInt8(REG_MIXER1) & mask);
668 *Muted = !(that->cm->enableSPDIFIn);
669 ntStatus = STATUS_SUCCESS;
670 }
671 if ((PropertyRequest->Verb & KSPROPERTY_TYPE_SET) && !(that->settingsLoaded)) {
672 if (*Muted) {
673 that->cm->enableSPDIFIn = FALSE;
674 that->CMIAdapter->clearUInt8Bit(REG_MIXER1, mask);
675 } else {
676 that->cm->enableSPDIFIn = TRUE;
677 that->CMIAdapter->setUInt8Bit(REG_MIXER1, mask);
678 }
679 ntStatus = STATUS_SUCCESS;
680 }
681 break;
682
683 case KSNODE_TOPO_MASTER_MUTE_DUMMY:
684 channel = (1 << channel);
685 if (PropertyRequest->Verb & KSPROPERTY_TYPE_GET) {
686 *Muted = that->masterMuteDummy & channel;
687 }
688 if (PropertyRequest->Verb & KSPROPERTY_TYPE_SET) {
689 if (*Muted) {
690 that->masterMuteDummy |= channel;
691 } else {
692 that->masterMuteDummy &= ~channel;
693 }
694 }
695 ntStatus = STATUS_SUCCESS;
696 break;
697 }
698 }
699
700 if (PropertyRequest->PropertyItem->Id == KSPROPERTY_AUDIO_LOUDNESS) {
701 PBOOL LoudnessOn = PBOOL(PropertyRequest->Value);
702 switch (PropertyRequest->Node) {
703 case KSNODE_TOPO_MICIN_LOUDNESS:
704 if (channel == CHAN_LEFT) {
705 if (PropertyRequest->Verb & KSPROPERTY_TYPE_GET) {
706 *LoudnessOn = (that->CMIAdapter->readMixer(SBREG_EXTENSION) & EN_MICBOOST);
707 }
708 if (PropertyRequest->Verb & KSPROPERTY_TYPE_SET) {
709 // DBGPRINT(("setting mic boost: previous state %d, new state %d", (that->CMIAdapter->readMixer(SBREG_EXTENSION) & EN_MICBOOST), (*LoudnessOn)));
710 if (*LoudnessOn) {
711 that->CMIAdapter->setMixerBit(SBREG_EXTENSION, EN_MICBOOST);
712 } else {
713 that->CMIAdapter->clearMixerBit(SBREG_EXTENSION, EN_MICBOOST);
714 }
715 }
716 ntStatus = STATUS_SUCCESS;
717 }
718 break;
719 case KSNODE_TOPO_MICOUT_LOUDNESS:
720 if (channel == CHAN_LEFT) {
721 if (PropertyRequest->Verb & KSPROPERTY_TYPE_GET) {
722 *LoudnessOn = !(that->CMIAdapter->readUInt8(REG_MIXER2) & DIS_MICGAIN);
723 }
724 if (PropertyRequest->Verb & KSPROPERTY_TYPE_SET) {
725 if (*LoudnessOn) {
726 that->CMIAdapter->clearUInt8Bit(REG_MIXER2, DIS_MICGAIN);
727 } else {
728 that->CMIAdapter->setUInt8Bit(REG_MIXER2, DIS_MICGAIN);
729 }
730 }
731 ntStatus = STATUS_SUCCESS;
732 }
733 break;
734 case KSNODE_TOPO_IEC_5V:
735 if (PropertyRequest->Verb & KSPROPERTY_TYPE_GET) {
736 *LoudnessOn = (that->CMIAdapter->readUInt32(REG_MISCCTRL) & EN_SPDO5V);
737 }
738 if (PropertyRequest->Verb & KSPROPERTY_TYPE_SET) {
739 if (*LoudnessOn) {
740 that->CMIAdapter->setUInt32Bit(REG_MISCCTRL, EN_SPDO5V);
741 } else {
742 that->CMIAdapter->clearUInt32Bit(REG_MISCCTRL, EN_SPDO5V);
743 }
744 }
745 ntStatus = STATUS_SUCCESS;
746 break;
747 case KSNODE_TOPO_IEC_OUT:
748 if (PropertyRequest->Verb & KSPROPERTY_TYPE_GET) {
749 if (that->cm) {
750 *LoudnessOn = that->cm->enableSPDIFOut;
751 }
752 }
753 if (PropertyRequest->Verb & KSPROPERTY_TYPE_SET) {
754 if (that->cm) {
755 that->cm->enableSPDIFOut = (*LoudnessOn);
756 }
757 }
758 ntStatus = STATUS_SUCCESS;
759 break;
760
761 case KSNODE_TOPO_IEC_INVERSE:
762 if (PropertyRequest->Verb & KSPROPERTY_TYPE_GET) {
763 if (that->cm->chipVersion <= 37) {
764 *LoudnessOn = (that->CMIAdapter->readUInt8(REG_MIXER4) & INV_SPDIFI1);
765 } else {
766 *LoudnessOn = (that->CMIAdapter->readUInt32(REG_CHFORMAT) & INV_SPDIFI2);
767 }
768 }
769 if (PropertyRequest->Verb & KSPROPERTY_TYPE_SET) {
770 if (*LoudnessOn) {
771 if (that->cm->chipVersion <= 37) {
772 that->CMIAdapter->setUInt8Bit(REG_MIXER4, INV_SPDIFI1);
773 } else {
774 that->CMIAdapter->setUInt32Bit(REG_CHFORMAT, INV_SPDIFI2);
775 }
776 } else {
777 if (that->cm->chipVersion <= 37) {
778 that->CMIAdapter->clearUInt8Bit(REG_MIXER4, INV_SPDIFI1);
779 } else {
780 that->CMIAdapter->clearUInt32Bit(REG_CHFORMAT, INV_SPDIFI2);
781 }
782 }
783 }
784 ntStatus = STATUS_SUCCESS;
785 break;
786
787 case KSNODE_TOPO_IEC_MONITOR:
788 if (PropertyRequest->Verb & KSPROPERTY_TYPE_GET) {
789 *LoudnessOn = (that->CMIAdapter->readUInt8(REG_MIXER1) & EN_SPDI2DAC);
790 }
791 if (PropertyRequest->Verb & KSPROPERTY_TYPE_SET) {
792 if (*LoudnessOn) {
793 that->CMIAdapter->setUInt8Bit(REG_MIXER1, EN_SPDI2DAC);
794 } else {
795 that->CMIAdapter->clearUInt8Bit(REG_MIXER1, EN_SPDI2DAC);
796 }
797 }
798 ntStatus = STATUS_SUCCESS;
799 break;
800
801 case KSNODE_TOPO_IEC_SELECT:
802 if (PropertyRequest->Verb & KSPROPERTY_TYPE_GET) {
803 if (that->cm->chipVersion <= 37) {
804 *LoudnessOn = (that->CMIAdapter->readUInt32(REG_CHFORMAT) & SEL_SPDIFI1);
805 } else {
806 *LoudnessOn = (that->CMIAdapter->readUInt32(REG_MISCCTRL) & SEL_SPDIFI2);
807 }
808 }
809 if (PropertyRequest->Verb & KSPROPERTY_TYPE_SET) {
810 if (*LoudnessOn) {
811 if (that->cm->chipVersion <= 37) {
812 that->CMIAdapter->setUInt32Bit(REG_CHFORMAT, SEL_SPDIFI1);
813 } else {
814 that->CMIAdapter->setUInt32Bit(REG_MISCCTRL, SEL_SPDIFI2);
815 }
816 } else {
817 if (that->cm->chipVersion <= 37) {
818 that->CMIAdapter->clearUInt32Bit(REG_CHFORMAT, SEL_SPDIFI1);
819 } else {
820 that->CMIAdapter->clearUInt32Bit(REG_MISCCTRL, SEL_SPDIFI2);
821 }
822 }
823 }
824 ntStatus = STATUS_SUCCESS;
825 break;
826
827 case KSNODE_TOPO_XCHG_FB:
828 if (PropertyRequest->Verb & KSPROPERTY_TYPE_GET) {
829 *LoudnessOn = (that->CMIAdapter->readUInt8(REG_MIXER1) & REAR2FRONT);
830 }
831 if ((PropertyRequest->Verb & KSPROPERTY_TYPE_SET) && !(that->settingsLoaded)) {
832 if (*LoudnessOn) {
833 that->CMIAdapter->setUInt8Bit(REG_MIXER1, REAR2FRONT);
834 } else {
835 that->CMIAdapter->clearUInt8Bit(REG_MIXER1, REAR2FRONT);
836 }
837 }
838 ntStatus = STATUS_SUCCESS;
839 break;
840
841 case KSNODE_TOPO_BASS2LINE:
842 if (PropertyRequest->Verb & KSPROPERTY_TYPE_GET) {
843 *LoudnessOn = (that->CMIAdapter->readUInt32(REG_LEGACY) & BASS2LINE);
844 }
845 if ((PropertyRequest->Verb & KSPROPERTY_TYPE_SET) && !(that->settingsLoaded)) {
846 if (*LoudnessOn) {
847 that->CMIAdapter->setUInt32Bit(REG_LEGACY, BASS2LINE);
848 } else {
849 that->CMIAdapter->clearUInt32Bit(REG_LEGACY, BASS2LINE);
850 }
851 }
852 ntStatus = STATUS_SUCCESS;
853 break;
854
855 case KSNODE_TOPO_CENTER2LINE:
856 if (PropertyRequest->Verb & KSPROPERTY_TYPE_GET) {
857 *LoudnessOn = (that->CMIAdapter->readUInt32(REG_LEGACY) & CENTER2LINE);
858 }
859 if ((PropertyRequest->Verb & KSPROPERTY_TYPE_SET) && !(that->settingsLoaded)) {
860 if (*LoudnessOn) {
861 that->CMIAdapter->setUInt32Bit(REG_LEGACY, CENTER2LINE);
862 } else {
863 that->CMIAdapter->clearUInt32Bit(REG_LEGACY, CENTER2LINE);
864 }
865 }
866 ntStatus = STATUS_SUCCESS;
867 break;
868
869 case KSNODE_TOPO_IEC_COPYRIGHT:
870 if (PropertyRequest->Verb & KSPROPERTY_TYPE_GET) {
871 *LoudnessOn = (that->CMIAdapter->readUInt32(REG_LEGACY) & EN_SPDCOPYRHT);
872 }
873 if ((PropertyRequest->Verb & KSPROPERTY_TYPE_SET) && !(that->settingsLoaded)) {
874 if (*LoudnessOn) {
875 that->CMIAdapter->setUInt32Bit(REG_LEGACY, EN_SPDCOPYRHT);
876 } else {
877 that->CMIAdapter->clearUInt32Bit(REG_LEGACY, EN_SPDCOPYRHT);
878 }
879 }
880 ntStatus = STATUS_SUCCESS;
881 break;
882
883 case KSNODE_TOPO_IEC_POLVALID:
884 if (PropertyRequest->Verb & KSPROPERTY_TYPE_GET) {
885 *LoudnessOn = (that->CMIAdapter->readUInt32(REG_CHFORMAT) & POLVALID);
886 }
887 if ((PropertyRequest->Verb & KSPROPERTY_TYPE_SET) && !(that->settingsLoaded)) {
888 if (*LoudnessOn) {
889 that->CMIAdapter->setUInt32Bit(REG_CHFORMAT, POLVALID);
890 } else {
891 that->CMIAdapter->clearUInt32Bit(REG_CHFORMAT, POLVALID);
892 }
893 }
894 ntStatus = STATUS_SUCCESS;
895 break;
896
897 case KSNODE_TOPO_IEC_LOOP:
898 if (PropertyRequest->Verb & KSPROPERTY_TYPE_GET) {
899 *LoudnessOn = (that->CMIAdapter->readUInt32(REG_FUNCTRL1) & LOOP_SPDF);
900 }
901 if ((PropertyRequest->Verb & KSPROPERTY_TYPE_SET) && !(that->settingsLoaded)) {
902 if (*LoudnessOn) {
903 that->CMIAdapter->setUInt32Bit(REG_FUNCTRL1, LOOP_SPDF);
904 } else {
905 that->CMIAdapter->clearUInt32Bit(REG_FUNCTRL1, LOOP_SPDF);
906 }
907 }
908 ntStatus = STATUS_SUCCESS;
909 break;
910
911 case KSNODE_TOPO_REAR2LINE:
912 if (PropertyRequest->Verb & KSPROPERTY_TYPE_GET) {
913 *LoudnessOn = (that->CMIAdapter->readUInt8(REG_MIXER1) & REAR2LINE);
914 }
915 if ((PropertyRequest->Verb & KSPROPERTY_TYPE_SET) && !(that->settingsLoaded)) {
916 if (*LoudnessOn) {
917 that->CMIAdapter->setUInt8Bit(REG_MIXER1, REAR2LINE);
918 } else {
919 that->CMIAdapter->clearUInt8Bit(REG_MIXER1, REAR2LINE);
920 }
921 }
922 ntStatus = STATUS_SUCCESS;
923 break;
924
925 case KSNODE_TOPO_CENTER2MIC:
926 if (PropertyRequest->Verb & KSPROPERTY_TYPE_GET) {
927 *LoudnessOn = (that->CMIAdapter->readUInt8(REG_MIXER4) & CENTER2MIC) && (that->cm->chipVersion > 37);
928 }
929 if ((PropertyRequest->Verb & KSPROPERTY_TYPE_SET) && !(that->settingsLoaded) && (that->cm->chipVersion > 37)) {
930 if (*LoudnessOn) {
931 that->CMIAdapter->setUInt8Bit(REG_MIXER4, CENTER2MIC);
932 } else {
933 that->CMIAdapter->clearUInt8Bit(REG_MIXER4, CENTER2MIC);
934 }
935 }
936 ntStatus = STATUS_SUCCESS;
937 break;
938 }
939 }
940
941 if ((NT_SUCCESS(ntStatus)) && (PropertyRequest->Verb & KSPROPERTY_TYPE_GET)) {
942 PropertyRequest->ValueSize = sizeof(BOOL);
943 }
944
945 }
946 } else if (PropertyRequest->Verb & KSPROPERTY_TYPE_BASICSUPPORT) {
947 bool supported = false;
948 if (PropertyRequest->PropertyItem->Id == KSPROPERTY_AUDIO_MUTE) {
949 switch (PropertyRequest->Node) {
950 case KSNODE_TOPO_CD_MUTE:
951 case KSNODE_TOPO_LINEIN_MUTE:
952 case KSNODE_TOPO_MICOUT_MUTE:
953 case KSNODE_TOPO_AUX_MUTE:
954 case KSNODE_TOPO_WAVEOUT_MUTE:
955 case KSNODE_TOPO_LINEIN_MUTE_IN:
956 case KSNODE_TOPO_MIC_MUTE_IN:
957 case KSNODE_TOPO_CD_MUTE_IN:
958 case KSNODE_TOPO_AUX_MUTE_IN:
959 case KSNODE_TOPO_WAVEOUT_MUTE_IN:
960 case KSNODE_TOPO_MASTER_MUTE_DUMMY:
961 supported = true;
962 }
963 }
964
965 if (PropertyRequest->PropertyItem->Id == KSPROPERTY_AUDIO_LOUDNESS) {
966 switch (PropertyRequest->Node) {
967 case KSNODE_TOPO_MICIN_LOUDNESS:
968 case KSNODE_TOPO_MICOUT_LOUDNESS:
969 case KSNODE_TOPO_IEC_5V:
970 case KSNODE_TOPO_IEC_OUT:
971 case KSNODE_TOPO_IEC_INVERSE:
972 case KSNODE_TOPO_IEC_MONITOR:
973 case KSNODE_TOPO_IEC_SELECT:
974 case KSNODE_TOPO_XCHG_FB:
975 case KSNODE_TOPO_BASS2LINE:
976 case KSNODE_TOPO_CENTER2LINE:
977 case KSNODE_TOPO_IEC_COPYRIGHT:
978 case KSNODE_TOPO_IEC_POLVALID:
979 case KSNODE_TOPO_IEC_LOOP:
980 case KSNODE_TOPO_REAR2LINE:
981 supported = true;
982 }
983 if ((PropertyRequest->Node == KSNODE_TOPO_CENTER2MIC) && (that->cm->chipVersion > 37)) {
984 supported = true;
985 }
986 }
987
988 if (supported) {
989 if (PropertyRequest->ValueSize >= (sizeof(KSPROPERTY_DESCRIPTION))) {
990 PKSPROPERTY_DESCRIPTION PropDesc = PKSPROPERTY_DESCRIPTION(PropertyRequest->Value);
991
992 PropDesc->AccessFlags = KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_SET | KSPROPERTY_TYPE_BASICSUPPORT;
993 PropDesc->DescriptionSize = sizeof(KSPROPERTY_DESCRIPTION);
994 PropDesc->PropTypeSet.Set = KSPROPTYPESETID_General;
995 PropDesc->PropTypeSet.Id = VT_BOOL;
996 PropDesc->PropTypeSet.Flags = 0;
997 PropDesc->MembersListCount = 0;
998 PropDesc->Reserved = 0;
999
1000 PropertyRequest->ValueSize = sizeof(KSPROPERTY_DESCRIPTION);
1001 ntStatus = STATUS_SUCCESS;
1002 } else if (PropertyRequest->ValueSize >= sizeof(ULONG)) {
1003 PULONG AccessFlags = PULONG(PropertyRequest->Value);
1004
1005 *AccessFlags = KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_SET | KSPROPERTY_TYPE_BASICSUPPORT;
1006
1007 PropertyRequest->ValueSize = sizeof(ULONG);
1008 ntStatus = STATUS_SUCCESS;
1009 }
1010 }
1011 }
1012
1013 return ntStatus;
1014 }
1015
1016 static NTSTATUS BasicSupportHandler(PPCPROPERTY_REQUEST PropertyRequest)
1017 {
1018 //PAGED_CODE();
1019 //ASSERT(PropertyRequest);
1020 DBGPRINT(("[BasicSupportHandler]"));
1021
1022 NTSTATUS ntStatus = STATUS_INVALID_DEVICE_REQUEST;
1023
1024 if (PropertyRequest->ValueSize >= (sizeof(KSPROPERTY_DESCRIPTION))) {
1025 PKSPROPERTY_DESCRIPTION PropDesc = PKSPROPERTY_DESCRIPTION(PropertyRequest->Value);
1026
1027 PropDesc->AccessFlags = KSPROPERTY_TYPE_BASICSUPPORT | KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_SET;
1028 PropDesc->DescriptionSize = sizeof(KSPROPERTY_DESCRIPTION) + sizeof(KSPROPERTY_MEMBERSHEADER) + sizeof(KSPROPERTY_STEPPING_LONG);
1029 PropDesc->PropTypeSet.Set = KSPROPTYPESETID_General;
1030 PropDesc->PropTypeSet.Id = VT_I4;
1031 PropDesc->PropTypeSet.Flags = 0;
1032 PropDesc->MembersListCount = 1;
1033 PropDesc->Reserved = 0;
1034
1035 if (PropertyRequest->ValueSize >= (sizeof(KSPROPERTY_DESCRIPTION) + sizeof(KSPROPERTY_MEMBERSHEADER) + sizeof(KSPROPERTY_STEPPING_LONG))) {
1036 PKSPROPERTY_MEMBERSHEADER Members = PKSPROPERTY_MEMBERSHEADER(PropDesc + 1);
1037
1038 Members->MembersFlags = KSPROPERTY_MEMBER_STEPPEDRANGES;
1039 Members->MembersSize = sizeof(KSPROPERTY_STEPPING_LONG);
1040 Members->MembersCount = 1;
1041 Members->Flags = 0;
1042
1043 PKSPROPERTY_STEPPING_LONG Range = PKSPROPERTY_STEPPING_LONG(Members + 1);
1044
1045 for (int i=0;i<SIZEOF_ARRAY(VolTable);i++) {
1046 if (VolTable[i].node == PropertyRequest->Node) {
1047 Range->Bounds.SignedMaximum = (VolTable[i].max << 16);
1048 Range->Bounds.SignedMinimum = (VolTable[i].min << 16);
1049 Range->SteppingDelta = (VolTable[i].step << 16);
1050 ntStatus = STATUS_SUCCESS;
1051 }
1052 }
1053 if (!NT_SUCCESS(ntStatus)) {
1054 switch (PropertyRequest->Node) {
1055 case KSNODE_TOPO_AUX_VOLUME:
1056 Range->Bounds.SignedMaximum = 0;
1057 Range->Bounds.SignedMinimum = (-60 << 16);
1058 Range->SteppingDelta = (4 << 16);
1059 ntStatus = STATUS_SUCCESS;
1060 break;
1061 case KSNODE_TOPO_MICIN_VOLUME:
1062 Range->Bounds.SignedMaximum = 0;
1063 Range->Bounds.SignedMinimum = (-56 << 16);
1064 Range->SteppingDelta = (8 << 16);
1065 ntStatus = STATUS_SUCCESS;
1066 break;
1067 }
1068 }
1069 Range->Reserved = 0;
1070
1071 PropertyRequest->ValueSize = sizeof(KSPROPERTY_DESCRIPTION) + sizeof(KSPROPERTY_MEMBERSHEADER) + sizeof(KSPROPERTY_STEPPING_LONG);
1072 } else {
1073 PropertyRequest->ValueSize = sizeof(KSPROPERTY_DESCRIPTION);
1074 ntStatus = STATUS_SUCCESS;
1075 }
1076 } else if (PropertyRequest->ValueSize >= sizeof(ULONG)) {
1077 PULONG AccessFlags = PULONG(PropertyRequest->Value);
1078 *AccessFlags = KSPROPERTY_TYPE_BASICSUPPORT | KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_SET;
1079 PropertyRequest->ValueSize = sizeof(ULONG);
1080 ntStatus = STATUS_SUCCESS;
1081 }
1082
1083 return ntStatus;
1084 }
1085
1086 NTSTATUS NTAPI PropertyHandler_Level(PPCPROPERTY_REQUEST PropertyRequest)
1087 {
1088 //PAGED_CODE();
1089 //ASSERT(PropertyRequest);
1090 DBGPRINT(("[PropertyHandler_Level]"));
1091
1092 CCMITopology *that = (CCMITopology *) ((PMINIPORTTOPOLOGY) PropertyRequest->MajorTarget);
1093 NTSTATUS ntStatus = STATUS_INVALID_PARAMETER;
1094 UInt32 channel;
1095 UInt8 mixerValue;
1096
1097 if ((PropertyRequest->Node == ULONG(-1)) || (PropertyRequest->Node >= KSNODE_TOPO_INVALID) || (PropertyRequest->PropertyItem->Id != KSPROPERTY_AUDIO_VOLUMELEVEL)) {
1098 return ntStatus;
1099 }
1100
1101 if ( ((PropertyRequest->Verb & KSPROPERTY_TYPE_GET) || (PropertyRequest->Verb & KSPROPERTY_TYPE_SET)) && (PropertyRequest->InstanceSize >= sizeof(LONG)) ) {
1102
1103 channel = *(PLONG(PropertyRequest->Instance));
1104
1105 if ((PropertyRequest->Node == KSNODE_TOPO_MICOUT_VOLUME) && (channel != CHAN_LEFT)) {
1106 return STATUS_INVALID_PARAMETER;
1107 }
1108
1109 if ( ( (channel == CHAN_LEFT) || (channel == CHAN_RIGHT) ) && (PropertyRequest->ValueSize >= sizeof(LONG))) {
1110
1111 PLONG Level = (PLONG)PropertyRequest->Value;
1112
1113 for (int i=0;i<SIZEOF_ARRAY(VolTable);i++)
1114 {
1115 if (VolTable[i].node == PropertyRequest->Node) {
1116 if (PropertyRequest->Verb & KSPROPERTY_TYPE_GET) {
1117
1118 mixerValue = (that->CMIAdapter->readMixer(VolTable[i].reg+channel) >> VolTable[i].shift) & VolTable[i].mask;
1119 *Level = that->NodeCache[(2*PropertyRequest->Node)+channel];
1120
1121 if (mixerValue != ((*Level >> (VolTable[i].dbshift+16))+VolTable[i].mask)) {
1122 *Level = (mixerValue - VolTable[i].mask) << (16+VolTable[i].dbshift);
1123 that->NodeCache[(2*PropertyRequest->Node)+channel] = *Level;
1124 }
1125 } else
1126 if (PropertyRequest->Verb & KSPROPERTY_TYPE_SET) {
1127 if (*Level <= (VolTable[i].min << 16)) {
1128 mixerValue = 0;
1129 that->NodeCache[(2*PropertyRequest->Node)+channel] = VolTable[i].min << 16;
1130 } else
1131 if (*Level >= (VolTable[i].max << 16)) {
1132 mixerValue = VolTable[i].mask;
1133 that->NodeCache[(2*PropertyRequest->Node)+channel] = VolTable[i].max << 16;
1134 } else {
1135 mixerValue = ((*Level >> (VolTable[i].dbshift+16)) + VolTable[i].mask) & VolTable[i].mask;
1136 that->NodeCache[(2*PropertyRequest->Node)+channel] = *Level;
1137 }
1138 that->CMIAdapter->writeMixer(VolTable[i].reg+channel, mixerValue << VolTable[i].shift);
1139 }
1140 ntStatus = STATUS_SUCCESS;
1141 }
1142 }
1143 if (PropertyRequest->Node == KSNODE_TOPO_AUX_VOLUME) {
1144 if (PropertyRequest->Verb & KSPROPERTY_TYPE_GET) {
1145 mixerValue = that->auxVolumeRegister;
1146 *Level = that->NodeCache[(2*PropertyRequest->Node)+channel];
1147 if (channel == CHAN_LEFT) {
1148 mixerValue >>= 4;
1149 }
1150 mixerValue &= 0x0F;
1151 if (mixerValue != ((*Level >> 18)+0x0F)) {
1152 *Level = (mixerValue - 0x0F) << 18;
1153 that->NodeCache[(2*PropertyRequest->Node)+channel] = *Level;
1154 }
1155 } else
1156 if (PropertyRequest->Verb & KSPROPERTY_TYPE_SET) {
1157 if (*Level <= (-30 << 16)) {
1158 mixerValue = 0;
1159 that->NodeCache[(2*PropertyRequest->Node)+channel] = -30 << 16;
1160 } else
1161 if (*Level >= 0) {
1162 mixerValue = 0x0F;
1163 that->NodeCache[(2*PropertyRequest->Node)+channel] = 0;
1164 } else {
1165 mixerValue = ((*Level >> 18) + 0x0F) & 0x0F;
1166 that->NodeCache[(2*PropertyRequest->Node)+channel] = *Level;
1167 }
1168
1169 if (channel == CHAN_RIGHT) {
1170 that->auxVolumeRegister = (that->auxVolumeRegister & 0xF0) | mixerValue;
1171 } else if (channel == CHAN_LEFT) {
1172 that->auxVolumeRegister = (that->auxVolumeRegister & 0x0F) | (mixerValue << 4);
1173 }
1174 that->CMIAdapter->writeUInt8(REG_MIXER3, that->auxVolumeRegister);
1175 }
1176 ntStatus = STATUS_SUCCESS;
1177 }
1178 if ((PropertyRequest->Node == KSNODE_TOPO_MICIN_VOLUME) && (channel == CHAN_LEFT)) {
1179 if (PropertyRequest->Verb & KSPROPERTY_TYPE_GET) {
1180 *Level = that->NodeCache[(2*PropertyRequest->Node)];
1181 mixerValue = that->micVolumeRegister >> 1 & 0x7;
1182 if (mixerValue != ((*Level >> 19)+0x07)) {
1183 *Level = (mixerValue - 0x07) << 19;
1184 that->NodeCache[(2*PropertyRequest->Node)] = *Level;
1185 }
1186 } else if (PropertyRequest->Verb & KSPROPERTY_TYPE_SET) {
1187 if (*Level <= (-56 << 16)) {
1188 mixerValue = 0;
1189 that->NodeCache[(2*PropertyRequest->Node)] = -56 << 16;
1190 } else if (*Level >= 0) {
1191 mixerValue = 0x07;
1192 that->NodeCache[(2*PropertyRequest->Node)] = 0;
1193 } else {
1194 mixerValue = ((*Level >> 19) + 0x07) & 0x07;
1195 that->NodeCache[(2*PropertyRequest->Node)] = *Level;
1196 }
1197 that->micVolumeRegister &= ~(0x07 << 1);
1198 that->micVolumeRegister |= mixerValue << 1;
1199 that->CMIAdapter->writeUInt8(REG_MIXER2, that->micVolumeRegister);
1200 }
1201 ntStatus = STATUS_SUCCESS;
1202 }
1203 if ((NT_SUCCESS(ntStatus)) && (PropertyRequest->Verb & KSPROPERTY_TYPE_GET)) {
1204 PropertyRequest->ValueSize = sizeof(LONG);
1205 }
1206 }
1207 } else if (PropertyRequest->Verb & KSPROPERTY_TYPE_BASICSUPPORT) {
1208 switch(PropertyRequest->Node) {
1209 case KSNODE_TOPO_LINEOUT_VOLUME:
1210 case KSNODE_TOPO_WAVEOUT_VOLUME:
1211 case KSNODE_TOPO_CD_VOLUME:
1212 case KSNODE_TOPO_LINEIN_VOLUME:
1213 case KSNODE_TOPO_MICOUT_VOLUME:
1214 case KSNODE_TOPO_MICIN_VOLUME:
1215 case KSNODE_TOPO_AUX_VOLUME:
1216 ntStatus = BasicSupportHandler(PropertyRequest);
1217 break;
1218 }
1219 }
1220
1221 return ntStatus;
1222 }
1223 NTSTATUS NTAPI PropertyHandler_CpuResources(PPCPROPERTY_REQUEST PropertyRequest)
1224 {
1225 //PAGED_CODE();
1226 //ASSERT(PropertyRequest);
1227 DBGPRINT(("[PropertyHandler_CpuResources]"));
1228
1229 NTSTATUS ntStatus = STATUS_INVALID_DEVICE_REQUEST;
1230
1231 if (PropertyRequest->Node == MAXULONG) {
1232 return ntStatus;
1233 }
1234 if (PropertyRequest->Node >= KSNODE_TOPO_INVALID) {
1235 return ntStatus;
1236 }
1237
1238 if (PropertyRequest->Verb & KSPROPERTY_TYPE_GET) {
1239 if (PropertyRequest->ValueSize >= sizeof(LONG)) {
1240 *((PLONG)PropertyRequest->Value) = KSAUDIO_CPU_RESOURCES_NOT_HOST_CPU;
1241
1242 PropertyRequest->ValueSize = sizeof(LONG);
1243 ntStatus = STATUS_SUCCESS;
1244 } else {
1245 ntStatus = STATUS_BUFFER_TOO_SMALL;
1246 }
1247 } else if (PropertyRequest->Verb & KSPROPERTY_TYPE_BASICSUPPORT) {
1248 if (PropertyRequest->ValueSize >= (sizeof(KSPROPERTY_DESCRIPTION))) {
1249 PKSPROPERTY_DESCRIPTION PropDesc = PKSPROPERTY_DESCRIPTION(PropertyRequest->Value);
1250
1251 PropDesc->AccessFlags = KSPROPERTY_TYPE_BASICSUPPORT |
1252 KSPROPERTY_TYPE_GET;
1253 PropDesc->DescriptionSize = sizeof(KSPROPERTY_DESCRIPTION);
1254 PropDesc->PropTypeSet.Set = KSPROPTYPESETID_General;
1255 PropDesc->PropTypeSet.Id = VT_I4;
1256 PropDesc->PropTypeSet.Flags = 0;
1257 PropDesc->MembersListCount = 0;
1258 PropDesc->Reserved = 0;
1259
1260 PropertyRequest->ValueSize = sizeof(KSPROPERTY_DESCRIPTION);
1261 ntStatus = STATUS_SUCCESS;
1262 } else if (PropertyRequest->ValueSize >= sizeof(ULONG)) {
1263 PULONG AccessFlags = PULONG(PropertyRequest->Value);
1264
1265 *AccessFlags = KSPROPERTY_TYPE_BASICSUPPORT | KSPROPERTY_TYPE_GET;
1266
1267 PropertyRequest->ValueSize = sizeof(ULONG);
1268 ntStatus = STATUS_SUCCESS;
1269 }
1270 }
1271
1272 return ntStatus;
1273 }
1274
1275 NTSTATUS NTAPI PropertyHandler_ComponentId(PPCPROPERTY_REQUEST PropertyRequest)
1276 {
1277 //PAGED_CODE();
1278 //ASSERT(PropertyRequest);
1279 DBGPRINT(("[PropertyHandler_ComponentId]"));
1280
1281 NTSTATUS ntStatus = STATUS_INVALID_DEVICE_REQUEST;
1282 CCMITopology *that = (CCMITopology *) ((PMINIPORTTOPOLOGY) PropertyRequest->MajorTarget);
1283
1284 if (PropertyRequest->Verb & KSPROPERTY_TYPE_GET) {
1285 if (PropertyRequest->ValueSize >= sizeof(KSCOMPONENTID)) {
1286 PKSCOMPONENTID pComponentId = (PKSCOMPONENTID)PropertyRequest->Value;
1287
1288 pComponentId->Manufacturer = MANUFACTURER_CM8738;
1289 pComponentId->Product = PRODUCT_CM8738;
1290 pComponentId->Component = COMPONENT_CM8738;
1291 pComponentId->Name = GUID_NULL;
1292 pComponentId->Version = CMIPCI_VERSION;
1293 pComponentId->Revision = that->cm->chipVersion;
1294
1295 PropertyRequest->ValueSize = sizeof(KSCOMPONENTID);
1296 ntStatus = STATUS_SUCCESS;
1297 } else if (PropertyRequest->ValueSize == 0) {
1298 PropertyRequest->ValueSize = sizeof(KSCOMPONENTID);
1299 ntStatus = STATUS_BUFFER_OVERFLOW;
1300 } else {
1301 PropertyRequest->ValueSize = 0;
1302 ntStatus = STATUS_BUFFER_TOO_SMALL;
1303 }
1304 } else if (PropertyRequest->Verb & KSPROPERTY_TYPE_BASICSUPPORT) {
1305 if (PropertyRequest->ValueSize >= sizeof(ULONG)) {
1306 PULONG AccessFlags = PULONG(PropertyRequest->Value);
1307
1308 *AccessFlags = KSPROPERTY_TYPE_BASICSUPPORT | KSPROPERTY_TYPE_GET;
1309
1310 PropertyRequest->ValueSize = sizeof(ULONG);
1311 ntStatus = STATUS_SUCCESS;
1312 } else {
1313 PropertyRequest->ValueSize = 0;
1314 ntStatus = STATUS_BUFFER_TOO_SMALL;
1315 }
1316 }
1317
1318 return ntStatus;
1319 }
1320
1321 NTSTATUS NTAPI PropertyHandler_Private(PPCPROPERTY_REQUEST PropertyRequest)
1322 {
1323 //PAGED_CODE();
1324 //ASSERT(PropertyRequest);
1325 DBGPRINT(("[PropertyHandler_Private]"));
1326
1327 NTSTATUS ntStatus = STATUS_INVALID_DEVICE_REQUEST;
1328 CCMITopology *that = (CCMITopology *) ((PMINIPORTTOPOLOGY) PropertyRequest->MajorTarget);
1329
1330 if (PropertyRequest->Verb & KSPROPERTY_TYPE_GET) {
1331 if (PropertyRequest->PropertyItem->Id != KSPROPERTY_CMI_GET) {
1332 return STATUS_INVALID_DEVICE_REQUEST;
1333 }
1334
1335 if (PropertyRequest->ValueSize == 0) {
1336 PropertyRequest->ValueSize = sizeof(CMIDATA);
1337 return STATUS_BUFFER_OVERFLOW;
1338 } else if (PropertyRequest->ValueSize < sizeof (CMIDATA)) {
1339 PropertyRequest->ValueSize = 0;
1340 return STATUS_BUFFER_TOO_SMALL;
1341 }
1342
1343 CMIDATA* cmiData = (CMIDATA*)PropertyRequest->Value;
1344 #ifdef WAVERT
1345 RtlStringCbPrintfA(cmiData->driverVersion, sizeof(cmiData->driverVersion), CMIVERSION "-WaveRT");
1346 #else
1347 RtlStringCbPrintfA(cmiData->driverVersion, sizeof(cmiData->driverVersion), CMIVERSION);
1348 #endif
1349 cmiData->hardwareRevision = that->cm->chipVersion;
1350 cmiData->maxChannels = that->cm->maxChannels;
1351 cmiData->IOBase = (USHORT)(ULONG_PTR)that->cm->IOBase;
1352 cmiData->MPUBase = (USHORT)(ULONG_PTR)that->cm->MPUBase;
1353 cmiData->enableSPDO = that->cm->enableSPDIFOut;
1354 cmiData->enableSPDI = that->cm->enableSPDIFIn;
1355 cmiData->formatMask = that->cm->formatMask;
1356 cmiData->exchangeFrontBack = (that->CMIAdapter->readUInt8(REG_MIXER1) & REAR2FRONT);
1357 cmiData->enableSPDO5V = (that->CMIAdapter->readUInt32(REG_MISCCTRL) & EN_SPDO5V);
1358 cmiData->enablePCMDAC = (that->CMIAdapter->readUInt8(REG_MIXER1) & EN_SPDI2DAC);
1359 cmiData->enableBass2Line = (that->CMIAdapter->readUInt32(REG_LEGACY) & BASS2LINE);
1360 cmiData->enableCenter2Line = (that->CMIAdapter->readUInt32(REG_LEGACY) & CENTER2LINE);
1361 cmiData->enableRear2Line = (that->CMIAdapter->readUInt8(REG_MIXER1) & REAR2LINE);
1362 cmiData->enableCenter2Mic = (that->CMIAdapter->readUInt8(REG_MIXER4) & CENTER2MIC) && (that->cm->chipVersion > 37);
1363 cmiData->enableSPDOCopyright = (that->CMIAdapter->readUInt32(REG_LEGACY) & EN_SPDCOPYRHT);
1364 cmiData->invertValidBitSPDI = (that->CMIAdapter->readUInt32(REG_CHFORMAT) & POLVALID);
1365 cmiData->loopSPDI = (that->CMIAdapter->readUInt32(REG_FUNCTRL1) & LOOP_SPDF);
1366 if (that->cm->chipVersion <= 37) {
1367 cmiData->select2ndSPDI = (that->CMIAdapter->readUInt32(REG_CHFORMAT) & SEL_SPDIFI1);
1368 cmiData->invertPhaseSPDI = (that->CMIAdapter->readUInt8(REG_MIXER4) & INV_SPDIFI1);
1369 } else {
1370 cmiData->select2ndSPDI = (that->CMIAdapter->readUInt32(REG_MISCCTRL) & SEL_SPDIFI2);
1371 cmiData->invertPhaseSPDI = (that->CMIAdapter->readUInt32(REG_CHFORMAT) & INV_SPDIFI2);
1372 }
1373
1374 PropertyRequest->ValueSize = sizeof(CMIDATA);
1375 ntStatus = STATUS_SUCCESS;
1376 } else if (PropertyRequest->Verb & KSPROPERTY_TYPE_SET) {
1377 if (PropertyRequest->PropertyItem->Id != KSPROPERTY_CMI_SET) {
1378 return STATUS_INVALID_DEVICE_REQUEST;
1379 }
1380
1381 if (PropertyRequest->ValueSize == 0) {
1382 PropertyRequest->ValueSize = sizeof(CMIDATA);
1383 return STATUS_BUFFER_OVERFLOW;
1384 } else if (PropertyRequest->ValueSize < sizeof (CMIDATA)) {
1385 PropertyRequest->ValueSize = 0;
1386 return STATUS_BUFFER_TOO_SMALL;
1387 }
1388 CMIDATA* cmiData = (CMIDATA*)PropertyRequest->Value;
1389 that->cm->enableSPDIFIn = cmiData->enableSPDI;
1390 that->cm->enableSPDIFOut = cmiData->enableSPDO;
1391 that->cm->formatMask = cmiData->formatMask;
1392
1393 if (cmiData->enableSPDI) {
1394 that->CMIAdapter->setUInt8Bit(REG_MIXER1, EN_WAVEIN_L | EN_WAVEIN_R);
1395 } else {
1396 that->CMIAdapter->clearUInt8Bit(REG_MIXER1, EN_WAVEIN_L | EN_WAVEIN_R);
1397 }
1398
1399 if (cmiData->exchangeFrontBack) {
1400 that->CMIAdapter->setUInt8Bit(REG_MIXER1, REAR2FRONT);
1401 } else {
1402 that->CMIAdapter->clearUInt8Bit(REG_MIXER1, REAR2FRONT);
1403 }
1404 if (cmiData->enableSPDO5V) {
1405 that->CMIAdapter->setUInt32Bit(REG_MISCCTRL, EN_SPDO5V);
1406 } else {
1407 that->CMIAdapter->clearUInt32Bit(REG_MISCCTRL, EN_SPDO5V);
1408 }
1409 if (cmiData->enablePCMDAC) {
1410 that->CMIAdapter->setUInt8Bit(REG_MIXER1, EN_SPDI2DAC);
1411 } else {
1412 that->CMIAdapter->clearUInt8Bit(REG_MIXER1, EN_SPDI2DAC);
1413 }
1414 if (cmiData->enableBass2Line) {
1415 that->CMIAdapter->setUInt32Bit(REG_LEGACY, BASS2LINE);
1416 } else {
1417 that->CMIAdapter->clearUInt32Bit(REG_LEGACY, BASS2LINE);
1418 }
1419 if (cmiData->enableCenter2Line) {
1420 that->CMIAdapter->setUInt32Bit(REG_LEGACY, CENTER2LINE);
1421 } else {
1422 that->CMIAdapter->clearUInt32Bit(REG_LEGACY, CENTER2LINE);
1423 }
1424 if (cmiData->enableRear2Line) {
1425 that->CMIAdapter->setUInt8Bit(REG_MIXER1, REAR2LINE);
1426 } else {
1427 that->CMIAdapter->clearUInt8Bit(REG_MIXER1, REAR2LINE);
1428 }
1429 if (that->cm->chipVersion > 37) {
1430 if (cmiData->enableCenter2Mic) {
1431 that->CMIAdapter->setUInt8Bit(REG_MIXER4, CENTER2MIC);
1432 } else {
1433 that->CMIAdapter->clearUInt8Bit(REG_MIXER4, CENTER2MIC);
1434 }
1435 }
1436 if (cmiData->enableSPDOCopyright) {
1437 that->CMIAdapter->setUInt32Bit(REG_LEGACY, EN_SPDCOPYRHT);
1438 } else {
1439 that->CMIAdapter->clearUInt32Bit(REG_LEGACY, EN_SPDCOPYRHT);
1440 }
1441 if (cmiData->invertValidBitSPDI) {
1442 that->CMIAdapter->setUInt32Bit(REG_CHFORMAT, POLVALID);
1443 } else {
1444 that->CMIAdapter->clearUInt32Bit(REG_CHFORMAT, POLVALID);
1445 }
1446 if (cmiData->loopSPDI) {
1447 that->CMIAdapter->setUInt32Bit(REG_FUNCTRL1, LOOP_SPDF);
1448 } else {
1449 that->CMIAdapter->clearUInt32Bit(REG_FUNCTRL1, LOOP_SPDF);
1450 }
1451 if (cmiData->select2ndSPDI) {
1452 if (that->cm->chipVersion <= 37) {
1453 that->CMIAdapter->setUInt32Bit(REG_CHFORMAT, SEL_SPDIFI1);
1454 } else {
1455 that->CMIAdapter->setUInt32Bit(REG_MISCCTRL, SEL_SPDIFI2);
1456 }
1457 } else {
1458 if (that->cm->chipVersion <= 37) {
1459 that->CMIAdapter->clearUInt32Bit(REG_CHFORMAT, SEL_SPDIFI1);
1460 } else {
1461 that->CMIAdapter->clearUInt32Bit(REG_MISCCTRL, SEL_SPDIFI2);
1462 }
1463 }
1464 if (cmiData->invertPhaseSPDI) {
1465 if (that->cm->chipVersion <= 37) {
1466 that->CMIAdapter->setUInt8Bit(REG_MIXER4, INV_SPDIFI1);
1467 } else {
1468 that->CMIAdapter->setUInt32Bit(REG_CHFORMAT, INV_SPDIFI2);
1469 }
1470 } else {
1471 if (that->cm->chipVersion <= 37) {
1472 that->CMIAdapter->clearUInt8Bit(REG_MIXER4, INV_SPDIFI1);
1473 } else {
1474 that->CMIAdapter->clearUInt32Bit(REG_CHFORMAT, INV_SPDIFI2);
1475 }
1476 }
1477
1478 that->storeMixerSettingsToRegistry();
1479
1480 ntStatus = STATUS_SUCCESS;
1481 } else if (PropertyRequest->Verb & KSPROPERTY_TYPE_BASICSUPPORT) {
1482 if (PropertyRequest->ValueSize >= sizeof(ULONG)) {
1483 PULONG AccessFlags = PULONG(PropertyRequest->Value);
1484
1485 *AccessFlags = KSPROPERTY_TYPE_BASICSUPPORT | KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_SET;
1486
1487 PropertyRequest->ValueSize = sizeof(ULONG);
1488 ntStatus = STATUS_SUCCESS;
1489 } else {
1490 PropertyRequest->ValueSize = 0;
1491 ntStatus = STATUS_BUFFER_TOO_SMALL;
1492 }
1493 }
1494
1495 return ntStatus;
1496 }