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.

1760 lines
52 KiB

  1. //==========================================================================;
  2. //
  3. // THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
  4. // KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
  5. // IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
  6. // PURPOSE.
  7. //
  8. // Copyright (c) 1992 - 1998 Microsoft Corporation. All Rights Reserved.
  9. //
  10. //==========================================================================;
  11. #include <wdm.h>
  12. #include <strmini.h>
  13. #include <ksmedia.h>
  14. #include "kskludge.h"
  15. #include "codmain.h"
  16. #include "codstrm.h"
  17. #include "codprop.h"
  18. #include "coddebug.h"
  19. //
  20. // Fake VBI Info header. Infinite Pin Tee Filter can't pass real ones
  21. // one from capture so we rely on this. MSTee can so this gets
  22. // overwritten.
  23. //
  24. KS_VBIINFOHEADER FakeVBIInfoHeader = {
  25. 10, /* StartLine; IGNORED */
  26. 21, /* EndLine; IGNORED */
  27. 28636360, /* SamplingFrequency; Hz. */
  28. 780, /* MinLineStartTime; IGNORED */
  29. 780, /* MaxLineStartTime; IGNORED */
  30. 780, /* ActualLineStartTime; microSec * 100 from HSync LE */
  31. 0, /* ActualLineEndTime; IGNORED */
  32. 0, /* VideoStandard; IGNORED */
  33. 1600, /* SamplesPerLine; */
  34. 1600, /* StrideInBytes; May be > SamplesPerLine */
  35. 1600*12 /* BufferSize; Bytes */
  36. };
  37. /*
  38. ** DriverEntry()
  39. **
  40. ** This routine is called when the driver is first loaded by PnP.
  41. ** It in turn, calls upon the stream class to perform registration services.
  42. **
  43. ** Arguments:
  44. **
  45. ** DriverObject -
  46. ** Driver object for this driver
  47. **
  48. ** RegistryPath -
  49. ** Registry path string for this driver's key
  50. **
  51. ** Returns:
  52. **
  53. ** Results of StreamClassRegisterAdapter()
  54. **
  55. ** Side Effects: none
  56. */
  57. ULONG
  58. DriverEntry( IN PDRIVER_OBJECT DriverObject,
  59. IN PUNICODE_STRING RegistryPath )
  60. {
  61. ULONG status = 0;
  62. HW_INITIALIZATION_DATA HwInitData;
  63. CDebugPrint(DebugLevelTrace,(CODECNAME ":--->DriverEntry(DriverObject=%x,RegistryPath=%x)\n",
  64. DriverObject, RegistryPath));
  65. RtlZeroMemory(&HwInitData, sizeof(HwInitData));
  66. HwInitData.HwInitializationDataSize = sizeof(HwInitData);
  67. /*CDEBUG_BREAK();*/
  68. //
  69. // Set the codec entry points for the driver
  70. //
  71. HwInitData.HwInterrupt = NULL; // HwInterrupt is only for HW devices
  72. HwInitData.HwReceivePacket = CodecReceivePacket;
  73. HwInitData.HwCancelPacket = CodecCancelPacket;
  74. HwInitData.HwRequestTimeoutHandler = CodecTimeoutPacket;
  75. HwInitData.DeviceExtensionSize = sizeof(HW_DEVICE_EXTENSION);
  76. HwInitData.PerRequestExtensionSize = sizeof(SRB_EXTENSION);
  77. HwInitData.FilterInstanceExtensionSize = 0;
  78. HwInitData.PerStreamExtensionSize = sizeof(STREAMEX);
  79. HwInitData.BusMasterDMA = FALSE;
  80. HwInitData.Dma24BitAddresses = FALSE;
  81. HwInitData.BufferAlignment = 3;
  82. HwInitData.TurnOffSynchronization = TRUE;
  83. HwInitData.DmaBufferSize = 0;
  84. CDebugPrint(DebugLevelVerbose,(CODECNAME ": StreamClassRegisterAdapter\n"));
  85. status = StreamClassRegisterAdapter(DriverObject, RegistryPath, &HwInitData);
  86. CDebugPrint(DebugLevelTrace,(CODECNAME ":<---DriverEntry(DriverObject=%x,RegistryPath=%x)=%d\n",
  87. DriverObject, RegistryPath, status));
  88. return status;
  89. }
  90. //==========================================================================;
  91. // Codec Request Handling Routines
  92. //==========================================================================;
  93. /*
  94. ** CodecInitialize()
  95. **
  96. ** This routine is called when an SRB_INITIALIZE_DEVICE request is received
  97. **
  98. ** Arguments:
  99. **
  100. ** pSrb - pointer to stream request block for the Initialize command
  101. **
  102. ** Returns:
  103. **
  104. ** Side Effects: none
  105. */
  106. BOOLEAN
  107. CodecInitialize ( IN OUT PHW_STREAM_REQUEST_BLOCK pSrb )
  108. {
  109. BOOLEAN bStatus = FALSE;
  110. PPORT_CONFIGURATION_INFORMATION ConfigInfo = pSrb->CommandData.ConfigInfo;
  111. PHW_DEVICE_EXTENSION pHwDevExt =
  112. (PHW_DEVICE_EXTENSION)ConfigInfo->HwDeviceExtension;
  113. CDebugPrint(DebugLevelTrace,(CODECNAME ":--->CodecInitialize(pSrb=%x)\n",pSrb));
  114. if (ConfigInfo->NumberOfAccessRanges == 0)
  115. {
  116. CDebugPrint(DebugLevelVerbose,(CODECNAME ": CodecInitialize\n"));
  117. ConfigInfo->StreamDescriptorSize = sizeof (HW_STREAM_HEADER) +
  118. DRIVER_STREAM_COUNT * sizeof (HW_STREAM_INFORMATION);
  119. // These are the driver defaults for scanline filtering.
  120. // Modify these WHEN you change the codec type to be more correct.
  121. SETBIT( pHwDevExt->ScanlinesRequested.DwordBitArray, 21 );
  122. // These are the driver defaults for subtream filtering.
  123. // Modify these WHEN you change the codec type
  124. pHwDevExt->SubstreamsRequested.SubstreamMask = KS_CC_SUBSTREAM_ODD;
  125. pHwDevExt->Streams = Streams;
  126. pHwDevExt->fTunerChange = FALSE;
  127. //
  128. // Allocate the results array based on the number of scanlines
  129. //
  130. pHwDevExt->DSPResultStartLine = pHwDevExt->DSPResultEndLine = 0;
  131. pHwDevExt->DSPResult = ( PDSPRESULT )
  132. ExAllocatePool( NonPagedPool,
  133. sizeof( DSPRESULT ) *
  134. (FakeVBIInfoHeader.EndLine - FakeVBIInfoHeader.StartLine + 1) );
  135. if( !pHwDevExt->DSPResult )
  136. {
  137. CDebugPrint( DebugLevelError,
  138. (CODECNAME ": DSP Result array allocation FAILED\n" ));
  139. //pSrb->Status = STATUS_INVALID_PARAMETER;
  140. }
  141. else {
  142. pHwDevExt->DSPResultStartLine = FakeVBIInfoHeader.StartLine;
  143. pHwDevExt->DSPResultEndLine = FakeVBIInfoHeader.EndLine;
  144. }
  145. // Zero out the substream state information (no substreams discovered yet)
  146. RtlZeroMemory( pHwDevExt->SubStreamState, sizeof(pHwDevExt->SubStreamState) );
  147. #ifdef CCINPUTPIN
  148. // Init LastPictureNumber's FastMutex
  149. ExInitializeFastMutex(&pHwDevExt->LastPictureMutex);
  150. #endif // CCINPUTPIN
  151. pSrb->Status = STATUS_SUCCESS;
  152. bStatus = TRUE;
  153. }
  154. else
  155. {
  156. CDebugPrint(DebugLevelError,(CODECNAME ": illegal config info\n"));
  157. pSrb->Status = STATUS_NO_SUCH_DEVICE;
  158. }
  159. CDebugPrint(DebugLevelTrace,
  160. (CODECNAME ":<---CodecInitialize(pSrb=%x)=%d\n", pSrb, bStatus));
  161. return (bStatus);
  162. }
  163. /*
  164. ** CodecUnInitialize()
  165. **
  166. ** This routine is called when an SRB_UNINITIALIZE_DEVICE request is received
  167. **
  168. ** Arguments:
  169. **
  170. ** pSrb - pointer to stream request block for the UnInitialize command
  171. **
  172. ** Returns:
  173. **
  174. ** Side Effects: none
  175. */
  176. BOOLEAN
  177. CodecUnInitialize (
  178. PHW_STREAM_REQUEST_BLOCK pSrb
  179. )
  180. {
  181. PHW_DEVICE_EXTENSION pHwDevExt = ((PHW_DEVICE_EXTENSION)pSrb->HwDeviceExtension);
  182. CDebugPrint(DebugLevelTrace,(CODECNAME ":--->CodecUnInitialize(pSrb=%x)\n",pSrb));
  183. pSrb->Status = STATUS_SUCCESS;
  184. CDebugPrint(DebugLevelTrace,(CODECNAME ":<---CodecUnInitialize(pSrb=%x)\n",pSrb));
  185. //
  186. // Free up the results buffer
  187. //
  188. if (pHwDevExt->DSPResult) {
  189. ExFreePool( pHwDevExt->DSPResult );
  190. pHwDevExt->DSPResult = NULL;
  191. pHwDevExt->DSPResultStartLine = pHwDevExt->DSPResultEndLine = 0;
  192. }
  193. return TRUE;
  194. }
  195. /*
  196. ** CodecOpenStream()
  197. **
  198. ** This routine is called when an OpenStream SRB request is received.
  199. ** A stream is identified by a stream number, which indexes an array
  200. ** of KSDATARANGE structures. The particular KSDATAFORMAT format to
  201. ** be used is also passed in, which should be verified for validity.
  202. **
  203. ** Arguments:
  204. **
  205. ** pSrb - pointer to stream request block for the Open command
  206. **
  207. ** Returns:
  208. **
  209. ** Side Effects: none
  210. */
  211. VOID
  212. CodecOpenStream( PHW_STREAM_REQUEST_BLOCK pSrb )
  213. {
  214. //
  215. // the stream extension structure is allocated by the stream class driver
  216. //
  217. PSTREAMEX pStrmEx = pSrb->StreamObject->HwStreamExtension;
  218. PHW_DEVICE_EXTENSION pHwDevExt = pSrb->HwDeviceExtension;
  219. int StreamNumber = pSrb->StreamObject->StreamNumber;
  220. PKSDATAFORMAT pKSVBIDataFormat =
  221. (PKSDATAFORMAT)pSrb->CommandData.OpenFormat;
  222. CDebugPrint(DebugLevelTrace,(CODECNAME ":--->CodecOpenStream(pSrb=%x)\n", pSrb));
  223. CDebugPrint(DebugLevelVerbose,(CODECNAME ": CodecOpenStream : StreamNumber=%d\n", StreamNumber));
  224. RtlZeroMemory(pStrmEx, sizeof (STREAMEX));
  225. //
  226. // check that the stream index requested isn't too high
  227. // or that the maximum number of instances hasn't been exceeded
  228. //
  229. if ( 0 <= StreamNumber && StreamNumber < DRIVER_STREAM_COUNT )
  230. {
  231. unsigned StreamInstance;
  232. unsigned maxInstances =
  233. Streams[StreamNumber].hwStreamInfo.NumberOfPossibleInstances;
  234. // Search for next open slot
  235. for (StreamInstance=0; StreamInstance < maxInstances; ++StreamInstance)
  236. {
  237. if (pHwDevExt->pStrmEx[StreamNumber][StreamInstance] == NULL)
  238. break;
  239. }
  240. if (StreamInstance < maxInstances)
  241. {
  242. if (CodecVerifyFormat(pKSVBIDataFormat, StreamNumber, &pStrmEx->MatchedFormat))
  243. {
  244. CASSERT (pHwDevExt->pStrmEx[StreamNumber][StreamInstance] == NULL);
  245. InitializeListHead( &pStrmEx->StreamControlQueue );
  246. InitializeListHead( &pStrmEx->StreamDataQueue );
  247. KeInitializeSpinLock( &pStrmEx->StreamControlSpinLock );
  248. KeInitializeSpinLock( &pStrmEx->StreamDataSpinLock );
  249. // Maintain an array of all the StreamEx structures in the HwDevExt
  250. // so that we can reference IRPs from any stream
  251. pHwDevExt->pStrmEx[StreamNumber][StreamInstance] = pStrmEx;
  252. // Save the Stream Format in the Stream Extension as well.
  253. pStrmEx->OpenedFormat = *pKSVBIDataFormat;
  254. // Set up pointers to the handlers for the stream data and control handlers
  255. pSrb->StreamObject->ReceiveDataPacket =
  256. (PVOID) Streams[StreamNumber].hwStreamObject.ReceiveDataPacket;
  257. pSrb->StreamObject->ReceiveControlPacket =
  258. (PVOID) Streams[StreamNumber].hwStreamObject.ReceiveControlPacket;
  259. //
  260. // The DMA flag must be set when the device will be performing DMA directly
  261. // to the data buffer addresses passed in to the ReceiceDataPacket routines.
  262. //
  263. pSrb->StreamObject->Dma = Streams[StreamNumber].hwStreamObject.Dma;
  264. //
  265. // The PIO flag must be set when the mini driver will be accessing the data
  266. // buffers passed in using logical addressing
  267. //
  268. pSrb->StreamObject->Pio = Streams[StreamNumber].hwStreamObject.Pio;
  269. pSrb->StreamObject->Allocator = Streams[StreamNumber].hwStreamObject.Allocator;
  270. //
  271. // How many extra bytes will be passed up from the driver for each frame?
  272. //
  273. pSrb->StreamObject->StreamHeaderMediaSpecific =
  274. Streams[StreamNumber].hwStreamObject.StreamHeaderMediaSpecific;
  275. pSrb->StreamObject->StreamHeaderWorkspace =
  276. Streams[StreamNumber].hwStreamObject.StreamHeaderWorkspace;
  277. //
  278. // Indicate the clock support available on this stream
  279. //
  280. pSrb->StreamObject->HwClockObject =
  281. Streams[StreamNumber].hwStreamObject.HwClockObject;
  282. //
  283. // Increment the instance count on this stream
  284. //
  285. pStrmEx->StreamInstance = StreamInstance;
  286. pHwDevExt->ActualInstances[StreamNumber]++;
  287. // Retain a private copy of the HwDevExt and StreamObject in the stream extension
  288. // so we can use a timer
  289. pStrmEx->pHwDevExt = pHwDevExt; // For timer use
  290. pStrmEx->pStreamObject = pSrb->StreamObject; // For timer use
  291. CDebugPrint( DebugLevelVerbose, ( CODECNAME ": Stream Instance %d\n",
  292. pStrmEx->StreamInstance ));
  293. // Copy the default filtering settings
  294. pStrmEx->ScanlinesRequested = pHwDevExt->ScanlinesRequested;
  295. pStrmEx->SubstreamsRequested = pHwDevExt->SubstreamsRequested;
  296. //
  297. // Load up default VBI info header
  298. RtlCopyMemory( &pStrmEx->CurrentVBIInfoHeader, &FakeVBIInfoHeader,
  299. sizeof( KS_VBIINFOHEADER ) );
  300. #ifdef CCINPUTPIN
  301. // Init VBISrbOnHold's spin lock
  302. KeInitializeSpinLock(&pStrmEx->VBIOnHoldSpinLock);
  303. #endif // CCINPUTPIN
  304. // Init DSP state
  305. CCStateNew(&pStrmEx->State);
  306. }
  307. else
  308. {
  309. CDebugPrint(DebugLevelError,
  310. (CODECNAME ": CodecOpenStream : Invalid Stream Format=%x\n",
  311. pKSVBIDataFormat ));
  312. pSrb->Status = STATUS_INVALID_PARAMETER;
  313. }
  314. }
  315. else
  316. {
  317. CDebugPrint(DebugLevelError,
  318. (CODECNAME ": CodecOpenStream : Stream %d Too Many Instances=%d\n",
  319. StreamNumber, pHwDevExt->ActualInstances[StreamNumber] ));
  320. pSrb->Status = STATUS_INVALID_PARAMETER;
  321. }
  322. }
  323. else
  324. {
  325. CDebugPrint(DebugLevelError,
  326. (CODECNAME ": CodecOpenStream : Invalid StreamNumber=%d\n",
  327. StreamNumber ));
  328. pSrb->Status = STATUS_INVALID_PARAMETER;
  329. }
  330. CDebugPrint(DebugLevelTrace,(CODECNAME ":<---CodecOpenStream(pSrb=%x)\n", pSrb));
  331. }
  332. /*
  333. ** CodecCloseStream()
  334. **
  335. ** Close the requested data stream
  336. **
  337. ** Arguments:
  338. **
  339. ** pSrb the request block requesting to close the stream
  340. **
  341. ** Returns:
  342. **
  343. ** Side Effects: none
  344. */
  345. VOID
  346. CodecCloseStream (
  347. PHW_STREAM_REQUEST_BLOCK pSrb
  348. )
  349. {
  350. PSTREAMEX pStrmEx = (PSTREAMEX)pSrb->StreamObject->HwStreamExtension;
  351. PHW_DEVICE_EXTENSION pHwDevExt = ((PHW_DEVICE_EXTENSION)pSrb->HwDeviceExtension);
  352. PHW_STREAM_REQUEST_BLOCK pCurrentSrb;
  353. PKSDATAFORMAT pKSDataFormat = pSrb->CommandData.OpenFormat;
  354. ULONG StreamNumber = pSrb->StreamObject->StreamNumber;
  355. ULONG StreamInstance = pStrmEx->StreamInstance;
  356. #ifdef CCINPUTPIN
  357. KIRQL Irql;
  358. #endif // CCINPUTPIN
  359. CDebugPrint(DebugLevelTrace,(CODECNAME ":--->CodecCloseStream(pSrb=%x)\n", pSrb));
  360. // CDEBUG_BREAK(); // Uncomment this code to break here.
  361. CDebugPrint( DebugLevelVerbose, ( CODECNAME "Strm %d StrmInst %d ActualInst %d\n",
  362. StreamNumber, StreamInstance, pHwDevExt->ActualInstances[StreamNumber] ));
  363. //
  364. // Flush the stream data queue
  365. //
  366. #ifdef CCINPUTPIN
  367. // Is there an SRB 'on hold'??
  368. KeAcquireSpinLock(&pStrmEx->VBIOnHoldSpinLock, &Irql);
  369. if (pStrmEx->pVBISrbOnHold)
  370. {
  371. PHW_STREAM_REQUEST_BLOCK pHoldSrb;
  372. pHoldSrb = pStrmEx->pVBISrbOnHold;
  373. pStrmEx->pVBISrbOnHold = NULL;
  374. KeReleaseSpinLock(&pStrmEx->VBIOnHoldSpinLock, Irql);
  375. pHoldSrb->Status = STATUS_CANCELLED;
  376. CDebugPrint(DebugLevelVerbose,
  377. (CODECNAME ":StreamClassStreamNotification(pHoldSrb->Status=0x%x)\n",
  378. pHoldSrb->Status));
  379. StreamClassStreamNotification(
  380. StreamRequestComplete, pHoldSrb->StreamObject, pHoldSrb);
  381. pSrb = NULL;
  382. }
  383. else
  384. KeReleaseSpinLock(&pStrmEx->VBIOnHoldSpinLock, Irql);
  385. #endif // CCINPUTPIN
  386. while( QueueRemove( &pCurrentSrb, &pStrmEx->StreamDataSpinLock,
  387. &pStrmEx->StreamDataQueue ))
  388. {
  389. CDebugPrint( DebugLevelVerbose,
  390. ( CODECNAME ": Removing control SRB %x\n", pCurrentSrb ));
  391. pCurrentSrb->Status = STATUS_CANCELLED;
  392. StreamClassStreamNotification( StreamRequestComplete,
  393. pCurrentSrb->StreamObject, pCurrentSrb );
  394. }
  395. //
  396. // Flush the stream control queue
  397. //
  398. while( QueueRemove( &pCurrentSrb, &pStrmEx->StreamControlSpinLock,
  399. &pStrmEx->StreamControlQueue ))
  400. {
  401. CDebugPrint( DebugLevelVerbose,
  402. ( CODECNAME ": Removing control SRB %x\n", pCurrentSrb ));
  403. pCurrentSrb->Status = STATUS_CANCELLED;
  404. StreamClassStreamNotification( StreamRequestComplete,
  405. pCurrentSrb->StreamObject, pCurrentSrb );
  406. }
  407. // Destroy DSP state
  408. CCStateDestroy(&pStrmEx->State);
  409. pHwDevExt->ActualInstances[StreamNumber]--;
  410. CASSERT (pHwDevExt->pStrmEx [StreamNumber][StreamInstance] != 0);
  411. pHwDevExt->pStrmEx [StreamNumber][StreamInstance] = 0;
  412. //
  413. // the minidriver may wish to free any resources that were allocate at
  414. // open stream time etc.
  415. //
  416. pStrmEx->hMasterClock = NULL;
  417. CDebugPrint(DebugLevelTrace,(CODECNAME ":<---CodecCloseStream(pSrb=%x)\n", pSrb));
  418. }
  419. /*
  420. ** CodecStreamInfo()
  421. **
  422. ** Returns the information of all streams that are supported by the
  423. ** mini-driver
  424. **
  425. ** Arguments:
  426. **
  427. ** pSrb - Pointer to the STREAM_REQUEST_BLOCK
  428. ** pSrb->HwDeviceExtension - will be the hardware device extension for
  429. ** as initialised in HwInitialise
  430. **
  431. ** Returns:
  432. **
  433. ** Side Effects: none
  434. */
  435. VOID
  436. CodecStreamInfo (
  437. PHW_STREAM_REQUEST_BLOCK pSrb
  438. )
  439. {
  440. int j;
  441. PHW_DEVICE_EXTENSION pHwDevExt =
  442. ((PHW_DEVICE_EXTENSION)pSrb->HwDeviceExtension);
  443. //
  444. // pick up the pointer to header which preceeds the stream info structs
  445. //
  446. PHW_STREAM_HEADER pstrhdr =
  447. (PHW_STREAM_HEADER)&(pSrb->CommandData.StreamBuffer->StreamHeader);
  448. //
  449. // pick up the pointer to the array of stream information data structures
  450. //
  451. PHW_STREAM_INFORMATION pstrinfo =
  452. (PHW_STREAM_INFORMATION)&(pSrb->CommandData.StreamBuffer->StreamInfo);
  453. CDebugPrint(DebugLevelTrace,(CODECNAME ":--->CodecStreamInfo(pSrb=%x)\n", pSrb));
  454. //
  455. // verify that the buffer is large enough to hold our return data
  456. //
  457. CASSERT (pSrb->NumberOfBytesToTransfer >=
  458. sizeof (HW_STREAM_HEADER) +
  459. sizeof (HW_STREAM_INFORMATION) * DRIVER_STREAM_COUNT);
  460. //
  461. // Set the header
  462. //
  463. #define GLOBAL_PROPERTIES
  464. #ifdef GLOBAL_PROPERTIES
  465. StreamHeader.NumDevPropArrayEntries = NUMBER_OF_CODEC_PROPERTY_SETS;
  466. StreamHeader.DevicePropertiesArray = (PKSPROPERTY_SET) CodecPropertyTable;
  467. #else // !GLOBAL_PROPERTIES
  468. StreamHeader.NumDevPropArrayEntries = 0;
  469. StreamHeader.DevicePropertiesArray = (PKSPROPERTY_SET)NULL;
  470. #endif // GLOBAL_PROPERTIES
  471. *pstrhdr = StreamHeader;
  472. //
  473. // stuff the contents of each HW_STREAM_INFORMATION struct
  474. //
  475. for (j = 0; j < DRIVER_STREAM_COUNT; j++) {
  476. *pstrinfo++ = Streams[j].hwStreamInfo;
  477. }
  478. CDebugPrint(DebugLevelTrace,(CODECNAME ":<---CodecStreamInfo(pSrb=%x)\n", pSrb));
  479. }
  480. /*
  481. ** CodecReceivePacket()
  482. **
  483. ** Main entry point for receiving codec based request SRBs. This routine
  484. ** will always be called at High Priority.
  485. **
  486. ** Note: This is an asyncronous entry point. The request does not complete
  487. ** on return from this function, the request only completes when a
  488. ** StreamClassDeviceNotification on this request block, of type
  489. ** DeviceRequestComplete, is issued.
  490. **
  491. ** Arguments:
  492. **
  493. ** pSrb - Pointer to the STREAM_REQUEST_BLOCK
  494. ** pSrb->HwDeviceExtension - will be the hardware device extension for
  495. ** as initialised in HwInitialise
  496. **
  497. ** Returns:
  498. **
  499. ** Side Effects: none
  500. */
  501. VOID
  502. STREAMAPI
  503. CodecReceivePacket(
  504. IN PHW_STREAM_REQUEST_BLOCK pSrb
  505. )
  506. {
  507. PHW_DEVICE_EXTENSION pHwDevExt = pSrb->HwDeviceExtension;
  508. CDebugPrint(DebugLevelTrace,(CODECNAME ":--->CodecReceivePacket(pSrb=%x)\n", pSrb));
  509. //
  510. // Assume success
  511. //
  512. pSrb->Status = STATUS_SUCCESS;
  513. if( !pHwDevExt->bAdapterQueueInitialized )
  514. {
  515. InitializeListHead( &pHwDevExt->AdapterSRBQueue );
  516. KeInitializeSpinLock( &pHwDevExt->AdapterSRBSpinLock );
  517. pHwDevExt->bAdapterQueueInitialized = TRUE;
  518. }
  519. //
  520. // determine the type of packet.
  521. //
  522. if( QueueAddIfNotEmpty( pSrb, &pHwDevExt->AdapterSRBSpinLock,
  523. &pHwDevExt->AdapterSRBQueue ))
  524. return;
  525. do
  526. {
  527. CDebugPrint(DebugLevelVerbose,
  528. (CODECNAME ": CodecReceivePacket: pSrb->Command=0x%x\n",
  529. pSrb->Command));
  530. switch (pSrb->Command)
  531. {
  532. case SRB_INITIALIZE_DEVICE:
  533. // open the device
  534. CodecInitialize(pSrb);
  535. break;
  536. case SRB_UNINITIALIZE_DEVICE:
  537. // close the device.
  538. CodecUnInitialize(pSrb);
  539. break;
  540. case SRB_OPEN_STREAM:
  541. // open a stream
  542. CodecOpenStream(pSrb);
  543. break;
  544. case SRB_CLOSE_STREAM:
  545. // close a stream
  546. CodecCloseStream(pSrb);
  547. break;
  548. case SRB_GET_STREAM_INFO:
  549. //
  550. // return a block describing all the streams
  551. //
  552. CodecStreamInfo(pSrb);
  553. break;
  554. case SRB_GET_DATA_INTERSECTION:
  555. //
  556. // Return a format, given a range
  557. //
  558. switch( pSrb->CommandData.IntersectInfo->StreamNumber )
  559. {
  560. case STREAM_VBI:
  561. CodecVBIFormatFromRange( pSrb );
  562. break;
  563. #ifdef CCINPUTPIN
  564. // Both streams can use CodecCCFormatFromRange() because they
  565. // both use KSDATAFORMAT structures.
  566. case STREAM_CCINPUT:
  567. #endif // CCINPUTPIN
  568. case STREAM_CC:
  569. CodecCCFormatFromRange( pSrb );
  570. break;
  571. default: // Unknown stream number?
  572. CDebugPrint( DebugLevelError, ( CODECNAME ": Unknown Stream Number\n" ));
  573. CDEBUG_BREAK();
  574. pSrb->Status = STATUS_NOT_IMPLEMENTED;
  575. break;
  576. }
  577. break;
  578. // We should never get the following since this is a single instance
  579. // device
  580. case SRB_OPEN_DEVICE_INSTANCE:
  581. case SRB_CLOSE_DEVICE_INSTANCE:
  582. CDebugPrint(DebugLevelError,
  583. (CODECNAME ": CodecReceivePacket : SRB_%s_DEVICE_INSTANCE not supported\n",
  584. (pSrb->Command == SRB_OPEN_DEVICE_INSTANCE)? "OPEN":"CLOSE" ));
  585. CDEBUG_BREAK();
  586. // Fall through to NOT IMPLEMENTED
  587. case SRB_UNKNOWN_DEVICE_COMMAND: // But this one we don't care about
  588. case SRB_INITIALIZATION_COMPLETE: // This one we don't care about
  589. case SRB_CHANGE_POWER_STATE: // This one we don't care about
  590. pSrb->Status = STATUS_NOT_IMPLEMENTED;
  591. break;
  592. case SRB_GET_DEVICE_PROPERTY:
  593. //
  594. // Get codec wide properties
  595. //
  596. CodecGetProperty (pSrb);
  597. break;
  598. case SRB_SET_DEVICE_PROPERTY:
  599. //
  600. // Set codec wide properties
  601. //
  602. CodecSetProperty (pSrb);
  603. break;
  604. case SRB_PAGING_OUT_DRIVER:
  605. case SRB_SURPRISE_REMOVAL:
  606. CDebugPrint(DebugLevelVerbose,
  607. (CODECNAME ": CodecReceivePacket: SRB_%s\n",
  608. (pSrb->Command == SRB_SURPRISE_REMOVAL)?
  609. "SURPRISE_REMOVAL" : "PAGING_OUT_DRIVER"));
  610. #if 0
  611. {
  612. PSTREAMEX pStrmEx;
  613. unsigned StreamNumber, StreamInstance;
  614. unsigned maxInstances =
  615. Streams[StreamNumber].hwStreamInfo.NumberOfPossibleInstances;
  616. // Do we have any pins connected and paused/running?
  617. // Search any used slots...
  618. for (StreamNumber = 0; StreamNumber < DRIVER_STREAM_COUNT; ++StreamNumber) {
  619. for (StreamInstance=0; StreamInstance < maxInstances; ++StreamInstance)
  620. {
  621. pStrmEx = pHwDevExt->pStrmEx[StreamNumber][StreamInstance];
  622. if (pStrmEx != NULL) {
  623. switch (pStrmEx->KSState) {
  624. case KSSTATE_RUN:
  625. case KSSTATE_PAUSE:
  626. CDebugPrint(DebugLevelError,
  627. (CODECNAME ": CodecReceivePacket : PAGING_OUT_DRIVER during RUN or PAUSE; failing request\n"));
  628. CDEBUG_BREAK();
  629. pSrb->Status = STATUS_UNSUCCESSFUL;
  630. goto break3;
  631. default:
  632. // Shouldn't have to do anything here except return SUCCESS
  633. break;
  634. }
  635. }
  636. }
  637. }
  638. break3:
  639. }
  640. #endif //0
  641. break;
  642. case SRB_UNKNOWN_STREAM_COMMAND:
  643. default:
  644. CDebugPrint(DebugLevelError,
  645. (CODECNAME ": CodecReceivePacket : UNKNOWN srb.Command = 0x%x\n",
  646. pSrb->Command));
  647. CDEBUG_BREAK();
  648. //
  649. // this is a request that we do not understand. Indicate invalid
  650. // command and complete the request
  651. //
  652. pSrb->Status = STATUS_NOT_IMPLEMENTED;
  653. }
  654. //
  655. // NOTE:
  656. //
  657. // all of the commands that we do, or do not understand can all be completed
  658. // syncronously at this point, so we can use a common callback routine here.
  659. // If any of the above commands require asyncronous processing, this will
  660. // have to change
  661. //
  662. CDebugPrint(DebugLevelVerbose,
  663. (CODECNAME ": CodecReceivePacket : DeviceRequestComplete(pSrb->Status=0x%x)\n",
  664. pSrb->Status));
  665. StreamClassDeviceNotification( DeviceRequestComplete,
  666. pSrb->HwDeviceExtension, pSrb );
  667. }while( QueueRemove( &pSrb, &pHwDevExt->AdapterSRBSpinLock,
  668. &pHwDevExt->AdapterSRBQueue ));
  669. CDebugPrint(DebugLevelTrace,(CODECNAME ":<---CodecReceivePacket(pSrb=%x)\n", pSrb));
  670. }
  671. /*
  672. ** CodecCancelPacket ()
  673. **
  674. ** Request to cancel a packet that is currently in process in the minidriver
  675. **
  676. ** Arguments:
  677. **
  678. ** pSrb - pointer to request packet to cancel
  679. **
  680. ** Returns:
  681. **
  682. ** Side Effects: none
  683. */
  684. VOID
  685. STREAMAPI
  686. CodecCancelPacket(
  687. PHW_STREAM_REQUEST_BLOCK pSrb
  688. )
  689. {
  690. PSTREAMEX pStrmEx = (PSTREAMEX)pSrb->StreamObject->HwStreamExtension;
  691. PHW_DEVICE_EXTENSION pHwDevExt = ((PHW_DEVICE_EXTENSION)pSrb->HwDeviceExtension);
  692. CDebugPrint(DebugLevelTrace,(CODECNAME ":--->CodecCancelPacket(pSrb=%x)\n", pSrb));
  693. CASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
  694. //
  695. // Check whether the SRB to cancel is in use by this stream
  696. //
  697. #ifdef CCINPUTPIN
  698. // Is SRB to cancel 'on hold'??
  699. KeAcquireSpinLockAtDpcLevel(&pStrmEx->VBIOnHoldSpinLock);
  700. if (pStrmEx->pVBISrbOnHold && pSrb == pStrmEx->pVBISrbOnHold)
  701. {
  702. pStrmEx->pVBISrbOnHold = NULL;
  703. KeReleaseSpinLockFromDpcLevel(&pStrmEx->VBIOnHoldSpinLock);
  704. pSrb->Status = STATUS_CANCELLED;
  705. CDebugPrint(DebugLevelVerbose,
  706. (CODECNAME ":StreamClassStreamNotification(pSrb->Status=0x%x)\n",
  707. pSrb->Status));
  708. StreamClassStreamNotification(
  709. StreamRequestComplete, pSrb->StreamObject, pSrb);
  710. pSrb = NULL;
  711. }
  712. else
  713. KeReleaseSpinLockFromDpcLevel(&pStrmEx->VBIOnHoldSpinLock);
  714. if (NULL == pSrb)
  715. ; // We're done; we CANCELLED the SRB above
  716. else
  717. #endif // CCINPUTPIN
  718. //
  719. // Attempt removal from data queue
  720. //
  721. if( QueueRemoveSpecific( pSrb, &pStrmEx->StreamDataSpinLock,
  722. &pStrmEx->StreamDataQueue ))
  723. {
  724. pSrb->Status = STATUS_CANCELLED;
  725. CDebugPrint(DebugLevelVerbose,
  726. (CODECNAME ":StreamRequestComplete(ReadyForNextStreamDataRequest,pSrb->Status=0x%x)\n",
  727. pSrb->Status));
  728. StreamClassStreamNotification( StreamRequestComplete,
  729. pSrb->StreamObject, pSrb );
  730. }
  731. else
  732. //
  733. // Attempt removal from command queue
  734. //
  735. if( QueueRemoveSpecific( pSrb, &pStrmEx->StreamControlSpinLock,
  736. &pStrmEx->StreamControlQueue ))
  737. {
  738. pSrb->Status = STATUS_CANCELLED;
  739. CDebugPrint(DebugLevelVerbose,
  740. (CODECNAME ":StreamRequestComplete(ReadyForNextStreamControlRequest,pSrb->Status=0x%x)\n",
  741. pSrb->Status));
  742. StreamClassStreamNotification( StreamRequestComplete, pSrb->StreamObject,
  743. pSrb );
  744. }
  745. else
  746. //
  747. // Attempt removal from adapter queue
  748. //
  749. if( QueueRemoveSpecific( pSrb, &pHwDevExt->AdapterSRBSpinLock,
  750. &pHwDevExt->AdapterSRBQueue ))
  751. {
  752. pSrb->Status = STATUS_CANCELLED;
  753. CDebugPrint(DebugLevelVerbose,
  754. (CODECNAME ":DeviceRequestComplete(pSrb->Status=0x%x)\n",
  755. pSrb->Status));
  756. StreamClassDeviceNotification( DeviceRequestComplete, pSrb->StreamObject,
  757. pSrb );
  758. }
  759. else
  760. CDebugPrint( DebugLevelWarning, ( CODECNAME "SRB %x not found to cancel\n", pSrb ));
  761. CDebugPrint(DebugLevelTrace,(CODECNAME ":<---CodecCancelPacket(pSrb=%x)\n", pSrb));
  762. }
  763. /*
  764. ** CodecTimeoutPacket()
  765. **
  766. ** This routine is called when a packet has been in the minidriver for
  767. ** too long. The codec must decide what to do with the packet
  768. **
  769. ** Arguments:
  770. **
  771. ** pSrb - pointer to the request packet that timed out
  772. **
  773. ** Returns:
  774. **
  775. ** Side Effects: none
  776. */
  777. VOID
  778. STREAMAPI
  779. CodecTimeoutPacket(
  780. PHW_STREAM_REQUEST_BLOCK pSrb
  781. )
  782. {
  783. CDebugPrint(DebugLevelTrace,(CODECNAME ":--->CodecTimeoutPacket(pSrb=%x)\n", pSrb));
  784. //
  785. // if we timeout while playing, then we need to consider this
  786. // condition an error, and reset the hardware, and reset everything
  787. // as well as cancelling this and all requests
  788. //
  789. //
  790. // if we are not playing, and this is a CTRL request, we still
  791. // need to reset everything as well as cancelling this and all requests
  792. //
  793. //
  794. // if this is a data request, and the device is paused, we probably have
  795. // run out of data buffer, and need more time, so just reset the timer,
  796. // and let the packet continue
  797. //
  798. // pSrb->TimeoutCounter = pSrb->TimeoutOriginal;
  799. pSrb->TimeoutCounter = 0;
  800. CDebugPrint(DebugLevelTrace,(CODECNAME ":<---CodecTimeoutPacket(pSrb=%x)\n", pSrb));
  801. }
  802. #if 0
  803. /*
  804. ** CompleteStreamSRB ()
  805. **
  806. ** This routine is called when a packet is being completed.
  807. ** The optional second notification type is used to indicate ReadyForNext
  808. **
  809. ** Arguments:
  810. **
  811. ** pSrb - pointer to the request packet that timed out
  812. **
  813. ** NotificationType1 - what kind of notification to return
  814. **
  815. ** NotificationType2 - what kind of notification to return (may be 0)
  816. **
  817. **
  818. ** Returns:
  819. **
  820. ** Side Effects: none
  821. */
  822. VOID
  823. CompleteStreamSRB (
  824. IN PHW_STREAM_REQUEST_BLOCK pSrb,
  825. STREAM_MINIDRIVER_STREAM_NOTIFICATION_TYPE NotificationType1,
  826. BOOL fUseNotification2,
  827. STREAM_MINIDRIVER_STREAM_NOTIFICATION_TYPE NotificationType2
  828. )
  829. {
  830. CDebugPrint(DebugLevelTrace,
  831. (CODECNAME ":--->CompleteStreamSRB(pSrb=%x)\n", pSrb));
  832. CDebugPrint(DebugLevelVerbose,
  833. (CODECNAME ": CompleteStreamSRB : NotificationType1=%d\n",
  834. NotificationType1 ));
  835. StreamClassStreamNotification(
  836. NotificationType1,
  837. pSrb->StreamObject,
  838. pSrb);
  839. if (fUseNotification2)
  840. {
  841. // ReadyForNext
  842. CDebugPrint(DebugLevelVerbose,
  843. (CODECNAME ": CompleteStreamSRB : NotificationType2=%d\n",
  844. NotificationType2 ));
  845. StreamClassStreamNotification(
  846. NotificationType2,
  847. pSrb->StreamObject);
  848. }
  849. CDebugPrint(DebugLevelTrace,(CODECNAME ":<---CompleteStreamSRB(pSrb=%x)\n", pSrb));
  850. }
  851. /*
  852. ** CompleteDeviceSRB ()
  853. **
  854. ** This routine is called when a packet is being completed.
  855. ** The optional second notification type is used to indicate ReadyForNext
  856. **
  857. ** Arguments:
  858. **
  859. ** pSrb - pointer to the request packet that timed out
  860. **
  861. ** NotificationType - what kind of notification to return
  862. **
  863. ** fReadyForNext - Send the "ReadyForNextSRB"
  864. **
  865. **
  866. ** Returns:
  867. **
  868. ** Side Effects: none
  869. */
  870. VOID
  871. CompleteDeviceSRB (
  872. IN PHW_STREAM_REQUEST_BLOCK pSrb,
  873. IN STREAM_MINIDRIVER_DEVICE_NOTIFICATION_TYPE NotificationType,
  874. BOOL fReadyForNext
  875. )
  876. {
  877. CDebugPrint(DebugLevelTrace,(CODECNAME ":--->CompleteDeviceSRB(pSrb=%x)\n", pSrb));
  878. CDebugPrint(DebugLevelVerbose,
  879. (CODECNAME ": CompleteDeviceSRB : NotificationType=%d\n",
  880. NotificationType ));
  881. StreamClassDeviceNotification(
  882. NotificationType,
  883. pSrb->HwDeviceExtension,
  884. pSrb);
  885. if (fReadyForNext)
  886. {
  887. CDebugPrint(DebugLevelVerbose,
  888. (CODECNAME ": CompleteDeviceSRB : ReadyForNextDeviceRequest\n"));
  889. StreamClassDeviceNotification(
  890. ReadyForNextDeviceRequest,
  891. pSrb->HwDeviceExtension);
  892. }
  893. CDebugPrint(DebugLevelTrace,(CODECNAME ":<---CompleteDeviceSRB(pSrb=%x)\n", pSrb));
  894. }
  895. #endif //0
  896. /*
  897. ** CodecCompareGUIDsAndFormatSize()
  898. **
  899. ** Checks for a match on the three GUIDs and FormatSize
  900. **
  901. ** Arguments:
  902. **
  903. ** IN DataRange1
  904. ** IN DataRange2
  905. **
  906. ** Returns:
  907. **
  908. ** TRUE if all elements match
  909. ** FALSE if any are different
  910. **
  911. ** Side Effects: none
  912. */
  913. BOOL
  914. CodecCompareGUIDsAndFormatSize(
  915. IN PKSDATARANGE DataRange1,
  916. IN PKSDATARANGE DataRange2,
  917. BOOLEAN bCheckSize
  918. )
  919. {
  920. BOOL rval = FALSE;
  921. CDebugPrint(DebugLevelTrace,
  922. (CODECNAME ":--->CodecCompareGUIDsAndFormatSize(DataRange1=%x,DataRange2=%x,bCheckSize=%s)\r\n",
  923. DataRange1, DataRange2, bCheckSize ? "TRUE":"FALSE"));
  924. if ( IsEqualGUID(&DataRange1->MajorFormat, &KSDATAFORMAT_TYPE_WILDCARD)
  925. || IsEqualGUID(&DataRange2->MajorFormat, &KSDATAFORMAT_TYPE_WILDCARD)
  926. || IsEqualGUID(&DataRange1->MajorFormat, &DataRange2->MajorFormat) )
  927. {
  928. if ( !IsEqualGUID(&DataRange1->MajorFormat, &DataRange2->MajorFormat) )
  929. {
  930. CDebugPrint(DebugLevelVerbose,
  931. (CODECNAME ": CodecCompareGUIDsAndFormatSize : Matched MajorFormat Using Wildcard:\n\t[%s] vs. [%s]\n",
  932. &DataRange1->MajorFormat, &DataRange2->MajorFormat ));
  933. }
  934. if ( IsEqualGUID(&DataRange1->SubFormat, &KSDATAFORMAT_SUBTYPE_WILDCARD)
  935. || IsEqualGUID(&DataRange2->SubFormat, &KSDATAFORMAT_SUBTYPE_WILDCARD)
  936. || IsEqualGUID(&DataRange1->SubFormat, &DataRange2->SubFormat) )
  937. {
  938. if ( !IsEqualGUID(&DataRange1->SubFormat, &DataRange2->SubFormat) )
  939. {
  940. CDebugPrint(DebugLevelVerbose,
  941. (CODECNAME ": CodecCompareGUIDsAndFormatSize : Matched SubFormat Using Wildcard:\n\t[%s] vs. [%s]\n",
  942. &DataRange1->SubFormat, &DataRange2->SubFormat ));
  943. }
  944. if ( IsEqualGUID(&DataRange1->Specifier, &KSDATAFORMAT_SPECIFIER_NONE)
  945. || IsEqualGUID(&DataRange2->Specifier, &KSDATAFORMAT_SPECIFIER_NONE)
  946. || IsEqualGUID(&DataRange1->Specifier, &DataRange2->Specifier) )
  947. {
  948. if ( !IsEqualGUID(&DataRange1->Specifier, &DataRange2->Specifier) )
  949. {
  950. CDebugPrint(DebugLevelVerbose,
  951. (CODECNAME ": CodecCompareGUIDsAndFormatSize : Matched Specifier Using Wildcard:\n\t[%s] vs. [%s]\n",
  952. &DataRange1->Specifier, &DataRange2->Specifier ));
  953. }
  954. if ( !bCheckSize || DataRange1->FormatSize == DataRange2->FormatSize)
  955. {
  956. rval = TRUE;
  957. }
  958. else
  959. {
  960. CDebugPrint(DebugLevelVerbose,
  961. (CODECNAME ": CodecCompareGUIDsAndFormatSize : FormatSize mismatch=%d vs. %d\n",
  962. DataRange1->FormatSize, DataRange2->FormatSize ));
  963. }
  964. }
  965. else
  966. {
  967. CDebugPrint(DebugLevelVerbose,
  968. (CODECNAME ": CodecCompareGUIDsAndFormatSize : Specifier mismatch:\n\t[%s] vs. [%s]\n",
  969. &DataRange1->Specifier, &DataRange2->Specifier ));
  970. }
  971. }
  972. else
  973. {
  974. CDebugPrint(DebugLevelVerbose,
  975. (CODECNAME ": CodecCompareGUIDsAndFormatSize : Subformat mismatch:\n\t[%s] vs. [%s]\n",
  976. &DataRange1->SubFormat, &DataRange2->SubFormat ));
  977. }
  978. }
  979. else
  980. {
  981. CDebugPrint(DebugLevelVerbose,
  982. (CODECNAME ": CodecCompareGUIDsAndFormatSize : MajorFormat mismatch:\n\t[%s] vs. [%s]\n",
  983. &DataRange1->MajorFormat, &DataRange2->MajorFormat ));
  984. }
  985. CDebugPrint(DebugLevelTrace,
  986. (CODECNAME ":<---CodecCompareGUIDsAndFormatSize(DataRange1=%x,DataRange2=%x,bCheckSize=%s)=%s\n",
  987. DataRange1, DataRange2, bCheckSize ? "TRUE":"FALSE", rval? "TRUE":"FALSE"));
  988. return rval;
  989. }
  990. /*
  991. ** CodecVerifyFormat()
  992. **
  993. ** Checks the validity of a format request
  994. **
  995. ** Arguments:
  996. **
  997. ** pKSDataFormat - pointer to a KS_DATAFORMAT_VBIINFOHEADER structure.
  998. **
  999. ** Returns:
  1000. **
  1001. ** TRUE if the format is supported
  1002. ** FALSE if the format cannot be suppored
  1003. **
  1004. ** Side Effects: none
  1005. */
  1006. BOOL
  1007. CodecVerifyFormat(IN KSDATAFORMAT *pKSDataFormat, UINT StreamNumber, PKSDATARANGE pMatchedFormat )
  1008. {
  1009. BOOL rval = FALSE;
  1010. ULONG FormatCount;
  1011. PKS_DATARANGE_VIDEO ThisFormat;
  1012. PKS_DATAFORMAT_VBIINFOHEADER pKSVBIDataFormat = ( PKS_DATAFORMAT_VBIINFOHEADER )pKSDataFormat;
  1013. CDebugPrint(DebugLevelTrace,(CODECNAME ":--->CodecVerifyFormat(%x)\n", pKSDataFormat));
  1014. for( FormatCount = 0; rval == FALSE && FormatCount < Streams[StreamNumber].hwStreamInfo.NumberOfFormatArrayEntries;
  1015. FormatCount++ )
  1016. {
  1017. CDebugPrint(DebugLevelTrace,(CODECNAME , "Testing stream %d against format %x\r\n", StreamNumber, FormatCount ));
  1018. ThisFormat = ( PKS_DATARANGE_VIDEO )Streams[StreamNumber].hwStreamInfo.StreamFormatsArray[FormatCount];
  1019. if( !CodecCompareGUIDsAndFormatSize( pKSDataFormat, &ThisFormat->DataRange, FALSE ) )
  1020. {
  1021. CDebugPrint( DebugLevelVerbose, ( CODECNAME ": General format mismatch\n" ));
  1022. continue;
  1023. }
  1024. if( IsEqualGUID( &ThisFormat->DataRange.Specifier, &KSDATAFORMAT_SPECIFIER_VBI ) )
  1025. {
  1026. if( pKSVBIDataFormat->VBIInfoHeader.VideoStandard != KS_AnalogVideo_NTSC_M )
  1027. {
  1028. CDebugPrint( DebugLevelVerbose, ( CODECNAME ": Incompatible video standard\n" ));
  1029. continue;
  1030. }
  1031. if( pKSVBIDataFormat->VBIInfoHeader.StartLine < MIN_VBI_Y_SAMPLES )
  1032. {
  1033. CDebugPrint( DebugLevelVerbose, ( CODECNAME ": VBIInfoHeader.StartLine too small %u\n",
  1034. pKSVBIDataFormat->VBIInfoHeader.StartLine ));
  1035. continue;
  1036. }
  1037. if( pKSVBIDataFormat->VBIInfoHeader.EndLine > MAX_VBI_Y_SAMPLES )
  1038. {
  1039. CDebugPrint( DebugLevelVerbose, ( CODECNAME ": VBIInfoHeader.EndLine too big %u\n",
  1040. pKSVBIDataFormat->VBIInfoHeader.EndLine ));
  1041. continue;
  1042. }
  1043. if( pKSVBIDataFormat->VBIInfoHeader.SamplesPerLine < MIN_VBI_X_SAMPLES ||
  1044. pKSVBIDataFormat->VBIInfoHeader.SamplesPerLine > MAX_VBI_X_SAMPLES )
  1045. {
  1046. CDebugPrint( DebugLevelVerbose, ( CODECNAME ": Invalid VBIInfoHeader.SamplesPerLine %u\n",
  1047. pKSVBIDataFormat->VBIInfoHeader.SamplesPerLine ));
  1048. continue;
  1049. }
  1050. rval = TRUE;
  1051. }
  1052. else
  1053. if( IsEqualGUID( &ThisFormat->DataRange.Specifier, &KSDATAFORMAT_SPECIFIER_NONE ) )
  1054. rval = TRUE;
  1055. else
  1056. {
  1057. CDebugPrint( DebugLevelVerbose, ( CODECNAME ": Incompatible major format\n" ));
  1058. continue;
  1059. }
  1060. if( rval == TRUE && pMatchedFormat )
  1061. *pMatchedFormat = ThisFormat->DataRange;
  1062. }
  1063. CDebugPrint(DebugLevelTrace,(CODECNAME ":<---CodecVerifyFormat(%x)=%s\n", pKSDataFormat, rval? "TRUE":"FALSE"));
  1064. return rval;
  1065. }
  1066. /*
  1067. ** CodecVBIFormatFromRange()
  1068. **
  1069. ** Returns a DATAFORMAT from a DATARANGE
  1070. **
  1071. ** Arguments:
  1072. **
  1073. ** IN PHW_STREAM_REQUEST_BLOCK pSrb
  1074. **
  1075. ** Returns:
  1076. **
  1077. ** TRUE if the format is supported
  1078. ** FALSE if the format cannot be suppored
  1079. **
  1080. ** Side Effects: none
  1081. */
  1082. BOOL
  1083. CodecVBIFormatFromRange( IN PHW_STREAM_REQUEST_BLOCK pSrb )
  1084. {
  1085. BOOL bStatus = FALSE;
  1086. PSTREAM_DATA_INTERSECT_INFO IntersectInfo;
  1087. PKSDATARANGE DataRange;
  1088. BOOL OnlyWantsSize;
  1089. ULONG StreamNumber;
  1090. ULONG j;
  1091. ULONG NumberOfFormatArrayEntries;
  1092. PKSDATAFORMAT *pAvailableFormats;
  1093. CDebugPrint(DebugLevelTrace,(CODECNAME ":--->CodecVBIFormatFromRange(pSrb=%x)\n", pSrb));
  1094. IntersectInfo = pSrb->CommandData.IntersectInfo;
  1095. StreamNumber = IntersectInfo->StreamNumber;
  1096. DataRange = IntersectInfo->DataRange;
  1097. pSrb->ActualBytesTransferred = 0;
  1098. //
  1099. // Check that the stream number is valid
  1100. //
  1101. // if (StreamNumber < DRIVER_STREAM_COUNT)
  1102. // {
  1103. NumberOfFormatArrayEntries =
  1104. Streams[StreamNumber].hwStreamInfo.NumberOfFormatArrayEntries;
  1105. //
  1106. // Get the pointer to the array of available formats
  1107. //
  1108. pAvailableFormats = Streams[StreamNumber].hwStreamInfo.StreamFormatsArray;
  1109. //
  1110. // Is the caller trying to get the format, or the size of the format?
  1111. //
  1112. OnlyWantsSize = (IntersectInfo->SizeOfDataFormatBuffer == sizeof(ULONG));
  1113. //
  1114. // Walk the formats supported by the stream searching for a match
  1115. // of the three GUIDs which together define a DATARANGE
  1116. //
  1117. for (j = 0; j < NumberOfFormatArrayEntries; j++, pAvailableFormats++)
  1118. {
  1119. if ( CodecCompareGUIDsAndFormatSize(DataRange, *pAvailableFormats, TRUE) )
  1120. {
  1121. #ifdef KS_DATARANGE_VIDEO_VBI__EQ__KS_DATAFORMAT_VBIINFOHEADER
  1122. ULONG FormatSize = (*pAvailableFormats)->FormatSize;
  1123. #else
  1124. PKS_DATARANGE_VIDEO_VBI pDataRangeVBI = (PKS_DATARANGE_VIDEO_VBI)*pAvailableFormats;
  1125. ULONG FormatSize = sizeof( KS_DATAFORMAT_VBIINFOHEADER );
  1126. #endif
  1127. // Is the caller trying to get the format, or the size of the format?
  1128. if ( IntersectInfo->SizeOfDataFormatBuffer == sizeof(FormatSize) )
  1129. {
  1130. CDebugPrint(DebugLevelVerbose,
  1131. (CODECNAME ": CodecVBIFormatFromRange : Format Size=%d\n",
  1132. FormatSize));
  1133. *(PULONG)IntersectInfo->DataFormatBuffer = FormatSize;
  1134. pSrb->ActualBytesTransferred = sizeof(FormatSize);
  1135. bStatus = TRUE;
  1136. }
  1137. else
  1138. {
  1139. // Verify that there is enough room in the supplied buffer for the whole thing
  1140. if ( IntersectInfo->SizeOfDataFormatBuffer >= FormatSize )
  1141. {
  1142. #ifdef KS_DATARANGE_VIDEO_VBI__EQ__KS_DATAFORMAT_VBIINFOHEADER
  1143. RtlCopyMemory(IntersectInfo->DataFormatBuffer, *pAvailableFormats, FormatSize);
  1144. pSrb->ActualBytesTransferred = FormatSize;
  1145. #else
  1146. PKS_DATAFORMAT_VBIINFOHEADER InterVBIHdr =
  1147. (PKS_DATAFORMAT_VBIINFOHEADER)IntersectInfo->DataFormatBuffer;
  1148. RtlCopyMemory(&InterVBIHdr->DataFormat, &pDataRangeVBI->DataRange, sizeof(KSDATARANGE));
  1149. ((PKSDATAFORMAT)IntersectInfo->DataFormatBuffer)->FormatSize = FormatSize;
  1150. RtlCopyMemory(&InterVBIHdr->VBIInfoHeader, &pDataRangeVBI->VBIInfoHeader, sizeof(KS_VBIINFOHEADER));
  1151. pSrb->ActualBytesTransferred = FormatSize;
  1152. #endif
  1153. bStatus = TRUE;
  1154. }
  1155. else
  1156. {
  1157. CDebugPrint(DebugLevelVerbose,
  1158. (CODECNAME ": CodecVBIFormatFromRange : Buffer Too Small=%d vs. %d\n",
  1159. IntersectInfo->SizeOfDataFormatBuffer, FormatSize));
  1160. pSrb->Status = STATUS_BUFFER_TOO_SMALL;
  1161. }
  1162. }
  1163. break;
  1164. }
  1165. }
  1166. if ( j == NumberOfFormatArrayEntries )
  1167. {
  1168. CDebugPrint(DebugLevelVerbose,(CODECNAME ": CodecVBIFormatFromRange : Stream Format not found.\n" ));
  1169. }
  1170. // }
  1171. // else
  1172. // {
  1173. // CDebugPrint(DebugLevelVerbose,(CODECNAME ": CodecVBIFormatFromRange : StreamNumber too big=%d\n", StreamNumber));
  1174. // pSrb->Status = STATUS_NOT_IMPLEMENTED;
  1175. // bStatus = FALSE;
  1176. // CDEBUG_BREAK();
  1177. // }
  1178. CDebugPrint(DebugLevelTrace,
  1179. (CODECNAME ":<---CodecVBIFormatFromRange(pSrb=%x)=%s\n",
  1180. pSrb, bStatus ? "TRUE" : "FALSE" ));
  1181. return bStatus;
  1182. }
  1183. /*
  1184. ** CodecCCFormatFromRange()
  1185. **
  1186. ** Returns a DATAFORMAT from a DATARANGE
  1187. **
  1188. ** Arguments:
  1189. **
  1190. ** IN PHW_STREAM_REQUEST_BLOCK pSrb
  1191. **
  1192. ** Returns:
  1193. **
  1194. ** TRUE if the format is supported
  1195. ** FALSE if the format cannot be suppored
  1196. **
  1197. ** Side Effects: none
  1198. */
  1199. BOOL
  1200. CodecCCFormatFromRange( IN PHW_STREAM_REQUEST_BLOCK pSrb )
  1201. {
  1202. BOOL bStatus = FALSE;
  1203. PSTREAM_DATA_INTERSECT_INFO IntersectInfo;
  1204. PKSDATARANGE DataRange;
  1205. BOOL OnlyWantsSize;
  1206. ULONG StreamNumber;
  1207. ULONG j;
  1208. ULONG NumberOfFormatArrayEntries;
  1209. PKSDATAFORMAT *pAvailableFormats;
  1210. CDebugPrint(DebugLevelTrace,(CODECNAME ":--->CodecCCFormatFromRange(pSrb=%x)\n", pSrb));
  1211. IntersectInfo = pSrb->CommandData.IntersectInfo;
  1212. StreamNumber = IntersectInfo->StreamNumber;
  1213. DataRange = IntersectInfo->DataRange;
  1214. pSrb->ActualBytesTransferred = 0;
  1215. //
  1216. // Check that the stream number is valid
  1217. //
  1218. // if (StreamNumber < DRIVER_STREAM_COUNT)
  1219. // {
  1220. NumberOfFormatArrayEntries =
  1221. Streams[StreamNumber].hwStreamInfo.NumberOfFormatArrayEntries;
  1222. //
  1223. // Get the pointer to the array of available formats
  1224. //
  1225. pAvailableFormats = Streams[StreamNumber].hwStreamInfo.StreamFormatsArray;
  1226. //
  1227. // Is the caller trying to get the format, or the size of the format?
  1228. //
  1229. OnlyWantsSize = (IntersectInfo->SizeOfDataFormatBuffer == sizeof(ULONG));
  1230. //
  1231. // Walk the formats supported by the stream searching for a match
  1232. // of the three GUIDs which together define a DATARANGE
  1233. //
  1234. for (j = 0; j < NumberOfFormatArrayEntries; j++, pAvailableFormats++)
  1235. {
  1236. if ( CodecCompareGUIDsAndFormatSize(DataRange, *pAvailableFormats, TRUE) )
  1237. {
  1238. PKSDATARANGE pDataRangeCC = (PKSDATARANGE)*pAvailableFormats;
  1239. ULONG FormatSize = sizeof( KSDATARANGE );
  1240. // Is the caller trying to get the format, or the size of it?
  1241. if ( IntersectInfo->SizeOfDataFormatBuffer == sizeof(FormatSize) )
  1242. {
  1243. CDebugPrint(DebugLevelVerbose,
  1244. (CODECNAME ": CodecCCFormatFromRange : Format Size=%d\n",
  1245. FormatSize));
  1246. *(PULONG)IntersectInfo->DataFormatBuffer = FormatSize;
  1247. pSrb->ActualBytesTransferred = sizeof(FormatSize);
  1248. bStatus = TRUE;
  1249. }
  1250. else
  1251. {
  1252. // Verify that there is enough room in the supplied buffer
  1253. // for the whole thing
  1254. if ( IntersectInfo->SizeOfDataFormatBuffer >= FormatSize )
  1255. {
  1256. PKSDATAFORMAT InterCCHdr =
  1257. (PKSDATAFORMAT)IntersectInfo->DataFormatBuffer;
  1258. *InterCCHdr = *pDataRangeCC;
  1259. InterCCHdr->FormatSize = FormatSize;
  1260. pSrb->ActualBytesTransferred = FormatSize;
  1261. bStatus = TRUE;
  1262. }
  1263. else
  1264. {
  1265. CDebugPrint(DebugLevelVerbose,
  1266. (CODECNAME ": CodecCCFormatFromRange : Buffer Too Small=%d vs. %d\n",
  1267. IntersectInfo->SizeOfDataFormatBuffer, FormatSize));
  1268. pSrb->Status = STATUS_BUFFER_TOO_SMALL;
  1269. }
  1270. }
  1271. break;
  1272. }
  1273. }
  1274. if ( j == NumberOfFormatArrayEntries )
  1275. {
  1276. CDebugPrint(DebugLevelVerbose,(CODECNAME ": CodecCCFormatFromRange : Stream Format not found.\n" ));
  1277. }
  1278. // }
  1279. // else
  1280. // {
  1281. // CDebugPrint(DebugLevelVerbose,(CODECNAME ": CodecVBIFormatFromRange : StreamNumber too big=%d\n", StreamNumber));
  1282. // pSrb->Status = STATUS_NOT_IMPLEMENTED;
  1283. // bStatus = FALSE;
  1284. // CDEBUG_BREAK();
  1285. // }
  1286. CDebugPrint(DebugLevelTrace,
  1287. (CODECNAME ":<---CodecCCFormatFromRange(pSrb=%x)=%s\n",
  1288. pSrb, bStatus ? "TRUE" : "FALSE" ));
  1289. return bStatus;
  1290. }
  1291. /*
  1292. ** QueueAddIfNotEmpty
  1293. **
  1294. ** Adds an SRB to the current queue if it is not empty
  1295. **
  1296. ** Arguments:
  1297. **
  1298. ** IN PHW_STREAM_REQUEST_BLOCK pSrb
  1299. ** IN PKSPIN_LOCK pQueueSpinLock
  1300. ** IN PLIST_ENTRY pQueue
  1301. **
  1302. ** Returns:
  1303. **
  1304. ** TRUE if SRB was added (queue is not empty)
  1305. ** FALSE if SRB was not added (queue is empty)
  1306. ** Side Effects: none
  1307. */
  1308. BOOL STREAMAPI QueueAddIfNotEmpty( IN PHW_STREAM_REQUEST_BLOCK pSrb,
  1309. IN PKSPIN_LOCK pQueueSpinLock,
  1310. IN PLIST_ENTRY pQueue
  1311. )
  1312. {
  1313. KIRQL Irql;
  1314. PSRB_EXTENSION pSrbExtension;
  1315. BOOL bAddedSRB = FALSE;
  1316. CDebugPrint( DebugLevelVerbose, ( CODECNAME ":--->QueueAddIfNotEmpty %x\n", pSrb ));
  1317. CASSERT( pSrb );
  1318. pSrbExtension = ( PSRB_EXTENSION )pSrb->SRBExtension;
  1319. CASSERT( pSrbExtension );
  1320. KeAcquireSpinLock( pQueueSpinLock, &Irql );
  1321. if( !IsListEmpty( pQueue ))
  1322. {
  1323. pSrbExtension->pSrb = pSrb;
  1324. InsertTailList( pQueue, &pSrbExtension->ListEntry );
  1325. bAddedSRB = TRUE;
  1326. }
  1327. KeReleaseSpinLock( pQueueSpinLock, Irql );
  1328. CDebugPrint( DebugLevelVerbose, ( CODECNAME ": %s%x\n", bAddedSRB ?
  1329. "Added SRB to Queue " : ": Queue is empty, not adding ", pSrb ));
  1330. CDebugPrint( DebugLevelVerbose, ( CODECNAME ":<---QueueAddIfNotEmpty %x\n", bAddedSRB ));
  1331. return bAddedSRB;
  1332. }
  1333. /*
  1334. ** QueueAdd
  1335. **
  1336. ** Adds an SRB to the current queue unconditionally
  1337. **
  1338. ** Arguments:
  1339. **
  1340. ** IN PHW_STREAM_REQUEST_BLOCK pSrb
  1341. ** IN PKSPIN_LOCK pQueueSpinLock
  1342. ** IN PLIST_ENTRY pQueue
  1343. **
  1344. ** Returns:
  1345. **
  1346. ** TRUE
  1347. ** Side Effects: none
  1348. */
  1349. BOOL STREAMAPI QueueAdd( IN PHW_STREAM_REQUEST_BLOCK pSrb,
  1350. IN PKSPIN_LOCK pQueueSpinLock,
  1351. IN PLIST_ENTRY pQueue
  1352. )
  1353. {
  1354. KIRQL Irql;
  1355. PSRB_EXTENSION pSrbExtension;
  1356. CDebugPrint( DebugLevelVerbose, ( CODECNAME ":--->QueueAdd %x\n", pSrb ));
  1357. CASSERT( pSrb );
  1358. pSrbExtension = ( PSRB_EXTENSION )pSrb->SRBExtension;
  1359. CASSERT( pSrbExtension );
  1360. KeAcquireSpinLock( pQueueSpinLock, &Irql );
  1361. pSrbExtension->pSrb = pSrb;
  1362. InsertTailList( pQueue, &pSrbExtension->ListEntry );
  1363. KeReleaseSpinLock( pQueueSpinLock, Irql );
  1364. CDebugPrint( DebugLevelVerbose, ( CODECNAME ": Added SRB %x to Queue\n", pSrb ));
  1365. CDebugPrint( DebugLevelVerbose, ( CODECNAME ":<---QueueAdd\n" ));
  1366. return TRUE;
  1367. }
  1368. /*
  1369. ** QueueRemove
  1370. **
  1371. ** Removes the next available SRB from the current queue
  1372. **
  1373. ** Arguments:
  1374. **
  1375. ** IN PHW_STREAM_REQUEST_BLOCK * pSrb
  1376. ** IN PKSPIN_LOCK pQueueSpinLock
  1377. ** IN PLIST_ENTRY pQueue
  1378. **
  1379. ** Returns:
  1380. **
  1381. ** TRUE if SRB was removed
  1382. ** FALSE if SRB was not removed
  1383. ** Side Effects: none
  1384. */
  1385. BOOL STREAMAPI QueueRemove(
  1386. IN OUT PHW_STREAM_REQUEST_BLOCK * pSrb,
  1387. IN PKSPIN_LOCK pQueueSpinLock,
  1388. IN PLIST_ENTRY pQueue
  1389. )
  1390. {
  1391. KIRQL Irql;
  1392. BOOL bRemovedSRB = FALSE;
  1393. CDebugPrint( DebugLevelVerbose, ( CODECNAME ":--->QueueRemove\n" ));
  1394. KeAcquireSpinLock( pQueueSpinLock, &Irql );
  1395. *pSrb = ( PHW_STREAM_REQUEST_BLOCK )NULL;
  1396. CDebugPrint( DebugLevelVerbose,
  1397. ( CODECNAME ": QFlink %x QBlink %x\n", pQueue->Flink, pQueue->Blink ));
  1398. if( !IsListEmpty( pQueue ))
  1399. {
  1400. PHW_STREAM_REQUEST_BLOCK * pCurrentSrb;
  1401. PUCHAR Ptr = ( PUCHAR )RemoveHeadList( pQueue );
  1402. pCurrentSrb = ( PHW_STREAM_REQUEST_BLOCK * )((( PUCHAR )Ptr ) +
  1403. sizeof( LIST_ENTRY ));
  1404. CASSERT( *pCurrentSrb );
  1405. *pSrb = *pCurrentSrb;
  1406. bRemovedSRB = TRUE;
  1407. }
  1408. else
  1409. CDebugPrint( DebugLevelVerbose, ( CODECNAME ": Queue is empty\n" ));
  1410. KeReleaseSpinLock( pQueueSpinLock, Irql );
  1411. CDebugPrint( DebugLevelVerbose, ( CODECNAME ":<---QueueRemove %x %x\n",
  1412. bRemovedSRB, *pSrb ));
  1413. return bRemovedSRB;
  1414. }
  1415. /*
  1416. ** QueueRemoveSpecific
  1417. **
  1418. ** Removes a specific SRB from the queue
  1419. **
  1420. ** Arguments:
  1421. **
  1422. ** IN PHW_STREAM_REQUEST_BLOCK pSrb
  1423. ** IN PKSPIN_LOCK pQueueSpinLock
  1424. ** IN PLIST_ENTRY pQueue
  1425. **
  1426. ** Returns:
  1427. **
  1428. ** TRUE if the SRB was found and removed
  1429. ** FALSE if the SRB was not found
  1430. **
  1431. ** Side Effects: none
  1432. */
  1433. BOOL STREAMAPI QueueRemoveSpecific(
  1434. IN PHW_STREAM_REQUEST_BLOCK pSrb,
  1435. IN PKSPIN_LOCK pQueueSpinLock,
  1436. IN PLIST_ENTRY pQueue
  1437. )
  1438. {
  1439. KIRQL Irql;
  1440. PHW_STREAM_REQUEST_BLOCK * pCurrentSrb;
  1441. PLIST_ENTRY pCurrentEntry;
  1442. BOOL bRemovedSRB = FALSE;
  1443. CASSERT( pSrb );
  1444. CDebugPrint( DebugLevelVerbose, ( CODECNAME ":--->QueueRemoveSpecific %x\n", pSrb ));
  1445. KeAcquireSpinLock( pQueueSpinLock, &Irql );
  1446. if( !IsListEmpty( pQueue ))
  1447. {
  1448. pCurrentEntry = pQueue->Flink;
  1449. while(( pCurrentEntry != pQueue ) && !bRemovedSRB )
  1450. {
  1451. pCurrentSrb = ( PHW_STREAM_REQUEST_BLOCK * )((( PUCHAR )pCurrentEntry ) +
  1452. sizeof( LIST_ENTRY ));
  1453. CASSERT( *pCurrentSrb );
  1454. if( *pCurrentSrb == pSrb )
  1455. {
  1456. RemoveEntryList( pCurrentEntry );
  1457. bRemovedSRB = TRUE;
  1458. }
  1459. pCurrentEntry = pCurrentEntry->Flink;
  1460. }
  1461. }
  1462. KeReleaseSpinLock( pQueueSpinLock, Irql );
  1463. if( IsListEmpty( pQueue ))
  1464. CDebugPrint( DebugLevelVerbose, ( CODECNAME ": Queue is empty\n" ));
  1465. CDebugPrint( DebugLevelVerbose, ( CODECNAME ":<---QueueRemoveSpecific %x\n",
  1466. bRemovedSRB ));
  1467. return bRemovedSRB;
  1468. }
  1469. /*
  1470. ** QueueEmpty
  1471. **
  1472. ** Indicates whether or not the queue is empty
  1473. **
  1474. ** Arguments:
  1475. **
  1476. ** IN PKSPIN_LOCK pQueueSpinLock
  1477. ** IN PLIST_ENTRY pQueue
  1478. **
  1479. ** Returns:
  1480. **
  1481. ** TRUE if queue is empty
  1482. ** FALSE if queue is not empty
  1483. ** Side Effects: none
  1484. */
  1485. BOOL STREAMAPI QueueEmpty(
  1486. IN PKSPIN_LOCK pQueueSpinLock,
  1487. IN PLIST_ENTRY pQueue
  1488. )
  1489. {
  1490. KIRQL Irql;
  1491. BOOL bEmpty = FALSE;
  1492. CDebugPrint( DebugLevelVerbose, ( CODECNAME ":---> QueueEmpty\n" ));
  1493. KeAcquireSpinLock( pQueueSpinLock, &Irql );
  1494. bEmpty = IsListEmpty( pQueue );
  1495. KeReleaseSpinLock( pQueueSpinLock, Irql );
  1496. CDebugPrint( DebugLevelVerbose, ( CODECNAME ":<--- QueueEmpty %x\n", bEmpty ));
  1497. return bEmpty;
  1498. }