Leaked source code of windows server 2003
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.

1855 lines
57 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. // init lock for pVideoInfoHeader
  442. // we need it to serialize using/setting of VideoInfoHeader
  443. KeInitializeSpinLock (&pStrmEx->lockVideoInfoHeader);
  444. DbgLogInfo(("TestCap: AdapterOpenStream Exit\n"));
  445. }
  446. /*
  447. ** AdapterCloseStream()
  448. **
  449. ** Close the requested data stream.
  450. **
  451. ** Note that a stream could be closed arbitrarily in the midst of streaming
  452. ** if a user mode app crashes. Therefore, you must release all outstanding
  453. ** resources, disable interrupts, complete all pending SRBs, and put the
  454. ** stream back into a quiescent condition.
  455. **
  456. ** Arguments:
  457. **
  458. ** pSrb the request block requesting to close the stream
  459. **
  460. ** Returns:
  461. **
  462. ** Side Effects: none
  463. */
  464. VOID
  465. STREAMAPI
  466. AdapterCloseStream (
  467. PHW_STREAM_REQUEST_BLOCK pSrb
  468. )
  469. {
  470. PSTREAMEX pStrmEx = (PSTREAMEX)pSrb->StreamObject->HwStreamExtension;
  471. PHW_DEVICE_EXTENSION pHwDevExt = ((PHW_DEVICE_EXTENSION)pSrb->HwDeviceExtension);
  472. int StreamNumber = pSrb->StreamObject->StreamNumber;
  473. KS_VIDEOINFOHEADER *pVideoInfoHdr = pStrmEx->pVideoInfoHeader;
  474. DbgLogInfo(("TestCap: -------- ADAPTERCLOSESTREAM ------ StreamNumber=%d\n", StreamNumber));
  475. if (pHwDevExt->StreamSRBListSize > 0) {
  476. VideoQueueCancelAllSRBs (pStrmEx);
  477. DbgLogError(("TestCap: Outstanding SRBs at stream close!!!\n"));
  478. }
  479. pHwDevExt->ActualInstances[StreamNumber]--;
  480. ASSERT (pHwDevExt->pStrmEx [StreamNumber] != 0);
  481. pHwDevExt->pStrmEx [StreamNumber] = 0;
  482. //
  483. // the minidriver should free any resources that were allocate at
  484. // open stream time etc.
  485. //
  486. // Free the variable length VIDEOINFOHEADER
  487. if (pVideoInfoHdr) {
  488. ExFreePool(pVideoInfoHdr);
  489. pStrmEx->pVideoInfoHeader = NULL;
  490. }
  491. // Make sure we no longer reference the clock
  492. pStrmEx->hMasterClock = NULL;
  493. // Make sure the state is reset to stopped,
  494. pStrmEx->KSState = KSSTATE_STOP;
  495. }
  496. /*
  497. ** AdapterStreamInfo()
  498. **
  499. ** Returns the information of all streams that are supported by the
  500. ** mini-driver
  501. **
  502. ** Arguments:
  503. **
  504. ** pSrb - Pointer to the STREAM_REQUEST_BLOCK
  505. ** pSrb->HwDeviceExtension - will be the hardware device extension for
  506. ** as initialised in HwInitialise
  507. **
  508. ** Returns:
  509. **
  510. ** Side Effects: none
  511. */
  512. VOID
  513. STREAMAPI
  514. AdapterStreamInfo (
  515. PHW_STREAM_REQUEST_BLOCK pSrb
  516. )
  517. {
  518. int j;
  519. PHW_DEVICE_EXTENSION pHwDevExt =
  520. ((PHW_DEVICE_EXTENSION)pSrb->HwDeviceExtension);
  521. //
  522. // pick up the pointer to header which preceeds the stream info structs
  523. //
  524. PHW_STREAM_HEADER pstrhdr =
  525. (PHW_STREAM_HEADER)&(pSrb->CommandData.StreamBuffer->StreamHeader);
  526. //
  527. // pick up the pointer to the array of stream information data structures
  528. //
  529. PHW_STREAM_INFORMATION pstrinfo =
  530. (PHW_STREAM_INFORMATION)&(pSrb->CommandData.StreamBuffer->StreamInfo);
  531. //
  532. // verify that the buffer is large enough to hold our return data
  533. //
  534. DEBUG_ASSERT (pSrb->NumberOfBytesToTransfer >=
  535. sizeof (HW_STREAM_HEADER) +
  536. sizeof (HW_STREAM_INFORMATION) * DRIVER_STREAM_COUNT);
  537. // Ugliness. To allow mulitple instances, modify the pointer to the
  538. // AnalogVideoMedium and save it in our device extension
  539. Streams[STREAM_AnalogVideoInput].hwStreamInfo.Mediums =
  540. &pHwDevExt->AnalogVideoInputMedium;
  541. // pHwDevExt->AnalogVideoInputMedium = CrossbarMediums[9];
  542. // pHwDevExt->AnalogVideoInputMedium.Id = pHwDevExt->DriverMediumInstanceCount;
  543. //
  544. // Set the header
  545. //
  546. StreamHeader.NumDevPropArrayEntries = NUMBER_OF_ADAPTER_PROPERTY_SETS;
  547. StreamHeader.DevicePropertiesArray = (PKSPROPERTY_SET) AdapterPropertyTable;
  548. *pstrhdr = StreamHeader;
  549. //
  550. // stuff the contents of each HW_STREAM_INFORMATION struct
  551. //
  552. for (j = 0; j < DRIVER_STREAM_COUNT; j++) {
  553. *pstrinfo++ = Streams[j].hwStreamInfo;
  554. }
  555. }
  556. /*
  557. ** AdapterReceivePacket()
  558. **
  559. ** Main entry point for receiving adapter based request SRBs. This routine
  560. ** will always be called at Passive level.
  561. **
  562. ** Note: This is an asyncronous entry point. The request does not necessarily
  563. ** complete on return from this function, the request only completes when a
  564. ** StreamClassDeviceNotification on this request block, of type
  565. ** DeviceRequestComplete, is issued.
  566. **
  567. ** Arguments:
  568. **
  569. ** pSrb - Pointer to the STREAM_REQUEST_BLOCK
  570. ** pSrb->HwDeviceExtension - will be the hardware device extension for
  571. ** as initialised in HwInitialise
  572. **
  573. ** Returns:
  574. **
  575. ** Side Effects: none
  576. */
  577. VOID
  578. STREAMAPI
  579. AdapterReceivePacket(
  580. IN PHW_STREAM_REQUEST_BLOCK pSrb
  581. )
  582. {
  583. PHW_DEVICE_EXTENSION pHwDevExt = ((PHW_DEVICE_EXTENSION)pSrb->HwDeviceExtension);
  584. BOOL Busy;
  585. DEBUG_ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);
  586. DbgLogTrace(("TestCap: Receiving Adapter SRB %8x, %x\n", pSrb, pSrb->Command));
  587. // The very first time through, we need to initialize the adapter spinlock
  588. // and queue
  589. if (!pHwDevExt->AdapterQueueInitialized) {
  590. InitializeListHead (&pHwDevExt->AdapterSRBList);
  591. KeInitializeSpinLock (&pHwDevExt->AdapterSpinLock);
  592. pHwDevExt->AdapterQueueInitialized = TRUE;
  593. pHwDevExt->ProcessingAdapterSRB = FALSE;
  594. }
  595. //
  596. // If we're already processing an SRB, add it to the queue
  597. //
  598. Busy = AddToListIfBusy (
  599. pSrb,
  600. &pHwDevExt->AdapterSpinLock,
  601. &pHwDevExt->ProcessingAdapterSRB,
  602. &pHwDevExt->AdapterSRBList);
  603. if (Busy) {
  604. return;
  605. }
  606. //
  607. // This will run until the queue is empty
  608. //
  609. while (TRUE) {
  610. //
  611. // Assume success
  612. //
  613. pSrb->Status = STATUS_SUCCESS;
  614. //
  615. // determine the type of packet.
  616. //
  617. switch (pSrb->Command)
  618. {
  619. case SRB_INITIALIZE_DEVICE:
  620. // open the device
  621. HwInitialize(pSrb);
  622. break;
  623. case SRB_UNINITIALIZE_DEVICE:
  624. // close the device.
  625. HwUnInitialize(pSrb);
  626. break;
  627. case SRB_OPEN_STREAM:
  628. // open a stream
  629. AdapterOpenStream(pSrb);
  630. break;
  631. case SRB_CLOSE_STREAM:
  632. // close a stream
  633. AdapterCloseStream(pSrb);
  634. break;
  635. case SRB_GET_STREAM_INFO:
  636. //
  637. // return a block describing all the streams
  638. //
  639. AdapterStreamInfo(pSrb);
  640. break;
  641. case SRB_GET_DATA_INTERSECTION:
  642. //
  643. // Return a format, given a range
  644. //
  645. AdapterFormatFromRange(pSrb);
  646. break;
  647. case SRB_OPEN_DEVICE_INSTANCE:
  648. case SRB_CLOSE_DEVICE_INSTANCE:
  649. //
  650. // We should never get these since this is a single instance device
  651. //
  652. TRAP;
  653. pSrb->Status = STATUS_NOT_IMPLEMENTED;
  654. break;
  655. case SRB_GET_DEVICE_PROPERTY:
  656. //
  657. // Get adapter wide properties
  658. //
  659. AdapterGetProperty (pSrb);
  660. break;
  661. case SRB_SET_DEVICE_PROPERTY:
  662. //
  663. // Set adapter wide properties
  664. //
  665. AdapterSetProperty (pSrb);
  666. break;
  667. case SRB_PAGING_OUT_DRIVER:
  668. //
  669. // The driver is being paged out
  670. // Disable Interrupts if you have them!
  671. //
  672. DbgLogInfo(("'Testcap: Receiving SRB_PAGING_OUT_DRIVER -- SRB=%x\n", pSrb));
  673. break;
  674. case SRB_CHANGE_POWER_STATE:
  675. //
  676. // Changing the device power state, D0 ... D3
  677. //
  678. DbgLogInfo(("'Testcap: Receiving SRB_CHANGE_POWER_STATE ------ SRB=%x\n", pSrb));
  679. AdapterPowerState(pSrb);
  680. break;
  681. case SRB_INITIALIZATION_COMPLETE:
  682. //
  683. // Stream class has finished initialization.
  684. // Now create DShow Medium interface BLOBs.
  685. // This needs to be done at low priority since it uses the registry
  686. //
  687. DbgLogInfo(("'Testcap: Receiving SRB_INITIALIZATION_COMPLETE-- SRB=%x\n", pSrb));
  688. AdapterCompleteInitialization (pSrb);
  689. break;
  690. case SRB_UNKNOWN_DEVICE_COMMAND:
  691. default:
  692. //
  693. // this is a request that we do not understand. Indicate invalid
  694. // command and complete the request
  695. //
  696. pSrb->Status = STATUS_NOT_IMPLEMENTED;
  697. }
  698. //
  699. // Indicate back to the Stream Class that we're done with this SRB
  700. //
  701. CompleteDeviceSRB (pSrb);
  702. //
  703. // See if there's anything else on the queue
  704. //
  705. Busy = RemoveFromListIfAvailable (
  706. &pSrb,
  707. &pHwDevExt->AdapterSpinLock,
  708. &pHwDevExt->ProcessingAdapterSRB,
  709. &pHwDevExt->AdapterSRBList);
  710. if (!Busy) {
  711. break;
  712. }
  713. } // end of while there's anything in the queue
  714. }
  715. /*
  716. ** AdapterCancelPacket ()
  717. **
  718. ** Request to cancel a packet that is currently in process in the minidriver
  719. **
  720. ** Arguments:
  721. **
  722. ** pSrb - pointer to request packet to cancel
  723. **
  724. ** Returns:
  725. **
  726. ** Side Effects: none
  727. */
  728. VOID
  729. STREAMAPI
  730. AdapterCancelPacket(
  731. PHW_STREAM_REQUEST_BLOCK pSrb
  732. )
  733. {
  734. PHW_DEVICE_EXTENSION pHwDevExt = (PHW_DEVICE_EXTENSION)pSrb->HwDeviceExtension;
  735. PSTREAMEX pStrmEx;
  736. int StreamNumber;
  737. BOOL Found = FALSE;
  738. //
  739. // Run through all the streams the driver has available
  740. //
  741. for (StreamNumber = 0; !Found && (StreamNumber < DRIVER_STREAM_COUNT); StreamNumber++) {
  742. //
  743. // Check to see if the stream is in use
  744. //
  745. if (pStrmEx = (PSTREAMEX) pHwDevExt->pStrmEx[StreamNumber]) {
  746. Found = VideoQueueCancelOneSRB (
  747. pStrmEx,
  748. pSrb
  749. );
  750. } // if the stream is open
  751. } // for all streams
  752. DbgLogInfo(("TestCap: Cancelling SRB %8x Succeeded=%d\n", pSrb, Found));
  753. }
  754. /*
  755. ** AdapterTimeoutPacket()
  756. **
  757. ** This routine is called when a packet has been in the minidriver for
  758. ** too long. The adapter must decide what to do with the packet
  759. **
  760. ** Arguments:
  761. **
  762. ** pSrb - pointer to the request packet that timed out
  763. **
  764. ** Returns:
  765. **
  766. ** Side Effects: none
  767. */
  768. VOID
  769. STREAMAPI
  770. AdapterTimeoutPacket(
  771. PHW_STREAM_REQUEST_BLOCK pSrb
  772. )
  773. {
  774. //
  775. // Unlike most devices, we need to hold onto data SRBs indefinitely,
  776. // since the graph could be in a pause state indefinitely
  777. //
  778. DbgLogInfo(("TestCap: Timeout Adapter SRB %8x\n", pSrb));
  779. pSrb->TimeoutCounter = pSrb->TimeoutOriginal;
  780. }
  781. /*
  782. ** CompleteDeviceSRB ()
  783. **
  784. ** This routine is called when a packet is being completed.
  785. ** The optional second notification type is used to indicate ReadyForNext
  786. **
  787. ** Arguments:
  788. **
  789. ** pSrb - pointer to the request packet that timed out
  790. **
  791. ** Returns:
  792. **
  793. ** Side Effects:
  794. **
  795. */
  796. VOID
  797. STREAMAPI
  798. CompleteDeviceSRB (
  799. IN PHW_STREAM_REQUEST_BLOCK pSrb
  800. )
  801. {
  802. DbgLogTrace(("TestCap: Completing Adapter SRB %8x\n", pSrb));
  803. StreamClassDeviceNotification( DeviceRequestComplete, pSrb->HwDeviceExtension, pSrb);
  804. }
  805. /*
  806. ** IsEqualOrWildGUID()
  807. **
  808. ** Compares two GUIDS like IsEqualGUID(), except allows wildcard matches
  809. **
  810. ** Arguments:
  811. **
  812. ** IN GUID *g1
  813. ** IN GUID *g2
  814. **
  815. ** Returns:
  816. **
  817. ** TRUE if both GUIDs match or only one is a wildcard
  818. ** FALSE if GUIDs are different or both are wildcards
  819. **
  820. ** Side Effects: none
  821. */
  822. BOOL
  823. STREAMAPI
  824. IsEqualOrWildGUID(IN GUID *g1, IN GUID *g2)
  825. {
  826. return (IsEqualGUID(g1, g2) && !IsEqualGUID(g1, &KSDATAFORMAT_TYPE_WILDCARD)
  827. || ((IsEqualGUID(g1, &KSDATAFORMAT_TYPE_WILDCARD)
  828. || IsEqualGUID(g2, &KSDATAFORMAT_TYPE_WILDCARD))
  829. && !IsEqualGUID(g1, g2))
  830. );
  831. }
  832. /*
  833. ** AdapterCompareGUIDsAndFormatSize()
  834. **
  835. ** Checks for a match on the three GUIDs and FormatSize
  836. **
  837. ** Arguments:
  838. **
  839. ** IN DataRange1
  840. ** IN DataRange2
  841. ** BOOL fCompareFormatSize - TRUE when comparing ranges
  842. ** - FALSE when comparing formats
  843. **
  844. ** Returns:
  845. **
  846. ** TRUE if all elements match
  847. ** FALSE if any are different
  848. **
  849. ** Side Effects: none
  850. */
  851. BOOL
  852. STREAMAPI
  853. AdapterCompareGUIDsAndFormatSize(
  854. IN PKSDATARANGE DataRange1,
  855. IN PKSDATARANGE DataRange2,
  856. BOOL fCompareFormatSize
  857. )
  858. {
  859. return (
  860. IsEqualOrWildGUID (
  861. &DataRange1->MajorFormat,
  862. &DataRange2->MajorFormat) &&
  863. IsEqualOrWildGUID (
  864. &DataRange1->SubFormat,
  865. &DataRange2->SubFormat) &&
  866. IsEqualOrWildGUID (
  867. &DataRange1->Specifier,
  868. &DataRange2->Specifier) &&
  869. (fCompareFormatSize ?
  870. (DataRange1->FormatSize == DataRange2->FormatSize) : TRUE ));
  871. }
  872. /*
  873. ** MultiplyCheckOverflow()
  874. **
  875. ** Perform a 32-bit unsigned multiplication and return if the multiplication
  876. ** did not overflow.
  877. **
  878. ** Arguments:
  879. **
  880. ** a - first operand
  881. ** b - second operand
  882. ** pab - result
  883. **
  884. ** Returns:
  885. **
  886. ** TRUE - no overflow
  887. ** FALSE - overflow occurred
  888. **
  889. */
  890. BOOL
  891. MultiplyCheckOverflow (
  892. ULONG a,
  893. ULONG b,
  894. ULONG *pab
  895. )
  896. {
  897. *pab = a * b;
  898. if ((a == 0) || (((*pab) / a) == b)) {
  899. return TRUE;
  900. }
  901. return FALSE;
  902. }
  903. /*
  904. ** AdapterVerifyFormat()
  905. **
  906. ** Checks the validity of a format request by walking through the
  907. ** array of supported KSDATA_RANGEs for a given stream.
  908. **
  909. ** Arguments:
  910. **
  911. ** pKSDataFormat - pointer of a KSDATAFORMAT structure.
  912. ** StreamNumber - index of the stream being queried / opened.
  913. **
  914. ** Returns:
  915. **
  916. ** TRUE if the format is supported
  917. ** FALSE if the format cannot be suppored
  918. **
  919. ** Side Effects: none
  920. */
  921. BOOL
  922. STREAMAPI
  923. AdapterVerifyFormat(
  924. PKSDATAFORMAT pKSDataFormatToVerify,
  925. int StreamNumber
  926. )
  927. {
  928. BOOL fOK = FALSE;
  929. ULONG j;
  930. ULONG NumberOfFormatArrayEntries;
  931. PKSDATAFORMAT *pAvailableFormats;
  932. //
  933. // Check that the stream number is valid
  934. //
  935. if (StreamNumber >= DRIVER_STREAM_COUNT) {
  936. TRAP;
  937. return FALSE;
  938. }
  939. NumberOfFormatArrayEntries =
  940. Streams[StreamNumber].hwStreamInfo.NumberOfFormatArrayEntries;
  941. //
  942. // Get the pointer to the array of available formats
  943. //
  944. pAvailableFormats = Streams[StreamNumber].hwStreamInfo.StreamFormatsArray;
  945. DbgLogInfo(("TestCap: AdapterVerifyFormat, Stream=%d\n", StreamNumber));
  946. DbgLogInfo(("TestCap: FormatSize=%d\n", pKSDataFormatToVerify->FormatSize));
  947. DbgLogInfo(("TestCap: MajorFormat=%x\n", pKSDataFormatToVerify->MajorFormat));
  948. //
  949. // Walk the formats supported by the stream
  950. //
  951. for (j = 0; j < NumberOfFormatArrayEntries; j++, pAvailableFormats++) {
  952. // Check for a match on the three GUIDs and format size
  953. if (!AdapterCompareGUIDsAndFormatSize(
  954. pKSDataFormatToVerify,
  955. *pAvailableFormats,
  956. FALSE /* CompareFormatSize */ )) {
  957. continue;
  958. }
  959. //
  960. // Now that the three GUIDs match, switch on the Specifier
  961. // to do a further type-specific check
  962. //
  963. // -------------------------------------------------------------------
  964. // Specifier FORMAT_VideoInfo for VIDEOINFOHEADER
  965. // -------------------------------------------------------------------
  966. if (IsEqualGUID (&pKSDataFormatToVerify->Specifier,
  967. &KSDATAFORMAT_SPECIFIER_VIDEOINFO) &&
  968. pKSDataFormatToVerify->FormatSize >=
  969. sizeof (KS_DATAFORMAT_VIDEOINFOHEADER)) {
  970. PKS_DATAFORMAT_VIDEOINFOHEADER pDataFormatVideoInfoHeader =
  971. (PKS_DATAFORMAT_VIDEOINFOHEADER) pKSDataFormatToVerify;
  972. PKS_VIDEOINFOHEADER pVideoInfoHdrToVerify =
  973. (PKS_VIDEOINFOHEADER) &pDataFormatVideoInfoHeader->VideoInfoHeader;
  974. PKS_DATARANGE_VIDEO pKSDataRangeVideo = (PKS_DATARANGE_VIDEO) *pAvailableFormats;
  975. KS_VIDEO_STREAM_CONFIG_CAPS *pConfigCaps = &pKSDataRangeVideo->ConfigCaps;
  976. RECT rcImage;
  977. DbgLogInfo(("TestCap: AdapterVerifyFormat\n"));
  978. DbgLogInfo(("TestCap: pVideoInfoHdrToVerify=%x\n", pVideoInfoHdrToVerify));
  979. DbgLogInfo(("TestCap: KS_VIDEOINFOHEADER size=%d\n",
  980. KS_SIZE_VIDEOHEADER (pVideoInfoHdrToVerify)));
  981. DbgLogInfo(("TestCap: Width=%d Height=%d BitCount=%d\n",
  982. pVideoInfoHdrToVerify->bmiHeader.biWidth,
  983. pVideoInfoHdrToVerify->bmiHeader.biHeight,
  984. pVideoInfoHdrToVerify->bmiHeader.biBitCount));
  985. DbgLogInfo(("TestCap: biSizeImage=%d\n",
  986. pVideoInfoHdrToVerify->bmiHeader.biSizeImage));
  987. /*
  988. ** HOW BIG IS THE IMAGE REQUESTED (pseudocode follows)
  989. **
  990. ** if (IsRectEmpty (&rcTarget) {
  991. ** SetRect (&rcImage, 0, 0,
  992. ** BITMAPINFOHEADER.biWidth,
  993. BITMAPINFOHEADER.biHeight);
  994. ** }
  995. ** else {
  996. ** // Probably rendering to a DirectDraw surface,
  997. ** // where biWidth is used to expressed the "stride"
  998. ** // in units of pixels (not bytes) of the destination surface.
  999. ** // Therefore, use rcTarget to get the actual image size
  1000. **
  1001. ** rcImage = rcTarget;
  1002. ** }
  1003. */
  1004. if ((pVideoInfoHdrToVerify->rcTarget.right -
  1005. pVideoInfoHdrToVerify->rcTarget.left <= 0) ||
  1006. (pVideoInfoHdrToVerify->rcTarget.bottom -
  1007. pVideoInfoHdrToVerify->rcTarget.top <= 0)) {
  1008. rcImage.left = rcImage.top = 0;
  1009. rcImage.right = pVideoInfoHdrToVerify->bmiHeader.biWidth;
  1010. rcImage.bottom = pVideoInfoHdrToVerify->bmiHeader.biHeight;
  1011. }
  1012. else {
  1013. rcImage = pVideoInfoHdrToVerify->rcTarget;
  1014. }
  1015. //
  1016. // Check that bmiHeader.biSize is valid since we use it later.
  1017. //
  1018. {
  1019. ULONG VideoHeaderSize = KS_SIZE_VIDEOHEADER (
  1020. pVideoInfoHdrToVerify
  1021. );
  1022. ULONG DataFormatSize = FIELD_OFFSET (
  1023. KS_DATAFORMAT_VIDEOINFOHEADER, VideoInfoHeader
  1024. ) + VideoHeaderSize;
  1025. if (
  1026. VideoHeaderSize < pVideoInfoHdrToVerify->bmiHeader.biSize ||
  1027. DataFormatSize < VideoHeaderSize ||
  1028. DataFormatSize > pKSDataFormatToVerify -> FormatSize
  1029. ) {
  1030. fOK = FALSE;
  1031. break;
  1032. }
  1033. }
  1034. //
  1035. // Compute the minimum size of our buffers to validate against.
  1036. // The image synthesis routines synthesize |biHeight| rows of
  1037. // biWidth pixels in either RGB24 or UYVY. In order to ensure
  1038. // safe synthesis into the buffer, we need to know how large an
  1039. // image this will produce.
  1040. //
  1041. // I do this explicitly because of the method that the data is
  1042. // synthesized. A variation of this may or may not be necessary
  1043. // depending on the mechanism the driver in question fills the
  1044. // capture buffers. The important thing is to ensure that they
  1045. // aren't overrun during capture.
  1046. //
  1047. {
  1048. ULONG ImageSize;
  1049. if (!MultiplyCheckOverflow (
  1050. (ULONG)pVideoInfoHdrToVerify->bmiHeader.biWidth,
  1051. (ULONG)abs (pVideoInfoHdrToVerify->bmiHeader.biHeight),
  1052. &ImageSize
  1053. )) {
  1054. fOK = FALSE;
  1055. break;
  1056. }
  1057. //
  1058. // We only support KS_BI_RGB (24) and KS_BI_YUV422 (16), so
  1059. // this is valid for those formats.
  1060. //
  1061. if (!MultiplyCheckOverflow (
  1062. ImageSize,
  1063. (ULONG)(pVideoInfoHdrToVerify->bmiHeader.biBitCount / 8),
  1064. &ImageSize
  1065. )) {
  1066. fOK = FALSE;
  1067. break;
  1068. }
  1069. //
  1070. // Valid for the formats we use. Otherwise, this would be
  1071. // checked later.
  1072. //
  1073. if (pVideoInfoHdrToVerify->bmiHeader.biSizeImage <
  1074. ImageSize) {
  1075. fOK = FALSE;
  1076. break;
  1077. }
  1078. }
  1079. //
  1080. // Perform all other verification tests here!!!
  1081. //
  1082. //
  1083. // HOORAY, the format passed all of the tests, so we support it
  1084. //
  1085. fOK = TRUE;
  1086. break;
  1087. } // End of VIDEOINFOHEADER specifier
  1088. // -------------------------------------------------------------------
  1089. // Specifier FORMAT_AnalogVideo for KS_ANALOGVIDEOINFO
  1090. // -------------------------------------------------------------------
  1091. else if (IsEqualGUID (&pKSDataFormatToVerify->Specifier,
  1092. &KSDATAFORMAT_SPECIFIER_ANALOGVIDEO) &&
  1093. pKSDataFormatToVerify->FormatSize >=
  1094. sizeof (KS_DATARANGE_ANALOGVIDEO)) {
  1095. //
  1096. // For analog video, the DataRange and DataFormat
  1097. // are identical, so just copy the whole structure
  1098. //
  1099. PKS_DATARANGE_ANALOGVIDEO DataRangeVideo =
  1100. (PKS_DATARANGE_ANALOGVIDEO) *pAvailableFormats;
  1101. //
  1102. // Perform all other verification tests here!!!
  1103. //
  1104. fOK = TRUE;
  1105. break;
  1106. } // End of KS_ANALOGVIDEOINFO specifier
  1107. // -------------------------------------------------------------------
  1108. // Specifier FORMAT_VBI for KS_VIDEO_VBI
  1109. // -------------------------------------------------------------------
  1110. else if (IsEqualGUID (&pKSDataFormatToVerify->Specifier,
  1111. &KSDATAFORMAT_SPECIFIER_VBI) &&
  1112. pKSDataFormatToVerify->FormatSize >=
  1113. sizeof (KS_DATAFORMAT_VBIINFOHEADER))
  1114. {
  1115. //
  1116. // Do some VBI-specific tests
  1117. //
  1118. PKS_DATAFORMAT_VBIINFOHEADER pKSVBIDataFormat;
  1119. DbgLogInfo(("Testcap: This is a VBIINFOHEADER format pin.\n" ));
  1120. pKSVBIDataFormat = (PKS_DATAFORMAT_VBIINFOHEADER)pKSDataFormatToVerify;
  1121. //
  1122. // Check VideoStandard, we only support NTSC_M
  1123. //
  1124. if (KS_AnalogVideo_NTSC_M
  1125. == pKSVBIDataFormat->VBIInfoHeader.VideoStandard)
  1126. {
  1127. fOK = TRUE;
  1128. break;
  1129. }
  1130. else
  1131. {
  1132. DbgLogError(
  1133. ("Testcap: AdapterVerifyFormat : VideoStandard(%d) != NTSC_M\n",
  1134. pKSVBIDataFormat->VBIInfoHeader.VideoStandard));
  1135. }
  1136. }
  1137. // -------------------------------------------------------------------
  1138. // Type FORMAT_NABTS for NABTS pin
  1139. // -------------------------------------------------------------------
  1140. else if (IsEqualGUID (&pKSDataFormatToVerify->SubFormat,
  1141. &KSDATAFORMAT_SUBTYPE_NABTS))
  1142. {
  1143. fOK = TRUE;
  1144. break;
  1145. }
  1146. // -------------------------------------------------------------------
  1147. // for CC pin
  1148. // -------------------------------------------------------------------
  1149. else if (IsEqualGUID (&pKSDataFormatToVerify->SubFormat,
  1150. &KSDATAFORMAT_SUBTYPE_CC))
  1151. {
  1152. fOK = TRUE;
  1153. break;
  1154. }
  1155. } // End of loop on all formats for this stream
  1156. return fOK;
  1157. }
  1158. /*
  1159. ** AdapterFormatFromRange()
  1160. **
  1161. ** Produces a DATAFORMAT given a DATARANGE.
  1162. **
  1163. ** Think of a DATARANGE as a multidimensional space of all of the possible image
  1164. ** sizes, cropping, scaling, and framerate possibilities. Here, the caller
  1165. ** is saying "Out of this set of possibilities, could you verify that my
  1166. ** request is acceptable?". The resulting singular output is a DATAFORMAT.
  1167. ** Note that each different colorspace (YUV vs RGB8 vs RGB24)
  1168. ** must be represented as a separate DATARANGE.
  1169. **
  1170. ** Generally, the resulting DATAFORMAT will be immediately used to open a stream
  1171. ** in that format.
  1172. **
  1173. ** Arguments:
  1174. **
  1175. ** IN PHW_STREAM_REQUEST_BLOCK pSrb
  1176. **
  1177. ** Returns:
  1178. **
  1179. ** TRUE if the format is supported
  1180. ** FALSE if the format cannot be suppored
  1181. **
  1182. ** Side Effects: none
  1183. */
  1184. BOOL
  1185. STREAMAPI
  1186. AdapterFormatFromRange(
  1187. IN PHW_STREAM_REQUEST_BLOCK pSrb
  1188. )
  1189. {
  1190. PSTREAM_DATA_INTERSECT_INFO IntersectInfo;
  1191. PKSDATARANGE DataRange;
  1192. BOOL OnlyWantsSize;
  1193. BOOL MatchFound = FALSE;
  1194. ULONG FormatSize;
  1195. ULONG StreamNumber;
  1196. ULONG j;
  1197. ULONG NumberOfFormatArrayEntries;
  1198. PKSDATAFORMAT *pAvailableFormats;
  1199. IntersectInfo = pSrb->CommandData.IntersectInfo;
  1200. StreamNumber = IntersectInfo->StreamNumber;
  1201. DataRange = IntersectInfo->DataRange;
  1202. //
  1203. // Check that the stream number is valid
  1204. //
  1205. if (StreamNumber >= DRIVER_STREAM_COUNT) {
  1206. pSrb->Status = STATUS_NOT_IMPLEMENTED;
  1207. TRAP;
  1208. return FALSE;
  1209. }
  1210. NumberOfFormatArrayEntries =
  1211. Streams[StreamNumber].hwStreamInfo.NumberOfFormatArrayEntries;
  1212. //
  1213. // Get the pointer to the array of available formats
  1214. //
  1215. pAvailableFormats = Streams[StreamNumber].hwStreamInfo.StreamFormatsArray;
  1216. //
  1217. // Is the caller trying to get the format, or the size of the format?
  1218. //
  1219. OnlyWantsSize = (IntersectInfo->SizeOfDataFormatBuffer == sizeof(ULONG));
  1220. //
  1221. // Walk the formats supported by the stream searching for a match
  1222. // of the three GUIDs which together define a DATARANGE
  1223. //
  1224. for (j = 0; j < NumberOfFormatArrayEntries; j++, pAvailableFormats++) {
  1225. if (!AdapterCompareGUIDsAndFormatSize(
  1226. DataRange,
  1227. *pAvailableFormats,
  1228. TRUE /* CompareFormatSize */)) {
  1229. continue;
  1230. }
  1231. //
  1232. // Now that the three GUIDs match, do a further type-specific check
  1233. //
  1234. // -------------------------------------------------------------------
  1235. // Specifier FORMAT_VideoInfo for VIDEOINFOHEADER
  1236. // -------------------------------------------------------------------
  1237. if (IsEqualGUID (&DataRange->Specifier,
  1238. &KSDATAFORMAT_SPECIFIER_VIDEOINFO)) {
  1239. PKS_DATARANGE_VIDEO DataRangeVideoToVerify =
  1240. (PKS_DATARANGE_VIDEO) DataRange;
  1241. PKS_DATARANGE_VIDEO DataRangeVideo =
  1242. (PKS_DATARANGE_VIDEO) *pAvailableFormats;
  1243. PKS_DATAFORMAT_VIDEOINFOHEADER DataFormatVideoInfoHeaderOut;
  1244. //
  1245. // Check that the other fields match
  1246. //
  1247. if ((DataRangeVideoToVerify->bFixedSizeSamples != DataRangeVideo->bFixedSizeSamples) ||
  1248. (DataRangeVideoToVerify->bTemporalCompression != DataRangeVideo->bTemporalCompression) ||
  1249. (DataRangeVideoToVerify->StreamDescriptionFlags != DataRangeVideo->StreamDescriptionFlags) ||
  1250. (DataRangeVideoToVerify->MemoryAllocationFlags != DataRangeVideo->MemoryAllocationFlags) ||
  1251. (RtlCompareMemory (&DataRangeVideoToVerify->ConfigCaps,
  1252. &DataRangeVideo->ConfigCaps,
  1253. sizeof (KS_VIDEO_STREAM_CONFIG_CAPS)) !=
  1254. sizeof (KS_VIDEO_STREAM_CONFIG_CAPS)))
  1255. {
  1256. continue;
  1257. }
  1258. //
  1259. // KS_SIZE_VIDEOHEADER() below is relying on bmiHeader.biSize from
  1260. // the caller's data range. This **MUST** be validated; the
  1261. // extended bmiHeader size (biSize) must not extend past the end
  1262. // of the range buffer. Possible arithmetic overflow is also
  1263. // checked for.
  1264. //
  1265. {
  1266. ULONG VideoHeaderSize = KS_SIZE_VIDEOHEADER (
  1267. &DataRangeVideoToVerify->VideoInfoHeader
  1268. );
  1269. ULONG DataRangeSize =
  1270. FIELD_OFFSET (KS_DATARANGE_VIDEO, VideoInfoHeader) +
  1271. VideoHeaderSize;
  1272. //
  1273. // Check that biSize does not extend past the buffer. The
  1274. // first two checks are for arithmetic overflow on the
  1275. // operations to compute the alleged size. (On unsigned
  1276. // math, a+b < a iff an arithmetic overflow occurred).
  1277. //
  1278. if (
  1279. VideoHeaderSize < DataRangeVideoToVerify->
  1280. VideoInfoHeader.bmiHeader.biSize ||
  1281. DataRangeSize < VideoHeaderSize ||
  1282. DataRangeSize > DataRangeVideoToVerify ->
  1283. DataRange.FormatSize
  1284. ) {
  1285. pSrb->Status = STATUS_INVALID_PARAMETER;
  1286. return FALSE;
  1287. }
  1288. }
  1289. // MATCH FOUND!
  1290. MatchFound = TRUE;
  1291. FormatSize = sizeof (KSDATAFORMAT) +
  1292. KS_SIZE_VIDEOHEADER (&DataRangeVideoToVerify->VideoInfoHeader);
  1293. if (OnlyWantsSize) {
  1294. break;
  1295. }
  1296. // Caller wants the full data format
  1297. if (IntersectInfo->SizeOfDataFormatBuffer < FormatSize) {
  1298. pSrb->Status = STATUS_BUFFER_TOO_SMALL;
  1299. return FALSE;
  1300. }
  1301. // Copy over the KSDATAFORMAT, followed by the
  1302. // actual VideoInfoHeader
  1303. DataFormatVideoInfoHeaderOut = (PKS_DATAFORMAT_VIDEOINFOHEADER) IntersectInfo->DataFormatBuffer;
  1304. // Copy over the KSDATAFORMAT
  1305. RtlCopyMemory(
  1306. &DataFormatVideoInfoHeaderOut->DataFormat,
  1307. &DataRangeVideoToVerify->DataRange,
  1308. sizeof (KSDATARANGE));
  1309. DataFormatVideoInfoHeaderOut->DataFormat.FormatSize = FormatSize;
  1310. // Copy over the callers requested VIDEOINFOHEADER
  1311. RtlCopyMemory(
  1312. &DataFormatVideoInfoHeaderOut->VideoInfoHeader,
  1313. &DataRangeVideoToVerify->VideoInfoHeader,
  1314. KS_SIZE_VIDEOHEADER (&DataRangeVideoToVerify->VideoInfoHeader));
  1315. // Calculate biSizeImage for this request, and put the result in both
  1316. // the biSizeImage field of the bmiHeader AND in the SampleSize field
  1317. // of the DataFormat.
  1318. //
  1319. // Note that for compressed sizes, this calculation will probably not
  1320. // be just width * height * bitdepth
  1321. DataFormatVideoInfoHeaderOut->VideoInfoHeader.bmiHeader.biSizeImage =
  1322. DataFormatVideoInfoHeaderOut->DataFormat.SampleSize =
  1323. KS_DIBSIZE(DataFormatVideoInfoHeaderOut->VideoInfoHeader.bmiHeader);
  1324. //
  1325. // Perform other validation such as cropping and scaling checks
  1326. //
  1327. break;
  1328. } // End of VIDEOINFOHEADER specifier
  1329. // -------------------------------------------------------------------
  1330. // Specifier FORMAT_AnalogVideo for KS_ANALOGVIDEOINFO
  1331. // -------------------------------------------------------------------
  1332. else if (IsEqualGUID (&DataRange->Specifier,
  1333. &KSDATAFORMAT_SPECIFIER_ANALOGVIDEO)) {
  1334. //
  1335. // For analog video, the DataRange and DataFormat
  1336. // are identical, so just copy the whole structure
  1337. //
  1338. PKS_DATARANGE_ANALOGVIDEO DataRangeVideo =
  1339. (PKS_DATARANGE_ANALOGVIDEO) *pAvailableFormats;
  1340. // MATCH FOUND!
  1341. MatchFound = TRUE;
  1342. FormatSize = sizeof (KS_DATARANGE_ANALOGVIDEO);
  1343. if (OnlyWantsSize) {
  1344. break;
  1345. }
  1346. // Caller wants the full data format
  1347. if (IntersectInfo->SizeOfDataFormatBuffer < FormatSize) {
  1348. pSrb->Status = STATUS_BUFFER_TOO_SMALL;
  1349. return FALSE;
  1350. }
  1351. RtlCopyMemory(
  1352. IntersectInfo->DataFormatBuffer,
  1353. DataRangeVideo,
  1354. sizeof (KS_DATARANGE_ANALOGVIDEO));
  1355. ((PKSDATAFORMAT)IntersectInfo->DataFormatBuffer)->FormatSize = FormatSize;
  1356. break;
  1357. } // End of KS_ANALOGVIDEOINFO specifier
  1358. // -------------------------------------------------------------------
  1359. // Specifier FORMAT_VBI for KS_VIDEO_VBI
  1360. // -------------------------------------------------------------------
  1361. else if (IsEqualGUID (&DataRange->Specifier,
  1362. &KSDATAFORMAT_SPECIFIER_VBI))
  1363. {
  1364. PKS_DATARANGE_VIDEO_VBI pDataRangeVBI =
  1365. (PKS_DATARANGE_VIDEO_VBI)*pAvailableFormats;
  1366. PKS_DATAFORMAT_VBIINFOHEADER InterVBIHdr =
  1367. (PKS_DATAFORMAT_VBIINFOHEADER)IntersectInfo->DataFormatBuffer;
  1368. // MATCH FOUND!
  1369. MatchFound = TRUE;
  1370. FormatSize = sizeof (KS_DATAFORMAT_VBIINFOHEADER);
  1371. // Is the caller trying to get the format, or the size of it?
  1372. if (OnlyWantsSize)
  1373. break;
  1374. // Verify that there is enough room in the supplied buffer
  1375. // for the whole thing
  1376. if (IntersectInfo->SizeOfDataFormatBuffer < FormatSize)
  1377. {
  1378. if (IntersectInfo->SizeOfDataFormatBuffer > 0) {
  1379. DbgLogError(
  1380. ("Testcap::AdapterFormatFromRange: "
  1381. "Specifier==VBI, Buffer too small=%d vs. %d\n",
  1382. IntersectInfo->SizeOfDataFormatBuffer,
  1383. FormatSize));
  1384. }
  1385. pSrb->Status = STATUS_BUFFER_TOO_SMALL;
  1386. return FALSE;
  1387. }
  1388. // If there is room, go ahead...
  1389. RtlCopyMemory(&InterVBIHdr->DataFormat,
  1390. &pDataRangeVBI->DataRange,
  1391. sizeof (KSDATARANGE));
  1392. ((PKSDATAFORMAT)IntersectInfo->DataFormatBuffer)->FormatSize = FormatSize;
  1393. RtlCopyMemory(&InterVBIHdr->VBIInfoHeader,
  1394. &pDataRangeVBI->VBIInfoHeader,
  1395. sizeof(KS_VBIINFOHEADER));
  1396. break;
  1397. } // End of KS_VIDEO_VBI specifier
  1398. // -------------------------------------------------------------------
  1399. // Type FORMAT_NABTS for NABTS pin
  1400. // -------------------------------------------------------------------
  1401. else if (IsEqualGUID (&DataRange->SubFormat,
  1402. &KSDATAFORMAT_SUBTYPE_NABTS))
  1403. {
  1404. PKSDATARANGE pDataRange = (PKSDATARANGE)*pAvailableFormats;
  1405. // MATCH FOUND!
  1406. MatchFound = TRUE;
  1407. FormatSize = sizeof (KSDATAFORMAT);
  1408. // Is the caller trying to get the format, or the size of it?
  1409. if (OnlyWantsSize)
  1410. break;
  1411. // Verify that there is enough room in the supplied buffer
  1412. // for the whole thing
  1413. if (IntersectInfo->SizeOfDataFormatBuffer >= FormatSize)
  1414. {
  1415. RtlCopyMemory(IntersectInfo->DataFormatBuffer,
  1416. pDataRange,
  1417. FormatSize);
  1418. ((PKSDATAFORMAT)IntersectInfo->DataFormatBuffer)->FormatSize = FormatSize;
  1419. }
  1420. else
  1421. {
  1422. if (IntersectInfo->SizeOfDataFormatBuffer > 0) {
  1423. DbgLogError(
  1424. ("Testcap::AdapterFormatFromRange: "
  1425. "SubFormat==NABTS, Buffer too small=%d vs. %d\n",
  1426. IntersectInfo->SizeOfDataFormatBuffer,
  1427. FormatSize));
  1428. }
  1429. pSrb->Status = STATUS_BUFFER_TOO_SMALL;
  1430. return FALSE;
  1431. }
  1432. break;
  1433. } // End of KS_SUBTYPE_NABTS
  1434. // -------------------------------------------------------------------
  1435. // for CC pin
  1436. // -------------------------------------------------------------------
  1437. else if (IsEqualGUID (&DataRange->SubFormat,
  1438. &KSDATAFORMAT_SUBTYPE_CC))
  1439. {
  1440. PKSDATARANGE pDataRange = (PKSDATARANGE)*pAvailableFormats;
  1441. // MATCH FOUND!
  1442. MatchFound = TRUE;
  1443. FormatSize = sizeof (KSDATAFORMAT);
  1444. // Is the caller trying to get the format, or the size of it?
  1445. if (OnlyWantsSize)
  1446. break;
  1447. // Verify that there is enough room in the supplied buffer
  1448. // for the whole thing
  1449. if (IntersectInfo->SizeOfDataFormatBuffer >= FormatSize)
  1450. {
  1451. RtlCopyMemory(IntersectInfo->DataFormatBuffer,
  1452. pDataRange,
  1453. FormatSize);
  1454. ((PKSDATAFORMAT)IntersectInfo->DataFormatBuffer)->FormatSize = FormatSize;
  1455. }
  1456. else
  1457. {
  1458. if (IntersectInfo->SizeOfDataFormatBuffer > 0) {
  1459. DbgLogError(
  1460. ("Testcap::AdapterFormatFromRange: "
  1461. "SubFormat==CC, Buffer too small=%d vs. %d\n",
  1462. IntersectInfo->SizeOfDataFormatBuffer,
  1463. FormatSize));
  1464. }
  1465. pSrb->Status = STATUS_BUFFER_TOO_SMALL;
  1466. return FALSE;
  1467. }
  1468. break;
  1469. } // End of CC pin format check
  1470. else {
  1471. pSrb->Status = STATUS_NO_MATCH;
  1472. return FALSE;
  1473. }
  1474. } // End of loop on all formats for this stream
  1475. if (!MatchFound) {
  1476. pSrb->Status = STATUS_NO_MATCH;
  1477. return FALSE;
  1478. }
  1479. if (OnlyWantsSize) {
  1480. *(PULONG) IntersectInfo->DataFormatBuffer = FormatSize;
  1481. FormatSize = sizeof(ULONG);
  1482. }
  1483. pSrb->ActualBytesTransferred = FormatSize;
  1484. return TRUE;
  1485. }