ReactOS  0.4.15-dev-4872-g8a3db97
prophnd.cpp
Go to the documentation of this file.
1 /********************************************************************************
2 ** Copyright (c) 1998-2000 Microsoft Corporation. All Rights Reserved.
3 **
4 ** Portions Copyright (c) 1998-1999 Intel Corporation
5 **
6 ********************************************************************************/
7 
8 /* The file prophnd.cpp was reviewed by LCA in June 2011 and is acceptable for use by Microsoft. */
9 
10 // Every debug output has "Modulname text".
11 #define STR_MODULENAME "AC97 Property handler: "
12 
13 #include "mintopo.h"
14 
15 // These are the values passed to the property handler in the instance
16 // parameter that normally represents the channel.
17 const LONG CHAN_LEFT = 0;
18 const LONG CHAN_RIGHT = 1;
19 const LONG CHAN_MASTER = -1;
20 
21 
22 // paged code goes here.
23 #ifdef _MSC_VER
24 #pragma code_seg("PAGE")
25 #endif
26 
27 
28 /*****************************************************************************
29  * CAC97MiniportTopology::SetMultichannelMute
30  *****************************************************************************
31  * This function is used to set one of the multichannel mutes.
32  * It takes the master mono into account when calculating the mute.
33  * Make sure that you updated the stNodeCache before calling this function.
34  */
36 (
38  IN TopoNodes Mute
39 )
40 {
41  PAGED_CODE();
42 
43  NTSTATUS ntStatus = STATUS_SUCCESS;
44  BOOL bMute;
45 
46  // The first calls to SetMultichannelMute could be without valid
47  // cache information because WDMAUD might currently query the nodes
48  // (this is at system startup). When WDMAUD queried all nodes then
49  // all cache information will be valid.
50  if (that->stNodeCache[NODE_VIRT_MASTERMONO_MUTE].bLeftValid &&
51  that->stNodeCache[Mute].bLeftValid)
52  {
53  // We get the master mono mute and the mute that is to change.
54  // Then we "or" them and write the value to the register.
55  bMute = that->stNodeCache[NODE_VIRT_MASTERMONO_MUTE].lLeft ||
56  that->stNodeCache[Mute].lLeft;
57 
58  ntStatus = that->AdapterCommon->WriteCodecRegister (
59  that->AdapterCommon->GetNodeReg (Mute),
60  bMute ? -1 : 0,
61  that->AdapterCommon->GetNodeMask (Mute));
62 
63  DOUT (DBG_PROPERTY, ("SET: %s -> 0x%x", NodeStrings[Mute], (int)bMute));
64  }
65 
66  return ntStatus;
67 }
68 
69 /*****************************************************************************
70  * CAC97MiniportTopology::SetMultichannelVolume
71  *****************************************************************************
72  * This function is used to set one of the multichannel volumes.
73  * It takes the master mono into account when calculating the volume.
74  * Make sure that you updated the stNodeCache before calling this function.
75  */
77 (
80 )
81 {
82  PAGED_CODE();
83 
84  NTSTATUS ntStatus = STATUS_SUCCESS;
86  ULONG uStep;
87  LONG lLevel;
88  WORD wRegister;
89 
90  // The first calls to SetMultichannelMute could be without valid
91  // cache information because WDMAUD might currently query the nodes
92  // (this is at system startup). When WDMAUD queried all nodes then
93  // all cache information will be valid.
94  if (that->stNodeCache[NODE_VIRT_MASTERMONO_VOLUME].bLeftValid &&
95  that->stNodeCache[NODE_VIRT_MASTERMONO_VOLUME].bRightValid &&
96  that->stNodeCache[Volume].bLeftValid &&
97  that->stNodeCache[Volume].bRightValid)
98  {
99  // We get the master mono volume and the volume that is to change.
100  // Then we substract master mono from it and write the value to the
101  // register.
102  lLevel = that->stNodeCache[Volume].lLeft +
103  that->stNodeCache[NODE_VIRT_MASTERMONO_VOLUME].lLeft;
104 
105  // Translate the dB value into a register value.
106 
107  // Get the registered DB values
108  ntStatus = GetDBValues (that->AdapterCommon, Volume,
109  &lMinimum, &lMaximum, &uStep);
110  if (!NT_SUCCESS(ntStatus))
111  return ntStatus;
112 
113  // Check borders.
114  if (lLevel < lMinimum) lLevel = lMinimum;
115  if (lLevel > lMaximum) lLevel = lMaximum;
116 
117  // Calculate the register value
118  wRegister = (WORD)(((lMaximum + uStep / 2) - lLevel) / uStep) << 8;
119 
120  // Get the right value too.
121  lLevel = that->stNodeCache[Volume].lRight +
122  that->stNodeCache[NODE_VIRT_MASTERMONO_VOLUME].lRight;
123 
124  // Check borders.
125  if (lLevel < lMinimum) lLevel = lMinimum;
126  if (lLevel > lMaximum) lLevel = lMaximum;
127 
128  // Add it to the register value.
129  wRegister += (WORD)(((lMaximum + uStep / 2) - lLevel) / uStep);
130 
131  // Write it.
132  ntStatus = that->AdapterCommon->WriteCodecRegister (
133  that->AdapterCommon->GetNodeReg (Volume),
134  wRegister,
135  that->AdapterCommon->GetNodeMask (Volume));
136 
137  DOUT (DBG_PROPERTY, ("SET: %s -> 0x%x/0x%x", NodeStrings[Volume],
138  that->stNodeCache[Volume].lLeft +
139  that->stNodeCache[NODE_VIRT_MASTERMONO_VOLUME].lLeft,
140  lLevel));
141  }
142 
143  return ntStatus;
144 }
145 
146 /*****************************************************************************
147  * CAC97MiniportTopology::GetDBValues
148  *****************************************************************************
149  * This function is used internally and does no parameter checking. The only
150  * parameter that could be invalid is the node.
151  * It returns the dB values (means minimum, maximum, step) of the node control,
152  * mainly for the property call "basic support". Sure, the node must be a
153  * volume or tone control node, not a mute or mux node.
154  */
156 (
157  IN PADAPTERCOMMON AdapterCommon,
158  IN TopoNodes Node,
159  OUT LONG *plMinimum,
160  OUT LONG *plMaximum,
161  OUT ULONG *puStep
162 )
163 {
164  PAGED_CODE();
165 
166  DOUT (DBG_PRINT, ("[CAC97MiniportTopology::GetDBValues]"));
167 
168  // This is going to be simple. Check the node and return the parameters.
169  switch (Node)
170  {
171  // These nodes could have 5bit or 6bit controls, so we first
172  // have to check this.
174  case NODE_FRONT_VOLUME:
175  case NODE_HPOUT_VOLUME:
177  case NODE_CENTER_VOLUME:
178  case NODE_LFE_VOLUME:
181  // needed for the config query
183 
184  // which node to query?
188  if (Node == NODE_HPOUT_VOLUME)
190  if (Node == NODE_SURROUND_VOLUME)
192  if ((Node == NODE_CENTER_VOLUME) || (Node == NODE_LFE_VOLUME))
194 
195  // check if we have 6th bit support.
196  if (AdapterCommon->GetNodeConfig (config))
197  {
198  // 6bit control
199  *plMaximum = 0; // 0 dB
200  *plMinimum = 0xFFA18000; // -94.5 dB
201  *puStep = 0x00018000; // 1.5 dB
202  }
203  else
204  {
205  // 5bit control
206  *plMaximum = 0; // 0 dB
207  *plMinimum = 0xFFD18000; // -46.5 dB
208  *puStep = 0x00018000; // 1.5 dB
209  }
210  break;
211 
213  // This virtual control gets added to the speaker volumes.
214  // We assume 5-bit volumes.
215  *plMaximum = 0; // 0 dB
216  *plMinimum = 0xFFD18000; // -46.5 dB
217  *puStep = 0x00018000; // 1.5 dB
218  break;
219 
220  case NODE_PCBEEP_VOLUME:
221  *plMaximum = 0; // 0 dB
222  *plMinimum = 0xFFD30000; // -45 dB
223  *puStep = 0x00030000; // 3 dB
224  break;
225 
226  case NODE_PHONE_VOLUME:
227  case NODE_MICIN_VOLUME:
228  case NODE_LINEIN_VOLUME:
229  case NODE_CD_VOLUME:
230  case NODE_VIDEO_VOLUME:
231  case NODE_AUX_VOLUME:
232  case NODE_WAVEOUT_VOLUME:
233  *plMaximum = 0x000C0000; // 12 dB
234  *plMinimum = 0xFFDD8000; // -34.5 dB
235  *puStep = 0x00018000; // 1.5 dB
236  break;
237 
238 
247  case NODE_MIC_VOLUME:
248  *plMaximum = 0x00168000; // 22.5 dB
249  *plMinimum = 0; // 0 dB
250  *puStep = 0x00018000; // 1.5 dB
251  break;
252 
253  case NODE_BASS:
254  case NODE_TREBLE:
255  *plMaximum = 0x000A8000; // 10.5 dB
256  *plMinimum = 0xFFF58000; // -10.5 dB
257  *puStep = 0x00018000; // 1.5 dB
258  break;
259 
260  // These nodes can be fixed or variable.
261  // Normally we won't display a fixed volume slider, but if 3D is
262  // supported and both sliders are fixed, we have to display one fixed
263  // slider for the advanced control panel.
264  case NODE_VIRT_3D_CENTER:
265  case NODE_VIRT_3D_DEPTH:
266  if (AdapterCommon->GetNodeConfig (NODEC_3D_CENTER_ADJUSTABLE) &&
268  {
269  *plMaximum = 0x000F0000; // +15 dB
270  *plMinimum = 0x00000000; // 0 dB
271  *puStep = 0x00010000; // 1 dB
272  }
273  else
274  if (AdapterCommon->GetNodeConfig (NODEC_3D_DEPTH_ADJUSTABLE) &&
276  {
277  *plMaximum = 0x000F0000; // +15 dB
278  *plMinimum = 0x00000000; // 0 dB
279  *puStep = 0x00010000; // 1 dB
280  }
281  else
282  {
283  // In case it is fixed, read the value and return it.
284  WORD wRegister;
285 
286  // read the register
287  if (!NT_SUCCESS (AdapterCommon->ReadCodecRegister (
288  AdapterCommon->GetNodeReg (Node), &wRegister)))
289  wRegister = 0; // in case we fail.
290 
291  // mask out the control
292  wRegister &= AdapterCommon->GetNodeMask (Node);
293  if (Node == NODE_VIRT_3D_CENTER)
294  {
295  wRegister >>= 8;
296  }
297  // calculate the dB value.
298  *plMaximum = (DWORD)(-wRegister) << 16; // fixed value
299  *plMinimum = (DWORD)(-wRegister) << 16; // fixed value
300  *puStep = 0x00010000; // 1 dB
301  }
302  break;
303 
304  case NODE_INVALID:
305  default:
306  // poeser pupe, tu.
307  DOUT (DBG_ERROR, ("GetDBValues: Invalid node requested."));
309  }
310 
311  return STATUS_SUCCESS;
312 }
313 
314 /*****************************************************************************
315  * CAC97MiniportTopology::PropertyHandler_OnOff
316  *****************************************************************************
317  * Accesses a KSAUDIO_ONOFF value property.
318  * This function (property handler) is called by portcls every time there is a
319  * get or a set request for the node. The connection between the node type and
320  * the property handler is made in the automation table which is referenced
321  * when you register the node.
322  * We use this property handler for all nodes that have a checkbox, means mute
323  * controls and the special checkbox controls under advanced properties, which
324  * are AGC and LOUDNESS.
325  */
327 (
328  IN PPCPROPERTY_REQUEST PropertyRequest
329 )
330 {
331  PAGED_CODE ();
332 
333  ASSERT (PropertyRequest);
334 
336  LONG channel;
337  TopoNodes NodeDef;
338  // The major target is the object pointer to the topology miniport.
339  CAC97MiniportTopology *that =
340  (CAC97MiniportTopology *) PropertyRequest->MajorTarget;
341 
342  ASSERT (that);
343 
344  DOUT (DBG_PRINT, ("[CAC97MiniportTopology::PropertyHandler_OnOff]"));
345 
346  // validate node
347  if (PropertyRequest->Node == (ULONG)-1)
348  return ntStatus;
349 
350  // do the appropriate action for the request.
351 
352  // we should do a get or a set?
353  if ((PropertyRequest->Verb & KSPROPERTY_TYPE_GET) ||
354  (PropertyRequest->Verb & KSPROPERTY_TYPE_SET))
355  {
356  // validate parameters
357  if ((PropertyRequest->InstanceSize < sizeof(LONG)) ||
358  (PropertyRequest->ValueSize < sizeof(BOOL)))
359  return ntStatus;
360 
361  // get channel
362  channel = *(PLONG)PropertyRequest->Instance;
363 
364  // check channel types, return when unknown
365  // as you can see, we have no multichannel support.
366  if ((channel != CHAN_LEFT) &&
367  (channel != CHAN_RIGHT) &&
368  (channel != CHAN_MASTER))
369  return ntStatus;
370 
371  // We have only mono mutes or On/Off checkboxes although they might control
372  // a stereo path. For example, we have a 1-bit mute for CD Volume. This
373  // mute controls both CD Volume channels.
374  if (channel == CHAN_RIGHT)
375  return ntStatus;
376 
377  // get the buffer
378  PBOOL OnOff = (PBOOL)PropertyRequest->Value;
379 
380  // Switch on the node id. This is just for parameter checking.
381  // If something goes wrong, we will immediately return with
382  // ntStatus, which is STATUS_INVALID_PARAMETER.
383  switch (NodeDef = that->TransNodeNrToNodeDef (PropertyRequest->Node))
384  {
385  // These are mutes for mono volumes.
386  case NODE_PCBEEP_MUTE:
387  case NODE_PHONE_MUTE:
388  case NODE_MIC_MUTE:
389  case NODE_MICIN_MUTE:
390  case NODE_CENTER_MUTE:
391  case NODE_LFE_MUTE:
393  // check type
394  if (PropertyRequest->PropertyItem->Id != KSPROPERTY_AUDIO_MUTE)
395  return ntStatus;
396  break;
397 
398  // Well, this one is a AGC, although there is no _automatic_ gain
399  // control, but we have a mic boost (which is some kind of manual
400  // gain control).
401  // The 3D Bypass is a real fake, but that's how you get check boxes
402  // on the advanced control panel.
403  // Both controls are in a mono path.
405  case NODE_MIC_BOOST:
406  // check type
407  if (PropertyRequest->PropertyItem->Id != KSPROPERTY_AUDIO_AGC)
408  return ntStatus;
409  break;
410 
411  // Simulated Stereo is a AGC control in a stereo path.
412  case NODE_SIMUL_STEREO:
413  // check type
414  if (PropertyRequest->PropertyItem->Id != KSPROPERTY_AUDIO_AGC)
415  return ntStatus;
416  break;
417 
418  // This is a loudness control in a stereo path. We have to check the
419  // type.
420  case NODE_LOUDNESS:
421  // check type
422  if (PropertyRequest->PropertyItem->Id != KSPROPERTY_AUDIO_LOUDNESS)
423  return ntStatus;
424  break;
425 
426  // For 3D Enable and Mic are exposed as loudness in a mono path.
427  case NODE_VIRT_3D_ENABLE:
428  case NODE_MIC_SELECT:
429  // check type
430  if (PropertyRequest->PropertyItem->Id != KSPROPERTY_AUDIO_LOUDNESS)
431  return ntStatus;
432  break;
433 
434  // These are mutes in a stereo path.
435  // Because the HW has only one mute-bit for the stereo channel, we
436  // expose the mute as mono. this works in current OS and hopefully
437  // will work in future OS.
438  case NODE_WAVEOUT_MUTE:
439  case NODE_LINEIN_MUTE:
440  case NODE_CD_MUTE:
441  case NODE_VIDEO_MUTE:
442  case NODE_AUX_MUTE:
443  case NODE_MASTEROUT_MUTE:
444  case NODE_FRONT_MUTE:
445  case NODE_SURROUND_MUTE:
446  case NODE_HPOUT_MUTE:
447  // just check the type.
448  if (PropertyRequest->PropertyItem->Id != KSPROPERTY_AUDIO_MUTE)
449  return ntStatus;
450  break;
451 
452  case NODE_INVALID:
453  default:
454  // Ooops.
455  DOUT (DBG_ERROR, ("PropertyHandler_OnOff: Invalid node requested."));
456  return ntStatus;
457  }
458 
459  // Now, do some action!
460 
461  if (PropertyRequest->Verb & KSPROPERTY_TYPE_GET)
462  {
463  WORD wRegister;
464 
465  // Read the HW register for the node except NODE_VIRT_MASTERMONO_MUTE,
466  // since this is pure virtual.
467  if (NodeDef != NODE_VIRT_MASTERMONO_MUTE)
468  {
469  // get the register and read it.
470  ntStatus = that->AdapterCommon->ReadCodecRegister (
471  that->AdapterCommon->GetNodeReg (NodeDef), &wRegister);
472  if (!NT_SUCCESS (ntStatus))
473  return ntStatus;
474  // Mask out every unused bit.
475  wRegister &= that->AdapterCommon->GetNodeMask (NodeDef);
476  // Store the value.
477  *OnOff = wRegister ? TRUE : FALSE;
478  }
479  else
480  {
481  // Assume no mute for master mono.
482  *OnOff = FALSE;
483  }
484 
485  // When we have cache information then return this instead of the
486  // calculated value. If we don't, store the calculated value.
487  if (that->stNodeCache[NodeDef].bLeftValid)
488  *OnOff = that->stNodeCache[NodeDef].lLeft;
489  else
490  {
491  that->stNodeCache[NodeDef].lLeft = *OnOff;
492  that->stNodeCache[NodeDef].bLeftValid = (BYTE)-1;
493  }
494 
495  PropertyRequest->ValueSize = sizeof(BOOL);
496  DOUT (DBG_PROPERTY, ("GET: %s = 0x%x", NodeStrings[NodeDef], *OnOff));
497 
498  // Set the return code here.
499  ntStatus = STATUS_SUCCESS;
500  }
501  else // this must be a set.
502  {
503  // First update the node cache.
504  that->stNodeCache[NodeDef].bLeftValid = (BYTE)-1;
505  that->stNodeCache[NodeDef].lLeft = (*OnOff) ? TRUE : FALSE;
506 
507  //
508  // If we have a master mono, then we have to program the speaker
509  // mutes a little different.
510  // Check for master mono (surround or headphone present) and
511  // if one of the speaker mutes is requested.
512  //
513  if ((that->AdapterCommon->GetPinConfig (PINC_SURROUND_PRESENT) ||
514  that->AdapterCommon->GetPinConfig (PINC_HPOUT_PRESENT)) &&
515  ((NodeDef == NODE_VIRT_MASTERMONO_MUTE) || (NodeDef == NODE_LFE_MUTE) ||
516  (NodeDef == NODE_CENTER_MUTE) || (NodeDef == NODE_FRONT_MUTE) ||
517  (NodeDef == NODE_SURROUND_MUTE) || (NodeDef == NODE_HPOUT_MUTE)))
518  {
519  //
520  // For master mono we have to update all speakers.
521  //
522  if (NodeDef == NODE_VIRT_MASTERMONO_MUTE)
523  {
524  // Update all speaker mutes.
525  ntStatus = SetMultichannelMute (that, NODE_FRONT_MUTE);
526  if (that->AdapterCommon->GetPinConfig (PINC_HPOUT_PRESENT))
527  ntStatus = SetMultichannelMute (that, NODE_HPOUT_MUTE);
528  if (that->AdapterCommon->GetPinConfig (PINC_SURROUND_PRESENT))
529  ntStatus = SetMultichannelMute (that, NODE_SURROUND_MUTE);
530  if (that->AdapterCommon->GetPinConfig (PINC_CENTER_LFE_PRESENT))
531  {
532  ntStatus = SetMultichannelMute (that, NODE_CENTER_MUTE);
533  ntStatus = SetMultichannelMute (that, NODE_LFE_MUTE);
534  }
535  }
536  else // Update the individual speaker mute.
537  {
538  ntStatus = SetMultichannelMute (that, NodeDef);
539  }
540  }
541  else
542  {
543  //
544  // For all other mutes/checkboxes just write the value to the HW.
545  //
546  ntStatus = that->AdapterCommon->WriteCodecRegister (
547  that->AdapterCommon->GetNodeReg (NodeDef),
548  (*OnOff) ? -1 : 0,
549  that->AdapterCommon->GetNodeMask (NodeDef));
550  }
551 
552  DOUT (DBG_PROPERTY, ("SET: %s -> 0x%x", NodeStrings[NodeDef], *OnOff));
553 
554  // ntStatus was set with the write call! whatever this is, return it.
555  }
556  }
557 
558  return ntStatus;
559 }
560 
561 /*****************************************************************************
562  * CAC97MiniportTopology::BasicSupportHandler
563  *****************************************************************************
564  * Assists in BASICSUPPORT accesses on level properties.
565  * This function is called internally every time there is a "basic support"
566  * request on a volume or tone control. The basic support is used to retrieve
567  * some information about the range of the control (from - to dB, steps) and
568  * which type of control (tone, volume).
569  * Basically, this function just calls GetDBValues to get the range information
570  * and fills the rest of the structure with some constants.
571  */
573 (
574  IN PPCPROPERTY_REQUEST PropertyRequest
575 )
576 {
577  PAGED_CODE ();
578 
579  ASSERT (PropertyRequest);
580 
581  DOUT (DBG_PRINT, ("[CAC97MiniportTopology::BasicSupportHandler]"));
582 
584  // The major target is the object pointer to the topology miniport.
585  CAC97MiniportTopology *that =
586  (CAC97MiniportTopology *) PropertyRequest->MajorTarget;
587 
588  ASSERT (that);
589 
590 
591  // if there is enough space for a KSPROPERTY_DESCRIPTION information
592  if (PropertyRequest->ValueSize >= (sizeof(KSPROPERTY_DESCRIPTION)))
593  {
594  // we return a KSPROPERTY_DESCRIPTION structure.
595  PKSPROPERTY_DESCRIPTION PropDesc = (PKSPROPERTY_DESCRIPTION)PropertyRequest->Value;
596 
600  PropDesc->DescriptionSize = sizeof(KSPROPERTY_DESCRIPTION) +
601  sizeof(KSPROPERTY_MEMBERSHEADER) +
602  sizeof(KSPROPERTY_STEPPING_LONG);
604  PropDesc->PropTypeSet.Id = VT_I4;
605  PropDesc->PropTypeSet.Flags = 0;
606  PropDesc->MembersListCount = 1;
607  PropDesc->Reserved = 0;
608 
609  // if return buffer can also hold a range description, return it too
610  if (PropertyRequest->ValueSize >= (sizeof(KSPROPERTY_DESCRIPTION) +
612  {
613  // fill in the members header
614  PKSPROPERTY_MEMBERSHEADER Members = (PKSPROPERTY_MEMBERSHEADER)(PropDesc + 1);
615 
617  Members->MembersSize = sizeof(KSPROPERTY_STEPPING_LONG);
618  Members->MembersCount = 1;
619  Members->Flags = 0;
620 
621  // fill in the stepped range
623 
624  ntStatus = GetDBValues (that->AdapterCommon,
625  that->TransNodeNrToNodeDef (PropertyRequest->Node),
626  &Range->Bounds.SignedMinimum,
627  &Range->Bounds.SignedMaximum,
628  &Range->SteppingDelta);
629 
630  Range->Reserved = 0;
631 
632  // set the return value size
633  PropertyRequest->ValueSize = sizeof(KSPROPERTY_DESCRIPTION) +
634  sizeof(KSPROPERTY_MEMBERSHEADER) +
635  sizeof(KSPROPERTY_STEPPING_LONG);
636 
637  DOUT (DBG_PROPERTY, ("BASIC_SUPPORT: %s max=0x%x min=0x%x step=0x%x",
638  NodeStrings[that->TransNodeNrToNodeDef (PropertyRequest->Node)],
639  Range->Bounds.SignedMaximum, Range->Bounds.SignedMinimum,
640  Range->SteppingDelta));
641  } else
642  {
643  // we hadn't enough space for the range information;
644  // set the return value size
645  PropertyRequest->ValueSize = sizeof(KSPROPERTY_DESCRIPTION);
646  }
647 
648  ntStatus = STATUS_SUCCESS;
649  }
650  else if (PropertyRequest->ValueSize >= sizeof(ULONG))
651  {
652  // if return buffer can hold a ULONG, return the access flags
653  PULONG AccessFlags = (PULONG)PropertyRequest->Value;
654 
655  *AccessFlags = KSPROPERTY_TYPE_BASICSUPPORT |
658 
659  // set the return value size
660  PropertyRequest->ValueSize = sizeof(ULONG);
661  ntStatus = STATUS_SUCCESS;
662  }
663 
664  // In case there was not even enough space for a ULONG in the return buffer,
665  // we fail this request with STATUS_INVALID_DEVICE_REQUEST.
666  // Any other case will return STATUS_SUCCESS.
667  return ntStatus;
668 }
669 
670 /*****************************************************************************
671  * CAC97MiniportTopology::PropertyHandler_Level
672  *****************************************************************************
673  * Accesses a KSAUDIO_LEVEL property.
674  * This function (property handler) is called by portcls every time there is a
675  * get, set or basic support request for the node. The connection between the
676  * node type and the property handler is made in the automation table which is
677  * referenced when you register the node.
678  * We use this property handler for all volume controls (and virtual volume
679  * controls for recording).
680  */
682 (
683  IN PPCPROPERTY_REQUEST PropertyRequest
684 )
685 {
686  PAGED_CODE ();
687 
688  ASSERT (PropertyRequest);
689 
690  DOUT (DBG_PRINT, ("[CAC97MiniportTopology::PropertyHandler_Level]"));
691 
693  TopoNodes NodeDef;
694  LONG channel;
696  ULONG uStep;
697  // The major target is the object pointer to the topology miniport.
698  CAC97MiniportTopology *that =
699  (CAC97MiniportTopology *) PropertyRequest->MajorTarget;
700 
701  ASSERT (that);
702 
703  // validate node
704  if (PropertyRequest->Node == (ULONG)-1)
705  return ntStatus;
706 
707  // do the appropriate action for the request.
708 
709  // we should do a get or a set?
710  if ((PropertyRequest->Verb & KSPROPERTY_TYPE_GET) ||
711  (PropertyRequest->Verb & KSPROPERTY_TYPE_SET))
712  {
713  // validate parameters
714  if ((PropertyRequest->InstanceSize < sizeof(LONG)) ||
715  (PropertyRequest->ValueSize < sizeof(LONG)))
716  return ntStatus;
717 
718  // get channel information
719  channel = *((PLONG)PropertyRequest->Instance);
720 
721  // check channel types, return when unknown
722  // as you can see, we have no multichannel support.
723  if ((channel != CHAN_LEFT) &&
724  (channel != CHAN_RIGHT) &&
725  (channel != CHAN_MASTER))
726  return ntStatus;
727 
728  // get the buffer
729  PLONG Level = (PLONG)PropertyRequest->Value;
730 
731  // Switch on the node id. This is just for parameter checking.
732  // If something goes wrong, we will immideately return with
733  // ntStatus, which is STATUS_INVALID_PARAMETER.
734  switch(NodeDef = that->TransNodeNrToNodeDef (PropertyRequest->Node))
735  {
736  // these are mono channels, don't respond to a right channel
737  // request.
738  case NODE_PCBEEP_VOLUME:
739  case NODE_PHONE_VOLUME:
740  case NODE_MIC_VOLUME:
746  case NODE_MICIN_VOLUME:
748  case NODE_CENTER_VOLUME:
749  case NODE_LFE_VOLUME:
750  // check type
751  if (PropertyRequest->PropertyItem->Id != KSPROPERTY_AUDIO_VOLUMELEVEL)
752  return ntStatus;
753  // check channel
754  if (channel == CHAN_RIGHT)
755  return ntStatus;
756  // Well, this is a fake for the routine below that should work
757  // for all nodes ... On AC97 the right channel are the LSBs and
758  // mono channels have only LSBs used. Windows however thinks that
759  // mono channels are left channels (only). So we could say here
760  // we have a right channel request (to prg. the LSBs) instead of
761  // a left channel request. But we have some controls that are HW-
762  // stereo, but exposed to the system as mono. These are the virtual
763  // volume controls in front of the wave-in muxer for the MIC, PHONE
764  // and MONO MIX signals (see to the switch:
765  // NODE_VIRT_MASTER_INPUT_VOLUME1, 7 and 8). Saying we have a MASTER
766  // request makes sure the value is prg. for left and right channel,
767  // but on HW-mono controls the right channel is prg. only, cause the
768  // mask in ac97reg.h leads to a 0-mask for left channel prg. which
769  // just does nothing ;)
770  channel = CHAN_MASTER;
771  break;
772 
773  // These are stereo channels.
775  case NODE_FRONT_VOLUME:
777  case NODE_HPOUT_VOLUME:
778  case NODE_LINEIN_VOLUME:
779  case NODE_CD_VOLUME:
780  case NODE_VIDEO_VOLUME:
781  case NODE_AUX_VOLUME:
782  case NODE_WAVEOUT_VOLUME:
788  // check type
789  if (PropertyRequest->PropertyItem->Id != KSPROPERTY_AUDIO_VOLUMELEVEL)
790  return ntStatus;
791  // check channel; we don't support a get with master
792  if ((channel == CHAN_MASTER) &&
793  (PropertyRequest->Verb & KSPROPERTY_TYPE_GET))
794  return ntStatus;
795  break;
796 
797  case NODE_INVALID:
798  default:
799  // Ooops
800  DOUT (DBG_ERROR, ("PropertyHandler_Level: Invalid node requested."));
801  return ntStatus;
802  }
803 
804  // Now, do some action!
805 
806  // get the registered dB values.
807  ntStatus = GetDBValues (that->AdapterCommon, NodeDef, &lMinimum,
808  &lMaximum, &uStep);
809  if (!NT_SUCCESS (ntStatus))
810  return ntStatus;
811 
812  // do a get
813  if (PropertyRequest->Verb & KSPROPERTY_TYPE_GET)
814  {
815  WORD wRegister;
816 
817  // Read the HW register for the node except NODE_VIRT_MASTERMONO_VOLUME
818  // since this is pure virtual.
819  if (NodeDef != NODE_VIRT_MASTERMONO_VOLUME)
820  {
821  // Get the register and read it.
822  ntStatus = that->AdapterCommon->ReadCodecRegister (
823  that->AdapterCommon->GetNodeReg (NodeDef), &wRegister);
824  if (!NT_SUCCESS (ntStatus))
825  return ntStatus;
826 
827  // mask out every unused bit and rotate.
828  if (channel == CHAN_LEFT)
829  {
830  wRegister = (wRegister & (that->AdapterCommon->GetNodeMask (NodeDef)
831  & AC97REG_MASK_LEFT)) >> 8;
832  }
833  else // here goes mono or stereo-right
834  {
835  wRegister &= (that->AdapterCommon->GetNodeMask (NodeDef) &
837  }
838 
839  // Oops - NODE_PCBEEP_VOLUME doesn't use bit0. We have to adjust.
840  if (NodeDef == NODE_PCBEEP_VOLUME)
841  wRegister >>= 1;
842 
843  // we have to translate the reg to dB.dB value.
844 
845  switch (NodeDef)
846  {
847  // for record, we calculate it reverse.
856  case NODE_MICIN_VOLUME:
857  *Level = lMinimum + uStep * wRegister;
858  break;
859  default:
860  *Level = lMaximum - uStep * wRegister;
861  break;
862  }
863 
864  // For the virtual controls, which are in front of a muxer, there
865  // is no mute control displayed. But we have a HW mute control, so
866  // what we do is enabling this mute when the user moves the slider
867  // down to the bottom and disabling it on every other position.
868  // We will return a PROP_MOST_NEGATIVE value in case the slider
869  // is moved to the bottom.
870  // We do this only for the "mono muxer" since the volume there ranges
871  // from 0 to -46.5dB. The record volumes only have a range from
872  // 0 to +22.5dB and we cannot mute them when the slider is down.
873  if ((NodeDef == NODE_VIRT_MONOOUT_VOLUME1) ||
874  (NodeDef == NODE_VIRT_MONOOUT_VOLUME2))
875  {
876  // read the register again.
877  ntStatus = that->AdapterCommon->ReadCodecRegister (
878  that->AdapterCommon->GetNodeReg (NodeDef), &wRegister);
879  if (!NT_SUCCESS (ntStatus))
880  return ntStatus;
881  // return most negative value in case it is checked.
882  if (wRegister & AC97REG_MASK_MUTE)
884  }
885  }
886  else // This is master mono volume.
887  {
888  // Assume 0dB for master mono volume.
889  *Level = 0;
890  }
891 
892  // when we have cache information then return this instead
893  // of the calculated value. if we don't, store the calculated
894  // value.
895  // We do that twice for master because in case we didn't set
896  // the NodeCache yet it will be set then.
897  if ((channel == CHAN_LEFT) || (channel == CHAN_MASTER))
898  {
899  if (that->stNodeCache[NodeDef].bLeftValid)
900  *Level = that->stNodeCache[NodeDef].lLeft;
901  else
902  {
903  that->stNodeCache[NodeDef].lLeft = *Level;
904  that->stNodeCache[NodeDef].bLeftValid = (BYTE)-1;
905  }
906  }
907 
908  if ((channel == CHAN_RIGHT) || (channel == CHAN_MASTER))
909  {
910  if (that->stNodeCache[NodeDef].bRightValid)
911  *Level = that->stNodeCache[NodeDef].lRight;
912  else
913  {
914  that->stNodeCache[NodeDef].lRight = *Level;
915  that->stNodeCache[NodeDef].bRightValid = (BYTE)-1;
916  }
917  }
918 
919  // thats all, good bye.
920  PropertyRequest->ValueSize = sizeof(LONG);
921  DOUT (DBG_PROPERTY, ("GET: %s(%s) = 0x%x",NodeStrings[NodeDef],
922  channel==CHAN_LEFT ? "L" : "R", *Level));
923 
924  // ntStatus was set with the read call! whatever this is, return it.
925  }
926  else // this must be a set
927  {
928  WORD wRegister;
929  LONG lLevel = *Level;
930 
931  //
932  // Check borders.
933  //
934  // These 2 lines will have a special effect on sndvol32.
935  // Whenever you move the balance slider on a volume, one channel
936  // keeps the same and the other volume channel gets descreased.
937  // With ac97 on recording controls, the default slider position
938  // is at 0dB and the range of the volume is 0dB till +22.5dB.
939  // That means that panning (moving the balance slider) is simply
940  // impossible. If you would store the volume like sndvol gives it
941  // to you and you return it on a get, then the balance slider
942  // moves and stays at the position the user wanted it. However,
943  // if you return the actual volume the balance slider will jump
944  // back to the position that the HW can do (play with it to see
945  // how it works).
946  //
947  if (lLevel > lMaximum) lLevel = lMaximum;
948  if (lLevel < lMinimum) lLevel = lMinimum;
949 
950  // First update the node cache.
951  if ((channel == CHAN_LEFT) || (channel == CHAN_MASTER))
952  {
953  that->stNodeCache[NodeDef].bLeftValid = (BYTE)-1;
954  that->stNodeCache[NodeDef].lLeft = lLevel;
955  }
956  if ((channel == CHAN_RIGHT) || (channel == CHAN_MASTER))
957  {
958  that->stNodeCache[NodeDef].bRightValid = (BYTE)-1;
959  that->stNodeCache[NodeDef].lRight = lLevel;
960  }
961 
962  //
963  // If we have a master mono, then we have to program the speaker
964  // volumes a little different.
965  // Check for master mono (surround or headphone present) and
966  // if one of the speaker volumes is requested.
967  //
968  if ((that->AdapterCommon->GetPinConfig (PINC_SURROUND_PRESENT) ||
969  that->AdapterCommon->GetPinConfig (PINC_HPOUT_PRESENT)) &&
970  ((NodeDef == NODE_VIRT_MASTERMONO_VOLUME) || (NodeDef == NODE_LFE_VOLUME) ||
971  (NodeDef == NODE_CENTER_VOLUME) || (NodeDef == NODE_FRONT_VOLUME) ||
972  (NodeDef == NODE_SURROUND_VOLUME) || (NodeDef == NODE_HPOUT_VOLUME)))
973  {
974  //
975  // For master mono we have to update all speaker volumes.
976  //
977  if (NodeDef == NODE_VIRT_MASTERMONO_VOLUME)
978  {
979  // Update all speaker volumes.
980  ntStatus = SetMultichannelVolume (that, NODE_FRONT_VOLUME);
981  if (that->AdapterCommon->GetPinConfig (PINC_HPOUT_PRESENT))
982  ntStatus = SetMultichannelVolume (that, NODE_HPOUT_VOLUME);
983  if (that->AdapterCommon->GetPinConfig (PINC_SURROUND_PRESENT))
984  ntStatus = SetMultichannelVolume (that, NODE_SURROUND_VOLUME);
985  if (that->AdapterCommon->GetPinConfig (PINC_CENTER_LFE_PRESENT))
986  {
987  ntStatus = SetMultichannelVolume (that, NODE_CENTER_VOLUME);
988  ntStatus = SetMultichannelVolume (that, NODE_LFE_VOLUME);
989  }
990  }
991  else // update the individual speaker volume only.
992  {
993  ntStatus = SetMultichannelVolume (that, NodeDef);
994  }
995  }
996  else // This is for all other volumes (or no master mono present).
997  {
998  // calculate the dB.dB value.
999 
1000  // The nodes are calculated differently.
1001  switch (NodeDef)
1002  {
1003  // for record controls we calculate it 'reverse'.
1012  // read the wavein selector.
1013  ntStatus = that->AdapterCommon->ReadCodecRegister (
1014  that->AdapterCommon->GetNodeReg (NODE_WAVEIN_SELECT),
1015  &wRegister);
1016  if (!NT_SUCCESS (ntStatus))
1017  return ntStatus;
1018 
1019  // mask out every unused bit.
1020  wRegister &= (that->AdapterCommon->GetNodeMask (
1022 
1023  // check if the volume that we change belongs to the active
1024  // (selected) virtual channel.
1025  // Tricky: If the virtual nodes are not defined consecutively
1026  // this comparision will fail.
1027  if ((NodeDef - NODE_VIRT_MASTER_INPUT_VOLUME1) != wRegister)
1028  return ntStatus;
1029 
1030  // fall through for calculation.
1031 
1032  case NODE_MICIN_VOLUME:
1033  wRegister = (WORD)(((lLevel + uStep / 2) - lMinimum) / uStep);
1034  break;
1035 
1038  // read the monoout selector.
1039  ntStatus = that->AdapterCommon->ReadCodecRegister (
1040  that->AdapterCommon->GetNodeReg (NODE_MONOOUT_SELECT),
1041  &wRegister);
1042  if (!NT_SUCCESS (ntStatus))
1043  return ntStatus;
1044 
1045  // mask out every unused bit.
1046  wRegister &= that->AdapterCommon->GetNodeMask (NODE_MONOOUT_SELECT);
1047 
1048  // check if the volume that we change belongs to the active
1049  // (selected) virtual channel.
1050  // Note: Monout select is set if we want to prg. MIC (Volume2).
1051  if ((!wRegister && (NodeDef == NODE_VIRT_MONOOUT_VOLUME2)) ||
1052  (wRegister && (NodeDef == NODE_VIRT_MONOOUT_VOLUME1)))
1053  return ntStatus;
1054 
1055  // fall through for calculation.
1056  default:
1057  wRegister = (WORD)(((lMaximum + uStep / 2) - lLevel) / uStep);
1058  break;
1059  }
1060 
1061  // Oops - NODE_PCBEEP_VOLUME doesn't use bit0. We have to adjust.
1062  if (NodeDef == NODE_PCBEEP_VOLUME)
1063  wRegister <<= 1;
1064 
1065  // write the stuff (with mask!).
1066  // Note: mono channels are 'master' here (see fake above).
1067  // this makes sure that left and right channel is prg. for the virt.
1068  // controls. On controls that only have the right channel, the left
1069  // channel programming does nothing cause the mask will be zero.
1070  if ((channel == CHAN_LEFT) || (channel == CHAN_MASTER))
1071  {
1072  // write only left.
1073  ntStatus = that->AdapterCommon->WriteCodecRegister (
1074  that->AdapterCommon->GetNodeReg (NodeDef),
1075  wRegister << 8,
1076  that->AdapterCommon->GetNodeMask (NodeDef) & AC97REG_MASK_LEFT);
1077  // immediately return on error
1078  if (!NT_SUCCESS (ntStatus))
1079  return ntStatus;
1080  }
1081 
1082  if ((channel == CHAN_RIGHT) || (channel == CHAN_MASTER))
1083  {
1084  // write only right.
1085  ntStatus = that->AdapterCommon->WriteCodecRegister (
1086  that->AdapterCommon->GetNodeReg (NodeDef),
1087  wRegister,
1088  that->AdapterCommon->GetNodeMask (NodeDef) & AC97REG_MASK_RIGHT);
1089  // immediately return on error
1090  if (!NT_SUCCESS (ntStatus))
1091  return ntStatus;
1092  }
1093 
1094  // For the virtual controls, which are in front of a muxer, there
1095  // is no mute control displayed. But we have a HW mute control, so
1096  // what we do is enabling this mute when the user moves the slider
1097  // down to the bottom and disabling it on every other position.
1098  // We do this only for the "mono muxer", the recording mutes will
1099  // never be muted.
1100  // Tricky: Master input virtual controls must be defined consecutively.
1101  if ((NodeDef >= NODE_VIRT_MASTER_INPUT_VOLUME1) &&
1102  (NodeDef <= NODE_VIRT_MASTER_INPUT_VOLUME8))
1103  {
1104  // disable the mute; this only works because the mute and volume
1105  // share the same register.
1106  ntStatus = that->AdapterCommon->WriteCodecRegister (
1107  that->AdapterCommon->GetNodeReg (NodeDef),
1108  0, AC97REG_MASK_MUTE);
1109 
1110  // Just in case.
1111  that->UpdateRecordMute ();
1112  }
1113 
1114  if ((NodeDef == NODE_VIRT_MONOOUT_VOLUME1) ||
1115  (NodeDef == NODE_VIRT_MONOOUT_VOLUME2))
1116  {
1117  // these are only mono controls so checking one entry is enough.
1118  if ( that->stNodeCache[NodeDef].bLeftValid &&
1119  (that->stNodeCache[NodeDef].lLeft <= lMinimum))
1120  {
1121  // set the mute; this only works because the mute and volume
1122  // share the same register.
1123  ntStatus = that->AdapterCommon->WriteCodecRegister (
1124  that->AdapterCommon->GetNodeReg (NodeDef),
1126  }
1127  else
1128  {
1129  // clear the mute; this only works because the mute and volume
1130  // share the same register.
1131  ntStatus = that->AdapterCommon->WriteCodecRegister (
1132  that->AdapterCommon->GetNodeReg (NodeDef),
1133  0, AC97REG_MASK_MUTE);
1134  }
1135  }
1136  }
1137 
1138  DOUT (DBG_PROPERTY, ("SET: %s(%s) -> 0x%x", NodeStrings[NodeDef],
1139  channel==CHAN_LEFT ? "L" : channel==CHAN_RIGHT ? "R" : "M",
1140  *Level));
1141 
1142  // ntStatus was set with the read call! whatever this is, return it.
1143  }
1144  }
1145  else
1146  {
1147  if (PropertyRequest->Verb & KSPROPERTY_TYPE_BASICSUPPORT)
1148  {
1149  ntStatus = BasicSupportHandler (PropertyRequest);
1150  }
1151  }
1152 
1153  return ntStatus;
1154 }
1155 
1156 /*****************************************************************************
1157  * CAC97MiniportTopology::PropertyHandler_Tone
1158  *****************************************************************************
1159  * Accesses a KSAUDIO_TONE property.
1160  * This function (property handler) is called by portcls every time there is a
1161  * get, set or basic support request for the node. The connection between the
1162  * node type and the property handler is made in the automation table which is
1163  * referenced when you register the node.
1164  * We use this property handler for all tone controls displayed at the advanced
1165  * property dialog in sndvol32 and the 3D controls displayed and exposed as
1166  * normal volume controls.
1167  */
1170  IN PPCPROPERTY_REQUEST PropertyRequest
1171 )
1172 {
1173  PAGED_CODE ();
1174 
1175  ASSERT (PropertyRequest);
1176 
1177  DOUT (DBG_PRINT, ("[CAC97MiniportTopology::PropertyHandler_Tone]"));
1178 
1180  TopoNodes NodeDef;
1182  ULONG uStep;
1183  // The major target is the object pointer to the topology miniport.
1184  CAC97MiniportTopology *that =
1185  (CAC97MiniportTopology *) PropertyRequest->MajorTarget;
1186 
1187  ASSERT (that);
1188 
1189  // validate node
1190  if (PropertyRequest->Node == (ULONG)-1)
1191  return ntStatus;
1192 
1193  // do the appropriate action for the request.
1194 
1195  // we should do a get or a set?
1196  if ((PropertyRequest->Verb & KSPROPERTY_TYPE_GET) ||
1197  (PropertyRequest->Verb & KSPROPERTY_TYPE_SET))
1198  {
1199  // validate parameters
1200  if ((PropertyRequest->InstanceSize < sizeof(LONG)) ||
1201  (PropertyRequest->ValueSize < sizeof(LONG)))
1202  return ntStatus;
1203 
1204  // get the buffer
1205  PLONG Level = (PLONG)PropertyRequest->Value;
1206 
1207  // Switch on the node id. This is just for parameter checking.
1208  // If something goes wrong, we will immideately return with
1209  // ntStatus, which is STATUS_INVALID_PARAMETER.
1210  switch(NodeDef = that->TransNodeNrToNodeDef (PropertyRequest->Node))
1211  {
1212  case NODE_BASS:
1213  // check type.
1214  if (PropertyRequest->PropertyItem->Id != KSPROPERTY_AUDIO_BASS)
1215  return ntStatus;
1216  break;
1217 
1218  case NODE_TREBLE:
1219  // check type.
1220  if (PropertyRequest->PropertyItem->Id != KSPROPERTY_AUDIO_TREBLE)
1221  return ntStatus;
1222  break;
1223 
1224  case NODE_VIRT_3D_CENTER:
1225  case NODE_VIRT_3D_DEPTH:
1226  // check 3D control
1227  if (!that->AdapterCommon->GetNodeConfig (NODEC_3D_CENTER_ADJUSTABLE)
1228  && (NodeDef == NODE_VIRT_3D_CENTER))
1229  return ntStatus;
1230  if (!that->AdapterCommon->GetNodeConfig (NODEC_3D_DEPTH_ADJUSTABLE)
1231  && (NodeDef == NODE_VIRT_3D_DEPTH))
1232  return ntStatus;
1233  // check type
1234  if (PropertyRequest->PropertyItem->Id != KSPROPERTY_AUDIO_VOLUMELEVEL)
1235  return ntStatus;
1236  // check channel
1237  if (*(PLONG(PropertyRequest->Instance)) == CHAN_RIGHT)
1238  return ntStatus;
1239  break;
1240 
1241  case NODE_INVALID:
1242  default:
1243  // Ooops
1244  DOUT (DBG_ERROR, ("PropertyHandler_Tone: Invalid node requested."));
1245  return ntStatus;
1246  }
1247 
1248  // Now, do some action!
1249 
1250  // get the registered DB values
1251  ntStatus = GetDBValues (that->AdapterCommon, NodeDef, &lMinimum,
1252  &lMaximum, &uStep);
1253  if (!NT_SUCCESS (ntStatus))
1254  return ntStatus;
1255 
1256  // do a get
1257  if (PropertyRequest->Verb & KSPROPERTY_TYPE_GET)
1258  {
1259  WORD wRegister;
1260 
1261  // first get the stuff.
1262  ntStatus = that->AdapterCommon->ReadCodecRegister (
1263  that->AdapterCommon->GetNodeReg (NodeDef), &wRegister);
1264  if (!NT_SUCCESS (ntStatus))
1265  return ntStatus;
1266 
1267  // mask out every unused bit.
1268  wRegister &= that->AdapterCommon->GetNodeMask (NodeDef);
1269 
1270  // rotate if bass tone control or 3D center control
1271  if ((NodeDef == NODE_BASS) || (NodeDef == NODE_VIRT_3D_CENTER))
1272  wRegister >>= 8;
1273 
1274  // convert from reg to dB.dB value.
1275  if ((NodeDef == NODE_VIRT_3D_CENTER) ||
1276  (NodeDef == NODE_VIRT_3D_DEPTH))
1277  {
1278  // That's for the 3D controls
1279  *Level = lMinimum + uStep * wRegister;
1280  }
1281  else
1282  {
1283  if (wRegister == 0x000F)
1284  *Level = 0; // bypass
1285  else
1286  // And that's for the tone controls
1287  *Level = lMaximum - uStep * wRegister;
1288  }
1289 
1290  // when we have cache information then return this instead
1291  // of the calculated value. if we don't, store the calculated
1292  // value.
1293  if (that->stNodeCache[NodeDef].bLeftValid)
1294  *Level = that->stNodeCache[NodeDef].lLeft;
1295  else
1296  {
1297  that->stNodeCache[NodeDef].lLeft = *Level;
1298  that->stNodeCache[NodeDef].bLeftValid = (BYTE)-1;
1299  }
1300 
1301  // we return a LONG
1302  PropertyRequest->ValueSize = sizeof(LONG);
1303  DOUT (DBG_PROPERTY, ("GET: %s = 0x%x", NodeStrings[NodeDef], *Level));
1304  // ntStatus was set with the read call! whatever this is, return it.
1305  }
1306  else // that must be a set
1307  {
1308  WORD wRegister;
1309  LONG lLevel = *Level;
1310 
1311  // calculate the dB.dB value.
1312  // check borders.
1313  if (lLevel > lMaximum) lLevel = lMaximum;
1314  if (lLevel < lMinimum) lLevel = lMinimum;
1315 
1316  // write the value to the node cache.
1317  that->stNodeCache[NodeDef].lLeft = *Level;
1318  that->stNodeCache[NodeDef].bLeftValid = (BYTE)-1;
1319 
1320  // convert from dB.dB value to reg.
1321  if ((NodeDef == NODE_VIRT_3D_CENTER) ||
1322  (NodeDef == NODE_VIRT_3D_DEPTH))
1323  {
1324  // For 3D controls
1325  wRegister = (WORD)(((lLevel + uStep / 2) - lMinimum) / uStep);
1326  }
1327  else
1328  {
1329  // For tone controls
1330  wRegister = (WORD)(((lMaximum + uStep / 2) - lLevel) / uStep);
1331  // We don't prg. 0dB Bass or 0dB Treble, instead we smartly prg.
1332  // a bypass which is reg. value 0x0F.
1333  if (wRegister == 7) // 0 dB
1334  wRegister = 0x000F; // bypass
1335  }
1336 
1337  // rotate if bass tone control or 3D center control
1338  if ((NodeDef == NODE_BASS) || (NodeDef == NODE_VIRT_3D_CENTER))
1339  wRegister <<= 8;
1340 
1341  // write the stuff.
1342  ntStatus = that->AdapterCommon->WriteCodecRegister (
1343  that->AdapterCommon->GetNodeReg (NodeDef),
1344  wRegister,
1345  that->AdapterCommon->GetNodeMask (NodeDef));
1346 
1347  DOUT (DBG_PROPERTY,("SET: %s -> 0x%x", NodeStrings[NodeDef], *Level));
1348  // ntStatus was set with the write call! whatever this is, return in.
1349  }
1350  }
1351  else
1352  {
1353  if (PropertyRequest->Verb & KSPROPERTY_TYPE_BASICSUPPORT)
1354  {
1355  ntStatus = BasicSupportHandler (PropertyRequest);
1356  }
1357  }
1358 
1359  return ntStatus;
1360 }
1361 
1362 /*****************************************************************************
1363  * CAC97MiniportTopology::PropertyHandler_Ulong
1364  *****************************************************************************
1365  * Accesses a ULONG value property. For MUX and DEMUX.
1366  * This function (property handler) is called by portcls every time there is a
1367  * get, set or basic support request for the node. The connection between the
1368  * node type and the property handler is made in the automation table which is
1369  * referenced when you register the node.
1370  * We use this property handler for all muxer controls.
1371  */
1374  IN PPCPROPERTY_REQUEST PropertyRequest
1375 )
1376 {
1377  PAGED_CODE ();
1378 
1379  ASSERT (PropertyRequest);
1380 
1381  DOUT (DBG_PRINT, ("[CAC97MiniportTopology::PropertyHandler_Ulong]"));
1382 
1384  TopoNodes NodeDef;
1386  ULONG uStep;
1387  // The major target is the object pointer to the topology miniport.
1388  CAC97MiniportTopology *that =
1389  (CAC97MiniportTopology *) PropertyRequest->MajorTarget;
1390 
1391  ASSERT (that);
1392 
1393 
1394  // validate node instance
1395  if (PropertyRequest->Node == (ULONG)-1)
1396  return ntStatus;
1397 
1398  // if we should do a get or set.
1399  if ((PropertyRequest->Verb & KSPROPERTY_TYPE_GET) ||
1400  (PropertyRequest->Verb & KSPROPERTY_TYPE_SET))
1401  {
1402  // validate buffer size.
1403  if (PropertyRequest->ValueSize < sizeof(ULONG))
1404  return ntStatus;
1405 
1406  // get the pointer to the buffer.
1407  PULONG PropValue = (PULONG)PropertyRequest->Value;
1408 
1409  // Switch on the node id. This is just for parameter checking.
1410  // If something goes wrong, we will immideately return with
1411  // ntStatus, which is STATUS_INVALID_PARAMETER.
1412  switch(NodeDef = that->TransNodeNrToNodeDef (PropertyRequest->Node))
1413  {
1414  case NODE_MONOOUT_SELECT:
1415  case NODE_WAVEIN_SELECT:
1416  // check the type
1417  if (PropertyRequest->PropertyItem->Id != KSPROPERTY_AUDIO_MUX_SOURCE)
1418  return ntStatus;
1419  break;
1420 
1421  case NODE_INVALID:
1422  default:
1423  // Ooops
1424  DOUT (DBG_ERROR, ("PropertyHandler_Tone: Invalid node requested."));
1425  return ntStatus;
1426  }
1427 
1428  // Now do some action!
1429 
1430  // should we return the value?
1431  if (PropertyRequest->Verb & KSPROPERTY_TYPE_GET)
1432  {
1433  WORD wRegister;
1434 
1435  // first get the stuff.
1436  ntStatus = that->AdapterCommon->ReadCodecRegister (
1437  that->AdapterCommon->GetNodeReg (NodeDef), &wRegister);
1438  if (!NT_SUCCESS (ntStatus))
1439  return ntStatus;
1440 
1441  // mask out every unused bit.
1442  wRegister &= that->AdapterCommon->GetNodeMask (NodeDef);
1443 
1444  // calculate the selected pin
1445  if (NodeDef == NODE_MONOOUT_SELECT)
1446  {
1447  // for mono out we have just one bit
1448  if (wRegister)
1449  *PropValue = 2;
1450  else
1451  *PropValue = 1;
1452  }
1453  else
1454  {
1455  // the wave in muxer is a stereo muxer, so just return the
1456  // right channel (gives values 0-7) and adjust it by adding 1.
1457  *PropValue = (wRegister & AC97REG_MASK_RIGHT) + 1;
1458  }
1459 
1460  // we return a LONG
1461  PropertyRequest->ValueSize = sizeof(LONG);
1462  DOUT (DBG_PROPERTY, ("GET: %s = 0x%x", NodeStrings[NodeDef],
1463  *PropValue));
1464  // ntStatus was set with the read call! whatever this is, return it.
1465  }
1466  else // that must be a set
1467  {
1468  TopoNodes VirtNode;
1469  WORD wRegister;
1470  ULONG ulSelect = *PropValue;
1471  LONG lLevel;
1472 
1473  // Check the selection first.
1474  if (NodeDef == NODE_MONOOUT_SELECT)
1475  {
1476  if ((ulSelect < 1) || (ulSelect > 2))
1477  return ntStatus; // STATUS_INVALID_PARAMETER
1478  }
1479  else
1480  {
1481  if ((ulSelect < 1) || (ulSelect > 8))
1482  return ntStatus; // STATUS_INVALID_PARAMETER
1483  }
1484 
1485  // calculate the register value for programming.
1486  if (NodeDef == NODE_MONOOUT_SELECT)
1487  {
1488  // for mono out we have just one bit
1489  if (ulSelect == 2)
1490  // the mask will make sure we only prg. one bit.
1491  wRegister = 0xFFFF;
1492  else
1493  // ulSelect == 1
1494  wRegister = 0;
1495  }
1496  else
1497  {
1498  // *257 is the same as: (ulSelect << 8) + ulSelect
1499  wRegister = (WORD)(ulSelect - 1) * 257;
1500  }
1501 
1502  // write the stuff.
1503  ntStatus = that->AdapterCommon->WriteCodecRegister (
1504  that->AdapterCommon->GetNodeReg (NodeDef),
1505  wRegister,
1506  that->AdapterCommon->GetNodeMask (NodeDef));
1507 
1508  // Store the virt. node for later use.
1509  // Tricky: Master input virtual controls must be defined consecutively.
1510  if (NodeDef == NODE_MONOOUT_SELECT)
1511  VirtNode = (TopoNodes)(NODE_VIRT_MONOOUT_VOLUME1 + (ulSelect - 1));
1512  else
1513  VirtNode = (TopoNodes)(NODE_VIRT_MASTER_INPUT_VOLUME1 + (ulSelect - 1));
1514 
1515  // Virtual controls make our life more complicated. When the user
1516  // changes the input source say from CD to LiniIn, then the system just
1517  // sends a message to the input muxer that the selection changed.
1518  // Cause we have only one HW register for the input muxer, all volumes
1519  // displayed for the user are "virtualized", means they are not there,
1520  // and when the selection changes, we have to prg. the volume of the
1521  // selected input to the HW register. That's what we do now.
1522 
1523  // get the registered DB values
1524  ntStatus = GetDBValues (that->AdapterCommon, VirtNode,
1525  &lMinimum, &lMaximum, &uStep);
1526  if (!NT_SUCCESS (ntStatus))
1527  return ntStatus;
1528 
1529  // We can be lazy here and don't check for mono controls. Reason
1530  // is that the level handler writes the volume value for mono
1531  // controls into both the left and right node cache ;))
1532 
1533  if (that->stNodeCache[VirtNode].bLeftValid &&
1534  that->stNodeCache[VirtNode].bRightValid)
1535  {
1536  // prg. left channel
1537  lLevel = that->stNodeCache[VirtNode].lLeft;
1538 
1539  // calculate the dB.dB value.
1540  if (NodeDef == NODE_MONOOUT_SELECT)
1541  wRegister = (WORD)(((lMaximum + uStep / 2) - lLevel) / uStep);
1542  else
1543  wRegister = (WORD)(((lLevel + uStep / 2) - lMinimum) / uStep);
1544 
1545  // write left channel.
1546  ntStatus = that->AdapterCommon->WriteCodecRegister (
1547  that->AdapterCommon->GetNodeReg (VirtNode),
1548  wRegister << 8,
1549  that->AdapterCommon->GetNodeMask (VirtNode) & AC97REG_MASK_LEFT);
1550 
1551  // prg. right channel
1552  lLevel = that->stNodeCache[VirtNode].lRight;
1553 
1554  // calculate the dB.dB value.
1555  if (NodeDef == NODE_MONOOUT_SELECT)
1556  wRegister = (WORD)(((lMaximum + uStep / 2) - lLevel) / uStep);
1557  else
1558  wRegister = (WORD)(((lLevel + uStep / 2) - lMinimum) / uStep);
1559 
1560  // write right channel.
1561  ntStatus = that->AdapterCommon->WriteCodecRegister (
1562  that->AdapterCommon->GetNodeReg (VirtNode),
1563  wRegister,
1564  that->AdapterCommon->GetNodeMask (VirtNode) & AC97REG_MASK_RIGHT);
1565 
1566  // For the virtual controls, which are in front of a muxer, there
1567  // is no mute control displayed. But we have a HW mute control, so
1568  // what we do is enabling this mute when the user moves the slider
1569  // down to the bottom and disabling it on every other position.
1570  // We do this only for the "mono muxer", the recording mutes will
1571  // never be muted.
1572  if (NodeDef == NODE_WAVEIN_SELECT)
1573  {
1574  // disable the mute; this only works because the mute and volume
1575  // share the same register.
1576  ntStatus = that->AdapterCommon->WriteCodecRegister (
1577  that->AdapterCommon->GetNodeReg (VirtNode),
1578  0, AC97REG_MASK_MUTE);
1579 
1580  that->UpdateRecordMute ();
1581  }
1582 
1583  if (NodeDef == NODE_MONOOUT_SELECT)
1584  {
1585  // these are only mono controls so checking one entry is enough.
1586  if ( that->stNodeCache[VirtNode].bLeftValid &&
1587  (that->stNodeCache[VirtNode].lLeft <= lMinimum))
1588  {
1589  // set the mute; this only works because the mute and volume
1590  // share the same register.
1591  ntStatus = that->AdapterCommon->WriteCodecRegister (
1592  that->AdapterCommon->GetNodeReg (VirtNode),
1594  }
1595  else
1596  {
1597  // clear the mute; this only works because the mute and volume
1598  // share the same register.
1599  ntStatus = that->AdapterCommon->WriteCodecRegister (
1600  that->AdapterCommon->GetNodeReg (VirtNode),
1601  0, AC97REG_MASK_MUTE);
1602  }
1603  }
1604  }
1605 
1606  DOUT (DBG_PROPERTY, ("SET: %s -> 0x%x", NodeStrings[NodeDef],
1607  *PropValue));
1608  // ntStatus was set with the write call! whatever this is, return it.
1609  }
1610  }
1611 
1612  return ntStatus;
1613 }
1614 
1615 /*****************************************************************************
1616  * CAC97MiniportTopology::PropertyHandler_CpuResources
1617  *****************************************************************************
1618  * Propcesses a KSPROPERTY_AUDIO_CPU_RESOURCES request
1619  * This property handler is called by the system for every node and every node
1620  * must support this property. Basically, this property is for performance
1621  * monitoring and we just say here that every function we claim to have has HW
1622  * support (which by the way is true).
1623  */
1626  IN PPCPROPERTY_REQUEST PropertyRequest
1627 )
1628 {
1629  PAGED_CODE ();
1630 
1631  ASSERT (PropertyRequest);
1632 
1633  DOUT (DBG_PRINT, ("[CAC97MiniportTopology::PropertyHandler_CpuResources]"));
1634 
1635  CAC97MiniportTopology *that =
1636  (CAC97MiniportTopology *) PropertyRequest->MajorTarget;
1638 
1639  ASSERT (that);
1640 
1641  // validate node
1642  if (PropertyRequest->Node == (ULONG)-1)
1643  return ntStatus;
1644 
1645  // validate the node def.
1646  if (that->TransNodeNrToNodeDef (PropertyRequest->Node) == NODE_INVALID)
1647  return ntStatus;
1648 
1649  // we should do a get
1650  if (PropertyRequest->Verb & KSPROPERTY_TYPE_GET)
1651  {
1652  // just return the flag.
1653  if (PropertyRequest->ValueSize >= sizeof(LONG))
1654  {
1655  *((PLONG)PropertyRequest->Value) = KSAUDIO_CPU_RESOURCES_NOT_HOST_CPU;
1656  PropertyRequest->ValueSize = sizeof(LONG);
1657  ntStatus = STATUS_SUCCESS;
1658  }
1659  else // not enough buffer.
1660  {
1661  ntStatus = STATUS_BUFFER_TOO_SMALL;
1662  }
1663  }
1664 
1665  return ntStatus;
1666 }
1667 
1668 #ifdef INCLUDE_PRIVATE_PROPERTY
1669 /*****************************************************************************
1670  * CAC97MiniportTopology::PropertyHandler_Private
1671  *****************************************************************************
1672  * This is a private property that returns some AC97 codec features.
1673  * This routine gets called whenever the topology filter gets a property
1674  * request with KSPROSETPID_Private and KSPROPERTY_AC97_FEATURES set. It is not
1675  * a node property but a filter property (you don't have to specify a node).
1676  */
1678 (
1679  IN PPCPROPERTY_REQUEST PropertyRequest
1680 )
1681 {
1682  PAGED_CODE ();
1683 
1684  ASSERT (PropertyRequest);
1685 
1686  DOUT (DBG_PRINT, ("[CAC97MiniportTopology::PropertyHandler_Private]"));
1687 
1689  // The major target is the object pointer to the topology miniport.
1690  CAC97MiniportTopology *that =
1691  (CAC97MiniportTopology *) PropertyRequest->MajorTarget;
1692 
1693 
1694  ASSERT (that);
1695 
1696 
1697  // We only have a get defined.
1698  if (PropertyRequest->Verb & KSPROPERTY_TYPE_GET)
1699  {
1700  // Check the ID ("function" in "group").
1701  if (PropertyRequest->PropertyItem->Id != KSPROPERTY_AC97_FEATURES)
1702  return ntStatus;
1703 
1704  // validate buffer size.
1705  if (PropertyRequest->ValueSize < sizeof (tAC97Features))
1706  return ntStatus;
1707 
1708  // The "Value" is the out buffer that you pass in DeviceIoControl call.
1709  tAC97Features *pAC97Features = (tAC97Features *) PropertyRequest->Value;
1710 
1711  // Check the buffer.
1712  if (!pAC97Features)
1713  return ntStatus;
1714 
1715  //
1716  // Fill the AC97Features structure.
1717  //
1718 
1719  // Set the volumes.
1720  pAC97Features->MasterVolume = Volume5bit;
1721  if (that->AdapterCommon->GetNodeConfig (NODEC_6BIT_MASTER_VOLUME))
1722  pAC97Features->MasterVolume = Volume6bit;
1723 
1724  pAC97Features->HeadphoneVolume = Volume5bit;
1725  if (!that->AdapterCommon->GetPinConfig (PINC_HPOUT_PRESENT))
1726  pAC97Features->HeadphoneVolume = VolumeDisabled;
1727  else if (that->AdapterCommon->GetNodeConfig (NODEC_6BIT_HPOUT_VOLUME))
1728  pAC97Features->HeadphoneVolume = Volume6bit;
1729 
1730  pAC97Features->MonoOutVolume = Volume5bit;
1731  if (!that->AdapterCommon->GetPinConfig (PINC_MONOOUT_PRESENT))
1732  pAC97Features->MonoOutVolume = VolumeDisabled;
1733  else if (that->AdapterCommon->GetNodeConfig (NODEC_6BIT_MONOOUT_VOLUME))
1734  pAC97Features->MonoOutVolume = Volume6bit;
1735 
1736  // The 18/20bit Resolution information.
1737  WORD wCodecID;
1738 
1739  // Read the reset register.
1740  ntStatus = that->AdapterCommon->ReadCodecRegister (AC97REG_RESET, &wCodecID);
1741  if (!NT_SUCCESS (ntStatus))
1742  return ntStatus;
1743 
1744  //
1745  // Now check the DAC and ADC resolution.
1746  //
1747 
1748  // First the DAC.
1749  pAC97Features->DAC = Resolution16bit;
1750  if (wCodecID & 0x0040)
1751  pAC97Features->DAC = Resolution18bit;
1752  if (wCodecID & 0x0080)
1753  pAC97Features->DAC = Resolution20bit;
1754 
1755  // Then the ADC.
1756  pAC97Features->ADC = Resolution16bit;
1757  if (wCodecID & 0x0100)
1758  pAC97Features->ADC = Resolution18bit;
1759  if (wCodecID & 0x0200)
1760  pAC97Features->ADC = Resolution20bit;
1761 
1762  // 3D technique
1763  pAC97Features->n3DTechnique = ((wCodecID & 0x7C00) >> 10);
1764 
1765  // Set the flag for MicIn.
1766  pAC97Features->bMicInPresent = that->AdapterCommon->
1767  GetPinConfig (PINC_MICIN_PRESENT) ? TRUE : FALSE;
1768 
1769  // Variable sample rate info.
1770  pAC97Features->bVSRPCM = that->AdapterCommon->
1771  GetNodeConfig (NODEC_PCM_VARIABLERATE_SUPPORTED) ? TRUE : FALSE;
1772  pAC97Features->bDSRPCM = that->AdapterCommon->
1773  GetNodeConfig (NODEC_PCM_DOUBLERATE_SUPPORTED) ? TRUE : FALSE;
1774  pAC97Features->bVSRMIC = that->AdapterCommon->
1775  GetNodeConfig (NODEC_MIC_VARIABLERATE_SUPPORTED) ? TRUE : FALSE;
1776 
1777  // Additional DAC's
1778  pAC97Features->bCenterDAC = that->AdapterCommon->
1779  GetNodeConfig (NODEC_CENTER_DAC_PRESENT) ? TRUE : FALSE;
1780  pAC97Features->bSurroundDAC = that->AdapterCommon->
1781  GetNodeConfig (NODEC_SURROUND_DAC_PRESENT) ? TRUE : FALSE;
1782  pAC97Features->bLFEDAC = that->AdapterCommon->
1783  GetNodeConfig (NODEC_LFE_DAC_PRESENT) ? TRUE : FALSE;
1784 
1785 
1786  // We filled out the structure.
1787  PropertyRequest->ValueSize = sizeof (tAC97Features);
1788  DOUT (DBG_PROPERTY, ("Get AC97Features succeeded."));
1789 
1790  // ntStatus was set with the read call! whatever this is, return it.
1791  }
1792 #ifdef PROPERTY_SHOW_SET
1793  else
1794  {
1795  // Just to show, we have a SET also.
1796  if (PropertyRequest->Verb & KSPROPERTY_TYPE_SET)
1797  {
1798  // This is the only property for a SET.
1799  if (PropertyRequest->PropertyItem->Id != KSPROPERTY_AC97_SAMPLE_SET)
1800  return ntStatus;
1801 
1802  // validate buffer size.
1803  if (PropertyRequest->ValueSize < sizeof (DWORD))
1804  return ntStatus;
1805 
1806  // Get the pointer to the DWORD.
1807  DWORD *pTimerTick = (DWORD *)PropertyRequest->Value;
1808 
1809  // Check the buffer.
1810  if (!pTimerTick)
1811  return ntStatus;
1812 
1813  // Print the message.
1814  DOUT (DBG_ALL, ("This computer is already %d ms running Windows!", *pTimerTick));
1815  ntStatus = STATUS_SUCCESS;
1816  }
1817  }
1818 #endif
1819 
1820  return ntStatus;
1821 }
1822 #endif
1823 
1824 
#define IN
Definition: typedefs.h:39
Definition: compat.h:2157
const LONG CHAN_RIGHT
Definition: prophnd.cpp:18
void UpdateRecordMute(void)
Definition: mintopo.cpp:2053
struct config_s config
ActualNumberDriverObjects * sizeof(PDRIVER_OBJECT)) PDRIVER_OBJECT *DriverObjectList
long lLeft
Definition: mintopo.h:75
LONG lMinimum
Definition: mmsystem.h:1287
LONG lMaximum
Definition: mmsystem.h:1288
#define TRUE
Definition: types.h:120
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
LONG NTSTATUS
Definition: precomp.h:26
static NTSTATUS NTAPI PropertyHandler_Tone(IN PPCPROPERTY_REQUEST PropertyRequest)
Definition: prophnd.cpp:1169
const LONG CHAN_LEFT
Definition: prophnd.cpp:17
IAC97AdapterCommon * PADAPTERCOMMON
Definition: shared.h:486
#define STATUS_INVALID_DEVICE_REQUEST
Definition: udferr_usr.h:138
static NTSTATUS SetMultichannelMute(IN CAC97MiniportTopology *that, IN TopoNodes Mute)
Definition: prophnd.cpp:36
const GUID KSPROPTYPESETID_General
Definition: property.c:17
PADAPTERCOMMON AdapterCommon
Definition: mintopo.h:98
_IRQL_requires_same_ typedef _In_ ULONG _In_ UCHAR Level
Definition: wmitypes.h:55
const LONG CHAN_MASTER
Definition: prophnd.cpp:19
if(dx==0 &&dy==0)
Definition: linetemp.h:174
#define DOUT(lvl, strings)
Definition: debug.h:82
#define BOOL
Definition: nt_native.h:43
#define DWORD
Definition: nt_native.h:44
#define KSPROPERTY_TYPE_GET
Definition: dmksctrl.h:42
#define KSAUDIO_CPU_RESOURCES_NOT_HOST_CPU
Definition: ksmedia.h:1198
GUID Set
Definition: dmksctrl.h:76
#define STATUS_BUFFER_TOO_SMALL
Definition: shellext.h:69
struct KSPROPERTY_MEMBERSHEADER * PKSPROPERTY_MEMBERSHEADER
#define FALSE
Definition: types.h:117
unsigned int BOOL
Definition: ntddk_ex.h:94
long LONG
Definition: pedump.c:60
NTSTATUS NTAPI PropertyHandler_Private(PPCPROPERTY_REQUEST PropertyRequest)
Definition: mintopo.cpp:1337
const WORD AC97REG_MASK_MUTE
Definition: mintopo.h:50
switch(r->id)
Definition: btrfs.c:3015
KSIDENTIFIER PropTypeSet
Definition: ks.h:1541
BOOL * PBOOL
Definition: windef.h:161
#define KSPROPERTY_TYPE_BASICSUPPORT
Definition: dmksctrl.h:45
TopoNodeConfig
Definition: shared.h:83
struct KSPROPERTY_STEPPING_LONG * PKSPROPERTY_STEPPING_LONG
ULONG DescriptionSize
Definition: ks.h:1540
#define ASSERT(a)
Definition: mode.c:44
ULONG Id
Definition: dmksctrl.h:77
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
static NTSTATUS SetMultichannelVolume(IN CAC97MiniportTopology *that, IN TopoNodes Volume)
Definition: prophnd.cpp:77
unsigned short WORD
Definition: ntddk_ex.h:93
unsigned long DWORD
Definition: ntddk_ex.h:95
static NTSTATUS NTAPI PropertyHandler_Ulong(IN PPCPROPERTY_REQUEST PropertyRequest)
Definition: prophnd.cpp:1373
TopoNodes TransNodeNrToNodeDef(IN int Node)
Definition: mintopo.h:135
const int DBG_ERROR
Definition: debug.h:19
ULONG Flags
Definition: dmksctrl.h:78
BYTE bLeftValid
Definition: mintopo.h:77
#define KSPROPERTY_MEMBER_STEPPEDRANGES
Definition: ks.h:1559
static NTSTATUS BasicSupportHandler(PPCPROPERTY_REQUEST PropertyRequest)
Definition: mintopo.cpp:1031
static NTSTATUS NTAPI PropertyHandler_Level(IN PPCPROPERTY_REQUEST PropertyRequest)
Definition: prophnd.cpp:682
Definition: range.c:39
static NTSTATUS NTAPI PropertyHandler_OnOff(IN PPCPROPERTY_REQUEST PropertyRequest)
Definition: prophnd.cpp:327
unsigned char BYTE
Definition: xxhash.c:193
BYTE bRightValid
Definition: mintopo.h:78
TopoNodes
Definition: shared.h:185
const int DBG_ALL
Definition: debug.h:35
const int DBG_PROPERTY
Definition: debug.h:29
static NTSTATUS NTAPI PropertyHandler_CpuResources(IN PPCPROPERTY_REQUEST PropertyRequest)
Definition: prophnd.cpp:1625
unsigned int * PULONG
Definition: retypes.h:1
const long PROP_MOST_NEGATIVE
Definition: mintopo.h:56
#define OUT
Definition: typedefs.h:40
static NTSTATUS BasicSupportHandler(IN PPCPROPERTY_REQUEST PropertyRequest)
Definition: prophnd.cpp:573
unsigned int ULONG
Definition: retypes.h:1
const WORD AC97REG_MASK_RIGHT
Definition: mintopo.h:49
tNodeCache stNodeCache[NODE_TOP_ELEMENT]
Definition: mintopo.h:106
#define STATUS_SUCCESS
Definition: shellext.h:65
ULONG MembersListCount
Definition: ks.h:1542
long lRight
Definition: mintopo.h:76
const WORD AC97REG_MASK_LEFT
Definition: mintopo.h:48
signed int * PLONG
Definition: retypes.h:5
#define KSPROPERTY_TYPE_SET
Definition: dmksctrl.h:43
const int DBG_PRINT
Definition: debug.h:17
struct KSPROPERTY_DESCRIPTION * PKSPROPERTY_DESCRIPTION
static NTSTATUS GetDBValues(IN PADAPTERCOMMON, IN TopoNodes Node, OUT LONG *plMinimum, OUT LONG *plMaximum, OUT ULONG *puStep)
Definition: prophnd.cpp:156
Definition: dlist.c:348
#define PAGED_CODE()