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

4439 lines
146 KiB

  1. /*++
  2. Copyright (C) Microsoft Corporation, 1999 - 2000
  3. Module Name:
  4. MSDVGuts.c
  5. Abstract:
  6. Main service functions.
  7. Last changed by:
  8. Author: Yee J. Wu
  9. Environment:
  10. Kernel mode only
  11. Revision History:
  12. $Revision:: $
  13. $Date:: $
  14. --*/
  15. #include "strmini.h"
  16. #include "ksmedia.h"
  17. #include "1394.h"
  18. #include "61883.h"
  19. #include "avc.h"
  20. #include "dbg.h"
  21. #include "ksguid.h"
  22. #include "msdvfmt.h" // Before msdvdefs.h
  23. #include "msdvdef.h"
  24. #include "MSDVGuts.h"
  25. #include "MsdvUtil.h"
  26. #include "MsdvAvc.h"
  27. #include "XPrtDefs.h"
  28. #include "EDevCtrl.h"
  29. //
  30. // Define formats supported
  31. //
  32. #include "avcstrm.h"
  33. #include "strmdata.h"
  34. #if DBG
  35. extern ULONG DVDebugXmt; // this is defined in msdvuppr.c
  36. #endif
  37. NTSTATUS
  38. DVGetDevInfo(
  39. IN PDVCR_EXTENSION pDevExt,
  40. IN PAV_61883_REQUEST pAVReq
  41. );
  42. VOID
  43. DVIniStrmExt(
  44. PHW_STREAM_OBJECT pStrmObject,
  45. PSTREAMEX pStrmExt,
  46. PDVCR_EXTENSION pDevExt,
  47. const PALL_STREAM_INFO pStream
  48. );
  49. NTSTATUS
  50. DVStreamGetConnectionProperty (
  51. PDVCR_EXTENSION pDevExt,
  52. PSTREAMEX pStrmExt,
  53. PSTREAM_PROPERTY_DESCRIPTOR pSPD,
  54. PULONG pulActualBytesTransferred
  55. );
  56. NTSTATUS
  57. DVGetDroppedFramesProperty(
  58. PDVCR_EXTENSION pDevExt,
  59. PSTREAMEX pStrmExt,
  60. PSTREAM_PROPERTY_DESCRIPTOR pSPD,
  61. PULONG pulBytesTransferred
  62. );
  63. #if 0 // Enable later
  64. #ifdef ALLOC_PRAGMA
  65. #pragma alloc_text(PAGE, DVGetDevInfo)
  66. #pragma alloc_text(PAGE, DVInitializeDevice)
  67. #pragma alloc_text(PAGE, DVGetStreamInfo)
  68. #pragma alloc_text(PAGE, DVVerifyDataFormat)
  69. #pragma alloc_text(PAGE, DVGetDataIntersection)
  70. #pragma alloc_text(PAGE, DVIniStrmExt)
  71. #pragma alloc_text(PAGE, DVOpenStream)
  72. #pragma alloc_text(PAGE, DVCloseStream)
  73. #pragma alloc_text(PAGE, DVChangePower)
  74. #pragma alloc_text(PAGE, DVSurpriseRemoval)
  75. #pragma alloc_text(PAGE, DVProcessPnPBusReset)
  76. #pragma alloc_text(PAGE, DVUninitializeDevice)
  77. #pragma alloc_text(PAGE, DVGetStreamState)
  78. #pragma alloc_text(PAGE, DVStreamingStop)
  79. #pragma alloc_text(PAGE, DVStreamingStart)
  80. #pragma alloc_text(PAGE, DVSetStreamState)
  81. #pragma alloc_text(PAGE, DVStreamGetConnectionProperty)
  82. #pragma alloc_text(PAGE, DVGetDroppedFramesProperty)
  83. #pragma alloc_text(PAGE, DVGetStreamProperty)
  84. #pragma alloc_text(PAGE, DVSetStreamProperty)
  85. #pragma alloc_text(PAGE, DVCancelAllPackets)
  86. #pragma alloc_text(PAGE, DVOpenCloseMasterClock)
  87. #pragma alloc_text(PAGE, DVIndicateMasterClock)
  88. #endif
  89. #endif
  90. DV_FORMAT_INFO DVFormatInfoTable[] = {
  91. //
  92. // SD DVCR
  93. //
  94. {
  95. {
  96. FMT_DVCR,
  97. FDF0_50_60_NTSC,
  98. 0,
  99. 0
  100. },
  101. DIF_SEQS_PER_NTSC_FRAME,
  102. DV_NUM_OF_RCV_BUFFERS,
  103. DV_NUM_OF_XMT_BUFFERS,
  104. FRAME_SIZE_SD_DVCR_NTSC,
  105. FRAME_TIME_NTSC,
  106. SRC_PACKETS_PER_NTSC_FRAME,
  107. MAX_SRC_PACKETS_PER_NTSC_FRAME,
  108. CIP_DBS_SD_DVCR,
  109. CIP_FN_SD_DVCR,
  110. 0,
  111. FALSE, // Source packet header
  112. },
  113. {
  114. {
  115. FMT_DVCR,
  116. FDF0_50_60_PAL,
  117. 0,
  118. 0
  119. },
  120. DIF_SEQS_PER_PAL_FRAME,
  121. DV_NUM_OF_RCV_BUFFERS,
  122. DV_NUM_OF_XMT_BUFFERS,
  123. FRAME_SIZE_SD_DVCR_PAL,
  124. FRAME_TIME_PAL,
  125. SRC_PACKETS_PER_PAL_FRAME,
  126. MAX_SRC_PACKETS_PER_PAL_FRAME,
  127. CIP_DBS_SD_DVCR,
  128. CIP_FN_SD_DVCR,
  129. 0,
  130. FALSE, // Source packet header
  131. },
  132. #ifdef SUPPORT_HD_DVCR
  133. //
  134. // HD DVCR
  135. //
  136. {
  137. {
  138. FMT_DVCR,
  139. FDF0_50_60_NTSC,
  140. 0,
  141. 0
  142. },
  143. DIF_SEQS_PER_NTSC_FRAME_HD,
  144. DV_NUM_OF_RCV_BUFFERS,
  145. DV_NUM_OF_XMT_BUFFERS,
  146. FRAME_SIZE_HD_DVCR_NTSC,
  147. FRAME_TIME_NTSC,
  148. SRC_PACKETS_PER_NTSC_FRAME,
  149. MAX_SRC_PACKETS_PER_NTSC_FRAME,
  150. CIP_DBS_HD_DVCR,
  151. CIP_FN_HD_DVCR,
  152. 0,
  153. FALSE, // Source packet header
  154. },
  155. {
  156. {
  157. FMT_DVCR,
  158. FDF0_50_60_PAL,
  159. 0,
  160. 0
  161. },
  162. DIF_SEQS_PER_PAL_FRAME_HD,
  163. DV_NUM_OF_RCV_BUFFERS,
  164. DV_NUM_OF_XMT_BUFFERS,
  165. FRAME_SIZE_HD_DVCR_PAL,
  166. FRAME_TIME_PAL,
  167. SRC_PACKETS_PER_PAL_FRAME,
  168. MAX_SRC_PACKETS_PER_PAL_FRAME,
  169. CIP_DBS_HD_DVCR,
  170. CIP_FN_HD_DVCR,
  171. 0,
  172. FALSE, // Source packet header
  173. },
  174. #endif
  175. #ifdef MSDV_SUPPORT_SDL_DVCR
  176. //
  177. // SDL DVCR
  178. //
  179. {
  180. {
  181. FMT_DVCR,
  182. FDF0_50_60_NTSC,
  183. 0,
  184. 0
  185. },
  186. DIF_SEQS_PER_NTSC_FRAME_SDL,
  187. DV_NUM_OF_RCV_BUFFERS,
  188. DV_NUM_OF_XMT_BUFFERS,
  189. FRAME_SIZE_SDL_DVCR_NTSC,
  190. FRAME_TIME_NTSC,
  191. SRC_PACKETS_PER_NTSC_FRAME,
  192. MAX_SRC_PACKETS_PER_NTSC_FRAME,
  193. CIP_DBS_SDL_DVCR,
  194. CIP_FN_SDL_DVCR,
  195. 0,
  196. FALSE, // Source packet header
  197. },
  198. {
  199. {
  200. FMT_DVCR,
  201. FDF0_50_60_PAL,
  202. 0,
  203. 0
  204. },
  205. DIF_SEQS_PER_PAL_FRAME_SDL,
  206. DV_NUM_OF_RCV_BUFFERS,
  207. DV_NUM_OF_XMT_BUFFERS,
  208. FRAME_SIZE_SDL_DVCR_PAL,
  209. FRAME_TIME_PAL,
  210. SRC_PACKETS_PER_PAL_FRAME,
  211. MAX_SRC_PACKETS_PER_PAL_FRAME,
  212. CIP_DBS_SDL_DVCR,
  213. CIP_FN_SDL_DVCR,
  214. 0,
  215. FALSE, // Source packet header
  216. },
  217. #endif // Not implemented.
  218. };
  219. #define MSDV_FORMATS_SUPPORTED (SIZEOF_ARRAY(DVFormatInfoTable))
  220. VOID
  221. DVTerminateAttachFrameThread(
  222. IN PSTREAMEX pStrmExt
  223. );
  224. VOID
  225. DVIniDevExtStruct(
  226. IN PDVCR_EXTENSION pDevExt,
  227. IN PPORT_CONFIGURATION_INFORMATION pConfigInfo
  228. )
  229. /*++
  230. Routine Description:
  231. Initialiaze the device extension structure.
  232. --*/
  233. {
  234. ULONG i;
  235. RtlZeroMemory( pDevExt, sizeof(DVCR_EXTENSION) );
  236. //
  237. // Cache what are in ConfigInfo in device extension
  238. //
  239. pDevExt->pBusDeviceObject = pConfigInfo->PhysicalDeviceObject; // IoCallDriver()
  240. pDevExt->pPhysicalDeviceObject = pConfigInfo->RealPhysicalDeviceObject; // Used in PnP API
  241. //
  242. // Allow only one stream open at a time to avoid cyclic format
  243. //
  244. pDevExt->cndStrmOpen = 0;
  245. //
  246. // Serialize in the event of getting two consecutive SRB_OPEN_STREAMs
  247. //
  248. KeInitializeMutex( &pDevExt->hMutex, 0); // Level 0 and in Signal state
  249. //
  250. // Initialize our pointer to stream extension
  251. //
  252. for (i=0; i<DV_STREAM_COUNT; i++) {
  253. pDevExt->paStrmExt[i] = NULL;
  254. }
  255. //
  256. // Bus reset, surprise removal
  257. //
  258. pDevExt->bDevRemoved = FALSE;
  259. pDevExt->PowerState = PowerDeviceD0;
  260. //
  261. // External device control (AV/C commands)
  262. //
  263. KeInitializeSpinLock( &pDevExt->AVCCmdLock ); // To guard the count
  264. pDevExt->cntCommandQueued = 0; // Cmd that is completed its life cycle waiting to be read (most for RAW_AVC's Set/Read model)
  265. InitializeListHead(&pDevExt->AVCCmdList);
  266. // Initialize the list of possible opcode values of the response
  267. // from a Transport State status or notify command. The first item
  268. // is the number of values that follow.
  269. ASSERT(sizeof(pDevExt->TransportModes) == 5);
  270. pDevExt->TransportModes[0] = 4;
  271. pDevExt->TransportModes[1] = 0xC1;
  272. pDevExt->TransportModes[2] = 0xC2;
  273. pDevExt->TransportModes[3] = 0xC3;
  274. pDevExt->TransportModes[4] = 0xC4;
  275. #ifdef SUPPORT_OPTIMIZE_AVCCMD_RETRIES
  276. // Set to default values used by avc.sys
  277. pDevExt->AVCCmdRetries = DEFAULT_AVC_RETRIES;
  278. pDevExt->DrvLoadCompleted = FALSE;
  279. pDevExt->AVCCmdRespTimeMax = 0;
  280. pDevExt->AVCCmdRespTimeMin = DEFAULT_AVC_TIMEOUT * (DEFAULT_AVC_RETRIES+1) / 10000;
  281. pDevExt->AVCCmdRespTimeSum = 0;
  282. pDevExt->AVCCmdCount = 0;
  283. #endif
  284. // AVC Command flow control
  285. KeInitializeMutex(&pDevExt->hMutexIssueAVCCmd, 0);
  286. }
  287. NTSTATUS
  288. DVGetDevInfo(
  289. IN PDVCR_EXTENSION pDevExt,
  290. IN PAV_61883_REQUEST pAVReq
  291. )
  292. /*++
  293. Routine Description:
  294. Issue AVC command to determine basic device information and cache them in the device extension.
  295. --*/
  296. {
  297. NTSTATUS Status;
  298. BYTE bAvcBuf[MAX_FCP_PAYLOAD_SIZE]; // For issue AV/C command within this module
  299. PKSPROPERTY_EXTXPORT_S pXPrtProperty; // Point to bAvcBuf;
  300. PAGED_CODE();
  301. //
  302. // Get unit's capabilities such as
  303. // Number of input/output plugs, data rate
  304. // UniqueID, VendorID and ModelID
  305. //
  306. if(!NT_SUCCESS(
  307. Status = DVGetUnitCapabilities(
  308. pDevExt
  309. ))) {
  310. TRACE(TL_PNP_ERROR,("Av61883_GetUnitCapabilities Failed = 0x%x\n", Status));
  311. return Status;
  312. }
  313. #ifdef NT51_61883
  314. //
  315. // Set to create local plug in exclusive address mode:
  316. // This is needed for device that does not support CCM, such as DV.
  317. //
  318. // PBinder: the problem is that you cannot expose a global plug (all nodes on the bus can see it),
  319. // since they have no knowledge of what that plug is used for (mpeg2/dv/audio/etc).
  320. // so instead, you must create a plug in an exclusive address range. this means that only the device
  321. // that you loaded for will see the plug. this means that if you had two pc's and a dv camcorder,
  322. // on both pc's, you'll have a plug you created for the dv camcorder, but the pc's will not be able
  323. // to see the plug you created, only the dv camcorder. Keep in mind, this should only be used for
  324. // devices that do not support some mechanism of determining what plug to use (such as ccm).
  325. // so for any device that just goes out and uses plug #0, this must be enabled.
  326. //
  327. if(!NT_SUCCESS(
  328. Status = DVSetAddressRangeExclusive(
  329. pDevExt
  330. ))) {
  331. return Status;
  332. }
  333. #endif // NT51_61883
  334. //
  335. // Get DV's oPCR[0]
  336. //
  337. if(pDevExt->NumOutputPlugs) {
  338. if(!NT_SUCCESS(
  339. Status = DVGetDVPlug(
  340. pDevExt,
  341. CMP_PlugOut,
  342. 0, // Plug [0]
  343. &pDevExt->hOPcrDV
  344. ))) {
  345. return Status;
  346. }
  347. }
  348. else {
  349. pDevExt->hOPcrDV = NULL; // Redundant since we Zero the whole DeviceExtension
  350. TRACE(TL_PNP_ERROR,("\'No output plug!\n"));
  351. //
  352. // This is bad! We cannot even stream from this DV device.
  353. //
  354. }
  355. //
  356. // Get DV's iPCR
  357. //
  358. if(pDevExt->NumInputPlugs) {
  359. if(!NT_SUCCESS(
  360. Status = DVGetDVPlug(
  361. pDevExt,
  362. CMP_PlugIn,
  363. 0, // Plug [0]
  364. &pDevExt->hIPcrDV
  365. ))) {
  366. return Status;
  367. }
  368. }
  369. else {
  370. pDevExt->hIPcrDV = NULL; // Redundant since we Zero the whole DeviceExtension
  371. TRACE(TL_PNP_ERROR,("\'No input plug!\n"));
  372. //
  373. // Some PAL camcorder has no DVIN plug; we will refuse to make PC->DV connection.
  374. //
  375. }
  376. #if 0 // Device control can still work!
  377. //
  378. // Need plug to stream DV (either direction)
  379. //
  380. if( pDevExt->hOPcrDV == NULL
  381. && pDevExt->hIPcrDV == NULL) {
  382. TRACE(TL_PNP_ERROR,("\'No input or output plug; return STATUS_INSUFFICIENT_RESOURCES!\n"));
  383. //
  384. // Cannot stream
  385. //
  386. return = STATUS_INSUFFICIENT_RESOUCES;
  387. }
  388. #endif
  389. //
  390. // Subunit_Info : VCR or camera
  391. //
  392. DVDelayExecutionThread(DV_AVC_CMD_DELAY_INTER_CMD);
  393. Status =
  394. DVIssueAVCCommand(
  395. pDevExt,
  396. AVC_CTYPE_STATUS,
  397. DV_SUBUNIT_INFO,
  398. (PVOID) bAvcBuf
  399. );
  400. if(STATUS_SUCCESS == Status) {
  401. TRACE(TL_PNP_WARNING|TL_FCP_WARNING,("\'DVGetDevInfo: Status %x DV_SUBUNIT_INFO (%x %x %x %x)\n",
  402. Status, bAvcBuf[0], bAvcBuf[1], bAvcBuf[2], bAvcBuf[3]));
  403. // Support DV (Camera+DVCR), DVCR, or analog-DV converter
  404. if( bAvcBuf[0] != AVC_DEVICE_TAPE_REC
  405. && bAvcBuf[1] != AVC_DEVICE_TAPE_REC
  406. && bAvcBuf[2] != AVC_DEVICE_TAPE_REC
  407. && bAvcBuf[3] != AVC_DEVICE_TAPE_REC)
  408. {
  409. TRACE(TL_PNP_ERROR,("DVGetDevInfo:Device supported: %x, %x; (VCR %x, Camera %x)\n",
  410. bAvcBuf[0], bAvcBuf[1], AVC_DEVICE_TAPE_REC, AVC_DEVICE_CAMERA));
  411. return STATUS_NOT_SUPPORTED; // We only support unit with a tape subunit
  412. }
  413. else {
  414. // DVCR..
  415. }
  416. } else {
  417. TRACE(TL_PNP_ERROR,("DVGetDevInfo: DV_SUBUNIT_INFO failed, Status %x\n", Status));
  418. //
  419. // Cannot open this device if it does not support manadatory AVC SUBUnit status command.
  420. // However, we are making an exception for the DV converter box (will return TIMEOUT).
  421. //
  422. // Has our device gone away?
  423. if ( STATUS_IO_DEVICE_ERROR == Status
  424. || STATUS_REQUEST_ABORTED == Status)
  425. return Status;
  426. }
  427. //
  428. // Medium_Info: MediaPresent, MediaType, RecordInhibit
  429. //
  430. pXPrtProperty = (PKSPROPERTY_EXTXPORT_S) bAvcBuf;
  431. DVDelayExecutionThread(DV_AVC_CMD_DELAY_INTER_CMD);
  432. Status =
  433. DVIssueAVCCommand(
  434. pDevExt,
  435. AVC_CTYPE_STATUS,
  436. VCR_MEDIUM_INFO,
  437. (PVOID) pXPrtProperty
  438. );
  439. if(STATUS_SUCCESS == Status) {
  440. pDevExt->bHasTape = pXPrtProperty->u.MediumInfo.MediaPresent;
  441. TRACE(TL_PNP_WARNING|TL_FCP_WARNING,("\'DVGetDevInfo: Status %x HasTape %s, VCR_MEDIUM_INFO (%x %x %x %x)\n",
  442. Status, pDevExt->bHasTape ? "Yes" : "No", bAvcBuf[0], bAvcBuf[1], bAvcBuf[2], bAvcBuf[3]));
  443. } else {
  444. pDevExt->bHasTape = FALSE;
  445. TRACE(TL_PNP_ERROR,("DVGetDevInfo: VCR_MEDIUM_INFO failed, Status %x\n", Status));
  446. // Has our device gone away?
  447. if ( STATUS_IO_DEVICE_ERROR == Status
  448. || STATUS_REQUEST_ABORTED == Status)
  449. return Status;
  450. }
  451. //
  452. // If this is a Panasonic AVC device, we will detect if it is a DVCPro format;
  453. // This needs to be called before MediaFormat
  454. //
  455. if(pDevExt->ulVendorID == VENDORID_PANASONIC) {
  456. DVDelayExecutionThread(DV_AVC_CMD_DELAY_INTER_CMD);
  457. DVGetDevIsItDVCPro(
  458. pDevExt
  459. );
  460. }
  461. //
  462. // Medium format: NTSC or PAL
  463. //
  464. pDevExt->VideoFormatIndex = FMT_IDX_SD_DVCR_NTSC; // Default
  465. DVDelayExecutionThread(DV_AVC_CMD_DELAY_INTER_CMD);
  466. if(!DVGetDevSignalFormat(
  467. pDevExt,
  468. KSPIN_DATAFLOW_OUT,
  469. 0)) {
  470. TRACE(TL_PNP_ERROR,("\'!!! Cannot determine IN/OUTPUT SIGNAL MODE!!!! Driver abort !!!\n"));
  471. return STATUS_UNSUCCESSFUL; // STATUS_NOT_SUPPORTED;
  472. } else {
  473. if( pDevExt->VideoFormatIndex != FMT_IDX_SD_DVCR_NTSC
  474. && pDevExt->VideoFormatIndex != FMT_IDX_SD_DVCR_PAL
  475. && pDevExt->VideoFormatIndex != FMT_IDX_SDL_DVCR_NTSC
  476. && pDevExt->VideoFormatIndex != FMT_IDX_SDL_DVCR_PAL
  477. ) {
  478. TRACE(TL_PNP_ERROR,("**** Format idx %d not supported by this driver ***\n", pDevExt->VideoFormatIndex));
  479. ASSERT(pDevExt->VideoFormatIndex == FMT_IDX_SD_DVCR_NTSC \
  480. || pDevExt->VideoFormatIndex == FMT_IDX_SD_DVCR_PAL \
  481. || pDevExt->VideoFormatIndex == FMT_IDX_SDL_DVCR_NTSC \
  482. || pDevExt->VideoFormatIndex == FMT_IDX_SDL_DVCR_PAL \
  483. );
  484. return STATUS_UNSUCCESSFUL; // STATUS_NOT_SUPPORTED;
  485. }
  486. }
  487. //
  488. // Mode of Operation: 0(Undetermined), Camera or VCR
  489. //
  490. DVDelayExecutionThread(DV_AVC_CMD_DELAY_INTER_CMD);
  491. DVGetDevModeOfOperation(
  492. pDevExt
  493. );
  494. return STATUS_SUCCESS; // Status;
  495. }
  496. NTSTATUS
  497. DVInitializeDevice(
  498. IN PDVCR_EXTENSION pDevExt,
  499. IN PPORT_CONFIGURATION_INFORMATION pConfigInfo,
  500. IN PAV_61883_REQUEST pAVReq
  501. )
  502. /*++
  503. Routine Description:
  504. This where we perform the necessary initialization tasks.
  505. --*/
  506. {
  507. int i;
  508. NTSTATUS Status = STATUS_SUCCESS;
  509. PAGED_CODE();
  510. //
  511. // Initialize the device extension structure
  512. //
  513. DVIniDevExtStruct(
  514. pDevExt,
  515. pConfigInfo
  516. );
  517. #ifdef READ_CUTOMIZE_REG_VALUES
  518. //
  519. // Get values from this device's own registry
  520. //
  521. DVGetPropertyValuesFromRegistry(
  522. pDevExt
  523. );
  524. #endif
  525. //
  526. // Query device information at the laod time:
  527. // Subunit
  528. // Unit Info
  529. // Mode of operation
  530. // NTSC or PAL
  531. // Speed
  532. // oPCR/iPCR
  533. //
  534. Status =
  535. DVGetDevInfo(
  536. pDevExt,
  537. pAVReq
  538. );
  539. if(!NT_SUCCESS(Status)) {
  540. TRACE(TL_PNP_ERROR,("\'DVGetDevInfo failed %x\n", Status));
  541. // While driver is loading, the device could be unplug.
  542. // In this case, the AVC command can return STATUS_REQUEST_ABORTED.
  543. // In DvGetDevInfo may then return STATUS_NOT_SUPPORTED or STATUS_UNSUCCESSFUL.
  544. // We will then return this status to indicate loading failure.
  545. #if 0 // DBG
  546. if(Status != STATUS_REQUEST_ABORTED && !NT_SUCCESS(Status)) {
  547. ASSERT(NT_SUCCESS(Status) && "DVGetDevInfo failed");
  548. }
  549. #endif
  550. return Status;
  551. }
  552. #ifdef NT51_61883
  553. //
  554. // Get Unit isoch parameters
  555. //
  556. if(!NT_SUCCESS(
  557. Status = DVGetUnitIsochParam(
  558. pDevExt,
  559. &pDevExt->UnitIoschParams
  560. )))
  561. return Status;
  562. //
  563. // Create a local output plug. This plug is used to updated isoch
  564. // resource used when connection was made.
  565. //
  566. if(!NT_SUCCESS(
  567. Status = DVCreateLocalPlug(
  568. pDevExt,
  569. CMP_PlugOut,
  570. 0, // Plug number
  571. &pDevExt->hOPcrPC
  572. )))
  573. return Status;
  574. #endif
  575. //
  576. // Note: Must do ExAllocatePool after DVIniDevExtStruct() since ->paCurrentStrmInfo is initialized.
  577. // Since the format that this driver support is known when this driver is known,'
  578. // the stream information table need to be custonmized. Make a copy and customized it.
  579. //
  580. //
  581. // Set the size of the stream inforamtion structure that we returned in SRB_GET_STREAM_INFO
  582. //
  583. pDevExt->paCurrentStrmInfo = (HW_STREAM_INFORMATION *)
  584. ExAllocatePool(NonPagedPool, sizeof(HW_STREAM_INFORMATION) * DV_STREAM_COUNT);
  585. if(!pDevExt->paCurrentStrmInfo)
  586. return STATUS_INSUFFICIENT_RESOURCES;
  587. pConfigInfo->StreamDescriptorSize =
  588. (DV_STREAM_COUNT * sizeof(HW_STREAM_INFORMATION)) + // number of stream descriptors
  589. sizeof(HW_STREAM_HEADER); // and 1 stream header
  590. // Make a copy of the default stream information
  591. for(i = 0; i < DV_STREAM_COUNT; i++ )
  592. pDevExt->paCurrentStrmInfo[i] = DVStreams[i].hwStreamInfo;
  593. // Set AUDIO AUX to reflect: NTSC/PAL, consumer DV or DVCPRO
  594. if(pDevExt->bDVCPro) {
  595. // Note: there is no DVInfo in VideoInfoHeader but there is for the iAV streams.
  596. SDDV_IavPalStream.DVVideoInfo.dwDVAAuxSrc = AAUXSRC_SD_PAL_DVCPRO;
  597. SDDV_IavPalStream.DVVideoInfo.dwDVAAuxSrc1 = AAUXSRC_SD_PAL_DVCPRO | AAUXSRC_AMODE_F;
  598. SDDV_IavPalStream.DVVideoInfo.dwDVVAuxSrc = VAUXSRC_DEFAULT | AUXSRC_PAL | AUXSRC_STYPE_SD_DVCPRO;
  599. SDDV_IavNtscStream.DVVideoInfo.dwDVAAuxSrc = AAUXSRC_SD_NTSC_DVCPRO;
  600. SDDV_IavNtscStream.DVVideoInfo.dwDVAAuxSrc1= AAUXSRC_SD_NTSC_DVCPRO | AAUXSRC_AMODE_F;
  601. SDDV_IavNtscStream.DVVideoInfo.dwDVVAuxSrc = VAUXSRC_DEFAULT | AUXSRC_NTSC | AUXSRC_STYPE_SD_DVCPRO;
  602. } else {
  603. // This might be necessary for the 2nd instance of MSDV (1st:DVCPRO; 2nd:DVSD)
  604. SDDV_IavPalStream.DVVideoInfo.dwDVAAuxSrc = AAUXSRC_SD_PAL;
  605. SDDV_IavPalStream.DVVideoInfo.dwDVAAuxSrc1 = AAUXSRC_SD_PAL | AAUXSRC_AMODE_F;
  606. SDDV_IavPalStream.DVVideoInfo.dwDVVAuxSrc = VAUXSRC_DEFAULT | AUXSRC_PAL | AUXSRC_STYPE_SD;
  607. SDDV_IavNtscStream.DVVideoInfo.dwDVAAuxSrc = AAUXSRC_SD_NTSC;
  608. SDDV_IavNtscStream.DVVideoInfo.dwDVAAuxSrc1= AAUXSRC_SD_NTSC | AAUXSRC_AMODE_F;
  609. SDDV_IavNtscStream.DVVideoInfo.dwDVVAuxSrc = VAUXSRC_DEFAULT | AUXSRC_NTSC | AUXSRC_STYPE_SD;
  610. }
  611. // Initialize last time format was updated
  612. pDevExt->tmLastFormatUpdate = GetSystemTime();
  613. TRACE(TL_PNP_WARNING,("\'#### %s%s:%s:%s PhyDO %x, BusDO %x, DevExt %x, FrmSz %d; StrmIf %d\n",
  614. (pDevExt->ulDevType == ED_DEVTYPE_VCR ? "DVCR" : (pDevExt->ulDevType == ED_DEVTYPE_CAMERA ? "Camera" : "Tuner?")),
  615. pDevExt->bDVCPro ? "(DVCPRO)":"",
  616. (pDevExt->VideoFormatIndex == FMT_IDX_SD_DVCR_NTSC || pDevExt->VideoFormatIndex == FMT_IDX_SDL_DVCR_NTSC)? "SD:NTSC" : (pDevExt->VideoFormatIndex == FMT_IDX_SD_DVCR_PAL || pDevExt->VideoFormatIndex == FMT_IDX_SDL_DVCR_PAL) ? "PAL" : "MPEG_TS?",
  617. (pDevExt->ulDevType == ED_DEVTYPE_VCR && pDevExt->NumInputPlugs > 0) ? "CanRec" : "NotRec",
  618. pDevExt->pPhysicalDeviceObject,
  619. pDevExt->pBusDeviceObject,
  620. pDevExt,
  621. DVFormatInfoTable[pDevExt->VideoFormatIndex].ulFrameSize,
  622. pConfigInfo->StreamDescriptorSize
  623. ));
  624. return STATUS_SUCCESS;
  625. }
  626. NTSTATUS
  627. DVInitializeCompleted(
  628. IN PDVCR_EXTENSION pDevExt
  629. )
  630. /*++
  631. Routine Description:
  632. This where we perform the necessary initialization tasks.
  633. --*/
  634. {
  635. PAGED_CODE();
  636. #ifdef SUPPORT_OPTIMIZE_AVCCMD_RETRIES
  637. //
  638. // Determine retries
  639. //
  640. pDevExt->DrvLoadCompleted = TRUE;
  641. if((pDevExt->AVCCmdRespTimeSum / pDevExt->AVCCmdCount) >
  642. (DEFAULT_AVC_TIMEOUT * DEFAULT_AVC_RETRIES / 10000)) {
  643. // If every AVC command was timed out, do not bother to retry.
  644. pDevExt->AVCCmdRetries = 0;
  645. } else {
  646. #if 0
  647. // Some camcorders do not queue up comand so follow a transport
  648. // state change, it will not accept any AVC command until transport
  649. // state is in the stable state. So further delay is needed.
  650. if(
  651. // Exception for Samsung; always timeout following XPrt command
  652. // Or maybe it does not support transport state status command!
  653. pDevExt->ulVendorID == VENDORID_SAMSUNG
  654. ) {
  655. TRACE(TL_PNP_ERROR,("Samsung DV device: use default AVC setting.\n"));
  656. } else {
  657. pDevExt->AVCCmdRetries = MAX_AVC_CMD_RETRIES;
  658. }
  659. #endif
  660. }
  661. TRACE(TL_PNP_ERROR,("AVCCMd Response Time: pDevExt:%x; Range (%d..%d); Avg %d/%d = %d; Retries:%d\n",
  662. pDevExt,
  663. pDevExt->AVCCmdRespTimeMin,
  664. pDevExt->AVCCmdRespTimeMax,
  665. pDevExt->AVCCmdRespTimeSum,
  666. pDevExt->AVCCmdCount,
  667. pDevExt->AVCCmdRespTimeSum / pDevExt->AVCCmdCount,
  668. pDevExt->AVCCmdRetries
  669. ));
  670. #endif
  671. return STATUS_SUCCESS;
  672. }
  673. NTSTATUS
  674. DVGetStreamInfo(
  675. IN PDVCR_EXTENSION pDevExt,
  676. IN ULONG ulBytesToTransfer,
  677. IN PHW_STREAM_HEADER pStreamHeader,
  678. IN PHW_STREAM_INFORMATION pStreamInfo
  679. )
  680. /*++
  681. Routine Description:
  682. Returns the information of all streams that are supported by the driver
  683. --*/
  684. {
  685. ULONG i;
  686. PAGED_CODE();
  687. //
  688. // Make sure we have enough space to return our stream informations
  689. //
  690. if(ulBytesToTransfer < sizeof (HW_STREAM_HEADER) + sizeof(HW_STREAM_INFORMATION) * DV_STREAM_COUNT ) {
  691. TRACE(TL_PNP_ERROR,("\'DVGetStrmInfo: ulBytesToTransfer %d ?= %d\n",
  692. ulBytesToTransfer, sizeof(HW_STREAM_HEADER) + sizeof(HW_STREAM_INFORMATION) * DV_STREAM_COUNT ));
  693. return STATUS_INVALID_PARAMETER;
  694. }
  695. //
  696. // Initialize stream header:
  697. // Device properties
  698. // Streams
  699. //
  700. RtlZeroMemory(pStreamHeader, sizeof(HW_STREAM_HEADER));
  701. pStreamHeader->NumberOfStreams = DV_STREAM_COUNT;
  702. pStreamHeader->SizeOfHwStreamInformation = sizeof(HW_STREAM_INFORMATION);
  703. pStreamHeader->NumDevPropArrayEntries = NUMBER_VIDEO_DEVICE_PROPERTIES;
  704. pStreamHeader->DevicePropertiesArray = (PKSPROPERTY_SET) VideoDeviceProperties;
  705. pStreamHeader->NumDevEventArrayEntries = NUMBER_VIDEO_DEVICE_EVENTS;
  706. pStreamHeader->DeviceEventsArray = (PKSEVENT_SET) VideoDeviceEvents;
  707. TRACE(TL_PNP_TRACE,("\'DVGetStreamInfo: StreamPropEntries %d, DevicePropEntries %d\n",
  708. pStreamHeader->NumberOfStreams, pStreamHeader->NumDevPropArrayEntries));
  709. //
  710. // Initialize the stream structure.
  711. //
  712. for( i = 0; i < DV_STREAM_COUNT; i++ )
  713. *pStreamInfo++ = pDevExt->paCurrentStrmInfo[i];
  714. //
  715. //
  716. // store a pointer to the topology for the device
  717. //
  718. pStreamHeader->Topology = &Topology;
  719. return STATUS_SUCCESS;
  720. }
  721. BOOL
  722. DVVerifyDataFormat(
  723. PKSDATAFORMAT pKSDataFormatToVerify,
  724. ULONG StreamNumber,
  725. ULONG ulSupportedFrameSize,
  726. HW_STREAM_INFORMATION * paCurrentStrmInfo
  727. )
  728. /*++
  729. Routine Description:
  730. Checks the validity of a format request by walking through the array of
  731. supported KSDATA_RANGEs for a given stream.
  732. Arguments:
  733. pKSDataFormat - pointer of a KS_DATAFORMAT_VIDEOINFOHEADER structure.
  734. StreamNumber - index of the stream being queried / opened.
  735. Return Value:
  736. TRUE if the format is supported
  737. FALSE if the format cannot be suppored
  738. --*/
  739. {
  740. PKSDATAFORMAT *pAvailableFormats;
  741. int NumberOfFormatArrayEntries;
  742. int j;
  743. PAGED_CODE();
  744. //
  745. // Make sure the stream index is valid (0..DV_STREAM_COUNT-1)
  746. //
  747. if(StreamNumber >= DV_STREAM_COUNT) {
  748. return FALSE;
  749. }
  750. //
  751. // How many formats does this stream support?
  752. //
  753. NumberOfFormatArrayEntries = paCurrentStrmInfo[StreamNumber].NumberOfFormatArrayEntries;
  754. //
  755. // Get the pointer to the array of available formats
  756. //
  757. pAvailableFormats = paCurrentStrmInfo[StreamNumber].StreamFormatsArray;
  758. //
  759. // Walk the array, searching for a match
  760. //
  761. for (j = 0; j < NumberOfFormatArrayEntries; j++, pAvailableFormats++) {
  762. //
  763. // Check supported sample size (== frame size). e.g. SD and SDL have different sample size.
  764. //
  765. if( (*pAvailableFormats)->SampleSize != ulSupportedFrameSize) {
  766. TRACE(TL_STRM_TRACE,("\' StrmNum %d, %d of %d formats, SizeToVerify %d *!=* SupportedSampleSize %d\n",
  767. StreamNumber,
  768. j+1, NumberOfFormatArrayEntries,
  769. (*pAvailableFormats)->SampleSize,
  770. ulSupportedFrameSize));
  771. continue;
  772. }
  773. if (!DVCmpGUIDsAndFormatSize(
  774. pKSDataFormatToVerify,
  775. *pAvailableFormats,
  776. TRUE, // Compare subformat
  777. FALSE /* CompareFormatSize */ )) {
  778. continue;
  779. }
  780. //
  781. // Additional verification test
  782. //
  783. if(IsEqualGUID (&pKSDataFormatToVerify->Specifier, &KSDATAFORMAT_SPECIFIER_VIDEOINFO)) {
  784. // Make sure
  785. if( ((PKS_DATAFORMAT_VIDEOINFOHEADER)pKSDataFormatToVerify)->VideoInfoHeader.bmiHeader.biSizeImage !=
  786. ulSupportedFrameSize) {
  787. TRACE(TL_STRM_WARNING,("VIDEOINFO: biSizeToVerify %d != Supported %d\n",
  788. ((PKS_DATAFORMAT_VIDEOINFOHEADER)pKSDataFormatToVerify)->VideoInfoHeader.bmiHeader.biSizeImage,
  789. ulSupportedFrameSize
  790. ));
  791. continue;
  792. } else {
  793. TRACE(TL_STRM_TRACE,("VIDOINFO: **** biSizeToVerify %d == Supported %d\n",
  794. ((PKS_DATAFORMAT_VIDEOINFOHEADER)pKSDataFormatToVerify)->VideoInfoHeader.bmiHeader.biSizeImage,
  795. ulSupportedFrameSize
  796. ));
  797. }
  798. #ifdef SUPPORT_NEW_AVC
  799. } else if (IsEqualGUID (&pKSDataFormatToVerify->Specifier, &KSDATAFORMAT_SPECIFIER_DVINFO) ||
  800. IsEqualGUID (&pKSDataFormatToVerify->Specifier, &KSDATAFORMAT_SPECIFIER_DV_AVC)
  801. ) {
  802. #else
  803. } else if (IsEqualGUID (&pKSDataFormatToVerify->Specifier, &KSDATAFORMAT_SPECIFIER_DVINFO)) {
  804. #endif
  805. // Test 50/60 bit
  806. if((((PKS_DATARANGE_DVVIDEO) pKSDataFormatToVerify)->DVVideoInfo.dwDVAAuxSrc & MASK_AUX_50_60_BIT) !=
  807. (((PKS_DATARANGE_DVVIDEO) *pAvailableFormats)->DVVideoInfo.dwDVAAuxSrc & MASK_AUX_50_60_BIT) ||
  808. (((PKS_DATARANGE_DVVIDEO) pKSDataFormatToVerify)->DVVideoInfo.dwDVVAuxSrc & MASK_AUX_50_60_BIT) !=
  809. (((PKS_DATARANGE_DVVIDEO) *pAvailableFormats)->DVVideoInfo.dwDVVAuxSrc & MASK_AUX_50_60_BIT) ) {
  810. TRACE(TL_STRM_WARNING,("VerifyFormat failed: ASrc: %x!=%x (MSDV);or VSrc: %x!=%x\n",
  811. ((PKS_DATARANGE_DVVIDEO) pKSDataFormatToVerify)->DVVideoInfo.dwDVAAuxSrc,
  812. ((PKS_DATARANGE_DVVIDEO) *pAvailableFormats)->DVVideoInfo.dwDVAAuxSrc,
  813. ((PKS_DATARANGE_DVVIDEO) pKSDataFormatToVerify)->DVVideoInfo.dwDVVAuxSrc,
  814. ((PKS_DATARANGE_DVVIDEO) *pAvailableFormats)->DVVideoInfo.dwDVVAuxSrc
  815. ));
  816. continue;
  817. }
  818. #if 0
  819. // Make sure the verified format's sample size is supported by the device
  820. if(ulSupportedFrameSize != ((PKS_DATARANGE_DVVIDEO) pKSDataFormatToVerify)->DataRange.SampleSize) {
  821. TRACE(TL_STRM_WARNING,("\'SupportedFrameSize %d != SampleSize:%d\n",
  822. ulSupportedFrameSize, ((PKS_DATARANGE_DVVIDEO)pKSDataFormatToVerify)->DataRange.SampleSize));
  823. continue;
  824. }
  825. #endif
  826. TRACE(TL_STRM_TRACE,("\'DVINFO: dwDVAAuxCtl %x, Supported %x\n",
  827. ((PKS_DATARANGE_DVVIDEO) pKSDataFormatToVerify)->DVVideoInfo.dwDVAAuxSrc,
  828. ((PKS_DATARANGE_DVVIDEO) *pAvailableFormats)->DVVideoInfo.dwDVAAuxSrc
  829. ));
  830. TRACE(TL_STRM_TRACE,("\'DVINFO: dwDVVAuxSrc %x, Supported %x\n",
  831. ((PKS_DATARANGE_DVVIDEO) pKSDataFormatToVerify)->DVVideoInfo.dwDVVAuxSrc,
  832. ((PKS_DATARANGE_DVVIDEO) *pAvailableFormats)->DVVideoInfo.dwDVVAuxSrc
  833. ));
  834. }
  835. else {
  836. continue;
  837. }
  838. return TRUE;
  839. }
  840. return FALSE;
  841. }
  842. NTSTATUS
  843. DVGetDataIntersection(
  844. IN ULONG ulStreamNumber,
  845. IN PKSDATARANGE pDataRange,
  846. OUT PVOID pDataFormatBuffer,
  847. IN ULONG ulSizeOfDataFormatBuffer,
  848. IN ULONG ulSupportedFrameSize,
  849. OUT ULONG *pulActualBytesTransferred,
  850. HW_STREAM_INFORMATION * paCurrentStrmInfo
  851. #ifdef SUPPORT_NEW_AVC
  852. ,IN HANDLE hPlug
  853. #endif
  854. )
  855. /*++
  856. Routine Description:
  857. Called to get a DATAFORMAT from a DATARANGE.
  858. --*/
  859. {
  860. BOOL bMatchFound = FALSE;
  861. ULONG ulFormatSize;
  862. ULONG j;
  863. ULONG ulNumberOfFormatArrayEntries;
  864. PKSDATAFORMAT *pAvailableFormats;
  865. PAGED_CODE();
  866. //
  867. // Check that the stream number is valid
  868. //
  869. if(ulStreamNumber >= DV_STREAM_COUNT) {
  870. TRACE(TL_STRM_ERROR,("\'DVCRFormatFromRange: ulStreamNumber %d >= DV_STREAM_COUNT %d\n", ulStreamNumber, DV_STREAM_COUNT));
  871. return STATUS_NOT_SUPPORTED;
  872. }
  873. // Number of format this stream supports
  874. ulNumberOfFormatArrayEntries = paCurrentStrmInfo[ulStreamNumber].NumberOfFormatArrayEntries;
  875. //
  876. // Get the pointer to the array of available formats
  877. //
  878. pAvailableFormats = paCurrentStrmInfo[ulStreamNumber].StreamFormatsArray;
  879. //
  880. // Walk the formats supported by the stream searching for a match
  881. // Note: DataIntersection is really enumerating supported MediaType only!
  882. // SO matter compare format is NTSC or PAL, we need suceeded both;
  883. // however, we will copy back only the format is currently supported (NTSC or PAL).
  884. //
  885. for(j = 0; j < ulNumberOfFormatArrayEntries; j++, pAvailableFormats++) {
  886. if(!DVCmpGUIDsAndFormatSize(pDataRange, *pAvailableFormats, FALSE, TRUE)) {
  887. TRACE(TL_STRM_TRACE,("\'DVCmpGUIDsAndFormatSize failed!\n"));
  888. continue;
  889. }
  890. //
  891. // Check supported sample size (== frame size).
  892. //
  893. if( (*pAvailableFormats)->SampleSize != ulSupportedFrameSize) {
  894. TRACE(TL_STRM_TRACE,("\' StrmNum %d, %d of %d formats, SizeToVerify %d *!=* SupportedSampleSize %d\n",
  895. ulStreamNumber,
  896. j+1, ulNumberOfFormatArrayEntries,
  897. (*pAvailableFormats)->SampleSize,
  898. ulSupportedFrameSize));
  899. continue;
  900. }
  901. // -------------------------------------------------------------------
  902. // Specifier FORMAT_VideoInfo for VIDEOINFOHEADER
  903. // -------------------------------------------------------------------
  904. if(IsEqualGUID (&pDataRange->Specifier, &KSDATAFORMAT_SPECIFIER_VIDEOINFO)) {
  905. PKS_DATARANGE_VIDEO pDataRangeVideoToVerify = (PKS_DATARANGE_VIDEO) pDataRange;
  906. PKS_DATARANGE_VIDEO pDataRangeVideo = (PKS_DATARANGE_VIDEO) *pAvailableFormats;
  907. #if 0
  908. //
  909. // Check that the other fields match
  910. //
  911. if ((pDataRangeVideoToVerify->bFixedSizeSamples != pDataRangeVideo->bFixedSizeSamples)
  912. || (pDataRangeVideoToVerify->bTemporalCompression != pDataRangeVideo->bTemporalCompression)
  913. || (pDataRangeVideoToVerify->StreamDescriptionFlags != pDataRangeVideo->StreamDescriptionFlags)
  914. || (pDataRangeVideoToVerify->MemoryAllocationFlags != pDataRangeVideo->MemoryAllocationFlags)
  915. #ifdef COMPARE_CONFIG_CAP
  916. || (RtlCompareMemory (&pDataRangeVideoToVerify->ConfigCaps,
  917. &pDataRangeVideo->ConfigCaps,
  918. sizeof (KS_VIDEO_STREAM_CONFIG_CAPS)) !=
  919. sizeof (KS_VIDEO_STREAM_CONFIG_CAPS))
  920. #endif
  921. ) {
  922. TRACE(TL_STRM_TRACE,("\'DVFormatFromRange: *!=* bFixSizeSample (%d %d) (%d %d) (%d %d) (%x %x)\n",
  923. pDataRangeVideoToVerify->bFixedSizeSamples, pDataRangeVideo->bFixedSizeSamples,
  924. pDataRangeVideoToVerify->bTemporalCompression , pDataRangeVideo->bTemporalCompression,
  925. pDataRangeVideoToVerify->StreamDescriptionFlags, pDataRangeVideo->StreamDescriptionFlags,
  926. pDataRangeVideoToVerify->ConfigCaps.VideoStandard, pDataRangeVideo->ConfigCaps.VideoStandard
  927. ));
  928. continue;
  929. } else {
  930. TRACE(TL_STRM_TRACE,("\'DVFormatFromRange: == bFixSizeSample (%d %d) (%d %d) (%d %d) (%x %x)\n",
  931. pDataRangeVideoToVerify->bFixedSizeSamples, pDataRangeVideo->bFixedSizeSamples,
  932. pDataRangeVideoToVerify->bTemporalCompression , pDataRangeVideo->bTemporalCompression,
  933. pDataRangeVideoToVerify->StreamDescriptionFlags, pDataRangeVideo->StreamDescriptionFlags,
  934. pDataRangeVideoToVerify->ConfigCaps.VideoStandard, pDataRangeVideo->ConfigCaps.VideoStandard
  935. ));
  936. }
  937. #endif
  938. bMatchFound = TRUE;
  939. ulFormatSize = sizeof (KSDATAFORMAT) +
  940. KS_SIZE_VIDEOHEADER (&pDataRangeVideo->VideoInfoHeader);
  941. if(ulSizeOfDataFormatBuffer == 0) {
  942. // We actually have not returned this much data,
  943. // this "size" will be used by Ksproxy to send down
  944. // a buffer of that size in next query.
  945. *pulActualBytesTransferred = ulFormatSize;
  946. return STATUS_BUFFER_OVERFLOW;
  947. }
  948. // Caller wants the full data format
  949. if(ulSizeOfDataFormatBuffer < ulFormatSize) {
  950. TRACE(TL_STRM_ERROR,("VIDEOINFO: StreamNum %d, SizeOfDataFormatBuffer %d < ulFormatSize %d\n",ulStreamNumber, ulSizeOfDataFormatBuffer, ulFormatSize));
  951. return STATUS_BUFFER_TOO_SMALL;
  952. }
  953. // KS_DATAFORMAT_VIDEOINFOHEADER
  954. // KSDATAFORMAT DataFormat;
  955. // KS_VIDEOINFOHEADER VideoInfoHeader;
  956. RtlCopyMemory(
  957. &((PKS_DATAFORMAT_VIDEOINFOHEADER)pDataFormatBuffer)->DataFormat,
  958. &pDataRangeVideo->DataRange,
  959. sizeof (KSDATAFORMAT));
  960. // This size is differnt from our data range size which also contains ConfigCap
  961. ((PKSDATAFORMAT)pDataFormatBuffer)->FormatSize = ulFormatSize;
  962. *pulActualBytesTransferred = ulFormatSize;
  963. RtlCopyMemory(
  964. &((PKS_DATAFORMAT_VIDEOINFOHEADER) pDataFormatBuffer)->VideoInfoHeader,
  965. &pDataRangeVideo->VideoInfoHeader,
  966. KS_SIZE_VIDEOHEADER (&pDataRangeVideo->VideoInfoHeader));
  967. TRACE(TL_STRM_TRACE,("\'DVFormatFromRange: Matched, StrmNum %d, FormatSize %d, CopySize %d; FormatBufferSize %d, biSizeImage.\n",
  968. ulStreamNumber, (*pAvailableFormats)->FormatSize, ulFormatSize, ulSizeOfDataFormatBuffer,
  969. ((PKS_DATAFORMAT_VIDEOINFOHEADER) pDataFormatBuffer)->VideoInfoHeader.bmiHeader.biSizeImage));
  970. return STATUS_SUCCESS;
  971. } else if (IsEqualGUID (&pDataRange->Specifier, &KSDATAFORMAT_SPECIFIER_DVINFO)) {
  972. // -------------------------------------------------------------------
  973. // Specifier FORMAT_DVInfo for KS_DATARANGE_DVVIDEO
  974. // -------------------------------------------------------------------
  975. // MATCH FOUND!
  976. bMatchFound = TRUE;
  977. ulFormatSize = sizeof(KS_DATARANGE_DVVIDEO);
  978. if(ulSizeOfDataFormatBuffer == 0) {
  979. // We actually have not returned this much data,
  980. // this "size" will be used by Ksproxy to send down
  981. // a buffer of that size in next query.
  982. *pulActualBytesTransferred = ulFormatSize;
  983. return STATUS_BUFFER_OVERFLOW;
  984. }
  985. // Caller wants the full data format
  986. if (ulSizeOfDataFormatBuffer < ulFormatSize) {
  987. TRACE(TL_STRM_ERROR,("\'DVINFO: StreamNum %d, SizeOfDataFormatBuffer %d < ulFormatSize %d\n", ulStreamNumber, ulSizeOfDataFormatBuffer, ulFormatSize));
  988. return STATUS_BUFFER_TOO_SMALL;
  989. }
  990. RtlCopyMemory(
  991. pDataFormatBuffer,
  992. *pAvailableFormats,
  993. (*pAvailableFormats)->FormatSize);
  994. ((PKSDATAFORMAT)pDataFormatBuffer)->FormatSize = ulFormatSize;
  995. *pulActualBytesTransferred = ulFormatSize;
  996. TRACE(TL_STRM_TRACE,("\'** DVFormatFromRange: (DVINFO) Matched, StrmNum %d, FormatSize %d, CopySize %d; FormatBufferSize %d.\n",
  997. ulStreamNumber, (*pAvailableFormats)->FormatSize, ulFormatSize, ulSizeOfDataFormatBuffer));
  998. return STATUS_SUCCESS;
  999. #ifdef SUPPORT_NEW_AVC
  1000. } else if (IsEqualGUID (&pDataRange->Specifier, &KSDATAFORMAT_SPECIFIER_DV_AVC)) {
  1001. // -------------------------------------------------------------------
  1002. // Specifier FORMAT_DVInfo for KS_DATARANGE_DVVIDEO
  1003. // -------------------------------------------------------------------
  1004. // MATCH FOUND!
  1005. bMatchFound = TRUE;
  1006. ulFormatSize = sizeof(KS_DATARANGE_DV_AVC);
  1007. if(ulSizeOfDataFormatBuffer == 0) {
  1008. // We actually have not returned this much data,
  1009. // this "size" will be used by Ksproxy to send down
  1010. // a buffer of that size in next query.
  1011. *pulActualBytesTransferred = ulFormatSize;
  1012. return STATUS_BUFFER_OVERFLOW;
  1013. }
  1014. // Caller wants the full data format
  1015. if (ulSizeOfDataFormatBuffer < ulFormatSize) {
  1016. TRACE(TL_STRM_ERROR,("\'** DV_AVC: StreamNum %d, SizeOfDataFormatBuffer %d < ulFormatSize %d\n", ulStreamNumber, ulSizeOfDataFormatBuffer, ulFormatSize));
  1017. return STATUS_BUFFER_TOO_SMALL;
  1018. }
  1019. RtlCopyMemory(
  1020. pDataFormatBuffer,
  1021. *pAvailableFormats,
  1022. (*pAvailableFormats)->FormatSize);
  1023. ((KS_DATAFORMAT_DV_AVC *)pDataFormatBuffer)->ConnectInfo.hPlug = hPlug;
  1024. ((PKSDATAFORMAT)pDataFormatBuffer)->FormatSize = ulFormatSize;
  1025. *pulActualBytesTransferred = ulFormatSize;
  1026. TRACE(TL_STRM_TRACE,("\'*** DVFormatFromRange: (DV_AVC) Matched, StrmNum %d, FormatSize %d, CopySize %d; FormatBufferSize %d.\n",
  1027. ulStreamNumber, (*pAvailableFormats)->FormatSize, ulFormatSize, ulSizeOfDataFormatBuffer));
  1028. return STATUS_SUCCESS;
  1029. #endif // SUPPORT_NEW_AVC
  1030. }
  1031. else {
  1032. TRACE(TL_STRM_ERROR,("\'Invalid Specifier, No match !\n"));
  1033. return STATUS_NO_MATCH;
  1034. }
  1035. } // End of loop on all formats for this stream
  1036. if(!bMatchFound) {
  1037. TRACE(TL_STRM_TRACE,("\'DVFormatFromRange: No Match! StrmNum %d, pDataRange %x\n", ulStreamNumber, pDataRange));
  1038. }
  1039. return STATUS_NO_MATCH;
  1040. }
  1041. VOID
  1042. DVIniStrmExt(
  1043. PHW_STREAM_OBJECT pStrmObject,
  1044. PSTREAMEX pStrmExt,
  1045. PDVCR_EXTENSION pDevExt,
  1046. const PALL_STREAM_INFO pStream
  1047. )
  1048. /*++
  1049. Routine Description:
  1050. Initialize stream extension strcuture.
  1051. --*/
  1052. {
  1053. PAGED_CODE();
  1054. RtlZeroMemory( pStrmExt, sizeof(STREAMEX) );
  1055. pStrmExt->bEOStream = TRUE; // Stream has not started yet!
  1056. pStrmExt->pStrmObject = pStrmObject;
  1057. pStrmExt->StreamState = KSSTATE_STOP;
  1058. pStrmExt->pDevExt = pDevExt;
  1059. pStrmExt->hMyClock = 0;
  1060. pStrmExt->hMasterClock = 0;
  1061. pStrmExt->hClock = 0;
  1062. //
  1063. // Aplly to both IN/OUT data flow
  1064. //
  1065. //
  1066. // Init isoch resources
  1067. //
  1068. pStrmExt->CurrentStreamTime = 0;
  1069. pStrmExt->cntSRBReceived = 0; // number of SRB_READ/WRITE_DATA
  1070. pStrmExt->cntSRBCancelled = 0; // number of SRB_READ/WRITE_DATA cancelled
  1071. pStrmExt->FramesProcessed = 0;
  1072. pStrmExt->PictureNumber = 0;
  1073. pStrmExt->FramesDropped = 0;
  1074. #ifdef MSDV_SUPPORT_EXTRACT_SUBCODE_DATA
  1075. //
  1076. // Subcode data that can be extract from a DV frame
  1077. //
  1078. pStrmExt->AbsTrackNumber = 0;
  1079. pStrmExt->bATNUpdated = FALSE;
  1080. pStrmExt->Timecode[0] = 0;
  1081. pStrmExt->Timecode[1] = 0;
  1082. pStrmExt->Timecode[2] = 0;
  1083. pStrmExt->Timecode[3] = 0;
  1084. pStrmExt->bTimecodeUpdated = FALSE;
  1085. #endif
  1086. //
  1087. // Flow control and queue management
  1088. //
  1089. pStrmExt->lStartIsochToken = 0;
  1090. pStrmExt->pAttachFrameThreadObject = NULL;
  1091. pStrmExt->cntSRBQueued = 0; // SRB_WRITE_DATA only
  1092. InitializeListHead(&pStrmExt->SRBQueuedListHead); // SRB_WRITE_DATA only
  1093. pStrmExt->cntDataDetached = 0;
  1094. InitializeListHead(&pStrmExt->DataDetachedListHead);
  1095. pStrmExt->cntDataAttached = 0;
  1096. InitializeListHead(&pStrmExt->DataAttachedListHead);
  1097. pStrmExt->b1stNewFrameFromPauseState = TRUE; // STOP State-> RUN will have discontinuity
  1098. //
  1099. // Work item variables use to cancel all SRBs
  1100. //
  1101. pStrmExt->lCancelStateWorkItem = 0;
  1102. pStrmExt->bAbortPending = FALSE;
  1103. #ifdef USE_WDM110
  1104. pStrmExt->pIoWorkItem = NULL;
  1105. #endif
  1106. //
  1107. // Cache the pointer
  1108. // What in DVStreams[] are READONLY
  1109. //
  1110. pStrmExt->pStrmInfo = &pStream->hwStreamInfo;
  1111. pStrmObject->ReceiveDataPacket = (PVOID) pStream->hwStreamObject.ReceiveDataPacket;
  1112. pStrmObject->ReceiveControlPacket = (PVOID) pStream->hwStreamObject.ReceiveControlPacket;
  1113. pStrmObject->Dma = pStream->hwStreamObject.Dma;
  1114. pStrmObject->Pio = pStream->hwStreamObject.Pio;
  1115. pStrmObject->StreamHeaderWorkspace = pStream->hwStreamObject.StreamHeaderWorkspace;
  1116. pStrmObject->StreamHeaderMediaSpecific = pStream->hwStreamObject.StreamHeaderMediaSpecific;
  1117. pStrmObject->HwClockObject = pStream->hwStreamObject.HwClockObject;
  1118. pStrmObject->Allocator = pStream->hwStreamObject.Allocator;
  1119. pStrmObject->HwEventRoutine = pStream->hwStreamObject.HwEventRoutine;
  1120. }
  1121. NTSTATUS
  1122. DVOpenStream(
  1123. IN PHW_STREAM_OBJECT pStrmObject,
  1124. IN PKSDATAFORMAT pOpenFormat,
  1125. IN PAV_61883_REQUEST pAVReq
  1126. )
  1127. /*++
  1128. Routine Description:
  1129. Verify the OpenFormat and then allocate PC resource needed for this stream.
  1130. The isoch resource, if needed, is allocated when streaming is transition to PAUSE state.
  1131. --*/
  1132. {
  1133. NTSTATUS Status = STATUS_SUCCESS;
  1134. PSTREAMEX pStrmExt;
  1135. PDVCR_EXTENSION pDevExt;
  1136. ULONG idxStreamNumber;
  1137. KSPIN_DATAFLOW DataFlow;
  1138. PIRP pIrp;
  1139. FMT_INDEX VideoFormatIndexLast; // Last format index; used to detect change.
  1140. #ifdef SUPPORT_NEW_AVC
  1141. AVCCONNECTINFO * pAvcConnectInfo;
  1142. #endif
  1143. PAGED_CODE();
  1144. pDevExt = (PDVCR_EXTENSION) pStrmObject->HwDeviceExtension;
  1145. pStrmExt = (PSTREAMEX) pStrmObject->HwStreamExtension;
  1146. idxStreamNumber = pStrmObject->StreamNumber;
  1147. TRACE(TL_STRM_TRACE,("\'DVOpenStream: pStrmObject %x, pOpenFormat %x, cntOpen %d, idxStream %d\n", pStrmObject, pOpenFormat, pDevExt->cndStrmOpen, idxStreamNumber));
  1148. //
  1149. // Only one string can be open at any time to prevent cyclin connection
  1150. //
  1151. if(pDevExt->cndStrmOpen > 0) {
  1152. TRACE(TL_STRM_WARNING,("\'DVOpenStream: %d stream open already; failed hr %x\n", pDevExt->cndStrmOpen, Status));
  1153. return STATUS_UNSUCCESSFUL;
  1154. }
  1155. if(!(pIrp = IoAllocateIrp(pDevExt->pBusDeviceObject->StackSize, FALSE)))
  1156. return STATUS_INSUFFICIENT_RESOURCES;
  1157. //
  1158. // If a user switch from Camera to VCR mode very quickly (passing the OFF position),
  1159. // the driver may not be relaoded to detect correct mode of operation.
  1160. // It is safe to redetect here.
  1161. // Note: MSDV does return all the stream info for both input and output pin format.
  1162. //
  1163. DVGetDevModeOfOperation(pDevExt);
  1164. //
  1165. // WARNING: !! we advertise both input and output pin regardless of its mode of operation,
  1166. // but Camera does not support input pin so open should failed!
  1167. // If a VCR does not have input pin should fail as well.
  1168. //
  1169. // Ignore checking for ED_DEVTYOPE_UNKNOWN (most likely a hardware decoder box)
  1170. //
  1171. if((pDevExt->ulDevType == ED_DEVTYPE_CAMERA ||
  1172. (pDevExt->ulDevType == ED_DEVTYPE_VCR && pDevExt->NumInputPlugs == 0))
  1173. && idxStreamNumber == 2) {
  1174. TRACE(TL_STRM_ERROR,("\'OpenStream failed: Camera or VCR (0 inpin).\n"));
  1175. Status = STATUS_UNSUCCESSFUL;
  1176. goto AbortOpenStream;
  1177. }
  1178. ASSERT(idxStreamNumber < DV_STREAM_COUNT);
  1179. ASSERT(pDevExt->paStrmExt[idxStreamNumber] == NULL); // Not yet open!
  1180. //
  1181. // Initialize the stream extension structure
  1182. //
  1183. DVIniStrmExt(
  1184. pStrmObject,
  1185. pStrmExt,
  1186. pDevExt,
  1187. &DVStreams[idxStreamNumber]
  1188. );
  1189. // Sony's NTSC can play PAL tape and its plug will change its supported format accordingly.
  1190. //
  1191. // Query video format (NTSC/PAL) supported.
  1192. // Compare with its default (set at load time or last opensteam),
  1193. // if difference, change our internal video format table.
  1194. //
  1195. DataFlow= pDevExt->paCurrentStrmInfo[idxStreamNumber].DataFlow;
  1196. VideoFormatIndexLast = pDevExt->VideoFormatIndex;
  1197. if(!DVGetDevSignalFormat(
  1198. pDevExt,
  1199. DataFlow,
  1200. pStrmExt
  1201. )) {
  1202. // If querying its format has failed, we cannot open this stream.
  1203. TRACE(TL_STRM_ERROR,("\'OpenStream failed:cannot determine signal mode (NTSC/PAL, SD.SDL).\n"));
  1204. Status = STATUS_UNSUCCESSFUL;
  1205. goto AbortOpenStream;
  1206. }
  1207. //
  1208. // Check the video data format is okay.
  1209. //
  1210. if(!DVVerifyDataFormat(
  1211. pOpenFormat,
  1212. idxStreamNumber,
  1213. DVFormatInfoTable[pDevExt->VideoFormatIndex].ulFrameSize,
  1214. pDevExt->paCurrentStrmInfo
  1215. ) ) {
  1216. TRACE(TL_STRM_ERROR,("\'DVOpenStream: AdapterVerifyFormat failed.\n"));
  1217. Status = STATUS_INVALID_PARAMETER;
  1218. goto AbortOpenStream;
  1219. }
  1220. //
  1221. // Initialize events used for synchronization
  1222. //
  1223. #ifdef SUPPORT_PREROLL_AT_RUN_STATE
  1224. KeInitializeEvent(&pStrmExt->hPreRollEvent, NotificationEvent, FALSE); // Non-signal; Satisfy multple thread; manual reset
  1225. #endif
  1226. KeInitializeEvent(&pStrmExt->hSrbArriveEvent, NotificationEvent, FALSE); // Non-signal; Satisfy multiple thread; manual reset
  1227. KeInitializeEvent(&pStrmExt->hCancelDoneEvent, NotificationEvent, TRUE); // Signal!
  1228. //
  1229. // Synchronize attaching frame thread and other critical operations:
  1230. // (1) power off/on; and
  1231. // (2) surprise removal
  1232. //
  1233. if(KSPIN_DATAFLOW_IN == DataFlow) {
  1234. KeInitializeEvent(&pStrmExt->hRunThreadEvent, SynchronizationEvent /*NotificationEvent*/, FALSE);
  1235. // Def to SIGNAL state
  1236. KeInitializeEvent(&pStrmExt->hStopThreadEvent, /*SynchronizationEvent*/ NotificationEvent, TRUE);
  1237. }
  1238. //
  1239. // Alloccate synchronization structures for flow control and queue management
  1240. //
  1241. if(!(pStrmExt->hStreamMutex = (KMUTEX *) ExAllocatePool(NonPagedPool, sizeof(KMUTEX)))) {
  1242. Status = STATUS_INSUFFICIENT_RESOURCES;
  1243. goto AbortOpenStream;
  1244. }
  1245. KeInitializeMutex( pStrmExt->hStreamMutex, 0); // Level 0 and in Signal state
  1246. if(!(pStrmExt->DataListLock = (KSPIN_LOCK *) ExAllocatePool(NonPagedPool, sizeof(KSPIN_LOCK)))) {
  1247. Status = STATUS_INSUFFICIENT_RESOURCES;
  1248. goto AbortOpenStream;
  1249. }
  1250. KeInitializeSpinLock(pStrmExt->DataListLock);
  1251. #if DBG
  1252. pStrmExt->DataListLockSave = pStrmExt->DataListLock;
  1253. #endif
  1254. //
  1255. // Allocate resource for timer DPC
  1256. //
  1257. if(!(pStrmExt->DPCTimer = (KDPC *) ExAllocatePool(NonPagedPool, sizeof(KDPC)))) {
  1258. Status = STATUS_INSUFFICIENT_RESOURCES;
  1259. goto AbortOpenStream;
  1260. }
  1261. if(!(pStrmExt->Timer = (KTIMER *) ExAllocatePool(NonPagedPool, sizeof(KTIMER)))) {
  1262. Status = STATUS_INSUFFICIENT_RESOURCES;
  1263. goto AbortOpenStream;
  1264. }
  1265. //
  1266. // Set a timer to periodically check for expired clock events.
  1267. // This timer is active only in RUN state and if we are the clock provider.
  1268. //
  1269. KeInitializeDpc(
  1270. pStrmExt->DPCTimer,
  1271. DVSignalClockEvent,
  1272. pStrmExt
  1273. );
  1274. KeInitializeTimer(
  1275. pStrmExt->Timer
  1276. );
  1277. pStrmExt->bTimerEnabled = FALSE;
  1278. #ifdef SUPPORT_NEW_AVC
  1279. if(IsEqualGUID (&pOpenFormat->Specifier, &KSDATAFORMAT_SPECIFIER_DV_AVC)) {
  1280. pAvcConnectInfo = &((KS_DATAFORMAT_DV_AVC *) pOpenFormat)->ConnectInfo;
  1281. if(DataFlow == KSPIN_DATAFLOW_OUT) {
  1282. // DV1(that is us) (oPCR) -> DV2 (iPCR)
  1283. pStrmExt->hOutputPcr = pDevExt->hOPcrDV; // DV1's oPCR
  1284. pStrmExt->hInputPcr = pAvcConnectInfo->hPlug; // DV2's iPCR
  1285. TRACE(TL_STRM_WARNING,("\'!!!!! (pStrmExt:%x) DV1 (oPCR:%x) -> DV2 (iPCR:%x) !!!!!\n\n", pStrmExt, pStrmExt->hOutputPcr, pStrmExt->hInputPcr));
  1286. } else {
  1287. // DV1(that is us) (iPCR) <- DV2 (oPCR)
  1288. pStrmExt->hOutputPcr = pAvcConnectInfo->hPlug; // DV2's oPCR
  1289. pStrmExt->hInputPcr = pDevExt->hIPcrDV; // DV1's iPCR
  1290. TRACE(TL_STRM_WARNING,("\'!!!!! (pStrmExt:%x) DV1 (iPCR:%x) <- DV2 (oPCR:%x) !!!!!\n\n", pStrmExt, pStrmExt->hInputPcr, pStrmExt->hOutputPcr));
  1291. }
  1292. pStrmExt->bDV2DVConnect = TRUE;
  1293. } else {
  1294. if(DataFlow == KSPIN_DATAFLOW_OUT) {
  1295. // DV1(that is us) (oPCR) -> PC (iPCR)
  1296. pStrmExt->hOutputPcr = pDevExt->hOPcrDV;
  1297. pStrmExt->hInputPcr = 0; // We do not create local iPCR
  1298. TRACE(TL_STRM_WARNING,("\'!!!!! (pStrmExt:%x) DV (oPCR:%x) -> PC (iPCR:%x) !!!!!\n\n", pStrmExt, pStrmExt->hOutputPcr, pStrmExt->hInputPcr));
  1299. } else {
  1300. // DV1(that is us) (iPCR) <- PC (oPCR)
  1301. pStrmExt->hOutputPcr = pDevExt->hOPcrPC;
  1302. pStrmExt->hInputPcr = pDevExt->hIPcrDV;
  1303. TRACE(TL_STRM_WARNING,("\'!!!!! (pStrmExt:%x) DV (iPCR:%x) <- PC (oPCR:%x) !!!!!\n\n", pStrmExt, pStrmExt->hInputPcr, pStrmExt->hOutputPcr));
  1304. }
  1305. pStrmExt->bDV2DVConnect = FALSE;
  1306. }
  1307. #else
  1308. if(DataFlow == KSPIN_DATAFLOW_OUT) {
  1309. // DV1(that is us) (oPCR) -> PC (iPCR)
  1310. pStrmExt->hOutputPcr = pDevExt->hOPcrDV;
  1311. pStrmExt->hInputPcr = 0; // We do not create local iPCR
  1312. TRACE(TL_STRM_WARNING,("\'!!!!! (pStrmExt:%x) DV (oPCR:%x) -> PC (iPCR:%x) !!!!!\n\n", pStrmExt, pStrmExt->hOutputPcr, pStrmExt->hInputPcr));
  1313. } else {
  1314. // DV1(that is us) (iPCR) <- PC (oPCR)
  1315. pStrmExt->hOutputPcr = pDevExt->hOPcrPC;
  1316. pStrmExt->hInputPcr = pDevExt->hIPcrDV;
  1317. TRACE(TL_STRM_WARNING,("\'!!!!! (pStrmExt:%x) DV (iPCR:%x) <- PC (oPCR:%x) !!!!!\n\n", pStrmExt, pStrmExt->hInputPcr, pStrmExt->hOutputPcr));
  1318. }
  1319. #endif
  1320. IoFreeIrp(pIrp); pIrp = NULL;
  1321. #if DBG
  1322. // Allocate buffer to keep statistic of transmitted buffers.
  1323. pStrmExt->paXmtStat = (XMT_FRAME_STAT *)
  1324. ExAllocatePool(NonPagedPool, sizeof(XMT_FRAME_STAT) * MAX_XMT_FRAMES_TRACED);
  1325. if(!pStrmExt->paXmtStat) {
  1326. Status = STATUS_INSUFFICIENT_RESOURCES;
  1327. goto AbortOpenStream;
  1328. }
  1329. pStrmExt->ulStatEntries = 0;
  1330. #endif
  1331. //
  1332. // Pre-allcoate resource (Lists)
  1333. //
  1334. if(!NT_SUCCESS(
  1335. Status = DvAllocatePCResource(
  1336. DataFlow,
  1337. pStrmExt
  1338. ))) {
  1339. goto AbortOpenStream;
  1340. }
  1341. //
  1342. // Cache it and reference when pDevExt is all we have,
  1343. // such as BusReset and SurprieseRemoval
  1344. //
  1345. pDevExt->idxStreamNumber = idxStreamNumber; // index of current active stream; work only if there is only one active stream at any time.
  1346. pDevExt->paStrmExt[idxStreamNumber] = pStrmExt;
  1347. //
  1348. // In the future, a DV can be unplug and plug back in,
  1349. // and restore its state if the application is not yet closed.
  1350. //
  1351. pDevExt->bDevRemoved = FALSE;
  1352. //
  1353. // No one else can open another stream (inout or output) unitil this is release.
  1354. // This is done to avoid cyclic graph.
  1355. //
  1356. pDevExt->cndStrmOpen++;
  1357. ASSERT(pDevExt->cndStrmOpen == 1); // Only one can be open at any time.
  1358. TRACE(TL_STRM_WARNING,("\'OpenStream: %d stream open, idx %d, Status %x, pStrmExt %x, pDevExt %x\n",
  1359. pDevExt->cndStrmOpen, pDevExt->idxStreamNumber, Status, pStrmExt, pDevExt));
  1360. TRACE(TL_STRM_WARNING,("\' #OPEN_STREAM#: Status %x, idxStream %d, pDevExt %x, pStrmExt %x\n",
  1361. Status, idxStreamNumber, pDevExt, pStrmExt));
  1362. return Status;
  1363. AbortOpenStream:
  1364. if(pIrp) {
  1365. IoFreeIrp(pIrp); pIrp = NULL;
  1366. }
  1367. if(pStrmExt->DataListLock) {
  1368. ExFreePool(pStrmExt->DataListLock); pStrmExt->DataListLock = NULL;
  1369. }
  1370. if(pStrmExt->hStreamMutex) {
  1371. ExFreePool(pStrmExt->hStreamMutex); pStrmExt->hStreamMutex = NULL;
  1372. }
  1373. if(pStrmExt->DPCTimer) {
  1374. ExFreePool(pStrmExt->DPCTimer); pStrmExt->DPCTimer = NULL;
  1375. }
  1376. if(pStrmExt->Timer) {
  1377. ExFreePool(pStrmExt->Timer); pStrmExt->Timer = NULL;
  1378. }
  1379. #if DBG
  1380. if(pStrmExt->paXmtStat) {
  1381. ExFreePool(pStrmExt->paXmtStat); pStrmExt->paXmtStat = NULL;
  1382. }
  1383. #endif
  1384. TRACE(TL_STRM_WARNING,("\'#OPEN_STREAM# failed!: Status %x, idxStream %d, pDevExt %x, pStrmExt %x\n",
  1385. Status, idxStreamNumber, pDevExt, pStrmExt));
  1386. return Status;
  1387. }
  1388. NTSTATUS
  1389. DVCloseStream(
  1390. IN PHW_STREAM_OBJECT pStrmObject,
  1391. IN PKSDATAFORMAT pOpenFormat,
  1392. IN PAV_61883_REQUEST pAVReq
  1393. )
  1394. /*++
  1395. Routine Description:
  1396. Called when an CloseStream Srb request is received
  1397. --*/
  1398. {
  1399. ULONG i;
  1400. PSTREAMEX pStrmExt;
  1401. PDVCR_EXTENSION pDevExt;
  1402. ULONG idxStreamNumber;
  1403. PAGED_CODE();
  1404. pDevExt = (PDVCR_EXTENSION) pStrmObject->HwDeviceExtension;
  1405. pStrmExt = (PSTREAMEX) pStrmObject->HwStreamExtension;
  1406. idxStreamNumber = pStrmObject->StreamNumber;
  1407. TRACE(TL_STRM_WARNING,("\'DVCloseStream: >> pStrmExt %x, pDevExt %x\n", pStrmExt, pDevExt));
  1408. //
  1409. // If the stream isn't open, just return
  1410. //
  1411. if(pStrmExt == NULL) {
  1412. ASSERT(pStrmExt && "CloseStream but pStrmExt is NULL!");
  1413. return STATUS_SUCCESS; // ????
  1414. }
  1415. //
  1416. // If surprise removal, we may get a close stream before surprise is completed.
  1417. //
  1418. if(
  1419. pStrmExt->pAttachFrameThreadObject // If thread is created!
  1420. && !pStrmExt->bTerminateThread
  1421. && pStrmExt->pStrmInfo->DataFlow == KSPIN_DATAFLOW_IN
  1422. ) {
  1423. NTSTATUS StatusWait;
  1424. TRACE(TL_PNP_WARNING|TL_STRM_WARNING,("\'>>>> CloseStream: Enter WFSO(hStopThreadEvent; lNeedService:%d)\n", pStrmExt->lNeedService));
  1425. StatusWait =
  1426. KeWaitForSingleObject(
  1427. &pStrmExt->hStopThreadEvent,
  1428. Executive,
  1429. KernelMode,
  1430. FALSE,
  1431. 0
  1432. );
  1433. TRACE(TL_PNP_WARNING|TL_STRM_WARNING,("\'<<<< CloseStream: Exit WFSO(hStopThreadEvent; lNeedService:%d)\n", pStrmExt->lNeedService));
  1434. }
  1435. //
  1436. // Wait until the pending work item is completed.
  1437. //
  1438. TRACE(TL_STRM_WARNING,("\'CloseStream: pStrmExt->lCancelStateWorkItem:%d\n", pStrmExt->lCancelStateWorkItem));
  1439. KeWaitForSingleObject( &pStrmExt->hCancelDoneEvent, Executive, KernelMode, FALSE, 0 );
  1440. // Cancel should have been done when we are in PAUSE state.
  1441. // But if an application is close, it might not transtioning into PAUSE state.
  1442. if(pStrmExt->bTimerEnabled) {
  1443. TRACE(TL_STRM_WARNING,("\'*** (CloseStream) CancelTimer *\n"));
  1444. KeCancelTimer(
  1445. pStrmExt->Timer
  1446. );
  1447. pStrmExt->bTimerEnabled = FALSE;
  1448. }
  1449. //
  1450. // If talking or listening (i.e. streaming), stop it!
  1451. // In case of system shutdown while streaming or application crash
  1452. //
  1453. DVStopCancelDisconnect(
  1454. pStrmExt
  1455. );
  1456. //
  1457. // Free all allocated PC resoruce
  1458. //
  1459. DvFreePCResource(
  1460. pStrmExt
  1461. );
  1462. ASSERT(pStrmExt->cntDataDetached == 0 && IsListEmpty(&pStrmExt->DataDetachedListHead) && "Detach List not empty!");
  1463. ASSERT(pStrmExt->cntDataAttached == 0 && IsListEmpty(&pStrmExt->DataAttachedListHead) && "Attach List not empty!");
  1464. ASSERT(pStrmExt->cntSRBQueued == 0 && IsListEmpty(&pStrmExt->SRBQueuedListHead) && "SrbQ List not empty!");
  1465. // Terminate the system thread that is used for attaching frame for transmit to DV
  1466. if(
  1467. KSPIN_DATAFLOW_IN == pStrmExt->pStrmInfo->DataFlow
  1468. && !pStrmExt->bTerminateThread
  1469. && pStrmExt->pAttachFrameThreadObject
  1470. ) {
  1471. DVTerminateAttachFrameThread(pStrmExt);
  1472. pStrmExt->pAttachFrameThreadObject = NULL;
  1473. TRACE(TL_STRM_WARNING,("** DVCloseStream: thread terminated!\n"));
  1474. }
  1475. #if DBG
  1476. // Print this only if the debug flag is set.
  1477. if(pStrmExt->paXmtStat) {
  1478. if(DVDebugXmt) {
  1479. TRACE(TL_STRM_WARNING|TL_CIP_WARNING,("Data transmission statistics: (%s %s); (Pause:%d; Run:%d); hMasterClk:%x; hClock:%x\n\n",
  1480. __DATE__, __TIME__, pStrmExt->lFramesAccumulatedPaused,
  1481. pStrmExt->lFramesAccumulatedRun, pStrmExt->hMasterClock, pStrmExt->hClock));
  1482. TRACE(TL_STRM_WARNING|TL_CIP_WARNING,("ST \tSrbRcv \tSrbQ \tSrbPend \tAttached \tSlot \ttmStream \tDrop \tSrb# \tFlags \ttmPres \tSCnt \tCyCnt \tCyOfst\n"));
  1483. for(i=0; i < pStrmExt->ulStatEntries; i++) {
  1484. TRACE(TL_STRM_WARNING|TL_CIP_WARNING,("%d \t%d \t%d \t%d \t%d \t%d \t%d \t%d \t%d \t%x \t%d \t%d \t%d \t%d\n",
  1485. pStrmExt->paXmtStat[i].StreamState,
  1486. pStrmExt->paXmtStat[i].cntSRBReceived,
  1487. pStrmExt->paXmtStat[i].cntSRBQueued,
  1488. pStrmExt->paXmtStat[i].cntSRBPending,
  1489. pStrmExt->paXmtStat[i].cntDataAttached,
  1490. (DWORD) pStrmExt->paXmtStat[i].FrameSlot,
  1491. (DWORD) pStrmExt->paXmtStat[i].tmStreamTime, // /10000,
  1492. pStrmExt->paXmtStat[i].DropCount,
  1493. pStrmExt->paXmtStat[i].FrameNumber,
  1494. (DWORD) pStrmExt->paXmtStat[i].OptionsFlags,
  1495. (DWORD) pStrmExt->paXmtStat[i].tmPresentation, // /10000,
  1496. pStrmExt->paXmtStat[i].tsTransmitted.CL_SecondCount,
  1497. pStrmExt->paXmtStat[i].tsTransmitted.CL_CycleCount,
  1498. pStrmExt->paXmtStat[i].tsTransmitted.CL_CycleOffset
  1499. ));
  1500. }
  1501. }
  1502. ExFreePool(pStrmExt->paXmtStat); pStrmExt->paXmtStat = NULL;
  1503. }
  1504. #endif
  1505. //
  1506. // Find the matching stream extension and invalidate it.
  1507. //
  1508. for (i=0; i<DV_STREAM_COUNT; i++) {
  1509. if(pStrmExt == pDevExt->paStrmExt[i]) {
  1510. ASSERT(!pDevExt->paStrmExt[i]->bAbortPending && "Cannot close a stream when abort is pending");
  1511. pDevExt->paStrmExt[i] = NULL;
  1512. break;
  1513. }
  1514. }
  1515. // Release this count so other can open.
  1516. pDevExt->cndStrmOpen--;
  1517. ASSERT(pDevExt->cndStrmOpen == 0);
  1518. TRACE(TL_STRM_WARNING,("\'DVCloseStream: %d stream; AQD [%d:%d:%d]\n",
  1519. pDevExt->cndStrmOpen,
  1520. pStrmExt->cntDataAttached,
  1521. pStrmExt->cntSRBQueued,
  1522. pStrmExt->cntDataDetached
  1523. ));
  1524. #if DBG
  1525. ASSERT(pStrmExt->DataListLockSave == pStrmExt->DataListLock);
  1526. #endif
  1527. if(pStrmExt->DataListLock) {
  1528. ExFreePool(pStrmExt->DataListLock); pStrmExt->DataListLock = NULL;
  1529. }
  1530. if(pStrmExt->hStreamMutex) {
  1531. ExFreePool(pStrmExt->hStreamMutex); pStrmExt->hStreamMutex = NULL;
  1532. }
  1533. if(pStrmExt->DPCTimer) {
  1534. ExFreePool(pStrmExt->DPCTimer); pStrmExt->DPCTimer = NULL;
  1535. }
  1536. if(pStrmExt->Timer) {
  1537. ExFreePool(pStrmExt->Timer); pStrmExt->Timer = NULL;
  1538. }
  1539. //
  1540. // Done with stream extention. Will be invalid from this point on.
  1541. //
  1542. #if 0
  1543. RtlZeroMemory(pStrmExt, sizeof(STREAMEX));
  1544. #endif
  1545. return STATUS_SUCCESS;
  1546. }
  1547. NTSTATUS
  1548. DVChangePower(
  1549. PDVCR_EXTENSION pDevExt,
  1550. PAV_61883_REQUEST pAVReq,
  1551. DEVICE_POWER_STATE NewPowerState
  1552. )
  1553. /*++
  1554. Routine Description:
  1555. Process changing this device's power state.
  1556. --*/
  1557. {
  1558. ULONG i;
  1559. NTSTATUS Status;
  1560. PAGED_CODE();
  1561. //
  1562. // D0: Device is on and can be streaming.
  1563. // D1,D2: not supported.
  1564. // D3: Device is off and can not streaming. The context is lost.
  1565. // Power can be removed from the device.
  1566. // When power is back on, we will get a bus reset.
  1567. //
  1568. TRACE(TL_PNP_WARNING,("\'PowrSt: %d->%d; (d0:[1:On],D3[4:off])\n", pDevExt->PowerState, NewPowerState));
  1569. Status = STATUS_SUCCESS;
  1570. if(pDevExt->PowerState == NewPowerState) {
  1571. TRACE(TL_PNP_WARNING,("\'ChangePower: same power state!\n"));
  1572. return STATUS_SUCCESS;
  1573. }
  1574. switch (NewPowerState) {
  1575. case PowerDeviceD3: // Power OFF
  1576. // We are at D0 and ask to go to D3: save state, stop streaming and Sleep
  1577. if( pDevExt->PowerState == PowerDeviceD0) {
  1578. pDevExt->PowerState = NewPowerState;
  1579. // For a supported power state change
  1580. for (i=0; i<DV_STREAM_COUNT; i++) {
  1581. if(pDevExt->paStrmExt[i]) {
  1582. TRACE(TL_PNP_WARNING,("\'D0->D3 (PowerOff), pStrmExt:%x; StrmSt:%d; IsochActive:%d; SrbQ:%d\n",
  1583. pDevExt->paStrmExt[i], pDevExt->paStrmExt[i]->StreamState, pDevExt->paStrmExt[i]->bIsochIsActive, pDevExt->paStrmExt[i]->cntSRBQueued));
  1584. //
  1585. // Halt attach frame thread if it is an input pin
  1586. //
  1587. if(
  1588. pDevExt->paStrmExt[i]->pAttachFrameThreadObject // If thread is created!
  1589. && !pDevExt->paStrmExt[i]->bTerminateThread // Not terminated abnormally
  1590. && pDevExt->paStrmExt[i]->pStrmInfo->DataFlow == KSPIN_DATAFLOW_IN
  1591. ) {
  1592. NTSTATUS StatusWait;
  1593. #if 1
  1594. // Will be set in the thread attaching thread.
  1595. KeClearEvent(&pDevExt->paStrmExt[i]->hStopThreadEvent);
  1596. #endif
  1597. InterlockedIncrement(&pDevExt->paStrmExt[i]->lNeedService); // Need thread to stop for other service.
  1598. // In case the attach frame thread is idle! (no data to attach!)
  1599. KeSetEvent(&pDevExt->paStrmExt[i]->hSrbArriveEvent, 0 ,FALSE);
  1600. #ifdef SUPPORT_PREROLL_AT_RUN_STATE
  1601. KeSetEvent(&pDevExt->paStrmExt[i]->hPreRollEvent, 0 ,FALSE);
  1602. #endif
  1603. TRACE(TL_PNP_WARNING,("\'>>>> DVChangePower: Enter WFSO(hStopThreadEvent; lNeedService:%d)\n", pDevExt->paStrmExt[i]->lNeedService));
  1604. StatusWait =
  1605. KeWaitForSingleObject(
  1606. &pDevExt->paStrmExt[i]->hStopThreadEvent, // Signal when thread has stopped.
  1607. Executive,
  1608. KernelMode,
  1609. FALSE,
  1610. 0
  1611. );
  1612. TRACE(TL_PNP_WARNING,("\'<<<< DVChangePower: Exit WFSO(hStopThreadEvent; lNeedService:%d)\n", pDevExt->paStrmExt[i]->lNeedService));
  1613. }
  1614. if(pDevExt->paStrmExt[i]->bIsochIsActive) {
  1615. // Stop isoch but do not change the streaming state
  1616. TRACE(TL_PNP_WARNING,("\'ChangePower: Stop isoche; StrmSt:%d\n", pDevExt->paStrmExt[i]->StreamState));
  1617. DVStreamingStop(
  1618. pDevExt->paStrmExt[i],
  1619. pDevExt,
  1620. pAVReq
  1621. ) ;
  1622. }
  1623. // Complete all the pending events so that the downstream
  1624. // filter (Video render) can release this buffer from AdviseTime() event.
  1625. // However, not sure why this is necessary since the lower filter
  1626. // will get a PAUSE() or STOP() from the filter manager. In such
  1627. DVSignalClockEvent(0, pDevExt->paStrmExt[i], 0, 0);
  1628. }
  1629. }
  1630. }
  1631. else {
  1632. TRACE(TL_PNP_WARNING,("\'ChangePower: unsupported %d -> %d; (do nothing!).\n", pDevExt->PowerState, DevicePowerState));
  1633. }
  1634. break;
  1635. case PowerDeviceD0: // Powering ON (waking up)
  1636. if( pDevExt->PowerState == PowerDeviceD3) {
  1637. // Set PowerState change and then Signal PowerOn event
  1638. pDevExt->PowerState = NewPowerState;
  1639. // For a supported power state change
  1640. for (i=0; i<DV_STREAM_COUNT; i++) {
  1641. if(pDevExt->paStrmExt[i]) {
  1642. TRACE(TL_PNP_WARNING,("\'D3->D0 (PowerOn), pStrmExt:%x; StrmSt:%d; IsochActive:%d; SrbQ:%d\n",
  1643. pDevExt->paStrmExt[i], pDevExt->paStrmExt[i]->StreamState, pDevExt->paStrmExt[i]->bIsochIsActive, pDevExt->paStrmExt[i]->cntSRBQueued));
  1644. if(!pDevExt->paStrmExt[i]->bIsochIsActive) {
  1645. TRACE(TL_PNP_WARNING,("\'ChangePower: StrmSt:%d; Start isoch\n", pDevExt->paStrmExt[i]->StreamState));
  1646. // Start isoch depending on streaming state for DATAFLOW_IN/OUT
  1647. if(pDevExt->paStrmExt[i]->pStrmInfo->DataFlow == KSPIN_DATAFLOW_IN) {
  1648. if(pDevExt->paStrmExt[i]->StreamState == KSSTATE_PAUSE ||
  1649. pDevExt->paStrmExt[i]->StreamState == KSSTATE_RUN) {
  1650. DVStreamingStart(
  1651. pDevExt->paStrmExt[i]->pStrmInfo->DataFlow,
  1652. pDevExt->paStrmExt[i],
  1653. pDevExt
  1654. ) ;
  1655. }
  1656. }
  1657. else if(pDevExt->paStrmExt[i]->pStrmInfo->DataFlow == KSPIN_DATAFLOW_OUT) {
  1658. if(pDevExt->paStrmExt[i]->StreamState == KSSTATE_RUN) {
  1659. DVStreamingStart(
  1660. pDevExt->paStrmExt[i]->pStrmInfo->DataFlow,
  1661. pDevExt->paStrmExt[i],
  1662. pDevExt
  1663. ) ;
  1664. }
  1665. }
  1666. } // IsochActive
  1667. #if 1 // Clear any buffer queued in the downstream.
  1668. // Complete all the pending events so that the downstream
  1669. // filter (Video render) can release this buffer from AdviseTime() event.
  1670. // However, not sure why this is necessary since the lower filter
  1671. // will get a PAUSE() or STOP() from the filter manager. In such
  1672. DVSignalClockEvent(0, pDevExt->paStrmExt[i], 0, 0);
  1673. #endif
  1674. //
  1675. // Resume attaching frame operation
  1676. //
  1677. if(
  1678. pDevExt->paStrmExt[i]->pAttachFrameThreadObject // If thread is created!
  1679. && !pDevExt->paStrmExt[i]->bTerminateThread // Not terminated abnormally
  1680. && pDevExt->paStrmExt[i]->pStrmInfo->DataFlow == KSPIN_DATAFLOW_IN
  1681. ) {
  1682. KeSetEvent(&pDevExt->paStrmExt[i]->hRunThreadEvent, 0 ,FALSE);
  1683. }
  1684. }
  1685. }
  1686. }
  1687. else {
  1688. TRACE(TL_PNP_WARNING,("\'ChangePower: supported %d -> %d; (do nothing!).\n", pDevExt->PowerState, DevicePowerState));
  1689. }
  1690. break;
  1691. // These state are not supported.
  1692. case PowerDeviceD1:
  1693. case PowerDeviceD2:
  1694. default:
  1695. TRACE(TL_PNP_WARNING,("\'ChangePower: unsupported %d to %d (do nothing).\n", pDevExt->PowerState, DevicePowerState));
  1696. Status = STATUS_SUCCESS; // STATUS_INVALID_PARAMETER;
  1697. break;
  1698. }
  1699. if(Status == STATUS_SUCCESS)
  1700. pDevExt->PowerState = NewPowerState;
  1701. else
  1702. Status = STATUS_NOT_IMPLEMENTED;
  1703. TRACE(TL_PNP_WARNING,("\'DVChangePower: Exiting; Status:%x\n", Status));
  1704. return STATUS_SUCCESS;
  1705. }
  1706. NTSTATUS
  1707. DVSurpriseRemoval(
  1708. PDVCR_EXTENSION pDevExt,
  1709. PAV_61883_REQUEST pAVReq
  1710. )
  1711. /*++
  1712. Routine Description:
  1713. Response to SRB_SURPRISE_REMOVAL.
  1714. --*/
  1715. {
  1716. ULONG i;
  1717. KIRQL oldIrql;
  1718. PKSEVENT_ENTRY pEvent = NULL;
  1719. PAGED_CODE();
  1720. //
  1721. // ONLY place this flag is set to TRUE.
  1722. // Block incoming read although there might still in the process of being attached
  1723. //
  1724. KeAcquireSpinLock(&pDevExt->AVCCmdLock, &oldIrql);
  1725. pDevExt->bDevRemoved = TRUE;
  1726. KeReleaseSpinLock(&pDevExt->AVCCmdLock, oldIrql);
  1727. //
  1728. // Now Stop the stream and clean up
  1729. //
  1730. for(i=0; i < DV_STREAM_COUNT; i++) {
  1731. if(pDevExt->paStrmExt[i] != NULL) {
  1732. TRACE(TL_PNP_WARNING,("\' #SURPRISE_REMOVAL# StrmNum %d, pStrmExt %x, Attached %d\n",
  1733. i, pDevExt->paStrmExt[i], pDevExt->paStrmExt[i]->cntDataAttached));
  1734. // Signal this event so SRB can complete.
  1735. if(pDevExt->paStrmExt[i]->pStrmInfo->DataFlow == KSPIN_DATAFLOW_IN ) {
  1736. //
  1737. // Imply EOStream! so the data source will stop sending us data.
  1738. //
  1739. KeAcquireSpinLock( pDevExt->paStrmExt[i]->DataListLock, &oldIrql);
  1740. if(!pDevExt->paStrmExt[i]->bEOStream)
  1741. pDevExt->paStrmExt[i]->bEOStream = TRUE;
  1742. //
  1743. // Signal EOStream
  1744. //
  1745. StreamClassStreamNotification(
  1746. SignalMultipleStreamEvents,
  1747. pDevExt->paStrmExt[i]->pStrmObject,
  1748. (GUID *)&KSEVENTSETID_Connection_Local,
  1749. KSEVENT_CONNECTION_ENDOFSTREAM
  1750. );
  1751. TRACE(TL_PNP_WARNING,("\'Signal KSEVENT_CONNECTION_ENDOFSTREAM\n"));
  1752. //
  1753. // Stop the attaching frame thread
  1754. //
  1755. if(
  1756. pDevExt->paStrmExt[i]->pAttachFrameThreadObject // If thread is created!
  1757. && !pDevExt->paStrmExt[i]->bTerminateThread
  1758. ) {
  1759. NTSTATUS StatusWait;
  1760. #if 1
  1761. // Will be set in the thread attaching thread.
  1762. KeClearEvent(&pDevExt->paStrmExt[i]->hStopThreadEvent);
  1763. #endif
  1764. InterlockedIncrement(&pDevExt->paStrmExt[i]->lNeedService); // Request count
  1765. // In case the attach frame thread is idle! (no data to attach!)
  1766. KeSetEvent(&pDevExt->paStrmExt[i]->hSrbArriveEvent, 0 ,FALSE);
  1767. #ifdef SUPPORT_PREROLL_AT_RUN_STATE
  1768. KeSetEvent(&pDevExt->paStrmExt[i]->hPreRollEvent, 0 ,FALSE);
  1769. #endif
  1770. KeReleaseSpinLock( pDevExt->paStrmExt[i]->DataListLock, oldIrql);
  1771. TRACE(TL_PNP_WARNING,("\'>>>> DVSurpriseRemoval: Enter WFSO(hStopThreadEvent; lNeedService:%d)\n", pDevExt->paStrmExt[i]->lNeedService));
  1772. StatusWait =
  1773. KeWaitForSingleObject(
  1774. &pDevExt->paStrmExt[i]->hStopThreadEvent, // Signal when thread has stopped.
  1775. Executive,
  1776. KernelMode,
  1777. FALSE,
  1778. 0
  1779. );
  1780. TRACE(TL_PNP_WARNING,("\'<<<< DVSurpriseRemoval: Exit WFSO(hStopThreadEvent; lNeedService:%d)\n", pDevExt->paStrmExt[i]->lNeedService));
  1781. //
  1782. // Note:
  1783. // Terminate AttachFraameThread: KeSetEvent(&pDevExt->hRunThreadEvent, 0 ,FALSE)
  1784. //
  1785. } else {
  1786. KeReleaseSpinLock( pDevExt->paStrmExt[i]->DataListLock, oldIrql);
  1787. }
  1788. }
  1789. //
  1790. // Abort stream; stop and cancel pending data request
  1791. //
  1792. TRACE(TL_PNP_WARNING,("\'DVSurpriseRemoval: AbortStream enter...\n"));
  1793. if(!DVAbortStream(pDevExt, pDevExt->paStrmExt[i])) {
  1794. TRACE(TL_PNP_ERROR,("\'DVSurpriseRemoval: AbortStream failed\n"));
  1795. }
  1796. //
  1797. // Adter surprise removal, all call to lower stack will be returned
  1798. // with error. Let's disconnect if it is connected.
  1799. //
  1800. //
  1801. // Disable the timer
  1802. //
  1803. if(pDevExt->paStrmExt[i]->bTimerEnabled) {
  1804. KeCancelTimer(
  1805. pDevExt->paStrmExt[i]->Timer
  1806. );
  1807. pDevExt->paStrmExt[i]->bTimerEnabled = FALSE;
  1808. }
  1809. //
  1810. // Wait until the pending work item is completed.
  1811. //
  1812. TRACE(TL_PNP_WARNING,("\'SupriseRemoval: Wait for CancelDoneEvent <entering>; lCancelStateWorkItem:%d\n", pDevExt->paStrmExt[i]->lCancelStateWorkItem));
  1813. KeWaitForSingleObject( &pDevExt->paStrmExt[i]->hCancelDoneEvent, Executive, KernelMode, FALSE, 0 );
  1814. TRACE(TL_PNP_WARNING,("\'SupriseRemoval: Wait for CancelDoneEvent <exited>...\n"));
  1815. }
  1816. }
  1817. // Signal KSEvent that device is removed.
  1818. // After this SRb, there will be no more Set/Get property Srb into this driver.
  1819. // By notifying the COM I/F, it will wither signal application that device is removed and
  1820. // return ERROR_DEVICE_REMOVED error code for subsequent calls.
  1821. // There might be multiple instances/threads of IAMExtTransport instance with the same KS event.
  1822. // There is only one device so they all enabled event are singalled.
  1823. do {
  1824. if(pEvent = StreamClassGetNextEvent((PVOID) pDevExt, 0, \
  1825. (GUID *)&KSEVENTSETID_EXTDEV_Command, KSEVENT_EXTDEV_NOTIFY_REMOVAL, pEvent)) {
  1826. // Make sure the right event and then signal it
  1827. if(pEvent->EventItem->EventId == KSEVENT_EXTDEV_NOTIFY_REMOVAL) {
  1828. StreamClassDeviceNotification(SignalDeviceEvent, pDevExt, pEvent);
  1829. TRACE(TL_PNP_WARNING,("\'->Signal NOTIFY_REMOVAL; pEvent:%x, EventId %d.\n", pEvent, pEvent->EventItem->EventId));
  1830. }
  1831. }
  1832. } while (pEvent != NULL);
  1833. //
  1834. // Since we may not get the busreset, let's go ahead and cancel all pending device control
  1835. //
  1836. DVAVCCmdResetAfterBusReset(pDevExt);
  1837. #ifdef NT51_61883
  1838. //
  1839. // Delete plug; 61883 will not accept 61883 request after surprise removal is processed.
  1840. //
  1841. if(pDevExt->hOPcrPC) {
  1842. // Do not care about return status since we are being unloaded.
  1843. DVDeleteLocalPlug(
  1844. pDevExt,
  1845. pDevExt->hOPcrPC
  1846. );
  1847. pDevExt->hOPcrPC = NULL;
  1848. }
  1849. #endif
  1850. TRACE(TL_PNP_WARNING,("\'SurpriseRemoval exiting.\n"));
  1851. return STATUS_SUCCESS;
  1852. }
  1853. // Return code is basically return in pSrb->Status.
  1854. NTSTATUS
  1855. DVProcessPnPBusReset(
  1856. PDVCR_EXTENSION pDevExt
  1857. )
  1858. /*++
  1859. Routine Description:
  1860. Process a bus reset.
  1861. Arguments:
  1862. Srb - Pointer to stream request block
  1863. Return Value:
  1864. Nothing
  1865. --*/
  1866. {
  1867. #ifdef MSDVDV_SUPPORT_BUSRESET_EVENT
  1868. PKSEVENT_ENTRY pEvent;
  1869. #endif
  1870. PAGED_CODE();
  1871. TRACE(TL_PNP_WARNING,("\'DVProcessPnPBusReset: >>\n"));
  1872. #ifdef MSDVDV_SUPPORT_BUSRESET_EVENT
  1873. //
  1874. // Signal (if enabled) busreset event to let upper layer know that a busreset has occurred.
  1875. //
  1876. pEvent = NULL;
  1877. pEvent =
  1878. StreamClassGetNextEvent(
  1879. (PVOID) pDevExt,
  1880. 0,
  1881. (GUID *)&KSEVENTSETID_EXTDEV_Command,
  1882. KSEVENT_EXTDEV_COMMAND_BUSRESET,
  1883. pEvent
  1884. );
  1885. if(pEvent) {
  1886. //
  1887. // signal the event here
  1888. //
  1889. if(pEvent->EventItem->EventId == KSEVENT_EXTDEV_COMMAND_BUSRESET) {
  1890. StreamClassDeviceNotification(
  1891. SignalDeviceEvent,
  1892. pDevExt,
  1893. pEvent
  1894. );
  1895. TRACE(TL_PNP_WARNING,("\'DVProcessPnPBusReset: Signal BUSRESET; EventId %d.\n", pEvent->EventItem->EventId));
  1896. }
  1897. }
  1898. #endif
  1899. //
  1900. // Reset pending count and AVC command that is in Interim
  1901. //
  1902. DVAVCCmdResetAfterBusReset(pDevExt);
  1903. //
  1904. // Can we return anything other than SUCCESS ?
  1905. //
  1906. return STATUS_SUCCESS;
  1907. }
  1908. NTSTATUS
  1909. DVUninitializeDevice(
  1910. IN PDVCR_EXTENSION pDevExt
  1911. )
  1912. /*++
  1913. Routine Description:
  1914. This where we perform the necessary initialization tasks.
  1915. Arguments:
  1916. Srb - Pointer to stream request block
  1917. '
  1918. Return Value:
  1919. Nothing
  1920. --*/
  1921. {
  1922. PAGED_CODE();
  1923. TRACE(TL_PNP_WARNING,("\'DVUnInitialize: enter with DeviceExtension=0x%8x\n", pDevExt));
  1924. //
  1925. // Clear all pending AVC command entries.
  1926. //
  1927. DVAVCCmdResetAfterBusReset(pDevExt);
  1928. // Free stream information allocated
  1929. if(pDevExt->paCurrentStrmInfo) {
  1930. ExFreePool(pDevExt->paCurrentStrmInfo);
  1931. pDevExt->paCurrentStrmInfo = NULL;
  1932. }
  1933. #ifdef NT51_61883
  1934. if(pDevExt->hOPcrPC) {
  1935. // Do not care about return status since we are being unloaded.
  1936. DVDeleteLocalPlug(
  1937. pDevExt,
  1938. pDevExt->hOPcrPC
  1939. );
  1940. pDevExt->hOPcrPC = NULL;
  1941. }
  1942. #endif
  1943. TRACE(TL_PNP_WARNING,("\'DVUnInitialize: Rest of allocated resources freed.\n"));
  1944. return STATUS_SUCCESS;
  1945. }
  1946. //*****************************************************************************
  1947. //*****************************************************************************
  1948. // S T R E A M S R B
  1949. //*****************************************************************************
  1950. //*****************************************************************************
  1951. NTSTATUS
  1952. DVGetStreamState(
  1953. PSTREAMEX pStrmExt,
  1954. PKSSTATE pStreamState,
  1955. PULONG pulActualBytesTransferred
  1956. )
  1957. /*++
  1958. Routine Description:
  1959. Gets the current state of the requested stream
  1960. --*/
  1961. {
  1962. PAGED_CODE();
  1963. if(!pStrmExt) {
  1964. TRACE(TL_STRM_ERROR,("\'GetStreamState: pStrmExt is NULL; STATUS_UNSUCCESSFUL\n"));
  1965. return STATUS_UNSUCCESSFUL;
  1966. }
  1967. *pStreamState = pStrmExt->StreamState;
  1968. *pulActualBytesTransferred = sizeof (KSSTATE);
  1969. TRACE(TL_STRM_TRACE,("\'GetStreamState: %d (was %d)\n", pStrmExt->StreamState, pStrmExt->StreamStatePrevious));
  1970. if(pStrmExt->StreamState == KSSTATE_PAUSE) {
  1971. // One way to preroll is to delay when querying getting into the PAUSE state.
  1972. // However, this routine is never executed! So we move this section of code
  1973. // to the thread.
  1974. #ifdef SUPPORT_PREROLL_AT_RUN_STATE
  1975. if( pStrmExt->pStrmInfo->DataFlow == KSPIN_DATAFLOW_IN
  1976. && pStrmExt->hMasterClock
  1977. && pStrmExt->CurrentStreamTime == 0
  1978. ) {
  1979. // Simulate preroll at the RUN state
  1980. // We do this only when we are the clock provider to avoid dropping frame
  1981. #define PREROLL_WAITTIME 2000000
  1982. NTSTATUS StatusWait;
  1983. LARGE_INTEGER DueTime;
  1984. DueTime = RtlConvertLongToLargeInteger(-((LONG) PREROLL_WAITTIME));
  1985. StatusWait = // Can only return STATUS_SUCCESS (signal) or STATUS_TIMEOUT
  1986. KeWaitForSingleObject(
  1987. &pStrmExt->hPreRollEvent,
  1988. Executive,
  1989. KernelMode, // Cannot return STATUS_USER_APC
  1990. FALSE, // Cannot be alerted STATUS_ALERTED
  1991. &DueTime
  1992. );
  1993. TRACE(TL_STRM_WARNING,("\'GetState: *Preroll*, waited %d msec; waitStatus:%x; srbRcved:%d\n",
  1994. (DWORD) ((GetSystemTime() - pStrmExt->tmStreamPause)/10000), StatusWait,
  1995. (DWORD) pStrmExt->cntSRBReceived));
  1996. }
  1997. #endif
  1998. // A very odd rule:
  1999. // When transitioning from stop to pause (and run->pause), DShow tries to preroll
  2000. // the graph. Capture sources can't preroll (there is no data until
  2001. // capture begin/run state), and indicate this by returning
  2002. // VFW_S_CANT_CUE (Map by KsProxy) in user mode. To indicate this
  2003. // condition from drivers, they must return ERROR_NO_DATA_DETECTED
  2004. if(pStrmExt->pStrmInfo->DataFlow == KSPIN_DATAFLOW_OUT)
  2005. return STATUS_NO_DATA_DETECTED;
  2006. else
  2007. return STATUS_SUCCESS;
  2008. } else
  2009. return STATUS_SUCCESS;
  2010. }
  2011. NTSTATUS
  2012. DVStreamingStop(
  2013. PSTREAMEX pStrmExt,
  2014. PDVCR_EXTENSION pDevExt,
  2015. PAV_61883_REQUEST pAVReq
  2016. )
  2017. /*++
  2018. Routine Description:
  2019. Transitioning from any state to ->STOP state.
  2020. Stops the video stream and cleans up all the descriptors;
  2021. ++*/
  2022. {
  2023. NTSTATUS Status = STATUS_SUCCESS;
  2024. PIRP pIrp;
  2025. KIRQL oldIrql;
  2026. PAGED_CODE();
  2027. #ifdef SUPPORT_NEW_AVC
  2028. // No need to do CIP if it is device to device connection
  2029. if(pStrmExt->bDV2DVConnect) {
  2030. if(pStrmExt->bIsochIsActive)
  2031. pStrmExt->bIsochIsActive = FALSE;
  2032. return STATUS_SUCCESS;
  2033. }
  2034. #endif
  2035. //
  2036. // Stop isoch listen or talk
  2037. // Note: streaming and stream state can be separate; e.g. SURPRISE_REMOVAL,
  2038. // we will stop stream but stream state does note get changed by this SRB.
  2039. //
  2040. if(pStrmExt->bIsochIsActive && pStrmExt->hConnect) {
  2041. if(!(pIrp = IoAllocateIrp(pDevExt->pBusDeviceObject->StackSize, FALSE)))
  2042. return STATUS_INSUFFICIENT_RESOURCES;
  2043. RtlZeroMemory(pAVReq, sizeof(AV_61883_REQUEST));
  2044. INIT_61883_HEADER(pAVReq, Av61883_Stop);
  2045. pAVReq->Stop.hConnect = pStrmExt->hConnect;
  2046. if(!NT_SUCCESS(
  2047. Status = DVSubmitIrpSynch(
  2048. pDevExt,
  2049. pIrp,
  2050. pAVReq
  2051. ))) {
  2052. TRACE(TL_61883_ERROR|TL_STRM_ERROR,("\'Av61883_Stop Failed; Status:%x\n", Status));
  2053. #if 1
  2054. KeAcquireSpinLock(pStrmExt->DataListLock, &oldIrql);
  2055. pStrmExt->bIsochIsActive = FALSE; // Set it. If this fail, it is a lower stack problem!
  2056. KeReleaseSpinLock(pStrmExt->DataListLock, oldIrql);
  2057. ASSERT(NT_SUCCESS(Status) && "Av61883_Stop failed!");
  2058. Status = STATUS_SUCCESS;
  2059. #endif
  2060. } else {
  2061. KeAcquireSpinLock(pStrmExt->DataListLock, &oldIrql);
  2062. pStrmExt->bIsochIsActive = FALSE;
  2063. KeReleaseSpinLock(pStrmExt->DataListLock, oldIrql);
  2064. }
  2065. IoFreeIrp(pIrp);
  2066. TRACE(TL_STRM_WARNING,("\'StreamingSTOPped; AQD [%d:%d:%d]\n",
  2067. pStrmExt->cntDataAttached,
  2068. pStrmExt->cntSRBQueued,
  2069. pStrmExt->cntDataDetached
  2070. ));
  2071. }
  2072. return Status;
  2073. }
  2074. NTSTATUS
  2075. DVStreamingStart(
  2076. KSPIN_DATAFLOW ulDataFlow,
  2077. PSTREAMEX pStrmExt,
  2078. PDVCR_EXTENSION pDevExt
  2079. )
  2080. /*++
  2081. Routine Description:
  2082. Tell device to start streaming.
  2083. ++*/
  2084. {
  2085. PIRP pIrp;
  2086. NTSTATUS Status;
  2087. PAV_61883_REQUEST pAVReq;
  2088. #if DBG
  2089. ULONGLONG tmStart = GetSystemTime();
  2090. #endif
  2091. PAGED_CODE();
  2092. #ifdef SUPPORT_NEW_AVC
  2093. // No need to do CIP if it is device to device connection
  2094. if(pStrmExt->bDV2DVConnect) {
  2095. if(!pStrmExt->bIsochIsActive)
  2096. pStrmExt->bIsochIsActive = TRUE;
  2097. return STATUS_SUCCESS;
  2098. }
  2099. #endif
  2100. // NOTE: MUTEX is not needed since we are not staring isoch while attaching data.
  2101. // This call is not reentry!!
  2102. // Since it take time to activate isoch transfer,
  2103. // this sychronous function might get call again.
  2104. // Need to start streaming only once.
  2105. if(InterlockedExchange(&pStrmExt->lStartIsochToken, 1) == 1) {
  2106. TRACE(TL_STRM_WARNING,("\'lStartIsochToken taken already; return STATUS_SUCCESS\n"));
  2107. return STATUS_SUCCESS;
  2108. }
  2109. #if DBG
  2110. // Can stream only if in power on state.
  2111. if(pDevExt->PowerState != PowerDeviceD0) {
  2112. TRACE(TL_STRM_ERROR,("\'StreamingStart: PowerSt:%d; StrmSt:%d\n", pDevExt->PowerState, pStrmExt->StreamState));
  2113. ASSERT(pDevExt->PowerState == PowerDeviceD0 && "Power state must be ON to start streaming!");
  2114. }
  2115. #endif
  2116. if(pStrmExt->bIsochIsActive) {
  2117. TRACE(TL_STRM_WARNING,("\nIsoch already active!\n"));
  2118. InterlockedExchange(&pStrmExt->lStartIsochToken, 0);
  2119. return STATUS_SUCCESS;
  2120. }
  2121. else
  2122. if(!pStrmExt->hConnect) {
  2123. TRACE(TL_STRM_WARNING,("hConnect=0, Cannot start isoch!\n"));
  2124. InterlockedExchange(&pStrmExt->lStartIsochToken, 0);
  2125. return STATUS_INVALID_PARAMETER;
  2126. }
  2127. else {
  2128. if(!(pAVReq = (AV_61883_REQUEST *) ExAllocatePool(NonPagedPool, sizeof(AV_61883_REQUEST)))) {
  2129. InterlockedExchange(&pStrmExt->lStartIsochToken, 0);
  2130. return STATUS_INSUFFICIENT_RESOURCES;
  2131. }
  2132. if(!(pIrp = IoAllocateIrp(pDevExt->pBusDeviceObject->StackSize, FALSE))) {
  2133. InterlockedExchange(&pStrmExt->lStartIsochToken, 0);
  2134. ExFreePool(pAVReq); pAVReq = NULL;
  2135. return STATUS_INSUFFICIENT_RESOURCES;
  2136. }
  2137. RtlZeroMemory(pAVReq, sizeof(AV_61883_REQUEST));
  2138. if(ulDataFlow == KSPIN_DATAFLOW_OUT) {
  2139. INIT_61883_HEADER(pAVReq, Av61883_Listen);
  2140. pAVReq->Listen.hConnect = pStrmExt->hConnect;
  2141. } else {
  2142. INIT_61883_HEADER(pAVReq, Av61883_Talk);
  2143. pAVReq->Talk.hConnect = pStrmExt->hConnect;
  2144. }
  2145. TRACE(TL_STRM_WARNING,("\'StreamingSTART; flow %d; AQD [%d:%d:%d]\n",
  2146. ulDataFlow,
  2147. pStrmExt->cntDataAttached,
  2148. pStrmExt->cntSRBQueued,
  2149. pStrmExt->cntDataDetached
  2150. ));
  2151. if(NT_SUCCESS(
  2152. Status = DVSubmitIrpSynch(
  2153. pDevExt,
  2154. pIrp,
  2155. pAVReq
  2156. ))) {
  2157. pStrmExt->bIsochIsActive = TRUE;
  2158. TRACE(TL_STRM_WARNING,("\'Av61883_%s; Status %x; Streaming...; took:%d (msec)\n",
  2159. (ulDataFlow == KSPIN_DATAFLOW_OUT ? "Listen" : "Talk"), Status,
  2160. (DWORD) ((GetSystemTime() - tmStart)/10000) ));
  2161. }
  2162. else {
  2163. TRACE(TL_61883_ERROR|TL_STRM_ERROR,("Av61883_%s; failed %x; pAVReq:%x\n", (ulDataFlow == KSPIN_DATAFLOW_OUT ? "Listen" : "Talk"), Status, pAVReq));
  2164. // ASSERT(NT_SUCCESS(Status) && "Start isoch failed!");
  2165. }
  2166. ExFreePool(pAVReq); pAVReq = NULL;
  2167. IoFreeIrp(pIrp); pIrp = NULL;
  2168. }
  2169. InterlockedExchange(&pStrmExt->lStartIsochToken, 0);
  2170. return Status;
  2171. }
  2172. NTSTATUS
  2173. DVSetStreamState(
  2174. PSTREAMEX pStrmExt,
  2175. PDVCR_EXTENSION pDevExt,
  2176. PAV_61883_REQUEST pAVReq,
  2177. KSSTATE StreamState
  2178. )
  2179. /*++
  2180. Routine Description:
  2181. Set to a new stream state.
  2182. --*/
  2183. {
  2184. NTSTATUS Status = STATUS_SUCCESS;
  2185. PAGED_CODE();
  2186. if(!pStrmExt)
  2187. return STATUS_UNSUCCESSFUL;
  2188. TRACE(TL_STRM_WARNING,("\'** (%x) Set StrmST from %d to %d; PowerSt:%d (1/On;4/Off]); SrbRcved:%d\n",
  2189. pStrmExt, pStrmExt->StreamState, StreamState, pDevExt->PowerState, (DWORD) pStrmExt->cntSRBReceived ));
  2190. #if DBG
  2191. if(StreamState == KSSTATE_RUN) {
  2192. ASSERT(pDevExt->PowerState == PowerDeviceD0 && "Cannot set to RUN while power is off!");
  2193. }
  2194. #endif
  2195. switch(StreamState) {
  2196. case KSSTATE_STOP:
  2197. if(pStrmExt->StreamState != KSSTATE_STOP) {
  2198. KeWaitForSingleObject( pStrmExt->hStreamMutex, Executive, KernelMode, FALSE, 0 );
  2199. // Once this is set, data stream will reject SRB_WRITE/READ_DATA
  2200. pStrmExt->StreamStatePrevious = pStrmExt->StreamState; // Cache previous stream state.
  2201. pStrmExt->StreamState = KSSTATE_STOP;
  2202. // If stop, must be EOStream; but not vice versa.
  2203. if(!pStrmExt->bEOStream) {
  2204. pStrmExt->bEOStream = TRUE;
  2205. }
  2206. // Stop the IOThread from processing
  2207. if(pStrmExt->pStrmInfo->DataFlow == KSPIN_DATAFLOW_IN) {
  2208. KeClearEvent(&pStrmExt->hSrbArriveEvent);
  2209. #ifdef SUPPORT_PREROLL_AT_RUN_STATE
  2210. KeClearEvent(&pStrmExt->hPreRollEvent);
  2211. #endif
  2212. }
  2213. KeReleaseMutex(pStrmExt->hStreamMutex, FALSE);
  2214. //
  2215. // If there is a cancel event, we must wait for it to complete.
  2216. //
  2217. TRACE(TL_STRM_WARNING,("\'KSSTATE_STOP: pStrmExt->lCancelStateWorkItem:%d\n", pStrmExt->lCancelStateWorkItem));
  2218. KeWaitForSingleObject( &pStrmExt->hCancelDoneEvent, Executive, KernelMode, FALSE, 0 );
  2219. ASSERT(pStrmExt->lCancelStateWorkItem == 0 && "KSSTATE_STOP while there is an active CancelStateWorkItem");
  2220. //
  2221. // Stop stream, cacel data requests, terminate thread and disconnect.
  2222. // This routine must suceeded in setting to STOP state
  2223. //
  2224. if(!NT_SUCCESS(
  2225. Status = DVStopCancelDisconnect(
  2226. pStrmExt
  2227. ))) {
  2228. Status = STATUS_SUCCESS; // Cannot fail setting to stop state.
  2229. }
  2230. }
  2231. break;
  2232. case KSSTATE_ACQUIRE:
  2233. //
  2234. // This is a KS only state, that has no correspondence in DirectShow
  2235. // It is our opportunity to allcoate resoruce (isoch bandwidth and program PCR (make connection)).
  2236. //
  2237. if(pStrmExt->StreamState == KSSTATE_STOP) {
  2238. //
  2239. // Create a dispatch thread to attach frame to transmit to DV
  2240. // This is create the first time transitioning from STOP->ACQUIRE state
  2241. //
  2242. if(
  2243. KSPIN_DATAFLOW_IN == pStrmExt->pStrmInfo->DataFlow
  2244. && pStrmExt->pAttachFrameThreadObject == NULL
  2245. ) {
  2246. //
  2247. // Create a system thread for attaching data (for transmiut to DV only).
  2248. //
  2249. if(!NT_SUCCESS(
  2250. Status = DVCreateAttachFrameThread(
  2251. pStrmExt
  2252. ))) {
  2253. // Note that intially hConnect is NULL.
  2254. break; // Cannot attach frame without this thread.
  2255. }
  2256. }
  2257. //
  2258. // Make connection
  2259. //
  2260. Status =
  2261. DVConnect(
  2262. pStrmExt->pStrmInfo->DataFlow,
  2263. pDevExt,
  2264. pStrmExt,
  2265. pAVReq
  2266. );
  2267. if(!NT_SUCCESS(Status)) {
  2268. TRACE(TL_STRM_ERROR,("\'Acquire failed; ST %x\n", Status));
  2269. // ASSERT(NT_SUCCESS(Status));
  2270. //
  2271. // Change to generic insufficient resource status.
  2272. //
  2273. Status = STATUS_INSUFFICIENT_RESOURCES;
  2274. //
  2275. // Note: even setting to this state failed, KSSTATE_PAUSE will still be called;
  2276. // Since hConnect is NULL, STATUS_INSUFFICIENT_RESOURCES will be returned.
  2277. //
  2278. } else {
  2279. //
  2280. // Verify connection by query the plug state
  2281. //
  2282. DVGetPlugState(
  2283. pDevExt,
  2284. pStrmExt,
  2285. pAVReq
  2286. );
  2287. }
  2288. }
  2289. break;
  2290. case KSSTATE_PAUSE:
  2291. if(pStrmExt->StreamState == KSSTATE_ACQUIRE ||
  2292. pStrmExt->StreamState == KSSTATE_STOP) {
  2293. #ifdef SUPPORT_NEW_AVC
  2294. if(!pStrmExt->bDV2DVConnect && pStrmExt->hConnect == NULL) {
  2295. #else
  2296. if(pStrmExt->hConnect == NULL) {
  2297. #endif
  2298. TRACE(TL_STRM_ERROR,("\'hConnect is NULL; STATUS_INSUFFICIENT_RESOURCES\n"));
  2299. // Cannot stream without connection!
  2300. Status = STATUS_INSUFFICIENT_RESOURCES;
  2301. break;
  2302. }
  2303. //
  2304. // Reset when transition from STOP to PAUSE state
  2305. //
  2306. // The system time (1394 CycleTime) will continue while setting
  2307. // from RUN to PAUSE state.
  2308. pStrmExt->b1stNewFrameFromPauseState = TRUE;
  2309. #ifdef SUPPORT_QUALITY_CONTROL
  2310. // +: late; -: early
  2311. pStrmExt->KSQuality.DeltaTime = 0; // On time
  2312. // Percentage * 10 of frame transmitted
  2313. pStrmExt->KSQuality.Proportion = 1000; // 100% sent
  2314. pStrmExt->KSQuality.Context = /* NOT USED */ 0;
  2315. #endif
  2316. pStrmExt->CurrentStreamTime = 0;
  2317. pStrmExt->FramesProcessed = 0;
  2318. pStrmExt->PictureNumber = 0;
  2319. pStrmExt->FramesDropped = 0;
  2320. pStrmExt->cntSRBReceived = 0;
  2321. pStrmExt->cntSRBCancelled = 0; // number of SRB_READ/WRITE_DATA cancelled
  2322. pStrmExt->bEOStream = FALSE;
  2323. #if DBG
  2324. //
  2325. // Initialize the debug log structure.
  2326. //
  2327. if(pStrmExt->paXmtStat) {
  2328. pStrmExt->ulStatEntries = 0;
  2329. pStrmExt->lFramesAccumulatedPaused = 0;
  2330. pStrmExt->lFramesAccumulatedRun = 0;
  2331. RtlZeroMemory(pStrmExt->paXmtStat, sizeof(XMT_FRAME_STAT) * MAX_XMT_FRAMES_TRACED);
  2332. }
  2333. #endif
  2334. //
  2335. // Reset this event in case graph is restarted.
  2336. // This evant will wait for enough buffers before start attaching frame for transmit
  2337. //
  2338. if(pStrmExt->pStrmInfo->DataFlow == KSPIN_DATAFLOW_IN) {
  2339. KeClearEvent(&pStrmExt->hSrbArriveEvent);
  2340. #ifdef SUPPORT_PREROLL_AT_RUN_STATE
  2341. KeClearEvent(&pStrmExt->hPreRollEvent);
  2342. #if DBG
  2343. pStrmExt->tmStreamPause = GetSystemTime();
  2344. #endif
  2345. #ifdef SUPPORT_KSPROXY_PREROLL_CHANGE
  2346. pStrmExt->StreamStatePrevious = pStrmExt->StreamState; // Cache previous stream state.
  2347. pStrmExt->StreamState = StreamState;
  2348. #ifdef SUPPORT_NEW_AVC
  2349. if(pStrmExt->bDV2DVConnect)
  2350. return STATUS_SUCCESS;
  2351. else {
  2352. #endif // SUPPORT_NEW_AVC
  2353. TRACE(TL_STRM_WARNING,("\'Set to KSSTATE_PAUSE; return STATUS_ALERTED\n"));
  2354. // We want to preroll.
  2355. return STATUS_ALERTED;
  2356. #ifdef SUPPORT_NEW_AVC
  2357. }
  2358. #endif // SUPPORT_NEW_AVC
  2359. #endif // SUPPORT_KSPROXY_PREROLL_CHANGE
  2360. #endif // SUPPORT_PREROLL_AT_RUN_STATE
  2361. }
  2362. } else if (pStrmExt->StreamState == KSSTATE_RUN) {
  2363. // The system time (1394 CycleTime) will continue while setting
  2364. // from RUN to PAUSE state.
  2365. pStrmExt->b1stNewFrameFromPauseState = TRUE;
  2366. //
  2367. // Stop only if listening; for talking, the "pause" frame will be repeated
  2368. //
  2369. if(pStrmExt->pStrmInfo->DataFlow == KSPIN_DATAFLOW_OUT) {
  2370. // stop the stream internally inside 1394 stack
  2371. DVStreamingStop(
  2372. pStrmExt,
  2373. pDevExt,
  2374. pAVReq
  2375. );
  2376. } else {
  2377. // Talk will continue.
  2378. // Do not stop isoch talk until stop state.
  2379. }
  2380. //
  2381. // StreamTime pauses, so pause checking for expired clock events.
  2382. // Resume if we enter RUN state again.
  2383. //
  2384. if(pStrmExt->bTimerEnabled) {
  2385. TRACE(TL_STRM_TRACE,("\'*** (RUN->PAUSE) CancelTimer *********************************************...\n"));
  2386. KeCancelTimer(
  2387. pStrmExt->Timer
  2388. );
  2389. pStrmExt->bTimerEnabled = FALSE;
  2390. //
  2391. // Complete any pending clock events
  2392. //
  2393. DVSignalClockEvent(0, pStrmExt, 0, 0);
  2394. }
  2395. }
  2396. break;
  2397. case KSSTATE_RUN:
  2398. if(pStrmExt->StreamState != KSSTATE_RUN) {
  2399. TRACE(TL_STRM_WARNING,("\'*RUN: hClock %x; hMasterClk %x; cntAttached:%d; StrmTm:%d\n", pStrmExt->hClock, pStrmExt->hMasterClock, pStrmExt->cntDataAttached, (DWORD) (pStrmExt->CurrentStreamTime/10000) ));
  2400. #if DBG
  2401. if(!pStrmExt->hMasterClock && !pStrmExt->hClock)
  2402. TRACE(TL_STRM_WARNING,("\'KSSTATE_RUN: no clock so free flowing!\n"));
  2403. #endif
  2404. // Use to mark the tick count when the stream start running.
  2405. // It is later used to calculate current stream time and dropped frames.
  2406. pStrmExt->tmStreamStart = GetSystemTime();
  2407. pStrmExt->LastSystemTime = pStrmExt->tmStreamStart;
  2408. // We start the timer to signal clock event only if we are the clock provider.
  2409. // The interval is set to half of a DV frame time.
  2410. if(pStrmExt->hMasterClock) {
  2411. LARGE_INTEGER DueTime;
  2412. DueTime = RtlConvertLongToLargeInteger(-((LONG) DVFormatInfoTable[pDevExt->VideoFormatIndex].ulAvgTimePerFrame/2));
  2413. TRACE(TL_STRM_WARNING,("\'*** ScheduleTimer (RUN) ***\n"));
  2414. KeSetTimerEx(
  2415. pStrmExt->Timer,
  2416. DueTime,
  2417. DVFormatInfoTable[pDevExt->VideoFormatIndex].ulAvgTimePerFrame/20000, // Repeat every 40 MilliSecond
  2418. pStrmExt->DPCTimer
  2419. );
  2420. pStrmExt->bTimerEnabled = TRUE;
  2421. }
  2422. if(pStrmExt->pStrmInfo->DataFlow == KSPIN_DATAFLOW_OUT) {
  2423. // Start isoch listen; isoch talk will be start in the dispatch thread in either PAUSE or RUN state.
  2424. // VfW application may use only one buffer! 61883 is attaching the descriptor list
  2425. // not this subunit driver so so it is ok to start streaming immediately without checking
  2426. // number of buffers attached.
  2427. Status =
  2428. DVStreamingStart(
  2429. pStrmExt->pStrmInfo->DataFlow,
  2430. pStrmExt,
  2431. pDevExt
  2432. );
  2433. }
  2434. }
  2435. break;
  2436. default:
  2437. TRACE(TL_STRM_ERROR,("\'SetStreamState: unknown state = %x\n",StreamState));
  2438. Status = STATUS_NOT_SUPPORTED;
  2439. break;
  2440. }
  2441. // Be sure to save the state of the stream.
  2442. TRACE(TL_STRM_WARNING,("\'DVSetStreamState: (%x) from %d -> %d, Status %x\n", pStrmExt, pStrmExt->StreamState, StreamState, Status));
  2443. if(Status == STATUS_SUCCESS) {
  2444. pStrmExt->StreamStatePrevious = pStrmExt->StreamState; // Cache previous stream state.
  2445. pStrmExt->StreamState = StreamState;
  2446. }
  2447. return Status;
  2448. }
  2449. NTSTATUS
  2450. DVStreamGetConnectionProperty (
  2451. PDVCR_EXTENSION pDevExt,
  2452. PSTREAMEX pStrmExt,
  2453. PSTREAM_PROPERTY_DESCRIPTOR pSPD,
  2454. PULONG pulActualBytesTransferred
  2455. )
  2456. /*++
  2457. Routine Description:
  2458. Handles KS_PROPERTY_CONNECTION* request. For now, only ALLOCATORFRAMING and
  2459. CONNECTION_STATE are supported.
  2460. --*/
  2461. {
  2462. NTSTATUS Status = STATUS_SUCCESS;
  2463. PAGED_CODE();
  2464. TRACE(TL_STRM_TRACE,("\'DVStreamGetConnectionProperty: entered ...\n"));
  2465. switch (pSPD->Property->Id) {
  2466. case KSPROPERTY_CONNECTION_ALLOCATORFRAMING:
  2467. if (pDevExt != NULL && pDevExt->cndStrmOpen) {
  2468. PKSALLOCATOR_FRAMING pFraming = (PKSALLOCATOR_FRAMING) pSPD->PropertyInfo;
  2469. #ifdef SUPPORT_NEW_AVC
  2470. if(pStrmExt->bDV2DVConnect) {
  2471. // No framing required.
  2472. pFraming->RequirementsFlags = 0;
  2473. pFraming->PoolType = DontUseThisType;
  2474. pFraming->Frames = 0;
  2475. pFraming->FrameSize = 0;
  2476. pFraming->FileAlignment = 0;
  2477. pFraming->Reserved = 0;
  2478. } else {
  2479. #endif
  2480. pFraming->RequirementsFlags =
  2481. KSALLOCATOR_REQUIREMENTF_SYSTEM_MEMORY |
  2482. KSALLOCATOR_REQUIREMENTF_INPLACE_MODIFIER |
  2483. KSALLOCATOR_REQUIREMENTF_PREFERENCES_ONLY;
  2484. pFraming->PoolType = NonPagedPool;
  2485. pFraming->Frames = \
  2486. (pDevExt->paStrmExt[pDevExt->idxStreamNumber]->pStrmInfo->DataFlow == KSPIN_DATAFLOW_OUT ? \
  2487. DVFormatInfoTable[pDevExt->VideoFormatIndex].ulNumOfRcvBuffers : \
  2488. DVFormatInfoTable[pDevExt->VideoFormatIndex].ulNumOfXmtBuffers);
  2489. // Note: we'll allocate the biggest frame. We need to make sure when we're
  2490. // passing the frame back up we also set the number of bytes in the frame.
  2491. pFraming->FrameSize = DVFormatInfoTable[pDevExt->VideoFormatIndex].ulFrameSize;
  2492. pFraming->FileAlignment = 0; // FILE_LONG_ALIGNMENT;
  2493. pFraming->Reserved = 0;
  2494. #ifdef SUPPORT_NEW_AVC
  2495. }
  2496. #endif
  2497. *pulActualBytesTransferred = sizeof (KSALLOCATOR_FRAMING);
  2498. TRACE(TL_STRM_TRACE,("\'AllocFraming: cntStrmOpen:%d; VdoFmtIdx:%d; Frames %d; size:%d\n", \
  2499. pDevExt->cndStrmOpen, pDevExt->VideoFormatIndex, pFraming->Frames, pFraming->FrameSize));
  2500. } else {
  2501. TRACE(TL_STRM_WARNING,("\'AllocFraming: pDevExt:%x; cntStrmOpen:%d\n", pDevExt, pDevExt->cndStrmOpen));
  2502. Status = STATUS_INVALID_PARAMETER;
  2503. }
  2504. break;
  2505. default:
  2506. *pulActualBytesTransferred = 0;
  2507. Status = STATUS_NOT_SUPPORTED;
  2508. break;
  2509. }
  2510. TRACE(TL_STRM_TRACE,("\'DVStreamGetConnectionProperty: exit.\n"));
  2511. return Status;
  2512. }
  2513. NTSTATUS
  2514. DVGetDroppedFramesProperty(
  2515. PDVCR_EXTENSION pDevExt,
  2516. PSTREAMEX pStrmExt,
  2517. PSTREAM_PROPERTY_DESCRIPTOR pSPD,
  2518. PULONG pulBytesTransferred
  2519. )
  2520. /*++
  2521. Routine Description:
  2522. Return the dropped frame information while captureing.
  2523. --*/
  2524. {
  2525. NTSTATUS Status = STATUS_SUCCESS;
  2526. PAGED_CODE();
  2527. switch (pSPD->Property->Id) {
  2528. case KSPROPERTY_DROPPEDFRAMES_CURRENT:
  2529. {
  2530. PKSPROPERTY_DROPPEDFRAMES_CURRENT_S pDroppedFrames =
  2531. (PKSPROPERTY_DROPPEDFRAMES_CURRENT_S) pSPD->PropertyInfo;
  2532. pDroppedFrames->AverageFrameSize = DVFormatInfoTable[pStrmExt->pDevExt->VideoFormatIndex].ulFrameSize;
  2533. if(pStrmExt->pStrmInfo->DataFlow == KSPIN_DATAFLOW_IN) {
  2534. // This is the picture number that MSDV is actually sending, and in a slow harddisk case,
  2535. // it will be greater than (FramesProcessed + FramesDropped) considering repeat frame.
  2536. pDroppedFrames->PictureNumber = pStrmExt->PictureNumber;
  2537. pDroppedFrames->DropCount = pStrmExt->FramesDropped; // pStrmExt->PictureNumber - pStrmExt->FramesProcessed; // For transmit, this value includes both dropped and repeated.
  2538. } else {
  2539. pDroppedFrames->PictureNumber = pStrmExt->PictureNumber;
  2540. pDroppedFrames->DropCount = pStrmExt->FramesDropped; // For transmit, this value includes both dropped and repeated.
  2541. }
  2542. TRACE(TL_STRM_TRACE,("\'hMasClk:%x; *DroppedFP: Pic#(%d), Drp(%d); tmCurStream:%d\n",
  2543. pStrmExt->hMasterClock,
  2544. (LONG) pDroppedFrames->PictureNumber, (LONG) pDroppedFrames->DropCount,
  2545. (DWORD) (pStrmExt->CurrentStreamTime/10000)
  2546. ));
  2547. *pulBytesTransferred = sizeof (KSPROPERTY_DROPPEDFRAMES_CURRENT_S);
  2548. Status = STATUS_SUCCESS;
  2549. }
  2550. break;
  2551. default:
  2552. *pulBytesTransferred = 0;
  2553. Status = STATUS_NOT_SUPPORTED;
  2554. break;
  2555. }
  2556. return Status;
  2557. }
  2558. #ifdef SUPPORT_QUALITY_CONTROL
  2559. NTSTATUS
  2560. DVGetQualityControlProperty(
  2561. PDVCR_EXTENSION pDevExt,
  2562. PSTREAMEX pStrmExt,
  2563. PSTREAM_PROPERTY_DESCRIPTOR pSPD,
  2564. PULONG pulBytesTransferred
  2565. )
  2566. /*++
  2567. Routine Description:
  2568. Return the dropped frame information while captureing.
  2569. --*/
  2570. {
  2571. NTSTATUS Status = STATUS_SUCCESS;
  2572. PAGED_CODE();
  2573. switch (pSPD->Property->Id) {
  2574. case KSPROPERTY_STREAM_QUALITY:
  2575. if(pStrmExt->pStrmInfo->DataFlow == KSPIN_DATAFLOW_IN) {
  2576. PKSQUALITY pKSQuality = (PKSQUALITY) pSPD->PropertyInfo;
  2577. // Quality control only
  2578. if(pStrmExt->StreamState == KSSTATE_STOP || pStrmExt->StreamState == KSSTATE_ACQUIRE) {
  2579. *pulBytesTransferred = 0;
  2580. Status = STATUS_UNSUCCESSFUL; // Data is not ready
  2581. ASSERT(pSPD->Property->Id == KSPROPERTY_STREAM_QUALITY);
  2582. break;
  2583. }
  2584. /*
  2585. log.Init_Quality(KSPROPERTY_QUALITY_REPORT, fSuccess);
  2586. log.LogInt("Proportion", ksQuality.Proportion,
  2587. "Indicates the percentage of frames currently being received which are actually being used. "
  2588. " This is expressed in units of 0.1 of a percent, where 1000 is optimal.");
  2589. log.LogLONGLONG("DeltaTime", ksQuality.DeltaTime,
  2590. "Indicates the delta in native units (as indicated by the Interface) from optimal time at which "
  2591. "the frames are being delivered, where a positive number means too late, and a negative number means too early. "
  2592. "Zero indicate a correct delta.");
  2593. log.LogPVOID("pvContext", ksQuality.Context,
  2594. "Context parameter which could be a pointer to the filter pin interface used to "
  2595. "locate the source of the complaint in the graph topology.");
  2596. */
  2597. pKSQuality->DeltaTime = pStrmExt->KSQuality.DeltaTime;
  2598. pKSQuality->Proportion = pStrmExt->KSQuality.Proportion;
  2599. pKSQuality->Context = 0; // Not used!
  2600. TRACE(TL_STRM_WARNING,("\'Get QualityControl: Context:%x; DeltaTime:%d; Proportion:%d\n",
  2601. pKSQuality->Context, (DWORD) pKSQuality->DeltaTime, pKSQuality->Proportion));
  2602. Status = STATUS_SUCCESS;
  2603. *pulBytesTransferred = sizeof(KSQUALITY);
  2604. } else {
  2605. *pulBytesTransferred = 0;
  2606. Status = STATUS_NOT_SUPPORTED;
  2607. }
  2608. break;
  2609. default:
  2610. *pulBytesTransferred = 0;
  2611. Status = STATUS_NOT_SUPPORTED;
  2612. break;
  2613. }
  2614. return Status;
  2615. }
  2616. #endif // SUPPORT_QUALITY_CONTROL
  2617. #ifdef SUPPORT_NEW_AVC
  2618. NTSTATUS
  2619. DVGetPinProperty(
  2620. PDVCR_EXTENSION pDevExt,
  2621. PSTREAMEX pStrmExt,
  2622. PSTREAM_PROPERTY_DESCRIPTOR pSPD,
  2623. PULONG pulBytesTransferred
  2624. )
  2625. /*++
  2626. Routine Description:
  2627. Return the dropped frame information while captureing.
  2628. --*/
  2629. {
  2630. NTSTATUS Status = STATUS_SUCCESS;
  2631. PKSPIN_MEDIUM pPinMediums;
  2632. KSMULTIPLE_ITEM * pMultipleItem;
  2633. ULONG idxStreamNumber;
  2634. ULONG ulMediumsSize;
  2635. PAGED_CODE();
  2636. switch (pSPD->Property->Id) {
  2637. case KSPROPERTY_PIN_MEDIUMS:
  2638. if(!pStrmExt->pStrmObject) {
  2639. *pulBytesTransferred = 0;
  2640. return STATUS_UNSUCCESSFUL;
  2641. }
  2642. idxStreamNumber = pStrmExt->pStrmObject->StreamNumber;
  2643. ulMediumsSize = DVStreams[idxStreamNumber].hwStreamInfo.MediumsCount * sizeof(KSPIN_MEDIUM);
  2644. TRACE(TL_STRM_WARNING,("\'KSPROPERTY_PIN_MEDIUMS: idx:%d; MediumSize:%d\n", idxStreamNumber, ulMediumsSize));
  2645. // Its is KSMULTIPLE_ITEM so it is a two step process to return the data:
  2646. // (1) return size in pActualBytesTransferred with STATUS_BUFFER_OVERFLOW
  2647. // (2) 2nd time to get its actual data.
  2648. if(pSPD->PropertyOutputSize == 0) {
  2649. *pulBytesTransferred = sizeof(KSMULTIPLE_ITEM) + ulMediumsSize;
  2650. Status = STATUS_BUFFER_OVERFLOW;
  2651. } else if(pSPD->PropertyOutputSize >= (sizeof(KSMULTIPLE_ITEM) + ulMediumsSize)) {
  2652. pMultipleItem = (KSMULTIPLE_ITEM *) pSPD->PropertyInfo; // pointer to the data
  2653. pMultipleItem->Count = DVStreams[idxStreamNumber].hwStreamInfo.MediumsCount;
  2654. pMultipleItem->Size = sizeof(KSMULTIPLE_ITEM) + ulMediumsSize;
  2655. pPinMediums = (PKSPIN_MEDIUM) (pMultipleItem + 1); // pointer to the data
  2656. memcpy(pPinMediums, DVStreams[idxStreamNumber].hwStreamInfo.Mediums, ulMediumsSize);
  2657. *pulBytesTransferred = sizeof(KSMULTIPLE_ITEM) + ulMediumsSize;
  2658. Status = STATUS_SUCCESS;
  2659. } else {
  2660. TRACE(TL_STRM_ERROR,("DVCRMediaSeekingProperty: KSPROPERTY_MEDIASEEKING_FORMAT; STATUS_INVALID_PARAMETER\n"));
  2661. Status = STATUS_INVALID_PARAMETER;
  2662. }
  2663. break;
  2664. default:
  2665. *pulBytesTransferred = 0;
  2666. Status = STATUS_NOT_SUPPORTED;
  2667. break;
  2668. }
  2669. return Status;
  2670. }
  2671. #endif
  2672. NTSTATUS
  2673. DVGetStreamProperty(
  2674. PHW_STREAM_REQUEST_BLOCK pSrb
  2675. )
  2676. /*++
  2677. Routine Description:
  2678. Routine to process property request
  2679. --*/
  2680. {
  2681. NTSTATUS Status = STATUS_SUCCESS;
  2682. PSTREAM_PROPERTY_DESCRIPTOR pSPD = pSrb->CommandData.PropertyInfo;
  2683. PAGED_CODE();
  2684. TRACE(TL_STRM_TRACE,("\'DVGetStreamProperty: entered ...\n"));
  2685. if(IsEqualGUID (&KSPROPSETID_Connection, &pSPD->Property->Set)) {
  2686. Status =
  2687. DVStreamGetConnectionProperty (
  2688. pSrb->HwDeviceExtension,
  2689. (PSTREAMEX) pSrb->StreamObject->HwStreamExtension,
  2690. pSrb->CommandData.PropertyInfo,
  2691. &pSrb->ActualBytesTransferred
  2692. );
  2693. }
  2694. else if (IsEqualGUID (&PROPSETID_VIDCAP_DROPPEDFRAMES, &pSPD->Property->Set)) {
  2695. Status =
  2696. DVGetDroppedFramesProperty (
  2697. pSrb->HwDeviceExtension,
  2698. (PSTREAMEX) pSrb->StreamObject->HwStreamExtension,
  2699. pSrb->CommandData.PropertyInfo,
  2700. &pSrb->ActualBytesTransferred
  2701. );
  2702. }
  2703. #ifdef SUPPORT_QUALITY_CONTROL
  2704. else if (IsEqualGUID (&KSPROPSETID_Stream, &pSPD->Property->Set)) {
  2705. Status =
  2706. DVGetQualityControlProperty (
  2707. pSrb->HwDeviceExtension,
  2708. (PSTREAMEX) pSrb->StreamObject->HwStreamExtension,
  2709. pSrb->CommandData.PropertyInfo,
  2710. &pSrb->ActualBytesTransferred
  2711. );
  2712. }
  2713. #endif
  2714. #ifdef SUPPORT_NEW_AVC
  2715. else if (IsEqualGUID (&KSPROPSETID_Pin, &pSPD->Property->Set)) {
  2716. Status =
  2717. DVGetPinProperty (
  2718. pSrb->HwDeviceExtension,
  2719. (PSTREAMEX) pSrb->StreamObject->HwStreamExtension,
  2720. pSrb->CommandData.PropertyInfo,
  2721. &pSrb->ActualBytesTransferred
  2722. );
  2723. }
  2724. #endif
  2725. else {
  2726. Status = STATUS_NOT_SUPPORTED;
  2727. }
  2728. return Status;
  2729. }
  2730. NTSTATUS
  2731. DVSetStreamProperty(
  2732. PHW_STREAM_REQUEST_BLOCK pSrb
  2733. )
  2734. /*++
  2735. Routine Description:
  2736. Routine to process set property request
  2737. --*/
  2738. {
  2739. PSTREAM_PROPERTY_DESCRIPTOR pSPD = pSrb->CommandData.PropertyInfo;
  2740. PAGED_CODE();
  2741. TRACE(TL_STRM_WARNING,("\'DVSetStreamProperty: entered ...\n"));
  2742. return STATUS_NOT_SUPPORTED;
  2743. }
  2744. NTSTATUS
  2745. DVCancelOnePacketCR(
  2746. IN PDEVICE_OBJECT DeviceObject,
  2747. IN PIRP pIrp,
  2748. IN PSRB_DATA_PACKET pSrbDataPacket
  2749. )
  2750. /*++
  2751. Routine Description:
  2752. Completion routine for detach an isoch descriptor associate with a pending read SRB.
  2753. Will cancel the pending SRB here if detaching descriptor has suceeded.
  2754. --*/
  2755. {
  2756. PSTREAMEX pStrmExt;
  2757. PLONG plSrbUseCount;
  2758. PHW_STREAM_REQUEST_BLOCK pSrbToCancel;
  2759. KIRQL oldIrql;
  2760. if(!NT_SUCCESS(pIrp->IoStatus.Status)) {
  2761. TRACE(TL_STRM_ERROR,("CancelOnePacketCR: Srb:%x failed pIrp->Status %x\n", pSrbDataPacket->pSrb, pIrp->IoStatus.Status));
  2762. IoFreeIrp(pIrp); // Allocated locally
  2763. return STATUS_MORE_PROCESSING_REQUIRED;
  2764. }
  2765. pStrmExt = pSrbDataPacket->pStrmExt;
  2766. //
  2767. // Add this to the attached list
  2768. //
  2769. KeAcquireSpinLock(pStrmExt->DataListLock, &oldIrql);
  2770. // while it is being cancelled, it was completed ?
  2771. if(pStrmExt->cntDataAttached <= 0) {
  2772. TRACE(TL_STRM_WARNING|TL_CIP_WARNING,("\'DVCancelOnePacketCR:pStrmExt:%x, pSrbDataPacket:%x, AQD[%d:%d:%d]\n", \
  2773. pStrmExt, pSrbDataPacket,
  2774. pStrmExt->cntDataAttached,
  2775. pStrmExt->cntSRBQueued,
  2776. pStrmExt->cntDataDetached
  2777. ));
  2778. ASSERT(pStrmExt->cntDataAttached > 0);
  2779. KeReleaseSpinLock(pStrmExt->DataListLock, oldIrql);
  2780. IoFreeIrp(pIrp); // Allocated locally
  2781. return STATUS_MORE_PROCESSING_REQUIRED;
  2782. }
  2783. pSrbToCancel = pSrbDataPacket->pSrb; // Offload pSrb so this list entry can be inserted to available list.
  2784. plSrbUseCount = (PLONG) pSrbDataPacket->pSrb->SRBExtension;
  2785. // Remove from attached and add it to the detach list
  2786. RemoveEntryList(&pSrbDataPacket->ListEntry); pStrmExt->cntDataAttached--; (*plSrbUseCount)--;
  2787. #if DBG
  2788. // Detect if 61883 is starve. This cause discontinuity.
  2789. // This can happen for many valid reasons (slow system).
  2790. // An assert is added to detect other unknown reason.
  2791. if(pStrmExt->cntDataAttached == 0 && pStrmExt->StreamState == KSSTATE_RUN) {
  2792. TRACE(TL_STRM_WARNING|TL_CIP_WARNING,("\n**** 61883 starve in RUN state (cancel); AQD[%d:%d:%d]\n\n",
  2793. pStrmExt->cntDataAttached, pStrmExt->cntSRBQueued, pStrmExt->cntDataDetached
  2794. ));
  2795. // ASSERT(pStrmExt->cntDataAttached > 0 && "61883 is starve at RUN state!!");
  2796. }
  2797. #endif
  2798. ASSERT(pStrmExt->cntDataAttached >= 0);
  2799. ASSERT(*plSrbUseCount >= 0);
  2800. InsertTailList(&pStrmExt->DataDetachedListHead, &pSrbDataPacket->ListEntry); pStrmExt->cntDataDetached++;
  2801. pSrbDataPacket->State |= DE_IRP_CANCELLED;
  2802. //
  2803. // Complete this Srb if its refCount is 0.
  2804. //
  2805. if(*plSrbUseCount == 0) {
  2806. PDVCR_EXTENSION pDevExt;
  2807. pDevExt = pStrmExt->pDevExt;
  2808. pSrbToCancel->Status = (pDevExt->bDevRemoved ? STATUS_DEVICE_REMOVED : STATUS_CANCELLED);
  2809. pSrbToCancel->CommandData.DataBufferArray->DataUsed = 0;
  2810. pSrbToCancel->ActualBytesTransferred = 0;
  2811. pStrmExt->cntSRBCancelled++; // RefCnt is 0, and cancelled.
  2812. TRACE(TL_CIP_TRACE,("\'DVCancelOnePacketCR: Srb:%x cancelled; St:%x; cntCancel:%d\n", pSrbToCancel, pSrbToCancel->Status, pStrmExt->cntSRBCancelled));
  2813. StreamClassStreamNotification(StreamRequestComplete, pSrbToCancel->StreamObject, pSrbToCancel);
  2814. pSrbDataPacket->State |= DE_IRP_SRB_COMPLETED; pSrbDataPacket->pSrb = NULL;
  2815. #if DBG
  2816. pStrmExt->cntSRBPending--;
  2817. #endif
  2818. }
  2819. else {
  2820. TRACE(TL_STRM_WARNING|TL_CIP_WARNING,("\'DVCancelOnePacketCR: Srb:%x; RefCnt:%d; not completed!\n", pSrbDataPacket->pSrb, *plSrbUseCount));
  2821. }
  2822. KeReleaseSpinLock(pStrmExt->DataListLock, oldIrql);
  2823. IoFreeIrp(pIrp); // Allocated locally
  2824. return STATUS_MORE_PROCESSING_REQUIRED;
  2825. }
  2826. NTSTATUS
  2827. DVStopCancelDisconnect(
  2828. PSTREAMEX pStrmExt
  2829. )
  2830. /*++
  2831. Routine Description:
  2832. Stop a stream, cacel all pening data requests, terminate system thread, and disconnect.
  2833. --*/
  2834. {
  2835. AV_61883_REQUEST * pAVReq;
  2836. if(!(pAVReq = (AV_61883_REQUEST *) ExAllocatePool(NonPagedPool, sizeof(AV_61883_REQUEST)) ))
  2837. return STATUS_INSUFFICIENT_RESOURCES;
  2838. //
  2839. // Set stream state and the work item thread can both call this routine.
  2840. // Use a mutex to synchronize them.
  2841. //
  2842. KeWaitForSingleObject( pStrmExt->hStreamMutex, Executive, KernelMode, FALSE, 0 );
  2843. //
  2844. // Stop the 1394 isoch data transfer; Stream state is unchanged.
  2845. //
  2846. DVStreamingStop(
  2847. pStrmExt,
  2848. pStrmExt->pDevExt,
  2849. pAVReq
  2850. );
  2851. ExFreePool(pAVReq); pAVReq = NULL;
  2852. //
  2853. // Cancel all packets
  2854. //
  2855. DVCancelAllPackets(
  2856. pStrmExt,
  2857. pStrmExt->pDevExt
  2858. );
  2859. //
  2860. // If the device is removed, terminate the system thread for attach frame.
  2861. //
  2862. if( pStrmExt->pDevExt->bDevRemoved
  2863. && KSPIN_DATAFLOW_IN == pStrmExt->pStrmInfo->DataFlow
  2864. && !pStrmExt->bTerminateThread
  2865. && pStrmExt->pAttachFrameThreadObject
  2866. ) {
  2867. DVTerminateAttachFrameThread(pStrmExt);
  2868. pStrmExt->pAttachFrameThreadObject = NULL;
  2869. TRACE(TL_STRM_WARNING|TL_CIP_WARNING,("** DVStopCancelDisconnect: AttachFrameThread terminated;\n"));
  2870. }
  2871. //
  2872. // Break the connection so 61883 will free isoch resource
  2873. //
  2874. DVDisconnect(
  2875. pStrmExt->pStrmInfo->DataFlow,
  2876. pStrmExt->pDevExt,
  2877. pStrmExt
  2878. );
  2879. KeReleaseMutex(pStrmExt->hStreamMutex, FALSE);
  2880. return STATUS_SUCCESS;
  2881. }
  2882. void
  2883. DVCancelSrbWorkItemRoutine(
  2884. #ifdef USE_WDM110 // Win2000 code base
  2885. // Extra parameter if using WDM10
  2886. PDEVICE_OBJECT DeviceObject,
  2887. #endif
  2888. PSTREAMEX pStrmExt
  2889. )
  2890. /*++
  2891. Routine Description:
  2892. This work item routine will stop streaming and cancel all SRBs.
  2893. --*/
  2894. {
  2895. PAGED_CODE();
  2896. TRACE(TL_STRM_WARNING,("\'CancelWorkItem: StreamState:%d; lCancel:%d\n",
  2897. pStrmExt->StreamState, pStrmExt->lCancelStateWorkItem));
  2898. ASSERT(pStrmExt->lCancelStateWorkItem == 1);
  2899. #ifdef USE_WDM110 // Win2000 code base
  2900. ASSERT(pStrmExt->pIoWorkItem);
  2901. #endif
  2902. //
  2903. // Stop the stream and cancel all pending requests.
  2904. //
  2905. if(!NT_SUCCESS(DVStopCancelDisconnect(pStrmExt))) {
  2906. // Canceling is in theory done!
  2907. InterlockedExchange(&pStrmExt->lCancelStateWorkItem, 0);
  2908. KeSetEvent(&pStrmExt->hCancelDoneEvent, 0, FALSE); pStrmExt->bAbortPending = FALSE;
  2909. goto DVAbortWorkItemRoutine;
  2910. }
  2911. //
  2912. // Canceling is in theory done!
  2913. //
  2914. InterlockedExchange(&pStrmExt->lCancelStateWorkItem, 0);
  2915. KeSetEvent(&pStrmExt->hCancelDoneEvent, 0, FALSE); pStrmExt->bAbortPending = FALSE;
  2916. // If the device is removed, terminate the system thread that is used
  2917. // for attaching frame for transmit to DV
  2918. if( pStrmExt->pDevExt->bDevRemoved
  2919. && KSPIN_DATAFLOW_IN == pStrmExt->pStrmInfo->DataFlow
  2920. && !pStrmExt->bTerminateThread
  2921. && pStrmExt->pAttachFrameThreadObject
  2922. ) {
  2923. DVTerminateAttachFrameThread(pStrmExt);
  2924. pStrmExt->pAttachFrameThreadObject = NULL;
  2925. TRACE(TL_STRM_WARNING|TL_CIP_WARNING,("** WortItemRoutine: thread terminated;\n"));
  2926. }
  2927. DVAbortWorkItemRoutine:
  2928. ;
  2929. #ifdef USE_WDM110 // Win2000 code base
  2930. // Release work item and release the cancel token
  2931. IoFreeWorkItem(pStrmExt->pIoWorkItem); pStrmExt->pIoWorkItem = NULL;
  2932. #endif
  2933. }
  2934. BOOL
  2935. DVAbortStream(
  2936. PDVCR_EXTENSION pDevExt,
  2937. PSTREAMEX pStrmExt
  2938. )
  2939. /*++
  2940. Routine Description:
  2941. Start a work item to abort streaming.
  2942. --*/
  2943. {
  2944. //
  2945. // Claim this token; only one abort streaming per STOP->PAUSE transition.
  2946. //
  2947. if(InterlockedExchange(&pStrmExt->lCancelStateWorkItem, 1) == 1) {
  2948. TRACE(TL_STRM_TRACE,("\'Cancel work item is already issued.\n"));
  2949. return FALSE;
  2950. }
  2951. TRACE(TL_STRM_WARNING,("\'DVAbortStream is issued; lCancelStateWorkItem:%d\n", pStrmExt->lCancelStateWorkItem));
  2952. //
  2953. // Non-signal this event so other thread depending on the completion will wait.
  2954. //
  2955. KeClearEvent(&pStrmExt->hCancelDoneEvent); pStrmExt->bAbortPending = TRUE;
  2956. //
  2957. // If we are not running at DISPATFCH level or higher, we abort the stream without scheduleing
  2958. // a work item; else schedule a work item is necessary.
  2959. //
  2960. if (KeGetCurrentIrql() <= APC_LEVEL) {
  2961. DVStopCancelDisconnect(pStrmExt);
  2962. InterlockedExchange(&pStrmExt->lCancelStateWorkItem, 0);
  2963. KeSetEvent(&pStrmExt->hCancelDoneEvent, 0, FALSE); pStrmExt->bAbortPending = FALSE;
  2964. return TRUE;
  2965. }
  2966. #ifdef USE_WDM110 // Win2000 code base
  2967. ASSERT(pStrmExt->pIoWorkItem == NULL); // Have not yet queued work item.
  2968. // We will queue work item to stop and cancel all SRBs
  2969. if(pStrmExt->pIoWorkItem = IoAllocateWorkItem(pDevExt->pBusDeviceObject)) {
  2970. IoQueueWorkItem(
  2971. pStrmExt->pIoWorkItem,
  2972. DVCancelSrbWorkItemRoutine,
  2973. DelayedWorkQueue, // CriticalWorkQueue
  2974. pStrmExt
  2975. );
  2976. #else // Win9x code base
  2977. ExInitializeWorkItem( &pStrmExt->IoWorkItem, DVCancelSrbWorkItemRoutine, pStrmExt);
  2978. if(TRUE) {
  2979. ExQueueWorkItem(
  2980. &pStrmExt->IoWorkItem,
  2981. DelayedWorkQueue // CriticalWorkQueue
  2982. );
  2983. #endif
  2984. TRACE(TL_STRM_WARNING,("\'CancelWorkItm queued; SrbRcv:%d;Pic#:%d;Prc:%d;;Drop:%d;Cncl:%d; AQD [%d:%d:%d]\n",
  2985. (DWORD) pStrmExt->cntSRBReceived,
  2986. (DWORD) pStrmExt->PictureNumber,
  2987. (DWORD) pStrmExt->FramesProcessed,
  2988. (DWORD) pStrmExt->FramesDropped,
  2989. (DWORD) pStrmExt->cntSRBCancelled,
  2990. pStrmExt->cntDataAttached,
  2991. pStrmExt->cntSRBQueued,
  2992. pStrmExt->cntDataDetached
  2993. ));
  2994. }
  2995. #ifdef USE_WDM110 // Win2000 code base
  2996. else {
  2997. InterlockedExchange(&pStrmExt->lCancelStateWorkItem, 0);
  2998. KeSetEvent(&pStrmExt->hCancelDoneEvent, 0, FALSE); pStrmExt->bAbortPending = FALSE;
  2999. ASSERT(pStrmExt->pIoWorkItem && "IoAllocateWorkItem failed.\n");
  3000. return FALSE;
  3001. }
  3002. #endif
  3003. return TRUE;
  3004. }
  3005. VOID
  3006. DVCancelOnePacket(
  3007. IN PHW_STREAM_REQUEST_BLOCK pSrbToCancel
  3008. )
  3009. /*++
  3010. Routine Description:
  3011. Search pending read lists for the SRB to be cancel. If found cancel it.
  3012. --*/
  3013. {
  3014. PDVCR_EXTENSION pDevExt;
  3015. PSTREAMEX pStrmExt;
  3016. KIRQL OldIrql;
  3017. pDevExt = (PDVCR_EXTENSION) pSrbToCancel->HwDeviceExtension;
  3018. // Cannot cancel device Srb.
  3019. if ((pSrbToCancel->Flags & SRB_HW_FLAGS_STREAM_REQUEST) != SRB_HW_FLAGS_STREAM_REQUEST) {
  3020. TRACE(TL_CIP_ERROR|TL_STRM_ERROR,("\'DVCancelOnePacket: Device SRB %x; cannot cancel!\n", pSrbToCancel));
  3021. ASSERT((pSrbToCancel->Flags & SRB_HW_FLAGS_STREAM_REQUEST) == SRB_HW_FLAGS_STREAM_REQUEST );
  3022. return;
  3023. }
  3024. // Can try to cancel a stream Srb and only if the stream extension still around.
  3025. pStrmExt = (PSTREAMEX) pSrbToCancel->StreamObject->HwStreamExtension;
  3026. if(pStrmExt == NULL) {
  3027. TRACE(TL_CIP_ERROR|TL_STRM_ERROR,("DVCancelOnePacket: pSrbTocancel %x but pStrmExt %x\n", pSrbToCancel, pStrmExt));
  3028. ASSERT(pStrmExt && "Stream SRB but stream extension is NULL\n");
  3029. return;
  3030. }
  3031. // We can only cancel SRB_READ/WRITE_DATA SRB
  3032. if((pSrbToCancel->Command != SRB_READ_DATA) && (pSrbToCancel->Command != SRB_WRITE_DATA)) {
  3033. TRACE(TL_CIP_ERROR|TL_STRM_ERROR,("DVCancelOnePacket: pSrbTocancel %x; Command:%d not SRB_READ,WRITE_DATA\n", pSrbToCancel, pSrbToCancel->Command));
  3034. return;
  3035. }
  3036. TRACE(TL_STRM_TRACE|TL_CIP_TRACE,("\'DVCancelOnePacket: KSSt %d; Srb:%x; AQD[%d:%d:%d]\n",
  3037. pStrmExt->StreamState, pSrbToCancel, pStrmExt->cntDataAttached, pStrmExt->cntSRBQueued, pStrmExt->cntDataDetached));
  3038. KeAcquireSpinLock(&pDevExt->AVCCmdLock, &OldIrql);
  3039. //
  3040. // If device is removed, the surprise removal routine will do the cancelling.
  3041. //
  3042. if(!pDevExt->bDevRemoved) {
  3043. KeReleaseSpinLock(&pDevExt->AVCCmdLock, OldIrql);
  3044. // We will start an work item to stop streaming if we ever get an cancel Srb.
  3045. if(!DVAbortStream(pDevExt, pStrmExt)) {
  3046. TRACE(TL_STRM_WARNING,("\'CancelOnePacket: pSrb:%x; AbortStream not taken!\n", pSrbToCancel));
  3047. }
  3048. } else {
  3049. TRACE(TL_STRM_WARNING,("\'CancelOnePacket: DevRemoved; pSrb:%x; AbortStream not taken!\n", pSrbToCancel));
  3050. KeReleaseSpinLock(&pDevExt->AVCCmdLock, OldIrql);
  3051. }
  3052. }
  3053. VOID
  3054. DVCancelAllPackets(
  3055. PSTREAMEX pStrmExt,
  3056. PDVCR_EXTENSION pDevExt
  3057. )
  3058. /*++
  3059. Routine Description:
  3060. Cancel all packet when This is where most of the interesting Stream requests come to us
  3061. --*/
  3062. {
  3063. PHW_STREAM_REQUEST_BLOCK pSrb;
  3064. PSRB_DATA_PACKET pSrbDataPacket;
  3065. PAV_61883_REQUEST pAVReq;
  3066. PSRB_ENTRY pSrbEntry;
  3067. NTSTATUS Status;
  3068. PIRP pIrp;
  3069. PLIST_ENTRY pEntry;
  3070. PIO_STACK_LOCATION NextIrpStack;
  3071. KIRQL oldIrql;
  3072. PAGED_CODE();
  3073. #if DBG
  3074. if(pStrmExt->StreamState != KSSTATE_STOP) {
  3075. TRACE(TL_STRM_WARNING|TL_CIP_WARNING,("DVCancelAllPackets: Enter; pStrmExt:%x; StrmSt:%d; IsochActive:%d\n",
  3076. pStrmExt, pStrmExt->StreamState, pStrmExt->bIsochIsActive));
  3077. }
  3078. #endif
  3079. //
  3080. // Detached request only if not streaming
  3081. //
  3082. // Note: no need to spin lock this if isoch has stopped.
  3083. if(!pStrmExt->bIsochIsActive) {
  3084. PLONG plSrbUseCount;
  3085. TRACE(TL_STRM_WARNING,("\'CancelAll: AQD: [%d:%d:%d]; DataAttachedListHead:%x\n",
  3086. pStrmExt->cntDataAttached,
  3087. pStrmExt->cntSRBQueued,
  3088. pStrmExt->cntDataDetached,
  3089. pStrmExt->DataAttachedListHead
  3090. ));
  3091. //
  3092. // Cancel buffer(s) that are still attached.
  3093. //
  3094. KeAcquireSpinLock(pStrmExt->DataListLock, &oldIrql);
  3095. pEntry = pStrmExt->DataAttachedListHead.Flink;
  3096. while(pEntry != &pStrmExt->DataAttachedListHead) {
  3097. ASSERT(pStrmExt->cntDataAttached > 0 && "List and cntAttached out of sync!");
  3098. // Get an irp and detached the buffer
  3099. if(!(pIrp = IoAllocateIrp(pDevExt->pBusDeviceObject->StackSize, FALSE))) {
  3100. KeReleaseSpinLock(pStrmExt->DataListLock, oldIrql);
  3101. return;
  3102. }
  3103. pSrbDataPacket = CONTAINING_RECORD(pEntry, SRB_DATA_PACKET, ListEntry);
  3104. #if DBG
  3105. if(!IsStateSet(pSrbDataPacket->State, DE_IRP_ATTACHED_COMPLETED)) {
  3106. TRACE(TL_STRM_ERROR,("Cancel (unattached) entry; pStrmExt:%x; pSrbDataPacket:%x\n", pStrmExt, pSrbDataPacket));
  3107. ASSERT(IsStateSet(pSrbDataPacket->State, DE_IRP_ATTACHED_COMPLETED));
  3108. }
  3109. #endif
  3110. pEntry = pEntry->Flink; // Next since this may get changed in the completion routine
  3111. KeReleaseSpinLock(pStrmExt->DataListLock, oldIrql);
  3112. pSrb = pSrbDataPacket->pSrb;
  3113. ASSERT(pSrbDataPacket->pSrb);
  3114. plSrbUseCount = (PLONG) pSrb->SRBExtension;
  3115. pAVReq = &pSrbDataPacket->AVReq;
  3116. RtlZeroMemory(pAVReq, sizeof(AV_61883_REQUEST));
  3117. INIT_61883_HEADER(pAVReq, Av61883_CancelFrame);
  3118. pAVReq->CancelFrame.hConnect = pStrmExt->hConnect;
  3119. pAVReq->CancelFrame.Frame = pSrbDataPacket->Frame;
  3120. TRACE(TL_CIP_TRACE,("\'Canceling AttachList: pSrb %x, AvReq %x; UseCount %d\n", pSrb, pAVReq, *plSrbUseCount));
  3121. ASSERT(pSrbDataPacket->Frame);
  3122. NextIrpStack = IoGetNextIrpStackLocation(pIrp);
  3123. NextIrpStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
  3124. NextIrpStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_61883_CLASS;
  3125. NextIrpStack->Parameters.Others.Argument1 = pAVReq;
  3126. IoSetCompletionRoutine(
  3127. pIrp,
  3128. DVCancelOnePacketCR,
  3129. pSrbDataPacket,
  3130. TRUE,
  3131. TRUE,
  3132. TRUE
  3133. );
  3134. Status =
  3135. IoCallDriver(
  3136. pDevExt->pBusDeviceObject,
  3137. pIrp
  3138. );
  3139. ASSERT(Status == STATUS_PENDING || Status == STATUS_SUCCESS);
  3140. KeAcquireSpinLock(pStrmExt->DataListLock, &oldIrql);
  3141. }
  3142. KeReleaseSpinLock(pStrmExt->DataListLock, oldIrql);
  3143. #if DBG
  3144. if(pStrmExt->cntDataAttached != 0) {
  3145. TRACE(TL_STRM_WARNING|TL_CIP_WARNING,("\'DVCancelAllPackets: cntDataAttached:%d !!\n", pStrmExt->cntDataAttached));
  3146. ASSERT(pStrmExt->cntDataAttached == 0);
  3147. }
  3148. #endif
  3149. //
  3150. // Cancel SRB that are still the SrbQ; this applies only to SRB_WRITE_DATA
  3151. //
  3152. pEntry = pStrmExt->SRBQueuedListHead.Flink;
  3153. while(pEntry != &pStrmExt->SRBQueuedListHead) {
  3154. pSrbEntry = CONTAINING_RECORD(pEntry, SRB_ENTRY, ListEntry);
  3155. plSrbUseCount = (PLONG) pSrbEntry->pSrb->SRBExtension;
  3156. pEntry = pEntry->Flink; // Next since this may get changed if removed
  3157. TRACE(TL_CIP_TRACE,("\'DVCnclAllPkts (SrbQ): cntQ:%d; pSrb:%x; UseCnt:%d (=? 1)\n", pStrmExt->cntSRBQueued, pSrbEntry->pSrb, *plSrbUseCount));
  3158. if(*plSrbUseCount == 1) {
  3159. RemoveEntryList(&pSrbEntry->ListEntry); pStrmExt->cntSRBQueued--; (*plSrbUseCount)--; // Remove from queueed.
  3160. pStrmExt->cntSRBCancelled++;
  3161. pSrbEntry->pSrb->Status = (pDevExt->bDevRemoved ? STATUS_DEVICE_REMOVED : STATUS_CANCELLED);
  3162. pSrbEntry->pSrb->CommandData.DataBufferArray->DataUsed = 0;
  3163. pSrbEntry->pSrb->ActualBytesTransferred = 0;
  3164. TRACE(TL_STRM_WARNING,("\'Cancel queued SRB: pSRB:%x, Status:%x; cntSrbCancelled:%d\n", pSrbEntry->pSrb, pSrbEntry->pSrb->Status, pStrmExt->cntSRBCancelled));
  3165. StreamClassStreamNotification(StreamRequestComplete, pSrbEntry->pSrb->StreamObject, pSrbEntry->pSrb);
  3166. #if DBG
  3167. pStrmExt->cntSRBPending--;
  3168. #endif
  3169. ExFreePool(pSrbEntry);
  3170. } else {
  3171. TRACE(TL_STRM_ERROR|TL_CIP_ERROR,("\'NOT Cancel queued SRB: pSRB:%x, Status:%x; *plSrbUseCount:%d, cntSrbCancelled:%d\n", pSrbEntry->pSrb, pSrbEntry->pSrb->Status, *plSrbUseCount, pStrmExt->cntSRBCancelled));
  3172. ASSERT(*plSrbUseCount == 0 && "Still in use ?");
  3173. break; // Still in used. Perhaps, free it in TimeoutHandler() or CancelOnePacket()
  3174. }
  3175. }
  3176. #if DBG
  3177. if(pStrmExt->cntSRBQueued != 0 || !IsListEmpty(&pStrmExt->SRBQueuedListHead)) {
  3178. TRACE(TL_STRM_ERROR|TL_CIP_ERROR,("\'DVCancelAllPackets: cntSRBQueued:%d !! Empty?%d\n", pStrmExt->cntSRBQueued, IsListEmpty(&pStrmExt->SRBQueuedListHead)));
  3179. ASSERT(pStrmExt->cntSRBQueued == 0);
  3180. }
  3181. #endif
  3182. }
  3183. else {
  3184. TRACE(TL_STRM_ERROR,("\'IsochActive; cannot cancel! cntSrbQ:%d; cntAttached:%d.\n", pStrmExt->cntSRBQueued, pStrmExt->cntDataAttached));
  3185. ASSERT(pStrmExt->bIsochIsActive);
  3186. }
  3187. TRACE(TL_STRM_WARNING|TL_CIP_WARNING,("\'DVCancelAllPackets: ************************ Exit!\n"));
  3188. }
  3189. VOID
  3190. DVTimeoutHandler(
  3191. IN PHW_STREAM_REQUEST_BLOCK pSrb
  3192. )
  3193. /*++
  3194. Routine Description:
  3195. This routine is called when a packet has been in the minidriver too long.
  3196. It can only valid if we are it wa a streaming packet and in PAUSE state;
  3197. else we have a problem!
  3198. Arguments:
  3199. pSrb - Pointer to Stream request block
  3200. Return Value:
  3201. Nothing
  3202. --*/
  3203. {
  3204. //
  3205. // Note:
  3206. // Called from StreamClass at DisptchLevel
  3207. //
  3208. //
  3209. // We only expect stream SRB, but not device SRB.
  3210. //
  3211. if ( (pSrb->Flags & SRB_HW_FLAGS_STREAM_REQUEST) != SRB_HW_FLAGS_STREAM_REQUEST) {
  3212. TRACE(TL_PNP_ERROR,("TimeoutHandler: Device SRB %x (cmd:%x) timed out!\n", pSrb, pSrb->Command));
  3213. return;
  3214. } else {
  3215. //
  3216. // pSrb->StreamObject (and pStrmExt) only valid if it is a stream SRB
  3217. //
  3218. PSTREAMEX pStrmExt;
  3219. pStrmExt = (PSTREAMEX) pSrb->StreamObject->HwStreamExtension;
  3220. if(!pStrmExt) {
  3221. TRACE(TL_PNP_ERROR,("TimeoutHandler: Stream SRB %x timeout with pStrmExt %x\n", pSrb, pStrmExt));
  3222. ASSERT(pStrmExt);
  3223. return;
  3224. }
  3225. TRACE(TL_STRM_WARNING,("\'TimeoutHandler: KSSt %d; Srb:%x (cmd:%x); AQD[%d:%d:%d]\n",
  3226. pStrmExt->StreamState, pSrb, pSrb->Command, pStrmExt->cntDataAttached, pStrmExt->cntSRBQueued, pStrmExt->cntDataDetached));
  3227. //
  3228. // Stream SRB (esp the data SRB) can time out if there is not
  3229. // data on the bus; however, it can only happen while in PAUSE
  3230. // or RUN state when attaching data SRB is valid.
  3231. //
  3232. if(pStrmExt->StreamState != KSSTATE_PAUSE &&
  3233. pStrmExt->StreamState != KSSTATE_RUN) {
  3234. TRACE(TL_PNP_ERROR|TL_STRM_ERROR,("\'TmOutHndlr:(Irql:%d) Srb %x (cmd:%x); %s, pStrmExt %x, AQD [%d:%d:%d]\n",
  3235. KeGetCurrentIrql(),
  3236. pSrb, pSrb->Command,
  3237. pStrmExt->StreamState == KSSTATE_RUN ? "RUN" :
  3238. pStrmExt->StreamState == KSSTATE_PAUSE ? "PAUSE":
  3239. pStrmExt->StreamState == KSSTATE_STOP ? "STOP": "Unknown",
  3240. pStrmExt,
  3241. pStrmExt->cntDataAttached,
  3242. pStrmExt->cntSRBQueued,
  3243. pStrmExt->cntDataDetached
  3244. ));
  3245. }
  3246. //
  3247. // Reset Timeout counter, or we are going to get this call immediately.
  3248. //
  3249. pSrb->TimeoutCounter = pSrb->TimeoutOriginal;
  3250. }
  3251. }
  3252. NTSTATUS
  3253. DVEventHandler(
  3254. IN PHW_EVENT_DESCRIPTOR pEventDescriptor
  3255. )
  3256. /*++
  3257. Routine Description:
  3258. This routine is called to process events.
  3259. --*/
  3260. {
  3261. PSTREAMEX pStrmExt;
  3262. if(IsEqualGUID (&KSEVENTSETID_Clock, pEventDescriptor->EventEntry->EventSet->Set)) {
  3263. if(pEventDescriptor->EventEntry->EventItem->EventId == KSEVENT_CLOCK_POSITION_MARK) {
  3264. if(pEventDescriptor->Enable) {
  3265. // Note: According to the DDK, StreamClass queues pEventDescriptor->EventEntry, and dellaocate
  3266. // every other structures, including the pEventDescriptor->EventData.
  3267. if(pEventDescriptor->StreamObject) {
  3268. PKSEVENT_TIME_MARK pEventTime;
  3269. pStrmExt = (PSTREAMEX) pEventDescriptor->StreamObject->HwStreamExtension;
  3270. pEventTime = (PKSEVENT_TIME_MARK) pEventDescriptor->EventData;
  3271. // Cache the event data (Specified in the ExtraEntryData of KSEVENT_ITEM)
  3272. RtlCopyMemory((pEventDescriptor->EventEntry+1), pEventDescriptor->EventData, sizeof(KSEVENT_TIME_MARK));
  3273. TRACE(TL_STRM_TRACE,("\'CurrentStreamTime:%d, MarkTime:%d\n", (DWORD) pStrmExt->CurrentStreamTime, (DWORD) pEventTime->MarkTime));
  3274. }
  3275. } else {
  3276. // Disabled!
  3277. TRACE(TL_STRM_TRACE,("\'KSEVENT_CLOCK_POSITION_MARK disabled!\n"));
  3278. }
  3279. return STATUS_SUCCESS;
  3280. }
  3281. } else if(IsEqualGUID (&KSEVENTSETID_Connection, pEventDescriptor->EventEntry->EventSet->Set)) {
  3282. TRACE(TL_STRM_WARNING,("\'Connection event: pEventDescriptor:%x; id:%d\n", pEventDescriptor, pEventDescriptor->EventEntry->EventItem->EventId));
  3283. pStrmExt = (PSTREAMEX) pEventDescriptor->StreamObject->HwStreamExtension;
  3284. if(pStrmExt->pStrmInfo->DataFlow == KSPIN_DATAFLOW_IN) {
  3285. if(pEventDescriptor->EventEntry->EventItem->EventId == KSEVENT_CONNECTION_ENDOFSTREAM) {
  3286. if(pEventDescriptor->Enable) {
  3287. TRACE(TL_STRM_TRACE,("\'KSEVENT_CONNECTION_ENDOFSTREAM enabled!\n"));
  3288. } else {
  3289. TRACE(TL_STRM_TRACE,("\'KSEVENT_CONNECTION_ENDOFSTREAM disabled!\n"));
  3290. }
  3291. return STATUS_SUCCESS;
  3292. }
  3293. }
  3294. }
  3295. TRACE(TL_STRM_ERROR,("\'NOT_SUPPORTED event: pEventDescriptor:%x\n", pEventDescriptor));
  3296. ASSERT(FALSE && "Event not advertised and not supported!");
  3297. return STATUS_NOT_SUPPORTED;
  3298. }
  3299. VOID
  3300. DVSignalClockEvent(
  3301. IN PKDPC Dpc,
  3302. IN PSTREAMEX pStrmExt,
  3303. IN PVOID SystemArgument1,
  3304. IN PVOID SystemArgument2
  3305. )
  3306. /*++
  3307. Routine Description:
  3308. This routine is called when we are the clock provider and when our clock "tick".
  3309. Find a pending clock event, signal it if it has expired.
  3310. --*/
  3311. {
  3312. PKSEVENT_ENTRY pEvent, pLast;
  3313. ULONGLONG tmStreamTime;
  3314. #if DBG
  3315. ULONG EventPendings = 0;
  3316. #endif
  3317. pEvent = NULL;
  3318. pLast = NULL;
  3319. //
  3320. // A clock tick for DV is one frame time. For better precision,
  3321. // we calculate current stream time with an offset from the last system time being queried.
  3322. // We also add a max latency of one frame for decoding a DV frame.
  3323. //
  3324. tmStreamTime =
  3325. pStrmExt->CurrentStreamTime +
  3326. (GetSystemTime() - pStrmExt->LastSystemTime) +
  3327. DVFormatInfoTable[pStrmExt->pDevExt->VideoFormatIndex].ulAvgTimePerFrame; // Allow one frame of latency
  3328. while((
  3329. pEvent = StreamClassGetNextEvent(
  3330. pStrmExt->pDevExt,
  3331. pStrmExt->pStrmObject,
  3332. (GUID *)&KSEVENTSETID_Clock,
  3333. KSEVENT_CLOCK_POSITION_MARK,
  3334. pLast ))
  3335. != NULL ) {
  3336. #if DBG
  3337. EventPendings++;
  3338. #endif
  3339. if (
  3340. // For real time capture (DV->PC), signal every frame.
  3341. // No frame that is produce can be "early" and requires AdviseTime().
  3342. pStrmExt->pStrmInfo->DataFlow == KSPIN_DATAFLOW_OUT ||
  3343. pStrmExt->bEOStream
  3344. || (pStrmExt->StreamState != KSSTATE_RUN) // If not in RUN state, Data should be completed.
  3345. || pStrmExt->pDevExt->PowerState != PowerDeviceD0 // If not power ON, data should be completed.
  3346. || ((PKSEVENT_TIME_MARK)(pEvent +1))->MarkTime <= (LONGLONG) tmStreamTime ) {
  3347. TRACE(TL_STRM_TRACE,("\'PowerSt:%d (ON:1?); StrmSt:%d; Clock event %x with id %d; Data:%x; \ttmMark\t%d \ttmCurrentStream \t%d; Notify!\n",
  3348. pStrmExt->pDevExt->PowerState, pStrmExt->StreamState,
  3349. pEvent, KSEVENT_CLOCK_POSITION_MARK, (PKSEVENT_TIME_MARK)(pEvent +1),
  3350. (DWORD) (((PKSEVENT_TIME_MARK)(pEvent +1))->MarkTime), (DWORD) tmStreamTime));
  3351. ASSERT( ((PKSEVENT_TIME_MARK)(pEvent +1))->MarkTime > 0 );
  3352. //
  3353. // signal the event here
  3354. //
  3355. StreamClassStreamNotification(
  3356. SignalStreamEvent,
  3357. pStrmExt->pStrmObject,
  3358. pEvent
  3359. );
  3360. #if DBG
  3361. if(pStrmExt->bEOStream) {
  3362. TRACE(TL_STRM_WARNING,("\'bEOStream: Clock event %x with id %d; Data:%x; \ttmMark \t%d \ttmCurStream \t%d\n",
  3363. pEvent, KSEVENT_CLOCK_POSITION_MARK, (PKSEVENT_TIME_MARK)(pEvent +1),
  3364. (DWORD) (((PKSEVENT_TIME_MARK)(pEvent +1))->MarkTime), (DWORD) tmStreamTime));
  3365. }
  3366. #endif
  3367. } else {
  3368. TRACE(TL_STRM_WARNING,("\'PowerST:%d; StrmST:%d; AQD[%d:%d:%d]; Still early! ClockEvent: \tMarkTime \t%d \ttmStream \t%d \tdetla \t%d\n",
  3369. pStrmExt->pDevExt->PowerState, pStrmExt->StreamState,
  3370. pStrmExt->cntDataAttached, pStrmExt->cntSRBQueued, pStrmExt->cntDataDetached,
  3371. (DWORD) (((PKSEVENT_TIME_MARK)(pEvent +1))->MarkTime), (DWORD) tmStreamTime,
  3372. (DWORD) ((((PKSEVENT_TIME_MARK)(pEvent +1))->MarkTime) - tmStreamTime)
  3373. ));
  3374. }
  3375. pLast = pEvent;
  3376. }
  3377. #if DBG
  3378. if(EventPendings == 0) {
  3379. TRACE(TL_STRM_TRACE,("\'No event pending; PowerSt:%d (ON:1?); StrmSt:%d; AQD[%d:%d:%d]\n",
  3380. pStrmExt->pDevExt->PowerState, pStrmExt->StreamState,
  3381. pStrmExt->cntDataAttached, pStrmExt->cntSRBQueued, pStrmExt->cntDataDetached
  3382. ));
  3383. }
  3384. #endif
  3385. }
  3386. VOID
  3387. StreamClockRtn(
  3388. IN PHW_TIME_CONTEXT TimeContext
  3389. )
  3390. /*++
  3391. Routine Description:
  3392. This routine is called whenever someone in the graph wants to know what time it is, and we are the Master Clock.
  3393. --*/
  3394. {
  3395. PDVCR_EXTENSION pDevExt;
  3396. PHW_STREAM_OBJECT pStrmObj;
  3397. PSTREAMEX pStrmExt;
  3398. // Call at dispatch level
  3399. pDevExt = (PDVCR_EXTENSION) TimeContext->HwDeviceExtension;
  3400. pStrmObj = TimeContext->HwStreamObject;
  3401. if(pStrmObj)
  3402. pStrmExt = pStrmObj->HwStreamExtension;
  3403. else
  3404. pStrmExt = 0;
  3405. if(!pDevExt || !pStrmExt) {
  3406. ASSERT(pDevExt && pStrmExt);
  3407. return;
  3408. }
  3409. switch (TimeContext->Function) {
  3410. case TIME_GET_STREAM_TIME:
  3411. //
  3412. // How long since the stream was first set into the run state?
  3413. //
  3414. ASSERT(pStrmExt->hMasterClock && "We are not master clock but we were qureied?");
  3415. TimeContext->SystemTime = GetSystemTime();
  3416. if(pStrmExt->pStrmInfo->DataFlow == KSPIN_DATAFLOW_IN) {
  3417. if(pStrmExt->StreamState == KSSTATE_RUN) { // Stream time is only meaningful in RUN state
  3418. if(TimeContext->SystemTime >= pStrmExt->LastSystemTime)
  3419. TimeContext->Time =
  3420. pStrmExt->CurrentStreamTime + (TimeContext->SystemTime - pStrmExt->LastSystemTime);
  3421. else {
  3422. TimeContext->Time = pStrmExt->CurrentStreamTime;
  3423. TRACE(TL_STRM_WARNING,("\'Clock went backward? %d -> %d\n", (DWORD) (TimeContext->SystemTime/10000), (DWORD) (pStrmExt->LastSystemTime/10000) ));
  3424. // ASSERT(TimeContext->SystemTime >= pStrmExt->LastSystemTime);
  3425. }
  3426. // Make current stream time one frame behind
  3427. if(TimeContext->Time > DVFormatInfoTable[pDevExt->VideoFormatIndex].ulAvgTimePerFrame)
  3428. TimeContext->Time = TimeContext->Time - DVFormatInfoTable[pDevExt->VideoFormatIndex].ulAvgTimePerFrame;
  3429. else
  3430. TimeContext->Time = 0;
  3431. } else {
  3432. if(pStrmExt->FramesProcessed > 0)
  3433. TimeContext->Time = pStrmExt->CurrentStreamTime;
  3434. else
  3435. TimeContext->Time = 0; // if get queried at the PAUSE state.
  3436. }
  3437. } else {
  3438. if(pStrmExt->StreamState == KSSTATE_RUN) {
  3439. #ifdef NT51_61883
  3440. // Can advance at most MAX_CYCLES_TIME (supported by 1394 OHCI).
  3441. if((TimeContext->SystemTime - pStrmExt->LastSystemTime) > MAX_CYCLES_TIME)
  3442. TimeContext->Time = pStrmExt->CurrentStreamTime + MAX_CYCLES_TIME;
  3443. #else
  3444. // Cannot advance more than one frame time.
  3445. if((TimeContext->SystemTime - pStrmExt->LastSystemTime) >= DVFormatInfoTable[pDevExt->VideoFormatIndex].ulAvgTimePerFrame)
  3446. TimeContext->Time = pStrmExt->CurrentStreamTime + DVFormatInfoTable[pDevExt->VideoFormatIndex].ulAvgTimePerFrame;
  3447. #endif // NT51_61883
  3448. else
  3449. TimeContext->Time =
  3450. pStrmExt->CurrentStreamTime + (TimeContext->SystemTime - pStrmExt->LastSystemTime);
  3451. // Necessary tuning ?
  3452. // Make current stream time one frame behind so that the downstream filter
  3453. // can render the data promptly instead of discarding it if it is late.
  3454. if(TimeContext->Time > DVFormatInfoTable[pDevExt->VideoFormatIndex].ulAvgTimePerFrame)
  3455. TimeContext->Time = TimeContext->Time - DVFormatInfoTable[pDevExt->VideoFormatIndex].ulAvgTimePerFrame;
  3456. else
  3457. TimeContext->Time = 0;
  3458. } else {
  3459. if(pStrmExt->FramesProcessed > 0)
  3460. TimeContext->Time = pStrmExt->CurrentStreamTime;
  3461. else
  3462. TimeContext->Time = 0;
  3463. }
  3464. }
  3465. TRACE(TL_STRM_TRACE,("\'TIME_GET_STREAM_TIME: ST:%d; Frame:%d; tmSys:%d; tmStream:%d msec\n",
  3466. pStrmExt->StreamState,
  3467. (DWORD) pStrmExt->PictureNumber,
  3468. (DWORD)(TimeContext->SystemTime/10000), (DWORD)(TimeContext->Time/10000)));
  3469. break;
  3470. default:
  3471. ASSERT(TimeContext->Function == TIME_GET_STREAM_TIME && "Unsupport clock func");
  3472. break;
  3473. } // switch TimeContext->Function
  3474. }
  3475. NTSTATUS
  3476. DVOpenCloseMasterClock (
  3477. PSTREAMEX pStrmExt,
  3478. HANDLE hMasterClockHandle
  3479. )
  3480. /*++
  3481. Routine Description:
  3482. We can be a clock provider.
  3483. --*/
  3484. {
  3485. PAGED_CODE();
  3486. // Make sure the stream exist.
  3487. if(pStrmExt == NULL) {
  3488. TRACE(TL_STRM_ERROR,("\'DVOpenCloseMasterClock: stream is not yet running.\n"));
  3489. ASSERT(pStrmExt);
  3490. return STATUS_UNSUCCESSFUL;
  3491. }
  3492. TRACE(TL_STRM_TRACE,("\'DVOpenCloseMasterClock: pStrmExt %x; hMyClock:%x->%x\n",
  3493. pStrmExt, pStrmExt->hMyClock, hMasterClockHandle));
  3494. if(hMasterClockHandle) {
  3495. // Open master clock
  3496. ASSERT(pStrmExt->hMyClock == NULL && "OpenMasterClk while hMyClock is not NULL!");
  3497. pStrmExt->hMyClock = hMasterClockHandle;
  3498. } else {
  3499. // Close master clock
  3500. ASSERT(pStrmExt->hMyClock && "CloseMasterClk while hMyClock is NULL!");
  3501. pStrmExt->hMyClock = NULL;
  3502. }
  3503. return STATUS_SUCCESS;
  3504. }
  3505. NTSTATUS
  3506. DVIndicateMasterClock (
  3507. PSTREAMEX pStrmExt,
  3508. HANDLE hIndicateClockHandle
  3509. )
  3510. /*++
  3511. Routine Description:
  3512. Compare the indicate clock handle with my clock handle.
  3513. If the same, we are the master clock; else, other device is
  3514. the master clock.
  3515. Note: either hMasterClock or hClock can be set.
  3516. --*/
  3517. {
  3518. PAGED_CODE();
  3519. // Make sure the stream exist.
  3520. if (pStrmExt == NULL) {
  3521. TRACE(TL_STRM_ERROR,("DVIndicateMasterClock: stream is not yet running.\n"));
  3522. ASSERT(pStrmExt);
  3523. return STATUS_UNSUCCESSFUL;
  3524. }
  3525. TRACE(TL_STRM_TRACE,("\'*>IndicateMasterClk[Enter]: pStrmExt:%x; hMyClk:%x; IndMClk:%x; pClk:%x, pMClk:%x\n",
  3526. pStrmExt, pStrmExt->hMyClock, hIndicateClockHandle, pStrmExt->hClock, pStrmExt->hMasterClock));
  3527. // it not null, set master clock accordingly.
  3528. if(hIndicateClockHandle == pStrmExt->hMyClock) {
  3529. pStrmExt->hMasterClock = hIndicateClockHandle;
  3530. pStrmExt->hClock = NULL;
  3531. } else {
  3532. pStrmExt->hMasterClock = NULL;
  3533. pStrmExt->hClock = hIndicateClockHandle;
  3534. }
  3535. TRACE(TL_STRM_TRACE,("\'<*IndicateMasterClk[Exit]: hMyClk:%x; IndMClk:%x; pClk:%x; pMClk:%x\n",
  3536. pStrmExt->hMyClock, hIndicateClockHandle, pStrmExt->hClock, pStrmExt->hMasterClock));
  3537. return STATUS_SUCCESS;
  3538. }