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

2677 lines
78 KiB

  1. /*++
  2. Copyright (C) Microsoft Corporation, 1999 - 2000
  3. Module Name:
  4. MSDVUtil.c
  5. Abstract:
  6. Provide utility functions for MSDV.
  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 "msdvfmt.h"
  22. #include "msdvdef.h"
  23. #include "MsdvAvc.h"
  24. #include "MsdvUtil.h"
  25. #include "XPrtDefs.h"
  26. #if 0 // Enable later
  27. #ifdef ALLOC_PRAGMA
  28. #pragma alloc_text(PAGE, DVDelayExecutionThread)
  29. #pragma alloc_text(PAGE, DVGetUnitCapabilities)
  30. // Local variables might paged out but the called might use it in DISPATCH level!
  31. // #pragma alloc_text(PAGE, DVGetDevModeOfOperation)
  32. // #pragma alloc_text(PAGE, DVGetDevIsItDVCPro)
  33. // #pragma alloc_text(PAGE, DVGetDevSignalFormat)
  34. #pragma alloc_text(PAGE, DvAllocatePCResource)
  35. #pragma alloc_text(PAGE, DvFreePCResource)
  36. #pragma alloc_text(PAGE, DVGetPlugState)
  37. #pragma alloc_text(PAGE, DVConnect)
  38. #pragma alloc_text(PAGE, DVDisconnect)
  39. #endif
  40. #endif
  41. extern DV_FORMAT_INFO DVFormatInfoTable[];
  42. VOID
  43. DVDelayExecutionThread(
  44. ULONG ulDelayMSec
  45. )
  46. /*
  47. Device might need a "wait" in between AV/C commands.
  48. */
  49. {
  50. PAGED_CODE();
  51. if (ulDelayMSec)
  52. {
  53. LARGE_INTEGER tmDelay;
  54. TRACE(TL_PNP_TRACE,("\'DelayExeThrd: %d MSec\n", ulDelayMSec));
  55. tmDelay.LowPart = (ULONG) (-1 * ulDelayMSec * 10000);
  56. tmDelay.HighPart = -1;
  57. KeDelayExecutionThread(KernelMode, FALSE, &tmDelay);
  58. }
  59. }
  60. NTSTATUS
  61. DVIrpSynchCR(
  62. IN PDEVICE_OBJECT DeviceObject,
  63. IN PIRP pIrp,
  64. IN PKEVENT Event
  65. )
  66. {
  67. KeSetEvent(Event, 0, FALSE);
  68. return STATUS_MORE_PROCESSING_REQUIRED;
  69. } // DVIrpSynchCR
  70. NTSTATUS
  71. DVSubmitIrpSynch(
  72. IN PDVCR_EXTENSION pDevExt,
  73. IN PIRP pIrp,
  74. IN PAV_61883_REQUEST pAVReq
  75. )
  76. {
  77. NTSTATUS Status;
  78. KEVENT Event;
  79. PIO_STACK_LOCATION NextIrpStack;
  80. Status = STATUS_SUCCESS;;
  81. NextIrpStack = IoGetNextIrpStackLocation(pIrp);
  82. NextIrpStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
  83. NextIrpStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_61883_CLASS;
  84. NextIrpStack->Parameters.Others.Argument1 = pAVReq;
  85. KeInitializeEvent(&Event, NotificationEvent, FALSE);
  86. IoSetCompletionRoutine(
  87. pIrp,
  88. DVIrpSynchCR,
  89. &Event,
  90. TRUE,
  91. TRUE,
  92. TRUE
  93. );
  94. Status =
  95. IoCallDriver(
  96. pDevExt->pBusDeviceObject,
  97. pIrp
  98. );
  99. if (Status == STATUS_PENDING) {
  100. TRACE(TL_PNP_TRACE,("\'Irp is pending...\n"));
  101. if(KeGetCurrentIrql() < DISPATCH_LEVEL) {
  102. KeWaitForSingleObject(
  103. &Event,
  104. Executive,
  105. KernelMode,
  106. FALSE,
  107. NULL
  108. );
  109. TRACE(TL_PNP_TRACE,("\'Irp has returned; IoStatus==Status %x\n", pIrp->IoStatus.Status));
  110. Status = pIrp->IoStatus.Status; // Final status
  111. }
  112. else {
  113. ASSERT(FALSE && "Pending but in DISPATCH_LEVEL!");
  114. return Status;
  115. }
  116. }
  117. return Status;
  118. } // DVSubmitIrpSynchAV
  119. BOOL
  120. DVGetDevModeOfOperation(
  121. IN PDVCR_EXTENSION pDevExt
  122. )
  123. {
  124. NTSTATUS Status;
  125. BYTE bAvcBuf[MAX_FCP_PAYLOAD_SIZE];
  126. PAGED_CODE();
  127. //
  128. // Use ConnectAV STATUS cmd to determine mode of operation,
  129. // except for some Canon DVs that it requires its vendor specific command
  130. //
  131. Status =
  132. DVIssueAVCCommand(
  133. pDevExt,
  134. AVC_CTYPE_STATUS,
  135. DV_CONNECT_AV_MODE,
  136. (PVOID) bAvcBuf
  137. );
  138. TRACE(TL_FCP_TRACE,("\'DV_CONNECT_AV_MODE: St:%x, %x %x %x %x : %x %x %x %x\n",
  139. Status, bAvcBuf[0], bAvcBuf[1], bAvcBuf[2], bAvcBuf[3], bAvcBuf[4], bAvcBuf[5], bAvcBuf[6], bAvcBuf[7]));
  140. if(Status == STATUS_SUCCESS) {
  141. if(bAvcBuf[0] == 0x0c) {
  142. if(bAvcBuf[1] == 0x00 &&
  143. bAvcBuf[2] == 0x38 &&
  144. bAvcBuf[3] == 0x38) {
  145. pDevExt->ulDevType = ED_DEVTYPE_CAMERA;
  146. } else {
  147. pDevExt->ulDevType = ED_DEVTYPE_VCR;
  148. }
  149. }
  150. } else if(pDevExt->ulVendorID == VENDORID_CANON) {
  151. // Try a vendor dependent command if it is a Canon AV device.
  152. Status =
  153. DVIssueAVCCommand(
  154. pDevExt,
  155. AVC_CTYPE_STATUS,
  156. DV_VEN_DEP_CANON_MODE,
  157. (PVOID) bAvcBuf
  158. );
  159. TRACE(TL_FCP_WARNING,("\'DV_VEN_DEP_CANON_MODE: Status %x, %x %x %x %x : %x %x %x %x %x %x\n",
  160. Status, bAvcBuf[0], bAvcBuf[1], bAvcBuf[2], bAvcBuf[3], bAvcBuf[4], bAvcBuf[5], bAvcBuf[6], bAvcBuf[7], bAvcBuf[8], bAvcBuf[9]));
  161. if(Status == STATUS_SUCCESS) {
  162. if(bAvcBuf[0] == 0x0c) {
  163. if(bAvcBuf[7] == 0x38) {
  164. pDevExt->ulDevType = ED_DEVTYPE_CAMERA;
  165. } else
  166. if(bAvcBuf[7] == 0x20) {
  167. pDevExt->ulDevType = ED_DEVTYPE_VCR;
  168. }
  169. }
  170. }
  171. }
  172. if(Status != STATUS_SUCCESS) {
  173. pDevExt->ulDevType = ED_DEVTYPE_UNKNOWN;
  174. TRACE(TL_FCP_ERROR,("\'DV_CONNECT_AV_MODE: Status %x, DevType %x, %x %x %x %x : %x %x %x %x : %x %x\n",
  175. Status, pDevExt->ulDevType, bAvcBuf[0], bAvcBuf[1], bAvcBuf[2], bAvcBuf[3], bAvcBuf[4], bAvcBuf[5], bAvcBuf[6], bAvcBuf[7], bAvcBuf[8], bAvcBuf[9]));
  176. }
  177. TRACE(TL_FCP_WARNING,("\'%s; NumOPlg:%d; NumIPlg:%d\n",
  178. pDevExt->ulDevType == ED_DEVTYPE_CAMERA ? "Camera" : pDevExt->ulDevType == ED_DEVTYPE_VCR ? "VTR" : "Unknown",
  179. pDevExt->NumOutputPlugs, pDevExt->NumInputPlugs));
  180. return TRUE;
  181. }
  182. BOOL
  183. DVGetDevIsItDVCPro(
  184. IN PDVCR_EXTENSION pDevExt
  185. )
  186. {
  187. NTSTATUS Status;
  188. BYTE bAvcBuf[MAX_FCP_PAYLOAD_SIZE];
  189. PAGED_CODE();
  190. //
  191. // Use Panasnoic's vendor dependent command to determine if the system support DVCPro
  192. //
  193. Status =
  194. DVIssueAVCCommand(
  195. pDevExt,
  196. AVC_CTYPE_STATUS,
  197. DV_VEN_DEP_DVCPRO,
  198. (PVOID) bAvcBuf
  199. );
  200. pDevExt->bDVCPro = Status == STATUS_SUCCESS;
  201. TRACE(TL_FCP_WARNING,("\'DVGetDevIsItDVCPro? %s; Status %x, %x %x %x %x : %x %x %x %x\n",
  202. pDevExt->bDVCPro ? "Yes":"No",
  203. Status, bAvcBuf[0], bAvcBuf[1], bAvcBuf[2], bAvcBuf[3], bAvcBuf[4], bAvcBuf[5], bAvcBuf[6], bAvcBuf[7]));
  204. return pDevExt->bDVCPro;
  205. }
  206. // The retries might be redundant since AVC.sys and 1394.sys retries.
  207. // For device that TIMEOUT an AVC command, we will only try it once.
  208. #define GET_MEDIA_FMT_MAX_RETRIES 10
  209. BOOL
  210. DVGetDevSignalFormat(
  211. IN PDVCR_EXTENSION pDevExt,
  212. IN KSPIN_DATAFLOW DataFlow,
  213. IN PSTREAMEX pStrmExt
  214. )
  215. {
  216. NTSTATUS Status;
  217. BYTE bAvcBuf[MAX_FCP_PAYLOAD_SIZE];
  218. LONG lRetries = GET_MEDIA_FMT_MAX_RETRIES;
  219. PAGED_CODE();
  220. //
  221. // Respone of Input/output signal mode is used to determine plug signal format:
  222. //
  223. // FMT:
  224. // DVCR 10:00 0000 = 0x80; Canon returns 00:100000 (0x20)
  225. // 50/60: 0:NTSC/60; 1:PAL/50
  226. // STYPE:
  227. // SD: 00000 (DVCPRO:11110)
  228. // HD: 00010
  229. // SDL:00001
  230. // 00:
  231. // SYT:
  232. // MPEG 10:10 0000 = 0xa0
  233. // TSF:0:NotTimeShifted; 1:Time shifted
  234. // 000 0000 0000 0000 0000 0000
  235. //
  236. // If this command failed, we can use Input/Output Signal Mode subunit command
  237. // to determine signal format.
  238. //
  239. do {
  240. RtlZeroMemory(bAvcBuf, sizeof(bAvcBuf));
  241. Status =
  242. DVIssueAVCCommand(
  243. pDevExt,
  244. AVC_CTYPE_STATUS,
  245. pStrmExt == NULL ? DV_OUT_PLUG_SIGNAL_FMT : (DataFlow == KSPIN_DATAFLOW_OUT ? DV_OUT_PLUG_SIGNAL_FMT : DV_IN_PLUG_SIGNAL_FMT),
  246. (PVOID) bAvcBuf
  247. );
  248. //
  249. // Camcorders that has problem with this command:
  250. //
  251. // Panasonic's DVCPRO: if power on while connected to PC, it will
  252. // reject this command with (STATUS_REQUEST_NOT_ACCEPTED)
  253. // so we will retry up to 10 time with .5 second wait between tries.
  254. //
  255. // JVC: returns STATUS_NOT_SUPPORTED.
  256. //
  257. // SONY DV Decoder Box: return STATUS_TIMEOUT or STATUS_REQUEST_ABORTED
  258. //
  259. if(STATUS_REQUEST_ABORTED == Status)
  260. return FALSE;
  261. else if(STATUS_SUCCESS == Status)
  262. break; // Normal case.
  263. else if(STATUS_NOT_SUPPORTED == Status || STATUS_TIMEOUT == Status) {
  264. TRACE(TL_FCP_WARNING | TL_PNP_WARNING,("SignalFormat: Encountered a known failed status:%x; no more retry\n", Status));
  265. break; // No need to retry
  266. } else {
  267. if(Status == STATUS_REQUEST_NOT_ACCEPTED) {
  268. // If device is not accepting command and return this status, retry.
  269. if(lRetries > 0) {
  270. TRACE(TL_FCP_WARNING | TL_PNP_WARNING,("\'ST:%x; Retry getting signal mode; wait...\n", Status));
  271. DVDelayExecutionThread(DV_AVC_CMD_DELAY_DVCPRO);
  272. }
  273. }
  274. }
  275. } while (--lRetries >= 0);
  276. if(NT_SUCCESS(Status)) {
  277. switch(bAvcBuf[0]) {
  278. case FMT_DVCR:
  279. case FMT_DVCR_CANON: // Workaround for buggy Canon Camcorders
  280. switch(bAvcBuf[1] & FDF0_STYPE_MASK) {
  281. case FDF0_STYPE_SD_DVCR:
  282. case FDF0_STYPE_SD_DVCPRO:
  283. pDevExt->VideoFormatIndex = ((bAvcBuf[1] & FDF0_50_60_MASK) ? FMT_IDX_SD_DVCR_PAL : FMT_IDX_SD_DVCR_NTSC);
  284. if(pStrmExt)
  285. RtlCopyMemory(&pStrmExt->cipQuad2[0], &bAvcBuf[0], 4);
  286. break;
  287. #ifdef MSDV_SUPPORT_HD_DVCR
  288. case FDF0_STYPE_HD_DVCR:
  289. pDevExt->VideoFormatIndex = ((bAvcBuf[1] & FDF0_50_60_MASK) ? FMT_IDX_HD_DVCR_PAL : FMT_IDX_HD_DVCR_NTSC);
  290. if(pStrmExt)
  291. RtlCopyMemory(&pStrmExt->cipQuad2[0], &bAvcBuf[0], 4);
  292. break;
  293. #endif
  294. #ifdef MSDV_SUPPORT_SDL_DVCR
  295. case FDF0_STYPE_SDL_DVCR:
  296. pDevExt->VideoFormatIndex = ((bAvcBuf[1] & FDF0_50_60_MASK) ? FMT_IDX_SDL_DVCR_PAL : FMT_IDX_SDL_DVCR_NTSC);
  297. if(pStrmExt)
  298. RtlCopyMemory(&pStrmExt->cipQuad2[0], &bAvcBuf[0], 4);
  299. break;
  300. #endif
  301. default: // Unknown format
  302. Status = STATUS_UNSUCCESSFUL;
  303. break;
  304. }
  305. break;
  306. #ifdef MSDV_SUPPORT_MPEG2TS
  307. case FMT_MPEG:
  308. pDevExt->VideoFormatIndex = FMT_IDX_MPEG2TS;
  309. if(pStrmExt)
  310. RtlCopyMemory(&pStrmExt->cipQuad2[0], &bAvcBuf[0], 4);
  311. break;
  312. #endif
  313. default:
  314. Status = STATUS_UNSUCCESSFUL;
  315. }
  316. if(NT_SUCCESS(Status)) {
  317. TRACE(TL_FCP_WARNING,("\'ST:%x; PlugSignal:FMT[%x %x %x %x]; VideoFormatIndex;%d\n", Status, bAvcBuf[0], bAvcBuf[1], bAvcBuf[2] , bAvcBuf[3], pDevExt->VideoFormatIndex));
  318. return TRUE; // Success
  319. }
  320. }
  321. TRACE(TL_FCP_WARNING,("\'ST:%x; PlugSignal:FMT[%x %x %x %x]\n", Status, bAvcBuf[0], bAvcBuf[1], bAvcBuf[2] , bAvcBuf[3], pDevExt->VideoFormatIndex));
  322. //
  323. // If "recommended" unit input/output plug signal status command fails,
  324. // try "manadatory" input/output signal mode status command.
  325. // This command may failed some device if its tape is not playing for
  326. // output signal mode command.
  327. //
  328. Status =
  329. DVIssueAVCCommand(
  330. pDevExt,
  331. AVC_CTYPE_STATUS,
  332. DataFlow == KSPIN_DATAFLOW_OUT ? VCR_OUTPUT_SIGNAL_MODE : VCR_INPUT_SIGNAL_MODE,
  333. (PVOID) bAvcBuf
  334. );
  335. if(STATUS_SUCCESS == Status) {
  336. PKSPROPERTY_EXTXPORT_S pXPrtProperty;
  337. pXPrtProperty = (PKSPROPERTY_EXTXPORT_S) bAvcBuf;
  338. TRACE(TL_FCP_WARNING,("\'** MediaFormat: Retry %d mSec; ST:%x; SignalMode:%dL\n",
  339. (GET_MEDIA_FMT_MAX_RETRIES - lRetries) * DV_AVC_CMD_DELAY_DVCPRO, Status, pXPrtProperty->u.SignalMode - ED_BASE));
  340. switch(pXPrtProperty->u.SignalMode) {
  341. case ED_TRANSBASIC_SIGNAL_525_60_SD:
  342. pDevExt->VideoFormatIndex = FMT_IDX_SD_DVCR_NTSC;
  343. if(pStrmExt) {
  344. pStrmExt->cipQuad2[0] = FMT_DVCR; // 0x80
  345. if(pDevExt->bDVCPro)
  346. pStrmExt->cipQuad2[1] = FDF0_50_60_NTSC | FDF0_STYPE_SD_DVCPRO; // 0x78 = NTSC(0):STYPE(11110):RSV(00)
  347. else
  348. pStrmExt->cipQuad2[1] = FDF0_50_60_NTSC | FDF0_STYPE_SD_DVCR; // 0x00 = NTSC(0):STYPE(00000):RSV(00)
  349. }
  350. break;
  351. case ED_TRANSBASIC_SIGNAL_625_50_SD:
  352. pDevExt->VideoFormatIndex = FMT_IDX_SD_DVCR_PAL;
  353. if(pStrmExt) {
  354. pStrmExt->cipQuad2[0] = FMT_DVCR; // 0x80
  355. if(pDevExt->bDVCPro)
  356. pStrmExt->cipQuad2[1] = FDF0_50_60_PAL | FDF0_STYPE_SD_DVCPRO; // 0xf8 = PAL(1):STYPE(11110):RSV(00)
  357. else
  358. pStrmExt->cipQuad2[1] = FDF0_50_60_PAL | FDF0_STYPE_SD_DVCR; // 0x80 = PAL(1):STYPE(00000):RSV(00)
  359. }
  360. break;
  361. #ifdef MSDV_SUPPORT_SDL_DVCR
  362. case ED_TRANSBASIC_SIGNAL_525_60_SDL:
  363. pDevExt->VideoFormatIndex = FMT_IDX_SDL_DVCR_NTSC;
  364. if(pStrmExt) {
  365. pStrmExt->cipQuad2[0] = FMT_DVCR; // 0x80
  366. pStrmExt->cipQuad2[1] = FDF0_50_60_NTSC | FDF0_STYPE_SDL_DVCR;
  367. }
  368. break;
  369. case ED_TRANSBASIC_SIGNAL_625_50_SDL:
  370. pDevExt->VideoFormatIndex = FMT_IDX_SDL_DVCR_PAL;
  371. if(pStrmExt) {
  372. pStrmExt->cipQuad2[0] = FMT_DVCR; // 0x80
  373. pStrmExt->cipQuad2[1] = FDF0_50_60_PAL | FDF0_STYPE_SDL_DVCR;
  374. }
  375. break;
  376. #endif
  377. default:
  378. TRACE(TL_FCP_ERROR,("\'Unsupported SignalMode:%dL", pXPrtProperty->u.SignalMode - ED_BASE));
  379. ASSERT(FALSE && "Unsupported IoSignal! Refuse to load.");
  380. return FALSE;
  381. break;
  382. }
  383. }
  384. // WORKITEM Sony HW CODEC does not response to any AVC command.
  385. // We are making an exception here to load it.
  386. if(Status == STATUS_TIMEOUT) {
  387. Status = STATUS_SUCCESS;
  388. }
  389. // We must know the signal format!! If this failed, the driver will either:
  390. // fail to load, or fail to open an stream
  391. ASSERT(Status == STATUS_SUCCESS && "Failed to get media signal format!\n");
  392. #if DBG
  393. if(pStrmExt) {
  394. // Note: bAvcBuf[0] is operand[1] == 10:fmt
  395. TRACE(TL_FCP_WARNING,("\'** MediaFormat: St:%x; idx:%d; CIP:[FMT:%.2x(%s); FDF:[%.2x(%s,%s):SYT]\n",
  396. Status,
  397. pDevExt->VideoFormatIndex,
  398. pStrmExt->cipQuad2[0],
  399. pStrmExt->cipQuad2[0] == FMT_DVCR ? "DVCR" : pStrmExt->cipQuad2[0] == FMT_MPEG ? "MPEG" : "Fmt:???",
  400. pStrmExt->cipQuad2[1],
  401. (pStrmExt->cipQuad2[1] & FDF0_50_60_MASK) == FDF0_50_60_PAL ? "PAL" : "NTSC",
  402. (pStrmExt->cipQuad2[1] & FDF0_STYPE_MASK) == FDF0_STYPE_SD_DVCR ? "SD" : \
  403. (pStrmExt->cipQuad2[1] & FDF0_STYPE_MASK) == FDF0_STYPE_SDL_DVCR ? "SDL" : \
  404. (pStrmExt->cipQuad2[1] & FDF0_STYPE_MASK) == FDF0_STYPE_HD_DVCR ? "HD" : \
  405. (pStrmExt->cipQuad2[1] & FDF0_STYPE_MASK) == FDF0_STYPE_SD_DVCPRO ? "DVCPRO" : "DV:????"
  406. ));
  407. } else
  408. TRACE(TL_FCP_WARNING|TL_CIP_WARNING,("\'** MediaFormat: St:%x; use idx:%d\n", Status, pDevExt->VideoFormatIndex));
  409. #endif
  410. return STATUS_SUCCESS == Status;
  411. }
  412. BOOL
  413. DVCmpGUIDsAndFormatSize(
  414. IN PKSDATARANGE pDataRange1,
  415. IN PKSDATARANGE pDataRange2,
  416. IN BOOL fCompareSubformat,
  417. IN BOOL fCompareFormatSize
  418. )
  419. /*++
  420. Routine Description:
  421. Checks for a match on the three GUIDs and FormatSize
  422. Arguments:
  423. IN pDataRange1
  424. IN pDataRange2
  425. Return Value:
  426. TRUE if all elements match
  427. FALSE if any are different
  428. --*/
  429. {
  430. return (
  431. IsEqualGUID (
  432. &pDataRange1->MajorFormat,
  433. &pDataRange2->MajorFormat) &&
  434. (fCompareSubformat ?
  435. IsEqualGUID (
  436. &pDataRange1->SubFormat,
  437. &pDataRange2->SubFormat) : TRUE) &&
  438. IsEqualGUID (
  439. &pDataRange1->Specifier,
  440. &pDataRange2->Specifier) &&
  441. (fCompareFormatSize ?
  442. (pDataRange1->FormatSize == pDataRange2->FormatSize) : TRUE ));
  443. }
  444. NTSTATUS
  445. DvAllocatePCResource(
  446. IN KSPIN_DATAFLOW DataFlow,
  447. IN PSTREAMEX pStrmExt // Note that pStrmExt can be NULL!
  448. )
  449. {
  450. PSRB_DATA_PACKET pSrbDataPacket;
  451. PDVCR_EXTENSION pDevExt;
  452. ULONG i, j;
  453. PAGED_CODE();
  454. //
  455. // Pre-allcoate PC resource
  456. //
  457. pDevExt = pStrmExt->pDevExt;
  458. for(i=0; i < (DataFlow == KSPIN_DATAFLOW_OUT ? \
  459. DVFormatInfoTable[pDevExt->VideoFormatIndex].ulNumOfRcvBuffers : \
  460. DVFormatInfoTable[pDevExt->VideoFormatIndex].ulNumOfXmtBuffers); i++) {
  461. if(!(pSrbDataPacket = ExAllocatePool(NonPagedPool, sizeof(SRB_DATA_PACKET)))) {
  462. for(j = 0; j < i; j++) {
  463. pSrbDataPacket = (PSRB_DATA_PACKET) \
  464. RemoveHeadList(&pStrmExt->DataDetachedListHead); pStrmExt->cntDataDetached--;
  465. ExFreePool(pSrbDataPacket->Frame); pSrbDataPacket->Frame = NULL;
  466. IoFreeIrp(pSrbDataPacket->pIrp); pSrbDataPacket->pIrp = NULL;
  467. ExFreePool(pSrbDataPacket); pSrbDataPacket = NULL;
  468. ASSERT(pStrmExt->cntDataDetached >= 0);
  469. return STATUS_NO_MEMORY;
  470. }
  471. }
  472. RtlZeroMemory(pSrbDataPacket, sizeof(SRB_DATA_PACKET));
  473. pSrbDataPacket->State = DE_IRP_SRB_COMPLETED; // Initial state.
  474. if(!(pSrbDataPacket->Frame = ExAllocatePool(NonPagedPool, sizeof(CIP_FRAME)))) {
  475. ExFreePool(pSrbDataPacket); pSrbDataPacket = NULL;
  476. for(j = 0; j < i; j++) {
  477. pSrbDataPacket = (PSRB_DATA_PACKET) \
  478. RemoveHeadList(&pStrmExt->DataDetachedListHead); pStrmExt->cntDataDetached--;
  479. ExFreePool(pSrbDataPacket->Frame); pSrbDataPacket->Frame = NULL;
  480. IoFreeIrp(pSrbDataPacket->pIrp); pSrbDataPacket->pIrp = NULL;
  481. ExFreePool(pSrbDataPacket); pSrbDataPacket = NULL;
  482. return STATUS_NO_MEMORY;
  483. }
  484. }
  485. if(!(pSrbDataPacket->pIrp = IoAllocateIrp(pDevExt->pBusDeviceObject->StackSize, FALSE))) {
  486. ExFreePool(pSrbDataPacket->Frame); pSrbDataPacket->Frame = NULL;
  487. ExFreePool(pSrbDataPacket); pSrbDataPacket = NULL;
  488. for(j = 0; j < i; j++) {
  489. pSrbDataPacket = (PSRB_DATA_PACKET) \
  490. RemoveHeadList(&pStrmExt->DataDetachedListHead); pStrmExt->cntDataDetached--;
  491. ExFreePool(pSrbDataPacket->Frame); pSrbDataPacket->Frame = NULL;
  492. IoFreeIrp(pSrbDataPacket->pIrp); pSrbDataPacket->pIrp = NULL;
  493. ExFreePool(pSrbDataPacket); pSrbDataPacket = NULL;
  494. return STATUS_INSUFFICIENT_RESOURCES;
  495. }
  496. }
  497. InsertTailList(&pStrmExt->DataDetachedListHead, &pSrbDataPacket->ListEntry); pStrmExt->cntDataDetached++;
  498. }
  499. return STATUS_SUCCESS;
  500. }
  501. NTSTATUS
  502. DvFreePCResource(
  503. IN PSTREAMEX pStrmExt
  504. )
  505. {
  506. PSRB_DATA_PACKET pSrbDataPacket;
  507. KIRQL oldIrql;
  508. PAGED_CODE();
  509. KeAcquireSpinLock(pStrmExt->DataListLock, &oldIrql);
  510. while(!IsListEmpty(&pStrmExt->DataDetachedListHead)) {
  511. pSrbDataPacket = (PSRB_DATA_PACKET)
  512. RemoveHeadList(
  513. &pStrmExt->DataDetachedListHead
  514. );
  515. ExFreePool(pSrbDataPacket->Frame);
  516. pSrbDataPacket->Frame = NULL;
  517. IoFreeIrp(pSrbDataPacket->pIrp);
  518. pSrbDataPacket->pIrp = NULL;
  519. ExFreePool(pSrbDataPacket);
  520. pStrmExt->cntDataDetached--;
  521. ASSERT(pStrmExt->cntDataDetached >= 0);
  522. }
  523. ASSERT(pStrmExt->cntDataDetached == 0);
  524. KeReleaseSpinLock(pStrmExt->DataListLock, oldIrql);
  525. return STATUS_SUCCESS;
  526. }
  527. NTSTATUS
  528. DVGetUnitCapabilities(
  529. IN PDVCR_EXTENSION pDevExt
  530. )
  531. /*++
  532. Routine Description:
  533. Get the targe device's unit capabilities
  534. Arguments:
  535. Return Value:
  536. STATUS_SUCCESS
  537. STATUS_INSUFFICIENT_RESOURCES
  538. status return from 61883.
  539. --*/
  540. {
  541. PIRP pIrp;
  542. PAV_61883_REQUEST pAVReq;
  543. NTSTATUS Status = STATUS_SUCCESS;
  544. GET_UNIT_IDS * pUnitIds;
  545. GET_UNIT_CAPABILITIES * pUnitCaps;
  546. PAGED_CODE();
  547. if(!(pIrp = IoAllocateIrp(pDevExt->pBusDeviceObject->StackSize, FALSE)))
  548. return STATUS_INSUFFICIENT_RESOURCES;
  549. if(!(pAVReq = (AV_61883_REQUEST *) ExAllocatePool(NonPagedPool, sizeof(AV_61883_REQUEST)))) {
  550. IoFreeIrp(pIrp); pIrp = NULL;
  551. return STATUS_INSUFFICIENT_RESOURCES;
  552. }
  553. //
  554. // Query device's capability
  555. //
  556. if(!(pUnitIds = (GET_UNIT_IDS *) ExAllocatePool(NonPagedPool, sizeof(GET_UNIT_IDS)))) {
  557. IoFreeIrp(pIrp); pIrp = NULL;
  558. ExFreePool(pAVReq); pAVReq = NULL;
  559. return STATUS_INSUFFICIENT_RESOURCES;
  560. }
  561. //
  562. // Query device's capability
  563. //
  564. if(!(pUnitCaps = (GET_UNIT_CAPABILITIES *) ExAllocatePool(NonPagedPool, sizeof(GET_UNIT_CAPABILITIES)))) {
  565. IoFreeIrp(pIrp); pIrp = NULL;
  566. ExFreePool(pAVReq); pAVReq = NULL;
  567. ExFreePool(pUnitIds); pUnitIds = NULL;
  568. return STATUS_INSUFFICIENT_RESOURCES;
  569. }
  570. RtlZeroMemory(pAVReq, sizeof(AV_61883_REQUEST));
  571. INIT_61883_HEADER(pAVReq, Av61883_GetUnitInfo);
  572. pAVReq->GetUnitInfo.nLevel = GET_UNIT_INFO_IDS;
  573. RtlZeroMemory(pUnitIds, sizeof(GET_UNIT_IDS));
  574. pAVReq->GetUnitInfo.Information = (PVOID) pUnitIds;
  575. Status =
  576. DVSubmitIrpSynch(
  577. pDevExt,
  578. pIrp,
  579. pAVReq
  580. );
  581. if(!NT_SUCCESS(Status)) {
  582. TRACE(TL_61883_ERROR,("\'Av61883_GetUnitInfo (IDS) Failed = 0x%x\n", Status));
  583. pDevExt->UniqueID.QuadPart = 0;
  584. pDevExt->ulVendorID = 0;
  585. pDevExt->ulModelID = 0;
  586. }
  587. else {
  588. pDevExt->UniqueID = pUnitIds->UniqueID;
  589. pDevExt->ulVendorID = pUnitIds->VendorID;
  590. pDevExt->ulModelID = pUnitIds->ModelID;
  591. TRACE(TL_61883_WARNING,("\'UniqueId:(%x:%x); VID:%x; MID:%x\n",
  592. pDevExt->UniqueID.LowPart, pDevExt->UniqueID.HighPart,
  593. pUnitIds->VendorID,
  594. pUnitIds->ModelID
  595. ));
  596. }
  597. RtlZeroMemory(pAVReq, sizeof(AV_61883_REQUEST));
  598. INIT_61883_HEADER(pAVReq, Av61883_GetUnitInfo);
  599. pAVReq->GetUnitInfo.nLevel = GET_UNIT_INFO_CAPABILITIES;
  600. RtlZeroMemory(pUnitCaps, sizeof(GET_UNIT_CAPABILITIES));
  601. pAVReq->GetUnitInfo.Information = (PVOID) pUnitCaps;
  602. Status =
  603. DVSubmitIrpSynch(
  604. pDevExt,
  605. pIrp,
  606. pAVReq
  607. );
  608. if(!NT_SUCCESS(Status)) {
  609. TRACE(TL_61883_ERROR,("Av61883_GetUnitInfo (CAPABILITIES) Failed = 0x%x\n", Status));
  610. pDevExt->MaxDataRate = 0;
  611. pDevExt->NumOutputPlugs = 0;
  612. pDevExt->NumInputPlugs = 0;
  613. pDevExt->HardwareFlags = 0;
  614. }
  615. else {
  616. pDevExt->MaxDataRate = pUnitCaps->MaxDataRate;
  617. pDevExt->NumOutputPlugs = pUnitCaps->NumOutputPlugs;
  618. pDevExt->NumInputPlugs = pUnitCaps->NumInputPlugs;
  619. pDevExt->HardwareFlags = pUnitCaps->HardwareFlags;
  620. }
  621. #if DBG
  622. if( pDevExt->NumOutputPlugs == 0
  623. || pDevExt->NumInputPlugs == 0)
  624. {
  625. TRACE(TL_PNP_WARNING|TL_61883_WARNING,("\'Watch out! NumOPlug:%d; NumIPlug:%d\n", pDevExt->NumOutputPlugs, pDevExt->NumInputPlugs));
  626. }
  627. #endif
  628. TRACE(TL_61883_WARNING,("\'UnitCaps:%s OutP:%d; InP:%d; MDRt:%s; HWFlg:%x; CtsF:%x; HwF:%x\n",
  629. (pUnitCaps->HardwareFlags & AV_HOST_DMA_DOUBLE_BUFFERING_ENABLED) ? "*PAE*;":"",
  630. pUnitCaps->NumOutputPlugs,
  631. pUnitCaps->NumInputPlugs,
  632. pUnitCaps->MaxDataRate == 0 ? "S100": pUnitCaps->MaxDataRate == 1? "S200" : "S400 or +",
  633. pUnitCaps->HardwareFlags,
  634. pUnitCaps->CTSFlags,
  635. pUnitCaps->HardwareFlags
  636. ));
  637. ExFreePool(pUnitIds); pUnitIds = NULL;
  638. ExFreePool(pUnitCaps); pUnitCaps = NULL;
  639. IoFreeIrp(pIrp); pIrp = NULL;
  640. ExFreePool(pAVReq); pAVReq = NULL;
  641. return Status;
  642. }
  643. NTSTATUS
  644. DVGetDVPlug(
  645. IN PDVCR_EXTENSION pDevExt,
  646. IN CMP_PLUG_TYPE PlugType,
  647. IN ULONG PlugNum,
  648. OUT HANDLE *pPlugHandle
  649. )
  650. /*++
  651. Routine Description:
  652. Get the targe device's plug handle
  653. Arguments:
  654. Return Value:
  655. STATUS_SUCCESS
  656. STATUS_INSUFFICIENT_RESOURCES
  657. status return from 61883.
  658. --*/
  659. {
  660. PIRP pIrp;
  661. PAV_61883_REQUEST pAVReq;
  662. NTSTATUS Status = STATUS_SUCCESS;
  663. PAGED_CODE();
  664. if(!(pIrp = IoAllocateIrp(pDevExt->pBusDeviceObject->StackSize, FALSE)))
  665. return STATUS_INSUFFICIENT_RESOURCES;
  666. if(!(pAVReq = (AV_61883_REQUEST *) ExAllocatePool(NonPagedPool, sizeof(AV_61883_REQUEST)))) {
  667. IoFreeIrp(pIrp); pIrp = NULL;
  668. return STATUS_INSUFFICIENT_RESOURCES;
  669. }
  670. RtlZeroMemory(pAVReq, sizeof(AV_61883_REQUEST));
  671. INIT_61883_HEADER(pAVReq, Av61883_GetPlugHandle);
  672. pAVReq->GetPlugHandle.PlugNum = PlugNum;
  673. pAVReq->GetPlugHandle.hPlug = 0;
  674. pAVReq->GetPlugHandle.Type = PlugType;
  675. if(NT_SUCCESS(
  676. Status = DVSubmitIrpSynch(
  677. pDevExt,
  678. pIrp,
  679. pAVReq
  680. ))) {
  681. *pPlugHandle = pAVReq->GetPlugHandle.hPlug;
  682. TRACE(TL_61883_WARNING,("\'Created h%sPlugDV[%d]=%x\n", PlugType == CMP_PlugIn ? "I" : "O", PlugNum, *pPlugHandle));
  683. } else {
  684. TRACE(TL_61883_ERROR,("\'Created h%sPlugDV[%d] failed; Status:%x\n", PlugType == CMP_PlugIn ? "I" : "O", PlugNum, Status));
  685. Status = STATUS_INSUFFICIENT_RESOURCES;
  686. }
  687. IoFreeIrp(pIrp); pIrp = NULL;
  688. ExFreePool(pAVReq); pAVReq = NULL;
  689. return Status;
  690. }
  691. #ifdef NT51_61883
  692. NTSTATUS
  693. DVSetAddressRangeExclusive(
  694. IN PDVCR_EXTENSION pDevExt
  695. )
  696. /*++
  697. Routine Description:
  698. Set this mode so that our local plug will be created in address exclusive mode.
  699. Arguments:
  700. Return Value:
  701. STATUS_SUCCESS
  702. STATUS_INSUFFICIENT_RESOURCES
  703. --*/
  704. {
  705. PIRP pIrp;
  706. PAV_61883_REQUEST pAVReq;
  707. NTSTATUS Status = STATUS_SUCCESS;
  708. SET_CMP_ADDRESS_TYPE SetCmpAddress;
  709. PAGED_CODE();
  710. if(!(pIrp = IoAllocateIrp(pDevExt->pBusDeviceObject->StackSize, FALSE)))
  711. return STATUS_INSUFFICIENT_RESOURCES;
  712. if(!(pAVReq = (AV_61883_REQUEST *) ExAllocatePool(NonPagedPool, sizeof(AV_61883_REQUEST)))) {
  713. IoFreeIrp(pIrp); pIrp = NULL;
  714. return STATUS_INSUFFICIENT_RESOURCES;
  715. }
  716. RtlZeroMemory(pAVReq, sizeof(AV_61883_REQUEST));
  717. INIT_61883_HEADER(pAVReq, Av61883_SetUnitInfo);
  718. pAVReq->SetUnitInfo.nLevel = SET_CMP_ADDRESS_RANGE_TYPE;
  719. SetCmpAddress.Type = CMP_ADDRESS_TYPE_EXCLUSIVE;
  720. pAVReq->SetUnitInfo.Information = (PVOID) &SetCmpAddress;
  721. if(!NT_SUCCESS(
  722. Status = DVSubmitIrpSynch(
  723. pDevExt,
  724. pIrp,
  725. pAVReq
  726. ))) {
  727. TRACE(TL_61883_ERROR,("\'SET_CMP_ADDRESS_RANGE_TYPE Failed:%x\n", Status));
  728. } else {
  729. TRACE(TL_61883_TRACE,("\'SET_CMP_ADDRESS_RANGE_TYPE suceeded.\n"));
  730. }
  731. IoFreeIrp(pIrp); pIrp = NULL;
  732. ExFreePool(pAVReq); pAVReq = NULL;
  733. return Status;
  734. }
  735. NTSTATUS
  736. DVGetUnitIsochParam(
  737. IN PDVCR_EXTENSION pDevExt,
  738. OUT UNIT_ISOCH_PARAMS * pUnitIoschParams
  739. )
  740. /*++
  741. Routine Description:
  742. Create an enumated local PC PCR
  743. Arguments:
  744. Return Value:
  745. STATUS_SUCCESS
  746. STATUS_INSUFFICIENT_RESOURCES
  747. --*/
  748. {
  749. PIRP pIrp;
  750. PAV_61883_REQUEST pAVReq;
  751. NTSTATUS Status = STATUS_SUCCESS;
  752. PAGED_CODE();
  753. if(!(pIrp = IoAllocateIrp(pDevExt->pBusDeviceObject->StackSize, FALSE)))
  754. return STATUS_INSUFFICIENT_RESOURCES;
  755. if(!(pAVReq = (AV_61883_REQUEST *) ExAllocatePool(NonPagedPool, sizeof(AV_61883_REQUEST)))) {
  756. IoFreeIrp(pIrp); pIrp = NULL;
  757. return STATUS_INSUFFICIENT_RESOURCES;
  758. }
  759. //
  760. // Get Unit isoch parameters
  761. //
  762. RtlZeroMemory(pAVReq, sizeof(AV_61883_REQUEST));
  763. INIT_61883_HEADER(pAVReq, Av61883_GetUnitInfo);
  764. pAVReq->GetUnitInfo.nLevel = GET_UNIT_INFO_ISOCH_PARAMS;
  765. RtlZeroMemory(pUnitIoschParams, sizeof(UNIT_ISOCH_PARAMS));
  766. pAVReq->GetUnitInfo.Information = (PVOID) pUnitIoschParams;
  767. Status =
  768. DVSubmitIrpSynch(
  769. pDevExt,
  770. pIrp,
  771. pAVReq
  772. );
  773. if(!NT_SUCCESS(Status)) {
  774. TRACE(TL_61883_ERROR,("Av61883_GetUnitInfo Failed:%x\n", Status));
  775. Status = STATUS_UNSUCCESSFUL; // Cannot stream without this!
  776. }
  777. TRACE(TL_61883_WARNING,("\'IsochParam: RxPkt:%d, RxDesc:%d; XmPkt:%d, XmDesc:%d\n",
  778. pUnitIoschParams->RX_NumPackets,
  779. pUnitIoschParams->RX_NumDescriptors,
  780. pUnitIoschParams->TX_NumPackets,
  781. pUnitIoschParams->TX_NumDescriptors
  782. ));
  783. IoFreeIrp(pIrp); pIrp = NULL;
  784. ExFreePool(pAVReq); pAVReq = NULL;
  785. return Status;
  786. }
  787. NTSTATUS
  788. DVSetUnitIsochParams(
  789. IN PDVCR_EXTENSION pDevExt,
  790. IN UNIT_ISOCH_PARAMS *pUnitIoschParams
  791. )
  792. /*++
  793. Routine Description:
  794. Set AV unit's isoch parameters via 61883.
  795. Arguments:
  796. Return Value:
  797. STATUS_SUCCESS
  798. STATUS_INSUFFICIENT_RESOURCES
  799. --*/
  800. {
  801. PIRP pIrp;
  802. PAV_61883_REQUEST pAVReq;
  803. NTSTATUS Status = STATUS_SUCCESS;
  804. PAGED_CODE();
  805. if(!(pIrp = IoAllocateIrp(pDevExt->pBusDeviceObject->StackSize, FALSE)))
  806. return STATUS_INSUFFICIENT_RESOURCES;
  807. if(!(pAVReq = (AV_61883_REQUEST *) ExAllocatePool(NonPagedPool, sizeof(AV_61883_REQUEST)))) {
  808. IoFreeIrp(pIrp); pIrp = NULL;
  809. return STATUS_INSUFFICIENT_RESOURCES;
  810. }
  811. RtlZeroMemory(pAVReq, sizeof(AV_61883_REQUEST));
  812. INIT_61883_HEADER(pAVReq, Av61883_SetUnitInfo);
  813. pAVReq->SetUnitInfo.nLevel = SET_UNIT_INFO_ISOCH_PARAMS;
  814. pAVReq->SetUnitInfo.Information = (PVOID) pUnitIoschParams;
  815. if(!NT_SUCCESS(
  816. Status = DVSubmitIrpSynch(
  817. pDevExt,
  818. pIrp,
  819. pAVReq
  820. ))) {
  821. TRACE(TL_61883_ERROR,("DVSetUnitIsochParams: Av61883_SetUnitInfo Failed:%x\n", Status));
  822. }
  823. TRACE(TL_61883_WARNING,("\'UnitIsochParams: Set: RxPkt:%d, RxDesc:%d; XmPkt:%d, XmDesc:%d\n",
  824. pUnitIoschParams->RX_NumPackets,
  825. pUnitIoschParams->RX_NumDescriptors,
  826. pUnitIoschParams->TX_NumPackets,
  827. pUnitIoschParams->TX_NumDescriptors
  828. ));
  829. IoFreeIrp(pIrp); pIrp = NULL;
  830. ExFreePool(pAVReq); pAVReq = NULL;
  831. return Status;
  832. }
  833. NTSTATUS
  834. DVMakeP2PConnection(
  835. IN PDVCR_EXTENSION pDevExt,
  836. IN KSPIN_DATAFLOW DataFlow,
  837. IN PSTREAMEX pStrmExt
  838. )
  839. /*++
  840. Routine Description:
  841. Make a point to point connection .
  842. Arguments:
  843. Return Value:
  844. STATUS_SUCCESS
  845. STATUS_INSUFFICIENT_RESOURCES
  846. --*/
  847. {
  848. PIRP pIrp;
  849. PAV_61883_REQUEST pAVReq;
  850. NTSTATUS Status = STATUS_SUCCESS;
  851. PAGED_CODE();
  852. if(!(pIrp = IoAllocateIrp(pDevExt->pBusDeviceObject->StackSize, FALSE)))
  853. return STATUS_INSUFFICIENT_RESOURCES;
  854. if(!(pAVReq = (AV_61883_REQUEST *) ExAllocatePool(NonPagedPool, sizeof(AV_61883_REQUEST)))) {
  855. IoFreeIrp(pIrp); pIrp = NULL;
  856. return STATUS_INSUFFICIENT_RESOURCES;
  857. }
  858. RtlZeroMemory(pAVReq, sizeof(AV_61883_REQUEST));
  859. INIT_61883_HEADER(pAVReq, Av61883_Connect);
  860. pAVReq->Connect.Type = CMP_PointToPoint; // !!
  861. pAVReq->Connect.hOutputPlug = pStrmExt->hOutputPcr;
  862. pAVReq->Connect.hInputPlug = pStrmExt->hInputPcr;
  863. // see which way we the data will flow...
  864. if(DataFlow == KSPIN_DATAFLOW_OUT) {
  865. // Other parameters !!
  866. } else {
  867. pAVReq->Connect.Format.FMT = pStrmExt->cipQuad2[0]; // From AV/C in/outpug plug signal format status cmd
  868. // 00 for NTSC, 80 for PAL; set the 50/60 bit
  869. pAVReq->Connect.Format.FDF_hi = pStrmExt->cipQuad2[1]; // From AV/C in/outpug plug signal format status cmd
  870. //
  871. // 16bit SYT field = 4BitCycleCount:12BitCycleOffset;
  872. // Will be set by 61883
  873. //
  874. pAVReq->Connect.Format.FDF_mid = 0;
  875. pAVReq->Connect.Format.FDF_lo = 0;
  876. //
  877. // Constants depend on the A/V data format (in or out plug format)
  878. //
  879. pAVReq->Connect.Format.bHeader = (BOOL) DVFormatInfoTable[pDevExt->VideoFormatIndex].SrcPktHeader;
  880. pAVReq->Connect.Format.Padding = (UCHAR) DVFormatInfoTable[pDevExt->VideoFormatIndex].QuadPadCount;
  881. pAVReq->Connect.Format.BlockSize = (UCHAR) DVFormatInfoTable[pDevExt->VideoFormatIndex].DataBlockSize;
  882. pAVReq->Connect.Format.Fraction = (UCHAR) DVFormatInfoTable[pDevExt->VideoFormatIndex].FractionNumber;
  883. }
  884. // Set this so that 61883 can know it is NTSC or PAL;
  885. // For read: It is needed so 61883 can preallocate just-enough packets
  886. // so that data can return in a much regular interval.
  887. if( pDevExt->VideoFormatIndex == FMT_IDX_SD_DVCR_NTSC
  888. || pDevExt->VideoFormatIndex == FMT_IDX_SDL_DVCR_NTSC)
  889. pAVReq->Connect.Format.BlockPeriod = 133466800; // nano-sec
  890. else
  891. pAVReq->Connect.Format.BlockPeriod = 133333333; // nano-sec
  892. TRACE(TL_61883_WARNING,("\'cipQuad2[0]:%x, cipQuad2[1]:%x, cipQuad2[2]:%x, cipQuad2[3]:%x\n",
  893. pStrmExt->cipQuad2[0],
  894. pStrmExt->cipQuad2[1],
  895. pStrmExt->cipQuad2[2],
  896. pStrmExt->cipQuad2[3]
  897. ));
  898. TRACE(TL_61883_WARNING,("\'Connect:oPcr:%x->iPcr:%x; cipQuad2[%.2x:%.2x:%.2x:%.2x]\n",
  899. pAVReq->Connect.hOutputPlug,
  900. pAVReq->Connect.hInputPlug,
  901. pAVReq->Connect.Format.FMT,
  902. pAVReq->Connect.Format.FDF_hi,
  903. pAVReq->Connect.Format.FDF_mid,
  904. pAVReq->Connect.Format.FDF_lo
  905. ));
  906. TRACE(TL_61883_WARNING,("\' BlkSz %d; SrcPkt %d; AvgTm %d, BlkPrd %d\n",
  907. pAVReq->Connect.Format.BlockSize,
  908. DVFormatInfoTable[pDevExt->VideoFormatIndex].ulSrcPackets,
  909. DVFormatInfoTable[pDevExt->VideoFormatIndex].ulAvgTimePerFrame,
  910. (DWORD) pAVReq->Connect.Format.BlockPeriod
  911. ));
  912. if(NT_SUCCESS(
  913. Status = DVSubmitIrpSynch(
  914. pDevExt,
  915. pIrp,
  916. pAVReq
  917. ))) {
  918. TRACE(TL_61883_WARNING,("\'hConnect:%x\n", pAVReq->Connect.hConnect));
  919. ASSERT(pAVReq->Connect.hConnect != NULL);
  920. pStrmExt->hConnect = pAVReq->Connect.hConnect;
  921. }
  922. else {
  923. TRACE(TL_61883_ERROR,("Av61883_Connect Failed; Status:%x\n", Status));
  924. ASSERT(!NT_SUCCESS(Status) && "DisConnect failed");
  925. pStrmExt->hConnect = NULL;
  926. }
  927. IoFreeIrp(pIrp); pIrp = NULL;
  928. ExFreePool(pAVReq); pAVReq = NULL;
  929. return Status;
  930. }
  931. NTSTATUS
  932. DVCreateLocalPlug(
  933. IN PDVCR_EXTENSION pDevExt,
  934. IN CMP_PLUG_TYPE PlugType,
  935. IN ULONG PlugNum,
  936. OUT HANDLE *pPlugHandle
  937. )
  938. /*++
  939. Routine Description:
  940. Create an enumated local PC PCR
  941. Arguments:
  942. Return Value:
  943. STATUS_SUCCESS
  944. STATUS_INSUFFICIENT_RESOURCES
  945. --*/
  946. {
  947. PIRP pIrp;
  948. PAV_61883_REQUEST pAVReq;
  949. NTSTATUS Status = STATUS_SUCCESS;
  950. PAGED_CODE();
  951. if(!(pIrp = IoAllocateIrp(pDevExt->pBusDeviceObject->StackSize, FALSE)))
  952. return STATUS_INSUFFICIENT_RESOURCES;
  953. if(!(pAVReq = (AV_61883_REQUEST *) ExAllocatePool(NonPagedPool, sizeof(AV_61883_REQUEST)))) {
  954. IoFreeIrp(pIrp); pIrp = NULL;
  955. return STATUS_INSUFFICIENT_RESOURCES;
  956. }
  957. // Need to correctly update Overhead_ID and payload fields of PC's own oPCR
  958. RtlZeroMemory(pAVReq, sizeof(AV_61883_REQUEST));
  959. INIT_61883_HEADER(pAVReq, Av61883_CreatePlug);
  960. pAVReq->CreatePlug.PlugNum = PlugNum;
  961. pAVReq->CreatePlug.hPlug = NULL;
  962. pAVReq->CreatePlug.Context = NULL;
  963. pAVReq->CreatePlug.pfnNotify = NULL;
  964. pAVReq->CreatePlug.PlugType = PlugType;
  965. //
  966. // Initialize oPCR values to default values using SDDV signal mode
  967. // with speed of 100Mbps data rate
  968. //
  969. pAVReq->CreatePlug.Pcr.oPCR.OnLine = 0; // We are not online so we cannot be programmed.
  970. pAVReq->CreatePlug.Pcr.oPCR.BCCCounter = 0;
  971. pAVReq->CreatePlug.Pcr.oPCR.PPCCounter = 0;
  972. pAVReq->CreatePlug.Pcr.oPCR.Channel = 0;
  973. pAVReq->CreatePlug.Pcr.oPCR.DataRate = CMP_SPEED_S100;
  974. pAVReq->CreatePlug.Pcr.oPCR.OverheadID = PCR_OVERHEAD_ID_SDDV;
  975. pAVReq->CreatePlug.Pcr.oPCR.Payload = PCR_PAYLOAD_SDDV;
  976. if(NT_SUCCESS(
  977. Status = DVSubmitIrpSynch(
  978. pDevExt,
  979. pIrp,
  980. pAVReq
  981. ))) {
  982. *pPlugHandle = pAVReq->CreatePlug.hPlug;
  983. TRACE(TL_61883_WARNING,("\'Created h%sPlugPC[%d]=%x\n", PlugType == CMP_PlugIn ? "I" : "O", PlugNum, *pPlugHandle));
  984. } else {
  985. TRACE(TL_61883_ERROR,("\'Created h%sPlugPC[%d] failed; Status:%x\n", pAVReq->CreatePlug.PlugType == CMP_PlugIn ? "I" : "O", PlugNum, Status));
  986. Status = STATUS_INSUFFICIENT_RESOURCES; // No plug!
  987. }
  988. IoFreeIrp(pIrp); pIrp = NULL;
  989. ExFreePool(pAVReq); pAVReq = NULL;
  990. return Status;
  991. }
  992. NTSTATUS
  993. DVDeleteLocalPlug(
  994. IN PDVCR_EXTENSION pDevExt,
  995. IN HANDLE PlugHandle
  996. )
  997. /*++
  998. Routine Description:
  999. Delete an enumated local PC PCR
  1000. Arguments:
  1001. Return Value:
  1002. Nothing
  1003. --*/
  1004. {
  1005. PIRP pIrp;
  1006. PAV_61883_REQUEST pAVReq;
  1007. NTSTATUS Status = STATUS_SUCCESS;
  1008. PAGED_CODE();
  1009. if(!(pIrp = IoAllocateIrp(pDevExt->pBusDeviceObject->StackSize, FALSE)))
  1010. return STATUS_INSUFFICIENT_RESOURCES;
  1011. if(!(pAVReq = (AV_61883_REQUEST *) ExAllocatePool(NonPagedPool, sizeof(AV_61883_REQUEST)))) {
  1012. IoFreeIrp(pIrp); pIrp = NULL;
  1013. return STATUS_INSUFFICIENT_RESOURCES;
  1014. }
  1015. // Delete our local oPCR
  1016. RtlZeroMemory(pAVReq, sizeof(AV_61883_REQUEST));
  1017. INIT_61883_HEADER(pAVReq, Av61883_DeletePlug);
  1018. pAVReq->DeletePlug.hPlug = PlugHandle;
  1019. Status =
  1020. DVSubmitIrpSynch(
  1021. pDevExt,
  1022. pIrp,
  1023. pAVReq
  1024. );
  1025. if(!NT_SUCCESS(Status)) {
  1026. TRACE(TL_61883_ERROR,("Av61883_DeletePlug Failed = 0x%x\n", Status));
  1027. // Do not care if this result in error.
  1028. } else {
  1029. TRACE(TL_61883_WARNING,("\'Av61883_DeletePlug: Deleted!\n", pDevExt->hOPcrPC));
  1030. }
  1031. IoFreeIrp(pIrp); pIrp = NULL;
  1032. ExFreePool(pAVReq); pAVReq = NULL;
  1033. return Status;
  1034. }
  1035. #endif
  1036. NTSTATUS
  1037. DVGetPlugState(
  1038. IN PDVCR_EXTENSION pDevExt,
  1039. IN PSTREAMEX pStrmExt,
  1040. IN PAV_61883_REQUEST pAVReq
  1041. )
  1042. /*++
  1043. Routine Description:
  1044. Ask 61883.sys for the plug state.
  1045. Arguments:
  1046. Return Value:
  1047. Nothing
  1048. --*/
  1049. {
  1050. PIRP pIrp;
  1051. NTSTATUS Status = STATUS_SUCCESS;
  1052. PAGED_CODE();
  1053. if(!(pIrp = IoAllocateIrp(pDevExt->pBusDeviceObject->StackSize, FALSE)))
  1054. return STATUS_INSUFFICIENT_RESOURCES;
  1055. //
  1056. // Query oPCR plug state
  1057. //
  1058. if(pStrmExt->hOutputPcr) {
  1059. RtlZeroMemory(pAVReq, sizeof(AV_61883_REQUEST));
  1060. INIT_61883_HEADER(pAVReq, Av61883_GetPlugState);
  1061. pAVReq->GetPlugState.hPlug = pStrmExt->hOutputPcr;
  1062. Status =
  1063. DVSubmitIrpSynch(
  1064. pDevExt,
  1065. pIrp,
  1066. pAVReq
  1067. );
  1068. if(!NT_SUCCESS(Status)) {
  1069. TRACE(TL_61883_ERROR,("Av61883_GetPlugState Failed %x\n", Status));
  1070. goto ExitGetState;
  1071. }
  1072. else {
  1073. TRACE(TL_61883_WARNING,("\'PlgState:(oPCR:%x): State %x; DRate %d; Payld %d; BCCnt %d; PPCnt %d\n",
  1074. pAVReq->GetPlugState.hPlug,
  1075. pAVReq->GetPlugState.State,
  1076. pAVReq->GetPlugState.DataRate,
  1077. pAVReq->GetPlugState.Payload,
  1078. pAVReq->GetPlugState.BC_Connections,
  1079. pAVReq->GetPlugState.PP_Connections
  1080. ));
  1081. }
  1082. }
  1083. //
  1084. // Query iPCR plug state
  1085. //
  1086. if(pStrmExt->hInputPcr) {
  1087. RtlZeroMemory(pAVReq, sizeof(AV_61883_REQUEST));
  1088. INIT_61883_HEADER(pAVReq, Av61883_GetPlugState);
  1089. pAVReq->GetPlugState.hPlug = pStrmExt->hInputPcr;
  1090. Status =
  1091. DVSubmitIrpSynch(
  1092. pDevExt,
  1093. pIrp,
  1094. pAVReq
  1095. );
  1096. if(!NT_SUCCESS(Status)) {
  1097. TRACE(TL_61883_ERROR,("Av61883_GetPlugState Failed %x\n", Status));
  1098. goto ExitGetState;
  1099. }
  1100. else {
  1101. TRACE(TL_61883_WARNING,("\'PlugState(iPCR:%x): State %x; DRate %d; Payld %d; BCCnt %d; PPCnt %d\n",
  1102. pAVReq->GetPlugState.hPlug,
  1103. pAVReq->GetPlugState.State,
  1104. pAVReq->GetPlugState.DataRate,
  1105. pAVReq->GetPlugState.Payload,
  1106. pAVReq->GetPlugState.BC_Connections,
  1107. pAVReq->GetPlugState.PP_Connections
  1108. ));
  1109. }
  1110. }
  1111. ExitGetState:
  1112. IoFreeIrp(pIrp);
  1113. return Status;
  1114. }
  1115. NTSTATUS
  1116. DVCreateAttachFrameThread(
  1117. PSTREAMEX pStrmExt
  1118. )
  1119. /*++
  1120. Routine Description:
  1121. Create a system thread for attaching data (for transmiut to DV only).
  1122. Arguments:
  1123. Return Value:
  1124. STATUS_SUCCESS or
  1125. return status from PsCreateSystemThread
  1126. --*/
  1127. {
  1128. NTSTATUS Status = STATUS_SUCCESS;
  1129. HANDLE hAttachFrameThread;
  1130. Status =
  1131. PsCreateSystemThread(
  1132. &hAttachFrameThread,
  1133. (ACCESS_MASK) 0,
  1134. NULL,
  1135. (HANDLE) 0,
  1136. NULL,
  1137. DVAttachFrameThread,
  1138. pStrmExt
  1139. );
  1140. if(!NT_SUCCESS(Status)) {
  1141. pStrmExt->bTerminateThread = TRUE;
  1142. TRACE(TL_CIP_ERROR|TL_FCP_ERROR,("\'PsCreateSystemThread() failed %x\n", Status));
  1143. ASSERT(NT_SUCCESS(Status));
  1144. }
  1145. else {
  1146. pStrmExt->bTerminateThread = FALSE; // Just started!
  1147. Status =
  1148. ObReferenceObjectByHandle(
  1149. hAttachFrameThread,
  1150. THREAD_ALL_ACCESS,
  1151. NULL,
  1152. KernelMode,
  1153. &pStrmExt->pAttachFrameThreadObject,
  1154. NULL
  1155. );
  1156. TRACE(TL_CIP_WARNING|TL_PNP_WARNING,("\'ObReferenceObjectByHandle() St %x; Obj %x\n", Status, pStrmExt->pAttachFrameThreadObject));
  1157. ZwClose(hAttachFrameThread);
  1158. // To signl end of an event
  1159. KeInitializeEvent(&pStrmExt->hThreadEndEvent, NotificationEvent, FALSE); // Non-signal
  1160. }
  1161. return Status;
  1162. }
  1163. NTSTATUS
  1164. DVConnect(
  1165. IN KSPIN_DATAFLOW ulDataFlow,
  1166. IN PDVCR_EXTENSION pDevExt,
  1167. IN PSTREAMEX pStrmExt,
  1168. IN PAV_61883_REQUEST pAVReq
  1169. )
  1170. /*++
  1171. Routine Description:
  1172. Ask 61883.sys to allocate isoch bandwidth and program PCR.
  1173. Arguments:
  1174. Return Value:
  1175. STATUS_SUCCESS
  1176. other Status from calling other routine.
  1177. --*/
  1178. {
  1179. NTSTATUS Status;
  1180. PAGED_CODE();
  1181. ASSERT(pStrmExt->hConnect == NULL);
  1182. //
  1183. // Do not reconnect. 61883 should handle all the necessary CMP reconnect.
  1184. //
  1185. if(pStrmExt->hConnect) {
  1186. return STATUS_SUCCESS;
  1187. }
  1188. #ifdef SUPPORT_NEW_AVC
  1189. //
  1190. // For Device to device connection, we only connect if we are the data producer (oPCR)
  1191. //
  1192. TRACE(TL_61883_WARNING,("\'[pStrmExt:%x]: %s PC (oPCR:%x, iPCR:%x); DV (oPCR:%x; iPCR:%x)\n",
  1193. pStrmExt,
  1194. ulDataFlow == KSPIN_DATAFLOW_OUT ? "OutPin" : "InPin",
  1195. pDevExt->hOPcrPC, 0,
  1196. pDevExt->hOPcrDV, pDevExt->hIPcrDV
  1197. ));
  1198. if(
  1199. pStrmExt->bDV2DVConnect &&
  1200. (pStrmExt->hOutputPcr != pDevExt->hOPcrDV)) {
  1201. TRACE(TL_61883_WARNING,("\'** pStrmExt:%x not data producer!\n\n", pStrmExt));
  1202. return STATUS_SUCCESS;
  1203. }
  1204. #endif
  1205. #ifdef NT51_61883
  1206. //
  1207. // Set Unit isoch parameters:
  1208. // The number of packets is depending on two factors:
  1209. // For a PAE system, number of packets cannnot be bigger than 64k/480 = 133
  1210. // For capture, number of packets should not be bigger than max packets to construct a DV buffer.
  1211. // This is needed to avoid completing two buffers in the same descriptor and can cause glitched
  1212. // in the "real time" playback of the data, esp the audio.
  1213. //
  1214. if(pDevExt->HardwareFlags & AV_HOST_DMA_DOUBLE_BUFFERING_ENABLED) {
  1215. // PAE system
  1216. pDevExt->UnitIoschParams.RX_NumPackets =
  1217. // pDevExt->UnitIoschParams.TX_NumPackets = // Use the default set by 61883
  1218. ((pDevExt->VideoFormatIndex == FMT_IDX_SD_DVCR_NTSC || pDevExt->VideoFormatIndex == FMT_IDX_SDL_DVCR_NTSC) ?
  1219. MAX_SRC_PACKETS_PER_NTSC_FRAME_PAE : MAX_SRC_PACKETS_PER_PAL_FRAME_PAE);
  1220. } else {
  1221. pDevExt->UnitIoschParams.RX_NumPackets =
  1222. // pDevExt->UnitIoschParams.TX_NumPackets = // Use the default set by 61883
  1223. ((pDevExt->VideoFormatIndex == FMT_IDX_SD_DVCR_NTSC || pDevExt->VideoFormatIndex == FMT_IDX_SDL_DVCR_NTSC) ?
  1224. MAX_SRC_PACKETS_PER_NTSC_FRAME : MAX_SRC_PACKETS_PER_PAL_FRAME);
  1225. }
  1226. if(!NT_SUCCESS(
  1227. Status = DVSetUnitIsochParams(
  1228. pDevExt,
  1229. &pDevExt->UnitIoschParams
  1230. ))) {
  1231. return Status;
  1232. }
  1233. #endif // NT51_61883
  1234. //
  1235. // Make a point to point connection
  1236. //
  1237. Status =
  1238. DVMakeP2PConnection(
  1239. pDevExt,
  1240. ulDataFlow,
  1241. pStrmExt
  1242. );
  1243. return Status;
  1244. }
  1245. NTSTATUS
  1246. DVDisconnect(
  1247. IN KSPIN_DATAFLOW ulDataFlow,
  1248. IN PDVCR_EXTENSION pDevExt,
  1249. IN PSTREAMEX pStrmExt
  1250. )
  1251. /*++
  1252. Routine Description:
  1253. Ask 61883.sys to free isoch bandwidth and program PCR.
  1254. Arguments:
  1255. Return Value:
  1256. Nothing
  1257. --*/
  1258. {
  1259. PIRP pIrp;
  1260. NTSTATUS Status = STATUS_SUCCESS;
  1261. PAV_61883_REQUEST pAVReq;
  1262. PAGED_CODE();
  1263. //
  1264. // Use the hPlug to disconnect
  1265. //
  1266. if(pStrmExt->hConnect) {
  1267. if(!(pAVReq = (AV_61883_REQUEST *) ExAllocatePool(NonPagedPool, sizeof(AV_61883_REQUEST))))
  1268. return STATUS_INSUFFICIENT_RESOURCES;
  1269. if(!(pIrp = IoAllocateIrp(pDevExt->pBusDeviceObject->StackSize, FALSE))) {
  1270. ExFreePool(pAVReq); pAVReq = NULL;
  1271. return STATUS_INSUFFICIENT_RESOURCES;
  1272. }
  1273. RtlZeroMemory(pAVReq, sizeof(AV_61883_REQUEST));
  1274. INIT_61883_HEADER(pAVReq, Av61883_Disconnect);
  1275. pAVReq->Disconnect.hConnect = pStrmExt->hConnect;
  1276. ASSERT(pStrmExt->hConnect);
  1277. if(!NT_SUCCESS(
  1278. Status = DVSubmitIrpSynch(
  1279. pDevExt,
  1280. pIrp,
  1281. pAVReq
  1282. ))) {
  1283. // This could be caused that the connection was not P2P, and
  1284. // it tried to disconnect.
  1285. TRACE(TL_61883_ERROR,("\'Disconnect hConnect:%x failed; ST %x; AvReq->ST %x\n", pStrmExt->hConnect, Status, pAVReq->Flags ));
  1286. // ASSERT(NT_SUCCESS(Status) && "DisConnect failed");
  1287. } else {
  1288. TRACE(TL_61883_TRACE,("\'Disconnect suceeded; ST %x; AvReq->ST %x\n", Status, pAVReq->Flags ));
  1289. }
  1290. IoFreeIrp(pIrp); pIrp = NULL;
  1291. ExFreePool(pAVReq); pAVReq = NULL;
  1292. TRACE(TL_61883_WARNING,("\'DisConn %s St:%x; Stat: SRBCnt:%d; [Pic# =? Prcs:Drp:Cncl:Rpt] [%d ?=%d+%d+%d+%d]\n",
  1293. ulDataFlow == KSPIN_DATAFLOW_OUT ? "[OutPin]" : "[InPin]",
  1294. Status,
  1295. (DWORD) pStrmExt->cntSRBReceived,
  1296. (DWORD) pStrmExt->PictureNumber,
  1297. (DWORD) pStrmExt->FramesProcessed,
  1298. (DWORD) pStrmExt->FramesDropped,
  1299. (DWORD) pStrmExt->cntSRBCancelled, // number of SRB_READ/WRITE_DATA cancelled
  1300. (DWORD) (pStrmExt->PictureNumber - pStrmExt->FramesProcessed - pStrmExt->FramesDropped - pStrmExt->cntSRBCancelled)
  1301. ));
  1302. #if DBG
  1303. if(DVFormatInfoTable[pDevExt->VideoFormatIndex].SrcPktHeader) {
  1304. ULONG ulElapsed = (DWORD) ((GetSystemTime() - pStrmExt->tmStreamStart)/(ULONGLONG) 10000);
  1305. TRACE(TL_61883_WARNING,("\'****-* TotalSrcPkt:%d; DisCont:%d; Elapse:%d msec; DataRate:%d bps *-****\n", \
  1306. pStrmExt->lTotalCycleCount, pStrmExt->lDiscontinuityCount,
  1307. ulElapsed,
  1308. pStrmExt->lTotalCycleCount * 188 * 1000 / ulElapsed * 8
  1309. ));
  1310. }
  1311. #endif
  1312. // We will not have another chance to reconnect it so we assume it is disconnected.
  1313. pStrmExt->hConnect = NULL;
  1314. }
  1315. return Status;
  1316. }
  1317. //
  1318. // GetSystemTime in 100 nS units
  1319. //
  1320. ULONGLONG GetSystemTime()
  1321. {
  1322. LARGE_INTEGER rate, ticks;
  1323. ticks = KeQueryPerformanceCounter(&rate);
  1324. return (KSCONVERT_PERFORMANCE_TIME(rate.QuadPart, ticks));
  1325. }
  1326. #define DIFBLK_SIZE 12000
  1327. #define PACK_NO_INFO 0xff
  1328. // Subcode header identifier
  1329. #define SC_HDR_TIMECODE 0x13
  1330. #define SC_HDR_BINARYGROUP 0x14
  1331. // header identifier
  1332. #define AAUX_HDR_SOURCE 0x50
  1333. #define AAUX_HDR_SOURCE_CONTROL 0x51
  1334. #define AAUX_HDR_REC_DATE 0x52
  1335. #define AAUX_HDR_REC_TIME 0x53
  1336. #define AAUX_HDR_BINARY_GROUP 0x54
  1337. #define AAUX_HDR_CC 0x55
  1338. #define AAUX_HDR_TR 0x56
  1339. #define VAUX_HDR_SOURCE 0x60
  1340. #define VAUX_HDR_SOURCE_CONTROL 0x61
  1341. #define VAUX_HDR_REC_DATE 0x62
  1342. #define VAUX_HDR_REC_TIME 0x63
  1343. #define VAUX_HDR_BINARY_GROUP 0x64
  1344. #define VAUX_HDR_CC 0x65
  1345. #define VAUX_HDR_TR 0x66
  1346. // Determine section type (MS 3 bits); Fig.66; Table 36.
  1347. #define ID0_SCT_MASK 0xe0
  1348. #define ID0_SCT_HEADER 0x00
  1349. #define ID0_SCT_SUBCODE 0x20
  1350. #define ID0_SCT_VAUX 0x40
  1351. #define ID0_SCT_AUDIO 0x60
  1352. #define ID0_SCT_VIDEO 0x80
  1353. // A pack is consisted of one byte of header identifier and 4 bytes of data; Part2, annex D.
  1354. typedef struct _DV_PACK {
  1355. UCHAR Header;
  1356. UCHAR Data[4];
  1357. } DV_PACK, *PDV_PACK;
  1358. typedef struct _DV_H0 {
  1359. UCHAR ID0;
  1360. UCHAR ID1;
  1361. UCHAR ID2;
  1362. UCHAR DSF;
  1363. UCHAR DFTIA;
  1364. UCHAR TF1;
  1365. UCHAR TF2;
  1366. UCHAR TF3;
  1367. UCHAR Reserved[72];
  1368. } DV_H0, *PDV_H0;
  1369. typedef struct _DV_SC {
  1370. UCHAR ID0;
  1371. UCHAR ID1;
  1372. UCHAR ID2;
  1373. struct {
  1374. UCHAR SID0;
  1375. UCHAR SID1;
  1376. UCHAR Reserved;
  1377. DV_PACK Pack;
  1378. } SSyb0;
  1379. struct {
  1380. UCHAR SID0;
  1381. UCHAR SID1;
  1382. UCHAR Reserved;
  1383. DV_PACK Pack;
  1384. } SSyb1;
  1385. struct {
  1386. UCHAR SID0;
  1387. UCHAR SID1;
  1388. UCHAR Reserved;
  1389. DV_PACK Pack;
  1390. } SSyb2;
  1391. struct {
  1392. UCHAR SID0;
  1393. UCHAR SID1;
  1394. UCHAR Reserved;
  1395. DV_PACK Pack;
  1396. } SSyb3;
  1397. struct {
  1398. UCHAR SID0;
  1399. UCHAR SID1;
  1400. UCHAR Reserved;
  1401. DV_PACK Pack;
  1402. } SSyb4;
  1403. struct {
  1404. UCHAR SID0;
  1405. UCHAR SID1;
  1406. UCHAR Reserved;
  1407. DV_PACK Pack;
  1408. } SSyb5;
  1409. UCHAR Reserved[29];
  1410. } DV_SC, *PDV_SC;
  1411. #define MAX_VAUX_PACK 15
  1412. typedef struct _DV_VAUX {
  1413. UCHAR ID0;
  1414. UCHAR ID1;
  1415. UCHAR ID2;
  1416. DV_PACK Pack[MAX_VAUX_PACK];
  1417. UCHAR Reserved[2];
  1418. } DV_VAUX, *PDV_VAUX;
  1419. typedef struct _DV_A {
  1420. UCHAR ID0;
  1421. UCHAR ID1;
  1422. UCHAR ID2;
  1423. DV_PACK Pack;
  1424. UCHAR Data[72];
  1425. } DV_A, *PDV_A;
  1426. typedef struct _DV_V {
  1427. UCHAR ID0;
  1428. UCHAR ID1;
  1429. UCHAR ID2;
  1430. UCHAR Data[77]; // 3..79
  1431. } DV_V, *PDV_V;
  1432. // Two source packets
  1433. #define V_BLOCKS 15
  1434. typedef struct _DV_AV {
  1435. DV_A A;
  1436. DV_V V[V_BLOCKS];
  1437. } DV_AV, *PDV_AV;
  1438. #define SC_SECTIONS 2
  1439. #define VAUX_SECTIONS 3
  1440. #define AV_SECTIONS 9
  1441. typedef struct _DV_DIF_SEQ {
  1442. DV_H0 H0;
  1443. DV_SC SC[SC_SECTIONS];
  1444. DV_VAUX VAux[VAUX_SECTIONS];
  1445. DV_AV AV[AV_SECTIONS];
  1446. } DV_DIF_SEQ, *PDV_DIF_SEQ;
  1447. typedef struct _DV_FRAME_NTSC {
  1448. DV_DIF_SEQ DifSeq[10];
  1449. } DV_FRAME_NTSC, *PDV_FRAME_NTSC;
  1450. typedef struct _DV_FRAME_PAL {
  1451. DV_DIF_SEQ DifSeq[12];
  1452. } DV_FRAME_PAL, *PDV_FRAME_PAL;
  1453. // By setting REC MODE to 111b (invalid recording) can
  1454. // cause DV to mute the audio
  1455. #define AAUX_REC_MODE_INVALID_MASK 0x38 // xx11:1xxx
  1456. #define AAUX_REC_MODE_ORIGINAL 0x08 // xx00:1xxx
  1457. #ifdef MSDV_SUPPORT_MUTE_AUDIO
  1458. // #define SHOW_ONE_FIELD_TWICE
  1459. BOOL
  1460. DVMuteDVFrame(
  1461. IN PDVCR_EXTENSION pDevExt,
  1462. IN OUT PUCHAR pFrameBuffer,
  1463. IN BOOL bMuteAudio
  1464. )
  1465. {
  1466. PDV_DIF_SEQ pDifSeq;
  1467. #ifdef SHOW_ONE_FIELD_TWICE
  1468. PDV_VAUX pVAux;
  1469. ULONG k;
  1470. #endif
  1471. ULONG i, j;
  1472. #ifdef SHOW_ONE_FIELD_TWICE
  1473. BOOL bFound1 = FALSE;
  1474. #endif
  1475. BOOL bFound2 = FALSE;
  1476. pDifSeq = (PDV_DIF_SEQ) pFrameBuffer;
  1477. // find the VVAX Source pack
  1478. for (i=0; i < DVFormatInfoTable[pDevExt->VideoFormatIndex].ulNumOfDIFSequences; i++) {
  1479. #ifdef SHOW_ONE_FIELD_TWICE // Advise by Adobe that we may want to show bothj field but mute audio
  1480. // Make the field2 output twice, FrameChange to 0 (same as previous frame)
  1481. for (j=0; j < VAUX_SECTIONS; j++) {
  1482. pVAux = &pDifSeq->VAux[j];
  1483. if((pVAux->ID0 & ID0_SCT_MASK) != ID0_SCT_VAUX) {
  1484. TRACE(TL_CIP_WARNING,("\'Invalid ID0:%.2x for pVAUX:%x (Dif:%d;V%d;S%d)\n", pVAux->ID0, pVAux, i, j, k));
  1485. continue;
  1486. }
  1487. for (k=0; k< MAX_VAUX_PACK; k++) {
  1488. if(pVAux->Pack[k].Header == VAUX_HDR_SOURCE_CONTROL) {
  1489. if(bMuteAudio) {
  1490. TRACE(TL_CIP_WARNING,("\'Mute Audio; pDifSeq:%x; pVAux:%x; (Dif:%d,V%d,S%d); %.2x,[%.2x,%.2x,%.2x,%.2x]; pack[2]->%.2x\n", \
  1491. pDifSeq, pVAux, i, j, k, \
  1492. pVAux->Pack[k].Header, pVAux->Pack[k].Data[0], pVAux->Pack[k].Data[1], pVAux->Pack[k].Data[2], pVAux->Pack[k].Data[3], \
  1493. (pVAux->Pack[k].Data[2] & 0x1F) ));
  1494. pVAux->Pack[k].Data[2] &= 0x1f; // 0x1F; // set FF, FS and FC to 0
  1495. TRACE(TL_CIP_TRACE,("\'pVAux->Pack[k].Data[2] = %.2x\n", pVAux->Pack[k].Data[2]));
  1496. } else {
  1497. TRACE(TL_CIP_TRACE,("\'un-Mute Audio; pack[2]: %.2x ->%.2x\n", pVAux->Pack[k].Data[2], (pVAux->Pack[k].Data[2] | 0xc0) ));
  1498. pVAux->Pack[k].Data[2] |= 0xe0; // set FF, FS and FCto 1; Show both fields in field 1,2 order
  1499. }
  1500. bFound1 = TRUE;
  1501. break; // Set only the 1st occurrence
  1502. }
  1503. }
  1504. }
  1505. #endif
  1506. for (j=0; j < AV_SECTIONS; j++) {
  1507. if(pDifSeq->AV[j].A.Pack.Header == AAUX_HDR_SOURCE_CONTROL) {
  1508. TRACE(TL_CIP_TRACE,("\'A0Aux %.2x,[%.2x,%.2x,%.2x,%.2x] %.2x->%.2x\n", \
  1509. pDifSeq->AV[j].A.Pack.Header, pDifSeq->AV[j].A.Pack.Data[0], \
  1510. pDifSeq->AV[j].A.Pack.Data[1], pDifSeq->AV[j].A.Pack.Data[2], pDifSeq->AV[j].A.Pack.Data[3], \
  1511. pDifSeq->AV[j].A.Pack.Data[1], pDifSeq->AV[j].A.Pack.Data[1] | AAUX_REC_MODE_INVALID_MASK
  1512. ));
  1513. if(bMuteAudio)
  1514. pDifSeq->AV[j].A.Pack.Data[1] |= AAUX_REC_MODE_INVALID_MASK; // Cause DV to mute this.
  1515. else
  1516. pDifSeq->AV[j].A.Pack.Data[1] = \
  1517. (pDifSeq->AV[j].A.Pack.Data[1] & ~AAUX_REC_MODE_INVALID_MASK) | AAUX_REC_MODE_ORIGINAL;
  1518. bFound2 = TRUE;
  1519. break; // Set only the 1st occurrence
  1520. }
  1521. }
  1522. // Must do the 1st occurance of all Dif sequences;
  1523. pDifSeq++; // Next DIF sequence
  1524. }
  1525. #ifdef SHOW_ONE_FIELD_TWICE
  1526. return (bFound1 && bFound2);
  1527. #else
  1528. return bFound2;
  1529. #endif
  1530. }
  1531. #endif
  1532. #ifdef MSDV_SUPPORT_EXTRACT_SUBCODE_DATA
  1533. VOID
  1534. DVCRExtractTimecodeFromFrame(
  1535. IN PDVCR_EXTENSION pDevExt,
  1536. IN PSTREAMEX pStrmExt,
  1537. IN PUCHAR pFrameBuffer
  1538. )
  1539. {
  1540. PUCHAR pDIFBlk;
  1541. PUCHAR pS0, pS1, pSID0;
  1542. ULONG i, j;
  1543. BYTE LastTimecode[4], Timecode[4]; // hh:mm:ss,ff
  1544. DWORD LastAbsTrackNumber, AbsTrackNumber;
  1545. PUCHAR pSID1;
  1546. BYTE Timecode2[4]; // hh:mm:ss,ff
  1547. DWORD AbsTrackNumber2;
  1548. BOOL bGetAbsT = TRUE, bGetTimecode = TRUE;
  1549. // Can be called at DISPATCH_LEVEL
  1550. pDIFBlk = (PUCHAR) pFrameBuffer;
  1551. // Save the last timecode so we will now if it has
  1552. LastTimecode[0] = pStrmExt->Timecode[0];
  1553. LastTimecode[1] = pStrmExt->Timecode[1];
  1554. LastTimecode[2] = pStrmExt->Timecode[2];
  1555. LastTimecode[3] = pStrmExt->Timecode[3];
  1556. LastAbsTrackNumber = pStrmExt->AbsTrackNumber;
  1557. //
  1558. // Traverse thru every DIF BLOCK looking for VA0,1 and 2
  1559. for(i=0; i < DVFormatInfoTable[pDevExt->VideoFormatIndex].ulNumOfDIFSequences; i++) {
  1560. pS0 = pDIFBlk + 80;
  1561. pS1 = pS0 + 80;
  1562. //
  1563. // Is this Subcode source packet? See Table 36 (P.111) of the Blue Book
  1564. //
  1565. if ((pS0[0] & 0xe0) == 0x20 && (pS1[0] & 0xe0) == 0x20) {
  1566. if(bGetAbsT) {
  1567. //
  1568. // See Figure 42 (p. 94) of the Blue book
  1569. // SID0(Low nibble),1 (high nibble) of every three subcode sync block can form the ATN
  1570. //
  1571. pSID0 = &pS0[3];
  1572. AbsTrackNumber = 0;
  1573. for (j = 0 ; j < 3; j++) {
  1574. AbsTrackNumber = (( ( (pSID0[0] & 0x0f) << 4) | (pSID0[1] >> 4) ) << (j * 8)) | AbsTrackNumber;
  1575. pSID0 += 8;
  1576. bGetAbsT = FALSE;
  1577. }
  1578. pSID1 = &pS1[3];
  1579. AbsTrackNumber2 = 0;
  1580. for (j = 0 ; j < 3; j++) {
  1581. AbsTrackNumber2 = (( ( (pSID1[0] & 0x0f) << 4) | (pSID1[1] >> 4) ) << (j * 8)) | AbsTrackNumber2;
  1582. pSID1 += 8;
  1583. }
  1584. // Verify that the track number is the same!
  1585. if(AbsTrackNumber == AbsTrackNumber2) {
  1586. bGetAbsT = FALSE;
  1587. } else {
  1588. bGetAbsT = TRUE;
  1589. TRACE(TL_CIP_TRACE,("\'%d Sequence; AbsT (%d,%d) != AbsT2 (%d,%d)\n",
  1590. i,
  1591. AbsTrackNumber / 2, AbsTrackNumber & 0x01,
  1592. AbsTrackNumber2 / 2, AbsTrackNumber2 & 0x01
  1593. ));
  1594. }
  1595. }
  1596. if(bGetTimecode) {
  1597. // See Figure 68 (p. 114) of the Blue Book
  1598. // Subcode sync block number 3, 4 and 5
  1599. for(j = 3; j <= 5; j++) {
  1600. // 3 bytes of IDs and follow by sequence of 8 bytes SyncBlock (3:5);
  1601. // 0x13 == TIMECODE
  1602. if(pS0[3+3+j*8] == 0x13
  1603. && pS0[3+3+j*8+4] != 0xff
  1604. && pS0[3+3+j*8+3] != 0xff
  1605. && pS0[3+3+j*8+2] != 0xff
  1606. && pS0[3+3+j*8+1] != 0xff) {
  1607. Timecode[0] = pS0[3+3+j*8+4]&0x3f; // hh
  1608. Timecode[1] = pS0[3+3+j*8+3]&0x7f; // mm
  1609. Timecode[2] = pS0[3+3+j*8+2]&0x7f; // ss
  1610. Timecode[3] = pS0[3+3+j*8+1]&0x3f; // ff
  1611. bGetTimecode = FALSE;
  1612. break;
  1613. }
  1614. }
  1615. // Subcode sync block number 9, 10 and 11
  1616. for(j = 3; j <= 5; j++) {
  1617. // 3 bytes of IDs and follow by sequence of 8 bytes SyncBlock (3:5);
  1618. // 0x13 == TIMECODE
  1619. if(pS1[3+3+j*8] == 0x13
  1620. && pS1[3+3+j*8+4] != 0xff
  1621. && pS1[3+3+j*8+3] != 0xff
  1622. && pS1[3+3+j*8+2] != 0xff
  1623. && pS1[3+3+j*8+1] != 0xff) {
  1624. Timecode2[0] = pS1[3+3+j*8+4]&0x3f; // hh
  1625. Timecode2[1] = pS1[3+3+j*8+3]&0x7f; // mm
  1626. Timecode2[2] = pS1[3+3+j*8+2]&0x7f; // ss
  1627. Timecode2[3] = pS1[3+3+j*8+1]&0x3f; // ff
  1628. bGetTimecode = FALSE;
  1629. break;
  1630. }
  1631. }
  1632. //
  1633. // Verify
  1634. //
  1635. if(!bGetTimecode) {
  1636. if( Timecode[0] == Timecode2[0]
  1637. && Timecode[1] == Timecode2[1]
  1638. && Timecode[2] == Timecode2[2]
  1639. && Timecode[3] == Timecode2[3]) {
  1640. } else {
  1641. bGetTimecode = TRUE;
  1642. TRACE(TL_CIP_TRACE,("\'%d Sequence; %.2x:%.2x:%.2x,%.2x != %.2x:%.2x:%.2x,%.2x\n",
  1643. i,
  1644. Timecode[0], Timecode[1], Timecode[2], Timecode[3],
  1645. Timecode2[0], Timecode2[1], Timecode2[2], Timecode2[3]
  1646. ));
  1647. }
  1648. }
  1649. }
  1650. }
  1651. if(!bGetAbsT && !bGetTimecode)
  1652. break;
  1653. pDIFBlk += DIFBLK_SIZE; // Get to next block
  1654. }
  1655. if(!bGetAbsT && pStrmExt->AbsTrackNumber != AbsTrackNumber) {
  1656. pStrmExt->AbsTrackNumber = AbsTrackNumber; // BF is the LSB
  1657. pStrmExt->bATNUpdated = TRUE;
  1658. TRACE(TL_CIP_TRACE,("\'Extracted TrackNum:%d; DicontBit:%d\n", AbsTrackNumber / 2, AbsTrackNumber & 0x01));
  1659. }
  1660. if(!bGetTimecode &&
  1661. (
  1662. Timecode[0] != LastTimecode[0] ||
  1663. Timecode[1] != LastTimecode[1] ||
  1664. Timecode[2] != LastTimecode[2] ||
  1665. Timecode[3] != LastTimecode[3]
  1666. )
  1667. ) {
  1668. pStrmExt->Timecode[0] = Timecode[0]; // hh
  1669. pStrmExt->Timecode[1] = Timecode[1]; // mm
  1670. pStrmExt->Timecode[2] = Timecode[2]; // mm
  1671. pStrmExt->Timecode[3] = Timecode[3]; // ff
  1672. pStrmExt->bTimecodeUpdated = TRUE;
  1673. TRACE(TL_CIP_TRACE,("\'Extracted Timecode %.2x:%.2x:%.2x,%.2x\n", Timecode[0], Timecode[1], Timecode[2], Timecode[3]));
  1674. }
  1675. }
  1676. #endif // MSDV_SUPPORT_EXTRACT_SUBCODE_DATA
  1677. #ifdef MSDV_SUPPORT_EXTRACT_DV_DATE_TIME
  1678. VOID
  1679. DVCRExtractRecDateAndTimeFromFrame(
  1680. IN PDVCR_EXTENSION pDevExt,
  1681. IN PSTREAMEX pStrmExt,
  1682. IN PUCHAR pFrameBuffer
  1683. )
  1684. {
  1685. PUCHAR pDIFBlk;
  1686. PUCHAR pS0, pS1;
  1687. ULONG i, j;
  1688. BOOL bGetRecDate = TRUE, bGetRecTime = TRUE;
  1689. // Can be called at DISPATCH_LEVEL
  1690. pDIFBlk = (PUCHAR) pFrameBuffer + DIFBLK_SIZE * DVFormatInfoTable[pDevExt->VideoFormatIndex].ulNumOfDIFSequences/2;
  1691. //
  1692. // REC Data (VRD) and Time (VRT) on in the 2nd half oa a video frame
  1693. //
  1694. for(i=DVFormatInfoTable[pDevExt->VideoFormatIndex].ulNumOfDIFSequences/2; i < DVFormatInfoTable[pDevExt->VideoFormatIndex].ulNumOfDIFSequences; i++) {
  1695. pS0 = pDIFBlk + 80;
  1696. pS1 = pS0 + 80;
  1697. //
  1698. // Find SC0 and SC1. See Table 36 (P.111) of the Blue Book
  1699. //
  1700. // SC0/1: ID(0,1,2), Data (3,50), Reserved(51-79)
  1701. // SC0:Data: SSYB0(3..10), SSYB1(11..18), SSYB2(19..26), SSYB3(27..34), SSYB4(35..42), SSYB5(43..50)
  1702. // SC1:Data: SSYB6(3..10), SSYB7(11..18), SSYB8(19..26), SSYB9(27..34), SSYB10(35..42), SSYB11(43..50)
  1703. // SSYBx(SubCodeId0, SubcodeID1, Reserved, Pack(3,4,5,6,7))
  1704. //
  1705. // TTC are in the 1st half: SSYB0..11 (every)
  1706. // TTC are in the 2nd half: SSYB0,3,6,9
  1707. // VRD are in the 2nd half of a video frame, SSYB1,4,7,10
  1708. // VRT are in the 2nd half of a video frame, SSYB2,5,8,11
  1709. //
  1710. // Subcode data ?
  1711. if ((pS0[0] & 0xe0) == 0x20 && (pS1[0] & 0xe0) == 0x20) {
  1712. //
  1713. // RecDate: VRD
  1714. //
  1715. if(bGetRecDate) {
  1716. // go thru 6 sync blocks (8 bytes per block) per Subcode; idx 1(SSYB1),4(SSYB4) for SC0
  1717. for(j=0; j <= 5 ; j++) {
  1718. if(j == 1 || j == 4) {
  1719. // 0x62== RecDate
  1720. if(pS0[3+3+j*8] == 0x62) {
  1721. pStrmExt->RecDate[0] = pS0[3+3+j*8+4]; // Year
  1722. pStrmExt->RecDate[1] = pS0[3+3+j*8+3]&0x1f; // Month
  1723. pStrmExt->RecDate[2] = pS0[3+3+j*8+2]&0x3f; // Day
  1724. pStrmExt->RecDate[3] = pS0[3+3+j*8+1]&0x3f; // TimeZone
  1725. bGetRecDate = FALSE;
  1726. break;
  1727. }
  1728. }
  1729. }
  1730. }
  1731. if(bGetRecDate) {
  1732. // go thru 6 sync blocks (8 bytes per block) per Subcode; idx 1 (SSYB7),4(SSYB10) for SC1
  1733. for(j=0; j <= 5; j++) {
  1734. if(j == 1 || j == 4) {
  1735. // 0x62== RecDate
  1736. if(pS1[3+3+j*8] == 0x62) {
  1737. pStrmExt->RecDate[0] = pS1[3+3+j*8+4]; // Year
  1738. pStrmExt->RecDate[1] = pS1[3+3+j*8+3]&0x1f; // Month
  1739. pStrmExt->RecDate[2] = pS1[3+3+j*8+2]&0x3f; // Day
  1740. pStrmExt->RecDate[3] = pS1[3+3+j*8+1]&0x3f; // TimeZone
  1741. bGetRecDate = FALSE;
  1742. break;
  1743. }
  1744. }
  1745. }
  1746. }
  1747. //
  1748. // RecTime: VRT
  1749. //
  1750. if(bGetRecTime) {
  1751. // go thru 6 sync blocks (8 bytes per block) per Subcode; idx 2(SSYB2),5(SSYB5) for SC0
  1752. for(j=0; j <= 5 ; j++) {
  1753. if(j == 2 || j == 5) {
  1754. // 0x63== RecTime
  1755. if(pS0[3+3+j*8] == 0x63) {
  1756. pStrmExt->RecTime[0] = pS0[3+3+j*8+4]&0x3f;
  1757. pStrmExt->RecTime[1] = pS0[3+3+j*8+3]&0x7f;
  1758. pStrmExt->RecTime[2] = pS0[3+3+j*8+2]&0x7f;
  1759. pStrmExt->RecTime[3] = pS0[3+3+j*8+1]&0x3f;
  1760. bGetRecTime = FALSE;
  1761. break;
  1762. }
  1763. }
  1764. }
  1765. }
  1766. if(bGetRecTime) {
  1767. // go thru 6 sync blocks (8 bytes per block) per Subcode; idx 2 (SSYB8),5(SSYB11) for SC1
  1768. for(j=0; j <= 5; j++) {
  1769. if(j == 2 || j == 5) {
  1770. // 0x63== RecTime
  1771. if(pS1[3+3+j*8] == 0x63) {
  1772. pStrmExt->RecTime[0] = pS1[3+3+j*8+4]&0x3f;
  1773. pStrmExt->RecTime[1] = pS1[3+3+j*8+3]&0x7f;
  1774. pStrmExt->RecTime[2] = pS1[3+3+j*8+2]&0x7f;
  1775. pStrmExt->RecTime[3] = pS1[3+3+j*8+1]&0x3f;
  1776. bGetRecTime = FALSE;
  1777. break;
  1778. }
  1779. }
  1780. }
  1781. }
  1782. }
  1783. if(!bGetRecDate && !bGetRecTime)
  1784. break;
  1785. pDIFBlk += DIFBLK_SIZE; // Next sequence
  1786. }
  1787. TRACE(TL_CIP_TRACE,("\'Frame# %.5d, Date %s %x-%.2x-%.2x, Time %s %.2x:%.2x:%.2x,%.2x\n",
  1788. (ULONG) pStrmExt->FramesProcessed,
  1789. bGetRecDate ? "NF:" : "Found:", pStrmExt->RecDate[0], pStrmExt->RecDate[1] & 0x1f, pStrmExt->RecDate[2] & 0x3f,
  1790. bGetRecTime ? "NF:" : "Found:",pStrmExt->RecTime[0], pStrmExt->RecTime[1], pStrmExt->RecTime[2], pStrmExt->RecTime[3]
  1791. ));
  1792. }
  1793. #endif // MSDV_SUPPORT_EXTRACT_DV_DATE_TIME
  1794. #ifdef READ_CUTOMIZE_REG_VALUES
  1795. NTSTATUS
  1796. CreateRegistryKeySingle(
  1797. IN HANDLE hKey,
  1798. IN ACCESS_MASK desiredAccess,
  1799. PWCHAR pwszSection,
  1800. OUT PHANDLE phKeySection
  1801. )
  1802. {
  1803. NTSTATUS status;
  1804. UNICODE_STRING ustr;
  1805. OBJECT_ATTRIBUTES objectAttributes;
  1806. RtlInitUnicodeString(&ustr, pwszSection);
  1807. InitializeObjectAttributes(
  1808. &objectAttributes,
  1809. &ustr,
  1810. OBJ_CASE_INSENSITIVE,
  1811. hKey,
  1812. NULL
  1813. );
  1814. status =
  1815. ZwCreateKey(
  1816. phKeySection,
  1817. desiredAccess,
  1818. &objectAttributes,
  1819. 0,
  1820. NULL, /* optional*/
  1821. REG_OPTION_NON_VOLATILE,
  1822. NULL
  1823. );
  1824. return status;
  1825. }
  1826. NTSTATUS
  1827. CreateRegistrySubKey(
  1828. IN HANDLE hKey,
  1829. IN ACCESS_MASK desiredAccess,
  1830. PWCHAR pwszSection,
  1831. OUT PHANDLE phKeySection
  1832. )
  1833. {
  1834. UNICODE_STRING ustr;
  1835. USHORT usPos = 1; // Skip first backslash
  1836. static WCHAR wSep = '\\';
  1837. NTSTATUS status = STATUS_SUCCESS;
  1838. RtlInitUnicodeString(&ustr, pwszSection);
  1839. while(usPos < ustr.Length) {
  1840. if(ustr.Buffer[usPos] == wSep) {
  1841. // NULL terminate our partial string
  1842. ustr.Buffer[usPos] = UNICODE_NULL;
  1843. status =
  1844. CreateRegistryKeySingle(
  1845. hKey,
  1846. desiredAccess,
  1847. ustr.Buffer,
  1848. phKeySection
  1849. );
  1850. ustr.Buffer[usPos] = wSep;
  1851. if(NT_SUCCESS(status)) {
  1852. ZwClose(*phKeySection);
  1853. } else {
  1854. break;
  1855. }
  1856. }
  1857. usPos++;
  1858. }
  1859. // Create the full key
  1860. if(NT_SUCCESS(status)) {
  1861. status =
  1862. CreateRegistryKeySingle(
  1863. hKey,
  1864. desiredAccess,
  1865. ustr.Buffer,
  1866. phKeySection
  1867. );
  1868. }
  1869. return status;
  1870. }
  1871. NTSTATUS
  1872. GetRegistryKeyValue (
  1873. IN HANDLE Handle,
  1874. IN PWCHAR KeyNameString,
  1875. IN ULONG KeyNameStringLength,
  1876. IN PVOID Data,
  1877. IN PULONG DataLength
  1878. )
  1879. /*++
  1880. Routine Description:
  1881. This routine gets the specified value out of the registry
  1882. Arguments:
  1883. Handle - Handle to location in registry
  1884. KeyNameString - registry key we're looking for
  1885. KeyNameStringLength - length of registry key we're looking for
  1886. Data - where to return the data
  1887. DataLength - how big the data is
  1888. Return Value:
  1889. status is returned from ZwQueryValueKey
  1890. --*/
  1891. {
  1892. NTSTATUS status = STATUS_INSUFFICIENT_RESOURCES;
  1893. UNICODE_STRING keyName;
  1894. ULONG length;
  1895. PKEY_VALUE_FULL_INFORMATION fullInfo;
  1896. RtlInitUnicodeString(&keyName, KeyNameString);
  1897. length = sizeof(KEY_VALUE_FULL_INFORMATION) +
  1898. KeyNameStringLength + *DataLength;
  1899. fullInfo = ExAllocatePool(PagedPool, length);
  1900. if (fullInfo) {
  1901. status = ZwQueryValueKey(
  1902. Handle,
  1903. &keyName,
  1904. KeyValueFullInformation,
  1905. fullInfo,
  1906. length,
  1907. &length
  1908. );
  1909. if (NT_SUCCESS(status)){
  1910. ASSERT(fullInfo->DataLength <= *DataLength);
  1911. RtlCopyMemory(
  1912. Data,
  1913. ((PUCHAR) fullInfo) + fullInfo->DataOffset,
  1914. fullInfo->DataLength
  1915. );
  1916. }
  1917. *DataLength = fullInfo->DataLength;
  1918. ExFreePool(fullInfo);
  1919. }
  1920. return (status);
  1921. }
  1922. #if 0 // Not used
  1923. NTSTATUS
  1924. SetRegistryKeyValue(
  1925. HANDLE hKey,
  1926. PWCHAR pwszEntry,
  1927. LONG nValue
  1928. )
  1929. {
  1930. NTSTATUS status;
  1931. UNICODE_STRING ustr;
  1932. RtlInitUnicodeString(&ustr, pwszEntry);
  1933. status =
  1934. ZwSetValueKey(
  1935. hKey,
  1936. &ustr,
  1937. 0, /* optional */
  1938. REG_DWORD,
  1939. &nValue,
  1940. sizeof(nValue)
  1941. );
  1942. return status;
  1943. }
  1944. #endif // Not used
  1945. //
  1946. // Registry subky and values wide character strings.
  1947. //
  1948. WCHAR wszSettings[] = L"Settings";
  1949. WCHAR wszATNSearch[] = L"bSupportATNSearch";
  1950. WCHAR wszSyncRecording[] = L"bSyncRecording";
  1951. WCHAR wszMaxDataSync[] = L"tmMaxDataSync";
  1952. WCHAR wszPlayPs2RecPs[] = L"fmPlayPause2RecPause";
  1953. WCHAR wszStop2RecPs[] = L"fmStop2RecPause";
  1954. WCHAR wszRecPs2Rec[] = L"tmRecPause2Rec";
  1955. WCHAR wszXprtStateChangeWait[] = L"tmXprtStateChangeWait";
  1956. BOOL
  1957. DVGetPropertyValuesFromRegistry(
  1958. IN PDVCR_EXTENSION pDevExt
  1959. )
  1960. {
  1961. NTSTATUS Status;
  1962. HANDLE hPDOKey, hKeySettings;
  1963. ULONG ulLength;
  1964. //
  1965. // Registry key:
  1966. // Windows 2000:
  1967. // HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Class\
  1968. // {6BDD1FC6-810F-11D0-BEC7-08002BE2092F\000x
  1969. //
  1970. // Win98:
  1971. // HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Class\Image\000x
  1972. //
  1973. Status =
  1974. IoOpenDeviceRegistryKey(
  1975. pDevExt->pPhysicalDeviceObject,
  1976. PLUGPLAY_REGKEY_DRIVER,
  1977. STANDARD_RIGHTS_READ,
  1978. &hPDOKey
  1979. );
  1980. // PDO might be deleted when it was removed.
  1981. if(! pDevExt->bDevRemoved) {
  1982. ASSERT(Status == STATUS_SUCCESS);
  1983. }
  1984. //
  1985. // loop through our table of strings,
  1986. // reading the registry for each.
  1987. //
  1988. if(NT_SUCCESS(Status)) {
  1989. // Create or open the settings key
  1990. Status =
  1991. CreateRegistrySubKey(
  1992. hPDOKey,
  1993. KEY_ALL_ACCESS,
  1994. wszSettings,
  1995. &hKeySettings
  1996. );
  1997. if(NT_SUCCESS(Status)) {
  1998. // Note: we can be more selective by checking
  1999. // pDevExt->ulDevType
  2000. #if 0 // Not supported yet!
  2001. // ATNSearch
  2002. ulLength = sizeof(LONG);
  2003. Status = GetRegistryKeyValue(
  2004. hKeySettings,
  2005. wszATNSearch,
  2006. sizeof(wszATNSearch),
  2007. (PVOID) &pDevExt->bATNSearch,
  2008. &ulLength);
  2009. TRACE(TL_PNP_WARNING,("\'GetRegVal: St:%x, Len:%d, bATNSearch:%d (1:Yes)\n", Status, ulLength, pDevExt->bATNSearch));
  2010. if(!NT_SUCCESS(Status)) pDevExt->bATNSearch = FALSE;
  2011. // bSyncRecording
  2012. ulLength = sizeof(LONG);
  2013. Status = GetRegistryKeyValue(
  2014. hKeySettings,
  2015. wszSyncRecording,
  2016. sizeof(wszSyncRecording),
  2017. (PVOID) &pDevExt->bSyncRecording,
  2018. &ulLength);
  2019. TRACE(TL_PNP_WARNING,("\'GetRegVal: St:%x, Len:%d, bSyncRecording:%d (1:Yes)\n", Status, ulLength, pDevExt->bSyncRecording));
  2020. if(!NT_SUCCESS(Status)) pDevExt->bSyncRecording = FALSE;
  2021. // tmMaxDataSync
  2022. ulLength = sizeof(LONG);
  2023. Status = GetRegistryKeyValue(
  2024. hKeySettings,
  2025. wszMaxDataSync,
  2026. sizeof(wszMaxDataSync),
  2027. (PVOID) &pDevExt->tmMaxDataSync,
  2028. &ulLength);
  2029. TRACE(TL_PNP_WARNING,("\'GetRegVal: St:%x, Len:%d, tmMaxDataSync:%d (msec)\n", Status, ulLength, pDevExt->tmMaxDataSync));
  2030. // fmPlayPs2RecPs
  2031. ulLength = sizeof(LONG);
  2032. Status = GetRegistryKeyValue(
  2033. hKeySettings,
  2034. wszPlayPs2RecPs,
  2035. sizeof(wszPlayPs2RecPs),
  2036. (PVOID) &pDevExt->fmPlayPs2RecPs,
  2037. &ulLength);
  2038. TRACE(TL_PNP_WARNING,("\'GetRegVal: St:%x, Len:%d, fmPlayPs2RecPs:%d (frames)\n", Status, ulLength, pDevExt->fmPlayPs2RecPs));
  2039. // fmStop2RecPs
  2040. ulLength = sizeof(LONG);
  2041. Status = GetRegistryKeyValue(
  2042. hKeySettings,
  2043. wszStop2RecPs,
  2044. sizeof(wszStop2RecPs),
  2045. (PVOID) &pDevExt->fmStop2RecPs,
  2046. &ulLength);
  2047. TRACE(TL_PNP_WARNING,("\'GetRegVal: St:%x, Len:%d, fmStop2RecPs:%d (frames)\n", Status, ulLength, pDevExt->fmStop2RecPs));
  2048. // tmRecPs2Rec
  2049. ulLength = sizeof(LONG);
  2050. Status = GetRegistryKeyValue(
  2051. hKeySettings,
  2052. wszRecPs2Rec,
  2053. sizeof(wszRecPs2Rec),
  2054. (PVOID) &pDevExt->tmRecPs2Rec,
  2055. &ulLength);
  2056. TRACE(TL_PNP_WARNING,("\'GetRegVal: St:%x, Len:%d, tmRecPs2Rec:%d (msec)\n", Status, ulLength, pDevExt->tmRecPs2Rec));
  2057. #endif
  2058. ulLength = sizeof(LONG);
  2059. Status = GetRegistryKeyValue(
  2060. hKeySettings,
  2061. wszXprtStateChangeWait,
  2062. sizeof(wszXprtStateChangeWait),
  2063. (PVOID) &pDevExt->XprtStateChangeWait, // in msec
  2064. &ulLength);
  2065. TRACE(TL_PNP_WARNING,("\'GetRegVal: St:%x, Len:%d, XprtStateChangeWait:%d msec\n", Status, ulLength, pDevExt->XprtStateChangeWait));
  2066. if(!NT_SUCCESS(Status)) pDevExt->XprtStateChangeWait = 0;
  2067. ZwClose(hKeySettings);
  2068. ZwClose(hPDOKey);
  2069. return TRUE;
  2070. } else {
  2071. TRACE(TL_PNP_ERROR,("\'GetPropertyValuesFromRegistry: CreateRegistrySubKey failed with Status=%x\n", Status));
  2072. }
  2073. ZwClose(hPDOKey);
  2074. } else {
  2075. TRACE(TL_PNP_ERROR,("\'GetPropertyValuesFromRegistry: IoOpenDeviceRegistryKey failed with Status=%x\n", Status));
  2076. }
  2077. // Not implemented so always return FALSE to use the defaults.
  2078. return FALSE;
  2079. }
  2080. #if 0 // Not used
  2081. BOOL
  2082. DVSetPropertyValuesToRegistry(
  2083. PDVCR_EXTENSION pDevExt
  2084. )
  2085. {
  2086. // Set the default to :
  2087. // HLM\Software\DeviceExtension->pchVendorName\1394DCam
  2088. NTSTATUS Status;
  2089. HANDLE hPDOKey, hKeySettings;
  2090. TRACE(TL_PNP_TRACE,("\'SetPropertyValuesToRegistry: pDevExt=%x; pDevExt->pBusDeviceObject=%x\n", pDevExt, pDevExt->pBusDeviceObject));
  2091. //
  2092. // Registry key:
  2093. // HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Class\
  2094. // {6BDD1FC6-810F-11D0-BEC7-08002BE2092F\000x
  2095. //
  2096. Status =
  2097. IoOpenDeviceRegistryKey(
  2098. pDevExt->pPhysicalDeviceObject,
  2099. PLUGPLAY_REGKEY_DRIVER,
  2100. STANDARD_RIGHTS_WRITE,
  2101. &hPDOKey);
  2102. // PDO might be deleted when it was removed.
  2103. if(! pDevExt->bDevRemoved) {
  2104. ASSERT(Status == STATUS_SUCCESS);
  2105. }
  2106. //
  2107. // loop through our table of strings,
  2108. // reading the registry for each.
  2109. //
  2110. if(NT_SUCCESS(Status)) {
  2111. // Create or open the settings key
  2112. Status =
  2113. CreateRegistrySubKey(
  2114. hPDOKey,
  2115. KEY_ALL_ACCESS,
  2116. wszSettings,
  2117. &hKeySettings
  2118. );
  2119. if(NT_SUCCESS(Status)) {
  2120. #if 0 // Note used, just an example:
  2121. // Brightness
  2122. Status = SetRegistryKeyValue(
  2123. hKeySettings,
  2124. wszBrightness,
  2125. pDevExt->XXXX);
  2126. TRACE(TL_PNP_TRACE,("\'SetPropertyValuesToRegistry: Status %x, Brightness %d\n", Status, pDevExt->Brightness));
  2127. #endif
  2128. ZwClose(hKeySettings);
  2129. ZwClose(hPDOKey);
  2130. return TRUE;
  2131. } else {
  2132. TRACE(TL_PNP_ERROR,("\'GetPropertyValuesToRegistry: CreateRegistrySubKey failed with Status=%x\n", Status));
  2133. }
  2134. ZwClose(hPDOKey);
  2135. } else {
  2136. TRACE(TL_PNP_TRACE,("\'GetPropertyValuesToRegistry: IoOpenDeviceRegistryKey failed with Status=%x\n", Status));
  2137. }
  2138. return FALSE;
  2139. }
  2140. #endif // Not used
  2141. #endif // READ_CUTOMIZE_REG_VALUES