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.

1916 lines
62 KiB

  1. // $Header: G:/SwDev/WDM/Video/bt848/rcs/Capmain.c 1.19 1998/05/11 23:59:54 tomz Exp $
  2. //==========================================================================;
  3. //
  4. // THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
  5. // KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
  6. // IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
  7. // PURPOSE.
  8. //
  9. // Copyright (c) 1992 - 1996 Microsoft Corporation. All Rights Reserved.
  10. //
  11. //==========================================================================;
  12. #define INITGUID
  13. #define BT848_MEDIUMS
  14. #ifdef __cplusplus
  15. extern "C" {
  16. #endif
  17. #include "strmini.h"
  18. #include "ksmedia.h"
  19. #ifdef __cplusplus
  20. }
  21. #endif
  22. #include "device.h"
  23. #include "capmain.h"
  24. #include "capstrm.h"
  25. #include "capdebug.h"
  26. #include "capprop.h"
  27. LONG PinTypes_ [MaxInpPins]; // just allocate maximum possible
  28. DWORD xtals_ [2]; // no more than 2 xtals
  29. extern PsDevice *gpPsDevice;
  30. extern BYTE *gpjBaseAddr;
  31. extern VOID *gpHwDeviceExtension;
  32. void AdapterFormatFromRange( IN PHW_STREAM_REQUEST_BLOCK pSrb );
  33. VOID ReadRegistryValues( IN PDEVICE_OBJECT PhysicalDeviceObject );
  34. inline void CompleteDeviceSRB( IN OUT PHW_STREAM_REQUEST_BLOCK pSrb );
  35. extern DWORD GetSizeHwDeviceExtension( );
  36. extern DWORD GetSizeStreamEx( );
  37. extern PsDevice *GetCurrentDevice( );
  38. extern void SetCurrentDevice( PsDevice *dev );
  39. extern BYTE *GetBase();
  40. extern void SetBase(BYTE *base);
  41. PHW_STREAM_REQUEST_BLOCK StreamIdxToSrb[4];
  42. void CheckSrbStatus( PHW_STREAM_REQUEST_BLOCK pSrb )
  43. {
  44. VideoStream StreamNumber = (VideoStream)pSrb->StreamObject->StreamNumber;
  45. DebugOut((1, " *** completing pSrb(%x) strm(%d) status(%x)\n", pSrb, StreamNumber, pSrb->Status ));
  46. switch ( pSrb->Status )
  47. {
  48. case STATUS_SUCCESS:
  49. case STATUS_CANCELLED:
  50. break;
  51. default:
  52. DebugOut((0, "*** pSrb->Status = %x\n", pSrb->Status ));
  53. DEBUG_BREAKPOINT();
  54. }
  55. }
  56. /* Function: GetRequestedSize
  57. * Purpose: Figures out what the image size should be
  58. * Input: vidHdr: KS_VIDEOINFOHEADER &
  59. * size: MSize &
  60. * Output: None
  61. */
  62. void GetRequestedSize2( const KS_VIDEOINFOHEADER2 &vidHdr, MSize &size )
  63. {
  64. Trace t("GetRequestedSize()");
  65. size.Set( vidHdr.bmiHeader.biWidth, abs(vidHdr.bmiHeader.biHeight) );
  66. MRect dst( vidHdr.rcTarget );
  67. // if writing to a DD surface maybe ?
  68. if ( !dst.IsNull() && !dst.IsEmpty() )
  69. size.Set( dst.Width(), dst.Height() );
  70. }
  71. void GetRequestedSize( const KS_VIDEOINFOHEADER &vidHdr, MSize &size )
  72. {
  73. Trace t("GetRequestedSize()");
  74. size.Set( vidHdr.bmiHeader.biWidth, abs(vidHdr.bmiHeader.biHeight) );
  75. MRect dst( vidHdr.rcTarget );
  76. // if writing to a DD surface maybe ?
  77. if ( !dst.IsNull() && !dst.IsEmpty() )
  78. size.Set( dst.Width(), dst.Height() );
  79. }
  80. /* Function: VerifyVideoStream
  81. * Purpose: Checks the paramaters passed in for opening steam
  82. * Input: vidHDR: KS_DATAFORMAT_VIDEOINFOHEADER
  83. * Output: Success or Fail
  84. */
  85. ErrorCode VerifyVideoStream( const KS_DATAFORMAT_VIDEOINFOHEADER &vidHDR )
  86. {
  87. Trace t("VerifyVideoStream()");
  88. // [WRK] - add guid for VideoInfoHeader2
  89. // simply verify that major and format are of video nature...
  90. if ( IsEqualGUID( vidHDR.DataFormat.MajorFormat, KSDATAFORMAT_TYPE_VIDEO ) &&
  91. IsEqualGUID( vidHDR.DataFormat.Specifier, KSDATAFORMAT_SPECIFIER_VIDEOINFO ) ) {
  92. MSize size;
  93. GetRequestedSize( vidHDR.VideoInfoHeader, size );
  94. // ... and here see if the subtype is one of those supported by us
  95. ColorSpace tmpCol( vidHDR.DataFormat.SubFormat );
  96. MRect dst( vidHDR.VideoInfoHeader.rcTarget );
  97. // make sure the dimentions are acceptable
  98. if ( tmpCol.IsValid() && tmpCol.CheckDimentions( size ) &&
  99. tmpCol.CheckLeftTop( dst.TopLeft() ) ) {
  100. DebugOut((1, "VerifyVideoStream succeeded\n"));
  101. return Success;
  102. }
  103. }
  104. DebugOut((0, "VerifyVideoStream failed\n"));
  105. return Fail;
  106. }
  107. ErrorCode VerifyVideoStream2( const KS_DATAFORMAT_VIDEOINFOHEADER2 &vidHDR )
  108. {
  109. Trace t("VerifyVideoStream2()");
  110. // [WRK] - add guid for VideoInfoHeader2
  111. // simply verify that major and format are of video nature...
  112. if ( IsEqualGUID( vidHDR.DataFormat.MajorFormat, KSDATAFORMAT_TYPE_VIDEO ) &&
  113. IsEqualGUID( vidHDR.DataFormat.Specifier, KSDATAFORMAT_SPECIFIER_VIDEOINFO2 ) ) {
  114. MSize size;
  115. GetRequestedSize2( vidHDR.VideoInfoHeader2, size );
  116. // ... and here see if the subtype is one of those supported by us
  117. ColorSpace tmpCol( vidHDR.DataFormat.SubFormat );
  118. MRect dst( vidHDR.VideoInfoHeader2.rcTarget );
  119. // make sure the dimentions are acceptable
  120. if ( tmpCol.IsValid() && tmpCol.CheckDimentions( size ) &&
  121. tmpCol.CheckLeftTop( dst.TopLeft() ) ) {
  122. DebugOut((1, "VerifyVideoStream2 succeeded\n"));
  123. return Success;
  124. }
  125. }
  126. DebugOut((0, "VerifyVideoStream2 failed\n"));
  127. return Fail;
  128. }
  129. /* Function: VerifyVBIStream
  130. * Purpose: Checks that VBI stream info during open is correct
  131. * Input: rKSDataFormat: KS_DATAFORMAT &
  132. * Output: ErrorCode
  133. */
  134. ErrorCode VerifyVBIStream( const KS_DATAFORMAT_VBIINFOHEADER &rKSDataFormat )
  135. {
  136. Trace t("VerifyVBIStream()");
  137. if ( IsEqualGUID( rKSDataFormat.DataFormat.MajorFormat, KSDATAFORMAT_TYPE_VBI ) &&
  138. IsEqualGUID( rKSDataFormat.DataFormat.Specifier,
  139. KSDATAFORMAT_SPECIFIER_VBI ) &&
  140. rKSDataFormat.VBIInfoHeader.StartLine == VBIStart &&
  141. rKSDataFormat.VBIInfoHeader.EndLine == VBIEnd &&
  142. rKSDataFormat.VBIInfoHeader.SamplesPerLine == VBISamples )
  143. return Success;
  144. return Fail;
  145. }
  146. /*
  147. ** DriverEntry()
  148. **
  149. ** This routine is called when an SRB_INITIALIZE_DEVICE request is received
  150. **
  151. ** Arguments:
  152. **
  153. ** Context1 and Context2
  154. **
  155. ** Returns:
  156. **
  157. ** Results of StreamClassRegisterAdapter()
  158. **
  159. ** Side Effects: none
  160. */
  161. extern "C" ULONG DriverEntry( PVOID Arg1, PVOID Arg2 )
  162. {
  163. Trace t("DriverEntry()");
  164. //
  165. // Entry points for Port Driver
  166. //
  167. HW_INITIALIZATION_DATA HwInitData;
  168. RtlZeroMemory( &HwInitData, sizeof( HwInitData ));
  169. HwInitData.HwInitializationDataSize = sizeof( HwInitData );
  170. HwInitData.HwInterrupt = (PHW_INTERRUPT)&HwInterrupt;
  171. HwInitData.HwReceivePacket = &AdapterReceivePacket;
  172. HwInitData.HwCancelPacket = &AdapterCancelPacket;
  173. HwInitData.HwRequestTimeoutHandler = &AdapterTimeoutPacket;
  174. HwInitData.DeviceExtensionSize = GetSizeHwDeviceExtension( );
  175. HwInitData.PerRequestExtensionSize = sizeof(SRB_EXTENSION);
  176. HwInitData.FilterInstanceExtensionSize = 0;
  177. // double to support alternating/interleaved
  178. HwInitData.PerStreamExtensionSize = GetSizeStreamEx( );
  179. HwInitData.BusMasterDMA = true;
  180. HwInitData.Dma24BitAddresses = FALSE;
  181. HwInitData.BufferAlignment = 4;
  182. HwInitData.TurnOffSynchronization = FALSE;
  183. HwInitData.DmaBufferSize = RISCProgramsSize;
  184. return (StreamClassRegisterAdapter(Arg1, Arg2,&HwInitData));
  185. }
  186. /******************************************************************************
  187. Adapter Based Request Handling Routines
  188. ******************************************************************************/
  189. /*
  190. ** HwInitialize()
  191. **
  192. ** This routine is called when an SRB_INITIALIZE_DEVICE request is received
  193. **
  194. ** Arguments:
  195. **
  196. ** pSrb - pointer to stream request block for the Initialize command
  197. **
  198. ** Returns:
  199. **
  200. ** Side Effects: none
  201. */
  202. BOOLEAN HwInitialize( IN OUT PHW_STREAM_REQUEST_BLOCK pSrb )
  203. {
  204. Trace t("HwInitialize()");
  205. DebugOut((1, "HwInitialize()\n"));
  206. // initialize ourselves
  207. PPORT_CONFIGURATION_INFORMATION ConfigInfo =
  208. pSrb->CommandData.ConfigInfo;
  209. gpHwDeviceExtension = ConfigInfo->HwDeviceExtension;
  210. DebugOut((0, "*** gpHwDeviceExtension = %x\n", gpHwDeviceExtension));
  211. PHW_DEVICE_EXTENSION HwDeviceExtension =
  212. (PHW_DEVICE_EXTENSION) gpHwDeviceExtension;
  213. DWORD dwBase = ConfigInfo->AccessRanges[0].RangeStart.LowPart;
  214. SetBase((BYTE *)dwBase);
  215. if ( ConfigInfo->NumberOfAccessRanges != 1 ) {
  216. DebugOut((1, "illegal config info\n"));
  217. pSrb->Status = STATUS_NO_SUCH_DEVICE;
  218. }
  219. // read info from the registry
  220. ReadXBarRegistryValues( ConfigInfo->PhysicalDeviceObject );
  221. ReadXTalRegistryValues( ConfigInfo->PhysicalDeviceObject );
  222. ReadTunerRegistryValues( ConfigInfo->PhysicalDeviceObject );
  223. HwDeviceExtension->psdevice =
  224. new ( &(HwDeviceExtension->psdevicemem) ) PsDevice( dwBase );
  225. DebugOut((0, "psdevice = %x\n", HwDeviceExtension->psdevice ));
  226. DebugOut((0, "&psdevicemem = %x\n", &HwDeviceExtension->psdevicemem ));
  227. PsDevice *adapter = HwDeviceExtension->psdevice;
  228. // save for later use when phys address if obtained
  229. SetCurrentDevice( adapter );
  230. // make sure initialization is successful
  231. if ( !adapter->InitOK() ) {
  232. DebugOut((1, "Error initializing\n"));
  233. pSrb->Status = STATUS_INSUFFICIENT_RESOURCES;
  234. }
  235. // save our PDO
  236. adapter->PDO = ConfigInfo->PhysicalDeviceObject;
  237. ConfigInfo->StreamDescriptorSize = sizeof( HW_STREAM_HEADER ) +
  238. DRIVER_STREAM_COUNT * sizeof( HW_STREAM_INFORMATION );
  239. DebugOut((1, "Exit : HwInitialize()\n"));
  240. // go to usual priority, completing the SRB at the same time
  241. StreamClassCallAtNewPriority( pSrb->StreamObject, HwDeviceExtension, LowToHigh,
  242. PHW_PRIORITY_ROUTINE( CompleteDeviceSRB ), pSrb );
  243. return (TRUE);
  244. }
  245. /*
  246. ** HwUnInitialize()
  247. **
  248. ** This routine is called when an SRB_UNINITIALIZE_DEVICE request is received
  249. **
  250. ** Arguments:
  251. **
  252. ** pSrb - pointer to stream request block for the UnInitialize command
  253. **
  254. ** Returns:
  255. **
  256. ** Side Effects: none
  257. */
  258. void HwUnInitialize( IN PHW_STREAM_REQUEST_BLOCK pSrb )
  259. {
  260. Trace t("HwUnInitialize()");
  261. PHW_DEVICE_EXTENSION HwDeviceExtension =
  262. (PHW_DEVICE_EXTENSION) pSrb->HwDeviceExtension;
  263. DebugOut((0, "HwUnInitialize - pSrb(%x)\n", pSrb));
  264. PsDevice *adapter = HwDeviceExtension->psdevice;
  265. adapter->~PsDevice();
  266. }
  267. /*
  268. ** AdapterOpenStream()
  269. **
  270. ** This routine is called when an OpenStream SRB request is received
  271. **
  272. ** Arguments:
  273. **
  274. ** pSrb - pointer to stream request block for the Open command
  275. **
  276. ** Returns:
  277. **
  278. ** Side Effects: none
  279. */
  280. VOID AdapterOpenStream( IN PHW_STREAM_REQUEST_BLOCK pSrb )
  281. {
  282. Trace t("AdapterOpenStream()");
  283. //
  284. // the stream extension structure is allocated by the stream class driver
  285. //
  286. // retrieve the device object pointer
  287. PHW_DEVICE_EXTENSION HwDeviceExtension =
  288. (PHW_DEVICE_EXTENSION) pSrb->HwDeviceExtension;
  289. PsDevice *adapter = HwDeviceExtension->psdevice;
  290. VideoStream StreamNumber = (VideoStream)pSrb->StreamObject->StreamNumber;
  291. StreamIdxToSrb[StreamNumber] = pSrb;
  292. DebugOut((1, "AdapterOpenStream(%d) - pSrb(%x)\n", StreamNumber, pSrb));
  293. // [STRM] [!!!]
  294. //if ( !( StreamNumber >= VS_Field1 && StreamNumber <= DRIVER_STREAM_COUNT ) ) {
  295. // pSrb->Status = STATUS_INVALID_PARAMETER; // ?change to the proper error code?
  296. // return;
  297. //}
  298. if ( StreamNumber == STREAM_IDX_ANALOG ) // [TMZ] [!!] was 3
  299. {
  300. pSrb->StreamObject->ReceiveDataPacket = AnalogReceiveDataPacket;
  301. pSrb->StreamObject->ReceiveControlPacket = AnalogReceiveCtrlPacket;
  302. return; // nothing to do for the analog stream
  303. }
  304. PSTREAMEX pStrmEx = (PSTREAMEX)pSrb->StreamObject->HwStreamExtension;
  305. RtlZeroMemory( &pStrmEx->FrameInfo, sizeof( pStrmEx->FrameInfo ) );
  306. pStrmEx->StreamNumber = StreamNumber;
  307. // size of the media specific data
  308. UINT MediaSpecific = sizeof( KS_FRAME_INFO );
  309. // Always open VBI stream as Alternating fields
  310. if ( StreamNumber == STREAM_IDX_VBI )
  311. {
  312. const KS_DATAFORMAT_VBIINFOHEADER &rKSVBIDataFormat =
  313. *(PKS_DATAFORMAT_VBIINFOHEADER) pSrb->CommandData.OpenFormat;
  314. if ( VerifyVBIStream( rKSVBIDataFormat ) != Success )
  315. {
  316. DebugOut((0, "*** VerifyVBIStream failed - aborting\n"));
  317. pSrb->Status = STATUS_INVALID_PARAMETER; // ?change to the proper error code?
  318. return;
  319. }
  320. if ( adapter->OpenVBIChannel( pStrmEx ) != Success )
  321. {
  322. DebugOut((0, "*** OpenVBIChannel failed - aborting\n"));
  323. pSrb->Status = STATUS_INVALID_PARAMETER; // ?change to the proper error code?
  324. return;
  325. }
  326. VBIAlterChannel *chan = (VBIAlterChannel *)pStrmEx->videochannel;
  327. //chan->pStrmEx = pStrmEx;
  328. chan->SetVidHdr( rKSVBIDataFormat );
  329. MediaSpecific = sizeof( KS_VBI_FRAME_INFO );
  330. }
  331. else
  332. {
  333. // is it where the size, fourcc, etc. are specified ? they should be settable
  334. // via properies sets
  335. const KS_DATAFORMAT_VIDEOINFOHEADER &rKSDataFormat = *(PKS_DATAFORMAT_VIDEOINFOHEADER) pSrb->CommandData.OpenFormat;
  336. const KS_VIDEOINFOHEADER &rVideoInfoHdrRequested = rKSDataFormat.VideoInfoHeader;
  337. const KS_DATAFORMAT_VIDEOINFOHEADER2 &rKSDataFormat2 = *(PKS_DATAFORMAT_VIDEOINFOHEADER2) pSrb->CommandData.OpenFormat;
  338. const KS_VIDEOINFOHEADER2 &rVideoInfoHdrRequested2 = rKSDataFormat2.VideoInfoHeader2;
  339. DebugOut((1, "AdapterOpenStream\n"));
  340. if ( IsEqualGUID( rKSDataFormat.DataFormat.Specifier, KSDATAFORMAT_SPECIFIER_VIDEOINFO ) )
  341. {
  342. DebugOut((1, "StreamNumber=%d\n", pSrb->StreamObject->StreamNumber));
  343. DebugOut((1, "FormatSize=%d\n", rKSDataFormat.DataFormat.FormatSize));
  344. DebugOut((1, "MajorFormat=%x\n", rKSDataFormat.DataFormat.MajorFormat));
  345. DebugOut((1, "pVideoInfoHdrRequested=%x\n", &rVideoInfoHdrRequested));
  346. DebugOut((1, "Bpp =%d\n", rVideoInfoHdrRequested.bmiHeader.biBitCount ) );
  347. DebugOut((1, "Width =%d\n", rVideoInfoHdrRequested.bmiHeader.biWidth));
  348. DebugOut((1, "Height =%d\n", rVideoInfoHdrRequested.bmiHeader.biHeight));
  349. DebugOut((1, "biSizeImage =%d\n", rVideoInfoHdrRequested.bmiHeader.biSizeImage));
  350. if ( VerifyVideoStream( rKSDataFormat ) != Success )
  351. {
  352. pSrb->Status = STATUS_INVALID_PARAMETER; // ?change to the proper error code?
  353. return;
  354. }
  355. }
  356. else
  357. {
  358. DebugOut((1, "StreamNumber=%d\n", pSrb->StreamObject->StreamNumber));
  359. DebugOut((1, "FormatSize=%d\n", rKSDataFormat2.DataFormat.FormatSize));
  360. DebugOut((1, "MajorFormat=%x\n", rKSDataFormat2.DataFormat.MajorFormat));
  361. DebugOut((1, "pVideoInfoHdrRequested2=%x\n", &rVideoInfoHdrRequested2));
  362. DebugOut((1, "Bpp =%d\n", rVideoInfoHdrRequested2.bmiHeader.biBitCount ) );
  363. DebugOut((1, "Width =%d\n", rVideoInfoHdrRequested2.bmiHeader.biWidth));
  364. DebugOut((1, "Height =%d\n", rVideoInfoHdrRequested2.bmiHeader.biHeight));
  365. DebugOut((1, "biSizeImage =%d\n", rVideoInfoHdrRequested2.bmiHeader.biSizeImage));
  366. if ( VerifyVideoStream2( rKSDataFormat2 ) != Success )
  367. {
  368. pSrb->Status = STATUS_INVALID_PARAMETER; // ?change to the proper error code?
  369. return;
  370. }
  371. }
  372. // at this point have to see what type of channel is to be opened:
  373. // single field, alternating or interleaved
  374. // algorithm is like this:
  375. // 1. look at the video format Specifier guid. If it's a infoheader2, it
  376. // will tell us type of stream to open.
  377. // 2. else look at the vertical size to decide single field vs. interleaved
  378. if ( IsEqualGUID( rKSDataFormat.DataFormat.Specifier, KSDATAFORMAT_SPECIFIER_VIDEOINFO ) )
  379. {
  380. MSize size;
  381. GetRequestedSize( rVideoInfoHdrRequested, size );
  382. // different video standards have different vertical sizes
  383. int threshold = adapter->GetFormat() == VFormat_NTSC ? 240 : 288;
  384. if ( size.cy > threshold )
  385. {
  386. if ( adapter->OpenInterChannel( pStrmEx, StreamNumber ) != Success )
  387. {
  388. pSrb->Status = STATUS_INVALID_PARAMETER; // ?change to the proper error code?
  389. return;
  390. }
  391. }
  392. else
  393. {
  394. if ( adapter->OpenChannel( pStrmEx, StreamNumber ) != Success )
  395. {
  396. pSrb->Status = STATUS_INVALID_PARAMETER; // ?change to the proper error code?
  397. return;
  398. }
  399. }
  400. VideoChannel *chan = (VideoChannel *)pStrmEx->videochannel;
  401. //chan->pStrmEx = pStrmEx;
  402. chan->SetVidHdr( rVideoInfoHdrRequested );
  403. }
  404. else if ( IsEqualGUID( rKSDataFormat2.DataFormat.Specifier, KSDATAFORMAT_SPECIFIER_VIDEOINFO2 ) )
  405. {
  406. MSize size;
  407. GetRequestedSize2( rVideoInfoHdrRequested2, size );
  408. // different video standards have different vertical sizes
  409. int threshold = adapter->GetFormat() == VFormat_NTSC ? 240 : 288;
  410. if ( size.cy > threshold )
  411. {
  412. if ( adapter->OpenInterChannel( pStrmEx, StreamNumber ) != Success )
  413. {
  414. pSrb->Status = STATUS_INVALID_PARAMETER; // ?change to the proper error code?
  415. return;
  416. }
  417. }
  418. else
  419. {
  420. if ( adapter->OpenChannel( pStrmEx, StreamNumber ) != Success )
  421. {
  422. pSrb->Status = STATUS_INVALID_PARAMETER; // ?change to the proper error code?
  423. return;
  424. }
  425. }
  426. VideoChannel *chan = (VideoChannel *)pStrmEx->videochannel;
  427. //chan->pStrmEx = pStrmEx;
  428. chan->SetVidHdr2( rVideoInfoHdrRequested2 );
  429. }
  430. else
  431. {
  432. if ( adapter->OpenInterChannel( pStrmEx, StreamNumber ) != Success )
  433. {
  434. pSrb->Status = STATUS_INVALID_PARAMETER; // ?change to the proper error code?
  435. return;
  436. }
  437. if ( adapter->OpenAlterChannel( pStrmEx, StreamNumber ) != Success )
  438. {
  439. pSrb->Status = STATUS_INVALID_PARAMETER; // ?change to the proper error code?
  440. return;
  441. }
  442. // [WRK] - check the height of the image for alter channel !> threshold
  443. VideoChannel *chan = (VideoChannel *)pStrmEx->videochannel;
  444. //chan->pStrmEx = pStrmEx;
  445. chan->SetVidHdr( rVideoInfoHdrRequested );
  446. }
  447. }
  448. #ifdef ENABLE_DDRAW_STUFF
  449. //TODO: should we check to see what kind of stream type this is?
  450. if( OpenKernelDirectDraw( pSrb ) )
  451. {
  452. OpenKernelDDrawSurfaceHandle( pSrb );
  453. RegisterForDirectDrawEvents( pSrb );
  454. }
  455. #endif
  456. // the structure of the driver is such that a single callback could be used
  457. // for all stream requests. But the code below could be used to supply
  458. // different entry points for different streams
  459. pSrb->StreamObject->ReceiveDataPacket = VideoReceiveDataPacket;
  460. pSrb->StreamObject->ReceiveControlPacket = VideoReceiveCtrlPacket;
  461. pSrb->StreamObject->Dma = true;
  462. pSrb->StreamObject->Allocator = Streams[StreamNumber].hwStreamObject.Allocator;
  463. //
  464. // The PIO flag must be set when the mini driver will be accessing the data
  465. // buffers passed in using logical addressing
  466. //
  467. pSrb->StreamObject->Pio = true;
  468. pSrb->StreamObject->StreamHeaderMediaSpecific = MediaSpecific;
  469. pSrb->StreamObject->HwClockObject.ClockSupportFlags = 0;
  470. pSrb->StreamObject->HwClockObject.HwClockFunction = 0;
  471. DebugOut((1, "AdapterOpenStream Exit\n"));
  472. }
  473. /*
  474. ** AdapterCloseStream()
  475. **
  476. ** Close the requested data stream
  477. **
  478. ** Arguments:
  479. **
  480. ** pSrb the request block requesting to close the stream
  481. **
  482. ** Returns:
  483. **
  484. ** Side Effects: none
  485. */
  486. VOID AdapterCloseStream( PHW_STREAM_REQUEST_BLOCK pSrb )
  487. {
  488. Trace t("AdapterCloseStream()");
  489. PHW_DEVICE_EXTENSION HwDeviceExtension =
  490. (PHW_DEVICE_EXTENSION) pSrb->HwDeviceExtension;
  491. PsDevice *adapter = HwDeviceExtension->psdevice;
  492. VideoChannel *chan = (VideoChannel *)((PSTREAMEX)pSrb->StreamObject->HwStreamExtension)->videochannel;
  493. VideoStream StreamNumber = (VideoStream)pSrb->StreamObject->StreamNumber;
  494. DebugOut((1, "AdapterCloseStream(%d) - pSrb(%x)\n", StreamNumber, pSrb));
  495. if ( !( StreamNumber >= 0 && StreamNumber < DRIVER_STREAM_COUNT ) ) {
  496. DebugOut((0, " AdapterCloseStream - failed to close stream %d\n", StreamNumber));
  497. DEBUG_BREAKPOINT();
  498. pSrb->Status = STATUS_INVALID_PARAMETER; // ?change to the proper error code?
  499. return;
  500. }
  501. if ( StreamNumber == STREAM_IDX_ANALOG ) // nothing to close for analog
  502. {
  503. DebugOut((1, " AdapterCloseStream - doing nothing, stream (%d) was assumed to be analog\n", StreamNumber));
  504. return;
  505. }
  506. #ifdef ENABLE_DDRAW_STUFF
  507. //TODO: should we check to see what kind of stream type this is?
  508. UnregisterForDirectDrawEvents( pSrb );
  509. CloseKernelDDrawSurfaceHandle( pSrb );
  510. CloseKernelDirectDraw( pSrb );
  511. #endif
  512. // CloseChannel() has a bit of ugly code to take care of paired channels
  513. adapter->CloseChannel( chan );
  514. }
  515. /*
  516. ** AdapterStreamInfo()
  517. **
  518. ** Returns the information of all streams that are supported by the
  519. ** mini-driver
  520. **
  521. ** Arguments:
  522. **
  523. ** pSrb - Pointer to the STREAM_REQUEST_BLOCK
  524. ** pSrb->HwDeviceExtension - will be the hardware device extension for
  525. ** as initialised in HwInitialise
  526. **
  527. ** Returns:
  528. **
  529. ** Side Effects: none
  530. */
  531. VOID AdapterStreamInfo( PHW_STREAM_REQUEST_BLOCK pSrb )
  532. {
  533. Trace t("AdapterStreamInfo()");
  534. //
  535. // pick up the pointer to header which preceeds the stream info structs
  536. //
  537. PHW_STREAM_HEADER pstrhdr =
  538. (PHW_STREAM_HEADER)&(pSrb->CommandData.StreamBuffer->StreamHeader);
  539. //
  540. // pick up the pointer to the stream information data structure
  541. //
  542. PHW_STREAM_INFORMATION pstrinfo =
  543. (PHW_STREAM_INFORMATION)&(pSrb->CommandData.StreamBuffer->StreamInfo);
  544. //
  545. // verify that the buffer is large enough to hold our return data
  546. //
  547. DEBUG_ASSERT( pSrb->NumberOfBytesToTransfer >=
  548. sizeof( HW_STREAM_HEADER ) +
  549. sizeof( HW_STREAM_INFORMATION ) * DRIVER_STREAM_COUNT );
  550. //
  551. // Set the header
  552. //
  553. StreamHeader.NumDevPropArrayEntries = NUMBER_OF_ADAPTER_PROPERTY_SETS;
  554. StreamHeader.DevicePropertiesArray = (PKSPROPERTY_SET) AdapterPropertyTable;
  555. *pstrhdr = StreamHeader;
  556. //
  557. // stuff the contents of each HW_STREAM_INFORMATION struct
  558. //
  559. for ( int j = 0; j < DRIVER_STREAM_COUNT; j++ ) {
  560. *pstrinfo++ = Streams[j].hwStreamInfo;
  561. }
  562. }
  563. #ifdef HAUPPAUGEI2CPROVIDER
  564. // new private members of PsDevice for Hauppauge I2C Provider:
  565. // LARGE_INTEGER LastI2CAccessTime;
  566. // DWORD dwExpiredCookie = 0;
  567. //
  568. //
  569. /* Method: PsDevice::I2COpen
  570. * Purpose: Tries to allocate I2C port to the caller
  571. */
  572. NTSTATUS STDMETHODCALLTYPE PsDevice::I2COpen( PDEVICE_OBJECT pdo, ULONG ToOpen, PI2CControl ctrl )
  573. {
  574. Trace t("PsDevice::I2COpen()");
  575. DebugOut((1, "*** pdo->DeviceExtension = %x\n", pdo->DeviceExtension));
  576. LARGE_INTEGER CurTime;
  577. // need a way to obtain the device pointer
  578. PsDevice *adapter = GetCurrentDevice();
  579. KeQuerySystemTime( &CurTime );
  580. ctrl->Status = I2C_STATUS_NOERROR;
  581. // cookie is not NULL if I2C is open
  582. if ( ToOpen && adapter->dwCurCookie_ ) {
  583. // Check time stamp against current time to detect if current Cookie has timed out.
  584. // If it has remember the last timed out cookie and grant the new requestor access.
  585. if ( ( adapter->dwI2CClientTimeout != 0 ) && ( (CurTime - adapter->LastI2CAccessTime) > adapter->dwI2CClientTimeout ) ) {
  586. adapter->dwExpiredCookie = adapter->dwCurCookie_;
  587. } else {
  588. ctrl->dwCookie = 0;
  589. return STATUS_INVALID_HANDLE;
  590. }
  591. }
  592. // want to close ?
  593. if ( !ToOpen ) {
  594. if ( adapter->dwCurCookie_ == ctrl->dwCookie ) {
  595. adapter->dwCurCookie_ = 0;
  596. ctrl->dwCookie = 0;
  597. return STATUS_SUCCESS;
  598. } else {
  599. if ( (adapter->dwExpiredCookie != 0 ) && (adapter->dwExpiredCookie == ctrl->dwCookie ) ) {
  600. ctrl->Status = I2C_STATUS_ERROR;
  601. } else {
  602. ctrl->dwCookie = 0;
  603. ctrl->Status = I2C_STATUS_NOERROR;
  604. }
  605. return STATUS_INVALID_HANDLE;
  606. }
  607. }
  608. adapter->dwCurCookie_ = CurTime.LowPart;
  609. adapter->LastI2CAccessTime = CurTime;
  610. ctrl->dwCookie = adapter->dwCurCookie_;
  611. ctrl->ClockRate = 100000;
  612. return STATUS_SUCCESS;
  613. }
  614. NTSTATUS STDMETHODCALLTYPE PsDevice::I2CAccess( PDEVICE_OBJECT pdo, PI2CControl ctrl )
  615. {
  616. Trace t("PsDevice::I2CAccess()");
  617. DebugOut((1, "*** pdo->DeviceExtension = %x\n", pdo->DeviceExtension));
  618. ErrorCode error;
  619. PsDevice *adapter = GetCurrentDevice();
  620. ctrl->Status = I2C_STATUS_NOERROR;
  621. if ( ctrl->dwCookie != adapter->dwCurCookie_ ) {
  622. if ( (adapter->dwExpiredCookie != 0 ) && (adapter->dwExpiredCookie == ctrl->dwCookie ) )
  623. ctrl->Status = I2C_STATUS_ERROR;
  624. else
  625. ctrl->Status = I2C_STATUS_NOERROR;
  626. return STATUS_INVALID_HANDLE;
  627. }
  628. // Record time of this transaction to enable checking for timeout
  629. KeQuerySystemTime( &adapter->LastI2CAccessTime );
  630. // Check for valid combinations of I2C command & flags
  631. switch( ctrl->Command ) {
  632. case I2C_COMMAND_NULL:
  633. if ( ( ctrl->Flags & ~(I2C_FLAGS_START | I2C_FLAGS_STOP) ) ||
  634. ( ( ctrl->Flags & (I2C_FLAGS_START | I2C_FLAGS_STOP) ) == (I2C_FLAGS_START | I2C_FLAGS_STOP) ) ) {
  635. // Illegal combination of Command & Flags
  636. return STATUS_INVALID_PARAMETER;
  637. }
  638. if ( ctrl->Flags & I2C_FLAGS_START ) {
  639. if ( adapter->I2CSWStart() ) {
  640. ctrl->Status = I2C_STATUS_ERROR;
  641. return STATUS_SUCCESS;
  642. }
  643. }
  644. if ( ctrl->Flags & I2C_FLAGS_STOP ) {
  645. if ( adapter->I2CSWStop() ) {
  646. ctrl->Status = I2C_STATUS_ERROR;
  647. return STATUS_SUCCESS;
  648. }
  649. }
  650. break;
  651. case I2C_COMMAND_READ:
  652. if ( ctrl->Flags & ~(I2C_FLAGS_STOP | I2C_FLAGS_ACK) ) {
  653. // Illegal combination of Command & Flags
  654. return STATUS_INVALID_PARAMETER;
  655. }
  656. if ( adapter->I2CSWRead( &ctrl->Data ) ) {
  657. ctrl->Status = I2C_STATUS_ERROR;
  658. return STATUS_SUCCESS;
  659. }
  660. if ( ctrl->Flags & I2C_FLAGS_ACK ) {
  661. if ( adapter->I2CSWSendACK() ) {
  662. ctrl->Status = I2C_STATUS_ERROR;
  663. return STATUS_SUCCESS;
  664. }
  665. } else {
  666. if ( adapter->I2CSWSendNACK() ) {
  667. ctrl->Status = I2C_STATUS_ERROR;
  668. return STATUS_SUCCESS;
  669. }
  670. }
  671. if ( ctrl->Flags & I2C_FLAGS_STOP ) {
  672. if ( adapter->I2CSWStop() ) {
  673. ctrl->Status = I2C_STATUS_ERROR;
  674. return STATUS_SUCCESS;
  675. }
  676. }
  677. break;
  678. case I2C_COMMAND_WRITE:
  679. if ( ctrl->Flags & ~(I2C_FLAGS_START | I2C_FLAGS_STOP | I2C_FLAGS_ACK | I2C_FLAGS_DATACHAINING) ) {
  680. // Illegal combination of Command & Flags
  681. return STATUS_INVALID_PARAMETER;
  682. }
  683. if ( ctrl->Flags & I2C_FLAGS_DATACHAINING ) {
  684. if ( adapter->I2CSWStop() ) {
  685. ctrl->Status = I2C_STATUS_ERROR;
  686. return STATUS_SUCCESS;
  687. }
  688. if ( adapter->I2CSWStart() ) {
  689. ctrl->Status = I2C_STATUS_ERROR;
  690. return STATUS_SUCCESS;
  691. }
  692. }
  693. if ( ctrl->Flags & I2C_FLAGS_START ) {
  694. if ( adapter->I2CSWStart() ) {
  695. ctrl->Status = I2C_STATUS_ERROR;
  696. return STATUS_SUCCESS;
  697. }
  698. }
  699. error = adapter->I2CSWWrite(ctrl->Data);
  700. switch ( error ) {
  701. case I2CERR_NOACK:
  702. if ( ctrl->Flags & I2C_FLAGS_ACK ) {
  703. ctrl->Status = I2C_STATUS_ERROR;
  704. return STATUS_SUCCESS;
  705. }
  706. break;
  707. case I2CERR_OK:
  708. if ( ( ctrl->Flags & I2C_FLAGS_ACK ) == 0 ) {
  709. ctrl->Status = I2C_STATUS_ERROR;
  710. return STATUS_SUCCESS;
  711. }
  712. break;
  713. default:
  714. ctrl->Status = I2C_STATUS_ERROR;
  715. return STATUS_SUCCESS;
  716. }
  717. if ( ctrl->Flags & I2C_FLAGS_STOP ) {
  718. if ( adapter->I2CSWStop() ) {
  719. ctrl->Status = I2C_STATUS_ERROR;
  720. return STATUS_SUCCESS;
  721. }
  722. }
  723. break;
  724. case I2C_COMMAND_STATUS:
  725. // Flags are ignored
  726. return STATUS_NOT_IMPLEMENTED;
  727. case I2C_COMMAND_RESET:
  728. // Flags are ignored
  729. if ( adapter->I2CSWStart() ) {
  730. ctrl->Status = I2C_STATUS_ERROR;
  731. return STATUS_SUCCESS;
  732. }
  733. if ( adapter->I2CSWStop() ) {
  734. ctrl->Status = I2C_STATUS_ERROR;
  735. return STATUS_SUCCESS;
  736. }
  737. break;
  738. default:
  739. return STATUS_INVALID_PARAMETER;
  740. }
  741. return STATUS_SUCCESS;
  742. }
  743. #else
  744. /* Method: PsDevice::I2COpen
  745. * Purpose: Tries to allocate I2C port to the caller
  746. */
  747. NTSTATUS STDMETHODCALLTYPE PsDevice::I2COpen( PDEVICE_OBJECT pdo, ULONG ToOpen,
  748. PI2CControl ctrl )
  749. {
  750. Trace t("PsDevice::I2COpen()");
  751. DebugOut((1, "*** pdo->DeviceExtension = %x\n", pdo->DeviceExtension));
  752. // need a way to obtain the device pointer
  753. PsDevice *adapter = GetCurrentDevice();
  754. // cookie is not NULL if I2C is open
  755. if ( ToOpen && adapter->dwCurCookie_ ) {
  756. ctrl->Flags = I2C_STATUS_BUSY;
  757. return STATUS_DEVICE_BUSY;
  758. }
  759. // want to close ?
  760. if ( !ToOpen )
  761. if ( adapter->dwCurCookie_ == ctrl->dwCookie ) {
  762. adapter->dwCurCookie_ = 0;
  763. return STATUS_SUCCESS;
  764. } else {
  765. ctrl->Flags = I2C_STATUS_BUSY;
  766. return STATUS_DEVICE_BUSY;
  767. }
  768. // now we are opening
  769. LARGE_INTEGER CurTime;
  770. KeQuerySystemTime( &CurTime );
  771. adapter->dwCurCookie_ = CurTime.LowPart;
  772. ctrl->dwCookie = adapter->dwCurCookie_;
  773. ctrl->ClockRate = 100000;
  774. return STATUS_SUCCESS;
  775. }
  776. NTSTATUS STDMETHODCALLTYPE PsDevice::I2CAccess( PDEVICE_OBJECT pdo , PI2CControl ctrl )
  777. {
  778. Trace t("PsDevice::I2CAccess()");
  779. DebugOut((1, "*** pdo->DeviceExtension = %x\n", pdo->DeviceExtension));
  780. PsDevice *adapter = GetCurrentDevice();
  781. if ( ctrl->dwCookie != adapter->dwCurCookie_ ) {
  782. ctrl->Flags = I2C_STATUS_BUSY;
  783. return I2C_STATUS_BUSY;
  784. }
  785. ctrl->Flags = I2C_STATUS_NOERROR;
  786. // 848 I2C API currently needs to have an address for both write and read
  787. // commands. So, if START flag is set an address is passed. Cache it and use
  788. // later
  789. switch ( ctrl->Command ) {
  790. case I2C_COMMAND_READ:
  791. // got 'write' command first ( with the address )
  792. if ( adapter->I2CHWRead( adapter->GetI2CAddress(), &ctrl->Data ) != Success )
  793. ctrl->Flags = I2C_STATUS_ERROR;
  794. break;
  795. case I2C_COMMAND_WRITE:
  796. if ( ctrl->Flags & I2C_FLAGS_START ) {
  797. adapter->StoreI2CAddress( ctrl->Data );
  798. } else
  799. adapter->I2CHWWrite2( adapter->GetI2CAddress(), ctrl->Data );
  800. break;
  801. case I2C_COMMAND_STATUS:
  802. if ( adapter->I2CGetLastError() != I2CERR_OK )
  803. ctrl->Flags = I2C_STATUS_ERROR;
  804. break;
  805. case I2C_COMMAND_RESET:
  806. adapter->I2CInitHWMode( 100000 ); // assume frequency = 100Khz
  807. break;
  808. }
  809. return STATUS_SUCCESS;
  810. }
  811. #endif
  812. void HandleIRP( IN PHW_STREAM_REQUEST_BLOCK pSrb )
  813. {
  814. Trace t("HandleIRP()");
  815. DebugOut((1, "HandleIRP(%x)\n", pSrb));
  816. PHW_DEVICE_EXTENSION HwDeviceExtension =
  817. (PHW_DEVICE_EXTENSION) pSrb->HwDeviceExtension;
  818. PsDevice *adapter = HwDeviceExtension->psdevice;
  819. PIRP Irp = pSrb->Irp;
  820. PIO_STACK_LOCATION IrpStack = IoGetCurrentIrpStackLocation( Irp );
  821. switch ( IrpStack->MajorFunction ) {
  822. case IRP_MJ_PNP:
  823. if ( IrpStack->MinorFunction == IRP_MN_QUERY_INTERFACE ) {
  824. if ( IsEqualGUID( *IrpStack->Parameters.QueryInterface.InterfaceType,
  825. GUID_I2C_INTERFACE ) &&
  826. IrpStack->Parameters.QueryInterface.Size >= sizeof( I2CINTERFACE ) ) {
  827. IrpStack->Parameters.QueryInterface.InterfaceType = &GUID_I2C_INTERFACE;
  828. IrpStack->Parameters.QueryInterface.Size = sizeof( I2CINTERFACE );
  829. IrpStack->Parameters.QueryInterface.Version = 1;
  830. I2CINTERFACE *i2ciface =
  831. (I2CINTERFACE *)IrpStack->Parameters.QueryInterface.Interface;
  832. i2ciface->i2cOpen = &PsDevice::I2COpen;
  833. i2ciface->i2cAccess = &PsDevice::I2CAccess;
  834. IrpStack->Parameters.QueryInterface.InterfaceSpecificData = 0;
  835. // complete the irp
  836. Irp->IoStatus.Status = STATUS_SUCCESS;
  837. IoCompleteRequest( Irp, IO_NO_INCREMENT );
  838. break;
  839. } else {
  840. Irp->IoStatus.Status = STATUS_INVALID_PARAMETER_1;
  841. IoCompleteRequest( Irp, IO_NO_INCREMENT );
  842. }
  843. }
  844. default:
  845. pSrb->Status = STATUS_NOT_SUPPORTED;
  846. }
  847. }
  848. /** CompleteInitialization()
  849. **
  850. ** This routine is called when an SRB_COMPLETE_INITIALIZATION request is received
  851. **
  852. ** Arguments:
  853. **
  854. ** pSrb - pointer to stream request block
  855. **
  856. ** Returns:
  857. **
  858. ** Side Effects: none
  859. */
  860. void STDMETHODCALLTYPE CompleteInitialization( IN OUT PHW_STREAM_REQUEST_BLOCK pSrb )
  861. {
  862. Trace t("CompleteInitialization()");
  863. NTSTATUS Status;
  864. PHW_DEVICE_EXTENSION HwDeviceExtension =
  865. (PHW_DEVICE_EXTENSION) pSrb->HwDeviceExtension;
  866. PsDevice *adapter = HwDeviceExtension->psdevice;
  867. // Create the Registry blobs that DShow uses to create
  868. // graphs via Mediums
  869. Status = StreamClassRegisterFilterWithNoKSPins (
  870. adapter->PDO, // IN PDEVICE_OBJECT DeviceObject,
  871. &KSCATEGORY_TVTUNER, // IN GUID * InterfaceClassGUID,
  872. SIZEOF_ARRAY (TVTunerMediums), // IN ULONG PinCount,
  873. TVTunerPinDirection, // IN ULONG * Flags,
  874. TVTunerMediums, // IN KSPIN_MEDIUM * MediumList,
  875. NULL // IN GUID * CategoryList
  876. );
  877. Status = StreamClassRegisterFilterWithNoKSPins (
  878. adapter->PDO, // IN PDEVICE_OBJECT DeviceObject,
  879. &KSCATEGORY_CROSSBAR, // IN GUID * InterfaceClassGUID,
  880. SIZEOF_ARRAY (CrossbarMediums), // IN ULONG PinCount,
  881. CrossbarPinDirection, // IN ULONG * Flags,
  882. CrossbarMediums, // IN KSPIN_MEDIUM * MediumList,
  883. NULL // IN GUID * CategoryList
  884. );
  885. // Register the TVAudio decoder
  886. Status = StreamClassRegisterFilterWithNoKSPins (
  887. adapter->PDO, // IN PDEVICE_OBJECT DeviceObject,
  888. &KSCATEGORY_TVAUDIO, // IN GUID * InterfaceClassGUID,
  889. SIZEOF_ARRAY (TVAudioMediums), // IN ULONG PinCount,
  890. TVAudioPinDirection, // IN ULONG * Flags,
  891. TVAudioMediums, // IN KSPIN_MEDIUM * MediumList,
  892. NULL // IN GUID * CategoryList
  893. );
  894. // Register the Capture filter
  895. // Note: This should be done automatically be MSKsSrv.sys,
  896. // when that component comes on line (if ever) ...
  897. Status = StreamClassRegisterFilterWithNoKSPins (
  898. adapter->PDO, // IN PDEVICE_OBJECT DeviceObject,
  899. &KSCATEGORY_CAPTURE, // IN GUID * InterfaceClassGUID,
  900. SIZEOF_ARRAY (CaptureMediums), // IN ULONG PinCount,
  901. CapturePinDirection, // IN ULONG * Flags,
  902. CaptureMediums, // IN KSPIN_MEDIUM * MediumList,
  903. CaptureCategories // IN GUID * CategoryList
  904. );
  905. // go to usual priority, completing the SRB at the same time
  906. StreamClassCallAtNewPriority( pSrb->StreamObject, HwDeviceExtension, LowToHigh,
  907. PHW_PRIORITY_ROUTINE( CompleteDeviceSRB ), pSrb );
  908. }
  909. /*
  910. ** AdapterReceivePacket()
  911. **
  912. ** Main entry point for receiving adapter based request SRBs. This routine
  913. ** will always be called at High Priority.
  914. **
  915. ** Note: This is an asyncronous entry point. The request does not complete
  916. ** on return from this function, the request only completes when a
  917. ** StreamClassDeviceNotification on this request block, of type
  918. ** DeviceRequestComplete, is issued.
  919. **
  920. ** Arguments:
  921. **
  922. ** pSrb - Pointer to the STREAM_REQUEST_BLOCK
  923. ** pSrb->HwDeviceExtension - will be the hardware device extension for
  924. ** as initialised in HwInitialise
  925. **
  926. ** Returns:
  927. **
  928. ** Side Effects: none
  929. */
  930. VOID STREAMAPI AdapterReceivePacket( IN PHW_STREAM_REQUEST_BLOCK pSrb )
  931. {
  932. Trace t("AdapterReceivePacket()");
  933. BOOL CompleteRequestSynchronously = TRUE;
  934. //default to success
  935. pSrb->Status = STATUS_SUCCESS;
  936. PHW_DEVICE_EXTENSION HwDeviceExtension =
  937. (PHW_DEVICE_EXTENSION) pSrb->HwDeviceExtension;
  938. PsDevice *adapter = HwDeviceExtension->psdevice;
  939. //
  940. // determine the type of packet.
  941. //
  942. DebugOut((1, "'AdapterReceivePacket(%x) cmd(%x)\n", pSrb, pSrb->Command));
  943. switch ( pSrb->Command ) {
  944. case SRB_INITIALIZE_DEVICE:
  945. DebugOut((1, " SRB_INITIALIZE_DEVICE\n"));
  946. CompleteRequestSynchronously = FALSE;
  947. // have to schedule a low priority call to open the device because
  948. // registry functions are used during initialization
  949. StreamClassCallAtNewPriority( pSrb->StreamObject, pSrb->HwDeviceExtension,
  950. Low, PHW_PRIORITY_ROUTINE( HwInitialize ), pSrb );
  951. break;
  952. case SRB_UNINITIALIZE_DEVICE:
  953. DebugOut((1, " SRB_UNINITIALIZE_DEVICE\n"));
  954. // close the device.
  955. HwUnInitialize(pSrb);
  956. break;
  957. case SRB_OPEN_STREAM:
  958. DebugOut((1, " SRB_OPEN_STREAM\n"));
  959. // open a stream
  960. AdapterOpenStream( pSrb );
  961. break;
  962. case SRB_CLOSE_STREAM:
  963. DebugOut((1, " SRB_CLOSE_STREAM\n"));
  964. // close a stream
  965. AdapterCloseStream( pSrb );
  966. break;
  967. case SRB_GET_STREAM_INFO:
  968. DebugOut((1, " SRB_GET_STREAM_INFO\n"));
  969. //
  970. // return a block describing all the streams
  971. //
  972. AdapterStreamInfo(pSrb);
  973. break;
  974. case SRB_GET_DEVICE_PROPERTY:
  975. DebugOut((1, " SRB_GET_DEVICE_PROPERTY\n"));
  976. AdapterGetProperty( pSrb );
  977. break;
  978. case SRB_SET_DEVICE_PROPERTY:
  979. DebugOut((1, " SRB_SET_DEVICE_PROPERTY\n"));
  980. AdapterSetProperty( pSrb );
  981. break;
  982. case SRB_GET_DATA_INTERSECTION:
  983. DebugOut((1, " SRB_GET_DATA_INTERSECTION\n"));
  984. //
  985. // Return a format, given a range
  986. //
  987. AdapterFormatFromRange( pSrb );
  988. break;
  989. case SRB_INITIALIZATION_COMPLETE:
  990. DebugOut((1, " SRB_INITIALIZATION_COMPLETE\n"));
  991. //
  992. // Stream class has finished initialization.
  993. // Now create DShow Medium interface BLOBs.
  994. // This needs to be done at low priority since it uses the registry, so use a callback
  995. //
  996. CompleteRequestSynchronously = FALSE;
  997. StreamClassCallAtNewPriority( NULL /*pSrb->StreamObject*/, pSrb->HwDeviceExtension,
  998. Low, PHW_PRIORITY_ROUTINE( CompleteInitialization), pSrb );
  999. break;
  1000. case SRB_PAGING_OUT_DRIVER:
  1001. if ( (*(DWORD*)(gpjBaseAddr+0x10c) & 3) || (*(DWORD*)(gpjBaseAddr+0x104)) )
  1002. {
  1003. DebugOut((0, " ****** SRB_PAGING_OUT_DRIVER ENB(%x) MSK(%x)\n",
  1004. *(DWORD*)(gpjBaseAddr+0x10c) & 3,
  1005. *(DWORD*)(gpjBaseAddr+0x104)
  1006. ));
  1007. *(DWORD*)(gpjBaseAddr+0x10c) &= ~3; // disable interrupts [TMZ] [!!!]
  1008. *(DWORD*)(gpjBaseAddr+0x104) = 0; // disable interrupts [TMZ] [!!!]
  1009. }
  1010. break;
  1011. case SRB_UNKNOWN_DEVICE_COMMAND:
  1012. DebugOut((1, " SRB_UNKNOWN_DEVICE_COMMAND\n"));
  1013. HandleIRP( pSrb );
  1014. break;
  1015. // We should never get the following 2 since this is a single instance
  1016. // device
  1017. case SRB_OPEN_DEVICE_INSTANCE:
  1018. case SRB_CLOSE_DEVICE_INSTANCE:
  1019. default:
  1020. //
  1021. // this is a request that we do not understand. Indicate invalid
  1022. // command and complete the request
  1023. //
  1024. DebugOut((0, "SRB(%x) not recognized by this driver\n", pSrb->Command));
  1025. pSrb->Status = STATUS_NOT_IMPLEMENTED;
  1026. }
  1027. //
  1028. // Most, but not all SRBs are handled synchronously here
  1029. //
  1030. if ( CompleteRequestSynchronously ) {
  1031. CompleteDeviceSRB( pSrb );
  1032. }
  1033. }
  1034. /*
  1035. ** AdapterCancelPacket()
  1036. **
  1037. ** Request to cancel a packet that is currently in process in the minidriver
  1038. **
  1039. ** Arguments:
  1040. **
  1041. ** pSrb - pointer to request packet to cancel
  1042. **
  1043. ** Returns:
  1044. **
  1045. ** Side Effects: none
  1046. */
  1047. VOID STREAMAPI AdapterCancelPacket( PHW_STREAM_REQUEST_BLOCK pSrb )
  1048. {
  1049. Trace t("AdapterCancelPacket()");
  1050. VideoStream StreamNumber = (VideoStream)pSrb->StreamObject->StreamNumber;
  1051. DebugOut((1, "AdapterCancelPacket - pSrb(%x) strm(%d)\n", pSrb, StreamNumber));
  1052. VideoChannel *chan = (VideoChannel *)((PSTREAMEX)pSrb->StreamObject->HwStreamExtension)->videochannel;
  1053. pSrb->Status = STATUS_CANCELLED;
  1054. //
  1055. // it is necessary to call the request back correctly. Determine which
  1056. // type of command it is
  1057. //
  1058. switch ( pSrb->Flags & (SRB_HW_FLAGS_DATA_TRANSFER | SRB_HW_FLAGS_STREAM_REQUEST ) ) {
  1059. //
  1060. // find all stream commands, and do stream notifications
  1061. //
  1062. case SRB_HW_FLAGS_STREAM_REQUEST | SRB_HW_FLAGS_DATA_TRANSFER:
  1063. DebugOut((1, " Canceling data SRB\n" ) );
  1064. // adapter->Stop( *chan ); [!!!] [TMZ] [???] why is this commented out???
  1065. if (!chan->RemoveSRB( pSrb ))
  1066. {
  1067. DebugOut((0, " Canceling data SRB failed\n"));
  1068. DEBUG_BREAKPOINT();
  1069. }
  1070. break;
  1071. case SRB_HW_FLAGS_STREAM_REQUEST:
  1072. DebugOut((1, " Canceling control SRB\n" ) );
  1073. CheckSrbStatus( pSrb );
  1074. StreamClassStreamNotification( ReadyForNextStreamControlRequest,
  1075. pSrb->StreamObject );
  1076. StreamClassStreamNotification( StreamRequestComplete,
  1077. pSrb->StreamObject, pSrb );
  1078. break;
  1079. default:
  1080. //
  1081. // this must be a device request. Use device notifications
  1082. //
  1083. DebugOut((1, " Canceling SRB per device request\n" ) );
  1084. StreamClassDeviceNotification( ReadyForNextDeviceRequest,
  1085. pSrb->HwDeviceExtension );
  1086. StreamClassDeviceNotification( DeviceRequestComplete,
  1087. pSrb->HwDeviceExtension, pSrb );
  1088. }
  1089. }
  1090. /*
  1091. ** AdapterTimeoutPacket()
  1092. **
  1093. ** This routine is called when a packet has been in the minidriver for
  1094. ** too long. The adapter must decide what to do with the packet
  1095. **
  1096. ** Arguments:
  1097. **
  1098. ** pSrb - pointer to the request packet that timed out
  1099. **
  1100. ** Returns:
  1101. **
  1102. ** Side Effects: none
  1103. */
  1104. VOID STREAMAPI AdapterTimeoutPacket( PHW_STREAM_REQUEST_BLOCK pSrb )
  1105. {
  1106. Trace t("AdapterTimeoutPacket()");
  1107. DebugOut((0, "AdapterTimeoutPacket (incomplete) - pSrb(%x)\n", pSrb));
  1108. // [TMZ] Fix this
  1109. #if SHOW_BUILD_MSGS
  1110. #pragma message("*** AdapterTimeoutPacket needs to be completed")
  1111. #endif
  1112. DebugOut((0, " pSrb->Flags = %x\n", pSrb->Flags));
  1113. if ( pSrb->Flags & SRB_HW_FLAGS_STREAM_REQUEST )
  1114. {
  1115. DebugOut((0, " SRB_HW_FLAGS_STREAM_REQUEST\n"));
  1116. }
  1117. if ( pSrb->Flags & SRB_HW_FLAGS_DATA_TRANSFER )
  1118. {
  1119. DebugOut((0, " SRB_HW_FLAGS_DATA_TRANSFER\n"));
  1120. }
  1121. //
  1122. // if we timeout while playing, then we need to consider this
  1123. // condition an error, and reset the hardware, and reset everything
  1124. // as well as cancelling this and all requests
  1125. //
  1126. //
  1127. // if we are not playing, and this is a CTRL request, we still
  1128. // need to reset everything as well as cancelling this and all requests
  1129. //
  1130. //
  1131. // if this is a data request, and the device is paused, we probably have
  1132. // run out of data buffer, and need more time, so just reset the timer,
  1133. // and let the packet continue
  1134. //
  1135. pSrb->TimeoutCounter = pSrb->TimeoutOriginal;
  1136. }
  1137. /*
  1138. ** HwInterrupt()
  1139. **
  1140. ** Routine is called when an interrupt at the IRQ level specified by the
  1141. ** ConfigInfo structure passed to the HwInitialize routine is received.
  1142. **
  1143. ** Note: IRQs may be shared, so the device should ensure the IRQ received
  1144. ** was expected
  1145. **
  1146. ** Arguments:
  1147. **
  1148. ** pHwDevEx - the device extension for the hardware interrupt
  1149. **
  1150. ** Returns:
  1151. **
  1152. ** Side Effects: none
  1153. */
  1154. BOOLEAN HwInterrupt( IN PHW_DEVICE_EXTENSION HwDeviceExtension )
  1155. {
  1156. Trace t("HwInterrupt()");
  1157. DebugOut((1, "HwInterrupt called by system\n"));
  1158. PsDevice *adapter = (PsDevice *)(HwDeviceExtension->psdevice);
  1159. BOOLEAN b = adapter->Interrupt();
  1160. return( b );
  1161. }
  1162. /* Function: CompleteDeviceSRB
  1163. * Purpose: Called to complete a device SRB
  1164. * Input: pSrb
  1165. */
  1166. inline void CompleteDeviceSRB( IN OUT PHW_STREAM_REQUEST_BLOCK pSrb )
  1167. {
  1168. Trace t("CompleteDeviceSRB()");
  1169. StreamClassDeviceNotification( DeviceRequestComplete, pSrb->HwDeviceExtension, pSrb );
  1170. StreamClassDeviceNotification( ReadyForNextDeviceRequest, pSrb->HwDeviceExtension );
  1171. }
  1172. /*
  1173. ** AdapterCompareGUIDsAndFormatSize()
  1174. **
  1175. ** Checks for a match on the three GUIDs and FormatSize
  1176. **
  1177. ** Arguments:
  1178. **
  1179. ** IN DataRange1
  1180. ** IN DataRange2
  1181. **
  1182. ** Returns:
  1183. **
  1184. ** TRUE if all elements match
  1185. ** FALSE if any are different
  1186. **
  1187. ** Side Effects: none
  1188. */
  1189. bool AdapterCompareGUIDsAndFormatSize( IN const PKSDATARANGE DataRange1,
  1190. IN const PKSDATARANGE DataRange2 )
  1191. {
  1192. Trace t("AdapterCompareGUIDsAndFormatSize()");
  1193. bool bCheckSize = false;
  1194. #if 1 // use old guid verify
  1195. return (
  1196. IsEqualGUID( DataRange1->MajorFormat, DataRange2->MajorFormat ) &&
  1197. IsEqualGUID( DataRange1->SubFormat, DataRange2->SubFormat ) &&
  1198. IsEqualGUID( DataRange1->Specifier, DataRange2->Specifier ) &&
  1199. ( DataRange1->FormatSize == DataRange2->FormatSize ) );
  1200. #else // use new guid verify from cc decoder
  1201. bool rval = false;
  1202. if ( IsEqualGUID(DataRange1->MajorFormat, KSDATAFORMAT_TYPE_WILDCARD)
  1203. || IsEqualGUID(DataRange2->MajorFormat, KSDATAFORMAT_TYPE_WILDCARD)
  1204. || IsEqualGUID(DataRange1->MajorFormat, DataRange2->MajorFormat) )
  1205. {
  1206. if ( !IsEqualGUID(DataRange1->MajorFormat, DataRange2->MajorFormat) )
  1207. {
  1208. DebugOut((0, "Match 1\n" ));
  1209. }
  1210. if ( IsEqualGUID(DataRange1->SubFormat, KSDATAFORMAT_SUBTYPE_WILDCARD)
  1211. || IsEqualGUID(DataRange2->SubFormat, KSDATAFORMAT_SUBTYPE_WILDCARD)
  1212. || IsEqualGUID(DataRange1->SubFormat, DataRange2->SubFormat) )
  1213. {
  1214. if ( !IsEqualGUID(DataRange1->SubFormat, DataRange2->SubFormat) )
  1215. {
  1216. DebugOut((0, "Match 2\n" ));
  1217. }
  1218. if ( IsEqualGUID(DataRange1->Specifier, KSDATAFORMAT_SPECIFIER_WILDCARD)
  1219. || IsEqualGUID(DataRange2->Specifier, KSDATAFORMAT_SPECIFIER_WILDCARD)
  1220. || IsEqualGUID(DataRange1->Specifier, DataRange2->Specifier) )
  1221. {
  1222. if ( !IsEqualGUID(DataRange1->Specifier, DataRange2->Specifier) )
  1223. {
  1224. DebugOut((0, "Match 3\n" ));
  1225. }
  1226. if ( !bCheckSize || DataRange1->FormatSize == DataRange2->FormatSize)
  1227. {
  1228. DebugOut((0, "Victory !!!\n" ));
  1229. rval = true;
  1230. }
  1231. else
  1232. {
  1233. DebugOut((0, "FormatSize Mismatch\n" ));
  1234. }
  1235. }
  1236. else
  1237. {
  1238. DebugOut((0, "Specifier Mismatch\n" ));
  1239. }
  1240. }
  1241. else
  1242. {
  1243. DebugOut((0, "SubFormat Mismatch\n" ));
  1244. }
  1245. }
  1246. else
  1247. {
  1248. DebugOut((0, "MajorFormat Mismatch\n" ));
  1249. }
  1250. DebugOut((0, "CompareGUIDsAndFormatSize(\n"));
  1251. DebugOut((0, " DataRange1=%x\n", DataRange1));
  1252. DebugOut((0, " DataRange2=%x\n", DataRange2));
  1253. DebugOut((0, " bCheckSize=%s\n", bCheckSize ? "TRUE":"FALSE"));
  1254. DebugOut((0, ")\n"));
  1255. DebugOut((0, "returning %s\n", rval? "TRUE":"FALSE"));
  1256. return rval;
  1257. #endif
  1258. }
  1259. /*
  1260. ** AdapterFormatFromRange()
  1261. **
  1262. ** Returns a DATAFORMAT from a DATARANGE
  1263. **
  1264. ** Arguments:
  1265. **
  1266. ** IN PHW_STREAM_REQUEST_BLOCK pSrb
  1267. **
  1268. ** Returns:
  1269. **
  1270. ** TRUE if the format is supported
  1271. ** FALSE if the format cannot be suppored
  1272. **
  1273. ** Side Effects: none
  1274. */
  1275. void AdapterFormatFromRange( IN PHW_STREAM_REQUEST_BLOCK pSrb )
  1276. {
  1277. Trace t("AdapterFormatFromRange()");
  1278. PSTREAM_DATA_INTERSECT_INFO IntersectInfo;
  1279. PKSDATARANGE DataRange;
  1280. ULONG FormatSize=0;
  1281. ULONG StreamNumber;
  1282. ULONG j;
  1283. ULONG NumberOfFormatArrayEntries;
  1284. PKSDATAFORMAT *pAvailableFormats;
  1285. IntersectInfo = pSrb->CommandData.IntersectInfo;
  1286. StreamNumber = IntersectInfo->StreamNumber;
  1287. DataRange = IntersectInfo->DataRange;
  1288. //
  1289. // Check that the stream number is valid
  1290. //
  1291. if( StreamNumber >= DRIVER_STREAM_COUNT )
  1292. {
  1293. pSrb->Status = STATUS_NOT_IMPLEMENTED;
  1294. return;
  1295. }
  1296. NumberOfFormatArrayEntries =
  1297. Streams[StreamNumber].hwStreamInfo.NumberOfFormatArrayEntries;
  1298. //
  1299. // Get the pointer to the array of available formats
  1300. //
  1301. pAvailableFormats = Streams[StreamNumber].hwStreamInfo.StreamFormatsArray;
  1302. //
  1303. // Is the caller trying to get the format, or the size of the format?
  1304. //
  1305. bool OnlyWantsSize = (IntersectInfo->SizeOfDataFormatBuffer == sizeof( ULONG ) );
  1306. //
  1307. // Walk the formats supported by the stream searching for a match
  1308. // of the three GUIDs which together define a DATARANGE
  1309. //
  1310. for ( j = 0; j < NumberOfFormatArrayEntries; j++, pAvailableFormats++ )
  1311. {
  1312. if ( !AdapterCompareGUIDsAndFormatSize( DataRange, *pAvailableFormats ) )
  1313. {
  1314. continue;
  1315. }
  1316. //
  1317. // Now that the three GUIDs match, switch on the Specifier
  1318. // to do a further type specific check
  1319. //
  1320. // -------------------------------------------------------------------
  1321. // Specifier FORMAT_VideoInfo for VIDEOINFOHEADER
  1322. // -------------------------------------------------------------------
  1323. if ( IsEqualGUID( DataRange->Specifier, KSDATAFORMAT_SPECIFIER_VIDEOINFO ) )
  1324. {
  1325. PKS_DATARANGE_VIDEO DataRangeVideoToVerify = (PKS_DATARANGE_VIDEO)DataRange;
  1326. PKS_DATARANGE_VIDEO DataRangeVideo = (PKS_DATARANGE_VIDEO)*pAvailableFormats;
  1327. //
  1328. // Check that the other fields match
  1329. //
  1330. if ( (DataRangeVideoToVerify->bFixedSizeSamples != DataRangeVideo->bFixedSizeSamples) ||
  1331. (DataRangeVideoToVerify->bTemporalCompression != DataRangeVideo->bTemporalCompression) ||
  1332. (DataRangeVideoToVerify->StreamDescriptionFlags != DataRangeVideo->StreamDescriptionFlags) ||
  1333. (DataRangeVideoToVerify->MemoryAllocationFlags != DataRangeVideo->MemoryAllocationFlags) ||
  1334. (RtlCompareMemory( &DataRangeVideoToVerify->ConfigCaps,
  1335. &DataRangeVideo->ConfigCaps,
  1336. sizeof( KS_VIDEO_STREAM_CONFIG_CAPS ) ) !=
  1337. sizeof( KS_VIDEO_STREAM_CONFIG_CAPS ) ) )
  1338. {
  1339. DebugOut(( 1, "AdapterFormatFromRange(): at least one field does not match\n" ));
  1340. continue;
  1341. }
  1342. // MATCH FOUND!
  1343. FormatSize = sizeof( KSDATAFORMAT ) +
  1344. KS_SIZE_VIDEOHEADER( &DataRangeVideoToVerify->VideoInfoHeader );
  1345. if ( OnlyWantsSize )
  1346. {
  1347. break;
  1348. }
  1349. // Caller wants the full data format
  1350. if ( IntersectInfo->SizeOfDataFormatBuffer < FormatSize )
  1351. {
  1352. DebugOut(( 1, "AdapterFormatFromRange(): STATUS_BUFFER_TOO_SMALL\n" ));
  1353. pSrb->Status = STATUS_BUFFER_TOO_SMALL;
  1354. return;
  1355. }
  1356. // Copy over the KSDATAFORMAT, followed by the
  1357. // actual VideoInfoHeader
  1358. PKS_DATAFORMAT_VIDEOINFOHEADER InterVidHdr =
  1359. (PKS_DATAFORMAT_VIDEOINFOHEADER)IntersectInfo->DataFormatBuffer;
  1360. RtlCopyMemory( &InterVidHdr->DataFormat,
  1361. &DataRangeVideoToVerify->DataRange, sizeof( KSDATARANGE ) );
  1362. ((PKSDATAFORMAT)IntersectInfo->DataFormatBuffer)->FormatSize = FormatSize;
  1363. RtlCopyMemory( &InterVidHdr->VideoInfoHeader,
  1364. &DataRangeVideoToVerify->VideoInfoHeader,
  1365. KS_SIZE_VIDEOHEADER( &DataRangeVideoToVerify->VideoInfoHeader ) );
  1366. // report back the omage size as we know it
  1367. KS_VIDEOINFOHEADER &vidHDR = DataRangeVideoToVerify->VideoInfoHeader;
  1368. #ifdef HACK_FUDGE_RECTANGLES
  1369. // [!!!] [TMZ] - hack
  1370. if( vidHDR.rcTarget.bottom == 0 )
  1371. {
  1372. vidHDR.rcTarget.left = 0;
  1373. vidHDR.rcTarget.top = 0;
  1374. vidHDR.rcTarget.right = vidHDR.bmiHeader.biWidth;
  1375. vidHDR.rcTarget.bottom = abs(vidHDR.bmiHeader.biHeight);
  1376. }
  1377. if( InterVidHdr->VideoInfoHeader.rcTarget.bottom == 0 )
  1378. {
  1379. InterVidHdr->VideoInfoHeader.rcTarget.left = 0;
  1380. InterVidHdr->VideoInfoHeader.rcTarget.top = 0;
  1381. InterVidHdr->VideoInfoHeader.rcTarget.right = vidHDR.bmiHeader.biWidth;
  1382. InterVidHdr->VideoInfoHeader.rcTarget.bottom = abs(vidHDR.bmiHeader.biHeight);
  1383. }
  1384. #endif
  1385. MSize size;
  1386. GetRequestedSize( vidHDR, size );
  1387. ColorSpace tmpCol( DataRange->SubFormat );
  1388. MRect dst( vidHDR.rcTarget );
  1389. // make sure the dimentions are acceptable
  1390. if ( tmpCol.IsValid() && tmpCol.CheckDimentions( size ) &&
  1391. tmpCol.CheckLeftTop( dst.TopLeft() ) )
  1392. {
  1393. // if width is different, use it ( in bytes ) to calculate the size
  1394. if ( vidHDR.bmiHeader.biWidth != size.cx )
  1395. {
  1396. InterVidHdr->VideoInfoHeader.bmiHeader.biSizeImage =
  1397. vidHDR.bmiHeader.biWidth * abs(vidHDR.bmiHeader.biHeight);
  1398. }
  1399. else
  1400. {
  1401. InterVidHdr->VideoInfoHeader.bmiHeader.biSizeImage = size.cx *
  1402. tmpCol.GetBitCount() * abs(vidHDR.bmiHeader.biHeight) / 8;
  1403. }
  1404. DebugOut((1, "InterVidHdr->VideoInfoHeader.bmiHeader.biSizeImage = %d\n", InterVidHdr->VideoInfoHeader.bmiHeader.biSizeImage));
  1405. break;
  1406. }
  1407. else
  1408. {
  1409. pSrb->Status = STATUS_BUFFER_TOO_SMALL;
  1410. DebugOut((1, "AdapterFormatFromRange: Buffer too small\n"));
  1411. return;
  1412. }
  1413. } // End of VIDEOINFOHEADER specifier
  1414. // -------------------------------------------------------------------
  1415. // Specifier FORMAT_VideoInfo2 for VIDEOINFOHEADER2
  1416. // -------------------------------------------------------------------
  1417. else if ( IsEqualGUID( DataRange->Specifier, KSDATAFORMAT_SPECIFIER_VIDEOINFO2 ) )
  1418. {
  1419. PKS_DATARANGE_VIDEO2 DataRangeVideoToVerify = (PKS_DATARANGE_VIDEO2) DataRange;
  1420. PKS_DATARANGE_VIDEO2 DataRangeVideo = (PKS_DATARANGE_VIDEO2) *pAvailableFormats;
  1421. //
  1422. // Check that the other fields match
  1423. //
  1424. if ( (DataRangeVideoToVerify->bFixedSizeSamples != DataRangeVideo->bFixedSizeSamples) ||
  1425. (DataRangeVideoToVerify->bTemporalCompression != DataRangeVideo->bTemporalCompression) ||
  1426. (DataRangeVideoToVerify->StreamDescriptionFlags != DataRangeVideo->StreamDescriptionFlags) ||
  1427. (DataRangeVideoToVerify->MemoryAllocationFlags != DataRangeVideo->MemoryAllocationFlags) ||
  1428. (RtlCompareMemory( &DataRangeVideoToVerify->ConfigCaps,
  1429. &DataRangeVideo->ConfigCaps,
  1430. sizeof( KS_VIDEO_STREAM_CONFIG_CAPS ) ) !=
  1431. sizeof( KS_VIDEO_STREAM_CONFIG_CAPS ) ) )
  1432. {
  1433. DebugOut(( 1, "AdapterFormatFromRange(): at least one field does not match\n" ));
  1434. continue;
  1435. }
  1436. // MATCH FOUND!
  1437. FormatSize = sizeof( KSDATAFORMAT ) +
  1438. KS_SIZE_VIDEOHEADER2( &DataRangeVideoToVerify->VideoInfoHeader );
  1439. if ( OnlyWantsSize )
  1440. {
  1441. break;
  1442. }
  1443. // Caller wants the full data format
  1444. if ( IntersectInfo->SizeOfDataFormatBuffer < FormatSize )
  1445. {
  1446. DebugOut(( 1, "AdapterFormatFromRange(): STATUS_BUFFER_TOO_SMALL\n" ));
  1447. pSrb->Status = STATUS_BUFFER_TOO_SMALL;
  1448. return;
  1449. }
  1450. // Copy over the KSDATAFORMAT, followed by the
  1451. // actual VideoInfoHeader
  1452. PKS_DATAFORMAT_VIDEOINFOHEADER2 InterVidHdr =
  1453. (PKS_DATAFORMAT_VIDEOINFOHEADER2)IntersectInfo->DataFormatBuffer;
  1454. RtlCopyMemory( &InterVidHdr->DataFormat,
  1455. &DataRangeVideoToVerify->DataRange, sizeof( KSDATARANGE ) );
  1456. ((PKSDATAFORMAT)IntersectInfo->DataFormatBuffer)->FormatSize = FormatSize;
  1457. RtlCopyMemory( &InterVidHdr->VideoInfoHeader2,
  1458. &DataRangeVideoToVerify->VideoInfoHeader,
  1459. KS_SIZE_VIDEOHEADER2( &DataRangeVideoToVerify->VideoInfoHeader ) );
  1460. // report back the omage size as we know it
  1461. KS_VIDEOINFOHEADER2 &vidHDR = DataRangeVideoToVerify->VideoInfoHeader;
  1462. #ifdef HACK_FUDGE_RECTANGLES
  1463. // [!!!] [TMZ] - hack
  1464. if( vidHDR.rcTarget.bottom == 0 )
  1465. {
  1466. vidHDR.rcTarget.left = 0;
  1467. vidHDR.rcTarget.top = 0;
  1468. vidHDR.rcTarget.right = vidHDR.bmiHeader.biWidth;
  1469. vidHDR.rcTarget.bottom = abs(vidHDR.bmiHeader.biHeight);
  1470. }
  1471. if( InterVidHdr->VideoInfoHeader.rcTarget.bottom == 0 )
  1472. {
  1473. InterVidHdr->VideoInfoHeader.rcTarget.left = 0;
  1474. InterVidHdr->VideoInfoHeader.rcTarget.top = 0;
  1475. InterVidHdr->VideoInfoHeader.rcTarget.right = vidHDR.bmiHeader.biWidth;
  1476. InterVidHdr->VideoInfoHeader.rcTarget.bottom = abs(vidHDR.bmiHeader.biHeight);
  1477. }
  1478. #endif
  1479. MSize size;
  1480. GetRequestedSize2( vidHDR, size );
  1481. ColorSpace tmpCol( DataRange->SubFormat );
  1482. MRect dst( vidHDR.rcTarget );
  1483. // make sure the dimentions are acceptable
  1484. if ( tmpCol.IsValid() && tmpCol.CheckDimentions( size ) &&
  1485. tmpCol.CheckLeftTop( dst.TopLeft() ) )
  1486. {
  1487. // if width is different, use it ( in bytes ) to calculate the size
  1488. if ( vidHDR.bmiHeader.biWidth != size.cx )
  1489. {
  1490. InterVidHdr->VideoInfoHeader2.bmiHeader.biSizeImage =
  1491. vidHDR.bmiHeader.biWidth * abs(vidHDR.bmiHeader.biHeight);
  1492. }
  1493. else
  1494. {
  1495. InterVidHdr->VideoInfoHeader2.bmiHeader.biSizeImage = size.cx *
  1496. tmpCol.GetBitCount() * abs(vidHDR.bmiHeader.biHeight) / 8;
  1497. }
  1498. DebugOut((1, "InterVidHdr->VideoInfoHeader2.bmiHeader.biSizeImage = %d\n", InterVidHdr->VideoInfoHeader2.bmiHeader.biSizeImage));
  1499. break;
  1500. }
  1501. else
  1502. {
  1503. pSrb->Status = STATUS_BUFFER_TOO_SMALL;
  1504. DebugOut((1, "AdapterFormatFromRange: Buffer too small\n"));
  1505. return;
  1506. }
  1507. } // End of VIDEOINFOHEADER2 specifier
  1508. // -------------------------------------------------------------------
  1509. // Specifier FORMAT_AnalogVideo for KS_ANALOGVIDEOINFO
  1510. // -------------------------------------------------------------------
  1511. else if ( IsEqualGUID( DataRange->Specifier, KSDATAFORMAT_SPECIFIER_ANALOGVIDEO ) )
  1512. {
  1513. //
  1514. // For analog video, the DataRange and DataFormat
  1515. // are identical, so just copy the whole structure
  1516. //
  1517. PKS_DATARANGE_ANALOGVIDEO pDataRangeVideo =
  1518. (PKS_DATARANGE_ANALOGVIDEO) *pAvailableFormats;
  1519. // MATCH FOUND!
  1520. FormatSize = sizeof( KS_DATARANGE_ANALOGVIDEO );
  1521. if ( OnlyWantsSize )
  1522. {
  1523. break;
  1524. }
  1525. // Caller wants the full data format
  1526. if ( IntersectInfo->SizeOfDataFormatBuffer < FormatSize )
  1527. {
  1528. pSrb->Status = STATUS_BUFFER_TOO_SMALL;
  1529. DebugOut((1, "AdapterFormatFromRange: Buffer too small\n"));
  1530. return;
  1531. }
  1532. RtlCopyMemory( IntersectInfo->DataFormatBuffer,
  1533. pDataRangeVideo, sizeof( KS_DATARANGE_ANALOGVIDEO ) );
  1534. ((PKSDATAFORMAT)IntersectInfo->DataFormatBuffer)->FormatSize = FormatSize;
  1535. break;
  1536. }
  1537. else
  1538. {
  1539. if ( IsEqualGUID( DataRange->Specifier, KSDATAFORMAT_SPECIFIER_VBI ) )
  1540. {
  1541. PKS_DATARANGE_VIDEO_VBI pDataRangeVBI =
  1542. (PKS_DATARANGE_VIDEO_VBI)*pAvailableFormats;
  1543. FormatSize = sizeof( KS_DATAFORMAT_VBIINFOHEADER );
  1544. if ( OnlyWantsSize )
  1545. {
  1546. break;
  1547. }
  1548. // Caller wants the full data format
  1549. if ( IntersectInfo->SizeOfDataFormatBuffer < FormatSize )
  1550. {
  1551. pSrb->Status = STATUS_BUFFER_TOO_SMALL;
  1552. DebugOut((1, "AdapterFormatFromRange: Buffer too small\n"));
  1553. return;
  1554. }
  1555. // Copy over the KSDATAFORMAT, followed by the
  1556. // actual VideoInfoHeader
  1557. PKS_DATAFORMAT_VBIINFOHEADER InterVBIHdr =
  1558. (PKS_DATAFORMAT_VBIINFOHEADER)IntersectInfo->DataFormatBuffer;
  1559. RtlCopyMemory( &InterVBIHdr->DataFormat,
  1560. &pDataRangeVBI->DataRange, sizeof( KSDATARANGE ) );
  1561. ((PKSDATAFORMAT)IntersectInfo->DataFormatBuffer)->FormatSize = FormatSize;
  1562. RtlCopyMemory( &InterVBIHdr->VBIInfoHeader,
  1563. &pDataRangeVBI->VBIInfoHeader, sizeof( KS_VBIINFOHEADER ) );
  1564. break;
  1565. }
  1566. else
  1567. {
  1568. DebugOut(( 0, "AdapterFormatFromRange: STATUS_NO_MATCH\n" ));
  1569. pSrb->Status = STATUS_NO_MATCH;
  1570. return;
  1571. }
  1572. }
  1573. } // End of loop on all formats for this stream
  1574. if ( OnlyWantsSize )
  1575. {
  1576. DebugOut(( 2, "AdapterFormatFromRange: only wants size\n" ));
  1577. *(PULONG) IntersectInfo->DataFormatBuffer = FormatSize;
  1578. pSrb->ActualBytesTransferred = sizeof( ULONG );
  1579. return;
  1580. }
  1581. pSrb->ActualBytesTransferred = FormatSize;
  1582. DebugOut(( 2, "AdapterFormatFromRange: done\n" ));
  1583. return;
  1584. }