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.

1700 lines
50 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 - 1999 Microsoft Corporation. All Rights Reserved.
  9. //
  10. //==========================================================================;
  11. #include "strmini.h"
  12. #include "ksmedia.h"
  13. #include "capmain.h"
  14. #include "mediums.h"
  15. #include "capstrm.h"
  16. #include "capprop.h"
  17. #include "capdebug.h"
  18. // The only global used by this driver. It is used to keep track of the instance count of
  19. // the number of times the driver is loaded. This is used to create unique Mediums so that
  20. // the correct capture, crossbar, tuner, and tvaudio filters all get connected together.
  21. UINT GlobalDriverMediumInstanceCount = 0;
  22. // Debug Logging
  23. // 0 = Errors only
  24. // 1 = Info, stream state changes, stream open close
  25. // 2 = Verbose trace
  26. ULONG gDebugLevel = 0;
  27. /*
  28. ** DriverEntry()
  29. **
  30. ** This routine is called when the driver is first loaded by PnP.
  31. ** It in turn, calls upon the stream class to perform registration services.
  32. **
  33. ** Arguments:
  34. **
  35. ** DriverObject -
  36. ** Driver object for this driver
  37. **
  38. ** RegistryPath -
  39. ** Registry path string for this driver's key
  40. **
  41. ** Returns:
  42. **
  43. ** Results of StreamClassRegisterAdapter()
  44. **
  45. ** Side Effects: none
  46. */
  47. ULONG
  48. DriverEntry (
  49. IN PDRIVER_OBJECT DriverObject,
  50. IN PUNICODE_STRING RegistryPath
  51. )
  52. {
  53. HW_INITIALIZATION_DATA HwInitData;
  54. ULONG ReturnValue;
  55. DbgLogInfo(("TestCap: DriverEntry\n"));
  56. RtlZeroMemory(&HwInitData, sizeof(HwInitData));
  57. HwInitData.HwInitializationDataSize = sizeof(HwInitData);
  58. //
  59. // Set the Adapter entry points for the driver
  60. //
  61. HwInitData.HwInterrupt = NULL; // HwInterrupt;
  62. HwInitData.HwReceivePacket = AdapterReceivePacket;
  63. HwInitData.HwCancelPacket = AdapterCancelPacket;
  64. HwInitData.HwRequestTimeoutHandler = AdapterTimeoutPacket;
  65. HwInitData.DeviceExtensionSize = sizeof(HW_DEVICE_EXTENSION);
  66. HwInitData.PerRequestExtensionSize = sizeof(SRB_EXTENSION);
  67. HwInitData.FilterInstanceExtensionSize = 0;
  68. HwInitData.PerStreamExtensionSize = sizeof(STREAMEX);
  69. HwInitData.BusMasterDMA = FALSE;
  70. HwInitData.Dma24BitAddresses = FALSE;
  71. HwInitData.BufferAlignment = 3;
  72. HwInitData.DmaBufferSize = 0;
  73. // Don't rely on the stream class using raised IRQL to synchronize
  74. // execution. This single paramter most affects the overall structure
  75. // of the driver.
  76. HwInitData.TurnOffSynchronization = TRUE;
  77. ReturnValue = StreamClassRegisterAdapter(DriverObject, RegistryPath, &HwInitData);
  78. DbgLogInfo(("Testcap: StreamClassRegisterAdapter = %x\n", ReturnValue));
  79. return ReturnValue;
  80. }
  81. //==========================================================================;
  82. // Adapter Based Request Handling Routines
  83. //==========================================================================;
  84. /*
  85. ** HwInitialize()
  86. **
  87. ** This routine is called when an SRB_INITIALIZE_DEVICE request is received
  88. **
  89. ** Arguments:
  90. **
  91. ** pSrb - pointer to stream request block for the Initialize command
  92. **
  93. ** Returns:
  94. **
  95. ** Side Effects: none
  96. */
  97. BOOLEAN
  98. STREAMAPI
  99. HwInitialize (
  100. IN OUT PHW_STREAM_REQUEST_BLOCK pSrb
  101. )
  102. {
  103. STREAM_PHYSICAL_ADDRESS adr;
  104. ULONG Size;
  105. PUCHAR pDmaBuf;
  106. int j;
  107. PPORT_CONFIGURATION_INFORMATION ConfigInfo = pSrb->CommandData.ConfigInfo;
  108. PHW_DEVICE_EXTENSION pHwDevExt =
  109. (PHW_DEVICE_EXTENSION)ConfigInfo->HwDeviceExtension;
  110. DbgLogInfo(("Testcap: HwInitialize()\n"));
  111. if (ConfigInfo->NumberOfAccessRanges != 0) {
  112. DbgLogError(("Testcap: illegal config info\n"));
  113. pSrb->Status = STATUS_NO_SUCH_DEVICE;
  114. return (FALSE);
  115. }
  116. DbgLogInfo(("TestCap: Number of access ranges = %lx\n", ConfigInfo->NumberOfAccessRanges));
  117. DbgLogInfo(("TestCap: Memory Range = %lx\n", pHwDevExt->ioBaseLocal));
  118. DbgLogInfo(("TestCap: IRQ = %lx\n", ConfigInfo->BusInterruptLevel));
  119. if (ConfigInfo->NumberOfAccessRanges != 0) {
  120. pHwDevExt->ioBaseLocal
  121. = (PULONG)(ULONG_PTR) (ConfigInfo->AccessRanges[0].RangeStart.LowPart);
  122. }
  123. pHwDevExt->Irq = (USHORT)(ConfigInfo->BusInterruptLevel);
  124. ConfigInfo->StreamDescriptorSize = sizeof (HW_STREAM_HEADER) +
  125. DRIVER_STREAM_COUNT * sizeof (HW_STREAM_INFORMATION);
  126. pDmaBuf = StreamClassGetDmaBuffer(pHwDevExt);
  127. adr = StreamClassGetPhysicalAddress(pHwDevExt,
  128. NULL, pDmaBuf, DmaBuffer, &Size);
  129. // Init Crossbar properties
  130. pHwDevExt->VideoInputConnected = 0; // TvTuner video is the default
  131. pHwDevExt->AudioInputConnected = 5; // TvTuner audio is the default
  132. // Init VideoProcAmp properties
  133. pHwDevExt->Brightness = BrightnessDefault;
  134. pHwDevExt->BrightnessFlags = KSPROPERTY_VIDEOPROCAMP_FLAGS_AUTO;
  135. pHwDevExt->Contrast = ContrastDefault;
  136. pHwDevExt->ContrastFlags = KSPROPERTY_VIDEOPROCAMP_FLAGS_AUTO;
  137. pHwDevExt->ColorEnable = ColorEnableDefault;
  138. pHwDevExt->ColorEnableFlags = KSPROPERTY_VIDEOPROCAMP_FLAGS_MANUAL;
  139. // Init CameraControl properties
  140. pHwDevExt->Focus = FocusDefault;
  141. pHwDevExt->FocusFlags = KSPROPERTY_CAMERACONTROL_FLAGS_AUTO;
  142. pHwDevExt->Zoom = ZoomDefault;
  143. pHwDevExt->ZoomFlags = KSPROPERTY_CAMERACONTROL_FLAGS_AUTO;
  144. // Init TvTuner properties
  145. pHwDevExt->TunerMode = KSPROPERTY_TUNER_MODE_TV;
  146. pHwDevExt->Channel = 4;
  147. pHwDevExt->TunerInput = 0;
  148. pHwDevExt->Busy = 0;
  149. // Init TvAudio properties
  150. pHwDevExt->TVAudioMode = KS_TVAUDIO_MODE_MONO |
  151. KS_TVAUDIO_MODE_LANG_A ;
  152. // Init AnalogVideoDecoder properties
  153. pHwDevExt->VideoDecoderVideoStandard = KS_AnalogVideo_NTSC_M;
  154. pHwDevExt->VideoDecoderOutputEnable = FALSE;
  155. pHwDevExt->VideoDecoderVCRTiming = FALSE;
  156. // Init VideoControl properties
  157. pHwDevExt->VideoControlMode = 0;
  158. // Init VideoCompression properties
  159. pHwDevExt->CompressionSettings.CompressionKeyFrameRate = 15;
  160. pHwDevExt->CompressionSettings.CompressionPFramesPerKeyFrame = 3;
  161. pHwDevExt->CompressionSettings.CompressionQuality = 5000;
  162. pHwDevExt->PDO = ConfigInfo->RealPhysicalDeviceObject;
  163. DbgLogInfo(("TestCap: Physical Device Object = %lx\n", pHwDevExt->PDO));
  164. for (j = 0; j < MAX_TESTCAP_STREAMS; j++){
  165. // For each stream, maintain a separate queue for data and control
  166. InitializeListHead (&pHwDevExt->StreamSRBList[j]);
  167. InitializeListHead (&pHwDevExt->StreamControlSRBList[j]);
  168. KeInitializeSpinLock (&pHwDevExt->StreamSRBSpinLock[j]);
  169. pHwDevExt->StreamSRBListSize[j] = 0;
  170. }
  171. // Init ProtectionStatus
  172. pHwDevExt->ProtectionStatus = 0;
  173. // The following allows multiple instance of identical hardware
  174. // to be installed. GlobalDriverMediumInstanceCount is set in the Medium.Id field.
  175. pHwDevExt->DriverMediumInstanceCount = GlobalDriverMediumInstanceCount++;
  176. AdapterSetInstance (pSrb);
  177. DbgLogInfo(("TestCap: Exit, HwInitialize()\n"));
  178. pSrb->Status = STATUS_SUCCESS;
  179. return (TRUE);
  180. }
  181. /*
  182. ** HwUnInitialize()
  183. **
  184. ** This routine is called when an SRB_UNINITIALIZE_DEVICE request is received
  185. **
  186. ** Arguments:
  187. **
  188. ** pSrb - pointer to stream request block for the UnInitialize command
  189. **
  190. ** Returns:
  191. **
  192. ** Side Effects: none
  193. */
  194. BOOLEAN
  195. STREAMAPI
  196. HwUnInitialize (
  197. PHW_STREAM_REQUEST_BLOCK pSrb
  198. )
  199. {
  200. pSrb->Status = STATUS_SUCCESS;
  201. return TRUE;
  202. }
  203. /*
  204. ** AdapterPowerState()
  205. **
  206. ** This routine is called when an SRB_CHANGE_POWER_STATE request is received
  207. **
  208. ** Arguments:
  209. **
  210. ** pSrb - pointer to stream request block for the Change Power state command
  211. **
  212. ** Returns:
  213. **
  214. ** Side Effects: none
  215. */
  216. BOOLEAN
  217. STREAMAPI
  218. AdapterPowerState (
  219. PHW_STREAM_REQUEST_BLOCK pSrb
  220. )
  221. {
  222. PHW_DEVICE_EXTENSION pHwDevExt = ((PHW_DEVICE_EXTENSION)pSrb->HwDeviceExtension);
  223. pHwDevExt->DeviceState = pSrb->CommandData.DeviceState;
  224. return TRUE;
  225. }
  226. /*
  227. ** AdapterSetInstance()
  228. **
  229. ** This routine is called to set all of the Medium instance fields
  230. **
  231. ** Arguments:
  232. **
  233. ** pSrb - pointer to stream request block
  234. **
  235. ** Returns:
  236. **
  237. ** Side Effects: none
  238. */
  239. VOID
  240. STREAMAPI
  241. AdapterSetInstance (
  242. PHW_STREAM_REQUEST_BLOCK pSrb
  243. )
  244. {
  245. int j;
  246. PHW_DEVICE_EXTENSION pHwDevExt = ((PHW_DEVICE_EXTENSION)pSrb->HwDeviceExtension);
  247. // Use our HwDevExt as the instance data on the Mediums
  248. // This allows multiple instances to be uniquely identified and
  249. // connected. The value used in .Id is not important, only that
  250. // it is unique for each hardware connection
  251. for (j = 0; j < SIZEOF_ARRAY (TVTunerMediums); j++) {
  252. TVTunerMediums[j].Id = pHwDevExt->DriverMediumInstanceCount;
  253. }
  254. for (j = 0; j < SIZEOF_ARRAY (TVAudioMediums); j++) {
  255. TVAudioMediums[j].Id = pHwDevExt->DriverMediumInstanceCount;
  256. }
  257. for (j = 0; j < SIZEOF_ARRAY (CrossbarMediums); j++) {
  258. CrossbarMediums[j].Id = pHwDevExt->DriverMediumInstanceCount;
  259. }
  260. for (j = 0; j < SIZEOF_ARRAY (CaptureMediums); j++) {
  261. CaptureMediums[j].Id = pHwDevExt->DriverMediumInstanceCount;
  262. }
  263. pHwDevExt->AnalogVideoInputMedium = CaptureMediums[2];
  264. }
  265. /*
  266. ** AdapterCompleteInitialization()
  267. **
  268. ** This routine is called when an SRB_COMPLETE_INITIALIZATION request is received
  269. **
  270. ** Arguments:
  271. **
  272. ** pSrb - pointer to stream request block
  273. **
  274. ** Returns:
  275. **
  276. ** Side Effects: none
  277. */
  278. VOID
  279. STREAMAPI
  280. AdapterCompleteInitialization (
  281. PHW_STREAM_REQUEST_BLOCK pSrb
  282. )
  283. {
  284. NTSTATUS Status;
  285. PHW_DEVICE_EXTENSION pHwDevExt = ((PHW_DEVICE_EXTENSION)pSrb->HwDeviceExtension);
  286. KIRQL KIrql;
  287. KIrql = KeGetCurrentIrql();
  288. // Create the Registry blobs that DShow uses to create
  289. // graphs via Mediums
  290. // Register the TVTuner
  291. Status = StreamClassRegisterFilterWithNoKSPins (
  292. pHwDevExt->PDO, // IN PDEVICE_OBJECT DeviceObject,
  293. &KSCATEGORY_TVTUNER, // IN GUID * InterfaceClassGUID,
  294. SIZEOF_ARRAY (TVTunerMediums), // IN ULONG PinCount,
  295. TVTunerPinDirection, // IN ULONG * Flags,
  296. TVTunerMediums, // IN KSPIN_MEDIUM * MediumList,
  297. NULL // IN GUID * CategoryList
  298. );
  299. // Register the Crossbar
  300. Status = StreamClassRegisterFilterWithNoKSPins (
  301. pHwDevExt->PDO, // IN PDEVICE_OBJECT DeviceObject,
  302. &KSCATEGORY_CROSSBAR, // IN GUID * InterfaceClassGUID,
  303. SIZEOF_ARRAY (CrossbarMediums), // IN ULONG PinCount,
  304. CrossbarPinDirection, // IN ULONG * Flags,
  305. CrossbarMediums, // IN KSPIN_MEDIUM * MediumList,
  306. NULL // IN GUID * CategoryList
  307. );
  308. // Register the TVAudio decoder
  309. Status = StreamClassRegisterFilterWithNoKSPins (
  310. pHwDevExt->PDO, // IN PDEVICE_OBJECT DeviceObject,
  311. &KSCATEGORY_TVAUDIO, // IN GUID * InterfaceClassGUID,
  312. SIZEOF_ARRAY (TVAudioMediums), // IN ULONG PinCount,
  313. TVAudioPinDirection, // IN ULONG * Flags,
  314. TVAudioMediums, // IN KSPIN_MEDIUM * MediumList,
  315. NULL // IN GUID * CategoryList
  316. );
  317. // Register the Capture filter
  318. // Note: This should be done automatically be MSKsSrv.sys,
  319. // when that component comes on line (if ever) ...
  320. Status = StreamClassRegisterFilterWithNoKSPins (
  321. pHwDevExt->PDO, // IN PDEVICE_OBJECT DeviceObject,
  322. &KSCATEGORY_CAPTURE, // IN GUID * InterfaceClassGUID,
  323. SIZEOF_ARRAY (CaptureMediums), // IN ULONG PinCount,
  324. CapturePinDirection, // IN ULONG * Flags,
  325. CaptureMediums, // IN KSPIN_MEDIUM * MediumList,
  326. NULL // IN GUID * CategoryList
  327. );
  328. }
  329. /*
  330. ** AdapterOpenStream()
  331. **
  332. ** This routine is called when an OpenStream SRB request is received.
  333. ** A stream is identified by a stream number, which indexes an array
  334. ** of KSDATARANGE structures. The particular KSDATAFORMAT format to
  335. ** be used is also passed in, which should be verified for validity.
  336. **
  337. ** Arguments:
  338. **
  339. ** pSrb - pointer to stream request block for the Open command
  340. **
  341. ** Returns:
  342. **
  343. ** Side Effects: none
  344. */
  345. VOID
  346. STREAMAPI
  347. AdapterOpenStream (
  348. PHW_STREAM_REQUEST_BLOCK pSrb
  349. )
  350. {
  351. //
  352. // the stream extension structure is allocated by the stream class driver
  353. //
  354. PSTREAMEX pStrmEx = (PSTREAMEX)pSrb->StreamObject->HwStreamExtension;
  355. PHW_DEVICE_EXTENSION pHwDevExt = ((PHW_DEVICE_EXTENSION)pSrb->HwDeviceExtension);
  356. int StreamNumber = pSrb->StreamObject->StreamNumber;
  357. PKSDATAFORMAT pKSDataFormat = pSrb->CommandData.OpenFormat;
  358. RtlZeroMemory(pStrmEx, sizeof(STREAMEX));
  359. DbgLogInfo(("TestCap: ------- ADAPTEROPENSTREAM ------- StreamNumber=%d\n", StreamNumber));
  360. //
  361. // check that the stream index requested isn't too high
  362. // or that the maximum number of instances hasn't been exceeded
  363. //
  364. if (StreamNumber >= DRIVER_STREAM_COUNT || StreamNumber < 0) {
  365. pSrb->Status = STATUS_INVALID_PARAMETER;
  366. return;
  367. }
  368. //
  369. // Check that we haven't exceeded the instance count for this stream
  370. //
  371. if (pHwDevExt->ActualInstances[StreamNumber] >=
  372. Streams[StreamNumber].hwStreamInfo.NumberOfPossibleInstances) {
  373. pSrb->Status = STATUS_INVALID_PARAMETER;
  374. return;
  375. }
  376. //
  377. // Check the validity of the format being requested
  378. //
  379. if (!AdapterVerifyFormat (pKSDataFormat, StreamNumber)) {
  380. pSrb->Status = STATUS_INVALID_PARAMETER;
  381. return;
  382. }
  383. //
  384. // And set the format for the stream
  385. //
  386. if (!VideoSetFormat (pSrb)) {
  387. return;
  388. }
  389. ASSERT (pHwDevExt->pStrmEx [StreamNumber] == NULL);
  390. // Maintain an array of all the StreamEx structures in the HwDevExt
  391. // so that we can cancel IRPs from any stream
  392. pHwDevExt->pStrmEx [StreamNumber] = (PSTREAMX) pStrmEx;
  393. // Set up pointers to the handlers for the stream data and control handlers
  394. pSrb->StreamObject->ReceiveDataPacket =
  395. (PVOID) Streams[StreamNumber].hwStreamObject.ReceiveDataPacket;
  396. pSrb->StreamObject->ReceiveControlPacket =
  397. (PVOID) Streams[StreamNumber].hwStreamObject.ReceiveControlPacket;
  398. //
  399. // The DMA flag must be set when the device will be performing DMA directly
  400. // to the data buffer addresses passed in to the ReceiceDataPacket routines.
  401. //
  402. pSrb->StreamObject->Dma = Streams[StreamNumber].hwStreamObject.Dma;
  403. //
  404. // The PIO flag must be set when the mini driver will be accessing the data
  405. // buffers passed in using logical addressing
  406. //
  407. pSrb->StreamObject->Pio = Streams[StreamNumber].hwStreamObject.Pio;
  408. //
  409. // How many extra bytes will be passed up from the driver for each frame?
  410. //
  411. pSrb->StreamObject->StreamHeaderMediaSpecific =
  412. Streams[StreamNumber].hwStreamObject.StreamHeaderMediaSpecific;
  413. pSrb->StreamObject->StreamHeaderWorkspace =
  414. Streams[StreamNumber].hwStreamObject.StreamHeaderWorkspace;
  415. //
  416. // Indicate the clock support available on this stream
  417. //
  418. pSrb->StreamObject->HwClockObject =
  419. Streams[StreamNumber].hwStreamObject.HwClockObject;
  420. //
  421. // Increment the instance count on this stream
  422. //
  423. pHwDevExt->ActualInstances[StreamNumber]++;
  424. // Retain a private copy of the HwDevExt and StreamObject in the stream extension
  425. // so we can use a timer
  426. pStrmEx->pHwDevExt = pHwDevExt; // For timer use
  427. pStrmEx->pStreamObject = pSrb->StreamObject; // For timer use
  428. // Initialize the compression settings
  429. // These may have been changed from the default values in the HwDevExt
  430. // before the stream was opened
  431. pStrmEx->CompressionSettings.CompressionKeyFrameRate =
  432. pHwDevExt->CompressionSettings.CompressionKeyFrameRate;
  433. pStrmEx->CompressionSettings.CompressionPFramesPerKeyFrame =
  434. pHwDevExt->CompressionSettings.CompressionPFramesPerKeyFrame;
  435. pStrmEx->CompressionSettings.CompressionQuality =
  436. pHwDevExt->CompressionSettings.CompressionQuality;
  437. // Init VideoControl properties
  438. pStrmEx->VideoControlMode = pHwDevExt->VideoControlMode;
  439. // Init VBI variables
  440. pStrmEx->SentVBIInfoHeader = 0;
  441. DbgLogInfo(("TestCap: AdapterOpenStream Exit\n"));
  442. }
  443. /*
  444. ** AdapterCloseStream()
  445. **
  446. ** Close the requested data stream.
  447. **
  448. ** Note that a stream could be closed arbitrarily in the midst of streaming
  449. ** if a user mode app crashes. Therefore, you must release all outstanding
  450. ** resources, disable interrupts, complete all pending SRBs, and put the
  451. ** stream back into a quiescent condition.
  452. **
  453. ** Arguments:
  454. **
  455. ** pSrb the request block requesting to close the stream
  456. **
  457. ** Returns:
  458. **
  459. ** Side Effects: none
  460. */
  461. VOID
  462. STREAMAPI
  463. AdapterCloseStream (
  464. PHW_STREAM_REQUEST_BLOCK pSrb
  465. )
  466. {
  467. PSTREAMEX pStrmEx = (PSTREAMEX)pSrb->StreamObject->HwStreamExtension;
  468. PHW_DEVICE_EXTENSION pHwDevExt = ((PHW_DEVICE_EXTENSION)pSrb->HwDeviceExtension);
  469. int StreamNumber = pSrb->StreamObject->StreamNumber;
  470. PKSDATAFORMAT pKSDataFormat = pSrb->CommandData.OpenFormat;
  471. KS_VIDEOINFOHEADER *pVideoInfoHdr = pStrmEx->pVideoInfoHeader;
  472. DbgLogInfo(("TestCap: -------- ADAPTERCLOSESTREAM ------ StreamNumber=%d\n", StreamNumber));
  473. if (pHwDevExt->StreamSRBListSize > 0) {
  474. VideoQueueCancelAllSRBs (pStrmEx);
  475. DbgLogError(("TestCap: Outstanding SRBs at stream close!!!\n"));
  476. }
  477. pHwDevExt->ActualInstances[StreamNumber]--;
  478. ASSERT (pHwDevExt->pStrmEx [StreamNumber] != 0);
  479. pHwDevExt->pStrmEx [StreamNumber] = 0;
  480. //
  481. // the minidriver should free any resources that were allocate at
  482. // open stream time etc.
  483. //
  484. // Free the variable length VIDEOINFOHEADER
  485. if (pVideoInfoHdr) {
  486. ExFreePool(pVideoInfoHdr);
  487. pStrmEx->pVideoInfoHeader = NULL;
  488. }
  489. // Make sure we no longer reference the clock
  490. pStrmEx->hMasterClock = NULL;
  491. // Make sure the state is reset to stopped,
  492. pStrmEx->KSState = KSSTATE_STOP;
  493. }
  494. /*
  495. ** AdapterStreamInfo()
  496. **
  497. ** Returns the information of all streams that are supported by the
  498. ** mini-driver
  499. **
  500. ** Arguments:
  501. **
  502. ** pSrb - Pointer to the STREAM_REQUEST_BLOCK
  503. ** pSrb->HwDeviceExtension - will be the hardware device extension for
  504. ** as initialised in HwInitialise
  505. **
  506. ** Returns:
  507. **
  508. ** Side Effects: none
  509. */
  510. VOID
  511. STREAMAPI
  512. AdapterStreamInfo (
  513. PHW_STREAM_REQUEST_BLOCK pSrb
  514. )
  515. {
  516. int j;
  517. PHW_DEVICE_EXTENSION pHwDevExt =
  518. ((PHW_DEVICE_EXTENSION)pSrb->HwDeviceExtension);
  519. //
  520. // pick up the pointer to header which preceeds the stream info structs
  521. //
  522. PHW_STREAM_HEADER pstrhdr =
  523. (PHW_STREAM_HEADER)&(pSrb->CommandData.StreamBuffer->StreamHeader);
  524. //
  525. // pick up the pointer to the array of stream information data structures
  526. //
  527. PHW_STREAM_INFORMATION pstrinfo =
  528. (PHW_STREAM_INFORMATION)&(pSrb->CommandData.StreamBuffer->StreamInfo);
  529. //
  530. // verify that the buffer is large enough to hold our return data
  531. //
  532. DEBUG_ASSERT (pSrb->NumberOfBytesToTransfer >=
  533. sizeof (HW_STREAM_HEADER) +
  534. sizeof (HW_STREAM_INFORMATION) * DRIVER_STREAM_COUNT);
  535. // Ugliness. To allow mulitple instances, modify the pointer to the
  536. // AnalogVideoMedium and save it in our device extension
  537. Streams[STREAM_AnalogVideoInput].hwStreamInfo.Mediums =
  538. &pHwDevExt->AnalogVideoInputMedium;
  539. // pHwDevExt->AnalogVideoInputMedium = CrossbarMediums[9];
  540. // pHwDevExt->AnalogVideoInputMedium.Id = pHwDevExt->DriverMediumInstanceCount;
  541. //
  542. // Set the header
  543. //
  544. StreamHeader.NumDevPropArrayEntries = NUMBER_OF_ADAPTER_PROPERTY_SETS;
  545. StreamHeader.DevicePropertiesArray = (PKSPROPERTY_SET) AdapterPropertyTable;
  546. *pstrhdr = StreamHeader;
  547. //
  548. // stuff the contents of each HW_STREAM_INFORMATION struct
  549. //
  550. for (j = 0; j < DRIVER_STREAM_COUNT; j++) {
  551. *pstrinfo++ = Streams[j].hwStreamInfo;
  552. }
  553. }
  554. /*
  555. ** AdapterReceivePacket()
  556. **
  557. ** Main entry point for receiving adapter based request SRBs. This routine
  558. ** will always be called at Passive level.
  559. **
  560. ** Note: This is an asyncronous entry point. The request does not necessarily
  561. ** complete on return from this function, the request only completes when a
  562. ** StreamClassDeviceNotification on this request block, of type
  563. ** DeviceRequestComplete, is issued.
  564. **
  565. ** Arguments:
  566. **
  567. ** pSrb - Pointer to the STREAM_REQUEST_BLOCK
  568. ** pSrb->HwDeviceExtension - will be the hardware device extension for
  569. ** as initialised in HwInitialise
  570. **
  571. ** Returns:
  572. **
  573. ** Side Effects: none
  574. */
  575. VOID
  576. STREAMAPI
  577. AdapterReceivePacket(
  578. IN PHW_STREAM_REQUEST_BLOCK pSrb
  579. )
  580. {
  581. PHW_DEVICE_EXTENSION pHwDevExt = ((PHW_DEVICE_EXTENSION)pSrb->HwDeviceExtension);
  582. BOOL Busy;
  583. DEBUG_ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);
  584. DbgLogTrace(("TestCap: Receiving Adapter SRB %8x, %x\n", pSrb, pSrb->Command));
  585. // The very first time through, we need to initialize the adapter spinlock
  586. // and queue
  587. if (!pHwDevExt->AdapterQueueInitialized) {
  588. InitializeListHead (&pHwDevExt->AdapterSRBList);
  589. KeInitializeSpinLock (&pHwDevExt->AdapterSpinLock);
  590. pHwDevExt->AdapterQueueInitialized = TRUE;
  591. pHwDevExt->ProcessingAdapterSRB = FALSE;
  592. }
  593. //
  594. // If we're already processing an SRB, add it to the queue
  595. //
  596. Busy = AddToListIfBusy (
  597. pSrb,
  598. &pHwDevExt->AdapterSpinLock,
  599. &pHwDevExt->ProcessingAdapterSRB,
  600. &pHwDevExt->AdapterSRBList);
  601. if (Busy) {
  602. return;
  603. }
  604. //
  605. // This will run until the queue is empty
  606. //
  607. while (TRUE) {
  608. //
  609. // Assume success
  610. //
  611. pSrb->Status = STATUS_SUCCESS;
  612. //
  613. // determine the type of packet.
  614. //
  615. switch (pSrb->Command)
  616. {
  617. case SRB_INITIALIZE_DEVICE:
  618. // open the device
  619. HwInitialize(pSrb);
  620. break;
  621. case SRB_UNINITIALIZE_DEVICE:
  622. // close the device.
  623. HwUnInitialize(pSrb);
  624. break;
  625. case SRB_OPEN_STREAM:
  626. // open a stream
  627. AdapterOpenStream(pSrb);
  628. break;
  629. case SRB_CLOSE_STREAM:
  630. // close a stream
  631. AdapterCloseStream(pSrb);
  632. break;
  633. case SRB_GET_STREAM_INFO:
  634. //
  635. // return a block describing all the streams
  636. //
  637. AdapterStreamInfo(pSrb);
  638. break;
  639. case SRB_GET_DATA_INTERSECTION:
  640. //
  641. // Return a format, given a range
  642. //
  643. AdapterFormatFromRange(pSrb);
  644. break;
  645. case SRB_OPEN_DEVICE_INSTANCE:
  646. case SRB_CLOSE_DEVICE_INSTANCE:
  647. //
  648. // We should never get these since this is a single instance device
  649. //
  650. TRAP;
  651. pSrb->Status = STATUS_NOT_IMPLEMENTED;
  652. break;
  653. case SRB_GET_DEVICE_PROPERTY:
  654. //
  655. // Get adapter wide properties
  656. //
  657. AdapterGetProperty (pSrb);
  658. break;
  659. case SRB_SET_DEVICE_PROPERTY:
  660. //
  661. // Set adapter wide properties
  662. //
  663. AdapterSetProperty (pSrb);
  664. break;
  665. case SRB_PAGING_OUT_DRIVER:
  666. //
  667. // The driver is being paged out
  668. // Disable Interrupts if you have them!
  669. //
  670. DbgLogInfo(("'Testcap: Receiving SRB_PAGING_OUT_DRIVER -- SRB=%x\n", pSrb));
  671. break;
  672. case SRB_CHANGE_POWER_STATE:
  673. //
  674. // Changing the device power state, D0 ... D3
  675. //
  676. DbgLogInfo(("'Testcap: Receiving SRB_CHANGE_POWER_STATE ------ SRB=%x\n", pSrb));
  677. AdapterPowerState(pSrb);
  678. break;
  679. case SRB_INITIALIZATION_COMPLETE:
  680. //
  681. // Stream class has finished initialization.
  682. // Now create DShow Medium interface BLOBs.
  683. // This needs to be done at low priority since it uses the registry
  684. //
  685. DbgLogInfo(("'Testcap: Receiving SRB_INITIALIZATION_COMPLETE-- SRB=%x\n", pSrb));
  686. AdapterCompleteInitialization (pSrb);
  687. break;
  688. case SRB_UNKNOWN_DEVICE_COMMAND:
  689. default:
  690. //
  691. // this is a request that we do not understand. Indicate invalid
  692. // command and complete the request
  693. //
  694. pSrb->Status = STATUS_NOT_IMPLEMENTED;
  695. }
  696. //
  697. // Indicate back to the Stream Class that we're done with this SRB
  698. //
  699. CompleteDeviceSRB (pSrb);
  700. //
  701. // See if there's anything else on the queue
  702. //
  703. Busy = RemoveFromListIfAvailable (
  704. &pSrb,
  705. &pHwDevExt->AdapterSpinLock,
  706. &pHwDevExt->ProcessingAdapterSRB,
  707. &pHwDevExt->AdapterSRBList);
  708. if (!Busy) {
  709. break;
  710. }
  711. } // end of while there's anything in the queue
  712. }
  713. /*
  714. ** AdapterCancelPacket ()
  715. **
  716. ** Request to cancel a packet that is currently in process in the minidriver
  717. **
  718. ** Arguments:
  719. **
  720. ** pSrb - pointer to request packet to cancel
  721. **
  722. ** Returns:
  723. **
  724. ** Side Effects: none
  725. */
  726. VOID
  727. STREAMAPI
  728. AdapterCancelPacket(
  729. PHW_STREAM_REQUEST_BLOCK pSrb
  730. )
  731. {
  732. PHW_DEVICE_EXTENSION pHwDevExt = (PHW_DEVICE_EXTENSION)pSrb->HwDeviceExtension;
  733. PSTREAMEX pStrmEx;
  734. int StreamNumber;
  735. BOOL Found = FALSE;
  736. //
  737. // Run through all the streams the driver has available
  738. //
  739. for (StreamNumber = 0; !Found && (StreamNumber < DRIVER_STREAM_COUNT); StreamNumber++) {
  740. //
  741. // Check to see if the stream is in use
  742. //
  743. if (pStrmEx = (PSTREAMEX) pHwDevExt->pStrmEx[StreamNumber]) {
  744. Found = VideoQueueCancelOneSRB (
  745. pStrmEx,
  746. pSrb
  747. );
  748. } // if the stream is open
  749. } // for all streams
  750. DbgLogInfo(("TestCap: Cancelling SRB %8x Succeeded=%d\n", pSrb, Found));
  751. }
  752. /*
  753. ** AdapterTimeoutPacket()
  754. **
  755. ** This routine is called when a packet has been in the minidriver for
  756. ** too long. The adapter must decide what to do with the packet
  757. **
  758. ** Arguments:
  759. **
  760. ** pSrb - pointer to the request packet that timed out
  761. **
  762. ** Returns:
  763. **
  764. ** Side Effects: none
  765. */
  766. VOID
  767. STREAMAPI
  768. AdapterTimeoutPacket(
  769. PHW_STREAM_REQUEST_BLOCK pSrb
  770. )
  771. {
  772. //
  773. // Unlike most devices, we need to hold onto data SRBs indefinitely,
  774. // since the graph could be in a pause state indefinitely
  775. //
  776. DbgLogInfo(("TestCap: Timeout Adapter SRB %8x\n", pSrb));
  777. pSrb->TimeoutCounter = pSrb->TimeoutOriginal;
  778. }
  779. /*
  780. ** CompleteDeviceSRB ()
  781. **
  782. ** This routine is called when a packet is being completed.
  783. ** The optional second notification type is used to indicate ReadyForNext
  784. **
  785. ** Arguments:
  786. **
  787. ** pSrb - pointer to the request packet that timed out
  788. **
  789. ** Returns:
  790. **
  791. ** Side Effects:
  792. **
  793. */
  794. VOID
  795. STREAMAPI
  796. CompleteDeviceSRB (
  797. IN PHW_STREAM_REQUEST_BLOCK pSrb
  798. )
  799. {
  800. DbgLogTrace(("TestCap: Completing Adapter SRB %8x\n", pSrb));
  801. StreamClassDeviceNotification( DeviceRequestComplete, pSrb->HwDeviceExtension, pSrb);
  802. }
  803. /*
  804. ** IsEqualOrWildGUID()
  805. **
  806. ** Compares two GUIDS like IsEqualGUID(), except allows wildcard matches
  807. **
  808. ** Arguments:
  809. **
  810. ** IN GUID *g1
  811. ** IN GUID *g2
  812. **
  813. ** Returns:
  814. **
  815. ** TRUE if both GUIDs match or only one is a wildcard
  816. ** FALSE if GUIDs are different or both are wildcards
  817. **
  818. ** Side Effects: none
  819. */
  820. BOOL
  821. STREAMAPI
  822. IsEqualOrWildGUID(IN GUID *g1, IN GUID *g2)
  823. {
  824. return (IsEqualGUID(g1, g2) && !IsEqualGUID(g1, &KSDATAFORMAT_TYPE_WILDCARD)
  825. || ((IsEqualGUID(g1, &KSDATAFORMAT_TYPE_WILDCARD)
  826. || IsEqualGUID(g2, &KSDATAFORMAT_TYPE_WILDCARD))
  827. && !IsEqualGUID(g1, g2))
  828. );
  829. }
  830. /*
  831. ** AdapterCompareGUIDsAndFormatSize()
  832. **
  833. ** Checks for a match on the three GUIDs and FormatSize
  834. **
  835. ** Arguments:
  836. **
  837. ** IN DataRange1
  838. ** IN DataRange2
  839. ** BOOL fCompareFormatSize - TRUE when comparing ranges
  840. ** - FALSE when comparing formats
  841. **
  842. ** Returns:
  843. **
  844. ** TRUE if all elements match
  845. ** FALSE if any are different
  846. **
  847. ** Side Effects: none
  848. */
  849. BOOL
  850. STREAMAPI
  851. AdapterCompareGUIDsAndFormatSize(
  852. IN PKSDATARANGE DataRange1,
  853. IN PKSDATARANGE DataRange2,
  854. BOOL fCompareFormatSize
  855. )
  856. {
  857. return (
  858. IsEqualOrWildGUID (
  859. &DataRange1->MajorFormat,
  860. &DataRange2->MajorFormat) &&
  861. IsEqualOrWildGUID (
  862. &DataRange1->SubFormat,
  863. &DataRange2->SubFormat) &&
  864. IsEqualOrWildGUID (
  865. &DataRange1->Specifier,
  866. &DataRange2->Specifier) &&
  867. (fCompareFormatSize ?
  868. (DataRange1->FormatSize == DataRange2->FormatSize) : TRUE ));
  869. }
  870. /*
  871. ** AdapterVerifyFormat()
  872. **
  873. ** Checks the validity of a format request by walking through the
  874. ** array of supported KSDATA_RANGEs for a given stream.
  875. **
  876. ** Arguments:
  877. **
  878. ** pKSDataFormat - pointer of a KSDATAFORMAT structure.
  879. ** StreamNumber - index of the stream being queried / opened.
  880. **
  881. ** Returns:
  882. **
  883. ** TRUE if the format is supported
  884. ** FALSE if the format cannot be suppored
  885. **
  886. ** Side Effects: none
  887. */
  888. BOOL
  889. STREAMAPI
  890. AdapterVerifyFormat(
  891. PKSDATAFORMAT pKSDataFormatToVerify,
  892. int StreamNumber
  893. )
  894. {
  895. BOOL fOK = FALSE;
  896. ULONG j;
  897. ULONG NumberOfFormatArrayEntries;
  898. PKSDATAFORMAT *pAvailableFormats;
  899. //
  900. // Check that the stream number is valid
  901. //
  902. if (StreamNumber >= DRIVER_STREAM_COUNT) {
  903. TRAP;
  904. return FALSE;
  905. }
  906. NumberOfFormatArrayEntries =
  907. Streams[StreamNumber].hwStreamInfo.NumberOfFormatArrayEntries;
  908. //
  909. // Get the pointer to the array of available formats
  910. //
  911. pAvailableFormats = Streams[StreamNumber].hwStreamInfo.StreamFormatsArray;
  912. DbgLogInfo(("TestCap: AdapterVerifyFormat, Stream=%d\n", StreamNumber));
  913. DbgLogInfo(("TestCap: FormatSize=%d\n", pKSDataFormatToVerify->FormatSize));
  914. DbgLogInfo(("TestCap: MajorFormat=%x\n", pKSDataFormatToVerify->MajorFormat));
  915. //
  916. // Walk the formats supported by the stream
  917. //
  918. for (j = 0; j < NumberOfFormatArrayEntries; j++, pAvailableFormats++) {
  919. // Check for a match on the three GUIDs and format size
  920. if (!AdapterCompareGUIDsAndFormatSize(
  921. pKSDataFormatToVerify,
  922. *pAvailableFormats,
  923. FALSE /* CompareFormatSize */ )) {
  924. continue;
  925. }
  926. //
  927. // Now that the three GUIDs match, switch on the Specifier
  928. // to do a further type-specific check
  929. //
  930. // -------------------------------------------------------------------
  931. // Specifier FORMAT_VideoInfo for VIDEOINFOHEADER
  932. // -------------------------------------------------------------------
  933. if (IsEqualGUID (&pKSDataFormatToVerify->Specifier,
  934. &KSDATAFORMAT_SPECIFIER_VIDEOINFO)) {
  935. PKS_DATAFORMAT_VIDEOINFOHEADER pDataFormatVideoInfoHeader =
  936. (PKS_DATAFORMAT_VIDEOINFOHEADER) pKSDataFormatToVerify;
  937. PKS_VIDEOINFOHEADER pVideoInfoHdrToVerify =
  938. (PKS_VIDEOINFOHEADER) &pDataFormatVideoInfoHeader->VideoInfoHeader;
  939. PKS_DATARANGE_VIDEO pKSDataRangeVideo = (PKS_DATARANGE_VIDEO) *pAvailableFormats;
  940. KS_VIDEO_STREAM_CONFIG_CAPS *pConfigCaps = &pKSDataRangeVideo->ConfigCaps;
  941. RECT rcImage;
  942. DbgLogInfo(("TestCap: AdapterVerifyFormat\n"));
  943. DbgLogInfo(("TestCap: pVideoInfoHdrToVerify=%x\n", pVideoInfoHdrToVerify));
  944. DbgLogInfo(("TestCap: KS_VIDEOINFOHEADER size=%d\n",
  945. KS_SIZE_VIDEOHEADER (pVideoInfoHdrToVerify)));
  946. DbgLogInfo(("TestCap: Width=%d Height=%d BitCount=%d\n",
  947. pVideoInfoHdrToVerify->bmiHeader.biWidth,
  948. pVideoInfoHdrToVerify->bmiHeader.biHeight,
  949. pVideoInfoHdrToVerify->bmiHeader.biBitCount));
  950. DbgLogInfo(("TestCap: biSizeImage=%d\n",
  951. pVideoInfoHdrToVerify->bmiHeader.biSizeImage));
  952. /*
  953. ** HOW BIG IS THE IMAGE REQUESTED (pseudocode follows)
  954. **
  955. ** if (IsRectEmpty (&rcTarget) {
  956. ** SetRect (&rcImage, 0, 0,
  957. ** BITMAPINFOHEADER.biWidth,
  958. BITMAPINFOHEADER.biHeight);
  959. ** }
  960. ** else {
  961. ** // Probably rendering to a DirectDraw surface,
  962. ** // where biWidth is used to expressed the "stride"
  963. ** // in units of pixels (not bytes) of the destination surface.
  964. ** // Therefore, use rcTarget to get the actual image size
  965. **
  966. ** rcImage = rcTarget;
  967. ** }
  968. */
  969. if ((pVideoInfoHdrToVerify->rcTarget.right -
  970. pVideoInfoHdrToVerify->rcTarget.left <= 0) ||
  971. (pVideoInfoHdrToVerify->rcTarget.bottom -
  972. pVideoInfoHdrToVerify->rcTarget.top <= 0)) {
  973. rcImage.left = rcImage.top = 0;
  974. rcImage.right = pVideoInfoHdrToVerify->bmiHeader.biWidth;
  975. rcImage.bottom = pVideoInfoHdrToVerify->bmiHeader.biHeight;
  976. }
  977. else {
  978. rcImage = pVideoInfoHdrToVerify->rcTarget;
  979. }
  980. //
  981. // Perform all other verification tests here!!!
  982. //
  983. //
  984. // HOORAY, the format passed all of the tests, so we support it
  985. //
  986. fOK = TRUE;
  987. break;
  988. } // End of VIDEOINFOHEADER specifier
  989. // -------------------------------------------------------------------
  990. // Specifier FORMAT_AnalogVideo for KS_ANALOGVIDEOINFO
  991. // -------------------------------------------------------------------
  992. else if (IsEqualGUID (&pKSDataFormatToVerify->Specifier,
  993. &KSDATAFORMAT_SPECIFIER_ANALOGVIDEO)) {
  994. //
  995. // For analog video, the DataRange and DataFormat
  996. // are identical, so just copy the whole structure
  997. //
  998. PKS_DATARANGE_ANALOGVIDEO DataRangeVideo =
  999. (PKS_DATARANGE_ANALOGVIDEO) *pAvailableFormats;
  1000. //
  1001. // Perform all other verification tests here!!!
  1002. //
  1003. fOK = TRUE;
  1004. break;
  1005. } // End of KS_ANALOGVIDEOINFO specifier
  1006. // -------------------------------------------------------------------
  1007. // Specifier FORMAT_VBI for KS_VIDEO_VBI
  1008. // -------------------------------------------------------------------
  1009. else if (IsEqualGUID (&pKSDataFormatToVerify->Specifier,
  1010. &KSDATAFORMAT_SPECIFIER_VBI))
  1011. {
  1012. //
  1013. // Do some VBI-specific tests
  1014. //
  1015. PKS_DATAFORMAT_VBIINFOHEADER pKSVBIDataFormat;
  1016. DbgLogInfo(("Testcap: This is a VBIINFOHEADER format pin.\n" ));
  1017. pKSVBIDataFormat = (PKS_DATAFORMAT_VBIINFOHEADER)pKSDataFormatToVerify;
  1018. //
  1019. // Check VideoStandard, we only support NTSC_M
  1020. //
  1021. if (KS_AnalogVideo_NTSC_M
  1022. == pKSVBIDataFormat->VBIInfoHeader.VideoStandard)
  1023. {
  1024. fOK = TRUE;
  1025. break;
  1026. }
  1027. else
  1028. {
  1029. DbgLogError(
  1030. ("Testcap: AdapterVerifyFormat : VideoStandard(%d) != NTSC_M\n",
  1031. pKSVBIDataFormat->VBIInfoHeader.VideoStandard));
  1032. }
  1033. }
  1034. // -------------------------------------------------------------------
  1035. // Type FORMAT_NABTS for NABTS pin
  1036. // -------------------------------------------------------------------
  1037. else if (IsEqualGUID (&pKSDataFormatToVerify->SubFormat,
  1038. &KSDATAFORMAT_SUBTYPE_NABTS))
  1039. {
  1040. fOK = TRUE;
  1041. break;
  1042. }
  1043. // -------------------------------------------------------------------
  1044. // for CC pin
  1045. // -------------------------------------------------------------------
  1046. else if (IsEqualGUID (&pKSDataFormatToVerify->SubFormat,
  1047. &KSDATAFORMAT_SUBTYPE_CC))
  1048. {
  1049. fOK = TRUE;
  1050. break;
  1051. }
  1052. } // End of loop on all formats for this stream
  1053. return fOK;
  1054. }
  1055. /*
  1056. ** AdapterFormatFromRange()
  1057. **
  1058. ** Produces a DATAFORMAT given a DATARANGE.
  1059. **
  1060. ** Think of a DATARANGE as a multidimensional space of all of the possible image
  1061. ** sizes, cropping, scaling, and framerate possibilities. Here, the caller
  1062. ** is saying "Out of this set of possibilities, could you verify that my
  1063. ** request is acceptable?". The resulting singular output is a DATAFORMAT.
  1064. ** Note that each different colorspace (YUV vs RGB8 vs RGB24)
  1065. ** must be represented as a separate DATARANGE.
  1066. **
  1067. ** Generally, the resulting DATAFORMAT will be immediately used to open a stream
  1068. ** in that format.
  1069. **
  1070. ** Arguments:
  1071. **
  1072. ** IN PHW_STREAM_REQUEST_BLOCK pSrb
  1073. **
  1074. ** Returns:
  1075. **
  1076. ** TRUE if the format is supported
  1077. ** FALSE if the format cannot be suppored
  1078. **
  1079. ** Side Effects: none
  1080. */
  1081. BOOL
  1082. STREAMAPI
  1083. AdapterFormatFromRange(
  1084. IN PHW_STREAM_REQUEST_BLOCK pSrb
  1085. )
  1086. {
  1087. PSTREAM_DATA_INTERSECT_INFO IntersectInfo;
  1088. PKSDATARANGE DataRange;
  1089. BOOL OnlyWantsSize;
  1090. BOOL MatchFound = FALSE;
  1091. ULONG FormatSize;
  1092. ULONG StreamNumber;
  1093. ULONG j;
  1094. ULONG NumberOfFormatArrayEntries;
  1095. PKSDATAFORMAT *pAvailableFormats;
  1096. IntersectInfo = pSrb->CommandData.IntersectInfo;
  1097. StreamNumber = IntersectInfo->StreamNumber;
  1098. DataRange = IntersectInfo->DataRange;
  1099. //
  1100. // Check that the stream number is valid
  1101. //
  1102. if (StreamNumber >= DRIVER_STREAM_COUNT) {
  1103. pSrb->Status = STATUS_NOT_IMPLEMENTED;
  1104. TRAP;
  1105. return FALSE;
  1106. }
  1107. NumberOfFormatArrayEntries =
  1108. Streams[StreamNumber].hwStreamInfo.NumberOfFormatArrayEntries;
  1109. //
  1110. // Get the pointer to the array of available formats
  1111. //
  1112. pAvailableFormats = Streams[StreamNumber].hwStreamInfo.StreamFormatsArray;
  1113. //
  1114. // Is the caller trying to get the format, or the size of the format?
  1115. //
  1116. OnlyWantsSize = (IntersectInfo->SizeOfDataFormatBuffer == sizeof(ULONG));
  1117. //
  1118. // Walk the formats supported by the stream searching for a match
  1119. // of the three GUIDs which together define a DATARANGE
  1120. //
  1121. for (j = 0; j < NumberOfFormatArrayEntries; j++, pAvailableFormats++) {
  1122. if (!AdapterCompareGUIDsAndFormatSize(
  1123. DataRange,
  1124. *pAvailableFormats,
  1125. TRUE /* CompareFormatSize */)) {
  1126. continue;
  1127. }
  1128. //
  1129. // Now that the three GUIDs match, do a further type-specific check
  1130. //
  1131. // -------------------------------------------------------------------
  1132. // Specifier FORMAT_VideoInfo for VIDEOINFOHEADER
  1133. // -------------------------------------------------------------------
  1134. if (IsEqualGUID (&DataRange->Specifier,
  1135. &KSDATAFORMAT_SPECIFIER_VIDEOINFO)) {
  1136. PKS_DATARANGE_VIDEO DataRangeVideoToVerify =
  1137. (PKS_DATARANGE_VIDEO) DataRange;
  1138. PKS_DATARANGE_VIDEO DataRangeVideo =
  1139. (PKS_DATARANGE_VIDEO) *pAvailableFormats;
  1140. PKS_DATAFORMAT_VIDEOINFOHEADER DataFormatVideoInfoHeaderOut;
  1141. //
  1142. // Check that the other fields match
  1143. //
  1144. if ((DataRangeVideoToVerify->bFixedSizeSamples != DataRangeVideo->bFixedSizeSamples) ||
  1145. (DataRangeVideoToVerify->bTemporalCompression != DataRangeVideo->bTemporalCompression) ||
  1146. (DataRangeVideoToVerify->StreamDescriptionFlags != DataRangeVideo->StreamDescriptionFlags) ||
  1147. (DataRangeVideoToVerify->MemoryAllocationFlags != DataRangeVideo->MemoryAllocationFlags) ||
  1148. (RtlCompareMemory (&DataRangeVideoToVerify->ConfigCaps,
  1149. &DataRangeVideo->ConfigCaps,
  1150. sizeof (KS_VIDEO_STREAM_CONFIG_CAPS)) !=
  1151. sizeof (KS_VIDEO_STREAM_CONFIG_CAPS)))
  1152. {
  1153. continue;
  1154. }
  1155. // MATCH FOUND!
  1156. MatchFound = TRUE;
  1157. FormatSize = sizeof (KSDATAFORMAT) +
  1158. KS_SIZE_VIDEOHEADER (&DataRangeVideoToVerify->VideoInfoHeader);
  1159. if (OnlyWantsSize) {
  1160. break;
  1161. }
  1162. // Caller wants the full data format
  1163. if (IntersectInfo->SizeOfDataFormatBuffer < FormatSize) {
  1164. pSrb->Status = STATUS_BUFFER_TOO_SMALL;
  1165. return FALSE;
  1166. }
  1167. // Copy over the KSDATAFORMAT, followed by the
  1168. // actual VideoInfoHeader
  1169. DataFormatVideoInfoHeaderOut = (PKS_DATAFORMAT_VIDEOINFOHEADER) IntersectInfo->DataFormatBuffer;
  1170. // Copy over the KSDATAFORMAT
  1171. RtlCopyMemory(
  1172. &DataFormatVideoInfoHeaderOut->DataFormat,
  1173. &DataRangeVideoToVerify->DataRange,
  1174. sizeof (KSDATARANGE));
  1175. DataFormatVideoInfoHeaderOut->DataFormat.FormatSize = FormatSize;
  1176. // Copy over the callers requested VIDEOINFOHEADER
  1177. RtlCopyMemory(
  1178. &DataFormatVideoInfoHeaderOut->VideoInfoHeader,
  1179. &DataRangeVideoToVerify->VideoInfoHeader,
  1180. KS_SIZE_VIDEOHEADER (&DataRangeVideoToVerify->VideoInfoHeader));
  1181. // Calculate biSizeImage for this request, and put the result in both
  1182. // the biSizeImage field of the bmiHeader AND in the SampleSize field
  1183. // of the DataFormat.
  1184. //
  1185. // Note that for compressed sizes, this calculation will probably not
  1186. // be just width * height * bitdepth
  1187. DataFormatVideoInfoHeaderOut->VideoInfoHeader.bmiHeader.biSizeImage =
  1188. DataFormatVideoInfoHeaderOut->DataFormat.SampleSize =
  1189. KS_DIBSIZE(DataFormatVideoInfoHeaderOut->VideoInfoHeader.bmiHeader);
  1190. //
  1191. // Perform other validation such as cropping and scaling checks
  1192. //
  1193. break;
  1194. } // End of VIDEOINFOHEADER specifier
  1195. // -------------------------------------------------------------------
  1196. // Specifier FORMAT_AnalogVideo for KS_ANALOGVIDEOINFO
  1197. // -------------------------------------------------------------------
  1198. else if (IsEqualGUID (&DataRange->Specifier,
  1199. &KSDATAFORMAT_SPECIFIER_ANALOGVIDEO)) {
  1200. //
  1201. // For analog video, the DataRange and DataFormat
  1202. // are identical, so just copy the whole structure
  1203. //
  1204. PKS_DATARANGE_ANALOGVIDEO DataRangeVideo =
  1205. (PKS_DATARANGE_ANALOGVIDEO) *pAvailableFormats;
  1206. // MATCH FOUND!
  1207. MatchFound = TRUE;
  1208. FormatSize = sizeof (KS_DATARANGE_ANALOGVIDEO);
  1209. if (OnlyWantsSize) {
  1210. break;
  1211. }
  1212. // Caller wants the full data format
  1213. if (IntersectInfo->SizeOfDataFormatBuffer < FormatSize) {
  1214. pSrb->Status = STATUS_BUFFER_TOO_SMALL;
  1215. return FALSE;
  1216. }
  1217. RtlCopyMemory(
  1218. IntersectInfo->DataFormatBuffer,
  1219. DataRangeVideo,
  1220. sizeof (KS_DATARANGE_ANALOGVIDEO));
  1221. ((PKSDATAFORMAT)IntersectInfo->DataFormatBuffer)->FormatSize = FormatSize;
  1222. break;
  1223. } // End of KS_ANALOGVIDEOINFO specifier
  1224. // -------------------------------------------------------------------
  1225. // Specifier FORMAT_VBI for KS_VIDEO_VBI
  1226. // -------------------------------------------------------------------
  1227. else if (IsEqualGUID (&DataRange->Specifier,
  1228. &KSDATAFORMAT_SPECIFIER_VBI))
  1229. {
  1230. PKS_DATARANGE_VIDEO_VBI pDataRangeVBI =
  1231. (PKS_DATARANGE_VIDEO_VBI)*pAvailableFormats;
  1232. PKS_DATAFORMAT_VBIINFOHEADER InterVBIHdr =
  1233. (PKS_DATAFORMAT_VBIINFOHEADER)IntersectInfo->DataFormatBuffer;
  1234. // MATCH FOUND!
  1235. MatchFound = TRUE;
  1236. FormatSize = sizeof (KS_DATAFORMAT_VBIINFOHEADER);
  1237. // Is the caller trying to get the format, or the size of it?
  1238. if (OnlyWantsSize)
  1239. break;
  1240. // Verify that there is enough room in the supplied buffer
  1241. // for the whole thing
  1242. if (IntersectInfo->SizeOfDataFormatBuffer < FormatSize)
  1243. {
  1244. if (IntersectInfo->SizeOfDataFormatBuffer > 0) {
  1245. DbgLogError(
  1246. ("Testcap::AdapterFormatFromRange: "
  1247. "Specifier==VBI, Buffer too small=%d vs. %d\n",
  1248. IntersectInfo->SizeOfDataFormatBuffer,
  1249. FormatSize));
  1250. }
  1251. pSrb->Status = STATUS_BUFFER_TOO_SMALL;
  1252. return FALSE;
  1253. }
  1254. // If there is room, go ahead...
  1255. RtlCopyMemory(&InterVBIHdr->DataFormat,
  1256. &pDataRangeVBI->DataRange,
  1257. sizeof (KSDATARANGE));
  1258. ((PKSDATAFORMAT)IntersectInfo->DataFormatBuffer)->FormatSize = FormatSize;
  1259. RtlCopyMemory(&InterVBIHdr->VBIInfoHeader,
  1260. &pDataRangeVBI->VBIInfoHeader,
  1261. sizeof(KS_VBIINFOHEADER));
  1262. break;
  1263. } // End of KS_VIDEO_VBI specifier
  1264. // -------------------------------------------------------------------
  1265. // Type FORMAT_NABTS for NABTS pin
  1266. // -------------------------------------------------------------------
  1267. else if (IsEqualGUID (&DataRange->SubFormat,
  1268. &KSDATAFORMAT_SUBTYPE_NABTS))
  1269. {
  1270. PKSDATARANGE pDataRange = (PKSDATARANGE)*pAvailableFormats;
  1271. // MATCH FOUND!
  1272. MatchFound = TRUE;
  1273. FormatSize = sizeof (KSDATAFORMAT);
  1274. // Is the caller trying to get the format, or the size of it?
  1275. if (OnlyWantsSize)
  1276. break;
  1277. // Verify that there is enough room in the supplied buffer
  1278. // for the whole thing
  1279. if (IntersectInfo->SizeOfDataFormatBuffer >= FormatSize)
  1280. {
  1281. RtlCopyMemory(IntersectInfo->DataFormatBuffer,
  1282. pDataRange,
  1283. FormatSize);
  1284. ((PKSDATAFORMAT)IntersectInfo->DataFormatBuffer)->FormatSize = FormatSize;
  1285. }
  1286. else
  1287. {
  1288. if (IntersectInfo->SizeOfDataFormatBuffer > 0) {
  1289. DbgLogError(
  1290. ("Testcap::AdapterFormatFromRange: "
  1291. "SubFormat==NABTS, Buffer too small=%d vs. %d\n",
  1292. IntersectInfo->SizeOfDataFormatBuffer,
  1293. FormatSize));
  1294. }
  1295. pSrb->Status = STATUS_BUFFER_TOO_SMALL;
  1296. return FALSE;
  1297. }
  1298. break;
  1299. } // End of KS_SUBTYPE_NABTS
  1300. // -------------------------------------------------------------------
  1301. // for CC pin
  1302. // -------------------------------------------------------------------
  1303. else if (IsEqualGUID (&DataRange->SubFormat,
  1304. &KSDATAFORMAT_SUBTYPE_CC))
  1305. {
  1306. PKSDATARANGE pDataRange = (PKSDATARANGE)*pAvailableFormats;
  1307. // MATCH FOUND!
  1308. MatchFound = TRUE;
  1309. FormatSize = sizeof (KSDATAFORMAT);
  1310. // Is the caller trying to get the format, or the size of it?
  1311. if (OnlyWantsSize)
  1312. break;
  1313. // Verify that there is enough room in the supplied buffer
  1314. // for the whole thing
  1315. if (IntersectInfo->SizeOfDataFormatBuffer >= FormatSize)
  1316. {
  1317. RtlCopyMemory(IntersectInfo->DataFormatBuffer,
  1318. pDataRange,
  1319. FormatSize);
  1320. ((PKSDATAFORMAT)IntersectInfo->DataFormatBuffer)->FormatSize = FormatSize;
  1321. }
  1322. else
  1323. {
  1324. if (IntersectInfo->SizeOfDataFormatBuffer > 0) {
  1325. DbgLogError(
  1326. ("Testcap::AdapterFormatFromRange: "
  1327. "SubFormat==CC, Buffer too small=%d vs. %d\n",
  1328. IntersectInfo->SizeOfDataFormatBuffer,
  1329. FormatSize));
  1330. }
  1331. pSrb->Status = STATUS_BUFFER_TOO_SMALL;
  1332. return FALSE;
  1333. }
  1334. break;
  1335. } // End of CC pin format check
  1336. else {
  1337. pSrb->Status = STATUS_NO_MATCH;
  1338. return FALSE;
  1339. }
  1340. } // End of loop on all formats for this stream
  1341. if (!MatchFound) {
  1342. pSrb->Status = STATUS_NO_MATCH;
  1343. return FALSE;
  1344. }
  1345. if (OnlyWantsSize) {
  1346. *(PULONG) IntersectInfo->DataFormatBuffer = FormatSize;
  1347. FormatSize = sizeof(ULONG);
  1348. }
  1349. pSrb->ActualBytesTransferred = FormatSize;
  1350. return TRUE;
  1351. }