Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

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