ReactOS  0.4.15-dev-4872-g8a3db97
miniport.cpp
Go to the documentation of this file.
1 // Every debug output has "Modulname text"
2 #define STR_MODULENAME "AC97 Miniport: "
3 
4 //#include "shared.h"
5 //#include "miniport.h"
6 #include "wavepciminiport.h"
7 
8 /*****************************************************************************
9  * PinDataRangesPCMStream
10  *****************************************************************************
11  * The next 3 arrays contain information about the data ranges of the pin for
12  * wave capture, wave render and mic capture.
13  * These arrays are filled dynamically by BuildDataRangeInformation().
14  */
15 
19 
21 {
22  {
23  sizeof(KSDATARANGE),
24  0,
25  0,
26  0,
30  }
31 };
32 
33 /*****************************************************************************
34  * PinDataRangesPointersPCMStream
35  *****************************************************************************
36  * The next 3 arrays contain the pointers to the data range information of
37  * the pin for wave capture, wave render and mic capture.
38  * These arrays are filled dynamically by BuildDataRangeInformation().
39  */
43 
44 /*****************************************************************************
45  * PinDataRangePointerAnalogStream
46  *****************************************************************************
47  * This structure pointers to the data range structures for the wave pins.
48  */
50 {
52 };
53 
54 
55 /*****************************************************************************
56  * Wave Miniport Topology
57  *========================
58  *
59  * +-----------+
60  * | |
61  * Capture (PIN_WAVEIN) <---|2 --ADC-- 3|<=== (PIN_WAVEIN_BRIDGE)
62  * | |
63  * Render (PIN_WAVEOUT) --->|0 --DAC-- 1|===> (PIN_WAVEOUT_BRIDGE)
64  * | |
65  * Mic (PIN_MICIN) <---|4 --ADC-- 5|<=== (PIN_MICIN_BRIDGE)
66  * +-----------+
67  *
68  * Note that the exposed pins (left side) have to be a multiple of 2
69  * since there are some dependencies in the stream object.
70  */
71 
72 /*****************************************************************************
73  * MiniportPins
74  *****************************************************************************
75  * This structure describes pin (stream) types provided by this miniport.
76  * The field that sets the number of data range entries (SIZEOF_ARRAY) is
77  * overwritten by BuildDataRangeInformation().
78  */
80 {
81  // PIN_WAVEOUT
82  {
83  1,1,0, // InstanceCount
84  NULL, // AutomationTable
85  { // KsPinDescriptor
86  0, // InterfacesCount
87  NULL, // Interfaces
88  0, // MediumsCount
89  NULL, // Mediums
92  KSPIN_DATAFLOW_IN, // DataFlow
93  KSPIN_COMMUNICATION_SINK, // Communication
94  (GUID *) &KSCATEGORY_AUDIO, // Category
95  NULL, // Name
96  0 // Reserved
97  }
98  },
99 
100  // PIN_WAVEOUT_BRIDGE
101  {
102  0,0,0, // InstanceCount
103  NULL, // AutomationTable
104  { // KsPinDescriptor
105  0, // InterfacesCount
106  NULL, // Interfaces
107  0, // MediumsCount
108  NULL, // Mediums
110  PinDataRangePointersAnalogBridge, // DataRanges
111  KSPIN_DATAFLOW_OUT, // DataFlow
112  KSPIN_COMMUNICATION_NONE, // Communication
113  (GUID *) &KSCATEGORY_AUDIO, // Category
114  NULL, // Name
115  0 // Reserved
116  }
117  },
118 
119  // PIN_WAVEIN
120  {
121  1,1,0, // InstanceCount
122  NULL, // AutomationTable
123  { // KsPinDescriptor
124  0, // InterfacesCount
125  NULL, // Interfaces
126  0, // MediumsCount
127  NULL, // Mediums
130  KSPIN_DATAFLOW_OUT, // DataFlow
131  KSPIN_COMMUNICATION_SINK, // Communication
132  (GUID *) &PINNAME_CAPTURE, // Category
134  0 // Reserved
135  }
136  },
137 
138  // PIN_WAVEIN_BRIDGE
139  {
140  0,0,0, // InstanceCount
141  NULL, // AutomationTable
142  { // KsPinDescriptor
143  0, // InterfacesCount
144  NULL, // Interfaces
145  0, // MediumsCount
146  NULL, // Mediums
148  PinDataRangePointersAnalogBridge, // DataRanges
149  KSPIN_DATAFLOW_IN, // DataFlow
150  KSPIN_COMMUNICATION_NONE, // Communication
151  (GUID *) &KSCATEGORY_AUDIO, // Category
152  NULL, // Name
153  0 // Reserved
154  }
155  },
156 
157  //
158  // The Microphone pins are not used if PINC_MICIN_PRESENT is not set.
159  // To remove them, Init() will reduce the "PinCount" in the
160  // MiniportFilterDescriptor.
161  //
162  // PIN_MICIN
163  {
164  1,1,0, // InstanceCount
165  NULL, // AutomationTable
166  { // KsPinDescriptor
167  0, // InterfacesCount
168  NULL, // Interfaces
169  0, // MediumsCount
170  NULL, // Mediums
171  SIZEOF_ARRAY(PinDataRangePointersMicStream),// DataRangesCount
172  PinDataRangePointersMicStream, // DataRanges
173  KSPIN_DATAFLOW_OUT, // DataFlow
174  KSPIN_COMMUNICATION_SINK, // Communication
175  (GUID *) &KSCATEGORY_AUDIO, // Category
176  NULL, // Name
177  0 // Reserved
178  }
179  },
180 
181  // PIN_MICIN_BRIDGE
182  {
183  0,0,0, // InstanceCount
184  NULL, // AutomationTable
185  { // KsPinDescriptor
186  0, // InterfacesCount
187  NULL, // Interfaces
188  0, // MediumsCount
189  NULL, // Mediums
191  PinDataRangePointersAnalogBridge, // DataRanges
192  KSPIN_DATAFLOW_IN, // DataFlow
193  KSPIN_COMMUNICATION_NONE, // Communication
194  (GUID *) &KSCATEGORY_AUDIO, // Category
195  NULL, // Name
196  0 // Reserved
197  }
198  }
199 };
200 
201 /*****************************************************************************
202  * PropertiesDAC
203  *****************************************************************************
204  * Properties for the DAC node.
205  */
207 {
208  {
213  }
214 };
215 
216 /*****************************************************************************
217  * AutomationVolume
218  *****************************************************************************
219  * Automation table for volume controls.
220  */
222 
223 /*****************************************************************************
224  * TopologyNodes
225  *****************************************************************************
226  * List of nodes.
227  */
229 {
230  // NODE_WAVEOUT_DAC
231  {
232  0, // Flags
233  &AutomationDAC, // AutomationTable
234  &KSNODETYPE_DAC, // Type
235  NULL // Name
236  },
237  // NODE_WAVEIN_ADC
238  {
239  0, // Flags
240  NULL, // AutomationTable
241  &KSNODETYPE_ADC, // Type
242  NULL // Name
243  },
244  //
245  // The Microphone node is not used if PINC_MICIN_PRESENT is not set.
246  // To remove them, Init() will reduce the "NodeCount" in the
247  // MiniportFilterDescriptor.
248  //
249  // NODE_MICIN_ADC
250  {
251  0, // Flags
252  NULL, // AutomationTable
253  &KSNODETYPE_ADC, // Type
254  NULL // Name
255  }
256 };
257 
258 /*****************************************************************************
259  * MiniportConnections
260  *****************************************************************************
261  * This structure identifies the connections between filter pins and
262  * node pins.
263  */
265 {
266  //from_node from_pin to_node to_pin
271  //
272  // The Microphone connection is not used if PINC_MICIN_PRESENT is not set.
273  // To remove them, Init() will reduce the "ConnectionCount" in the
274  // MiniportFilterDescriptor.
275  //
278 };
279 
280 /*****************************************************************************
281  * MiniportFilterDescriptor
282  *****************************************************************************
283  * Complete miniport description.
284  * Init() modifies the pin count, node count and connection count in absence
285  * of the MicIn recording line.
286  */
288 {
289  0, // Version
290  NULL, // AutomationTable
291  sizeof(PCPIN_DESCRIPTOR), // PinSize
292  SIZEOF_ARRAY(MiniportPins), // PinCount
293  MiniportPins, // Pins
294  sizeof(PCNODE_DESCRIPTOR), // NodeSize
295  SIZEOF_ARRAY(MiniportNodes), // NodeCount
296  MiniportNodes, // Nodes
297  SIZEOF_ARRAY(MiniportConnections), // ConnectionCount
298  MiniportConnections, // Connections
299  0, // CategoryCount
300  NULL // Categories: NULL->use defaults (audio, render, capture)
301 };
302 
303 #ifdef _MSC_VER
304 #pragma code_seg("PAGE")
305 #endif
306 /*****************************************************************************
307  * CMiniport::PropertyChannelConfig
308  *****************************************************************************
309  * This is the property handler for KSPROPERTY_AUDIO_CHANNEL_CONFIG of the
310  * DAC node. It sets the channel configuration (how many channels, how user
311  * was setting up the speakers).
312  */
314 (
315  IN PPCPROPERTY_REQUEST PropertyRequest
316 )
317 {
318  PAGED_CODE ();
319 
320  ASSERT (PropertyRequest);
321 
322  DOUT (DBG_PRINT, ("[CMiniport::PropertyChannelConfig]"));
323 
325 
326  // The major target is the object pointer to the wave miniport.
327  // HACK ALERT - unsafe pointer cast - HACK ALERT
328  CMiniport *that = (CMiniport *)(CMiniportWaveICH*)
329  (PMINIPORTWAVEPCI)PropertyRequest->MajorTarget;
330 
331  ASSERT (that);
332 
333  // We only have a set defined.
334  if (PropertyRequest->Verb & KSPROPERTY_TYPE_SET)
335  {
336  // validate buffer size.
337  if (PropertyRequest->ValueSize < sizeof(LONG))
338  return ntStatus;
339 
340  // The "Value" is the input buffer with the channel config.
341  if (PropertyRequest->Value)
342  {
343  // We can accept different channel configurations, depending
344  // on the number of channels we can play.
345  if (that->AdapterCommon->GetPinConfig (PINC_SURROUND_PRESENT))
346  {
347  if (that->AdapterCommon->GetPinConfig (PINC_CENTER_LFE_PRESENT))
348  {
349  // we accept 5.1
350  if (*(PLONG)PropertyRequest->Value == KSAUDIO_SPEAKER_5POINT1)
351  {
352  that->m_dwChannelMask = *(PLONG)PropertyRequest->Value;
353  that->m_wChannels = 6;
354  that->AdapterCommon->WriteChannelConfigDefault (that->m_dwChannelMask);
355  ntStatus = STATUS_SUCCESS;
356  }
357  }
358 
359  // accept also surround or quad.
360  if ((*(PLONG)PropertyRequest->Value == KSAUDIO_SPEAKER_QUAD) ||
361  (*(PLONG)PropertyRequest->Value == KSAUDIO_SPEAKER_SURROUND))
362  {
363  that->m_dwChannelMask = *(PLONG)PropertyRequest->Value;
364  that->m_wChannels = 4;
365  that->AdapterCommon->WriteChannelConfigDefault (that->m_dwChannelMask);
366  ntStatus = STATUS_SUCCESS;
367  }
368  }
369 
370  // accept also stereo speakers.
371  if (*(PLONG)PropertyRequest->Value == KSAUDIO_SPEAKER_STEREO)
372  {
373  that->m_dwChannelMask = *(PLONG)PropertyRequest->Value;
374  that->m_wChannels = 2;
375  that->AdapterCommon->WriteChannelConfigDefault (that->m_dwChannelMask);
376  ntStatus = STATUS_SUCCESS;
377  }
378  }
379  }
380 
381  return ntStatus;
382 }
383 
384 
385 /*****************************************************************************
386  * CMiniport::BuildDataRangeInformation
387  *****************************************************************************
388  * This function dynamically build the data range information for the pins.
389  * It also connects the static arrays with the data range information
390  * structure.
391  * If this function returns with an error the miniport should be destroyed.
392  *
393  * To build the data range information, we test the most popular sample rates,
394  * the functions calls ProgramSampleRate in AdapterCommon object to actually
395  * program the sample rate. After probing that way for multiple sample rates,
396  * the original value, which is 48KHz is, gets restored.
397  * We have to test the sample rates for playback, capture and microphone
398  * separately. Every time we succeed, we update the data range information and
399  * the pointers that point to it.
400  */
402 {
403  PAGED_CODE ();
404 
405  NTSTATUS ntStatus;
406  int nWavePlaybackEntries = 0;
407  int nWaveRecordingEntries = 0;
408  int nMicEntries = 0;
409  int nChannels;
410  int nLoop;
411 
412  DOUT (DBG_PRINT, ("[CMiniport::BuildDataRangeInformation]"));
413 
414  //
415  // Calculate the number of max. channels available in the codec.
416  //
417  if (AdapterCommon->GetPinConfig (PINC_SURROUND_PRESENT))
418  {
419  if (AdapterCommon->GetPinConfig (PINC_CENTER_LFE_PRESENT))
420  {
421  nChannels = 6;
422  }
423  else
424  {
425  nChannels = 4;
426  }
427  }
428  else
429  {
430  nChannels = 2;
431  }
432 
433  // Check for the render sample rates.
434  for (nLoop = 0; nLoop < WAVE_SAMPLERATES_TESTED; nLoop++)
435  {
436  ntStatus = AdapterCommon->ProgramSampleRate (AC97REG_FRONT_SAMPLERATE,
437  dwWaveSampleRates[nLoop]);
438 
439  // We support the sample rate?
440  if (NT_SUCCESS (ntStatus))
441  {
442  // Add it to the PinDataRange
443  PinDataRangesPCMStreamRender[nWavePlaybackEntries].DataRange.FormatSize = sizeof(KSDATARANGE_AUDIO);
444  PinDataRangesPCMStreamRender[nWavePlaybackEntries].DataRange.Flags = 0;
445  PinDataRangesPCMStreamRender[nWavePlaybackEntries].DataRange.SampleSize = nChannels * 2;
446  PinDataRangesPCMStreamRender[nWavePlaybackEntries].DataRange.Reserved = 0;
451  PinDataRangesPCMStreamRender[nWavePlaybackEntries].MinimumBitsPerSample = 16;
452  PinDataRangesPCMStreamRender[nWavePlaybackEntries].MaximumBitsPerSample = 16;
455 
456  // Add it to the PinDataRangePointer
457  PinDataRangePointersPCMStreamRender[nWavePlaybackEntries] = (PKSDATARANGE)&PinDataRangesPCMStreamRender[nWavePlaybackEntries];
458 
459  // Increase count
460  nWavePlaybackEntries++;
461  }
462  }
463 
464  // Check for the capture sample rates.
465  for (nLoop = 0; nLoop < WAVE_SAMPLERATES_TESTED; nLoop++)
466  {
467  ntStatus = AdapterCommon->ProgramSampleRate (AC97REG_RECORD_SAMPLERATE, dwWaveSampleRates[nLoop]);
468 
469  // We support the sample rate?
470  if (NT_SUCCESS (ntStatus))
471  {
472  // Add it to the PinDataRange
473  PinDataRangesPCMStreamCapture[nWaveRecordingEntries].DataRange.FormatSize = sizeof(KSDATARANGE_AUDIO);
474  PinDataRangesPCMStreamCapture[nWaveRecordingEntries].DataRange.Flags = 0;
475  PinDataRangesPCMStreamCapture[nWaveRecordingEntries].DataRange.SampleSize = 4;
476  PinDataRangesPCMStreamCapture[nWaveRecordingEntries].DataRange.Reserved = 0;
480  PinDataRangesPCMStreamCapture[nWaveRecordingEntries].MaximumChannels = 2;
481  PinDataRangesPCMStreamCapture[nWaveRecordingEntries].MinimumBitsPerSample = 16;
482  PinDataRangesPCMStreamCapture[nWaveRecordingEntries].MaximumBitsPerSample = 16;
485 
486  // Add it to the PinDataRangePointer
487  PinDataRangePointersPCMStreamCapture[nWaveRecordingEntries] = (PKSDATARANGE)&PinDataRangesPCMStreamCapture[nWaveRecordingEntries];
488 
489  // Increase count
490  nWaveRecordingEntries++;
491  }
492  }
493 
494  // Check for the MIC sample rates.
495  for (nLoop = 0; nLoop < int(MIC_SAMPLERATES_TESTED); nLoop++)
496  {
497  ntStatus = AdapterCommon->ProgramSampleRate (AC97REG_MIC_SAMPLERATE, dwMicSampleRates[nLoop]);
498 
499  // We support the sample rate?
500  if (NT_SUCCESS (ntStatus))
501  {
502  // Add it to the PinDataRange
504  PinDataRangesMicStream[nMicEntries].DataRange.Flags = 0;
506  PinDataRangesMicStream[nMicEntries].DataRange.Reserved = 0;
510  PinDataRangesMicStream[nMicEntries].MaximumChannels = 1;
515 
516  // Add it to the PinDataRangePointer
518 
519  // Increase count
520  nMicEntries++;
521  }
522  }
523 
524  // Now go through the pin descriptor list and change the data range entries to the actual number.
525  for (nLoop = 0; nLoop < int(SIZEOF_ARRAY(MiniportPins)); nLoop++)
526  {
527  if (MiniportPins[nLoop].KsPinDescriptor.DataRanges == PinDataRangePointersPCMStreamRender)
528  MiniportPins[nLoop].KsPinDescriptor.DataRangesCount = nWavePlaybackEntries;
529  if (MiniportPins[nLoop].KsPinDescriptor.DataRanges == PinDataRangePointersPCMStreamCapture)
530  MiniportPins[nLoop].KsPinDescriptor.DataRangesCount = nWaveRecordingEntries;
531  if (MiniportPins[nLoop].KsPinDescriptor.DataRanges == PinDataRangePointersMicStream)
532  MiniportPins[nLoop].KsPinDescriptor.DataRangesCount = nMicEntries;
533  }
534 
535  return STATUS_SUCCESS;
536 }
537 
538 
539 /*****************************************************************************
540  * CMiniport::GetDescription
541  *****************************************************************************
542  * Gets the topology.
543  */
544 STDMETHODIMP_(NTSTATUS) CMiniport::GetDescription
545 (
546  _Out_ PPCFILTER_DESCRIPTOR *OutFilterDescriptor
547 )
548 {
549  PAGED_CODE ();
550 
551  ASSERT (OutFilterDescriptor);
552 
553  DOUT (DBG_PRINT, ("[CMiniport::GetDescription]"));
554 
555  *OutFilterDescriptor = &MiniportFilterDescriptor;
556 
557 
558  return STATUS_SUCCESS;
559 }
560 
561 
562 /*****************************************************************************
563 
564 
565  * CMiniport::DataRangeIntersection
566  *****************************************************************************
567  * Tests a data range intersection.
568  * Cause the AC97 controller does not support mono render or capture, we have
569  * to check the max. channel field (unfortunately, there is no MinimumChannel
570  * and MaximumChannel field, just a MaximumChannel field).
571  * If the MaximumChannel is 2, then we can pass this to the default handler of
572  * portcls which always chooses the most (SampleFrequency, Channel, Bits etc.)
573  *
574  * This DataRangeIntersection function is strictly only for the exposed formats
575  * in this sample driver. If you intend to add other formats like AC3 then
576  * you have to be make sure that you check the GUIDs and the data range, since
577  * portcls only checks the data range for waveformatex.
578  */
580 STDMETHODIMP_(NTSTATUS) CMiniport::DataRangeIntersection
581 (
582  ULONG PinId,
583  PKSDATARANGE ClientsDataRange,
584  PKSDATARANGE MyDataRange,
585 
587  PVOID ResultantFormat,
588  PULONG ResultantFormatLength
589 )
590 {
591  PAGED_CODE ();
592 
593  DOUT (DBG_PRINT, ("[CMiniport::DataRangeIntersection]"));
594 
595  //
596  // This function gets only called if the GUIDS in the KSDATARANGE_AUDIO
597  // structure that we attached to the pin are equal with the requested
598  // format (see "BuildDataRangeInformation).
599  // Additionally, for waveformatex portcls checks that the requested sample
600  // frequency range fits into our exposed sample frequency range. Since we
601  // only have discrete sample frequencies in the pin's data range, we don't
602  // have to check that either.
603  // There is one exception to this rule: portcls clones all WAVEFORMATEX
604  // data ranges to DSOUND dataranges, so we might get a data range
605  // intersection that has a DSOUND specifier. We don't support that
606  // since this is only used for HW acceleration
607  //
609  {
610  DOUT (DBG_PRINT, ("[DataRangeIntersection] We don't support DSOUND specifier"));
611  return STATUS_NOT_SUPPORTED;
612  }
613 
614  //
615  // Start with checking the size of the output buffer and validating that it is not NULL.
616  //
617  if (!OutputBufferLength || NULL == ResultantFormat)
618  {
619  *ResultantFormatLength = sizeof(KSDATAFORMAT) + sizeof(WAVEFORMATPCMEX);
620  return STATUS_BUFFER_OVERFLOW;
621  }
622 
623  if (OutputBufferLength < (sizeof(KSDATAFORMAT) + sizeof(WAVEFORMATPCMEX)))
624  {
625  DOUT (DBG_WARNING, ("[DataRangeIntersection] Buffer too small"));
627  }
628 
629  //
630  // We can only play or record multichannel (>=2 channels) except for the MIC
631  // recording channel where we can only record mono. Portcls checked the channels
632  // already, however, since we have no minimum channels field, the KSDATARANGE_AUDIO
633  // could have MaximumChannels = 1.
634  //
635  if (PinId != PIN_MICIN)
636  {
637  // reject mono format for normal wave playback or capture.
638  if (((PKSDATARANGE_AUDIO)ClientsDataRange)->MaximumChannels < 2)
639  {
640  DOUT (DBG_WARNING, ("[DataRangeIntersection] Mono requested for WaveIn or WaveOut"));
641  return STATUS_NO_MATCH;
642  }
643  }
644 
645  //
646  // Fill in the structure the datarange structure.
647  // KSDATARANGE and KSDATAFORMAT are the same.
648  //
649  *(PKSDATAFORMAT)ResultantFormat = *MyDataRange;
650 
651  //
652  // Modify the size of the data format structure to fit the WAVEFORMATPCMEX
653  // structure.
654  //
655  ((PKSDATAFORMAT)ResultantFormat)->FormatSize =
656  sizeof(KSDATAFORMAT) + sizeof(WAVEFORMATPCMEX);
657 
658  //
659  // Append the WAVEFORMATPCMEX structur.
660  //
661  PWAVEFORMATPCMEX WaveFormat = (PWAVEFORMATPCMEX)((PKSDATAFORMAT)ResultantFormat + 1);
662 
663  // We want a WAFEFORMATEXTENSIBLE which is equal to WAVEFORMATPCMEX.
665  // Set the number of channels
666  if (PinId == PIN_WAVEOUT)
667  {
668  // Get the max. possible channels for playback.
669  ULONG nMaxChannels = min (((PKSDATARANGE_AUDIO)ClientsDataRange)->MaximumChannels, m_wChannels);
670 
671  // We cannot play uneven number of channels
672  if (nMaxChannels & 0x01)
673  nMaxChannels--;
674  // ... and also 0 channels wouldn't be a good request.
675  if (!nMaxChannels)
676  return STATUS_NO_MATCH;
677 
678  WaveFormat->Format.nChannels = (WORD)nMaxChannels;
679  }
680  else
681  // This will be 2 for normal record and 1 for MIC record.
682  WaveFormat->Format.nChannels = (WORD)((PKSDATARANGE_AUDIO)MyDataRange)->MaximumChannels;
683 
684  //
685  // Hack for codecs that have only one sample rate converter that has both
686  // playback and recording data.
687  //
690  {
691  //
692  // We have to return this sample rate that is used in the open stream.
693  //
694  ULONG ulFrequency;
695 
698  else
700 
701  //
702  // Check if this sample rate is in the requested data range of the client.
703  //
704  if ((((PKSDATARANGE_AUDIO)ClientsDataRange)->MaximumSampleFrequency < ulFrequency) ||
705  (((PKSDATARANGE_AUDIO)ClientsDataRange)->MinimumSampleFrequency > ulFrequency))
706  {
707  return STATUS_NO_MATCH;
708  }
709 
710  WaveFormat->Format.nSamplesPerSec = ulFrequency;
711  }
712  else
713  {
714  // Since we have discrete frequencies in the data range, min = max.
715  WaveFormat->Format.nSamplesPerSec = ((PKSDATARANGE_AUDIO)MyDataRange)->MaximumSampleFrequency;
716  }
717 
718  // Will be 16.
719  WaveFormat->Format.wBitsPerSample = (WORD)((PKSDATARANGE_AUDIO)MyDataRange)->MaximumBitsPerSample;
720  // Will be 2 * channels.
721  WaveFormat->Format.nBlockAlign = (WaveFormat->Format.wBitsPerSample * WaveFormat->Format.nChannels) / 8;
722  // That is played in a sec.
723  WaveFormat->Format.nAvgBytesPerSec = WaveFormat->Format.nSamplesPerSec * WaveFormat->Format.nBlockAlign;
724  // WAVEFORMATPCMEX
725  WaveFormat->Format.cbSize = 22;
726  // We have as many valid bits as the bit depth is (16).
727  WaveFormat->Samples.wValidBitsPerSample = WaveFormat->Format.wBitsPerSample;
728  // Set the channel mask
729  if (PinId == PIN_WAVEOUT)
730  {
731  // If we can play in our configuration, then set the channel mask
732  if (WaveFormat->Format.nChannels == m_wChannels)
733  // Set the playback channel mask to the current speaker config.
734  WaveFormat->dwChannelMask = m_dwChannelMask;
735  else
736  {
737  //
738  // We have to set a channel mask.
739  // nChannles can only be 4 if we are in 6 channel mode. In that
740  // case it must be a QUAD configurations. The only other value
741  // allowed is 2 channels, which defaults to stereo.
742  //
743  if (WaveFormat->Format.nChannels == 4)
744  WaveFormat->dwChannelMask = KSAUDIO_SPEAKER_QUAD;
745  else
747  }
748  }
749  else
750  {
751  // This will be KSAUDIO_SPEAKER_STEREO for normal record and KSAUDIO_SPEAKER_MONO
752  // for MIC record.
753  if (PinId == PIN_MICIN)
754  // MicIn -> 1 channel
755  WaveFormat->dwChannelMask = KSAUDIO_SPEAKER_MONO;
756  else
757  // normal record -> 2 channels
759  }
760  // Here we specify the subtype of the WAVEFORMATEXTENSIBLE.
761  WaveFormat->SubFormat = KSDATAFORMAT_SUBTYPE_PCM;
762 
763  // Now overwrite also the sample size in the ksdataformat structure.
764  ((PKSDATAFORMAT)ResultantFormat)->SampleSize = WaveFormat->Format.nBlockAlign;
765 
766  //
767  // That we will return.
768  //
769  *ResultantFormatLength = sizeof(KSDATAFORMAT) + sizeof(WAVEFORMATPCMEX);
770 
771  DOUT (DBG_STREAM, ("[DataRangeIntersection] Frequency: %d, Channels: %d, bps: %d, ChannelMask: %X",
772  WaveFormat->Format.nSamplesPerSec, WaveFormat->Format.nChannels,
773  WaveFormat->Format.wBitsPerSample, WaveFormat->dwChannelMask));
774 
775  // Let portcls do some work ...
776  return STATUS_SUCCESS;
777 }
778 
779 
781 (
783  IN WavePins Pin
784 )
785 {
786  //
787  // Validate the channel (pin id).
788  //
789  if ((Pin != PIN_WAVEOUT) && (Pin != PIN_WAVEIN) &&
790  (Pin != PIN_MICIN))
791  {
792  DOUT (DBG_ERROR, ("[NewStream] Invalid channel passed!"));
794  }
795 
796  //
797  // Check if the pin is already in use
798  //
799  if (Streams[Pin/2])
800  {
801  DOUT (DBG_ERROR, ("[NewStream] Pin is already in use!"));
802  return STATUS_UNSUCCESSFUL;
803  }
804 
805  //
806  // Check parameters.
807  //
808  NTSTATUS ntStatus = TestDataFormat (DataFormat, Pin);
809  if (!NT_SUCCESS (ntStatus))
810  {
811  DOUT (DBG_VSR, ("[NewStream] TestDataFormat failed!"));
812  return ntStatus;
813  }
814 
815  return ntStatus;
816 }
817 
818 
819 /*****************************************************************************
820  * CMiniport::TestDataFormat
821  *****************************************************************************
822  * Checks if the passed data format is known to the driver and verifies that
823  * the number of channels, the width of one sample match to the AC97
824  * specification.
825  */
827 (
829  IN WavePins Pin
830 )
831 {
832  PAGED_CODE ();
833 
834  ASSERT (Format);
835 
836  DOUT (DBG_PRINT, ("[CMiniport::TestDataFormat]"));
837 
838  //
839  // KSDATAFORMAT contains three GUIDs to support extensible format. The
840  // first two GUIDs identify the type of data. The third indicates the
841  // type of specifier used to indicate format specifics. We are only
842  // supporting PCM audio formats that use WAVEFORMATEX.
843  //
844  if (!IsEqualGUIDAligned (Format->MajorFormat, KSDATAFORMAT_TYPE_AUDIO) ||
847  {
848  DOUT (DBG_ERROR, ("[TestDataFormat] Invalid format type!"));
850  }
851 
852  PWAVEFORMATPCMEX waveFormat = (PWAVEFORMATPCMEX)(Format + 1);
853 
854  //
855  // If the size doesn't match, then something is messed up.
856  //
857  if (Format->FormatSize < (sizeof(KSDATAFORMAT) + sizeof(WAVEFORMATEX)))
858  {
859  DOUT (DBG_WARNING, ("[TestDataFormat] Invalid FormatSize!"));
861  }
862 
863  //
864  // We only support PCM, 16-bit.
865  //
866  if (waveFormat->Format.wBitsPerSample != 16)
867  {
868  DOUT (DBG_WARNING, ("[TestDataFormat] Bits Per Sample must be 16!"));
870  }
871 
872  //
873  // We support WaveFormatPCMEX (=WAVEFORMATEXTENSIBLE) or WaveFormatPCM.
874  //
875  if ((waveFormat->Format.wFormatTag != WAVE_FORMAT_EXTENSIBLE) &&
876  (waveFormat->Format.wFormatTag != WAVE_FORMAT_PCM))
877  {
878  DOUT (DBG_WARNING, ("[TestDataFormat] Invalid Format Tag!"));
880  }
881 
882  //
883  // Make additional checks for the WAVEFORMATEXTENSIBLE
884  //
885  if (waveFormat->Format.wFormatTag == WAVE_FORMAT_EXTENSIBLE)
886  {
887  //
888  // If the size doesn't match, then something is messed up.
889  //
890  if (Format->FormatSize < (sizeof(KSDATAFORMAT) + sizeof(WAVEFORMATPCMEX)))
891  {
892  DOUT (DBG_WARNING, ("[TestDataFormat] Invalid FormatSize!"));
894  }
895 
896  //
897  // Check also the subtype (PCM) and the size of the extended data.
898  //
900  (waveFormat->Format.cbSize < (sizeof(WAVEFORMATPCMEX) - sizeof(WAVEFORMATEX))))
901  {
902  DOUT (DBG_WARNING, ("[TestDataFormat] Unsupported WAVEFORMATEXTENSIBLE!"));
904  }
905 
906  //
907  // Check the channel mask. We support 1, 2 channels or whatever was set
908  // with the Speaker config dialog.
909  //
910  if (((waveFormat->Format.nChannels == 1) &&
911  (waveFormat->dwChannelMask != KSAUDIO_SPEAKER_MONO)) ||
912  ((waveFormat->Format.nChannels == 2) &&
913  (waveFormat->dwChannelMask != KSAUDIO_SPEAKER_STEREO)) ||
914  ((waveFormat->Format.nChannels == m_wChannels) &&
915  (waveFormat->dwChannelMask != m_dwChannelMask)))
916  {
917  DOUT (DBG_WARNING, ("[TestDataFormat] Channel Mask!"));
919  }
920  }
921 
922  //
923  // Check the number of channels.
924  //
925  switch (Pin)
926  {
927  case PIN_MICIN: // 1 channel
928  if (waveFormat->Format.nChannels != 1)
929  {
930  DOUT (DBG_WARNING, ("[TestDataFormat] Invalid Number of Channels for PIN_MICIN!"));
932  }
933  break;
934  case PIN_WAVEIN: // 2 channels
935  if (waveFormat->Format.nChannels != 2)
936  {
937  DOUT (DBG_WARNING, ("[TestDataFormat] Invalid Number of Channels for PIN_WAVEIN!"));
939  }
940  break;
941  case PIN_WAVEOUT: // channel and mask from PropertyChannelConfig or standard.
942  if (waveFormat->Format.nChannels != m_wChannels)
943  {
944  DOUT (DBG_WARNING, ("[TestDataFormat] Invalid Number of Channels for PIN_WAVEOUT!"));
946  }
947  break;
948  }
949 
950  //
951  // Print the information.
952  //
953  if (waveFormat->Format.wFormatTag == WAVE_FORMAT_EXTENSIBLE)
954  {
955  DOUT (DBG_STREAM, ("[TestDataFormat] PCMEX - Frequency: %d, Channels: %d, bps: %d, ChannelMask: %X",
956  waveFormat->Format.nSamplesPerSec, waveFormat->Format.nChannels,
957  waveFormat->Format.wBitsPerSample, waveFormat->dwChannelMask));
958  }
959  else
960  {
961  DOUT (DBG_STREAM, ("[TestDataFormat] PCM - Frequency: %d, Channels: %d, bps: %d",
962  waveFormat->Format.nSamplesPerSec, waveFormat->Format.nChannels,
963  waveFormat->Format.wBitsPerSample));
964  }
965 
966  return STATUS_SUCCESS;
967 }
968 
969 /*****************************************************************************
970  * CMiniport::PowerChangeNotify
971  *****************************************************************************
972  * This routine gets called as a result of hooking up the IPowerNotify
973  * interface. This interface indicates the driver's desire to receive explicit
974  * notification of power state changes. The interface provides a single method
975  * (or callback) that is called by the miniport's corresponding port driver in
976  * response to a power state change. Using wave audio as an example, when the
977  * device is requested to go to a sleep state the port driver pauses any
978  * active streams and then calls the power notify callback to inform the
979  * miniport of the impending power down. The miniport then has an opportunity
980  * to save any necessary context before the adapter's PowerChangeState method
981  * is called. The process is reversed when the device is powering up. PortCls
982  * first calls the adapter's PowerChangeState method to power up the adapter.
983  * The port driver then calls the miniport's callback to allow the miniport to
984  * restore its context. Finally, the port driver unpauses any previously paused
985  * active audio streams.
986  */
987 STDMETHODIMP_(void) CMiniport::PowerChangeNotify
988 (
989  _In_ POWER_STATE NewState
990 )
991 {
992  PAGED_CODE ();
993  NTSTATUS ntStatus = STATUS_SUCCESS;
994 
995  DOUT (DBG_PRINT, ("[CMiniport::PowerChangeNotify]"));
996 
997  //
998  // Check to see if this is the current power state.
999  //
1000  if (NewState.DeviceState == m_PowerState)
1001  {
1002  DOUT (DBG_POWER, ("New device state equals old state."));
1003  return;
1004  }
1005 
1006  //
1007  // Check the new device state.
1008  //
1009  if ((NewState.DeviceState < PowerDeviceD0) ||
1010  (NewState.DeviceState > PowerDeviceD3))
1011  {
1012  DOUT (DBG_ERROR, ("Unknown device state: D%d.",
1013  (ULONG)NewState.DeviceState - (ULONG)PowerDeviceD0));
1014  return;
1015  }
1016 
1017  DOUT (DBG_POWER, ("Changing state to D%d.", (ULONG)NewState.DeviceState -
1018  (ULONG)PowerDeviceD0));
1019 
1020  //
1021  // In case we return to D0 power state from a D3 state, restore the
1022  // interrupt connection.
1023  //
1024  if (NewState.DeviceState == PowerDeviceD0)
1025  {
1026  ntStatus = InterruptSync->Connect ();
1027  if (!NT_SUCCESS (ntStatus))
1028  {
1029  DOUT (DBG_ERROR, ("Failed to connect the ISR with InterruptSync!"));
1030  // We can do nothing else than just continue ...
1031  }
1032  }
1033 
1034  //
1035  // Call the stream routine which takes care of the DMA engine.
1036  // That's all we have to do.
1037  //
1038  for (int loop = PIN_WAVEOUT_OFFSET; loop < PIN_MICIN_OFFSET; loop++)
1039  {
1040  if (Streams[loop])
1041  {
1042  Streams[loop]->PowerChangeNotify (NewState);
1043  }
1044  }
1045 
1046  //
1047  // In case we go to any sleep state we disconnect the interrupt service
1048  // reoutine from the interrupt.
1049  // Normally this is not required to do, but for some reason this fixes
1050  // a problem where we won't have any interrupts on specific motherboards
1051  // after resume.
1052  //
1053  if (NewState.DeviceState != PowerDeviceD0)
1054  {
1055  InterruptSync->Disconnect ();
1056  }
1057 
1058  //
1059  // Save the new state. This local value is used to determine when to
1060  // cache property accesses and when to permit the driver from accessing
1061  // the hardware.
1062  //
1063  m_PowerState = NewState.DeviceState;
1064  DOUT (DBG_POWER, ("Entering D%d",
1066 }
1067 
1068 /*****************************************************************************
1069  * CMiniport::ProcessResources
1070  *****************************************************************************
1071  * Processes the resource list, setting up helper objects accordingly.
1072  * Sets up the Interrupt + Service routine and DMA.
1073  */
1077 )
1078 {
1079  PAGED_CODE ();
1080 
1081  ASSERT (ResourceList);
1082 
1083 
1084  DOUT (DBG_PRINT, ("[CMiniport::ProcessResources]"));
1085 
1086 
1087  ULONG countIRQ = ResourceList->NumberOfInterrupts ();
1088  if (countIRQ < 1)
1089  {
1090  DOUT (DBG_ERROR, ("Unknown configuration for wave miniport!"));
1092  }
1093 
1094  //
1095  // Create an interrupt sync object
1096  //
1097  NTSTATUS ntStatus = STATUS_SUCCESS;
1098  ntStatus = PcNewInterruptSync (&InterruptSync,
1099  NULL,
1100  ResourceList,
1101  0,
1103 
1104  if (!NT_SUCCESS (ntStatus) || !InterruptSync)
1105  {
1106  DOUT (DBG_ERROR, ("Failed to create an interrupt sync!"));
1108  }
1109 
1110  //
1111  // Register our ISR.
1112  //
1113  ntStatus = InterruptSync->RegisterServiceRoutine (InterruptServiceRoutine,
1114  (PVOID)this, FALSE);
1115  if (!NT_SUCCESS (ntStatus))
1116  {
1117  DOUT (DBG_ERROR, ("Failed to register ISR!"));
1118  return ntStatus;
1119  }
1120 
1121  //
1122  // Connect the interrupt.
1123  //
1124  ntStatus = InterruptSync->Connect ();
1125  if (!NT_SUCCESS (ntStatus))
1126  {
1127  DOUT (DBG_ERROR, ("Failed to connect the ISR with InterruptSync!"));
1128  return ntStatus;
1129  }
1130 
1131  //
1132  // On failure object is destroyed which cleans up.
1133  //
1134  return STATUS_SUCCESS;
1135 }
1136 
1137 /*****************************************************************************
1138  * CMiniport::NonDelegatingQueryInterface
1139  *****************************************************************************
1140  * Obtains an interface. This function works just like a COM QueryInterface
1141  * call and is used if the object is not being aggregated.
1142  */
1147  _In_ REFIID iMiniPort,
1148  _In_ PMINIPORT miniPort
1149 )
1150 {
1151  PAGED_CODE ();
1152 
1153  ASSERT (Object);
1154 
1155  DOUT (DBG_PRINT, ("[CMiniport::NonDelegatingQueryInterface]"));
1156 
1157  // Is it IID_IUnknown?
1159  {
1160  *Object = (PVOID)miniPort;
1161  }
1162  // or IID_IMiniport ...
1163  else if (IsEqualGUIDAligned (Interface, IID_IMiniport))
1164  {
1165  *Object = (PVOID)miniPort;
1166  }
1167  // or IID_IMiniportWavePci ...
1168  else if (IsEqualGUIDAligned (Interface, iMiniPort))
1169  {
1170  *Object = (PVOID)miniPort;
1171  }
1172  // or IID_IPowerNotify ...
1173  else if (IsEqualGUIDAligned (Interface, IID_IPowerNotify))
1174  {
1175  *Object = (PVOID)(PPOWERNOTIFY)this;
1176  }
1177  else
1178  {
1179  // nothing found, must be an unknown interface.
1180  *Object = NULL;
1181  return STATUS_INVALID_PARAMETER;
1182  }
1183 
1184  //
1185  // We reference the interface for the caller.
1186  //
1187  ((PUNKNOWN)(*Object))->AddRef();
1188  return STATUS_SUCCESS;
1189 }
1190 
1191 /*****************************************************************************
1192  * CAC97MiniportWaveRT::Init
1193  *****************************************************************************
1194  * Initializes the miniport.
1195  * Initializes variables and modifies the wave topology if needed.
1196  */
1198 (
1199  _In_ PUNKNOWN UnknownAdapter,
1201  _In_ PPORT Port_
1202 )
1203 {
1204  PAGED_CODE ();
1205 
1206  ASSERT (UnknownAdapter);
1207  ASSERT (ResourceList);
1208  ASSERT (Port_);
1209 
1210  DOUT (DBG_PRINT, ("[CMiniport::Init]"));
1211 
1212  //
1213  // AddRef() is required because we are keeping this pointer.
1214  //
1215  obj_AddRef(Port_, (PVOID *)&Port);
1216 
1217  //
1218  // Set initial device power state
1219  //
1221 
1222  NTSTATUS ntStatus = UnknownAdapter->
1223  QueryInterface (IID_IAC97AdapterCommon, (PVOID *)&AdapterCommon);
1224  if (NT_SUCCESS (ntStatus))
1225  {
1226  //
1227  // Alter the topology for the wave miniport.
1228  //
1229  if (!(AdapterCommon->GetPinConfig (PINC_MICIN_PRESENT) &&
1230  AdapterCommon->GetPinConfig (PINC_MIC_PRESENT)))
1231  {
1232  //
1233  // Remove the pins, nodes and connections for the MICIN.
1234  //
1238  }
1239 
1240  //
1241  // Process the resources.
1242  //
1243  ntStatus = ProcessResources (ResourceList);
1244 
1245  //
1246  // Get the default channel config
1247  //
1248  AdapterCommon->ReadChannelConfigDefault (&m_dwChannelMask, &m_wChannels);
1249 
1250  //
1251  // If we came till that point, check the CoDec for supported standard
1252  // sample rates. This function will then fill the data range information
1253  //
1254  if (NT_SUCCESS (ntStatus))
1255  ntStatus = BuildDataRangeInformation ();
1256  }
1257 
1258  //
1259  // If we fail we get destroyed anyway (that's where we clean up).
1260  //
1261  return ntStatus;
1262 }
1263 
1265 {
1266  if(ppvObject) {
1267  *ppvObject = obj;
1268  if(obj) obj->AddRef();
1269  }
1270 }
1271 
1272 
1274 {
1275  if(ppvObject) {
1277  *ppvObject = NULL;
1278  if(obj) obj->Release();
1279  }
1280 }
1281 
1282 /*****************************************************************************
1283  * CAC97MiniportWaveRT::~CAC97MiniportWaveRT
1284  *****************************************************************************
1285  * Destructor.
1286  */
1288 {
1289  PAGED_CODE ();
1290 
1291  DOUT (DBG_PRINT, ("[CMiniport::~CMiniport]"));
1292 
1296  obj_Release((PVOID *)&Port);
1297 }
1298 
1299 /*****************************************************************************
1300  * Non paged code begins here
1301  *****************************************************************************
1302  */
1303 
1304 #ifdef _MSC_VER
1305 #pragma code_seg()
1306 #endif
1307 /*****************************************************************************
1308  * InterruptServiceRoutine
1309  *****************************************************************************
1310  * The task of the ISR is to clear an interrupt from this device so we don't
1311  * get an interrupt storm and schedule a DPC which actually does the
1312  * real work.
1313  */
1316  IN PINTERRUPTSYNC InterruptSync,
1318 )
1319 {
1320  UNREFERENCED_PARAMETER(InterruptSync);
1321 
1322  ASSERT (InterruptSync);
1324 
1325  ULONG GlobalStatus;
1326  USHORT DMAStatusRegister;
1327 
1328  //
1329  // Get our context which is a pointer to class CAC97MiniportWaveRT.
1330  //
1331  CMiniport *that = (CMiniport *)DynamicContext;
1332 
1333  //
1334  // Check for a valid AdapterCommon pointer.
1335  //
1336  if (!that->AdapterCommon)
1337  {
1338  //
1339  // In case we didn't handle the interrupt, unsuccessful tells the system
1340  // to call the next interrupt handler in the chain.
1341  //
1342  return STATUS_UNSUCCESSFUL;
1343  }
1344 
1345  //
1346  // From this point down, basically in the complete ISR, we cannot use
1347  // relative addresses (stream class base address + X_CR for example)
1348  // cause we might get called when the stream class is destroyed or
1349  // not existent. This doesn't make too much sense (that there is an
1350  // interrupt for a non-existing stream) but could happen and we have
1351  // to deal with the interrupt.
1352  //
1353 
1354  //
1355  // Read the global register to check the interrupt bits
1356  //
1357  GlobalStatus = that->AdapterCommon->ReadBMControlRegister32 (GLOB_STA);
1358 
1359  //
1360  // Check for weird return values. Could happen if the PCI device is already
1361  // disabled and another device that shares this interrupt generated an
1362  // interrupt.
1363  // The register should never have all bits cleared or set.
1364  //
1365  if (!GlobalStatus || (GlobalStatus == 0xFFFFFFFF))
1366  {
1367  return STATUS_UNSUCCESSFUL;
1368  }
1369 
1370  //
1371  // Check for PCM out interrupt.
1372  //
1373  NTSTATUS ntStatus = STATUS_UNSUCCESSFUL;
1374  if (GlobalStatus & GLOB_STA_POINT)
1375  {
1376  //
1377  // Read PCM out DMA status registers.
1378  //
1379  DMAStatusRegister = (USHORT)that->AdapterCommon->
1380  ReadBMControlRegister16 (PO_SR);
1381 
1382 
1383  //
1384  // We could now check for every possible error condition
1385  // (like FIFO error) and monitor the different errors, but currently
1386  // we have the same action for every INT and therefore we simplify
1387  // this routine enormous with just clearing the bits.
1388  //
1389  if (that->Streams[PIN_WAVEOUT_OFFSET])
1390  {
1391  //
1392  // ACK the interrupt.
1393  //
1394  that->AdapterCommon->WriteBMControlRegister (PO_SR, DMAStatusRegister);
1395  ntStatus = STATUS_SUCCESS;
1396 
1397  //
1398 
1400  }
1401  }
1402 
1403  //
1404  // Check for PCM in interrupt.
1405  //
1406  if (GlobalStatus & GLOB_STA_PIINT)
1407  {
1408  //
1409  // Read PCM in DMA status registers.
1410  //
1411  DMAStatusRegister = (USHORT)that->AdapterCommon->
1412  ReadBMControlRegister16 (PI_SR);
1413 
1414  //
1415  // We could now check for every possible error condition
1416  // (like FIFO error) and monitor the different errors, but currently
1417  // we have the same action for every INT and therefore we simplify
1418  // this routine enormous with just clearing the bits.
1419  //
1420  if (that->Streams[PIN_WAVEIN_OFFSET])
1421  {
1422  //
1423  // ACK the interrupt.
1424  //
1425  that->AdapterCommon->WriteBMControlRegister (PI_SR, DMAStatusRegister);
1426  ntStatus = STATUS_SUCCESS;
1427 
1429  }
1430  }
1431 
1432  //
1433  // Check for MIC in interrupt.
1434  //
1435  if (GlobalStatus & GLOB_STA_MINT)
1436  {
1437  //
1438  // Read MIC in DMA status registers.
1439  //
1440  DMAStatusRegister = (USHORT)that->AdapterCommon->
1441  ReadBMControlRegister16 (MC_SR);
1442 
1443  //
1444  // We could now check for every possible error condition
1445  // (like FIFO error) and monitor the different errors, but currently
1446  // we have the same action for every INT and therefore we simplify
1447  // this routine enormous with just clearing the bits.
1448  //
1449  if (that->Streams[PIN_MICIN_OFFSET])
1450  {
1451  //
1452  // ACK the interrupt.
1453  //
1454  that->AdapterCommon->WriteBMControlRegister (MC_SR, DMAStatusRegister);
1455  ntStatus = STATUS_SUCCESS;
1456 
1458  }
1459  }
1460 
1461  return ntStatus;
1462 }
ULONG GetCurrentSampleRate(void)
Definition: stream.h:130
#define IN
Definition: typedefs.h:39
return STATUS_NOT_SUPPORTED
#define REFIID
Definition: guiddef.h:118
const int DBG_WARNING
Definition: debug.h:18
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
const int PIN_MICIN_OFFSET
Definition: miniport.h:23
#define KSDATAFORMAT_SUBTYPE_PCM
Definition: ksmedia.h:1021
DWORD m_dwChannelMask
Definition: miniport.h:35
#define KSAUDIO_SPEAKER_STEREO
Definition: ksmedia.h:1454
NTSTATUS ValidateFormat(IN PKSDATAFORMAT DataFormat, IN WavePins Pin)
Definition: miniport.cpp:781
static PCCONNECTION_DESCRIPTOR MiniportConnections[]
Definition: miniport.cpp:264
union KSDATAFORMAT KSDATARANGE
#define _Out_
Definition: ms_sal.h:345
#define __fastcall
Definition: sync.c:38
WORD m_wChannels
Definition: miniport.h:36
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:317
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
IUnknown * PUNKNOWN
Definition: com_apitest.h:45
#define KSPROPSETID_Audio
Definition: ksmedia.h:1051
ULONG MaximumBitsPerSample
Definition: ksmedia.h:682
static HRESULT QueryInterface(REFIID, void **)
Definition: events.c:2587
NTSTATUS NonDelegatingQueryInterface(_In_ REFIID Interface, _COM_Outptr_ PVOID *Object, _In_ REFIID iMiniPort, _In_ PMINIPORT miniPort)
Definition: miniport.cpp:1144
void PowerChangeNotify(IN POWER_STATE NewState)
Definition: stream.cpp:289
LONG NTSTATUS
Definition: precomp.h:26
const ULONG PI_SR
Definition: ichreg.h:24
const ULONG PO_SR
Definition: ichreg.h:31
PINTERRUPTSYNC InterruptSync
Definition: miniport.h:32
static PCPIN_DESCRIPTOR MiniportPins[]
Definition: miniport.cpp:79
static KSDATARANGE_AUDIO PinDataRangesPCMStreamCapture[WAVE_SAMPLERATES_TESTED]
Definition: miniport.cpp:17
#define KSAUDIO_SPEAKER_MONO
Definition: ksmedia.h:1453
BOOL Init(PUSERCONNECT UserCon)
Definition: dllmain.c:385
#define KSAUDIO_SPEAKER_SURROUND
Definition: ksmedia.h:1457
KSPIN_DESCRIPTOR KsPinDescriptor
Definition: portcls.h:343
_In_ PRESOURCELIST _In_ PPORT Port_
Definition: miniport.h:96
#define KSAUDIO_SPEAKER_QUAD
Definition: ksmedia.h:1455
static PCNODE_DESCRIPTOR MiniportNodes[]
Definition: miniport.cpp:228
int nChannels
Definition: pcmconverter.c:95
#define DOUT(lvl, strings)
Definition: debug.h:82
static KSDATARANGE_AUDIO PinDataRangesPCMStreamRender[WAVE_SAMPLERATES_TESTED]
Definition: miniport.cpp:16
_Must_inspect_result_ _In_ WDFIORESREQLIST _In_opt_ PWDF_OBJECT_ATTRIBUTES _Out_ WDFIORESLIST * ResourceList
Definition: wdfresource.h:304
#define STATUS_BUFFER_TOO_SMALL
Definition: shellext.h:69
#define _Use_decl_annotations_
Definition: ms_sal.h:275
GLsizei GLsizei GLuint * obj
Definition: glext.h:6042
#define KSDATAFORMAT_SPECIFIER_WAVEFORMATEX
Definition: ksmedia.h:1031
#define IsEqualGUIDAligned(guid1, guid2)
Definition: wdm.template.h:235
ULONG ConnectionCount
Definition: portcls.h:362
_In_ WDFREQUEST _In_ size_t OutputBufferLength
Definition: wdfio.h:318
#define WAVE_FORMAT_PCM
Definition: constants.h:425
PDMACHANNEL DmaChannel
Definition: miniport.h:33
#define FALSE
Definition: types.h:117
const GUID KSCATEGORY_AUDIO
Definition: controls.c:25
static KSDATARANGE PinDataRangesAnalogBridge[]
Definition: miniport.cpp:20
long LONG
Definition: pedump.c:60
WORD wBitsPerSample
Definition: audioclient.idl:45
static NTSTATUS NTAPI PropertyChannelConfig(IN PPCPROPERTY_REQUEST PropertyRequest)
Definition: miniport.cpp:314
const int WAVE_SAMPLERATES_TESTED
Definition: miniport.h:13
NTSTATUS TestDataFormat(IN PKSDATAFORMAT Format, IN WavePins Pin)
Definition: miniport.cpp:827
const GUID KSDATAFORMAT_SPECIFIER_NONE
Definition: sup.c:37
KSDATARANGE DataRange
Definition: ksmedia.h:679
const ULONG GLOB_STA_POINT
Definition: ichreg.h:88
IPort * PPORT
Definition: portcls.h:1103
#define KSDATAFORMAT_SUBTYPE_ANALOG
Definition: ksmedia.h:993
#define KSAUDIO_SPEAKER_5POINT1
Definition: ksmedia.h:1459
const int PIN_WAVEIN_OFFSET
Definition: miniport.h:22
const ULONG GLOB_STA_MINT
Definition: ichreg.h:87
#define _In_
Definition: ms_sal.h:308
IMiniportWavePci * PMINIPORTWAVEPCI
Definition: portcls.h:1695
void * PVOID
Definition: retypes.h:9
DWORD nSamplesPerSec
Definition: audioclient.idl:42
const ULONG GLOB_STA_PIINT
Definition: ichreg.h:89
PADAPTERCOMMON AdapterCommon
Definition: miniport.h:31
void __fastcall obj_Release(void **ppvObject)
Definition: miniport.cpp:1273
static PKSDATARANGE PinDataRangePointersAnalogBridge[]
Definition: miniport.cpp:49
#define SIZEOF_ARRAY(ar)
Definition: cdrom.h:1482
#define KSAUDFNAME_RECORDING_CONTROL
Definition: ksmedia.h:333
#define ASSERT(a)
Definition: mode.c:44
IN PDCB IN VBO IN ULONG IN BOOLEAN Pin
Definition: fatprocs.h:424
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
WAVEFORMATEX Format
Definition: ksmedia.h:638
union WAVEFORMATEXTENSIBLE::@2979 Samples
const GUID IID_IUnknown
DEVICE_POWER_STATE m_PowerState
Definition: miniport.h:34
ULONG MinimumSampleFrequency
Definition: ksmedia.h:683
unsigned short WORD
Definition: ntddk_ex.h:93
ULONG MaximumChannels
Definition: ksmedia.h:680
const GUID KSNODETYPE_DAC
Definition: sup.c:15
NTSTATUS NTAPI PcNewInterruptSync(OUT PINTERRUPTSYNC *OutInterruptSync, IN PUNKNOWN OuterUnknown OPTIONAL, IN PRESOURCELIST ResourceList, IN ULONG ResourceIndex, IN INTERRUPTSYNCMODE Mode)
Definition: interrupt.cpp:305
#define STATICGUIDOF(guid)
Definition: dmksctrl.h:25
const int DBG_STREAM
Definition: debug.h:22
const DWORD dwMicSampleRates[MIC_SAMPLERATES_TESTED]
Definition: miniport.h:18
#define PINNAME_CAPTURE
Definition: ksmedia.h:147
struct KSDATARANGE_AUDIO * PKSDATARANGE_AUDIO
#define STATUS_UNSUCCESSFUL
Definition: udferr_usr.h:132
static PKSDATARANGE PinDataRangePointersMicStream[MIC_SAMPLERATES_TESTED]
Definition: miniport.cpp:42
const int DBG_ERROR
Definition: debug.h:19
#define PCFILTER_NODE
Definition: portcls.h:154
static PCFILTER_DESCRIPTOR MiniportFilterDescriptor
Definition: miniport.cpp:287
NTSTATUS BuildDataRangeInformation(void)
Definition: miniport.cpp:401
REFIID LPVOID * ppvObject
Definition: precomp.h:44
const int DBG_POWER
Definition: debug.h:23
#define KSDATAFORMAT_TYPE_AUDIO
Definition: ksmedia.h:983
_Must_inspect_result_ _In_ WDFCOLLECTION _In_ WDFOBJECT Object
STDMETHODIMP_(NTSTATUS) CMiniport
Definition: miniport.cpp:544
const int PIN_WAVEOUT_OFFSET
Definition: miniport.h:21
IResourceList * PRESOURCELIST
Definition: portcls.h:442
static PCPROPERTY_ITEM PropertiesDAC[]
Definition: miniport.cpp:206
union KSDATAFORMAT * PKSDATARANGE
const ULONG GLOB_STA
Definition: ichreg.h:43
const ULONG MC_SR
Definition: ichreg.h:38
const GUID KSNODETYPE_ADC
Definition: sup.c:16
WORD wValidBitsPerSample
Definition: ksmedia.h:641
#define KSDATAFORMAT_SPECIFIER_DSOUND
Definition: ksmedia.h:988
#define STATUS_BUFFER_OVERFLOW
Definition: shellext.h:66
NTSTATUS ProcessResources(IN PRESOURCELIST ResourceList)
Definition: miniport.cpp:1075
IN PVOID IN PVOID IN USHORT IN USHORT IN PINTERFACE Interface
Definition: pci.h:361
ULONG MaximumSampleFrequency
Definition: ksmedia.h:684
unsigned short USHORT
Definition: pedump.c:61
DWORD nAvgBytesPerSec
Definition: audioclient.idl:43
#define STATUS_NO_MATCH
Definition: ntstatus.h:751
CMiniportStream * Streams[PIN_MICIN_OFFSET+1]
Definition: miniport.h:29
const int DBG_VSR
Definition: debug.h:28
const int MIC_SAMPLERATES_TESTED
Definition: miniport.h:14
unsigned int * PULONG
Definition: retypes.h:1
#define min(a, b)
Definition: monoChain.cc:55
#define NULL
Definition: types.h:112
static KSDATARANGE_AUDIO PinDataRangesMicStream[MIC_SAMPLERATES_TESTED]
Definition: miniport.cpp:18
static ULONG WINAPI AddRef(IStream *iface)
Definition: clist.c:90
IInterruptSync * PINTERRUPTSYNC
Definition: portcls.h:888
ULONG MinimumBitsPerSample
Definition: ksmedia.h:681
IPowerNotify * PPOWERNOTIFY
Definition: portcls.h:2057
PPORT_ Port
Definition: miniport.h:30
virtual void InterruptServiceRoutine() PURE
unsigned int ULONG
Definition: retypes.h:1
WavePins
Definition: shared.h:316
const DWORD dwWaveSampleRates[WAVE_SAMPLERATES_TESTED]
Definition: miniport.h:16
static PKSDATARANGE PinDataRangePointersPCMStreamRender[WAVE_SAMPLERATES_TESTED]
Definition: miniport.cpp:40
#define STATUS_SUCCESS
Definition: shellext.h:65
WAVEFORMATPCMEX * PWAVEFORMATPCMEX
Definition: mmreg.h:468
#define STATUS_DEVICE_CONFIGURATION_ERROR
Definition: ntstatus.h:619
signed int * PLONG
Definition: retypes.h:5
#define KSPROPERTY_TYPE_SET
Definition: dmksctrl.h:43
DEFINE_PCAUTOMATION_TABLE_PROP(AutomationDAC, PropertiesDAC)
const int DBG_PRINT
Definition: debug.h:17
static NTSTATUS NTAPI InterruptServiceRoutine(IN PINTERRUPTSYNC InterruptSync, IN PVOID StaticContext)
Definition: miniport.cpp:1315
void __fastcall obj_AddRef(PUNKNOWN obj, void **ppvObject)
Definition: miniport.cpp:1264
IN PVOID DynamicContext
Definition: portcls.h:849
#define _COM_Outptr_
Definition: ms_sal.h:449
#define WAVE_FORMAT_EXTENSIBLE
Definition: ksmedia.h:651
KSDATAFORMAT * PKSDATAFORMAT
static PKSDATARANGE PinDataRangePointersPCMStreamCapture[WAVE_SAMPLERATES_TESTED]
Definition: miniport.cpp:41
#define PAGED_CODE()
unsigned int(__cdecl typeof(jpeg_read_scanlines))(struct jpeg_decompress_struct *
Definition: typeof.h:31