Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1037 lines
23 KiB

  1. /*++
  2. Copyright (c) 1997-2000 Microsoft Corporation All Rights Reserved
  3. Module Name:
  4. basewave.cpp
  5. Abstract:
  6. Implementation of wavecyclic miniport.
  7. --*/
  8. #include <msvad.h>
  9. #include "common.h"
  10. #include "basewave.h"
  11. //=============================================================================
  12. // CMiniportWaveCyclicMSVAD
  13. //=============================================================================
  14. //=============================================================================
  15. #pragma code_seg("PAGE")
  16. CMiniportWaveCyclicMSVAD::CMiniportWaveCyclicMSVAD
  17. (
  18. void
  19. )
  20. /*++
  21. Routine Description:
  22. Constructor for wavecyclic miniport.
  23. Arguments:
  24. Return Value:
  25. --*/
  26. {
  27. PAGED_CODE();
  28. DPF_ENTER(("[CMiniportWaveCyclicMSVAD::CMiniportWaveCyclicMSVAD]"));
  29. // Initialize members.
  30. //
  31. m_AdapterCommon = NULL;
  32. m_Port = NULL;
  33. m_FilterDescriptor = NULL;
  34. m_NotificationInterval = 0;
  35. m_SamplingFrequency = 0;
  36. m_ServiceGroup = NULL;
  37. m_MaxDmaBufferSize = DMA_BUFFER_SIZE;
  38. m_MaxOutputStreams = 0;
  39. m_MaxInputStreams = 0;
  40. m_MaxTotalStreams = 0;
  41. m_MinChannels = 0;
  42. m_MaxChannelsPcm = 0;
  43. m_MinBitsPerSamplePcm = 0;
  44. m_MaxBitsPerSamplePcm = 0;
  45. m_MinSampleRatePcm = 0;
  46. m_MaxSampleRatePcm = 0;
  47. } // CMiniportWaveCyclicMSVAD
  48. //=============================================================================
  49. CMiniportWaveCyclicMSVAD::~CMiniportWaveCyclicMSVAD
  50. (
  51. void
  52. )
  53. /*++
  54. Routine Description:
  55. Destructor for wavecyclic miniport
  56. Arguments:
  57. Return Value:
  58. --*/
  59. {
  60. PAGED_CODE();
  61. DPF_ENTER(("[CMiniportWaveCyclicMSVAD::~CMiniportWaveCyclicMSVAD]"));
  62. if (m_Port)
  63. {
  64. m_Port->Release();
  65. }
  66. if (m_ServiceGroup)
  67. {
  68. m_ServiceGroup->Release();
  69. }
  70. if (m_AdapterCommon)
  71. {
  72. m_AdapterCommon->Release();
  73. }
  74. } // ~CMiniportWaveCyclicMSVAD
  75. //=============================================================================
  76. STDMETHODIMP
  77. CMiniportWaveCyclicMSVAD::GetDescription
  78. (
  79. OUT PPCFILTER_DESCRIPTOR * OutFilterDescriptor
  80. )
  81. /*++
  82. Routine Description:
  83. The GetDescription function gets a pointer to a filter description.
  84. The descriptor is defined in wavtable.h for each MSVAD sample.
  85. Arguments:
  86. OutFilterDescriptor - Pointer to the filter description
  87. Return Value:
  88. NT status code.
  89. --*/
  90. {
  91. PAGED_CODE();
  92. ASSERT(OutFilterDescriptor);
  93. DPF_ENTER(("[CMiniportWaveCyclicMSVAD::GetDescription]"));
  94. *OutFilterDescriptor = m_FilterDescriptor;
  95. return (STATUS_SUCCESS);
  96. } // GetDescription
  97. //=============================================================================
  98. STDMETHODIMP
  99. CMiniportWaveCyclicMSVAD::Init
  100. (
  101. IN PUNKNOWN UnknownAdapter_,
  102. IN PRESOURCELIST ResourceList_,
  103. IN PPORTWAVECYCLIC Port_
  104. )
  105. /*++
  106. Routine Description:
  107. Arguments:
  108. UnknownAdapter_ - pointer to adapter common.
  109. ResourceList_ - resource list. MSVAD does not use resources.
  110. Port_ - pointer to the port
  111. Return Value:
  112. NT status code.
  113. --*/
  114. {
  115. PAGED_CODE();
  116. ASSERT(UnknownAdapter_);
  117. ASSERT(Port_);
  118. DPF_ENTER(("[CMiniportWaveCyclicMSVAD::Init]"));
  119. // AddRef() is required because we are keeping this pointer.
  120. //
  121. m_Port = Port_;
  122. m_Port->AddRef();
  123. // We want the IAdapterCommon interface on the adapter common object,
  124. // which is given to us as a IUnknown. The QueryInterface call gives us
  125. // an AddRefed pointer to the interface we want.
  126. //
  127. NTSTATUS ntStatus =
  128. UnknownAdapter_->QueryInterface
  129. (
  130. IID_IAdapterCommon,
  131. (PVOID *) &m_AdapterCommon
  132. );
  133. if (NT_SUCCESS(ntStatus))
  134. {
  135. KeInitializeMutex(&m_SampleRateSync, 1);
  136. ntStatus = PcNewServiceGroup(&m_ServiceGroup, NULL);
  137. if (NT_SUCCESS(ntStatus))
  138. {
  139. m_AdapterCommon->SetWaveServiceGroup(m_ServiceGroup);
  140. }
  141. }
  142. if (!NT_SUCCESS(ntStatus))
  143. {
  144. // clean up AdapterCommon
  145. //
  146. if (m_AdapterCommon)
  147. {
  148. // clean up the service group
  149. //
  150. if (m_ServiceGroup)
  151. {
  152. m_AdapterCommon->SetWaveServiceGroup(NULL);
  153. m_ServiceGroup->Release();
  154. m_ServiceGroup = NULL;
  155. }
  156. m_AdapterCommon->Release();
  157. m_AdapterCommon = NULL;
  158. }
  159. // release the port
  160. //
  161. m_Port->Release();
  162. m_Port = NULL;
  163. }
  164. return ntStatus;
  165. } // Init
  166. //=============================================================================
  167. NTSTATUS
  168. CMiniportWaveCyclicMSVAD::PropertyHandlerCpuResources
  169. (
  170. IN PPCPROPERTY_REQUEST PropertyRequest
  171. )
  172. /*++
  173. Routine Description:
  174. Processes KSPROPERTY_AUDIO_CPURESOURCES
  175. Arguments:
  176. PropertyRequest - property request structure
  177. Return Value:
  178. NT status code.
  179. --*/
  180. {
  181. PAGED_CODE();
  182. ASSERT(PropertyRequest);
  183. DPF_ENTER(("[CMiniportWaveCyclicMSVAD::PropertyHandlerCpuResources]"));
  184. NTSTATUS ntStatus = STATUS_INVALID_DEVICE_REQUEST;
  185. if (PropertyRequest->Verb & KSPROPERTY_TYPE_GET)
  186. {
  187. ntStatus = ValidatePropertyParams(PropertyRequest, sizeof(LONG), 0);
  188. if (NT_SUCCESS(ntStatus))
  189. {
  190. *(PLONG(PropertyRequest->Value)) = KSAUDIO_CPU_RESOURCES_NOT_HOST_CPU;
  191. PropertyRequest->ValueSize = sizeof(LONG);
  192. ntStatus = STATUS_SUCCESS;
  193. }
  194. }
  195. else if (PropertyRequest->Verb & KSPROPERTY_TYPE_BASICSUPPORT)
  196. {
  197. ntStatus =
  198. PropertyHandler_BasicSupport
  199. (
  200. PropertyRequest,
  201. KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_BASICSUPPORT,
  202. VT_I4
  203. );
  204. }
  205. return ntStatus;
  206. } // PropertyHandlerCpuResources
  207. //=============================================================================
  208. NTSTATUS
  209. CMiniportWaveCyclicMSVAD::PropertyHandlerGeneric
  210. (
  211. IN PPCPROPERTY_REQUEST PropertyRequest
  212. )
  213. /*++
  214. Routine Description:
  215. Handles all properties for this miniport.
  216. Arguments:
  217. PropertyRequest - property request structure
  218. Return Value:
  219. NT status code.
  220. --*/
  221. {
  222. PAGED_CODE();
  223. ASSERT(PropertyRequest);
  224. ASSERT(PropertyRequest->PropertyItem);
  225. NTSTATUS ntStatus = STATUS_INVALID_DEVICE_REQUEST;
  226. switch (PropertyRequest->PropertyItem->Id)
  227. {
  228. case KSPROPERTY_AUDIO_CPU_RESOURCES:
  229. ntStatus = PropertyHandlerCpuResources(PropertyRequest);
  230. break;
  231. default:
  232. DPF(D_TERSE, ("[PropertyHandlerGeneric: Invalid Device Request]"));
  233. ntStatus = STATUS_INVALID_DEVICE_REQUEST;
  234. }
  235. return ntStatus;
  236. } // PropertyHandlerGeneric
  237. //=============================================================================
  238. NTSTATUS
  239. CMiniportWaveCyclicMSVAD::ValidateFormat
  240. (
  241. IN PKSDATAFORMAT pDataFormat
  242. )
  243. /*++
  244. Routine Description:
  245. Validates that the given dataformat is valid.
  246. This version of the driver only supports PCM.
  247. Arguments:
  248. pDataFormat - The dataformat for validation.
  249. Return Value:
  250. NT status code.
  251. --*/
  252. {
  253. PAGED_CODE();
  254. ASSERT(pDataFormat);
  255. DPF_ENTER(("[CMiniportWaveCyclicMSVAD::ValidateFormat]"));
  256. NTSTATUS ntStatus = STATUS_INVALID_PARAMETER;
  257. PWAVEFORMATEX pwfx;
  258. pwfx = GetWaveFormatEx(pDataFormat);
  259. if (pwfx)
  260. {
  261. if (IS_VALID_WAVEFORMATEX_GUID(&pDataFormat->SubFormat))
  262. {
  263. USHORT wfxID = EXTRACT_WAVEFORMATEX_ID(&pDataFormat->SubFormat);
  264. switch (wfxID)
  265. {
  266. case WAVE_FORMAT_PCM:
  267. {
  268. switch (pwfx->wFormatTag)
  269. {
  270. case WAVE_FORMAT_PCM:
  271. {
  272. ntStatus = ValidatePcm(pwfx);
  273. break;
  274. }
  275. }
  276. break;
  277. }
  278. default:
  279. DPF(D_TERSE, ("Invalid format EXTRACT_WAVEFORMATEX_ID!"));
  280. break;
  281. }
  282. }
  283. else
  284. {
  285. DPF(D_TERSE, ("Invalid pDataFormat->SubFormat!") );
  286. }
  287. }
  288. return ntStatus;
  289. } // ValidateFormat
  290. //-----------------------------------------------------------------------------
  291. NTSTATUS
  292. CMiniportWaveCyclicMSVAD::ValidatePcm
  293. (
  294. IN PWAVEFORMATEX pWfx
  295. )
  296. /*++
  297. Routine Description:
  298. Given a waveformatex and format size validates that the format is in device
  299. datarange.
  300. Arguments:
  301. pWfx - wave format structure.
  302. Return Value:
  303. NT status code.
  304. --*/
  305. {
  306. PAGED_CODE();
  307. DPF_ENTER(("CMiniportWaveCyclicMSVAD::ValidatePcm"));
  308. if
  309. (
  310. pWfx &&
  311. (pWfx->cbSize == 0) &&
  312. (pWfx->nChannels >= m_MinChannels) &&
  313. (pWfx->nChannels <= m_MaxChannelsPcm) &&
  314. (pWfx->nSamplesPerSec >= m_MinSampleRatePcm) &&
  315. (pWfx->nSamplesPerSec <= m_MaxSampleRatePcm) &&
  316. (pWfx->wBitsPerSample >= m_MinBitsPerSamplePcm) &&
  317. (pWfx->wBitsPerSample <= m_MaxBitsPerSamplePcm)
  318. )
  319. {
  320. return STATUS_SUCCESS;
  321. }
  322. DPF(D_TERSE, ("Invalid PCM format"));
  323. return STATUS_INVALID_PARAMETER;
  324. } // ValidatePcm
  325. //=============================================================================
  326. // CMiniportWaveCyclicStreamMSVAD
  327. //=============================================================================
  328. CMiniportWaveCyclicStreamMSVAD::CMiniportWaveCyclicStreamMSVAD
  329. (
  330. void
  331. )
  332. {
  333. m_pMiniport = NULL;
  334. m_fCapture = FALSE;
  335. m_fFormat16Bit = FALSE;
  336. m_fFormatStereo = FALSE;
  337. m_ksState = KSSTATE_STOP;
  338. m_ulPin = (ULONG)-1;
  339. m_pDpc = NULL;
  340. m_pTimer = NULL;
  341. m_fDmaActive = FALSE;
  342. m_ulDmaPosition = 0;
  343. m_pvDmaBuffer = NULL;
  344. m_ulDmaBufferSize = 0;
  345. m_ulDmaMovementRate = 0;
  346. m_ullDmaTimeStamp = 0;
  347. }
  348. //=============================================================================
  349. CMiniportWaveCyclicStreamMSVAD::~CMiniportWaveCyclicStreamMSVAD
  350. (
  351. void
  352. )
  353. /*++
  354. Routine Description:
  355. Destructor for wavecyclic stream
  356. Arguments:
  357. void
  358. Return Value:
  359. --*/
  360. {
  361. PAGED_CODE();
  362. DPF_ENTER(("[CMiniportWaveCyclicStreamMS::~CMiniportWaveCyclicStreamMS]"));
  363. if (m_pTimer)
  364. {
  365. KeCancelTimer(m_pTimer);
  366. ExFreePool(m_pTimer);
  367. }
  368. if (m_pDpc)
  369. {
  370. ExFreePool( m_pDpc );
  371. }
  372. // Free the DMA buffer
  373. //
  374. FreeBuffer();
  375. } // ~CMiniportWaveCyclicStreamMSVAD
  376. //=============================================================================
  377. NTSTATUS
  378. CMiniportWaveCyclicStreamMSVAD::Init
  379. (
  380. IN PCMiniportWaveCyclicMSVAD Miniport_,
  381. IN ULONG Pin_,
  382. IN BOOLEAN Capture_,
  383. IN PKSDATAFORMAT DataFormat_
  384. )
  385. /*++
  386. Routine Description:
  387. Initializes the stream object. Allocate a DMA buffer, timer and DPC
  388. Arguments:
  389. Miniport_ - miniport object
  390. Pin_ - pin id
  391. Capture_ - TRUE if this is a capture stream
  392. DataFormat_ - new dataformat
  393. Return Value:
  394. NT status code.
  395. --*/
  396. {
  397. PAGED_CODE();
  398. DPF_ENTER(("[CMiniportWaveCyclicStreamMSVAD::Init]"));
  399. ASSERT(Miniport_);
  400. ASSERT(DataFormat_);
  401. NTSTATUS ntStatus = STATUS_SUCCESS;
  402. PWAVEFORMATEX pWfx;
  403. pWfx = GetWaveFormatEx(DataFormat_);
  404. if (!pWfx)
  405. {
  406. DPF(D_TERSE, ("Invalid DataFormat param in NewStream"));
  407. ntStatus = STATUS_INVALID_PARAMETER;
  408. }
  409. if (NT_SUCCESS(ntStatus))
  410. {
  411. m_pMiniport = Miniport_;
  412. m_ulPin = Pin_;
  413. m_fCapture = Capture_;
  414. m_fFormatStereo = (pWfx->nChannels == 2);
  415. m_fFormat16Bit = (pWfx->wBitsPerSample == 16);
  416. m_ksState = KSSTATE_STOP;
  417. m_ulDmaPosition = 0;
  418. m_fDmaActive = FALSE;
  419. m_pDpc = NULL;
  420. m_pTimer = NULL;
  421. m_pvDmaBuffer = NULL;
  422. // If this is not the capture stream, create the output file.
  423. //
  424. if (!m_fCapture)
  425. {
  426. DPF(D_TERSE, ("SaveData %X", &m_SaveData));
  427. ntStatus = m_SaveData.SetDataFormat(DataFormat_);
  428. if (NT_SUCCESS(ntStatus))
  429. {
  430. ntStatus = m_SaveData.Initialize();
  431. }
  432. }
  433. }
  434. // Allocate DMA buffer for this stream.
  435. //
  436. if (NT_SUCCESS(ntStatus))
  437. {
  438. ntStatus = AllocateBuffer(m_pMiniport->m_MaxDmaBufferSize, NULL);
  439. }
  440. // Set sample frequency. Note that m_SampleRateSync access should
  441. // be syncronized.
  442. //
  443. if (NT_SUCCESS(ntStatus))
  444. {
  445. ntStatus =
  446. KeWaitForSingleObject
  447. (
  448. &m_pMiniport->m_SampleRateSync,
  449. Executive,
  450. KernelMode,
  451. FALSE,
  452. NULL
  453. );
  454. if (NT_SUCCESS(ntStatus))
  455. {
  456. m_pMiniport->m_SamplingFrequency = pWfx->nSamplesPerSec;
  457. KeReleaseMutex(&m_pMiniport->m_SampleRateSync, FALSE);
  458. }
  459. else
  460. {
  461. DPF(D_TERSE, ("[SamplingFrequency Sync failed: %08X]", ntStatus));
  462. }
  463. }
  464. if (NT_SUCCESS(ntStatus))
  465. {
  466. ntStatus = SetFormat(DataFormat_);
  467. }
  468. if (NT_SUCCESS(ntStatus))
  469. {
  470. m_pDpc = (PRKDPC)
  471. ExAllocatePoolWithTag
  472. (
  473. NonPagedPool,
  474. sizeof(KDPC),
  475. MSVAD_POOLTAG
  476. );
  477. if (!m_pDpc)
  478. {
  479. DPF(D_TERSE, ("[Could not allocate memory for DPC]"));
  480. ntStatus = STATUS_INSUFFICIENT_RESOURCES;
  481. }
  482. }
  483. if (NT_SUCCESS(ntStatus))
  484. {
  485. m_pTimer = (PKTIMER)
  486. ExAllocatePoolWithTag
  487. (
  488. NonPagedPool,
  489. sizeof(KTIMER),
  490. MSVAD_POOLTAG
  491. );
  492. if (!m_pTimer)
  493. {
  494. DPF(D_TERSE, ("[Could not allocate memory for Timer]"));
  495. ntStatus = STATUS_INSUFFICIENT_RESOURCES;
  496. }
  497. }
  498. if (NT_SUCCESS(ntStatus))
  499. {
  500. KeInitializeDpc(m_pDpc, TimerNotify, m_pMiniport);
  501. KeInitializeTimerEx(m_pTimer, NotificationTimer);
  502. }
  503. return ntStatus;
  504. } // Init
  505. #pragma code_seg()
  506. //=============================================================================
  507. // CMiniportWaveCyclicStreamMSVAD IMiniportWaveCyclicStream
  508. //=============================================================================
  509. //=============================================================================
  510. STDMETHODIMP
  511. CMiniportWaveCyclicStreamMSVAD::GetPosition
  512. (
  513. OUT PULONG Position
  514. )
  515. /*++
  516. Routine Description:
  517. The GetPosition function gets the current position of the DMA read or write
  518. pointer for the stream. Callers of GetPosition should run at
  519. IRQL <= DISPATCH_LEVEL.
  520. Arguments:
  521. Position - Position of the DMA pointer
  522. Return Value:
  523. NT status code.
  524. --*/
  525. {
  526. if (m_fDmaActive)
  527. {
  528. ULONGLONG CurrentTime = KeQueryInterruptTime();
  529. ULONG TimeElapsedInMS =
  530. ( (ULONG) (CurrentTime - m_ullDmaTimeStamp) ) / 10000;
  531. ULONG ByteDisplacement =
  532. (m_ulDmaMovementRate * TimeElapsedInMS) / 1000;
  533. m_ulDmaPosition =
  534. (m_ulDmaPosition + ByteDisplacement) % m_ulDmaBufferSize;
  535. *Position = m_ulDmaPosition;
  536. m_ullDmaTimeStamp = CurrentTime;
  537. }
  538. else
  539. {
  540. *Position = m_ulDmaPosition;
  541. }
  542. return STATUS_SUCCESS;
  543. } // GetPosition
  544. //=============================================================================
  545. STDMETHODIMP
  546. CMiniportWaveCyclicStreamMSVAD::NormalizePhysicalPosition
  547. (
  548. IN OUT PLONGLONG PhysicalPosition
  549. )
  550. /*++
  551. Routine Description:
  552. Given a physical position based on the actual number of bytes transferred,
  553. NormalizePhysicalPosition converts the position to a time-based value of
  554. 100 nanosecond units. Callers of NormalizePhysicalPosition can run at any IRQL.
  555. Arguments:
  556. PhysicalPosition - On entry this variable contains the value to convert.
  557. On return it contains the converted value
  558. Return Value:
  559. NT status code.
  560. --*/
  561. {
  562. *PhysicalPosition =
  563. ( _100NS_UNITS_PER_SECOND /
  564. ( 1 << ( m_fFormatStereo + m_fFormat16Bit ) ) * *PhysicalPosition ) /
  565. m_pMiniport->m_SamplingFrequency;
  566. return STATUS_SUCCESS;
  567. } // NormalizePhysicalPosition
  568. #pragma code_seg("PAGE")
  569. //=============================================================================
  570. STDMETHODIMP_(NTSTATUS)
  571. CMiniportWaveCyclicStreamMSVAD::SetFormat
  572. (
  573. IN PKSDATAFORMAT Format
  574. )
  575. /*++
  576. Routine Description:
  577. The SetFormat function changes the format associated with a stream.
  578. Callers of SetFormat should run at IRQL PASSIVE_LEVEL
  579. Arguments:
  580. Format - Pointer to a KSDATAFORMAT structure which indicates the new format
  581. of the stream.
  582. Return Value:
  583. NT status code.
  584. --*/
  585. {
  586. PAGED_CODE();
  587. ASSERT(Format);
  588. DPF_ENTER(("[CMiniportWaveCyclicStreamMSVAD::SetFormat]"));
  589. NTSTATUS ntStatus = STATUS_INVALID_DEVICE_REQUEST;
  590. PWAVEFORMATEX pWfx;
  591. if (m_ksState != KSSTATE_RUN)
  592. {
  593. // MSVAD does not validate the format.
  594. //
  595. pWfx = GetWaveFormatEx(Format);
  596. if (pWfx)
  597. {
  598. ntStatus =
  599. KeWaitForSingleObject
  600. (
  601. &m_pMiniport->m_SampleRateSync,
  602. Executive,
  603. KernelMode,
  604. FALSE,
  605. NULL
  606. );
  607. if (NT_SUCCESS(ntStatus))
  608. {
  609. if (!m_fCapture)
  610. {
  611. ntStatus = m_SaveData.SetDataFormat(Format);
  612. }
  613. m_fFormatStereo = (pWfx->nChannels == 2);
  614. m_fFormat16Bit = (pWfx->wBitsPerSample == 16);
  615. m_pMiniport->m_SamplingFrequency =
  616. pWfx->nSamplesPerSec;
  617. m_ulDmaMovementRate = pWfx->nAvgBytesPerSec;
  618. DPF(D_TERSE, ("New Format: %d", pWfx->nSamplesPerSec));
  619. }
  620. KeReleaseMutex(&m_pMiniport->m_SampleRateSync, FALSE);
  621. }
  622. }
  623. return ntStatus;
  624. } // SetFormat
  625. //=============================================================================
  626. STDMETHODIMP_(ULONG)
  627. CMiniportWaveCyclicStreamMSVAD::SetNotificationFreq
  628. (
  629. IN ULONG Interval,
  630. OUT PULONG FramingSize
  631. )
  632. /*++
  633. Routine Description:
  634. The SetNotificationFrequency function sets the frequency at which
  635. notification interrupts are generated. Callers of SetNotificationFrequency
  636. should run at IRQL PASSIVE_LEVEL.
  637. Arguments:
  638. Interval - Value indicating the interval between interrupts,
  639. expressed in milliseconds
  640. FramingSize - Pointer to a ULONG value where the number of bytes equivalent
  641. to Interval milliseconds is returned
  642. Return Value:
  643. NT status code.
  644. --*/
  645. {
  646. PAGED_CODE();
  647. ASSERT(FramingSize);
  648. DPF_ENTER(("[CMiniportWaveCyclicStreamMSVAD::SetNotificationFreq]"));
  649. m_pMiniport->m_NotificationInterval = Interval;
  650. *FramingSize =
  651. ( 1 << ( m_fFormatStereo + m_fFormat16Bit ) ) *
  652. m_pMiniport->m_SamplingFrequency *
  653. Interval / 1000;
  654. return m_pMiniport->m_NotificationInterval;
  655. } // SetNotificationFreq
  656. //=============================================================================
  657. STDMETHODIMP
  658. CMiniportWaveCyclicStreamMSVAD::SetState
  659. (
  660. IN KSSTATE NewState
  661. )
  662. /*++
  663. Routine Description:
  664. The SetState function sets the new state of playback or recording for the
  665. stream. SetState should run at IRQL PASSIVE_LEVEL
  666. Arguments:
  667. NewState - KSSTATE indicating the new state for the stream.
  668. Return Value:
  669. NT status code.
  670. --*/
  671. {
  672. PAGED_CODE();
  673. DPF_ENTER(("[CMiniportWaveCyclicStreamMSVAD::SetState]"));
  674. NTSTATUS ntStatus = STATUS_SUCCESS;
  675. // The acquire state is not distinguishable from the stop state for our
  676. // purposes.
  677. //
  678. if (NewState == KSSTATE_ACQUIRE)
  679. {
  680. NewState = KSSTATE_STOP;
  681. }
  682. if (m_ksState != NewState)
  683. {
  684. switch(NewState)
  685. {
  686. case KSSTATE_PAUSE:
  687. {
  688. DPF(D_TERSE, ("KSSTATE_PAUSE"));
  689. m_fDmaActive = FALSE;
  690. }
  691. break;
  692. case KSSTATE_RUN:
  693. {
  694. DPF(D_TERSE, ("KSSTATE_RUN"));
  695. LARGE_INTEGER delay;
  696. // Set the timer for DPC.
  697. //
  698. m_ullDmaTimeStamp = KeQueryInterruptTime();
  699. m_fDmaActive = TRUE;
  700. delay.HighPart = 0;
  701. delay.LowPart = m_pMiniport->m_NotificationInterval;
  702. KeSetTimerEx
  703. (
  704. m_pTimer,
  705. delay,
  706. m_pMiniport->m_NotificationInterval,
  707. m_pDpc
  708. );
  709. }
  710. break;
  711. case KSSTATE_STOP:
  712. DPF(D_TERSE, ("KSSTATE_STOP"));
  713. m_fDmaActive = FALSE;
  714. m_ulDmaPosition = 0;
  715. KeCancelTimer( m_pTimer );
  716. // Wait until all work items are completed.
  717. //
  718. if (!m_fCapture)
  719. {
  720. m_SaveData.WaitAllWorkItems();
  721. }
  722. break;
  723. }
  724. m_ksState = NewState;
  725. }
  726. return ntStatus;
  727. } // SetState
  728. #pragma code_seg()
  729. //=============================================================================
  730. STDMETHODIMP_(void)
  731. CMiniportWaveCyclicStreamMSVAD::Silence
  732. (
  733. IN PVOID Buffer,
  734. IN ULONG ByteCount
  735. )
  736. /*++
  737. Routine Description:
  738. The Silence function is used to copy silence samplings to a certain location.
  739. Callers of Silence can run at any IRQL
  740. Arguments:
  741. Buffer - Pointer to the buffer where the silence samplings should
  742. be deposited.
  743. ByteCount - Size of buffer indicating number of bytes to be deposited.
  744. Return Value:
  745. NT status code.
  746. --*/
  747. {
  748. RtlFillMemory(Buffer, ByteCount, m_fFormat16Bit ? 0 : 0x80);
  749. } // Silence
  750. //=============================================================================
  751. void
  752. TimerNotify
  753. (
  754. IN PKDPC Dpc,
  755. IN PVOID DeferredContext,
  756. IN PVOID SA1,
  757. IN PVOID SA2
  758. )
  759. /*++
  760. Routine Description:
  761. Dpc routine. This simulates an interrupt service routine. The Dpc will be
  762. called whenever CMiniportWaveCyclicStreamMSVAD::m_pTimer triggers.
  763. Arguments:
  764. Dpc - the Dpc object
  765. DeferredContext - Pointer to a caller-supplied context to be passed to
  766. the DeferredRoutine when it is called
  767. SA1 - System argument 1
  768. SA2 - System argument 2
  769. Return Value:
  770. NT status code.
  771. --*/
  772. {
  773. PCMiniportWaveCyclicMSVAD pMiniport =
  774. (PCMiniportWaveCyclicMSVAD) DeferredContext;
  775. if (pMiniport && pMiniport->m_Port)
  776. {
  777. pMiniport->m_Port->Notify(pMiniport->m_ServiceGroup);
  778. }
  779. } // TimerNotify