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.

713 lines
22 KiB

  1. //===========================================================================
  2. //
  3. // THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
  4. // KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
  5. // IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
  6. // PURPOSE.
  7. //
  8. // Copyright (c) 1996 - 2000 Microsoft Corporation. All Rights Reserved.
  9. //
  10. //===========================================================================
  11. /*++
  12. Module Name:
  13. dcampkt.c
  14. Abstract:
  15. This file contains code to handle callback from the bus/class driver.
  16. They might be running in DISPATCH level.
  17. Author:
  18. Yee J. Wu 15-Oct-97
  19. Environment:
  20. Kernel mode only
  21. Revision History:
  22. --*/
  23. #include "strmini.h"
  24. #include "ksmedia.h"
  25. #include "1394.h"
  26. #include "wdm.h" // for DbgBreakPoint() defined in dbg.h
  27. #include "dbg.h"
  28. #include "dcamdef.h"
  29. #include "dcampkt.h"
  30. #include "sonydcam.h"
  31. #include "capprop.h"
  32. NTSTATUS
  33. DCamToInitializeStateCompletionRoutine(
  34. IN PDEVICE_OBJECT DeviceObject,
  35. IN PIRP pIrp,
  36. IN PDCAM_IO_CONTEXT pDCamIoContext
  37. )
  38. /*++
  39. Routine Description:
  40. Completion routine called after the device is initialize to a known state.
  41. Arguments:
  42. DriverObject - Pointer to driver object created by system.
  43. pIrp - Irp that just completed
  44. pDCamIoContext - A structure that contain the context of this IO completion routine.
  45. Return Value:
  46. None.
  47. --*/
  48. {
  49. PDCAM_EXTENSION pDevExt;
  50. PSTREAMEX pStrmEx;
  51. PIRB pIrb;
  52. if(!pDCamIoContext) {
  53. return STATUS_MORE_PROCESSING_REQUIRED;
  54. }
  55. pIrb = pDCamIoContext->pIrb;
  56. pDevExt = pDCamIoContext->pDevExt;
  57. DbgMsg2(("\'DCamToInitializeStateCompletionRoutine: completed DeviceState=%d; pIrp->IoStatus.Status=%x\n",
  58. pDCamIoContext->DeviceState, pIrp->IoStatus.Status));
  59. // Free MDL
  60. if(pIrb->FunctionNumber == REQUEST_ASYNC_WRITE) {
  61. DbgMsg3(("DCamToInitializeStateCompletionRoutine: IoFreeMdl\n"));
  62. IoFreeMdl(pIrb->u.AsyncWrite.Mdl);
  63. }
  64. // CAUTION:
  65. // Do we need to retry if the return is STATUS_TIMEOUT or invalid generation number ?
  66. //
  67. if(pIrp->IoStatus.Status != STATUS_SUCCESS) {
  68. ERROR_LOG(("DCamToInitializeStateCompletionRoutine: Status=%x != STATUS_SUCCESS; cannot restart its state.\n", pIrp->IoStatus.Status));
  69. if(pDCamIoContext->pSrb) {
  70. pDCamIoContext->pSrb->Status = STATUS_UNSUCCESSFUL;
  71. StreamClassStreamNotification(StreamRequestComplete, pDCamIoContext->pSrb->StreamObject, pDCamIoContext->pSrb);
  72. }
  73. DCamFreeIrbIrpAndContext(pDCamIoContext, pDCamIoContext->pIrb, pIrp);
  74. return STATUS_MORE_PROCESSING_REQUIRED;
  75. }
  76. //
  77. // Done here if we are in STOP or PAUSE state;
  78. // else setting to RUN state.
  79. //
  80. pStrmEx = (PSTREAMEX) pDevExt->pStrmEx;
  81. //
  82. // No stream is open, job is done.
  83. //
  84. if(!pStrmEx) {
  85. if(pDCamIoContext->pSrb) {
  86. pDCamIoContext->pSrb->Status = STATUS_SUCCESS;
  87. StreamClassStreamNotification(StreamRequestComplete, pDCamIoContext->pSrb->StreamObject, pDCamIoContext->pSrb);
  88. }
  89. return STATUS_MORE_PROCESSING_REQUIRED;
  90. }
  91. switch(pStrmEx->KSStateFinal) {
  92. case KSSTATE_STOP:
  93. case KSSTATE_PAUSE:
  94. pStrmEx->KSState = pStrmEx->KSStateFinal;
  95. if(pDCamIoContext->pSrb) {
  96. pDCamIoContext->pSrb->Status = STATUS_SUCCESS;
  97. StreamClassStreamNotification(StreamRequestComplete, pDCamIoContext->pSrb->StreamObject, pDCamIoContext->pSrb);
  98. }
  99. DCamFreeIrbIrpAndContext(pDCamIoContext, pDCamIoContext->pIrb, pIrp);
  100. break;
  101. case KSSTATE_RUN:
  102. if(pDCamIoContext->pSrb) {
  103. pDCamIoContext->pSrb->Status = STATUS_SUCCESS;
  104. StreamClassStreamNotification(StreamRequestComplete, pDCamIoContext->pSrb->StreamObject, pDCamIoContext->pSrb);
  105. }
  106. // Restart the stream.
  107. DCamSetKSStateRUN(pDevExt, pDCamIoContext->pSrb);
  108. // Need pDCamIoContext->pSrb; so free it after DCamSetKSStateRUN().
  109. DCamFreeIrbIrpAndContext(pDCamIoContext, pDCamIoContext->pIrb, pIrp);
  110. break;
  111. }
  112. return STATUS_MORE_PROCESSING_REQUIRED;
  113. }
  114. NTSTATUS
  115. DCamSetKSStateInitialize(
  116. PDCAM_EXTENSION pDevExt
  117. )
  118. /*++
  119. Routine Description:
  120. Set KSSTATE to KSSTATE_RUN.
  121. Arguments:
  122. pDevExt -
  123. Return Value:
  124. Nothing
  125. --*/
  126. {
  127. PSTREAMEX pStrmEx;
  128. PIRB pIrb;
  129. PIRP pIrp;
  130. PDCAM_IO_CONTEXT pDCamIoContext;
  131. PIO_STACK_LOCATION NextIrpStack;
  132. NTSTATUS Status;
  133. ASSERT(pDevExt);
  134. pStrmEx = (PSTREAMEX) pDevExt->pStrmEx;
  135. if(!DCamAllocateIrbIrpAndContext(&pDCamIoContext, &pIrb, &pIrp, pDevExt->BusDeviceObject->StackSize)) {
  136. return STATUS_INSUFFICIENT_RESOURCES;
  137. }
  138. //
  139. // Initialize the device to a known state
  140. // may need to do this due to power down??
  141. //
  142. pDCamIoContext->DeviceState = DCAM_SET_INITIALIZE; // Keep track of device state that we just set.
  143. pDCamIoContext->pDevExt = pDevExt;
  144. pDCamIoContext->RegisterWorkArea.AsULONG = 0;
  145. pDCamIoContext->RegisterWorkArea.Initialize.Initialize = TRUE;
  146. pDCamIoContext->RegisterWorkArea.AsULONG = bswap(pDevExt->RegisterWorkArea.AsULONG);
  147. pIrb->FunctionNumber = REQUEST_ASYNC_WRITE;
  148. pIrb->Flags = 0;
  149. pIrb->u.AsyncWrite.DestinationAddress.IA_Destination_Offset.Off_High = INITIAL_REGISTER_SPACE_HI;
  150. pIrb->u.AsyncWrite.DestinationAddress.IA_Destination_Offset.Off_Low =
  151. pDevExt->BaseRegister + FIELDOFFSET(CAMERA_REGISTER_MAP, Initialize);
  152. pIrb->u.AsyncWrite.nNumberOfBytesToWrite = sizeof(ULONG);
  153. pIrb->u.AsyncWrite.nBlockSize = 0;
  154. pIrb->u.AsyncWrite.fulFlags = 0;
  155. InterlockedExchange(&pIrb->u.AsyncWrite.ulGeneration, pDevExt->CurrentGeneration);
  156. pIrb->u.AsyncWrite.Mdl =
  157. IoAllocateMdl(&pDCamIoContext->RegisterWorkArea, sizeof(ULONG), FALSE, FALSE, NULL);
  158. MmBuildMdlForNonPagedPool(pIrb->u.AsyncWrite.Mdl);
  159. NextIrpStack = IoGetNextIrpStackLocation(pIrp);
  160. NextIrpStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
  161. NextIrpStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_1394_CLASS;
  162. NextIrpStack->Parameters.Others.Argument1 = pIrb;
  163. IoSetCompletionRoutine(
  164. pIrp,
  165. DCamToInitializeStateCompletionRoutine,
  166. pDCamIoContext,
  167. TRUE,
  168. TRUE,
  169. TRUE
  170. );
  171. Status =
  172. IoCallDriver(
  173. pDevExt->BusDeviceObject,
  174. pIrp
  175. );
  176. return STATUS_SUCCESS;
  177. }
  178. VOID
  179. DCamBusResetNotification(
  180. IN PVOID Context
  181. )
  182. /*++
  183. Routine Description:
  184. We receive this callback notification after a bus reset and if the device is still attached.
  185. This can happen when a new device is plugged in or an existing one is removed, or due to
  186. awaken from sleep state. We will restore the device to its original streaming state by
  187. (1) Initialize the device to a known state and then
  188. (2) launch a state machine to restart streaming.
  189. We will stop the state machine if previous state has failed. This can happen if the generation
  190. count is changed before the state mahcine is completed.
  191. The freeing and realocation of isoch bandwidth and channel are done in the bus reset irp.
  192. It is passed down by stream class in SRB_UNKNOWN_DEVICE_COMMAND. This IRP is guarantee to
  193. call after this bus reset notification has returned and while the state machine is going on.
  194. This is a callback at IRQL_DPC level; there are many 1394 APIs cannot be called at this level
  195. if it does blocking using KeWaitFor*Object(). Consult 1394 docuement for the list.
  196. Arguments:
  197. Context - Pointer to the context of this registered notification.
  198. Return Value:
  199. Nothing
  200. --*/
  201. {
  202. PDCAM_EXTENSION pDevExt = (PDCAM_EXTENSION) Context;
  203. PSTREAMEX pStrmEx;
  204. NTSTATUS Status;
  205. PIRP pIrp;
  206. PIRB pIrb;
  207. if(!pDevExt) {
  208. ERROR_LOG(("DCamBusResetNotification:pDevExt is 0.\n\n"));
  209. ASSERT(pDevExt);
  210. return;
  211. }
  212. //
  213. // Check a field in the context that must be valid to make sure that it is Ok to continue.
  214. //
  215. if(!pDevExt->BusDeviceObject) {
  216. ERROR_LOG(("DCamBusResetNotification:pDevExtBusDeviceObject is 0.\n\n"));
  217. ASSERT(pDevExt->BusDeviceObject);
  218. return;
  219. }
  220. DbgMsg2(("DCamBusResetNotification: pDevExt %x, pDevExt->pStrmEx %x, pDevExt->BusDeviceObject %x\n",
  221. pDevExt, pDevExt->pStrmEx, pDevExt->BusDeviceObject));
  222. //
  223. //
  224. // Get the current generation count first
  225. //
  226. // CAUTION:
  227. // not all 1394 APIs can be called in DCamSubmitIrpSynch() if in DISPATCH_LEVEL;
  228. // Getting generation count require no blocking so it is OK.
  229. if(!DCamAllocateIrbAndIrp(&pIrb, &pIrp, pDevExt->BusDeviceObject->StackSize)) {
  230. ERROR_LOG(("DCamBusResetNotification: DcamAllocateIrbAndIrp has failed!!\n\n\n"));
  231. ASSERT(FALSE);
  232. return;
  233. }
  234. pIrb->FunctionNumber = REQUEST_GET_GENERATION_COUNT;
  235. pIrb->Flags = 0;
  236. Status = DCamSubmitIrpSynch(pDevExt, pIrp, pIrb);
  237. if(Status) {
  238. ERROR_LOG(("\'DCamBusResetNotification: Status=%x while trying to get generation number\n", Status));
  239. // Done with them; free resources.
  240. DCamFreeIrbIrpAndContext(0, pIrb, pIrp);
  241. return;
  242. }
  243. ERROR_LOG(("DCamBusResetNotification: Generation number from %d to %d\n",
  244. pDevExt->CurrentGeneration, pIrb->u.GetGenerationCount.GenerationCount));
  245. InterlockedExchange(&pDevExt->CurrentGeneration, pIrb->u.GetGenerationCount.GenerationCount);
  246. // Done with them; free resources.
  247. DCamFreeIrbIrpAndContext(0, pIrb, pIrp);
  248. pStrmEx = (PSTREAMEX) pDevExt->pStrmEx;
  249. DbgMsg2(("\'%d:%s) DCamBusResetNotification: !!! pDevExt, %x; pStrmEx, %x !!!\n",
  250. pDevExt->idxDev, pDevExt->pchVendorName, pDevExt, pStrmEx));
  251. //
  252. // If the stream was open (pStrmEx != NULL && pStrmEx->pVideoInfoHeader != NULL),
  253. // then we need to restore its streaming state.
  254. //
  255. if (pStrmEx &&
  256. pStrmEx->pVideoInfoHeader != NULL) {
  257. DbgMsg2(("\'%d:%s) DCamBusResetNotification: Stream was open; Try allocate them again.\n", pDevExt->idxDev, pDevExt->pchVendorName));
  258. } else {
  259. DbgMsg2(("DCamBusResetNotification:Stream has not open on this device. Done!\n"));
  260. return;
  261. }
  262. //
  263. // Save the original state as the final state.
  264. //
  265. if(pStrmEx)
  266. pStrmEx->KSStateFinal = pStrmEx->KSState;
  267. //
  268. // Initialize the device, and restore to its original streaming state.
  269. //
  270. //
  271. // CAUTION:
  272. // maybe need to do this only if we are recovered from power loss state.
  273. // We can move this to power management function in the future.
  274. // In the completion routine, it will invoke other function to restore its streaming state.
  275. //
  276. DCamSetKSStateInitialize(pDevExt);
  277. DbgMsg2(("\'DCamBusResetNotification: Leaving...; Task complete in the CompletionRoutine.\n"));
  278. return;
  279. }
  280. NTSTATUS
  281. DCamDetachBufferCR(
  282. IN PDEVICE_OBJECT DeviceObject,
  283. IN PIRP pIrp,
  284. IN PIRB pIrb
  285. )
  286. /*++
  287. Routine Description:
  288. Detaching a buffer has completed. Attach next buffer.
  289. Returns more processing required so the IO Manager will leave us alone
  290. Arguments:
  291. DriverObject - Pointer to driver object created by system.
  292. pIrp - Irp that just completed
  293. pIrb - Context set in DCamIsochCallback()
  294. Return Value:
  295. None.
  296. --*/
  297. {
  298. IN PISOCH_DESCRIPTOR IsochDescriptor;
  299. PDCAM_EXTENSION pDevExt;
  300. PISOCH_DESCRIPTOR_RESERVED IsochDescriptorReserved;
  301. KIRQL oldIrql;
  302. if(!pIrb) {
  303. ERROR_LOG(("\'DCamDetachBufferCR: pIrb is NULL\n"));
  304. ASSERT(pIrb);
  305. IoFreeIrp(pIrp);
  306. return (STATUS_MORE_PROCESSING_REQUIRED);
  307. }
  308. // Get IsochDescriptor from the context (pIrb)
  309. IsochDescriptor = pIrb->u.IsochDetachBuffers.pIsochDescriptor;
  310. if(!IsochDescriptor) {
  311. ERROR_LOG(("\'DCamDetachBufferCR: IsochDescriptor is NULL\n"));
  312. ASSERT(IsochDescriptor);
  313. IoFreeIrp(pIrp);
  314. return (STATUS_MORE_PROCESSING_REQUIRED);
  315. }
  316. if(pIrp->IoStatus.Status != STATUS_SUCCESS) {
  317. ERROR_LOG(("\'DCamDetachBufferCR: pIrp->IoStatus.Status(%x) != STATUS_SUCCESS\n", pIrp->IoStatus.Status));
  318. ASSERT(pIrp->IoStatus.Status == STATUS_SUCCESS);
  319. IoFreeIrp(pIrp);
  320. return STATUS_MORE_PROCESSING_REQUIRED;
  321. }
  322. // IsochDescriptorReserved->Srb->Irp->IoStatus = pIrp->IoStatus.Status;
  323. IoFreeIrp(pIrp);
  324. // Freed and should not be referenced again!
  325. IsochDescriptor->DeviceReserved[5] = 0;
  326. IsochDescriptorReserved = (PISOCH_DESCRIPTOR_RESERVED) &IsochDescriptor->DeviceReserved[0];
  327. pDevExt = (PDCAM_EXTENSION) IsochDescriptor->Context1;
  328. DbgMsg3(("\'DCamDetachBufferCR: IsochDescriptorReserved=%x; DevExt=%x\n", IsochDescriptorReserved, pDevExt));
  329. ASSERT(IsochDescriptorReserved);
  330. ASSERT(pDevExt);
  331. if(pDevExt &&
  332. IsochDescriptorReserved) {
  333. //
  334. // Indicate that the Srb should be complete
  335. //
  336. IsochDescriptorReserved->Flags |= STATE_SRB_IS_COMPLETE;
  337. IsochDescriptorReserved->Srb->Status = STATUS_SUCCESS;
  338. IsochDescriptorReserved->Srb->CommandData.DataBufferArray->DataUsed = IsochDescriptor->ulLength;
  339. IsochDescriptorReserved->Srb->ActualBytesTransferred = IsochDescriptor->ulLength;
  340. DbgMsg3(("\'DCamDetachBufferCR: Completing Srb %x\n", IsochDescriptorReserved->Srb));
  341. KeAcquireSpinLock(&pDevExt->IsochDescriptorLock, &oldIrql);
  342. RemoveEntryList(&IsochDescriptorReserved->DescriptorList); InterlockedDecrement(&pDevExt->PendingReadCount);
  343. KeReleaseSpinLock(&pDevExt->IsochDescriptorLock, oldIrql);
  344. ASSERT(IsochDescriptorReserved->Srb->StreamObject);
  345. ASSERT(IsochDescriptorReserved->Srb->Flags & SRB_HW_FLAGS_STREAM_REQUEST);
  346. StreamClassStreamNotification(
  347. StreamRequestComplete,
  348. IsochDescriptorReserved->Srb->StreamObject,
  349. IsochDescriptorReserved->Srb);
  350. // Free it here instead of in DCamCompletionRoutine.
  351. ExFreePool(IsochDescriptor);
  352. KeAcquireSpinLock(&pDevExt->IsochWaitingLock, &oldIrql);
  353. if (!IsListEmpty(&pDevExt->IsochWaitingList) && pDevExt->PendingReadCount >= MAX_BUFFERS_SUPPLIED) {
  354. //
  355. // We had someone blocked waiting for us to complete. Pull
  356. // them off the waiting list and get them running
  357. //
  358. DbgMsg3(("DCamDetachBufferCR: Dequeueing request - Read Count = %x\n", pDevExt->PendingReadCount));
  359. IsochDescriptorReserved = \
  360. (PISOCH_DESCRIPTOR_RESERVED) RemoveHeadList(
  361. &pDevExt->IsochWaitingList
  362. );
  363. KeReleaseSpinLock(&pDevExt->IsochWaitingLock, oldIrql);
  364. IsochDescriptor = \
  365. (PISOCH_DESCRIPTOR) (((PUCHAR) IsochDescriptorReserved) -
  366. FIELDOFFSET(ISOCH_DESCRIPTOR, DeviceReserved[0]));
  367. DCamReadStreamWorker(IsochDescriptorReserved->Srb, IsochDescriptor);
  368. } else {
  369. KeReleaseSpinLock(&pDevExt->IsochWaitingLock, oldIrql);
  370. }
  371. }
  372. return (STATUS_MORE_PROCESSING_REQUIRED);
  373. }
  374. VOID
  375. DCamIsochCallback(
  376. IN PDCAM_EXTENSION pDevExt,
  377. IN PISOCH_DESCRIPTOR IsochDescriptor
  378. )
  379. /*++
  380. Routine Description:
  381. Called when an Isoch Descriptor completes
  382. Arguments:
  383. pDevExt - Pointer to our DeviceExtension
  384. IsochDescriptor - IsochDescriptor that completed
  385. Return Value:
  386. Nothing
  387. --*/
  388. {
  389. PIRB pIrb;
  390. PIRP pIrp;
  391. PSTREAMEX pStrmEx;
  392. PIO_STACK_LOCATION NextIrpStack;
  393. PISOCH_DESCRIPTOR_RESERVED IsochDescriptorReserved;
  394. PKSSTREAM_HEADER pDataPacket;
  395. PKS_FRAME_INFO pFrameInfo;
  396. KIRQL oldIrql;
  397. //
  398. // Debug check to make sure we're dealing with a real IsochDescriptor
  399. //
  400. ASSERT ( IsochDescriptor );
  401. IsochDescriptorReserved = (PISOCH_DESCRIPTOR_RESERVED) &IsochDescriptor->DeviceReserved[0];
  402. //
  403. // All Pending read will be either resubmitted, or cancelled (if out of resource).
  404. //
  405. if(pDevExt->bStopIsochCallback) {
  406. ERROR_LOG(("DCamIsochCallback: bStopCallback is set. IsochDescriptor %x (and Reserved %x) is returned and not processed.\n",
  407. IsochDescriptor, IsochDescriptorReserved));
  408. return;
  409. }
  410. //
  411. // Synchronization note:
  412. //
  413. // We are competing with cancel packet routine in the
  414. // event of device removal or setting to STOP state.
  415. // which ever got the spin lock to set DEATCH_BUFFER
  416. // flag take ownership completing the Irp/IsochDescriptor.
  417. //
  418. KeAcquireSpinLock(&pDevExt->IsochDescriptorLock, &oldIrql);
  419. if(pDevExt->bDevRemoved ||
  420. (IsochDescriptorReserved->Flags & (STATE_SRB_IS_COMPLETE | STATE_DETACHING_BUFFERS)) ) {
  421. ERROR_LOG(("DCamIsochCallback: bDevRemoved || STATE_SRB_IS_COMPLETE | STATE_DETACHING_BUFFERS %x %x\n",
  422. IsochDescriptorReserved,IsochDescriptorReserved->Flags));
  423. ASSERT((!pDevExt->bDevRemoved && !(IsochDescriptorReserved->Flags & (STATE_SRB_IS_COMPLETE | STATE_DETACHING_BUFFERS))));
  424. KeReleaseSpinLock(&pDevExt->IsochDescriptorLock, oldIrql);
  425. return;
  426. }
  427. IsochDescriptorReserved->Flags |= STATE_DETACHING_BUFFERS;
  428. KeReleaseSpinLock(&pDevExt->IsochDescriptorLock, oldIrql);
  429. pStrmEx = (PSTREAMEX) pDevExt->pStrmEx;
  430. ASSERT(pStrmEx == (PSTREAMEX)IsochDescriptorReserved->Srb->StreamObject->HwStreamExtension);
  431. pStrmEx->FrameCaptured++;
  432. pStrmEx->FrameInfo.PictureNumber = pStrmEx->FrameCaptured + pStrmEx->FrameInfo.DropCount;
  433. //
  434. // Return the timestamp for the frame
  435. //
  436. pDataPacket = IsochDescriptorReserved->Srb->CommandData.DataBufferArray;
  437. pFrameInfo = (PKS_FRAME_INFO) (pDataPacket + 1);
  438. ASSERT ( pDataPacket );
  439. ASSERT ( pFrameInfo );
  440. //
  441. // Return the timestamp for the frame
  442. //
  443. pDataPacket->PresentationTime.Numerator = 1;
  444. pDataPacket->PresentationTime.Denominator = 1;
  445. pDataPacket->Duration = pStrmEx->pVideoInfoHeader->AvgTimePerFrame;
  446. //
  447. // if we have a master clock
  448. //
  449. if (pStrmEx->hMasterClock) {
  450. ULONGLONG tmStream;
  451. tmGetStreamTime(IsochDescriptorReserved->Srb, pStrmEx, &tmStream);
  452. pDataPacket->PresentationTime.Time = tmStream;
  453. pDataPacket->OptionsFlags = 0;
  454. pDataPacket->OptionsFlags |=
  455. KSSTREAM_HEADER_OPTIONSF_TIMEVALID |
  456. KSSTREAM_HEADER_OPTIONSF_DURATIONVALID |
  457. KSSTREAM_HEADER_OPTIONSF_SPLICEPOINT; // Every frame we generate is a key frame (aka SplicePoint)
  458. DbgMsg3(("\'IsochCallback: Time(%dms); P#(%d)=Cap(%d)+Drp(%d); Pend%d\n",
  459. (ULONG) tmStream/10000,
  460. (ULONG) pStrmEx->FrameInfo.PictureNumber,
  461. (ULONG) pStrmEx->FrameCaptured,
  462. (ULONG) pStrmEx->FrameInfo.DropCount,
  463. pDevExt->PendingReadCount));
  464. } else {
  465. pDataPacket->PresentationTime.Time = 0;
  466. pDataPacket->OptionsFlags &=
  467. ~(KSSTREAM_HEADER_OPTIONSF_TIMEVALID |
  468. KSSTREAM_HEADER_OPTIONSF_DURATIONVALID);
  469. }
  470. // Set additional info fields about the data captured such as:
  471. // Frames Captured
  472. // Frames Dropped
  473. // Field Polarity
  474. pStrmEx->FrameInfo.ExtendedHeaderSize = pFrameInfo->ExtendedHeaderSize;
  475. *pFrameInfo = pStrmEx->FrameInfo;
  476. #ifdef SUPPORT_RGB24
  477. // Swaps B and R or BRG24 to RGB24.
  478. // There are 640x480 pixels so 307200 swaps are needed.
  479. if(pDevExt->CurrentModeIndex == VMODE4_RGB24 && pStrmEx->pVideoInfoHeader) {
  480. PBYTE pbFrameBuffer;
  481. BYTE bTemp;
  482. ULONG i, ulLen;
  483. #ifdef USE_WDM110 // Win2000
  484. // Driver verifier flag to use this but if this is used, this driver will not load for any Win9x OS.
  485. pbFrameBuffer = (PBYTE) MmGetSystemAddressForMdlSafe(IsochDescriptorReserved->Srb->Irp->MdlAddress, NormalPagePriority);
  486. #else // Win9x
  487. pbFrameBuffer = (PBYTE) MmGetSystemAddressForMdl (IsochDescriptorReserved->Srb->Irp->MdlAddress);
  488. #endif
  489. if(pbFrameBuffer) {
  490. // calculate number of pixels
  491. ulLen = abs(pStrmEx->pVideoInfoHeader->bmiHeader.biWidth) * abs(pStrmEx->pVideoInfoHeader->bmiHeader.biHeight);
  492. ASSERT(ulLen == pStrmEx->pVideoInfoHeader->bmiHeader.biSizeImage/3);
  493. if(ulLen > pStrmEx->pVideoInfoHeader->bmiHeader.biSizeImage)
  494. ulLen = pStrmEx->pVideoInfoHeader->bmiHeader.biSizeImage/3;
  495. for (i=0; i < ulLen; i++) {
  496. // swap R and B
  497. bTemp = pbFrameBuffer[0];
  498. pbFrameBuffer[0] = pbFrameBuffer[2];
  499. pbFrameBuffer[2] = bTemp;
  500. pbFrameBuffer += 3; // next RGB24 pixel
  501. }
  502. }
  503. }
  504. #endif
  505. // Reuse the Irp and Irb
  506. pIrp = (PIRP) IsochDescriptor->DeviceReserved[5];
  507. ASSERT(pIrp);
  508. pIrb = (PIRB) IsochDescriptor->DeviceReserved[6];
  509. ASSERT(pIrb);
  510. #if DBG
  511. // Same isochdescriptor should only be callback once.
  512. ASSERT((IsochDescriptor->DeviceReserved[7] == 0x87654321));
  513. IsochDescriptor->DeviceReserved[7]++;
  514. #endif
  515. pIrb->FunctionNumber = REQUEST_ISOCH_DETACH_BUFFERS;
  516. pIrb->u.IsochDetachBuffers.hResource = pDevExt->hResource;
  517. pIrb->u.IsochDetachBuffers.nNumberOfDescriptors = 1;
  518. pIrb->u.IsochDetachBuffers.pIsochDescriptor = IsochDescriptor;
  519. NextIrpStack = IoGetNextIrpStackLocation(pIrp);
  520. NextIrpStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
  521. NextIrpStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_1394_CLASS;
  522. NextIrpStack->Parameters.Others.Argument1 = pIrb;
  523. IoSetCompletionRoutine(
  524. pIrp,
  525. DCamDetachBufferCR, // Detach complete and will attach queued buffer.
  526. pIrb,
  527. TRUE,
  528. TRUE,
  529. TRUE
  530. );
  531. IoCallDriver(pDevExt->BusDeviceObject, pIrp);
  532. }