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.

2685 lines
83 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. Stream class based WDM driver for 1934 Desktop Camera.
  16. This file contains code to handle the stream class packets.
  17. Author:
  18. Shaun Pierce 25-May-96
  19. Modified:
  20. Yee J. Wu 15-Oct-97
  21. Environment:
  22. Kernel mode only
  23. Revision History:
  24. --*/
  25. #include "strmini.h"
  26. #include "ksmedia.h"
  27. #include "1394.h"
  28. #include "wdm.h" // for DbgBreakPoint() defined in dbg.h
  29. #include "dbg.h"
  30. #include "dcamdef.h"
  31. #include "dcampkt.h"
  32. #include "strmdata.h" // stream format and data ranges; static data
  33. #include "capprop.h" // Video and camera property function prototype
  34. #define WAIT_FOR_SLOW_DEVICE
  35. #ifdef ALLOC_PRAGMA
  36. #pragma alloc_text(PAGE, DCamProcessPnpIrp)
  37. #pragma alloc_text(PAGE, DCamGetStreamInfo)
  38. #pragma alloc_text(PAGE, DCamFreeIsochResource)
  39. #pragma alloc_text(PAGE, InitializeStreamExtension)
  40. #pragma alloc_text(PAGE, DCamOpenStream)
  41. #pragma alloc_text(PAGE, DCamCloseStream)
  42. #pragma alloc_text(PAGE, AdapterCompareGUIDsAndFormatSize)
  43. #pragma alloc_text(PAGE, AdapterVerifyFormat)
  44. #pragma alloc_text(PAGE, AdapterFormatFromRange)
  45. #pragma alloc_text(PAGE, VideoGetProperty)
  46. #pragma alloc_text(PAGE, VideoGetState)
  47. #pragma alloc_text(PAGE, VideoStreamGetConnectionProperty)
  48. #pragma alloc_text(PAGE, VideoStreamGetDroppedFramesProperty)
  49. #pragma alloc_text(PAGE, VideoIndicateMasterClock)
  50. #pragma alloc_text(PAGE, DCamReceivePacket)
  51. #pragma alloc_text(PAGE, DCamChangePower)
  52. #endif
  53. void
  54. tmGetStreamTime(
  55. IN PHW_STREAM_REQUEST_BLOCK Srb,
  56. PSTREAMEX pStrmEx,
  57. ULONGLONG * ptmStream)
  58. /*++
  59. Routine Description:
  60. Query the current time used to timestamp the frame or calculating the dropped frame.
  61. This is used in IsochCallback so must be paged in always.
  62. Arguments:
  63. Srb - Pointer to Stream request block
  64. Return Value:
  65. Nothing
  66. --*/
  67. {
  68. HW_TIME_CONTEXT TimeContext;
  69. TimeContext.HwDeviceExtension = (PVOID) Srb->HwDeviceExtension;
  70. TimeContext.HwStreamObject = Srb->StreamObject;
  71. TimeContext.Function = TIME_GET_STREAM_TIME;
  72. TimeContext.Time = 0;
  73. TimeContext.SystemTime = 0;
  74. StreamClassQueryMasterClockSync(
  75. pStrmEx->hMasterClock,
  76. &TimeContext);
  77. *ptmStream = TimeContext.Time;
  78. }
  79. BOOL
  80. DCamAllocateIrbAndIrp(
  81. PIRB * ppIrb,
  82. PIRP * ppIrp,
  83. CCHAR StackSize
  84. )
  85. {
  86. // Allocate Irb and Irp
  87. *ppIrb = ExAllocatePoolWithTag(NonPagedPool, sizeof(IRB), 'macd');
  88. if(!*ppIrb) {
  89. return FALSE;
  90. }
  91. *ppIrp = IoAllocateIrp(StackSize, FALSE);
  92. if(!*ppIrp) {
  93. ExFreePool(*ppIrb);
  94. *ppIrb = NULL;
  95. return FALSE;
  96. }
  97. // Initialize IRB
  98. RtlZeroMemory(*ppIrb, sizeof(IRB));
  99. return TRUE;
  100. }
  101. BOOL
  102. DCamAllocateIrbIrpAndContext(
  103. PDCAM_IO_CONTEXT * ppDCamIoContext,
  104. PIRB * ppIrb,
  105. PIRP * ppIrp,
  106. CCHAR StackSize
  107. )
  108. {
  109. // Allocate DCamIoContext
  110. *ppDCamIoContext = ExAllocatePoolWithTag(NonPagedPool, sizeof(DCAM_IO_CONTEXT), 'macd');
  111. if(!*ppDCamIoContext) {
  112. return FALSE;
  113. }
  114. // Allocate Irb and Irp
  115. *ppIrb = ExAllocatePoolWithTag(NonPagedPool, sizeof(IRB), 'macd');
  116. if(!*ppIrb) {
  117. ExFreePool(*ppDCamIoContext);
  118. *ppDCamIoContext = NULL;
  119. return FALSE;
  120. }
  121. *ppIrp = IoAllocateIrp(StackSize, FALSE);
  122. if(!*ppIrp) {
  123. ExFreePool(*ppDCamIoContext);
  124. *ppDCamIoContext = NULL;
  125. ExFreePool(*ppIrb);
  126. *ppIrb = NULL;
  127. return FALSE;
  128. }
  129. // Initialize this context
  130. RtlZeroMemory(*ppDCamIoContext, sizeof(DCAM_IO_CONTEXT));
  131. (*ppDCamIoContext)->dwSize = sizeof(DCAM_IO_CONTEXT);
  132. (*ppDCamIoContext)->pIrb = *ppIrb;
  133. // Initialize IRB
  134. RtlZeroMemory(*ppIrb, sizeof(IRB));
  135. return TRUE;
  136. }
  137. void
  138. DCamFreeIrbIrpAndContext(
  139. PDCAM_IO_CONTEXT pDCamIoContext,
  140. PIRB pIrb,
  141. PIRP pIrp
  142. )
  143. {
  144. if(pIrp)
  145. IoFreeIrp(pIrp);
  146. if(pIrb)
  147. ExFreePool(pIrb);
  148. if(pDCamIoContext)
  149. ExFreePool(pDCamIoContext);
  150. }
  151. BOOL
  152. DCamIsoEnable(
  153. PIRB pIrb,
  154. PDCAM_EXTENSION pDevExt,
  155. BOOL Enable
  156. )
  157. /*
  158. Start or start isoch transmission by setting the ISOEnable bit.
  159. TRUE: Start transmission;
  160. FALSE: Stop transmission.
  161. */
  162. {
  163. BOOL EnableVerify;
  164. DCamRegArea RegArea;
  165. NTSTATUS Status;
  166. LARGE_INTEGER stableTime;
  167. LONG lRetries = MAX_READ_REG_RETRIES;
  168. do {
  169. RegArea.AsULONG = (Enable ? START_ISOCH_TRANSMISSION : STOP_ISOCH_TRANSMISSION);
  170. Status = DCamWriteRegister(pIrb, pDevExt, FIELDOFFSET(CAMERA_REGISTER_MAP, IsoEnable), RegArea.AsULONG);
  171. EnableVerify = DCamDeviceInUse(pIrb, pDevExt);
  172. if(!NT_SUCCESS(Status) || EnableVerify != Enable) {
  173. ERROR_LOG(("\'DCAmIsoEnable: St:%x; Enable:%d vs EnableVerify:%d\n", Status, Enable, EnableVerify));
  174. if(lRetries >= 1) {
  175. stableTime.LowPart = DCAM_REG_STABLE_DELAY;
  176. stableTime.HighPart = -1;
  177. KeDelayExecutionThread(KernelMode, TRUE, &stableTime);
  178. ERROR_LOG(("\'DCamIsoEnable: delayed and try again...\n"))
  179. }
  180. }
  181. } while (--lRetries > 0 && (!NT_SUCCESS(Status) || (EnableVerify != Enable)) );
  182. return (EnableVerify == Enable);
  183. }
  184. void
  185. DCamProcessPnpIrp(
  186. IN PHW_STREAM_REQUEST_BLOCK Srb,
  187. PIO_STACK_LOCATION IrpStack,
  188. PDCAM_EXTENSION pDevExt
  189. )
  190. /*++
  191. Routine Description:
  192. Process PnP Irp.
  193. Arguments:
  194. Srb - Pointer to Stream request block
  195. Return Value:
  196. Nothing
  197. --*/
  198. {
  199. NTSTATUS Status, StatusWait;
  200. PIRB pIrb;
  201. PIRP pIrp;
  202. PSTREAMEX pStrmEx;
  203. PAGED_CODE();
  204. switch (IrpStack->MinorFunction) {
  205. #if 1
  206. case IRP_MN_QUERY_POWER:
  207. pStrmEx = (PSTREAMEX) pDevExt->pStrmEx;
  208. ERROR_LOG(("IRP_MN_QUERY_POWER: pStrmEx:%x\n", pStrmEx));
  209. if(!pStrmEx) {
  210. Srb->Status = STATUS_SUCCESS;
  211. break;
  212. }
  213. if(pStrmEx->KSState == KSSTATE_PAUSE || pStrmEx->KSState == KSSTATE_RUN) {
  214. ERROR_LOG(("Does not support hibernation while streaming!\n"));
  215. Srb->Status = STATUS_NOT_SUPPORTED;
  216. } else {
  217. ERROR_LOG(("OK to hibernation if not streaming\n"));
  218. Srb->Status = STATUS_SUCCESS;
  219. }
  220. break;
  221. #endif
  222. case IRP_MN_BUS_RESET:
  223. //
  224. // We will realocate the resource (bandwith and channel) in IRQL PASSIVE level.
  225. //
  226. Srb->Status = STATUS_SUCCESS;
  227. Status = STATUS_SUCCESS;
  228. //
  229. // The generation count is updated in the bus reset callback notification only.
  230. // Continue iff the generation count has been updated.
  231. // Else, we are assuming another bus reset has occurred,
  232. // and we will pass to us later.
  233. //
  234. if(pDevExt->CurrentGeneration != *((PULONG) &IrpStack->Parameters.Others.Argument4)) {
  235. ERROR_LOG(("DCamProcessPnpIrp: Generation count old (%d) != new (%d); STOP!\n",
  236. pDevExt->CurrentGeneration, *((PULONG) &IrpStack->Parameters.Others.Argument4)) );
  237. break;
  238. }
  239. pStrmEx = (PSTREAMEX) pDevExt->pStrmEx;
  240. DbgMsg2(("\'%d:%s) SonyDCamProcessPnpIrp: pDevExt %x; pStrmEx %x; CurGen %d\n",
  241. pDevExt->idxDev, pDevExt->pchVendorName, pDevExt, pStrmEx, pDevExt->CurrentGeneration));
  242. //
  243. // If the stream was open (pStrmEx != NULL && pStrmEx->pVideoInfoHeader != NULL);
  244. // We need to ask controller to allocate bandwidth and channel.
  245. //
  246. if(pStrmEx &&
  247. pStrmEx->pVideoInfoHeader != NULL) {
  248. DbgMsg2(("\'%d:%s) DCamProcessPnpIrp: Stream was open so re-allocate resource.\n", pDevExt->idxDev, pDevExt->pchVendorName));
  249. // Allocate Irb
  250. pIrb = ExAllocatePoolWithTag(NonPagedPool, sizeof(IRB), 'macd');
  251. if(!pIrb) {
  252. ERROR_LOG(("\'DCamProcessPnpIrp: allocate IRB failed; insufficient resource.\n"));
  253. Srb->Status = STATUS_INSUFFICIENT_RESOURCES;
  254. break;
  255. } else {
  256. ULONG ulChannel;
  257. HANDLE hResource;
  258. pIrp = IoAllocateIrp(pDevExt->BusDeviceObject->StackSize, FALSE);
  259. if(!pIrp) {
  260. ExFreePool(pIrb);
  261. Srb->Status = STATUS_INSUFFICIENT_RESOURCES;
  262. break;
  263. }
  264. RtlZeroMemory(pIrb, sizeof(IRB));
  265. //
  266. // Bus reset will free the bandwidth but not the bandwidth structure allocated by the lower driver
  267. //
  268. if (pDevExt->hBandwidth) {
  269. DbgMsg2(("\'DCamProcessPnpIrp: Attempt to free ->hBandwidth\n"));
  270. pIrb->FunctionNumber = REQUEST_ISOCH_FREE_BANDWIDTH;
  271. pIrb->Flags = 0;
  272. pIrb->u.IsochFreeBandwidth.hBandwidth = pDevExt->hBandwidth;
  273. Status = DCamSubmitIrpSynch(pDevExt, pIrp, pIrb);
  274. if (Status) {
  275. ERROR_LOG(("DCamProcessPnpIrp: Error %x while trying to free Isoch bandwidth\n", Status));
  276. ASSERT(Status == STATUS_SUCCESS || Status == STATUS_INVALID_GENERATION);
  277. }
  278. pDevExt->hBandwidth = NULL;
  279. }
  280. //
  281. // Before we assign the new hResource, we wait for it attaching buffer to complete.
  282. // For buffer that completed with previous hResource,
  283. // It will complete with error ?
  284. //
  285. StatusWait = KeWaitForSingleObject( &pStrmEx->hMutex, Executive, KernelMode, FALSE, 0 );
  286. //
  287. // Reallocate bandwidth and channel, and resource if necessary.
  288. // IF THIS FAIL, we are consider illegally streaming, and need to STOP streaming.
  289. //
  290. ulChannel = pDevExt->IsochChannel;
  291. hResource = pDevExt->hResource;
  292. Status = DCamAllocateIsochResource(pDevExt, pIrb, FALSE);
  293. if(Status) {
  294. ERROR_LOG(("\'%d:%s) DCamProcessPnpIrp: Re-AllocateIsochResource failed! Status=%x; Treat as device removed.\n\n",
  295. pDevExt->idxDev, pDevExt->pchVendorName, Status));
  296. ASSERT(Status == STATUS_SUCCESS);
  297. //
  298. // No resource so let's treat this situation as
  299. // Device has been removed because there is no
  300. // way to restart this.
  301. // This will stop future SRB_READ until stream is STOP and RUN again.
  302. //
  303. pDevExt->bDevRemoved = TRUE;
  304. Srb->Status = STATUS_INSUFFICIENT_RESOURCES;
  305. //
  306. // Stop tranmission so it will not send data to the old channel,
  307. // which might be "owned" by other device.
  308. //
  309. if(pStrmEx->KSState == KSSTATE_RUN) {
  310. // Disable EnableISO
  311. DCamIsoEnable(pIrb, pDevExt, FALSE);
  312. }
  313. KeReleaseMutex(&pStrmEx->hMutex, FALSE);
  314. ExFreePool(pIrb);
  315. IoFreeIrp(pIrp);
  316. return;
  317. }
  318. //
  319. // If channel number change due to bus reset, we must
  320. // - continue to blocking incoming SRB_READ (with mutex)
  321. // - if RUN state, stop transmission
  322. // - detach all pending buffer(s)
  323. // - free "stale" isoch resource
  324. // - if RUN state, program device to use the new channel
  325. // - if RUN state, restart transmission
  326. //
  327. if(pDevExt->IsochChannel != ISOCH_ANY_CHANNEL &&
  328. ulChannel != pDevExt->IsochChannel) {
  329. //
  330. // Stop tranmission so it will not send data to the old channel,
  331. // which might be "owned" by other device.
  332. //
  333. if(pStrmEx->KSState == KSSTATE_RUN) {
  334. // Disable EnableISO
  335. DCamIsoEnable(pIrb, pDevExt, FALSE);
  336. }
  337. //
  338. // Detach pending packets using the hOldRources and reattached using the new hResource
  339. // Note: incoming SRB_READ is block right now.
  340. // free old resource after all pending reads are detached.
  341. //
  342. if(pDevExt->PendingReadCount > 0) {
  343. Status = DCamReSubmitPacket(hResource, pDevExt, pStrmEx, pDevExt->PendingReadCount);
  344. }
  345. //
  346. // Free "stale" isoch resource
  347. //
  348. if(pDevExt->hResource != hResource) {
  349. DbgMsg2(("DCamReSubmitPacket: Attempt to free hStaleResource %x\n", hResource));
  350. pIrb->FunctionNumber = REQUEST_ISOCH_FREE_RESOURCES;
  351. pIrb->Flags = 0;
  352. pIrb->u.IsochFreeResources.hResource = hResource;
  353. Status = DCamSubmitIrpSynch(pDevExt, pIrp, pIrb);
  354. if (Status) {
  355. ERROR_LOG(("\'DCamFreeIsochResource: Error %x while trying to free Isoch resources\n\n", Status));
  356. ASSERT(Status == STATUS_SUCCESS);
  357. }
  358. }
  359. //
  360. // Getting ready to accept callback
  361. //
  362. pDevExt->bStopIsochCallback = FALSE;
  363. //
  364. // Restore to its initial Streaming state
  365. // mainly, programming device.
  366. //
  367. DCamSetKSStateInitialize(pDevExt);
  368. }
  369. KeReleaseMutex(&pStrmEx->hMutex, FALSE);
  370. ExFreePool(pIrb);
  371. IoFreeIrp(pIrp);
  372. }
  373. }
  374. if(Status == STATUS_SUCCESS) {
  375. //
  376. // Set to last saved configuration
  377. //
  378. SetCurrentDevicePropertyValues(pDevExt, (PIRB) Srb->SRBExtension);
  379. }
  380. DbgMsg2(("\'DCamProcessPnpIrp, IRP_MN_BUS_RESET: Done, Status %x\n", Status));
  381. break;
  382. case IRP_MN_QUERY_CAPABILITIES:
  383. ERROR_LOG(("\'SonyDCamProcessPnpIrp: IRP_MN_QUERY_CAPABILITIES: Srb->Status = STATUS_NOT_IMPLEMENTED.\n"));
  384. default:
  385. Srb->Status = STATUS_NOT_IMPLEMENTED;
  386. break;
  387. }
  388. }
  389. VOID
  390. DCamChangePower(
  391. IN PHW_STREAM_REQUEST_BLOCK pSrb
  392. )
  393. /*++
  394. Routine Description:
  395. Process chnaging this device's power state.
  396. Arguments:
  397. Srb - Pointer to Stream request block
  398. Return Value:
  399. Nothing
  400. --*/
  401. {
  402. PDCAM_EXTENSION pDevExt;
  403. PSTREAMEX pStrmEx;
  404. PIO_STACK_LOCATION IrpStack = IoGetCurrentIrpStackLocation(pSrb->Irp);
  405. DEVICE_POWER_STATE DevicePowerState = pSrb->CommandData.DeviceState;
  406. PAGED_CODE();
  407. pDevExt = (PDCAM_EXTENSION) pSrb->HwDeviceExtension;
  408. DbgMsg2(("\'DCamChangePower: pSrb=%x; pDevExt=%x\n", pSrb, pDevExt));
  409. ASSERT(pDevExt != NULL);
  410. if(!pDevExt) {
  411. pSrb->Status = STATUS_INVALID_PARAMETER;
  412. ERROR_LOG(("DCamChangePower: pDevExt is NULL!\n"));
  413. return;
  414. }
  415. pStrmEx = (PSTREAMEX) pDevExt->pStrmEx;
  416. if (pStrmEx ==NULL) {
  417. pSrb->Status = STATUS_SUCCESS;
  418. pDevExt->CurrentPowerState = DevicePowerState;
  419. DbgMsg2(("DCamChangePower: pStrmEx is NULL => Stream is not open. That is Ok!!\n"));
  420. return;
  421. }
  422. //
  423. // We can honor power state change:
  424. //
  425. // D0: device is on and running
  426. // D1,D2: not implemented.
  427. // D3: device is off and not running. Device context is lost.
  428. // Power can be removed from the device.
  429. // when power is back on, we will get a bus reset.
  430. //
  431. // (0) Remove DontSuspendIfStreamsAreRunning from INF
  432. // save current state.
  433. // (1) ->D3, to PAUSE/STOP state (depends on if pending buffers can be kept by its lower driver)
  434. // (2) ->D0, to restore saved state
  435. //
  436. // We can do the above but we do not know at this point
  437. // how our client application react
  438. //
  439. if(IrpStack->MinorFunction == IRP_MN_SET_POWER) {
  440. DbgMsg2(("DCamChangePower: changin power state from %d to %d.\n", pDevExt->CurrentPowerState, DevicePowerState));
  441. pSrb->Status = STATUS_SUCCESS;
  442. if(pDevExt->CurrentPowerState != DevicePowerState) {
  443. switch (DevicePowerState) {
  444. case PowerDeviceD3: // D0->D3: save state, stop streaming and Sleep
  445. if( pDevExt->CurrentPowerState == PowerDeviceD0 ) {
  446. DbgMsg1(("DCamChangePower: Switching from D0 to D3; Save current state.\n"));
  447. // Save current state to be restored when awake
  448. pStrmEx->KSSavedState = pStrmEx->KSState;
  449. }
  450. break;
  451. case PowerDeviceD0: // to Wakeup, restore state and running
  452. if( pDevExt->CurrentPowerState == PowerDeviceD3 ) {
  453. DbgMsg1(("DCamChangePower: Switching from D3 to D0; restore state.\n"));
  454. pStrmEx->KSState = pStrmEx->KSSavedState;
  455. }
  456. break;
  457. // These state are not defined and noe used.
  458. case PowerDeviceD1:
  459. case PowerDeviceD2:
  460. default:
  461. ERROR_LOG(("DCamChangePower: Invalid PowerState %d\n", DevicePowerState));
  462. pSrb->Status = STATUS_INVALID_PARAMETER;
  463. break;
  464. }
  465. }
  466. if(pSrb->Status == STATUS_SUCCESS)
  467. pDevExt->CurrentPowerState = DevicePowerState;
  468. } else {
  469. pSrb->Status = STATUS_NOT_IMPLEMENTED;
  470. }
  471. }
  472. VOID
  473. DCamGetStreamInfo(
  474. IN PHW_STREAM_REQUEST_BLOCK Srb
  475. )
  476. /*++
  477. Routine Description:
  478. Returns the information of all streams that are supported by the driver
  479. Arguments:
  480. Srb - Pointer to Stream request block
  481. Return Value:
  482. Nothing
  483. --*/
  484. {
  485. //
  486. // pick up the pointer to the stream information data structure
  487. //
  488. PIRB pIrb;
  489. PHW_STREAM_HEADER StreamHeader = &(Srb->CommandData.StreamBuffer->StreamHeader);
  490. PDCAM_EXTENSION pDevExt = (PDCAM_EXTENSION) Srb->HwDeviceExtension;
  491. PHW_STREAM_INFORMATION StreamInfo = &(Srb->CommandData.StreamBuffer->StreamInfo);
  492. PAGED_CODE();
  493. pIrb = (PIRB) Srb->SRBExtension;
  494. //
  495. // set number of streams
  496. //
  497. ASSERT (Srb->NumberOfBytesToTransfer >=
  498. sizeof (HW_STREAM_HEADER) +
  499. sizeof (HW_STREAM_INFORMATION));
  500. //
  501. // initialize stream header
  502. //
  503. RtlZeroMemory(StreamHeader,
  504. sizeof (HW_STREAM_HEADER) +
  505. sizeof (HW_STREAM_INFORMATION));
  506. //
  507. // initialize the number of streams supported
  508. //
  509. StreamHeader->NumberOfStreams = 1;
  510. StreamHeader->SizeOfHwStreamInformation = sizeof(HW_STREAM_INFORMATION);
  511. //
  512. // set the device property info
  513. //
  514. StreamHeader->NumDevPropArrayEntries = pDevExt->ulPropSetSupported;
  515. StreamHeader->DevicePropertiesArray = &pDevExt->VideoProcAmpSet;
  516. //
  517. // Initialize the stream structure.
  518. //
  519. // Number of instances field indicates the number of concurrent streams
  520. // of this type the device can support.
  521. //
  522. StreamInfo->NumberOfPossibleInstances = 1;
  523. //
  524. // indicates the direction of data flow for this stream, relative to
  525. // the driver
  526. //
  527. StreamInfo->DataFlow = KSPIN_DATAFLOW_OUT;
  528. //
  529. // dataAccessible - Indicates whether the data is "seen" by the host
  530. // processor.
  531. //
  532. StreamInfo->DataAccessible = TRUE;
  533. //
  534. // Return number of formats and the table.
  535. // These information is collected dynamically.
  536. //
  537. StreamInfo->NumberOfFormatArrayEntries = pDevExt->ModeSupported;
  538. StreamInfo->StreamFormatsArray = &pDevExt->DCamStrmModes[0];
  539. //
  540. // set the property information for the video stream
  541. //
  542. StreamInfo->NumStreamPropArrayEntries = NUMBER_VIDEO_STREAM_PROPERTIES;
  543. StreamInfo->StreamPropertiesArray = (PKSPROPERTY_SET) VideoStreamProperties;
  544. //
  545. // set the pin name and category
  546. //
  547. StreamInfo->Name = (GUID *) &PINNAME_VIDEO_CAPTURE;
  548. StreamInfo->Category = (GUID *) &PINNAME_VIDEO_CAPTURE;
  549. //
  550. // store a pointer to the topology for the device
  551. //
  552. Srb->CommandData.StreamBuffer->StreamHeader.Topology = &Topology;
  553. //
  554. // indicate success
  555. //
  556. Srb->Status = STATUS_SUCCESS;
  557. DbgMsg2(("\'DCamGetStreamInfo: NumFormat %d, StreamFormatArray %x\n",
  558. StreamInfo->NumberOfFormatArrayEntries, StreamInfo->StreamFormatsArray));
  559. }
  560. #define TIME_ROUNDING 1000 // Give it some rounding error of 100microsec
  561. #define TIME_0750FPS (1333333+TIME_ROUNDING) // 1/7.50 * 10,000,000 (unit=100ns)
  562. #define TIME_1500FPS (666666+TIME_ROUNDING) // 1/15.0 * 10,000,000 (unit=100ns) do not round to 666667
  563. #define TIME_3000FPS (333333+TIME_ROUNDING) // 1/30.0 * 10,000,000 (unit=100ns)
  564. NTSTATUS
  565. DCamAllocateIsochResource(
  566. PDCAM_EXTENSION pDevExt,
  567. PIRB Irb,
  568. BOOL bAllocateResource
  569. )
  570. {
  571. PIRP Irp;
  572. CCHAR StackSize;
  573. ULONG ModeIndex;
  574. PSTREAMEX pStrmEx;
  575. DWORD dwAvgTimePerFrame, dwCompression;
  576. ULONG fulSpeed;
  577. NTSTATUS Status = STATUS_SUCCESS;
  578. ASSERT(pDevExt);
  579. pStrmEx = (PSTREAMEX) pDevExt->pStrmEx;
  580. ASSERT(pStrmEx);
  581. DbgMsg2(("\'DCamAllocateIsochResource: enter; pStrmEx %x; pVideoInfo %x\n", pStrmEx, pStrmEx->pVideoInfoHeader));
  582. //
  583. // Now if they're on a YUV4:2:2 format, we've gotta check what
  584. // resolution they want it at, since we support this format
  585. // but in two different resolutions (modes on the camera).
  586. //
  587. // This is the INDEX to the frame rate and resource allocation; see IsochInfoTable.
  588. // 0 : reserved
  589. // 1 : 3.75
  590. // 2 : 7.5
  591. // 3 : 15 (DEFAULT_FRAME_RATE)
  592. // 4 : 30
  593. // 5 : 60 (Not supported for Mode 1 & 3)
  594. dwAvgTimePerFrame = (DWORD) pStrmEx->pVideoInfoHeader->AvgTimePerFrame;
  595. dwCompression = (DWORD) pStrmEx->pVideoInfoHeader->bmiHeader.biCompression;
  596. // Determine the Frame rate
  597. if (dwAvgTimePerFrame > TIME_0750FPS)
  598. pDevExt->FrameRate = 1; // 3.75FPS
  599. else if (dwAvgTimePerFrame > TIME_1500FPS)
  600. pDevExt->FrameRate = 2; // 7.5FPS
  601. else if (dwAvgTimePerFrame > TIME_3000FPS)
  602. pDevExt->FrameRate = 3; // 15 FPS
  603. else
  604. pDevExt->FrameRate = 4; // 30 FPS
  605. DbgMsg2(("\'DCamAllocateIsochResource: FrameRate: %d FPS\n", (1 << (pDevExt->FrameRate-1)) * 15 / 4));
  606. // Determine the Video Mode
  607. switch(dwCompression) {
  608. #ifdef SUPPORT_YUV444
  609. case FOURCC_Y444: // Mode 0
  610. ModeIndex = VMODE0_YUV444;
  611. break;
  612. #endif
  613. case FOURCC_UYVY: // Mode 1 or 3
  614. if (pStrmEx->pVideoInfoHeader->bmiHeader.biWidth == 640 &&
  615. (pStrmEx->pVideoInfoHeader->bmiHeader.biHeight == 480 ||
  616. pStrmEx->pVideoInfoHeader->bmiHeader.biHeight == -480)) {
  617. ModeIndex = VMODE3_YUV422;
  618. // Max frame rate is 15
  619. if(pDevExt->FrameRate > 3)
  620. pDevExt->FrameRate = 3;
  621. } else
  622. ModeIndex = VMODE1_YUV422;
  623. break;
  624. #ifdef SUPPORT_YUV411
  625. case FOURCC_Y411: // Mode 2
  626. ModeIndex = VMODE2_YUV411;
  627. break;
  628. #endif
  629. #ifdef SUPPORT_RGB24
  630. case KS_BI_RGB: // = 0
  631. ModeIndex = VMODE4_RGB24;
  632. // Max frame rate is 15
  633. if(pDevExt->FrameRate > 3)
  634. pDevExt->FrameRate = 3;
  635. break;
  636. #endif
  637. #ifdef SUPPORT_YUV800
  638. case FOURCC_Y800:
  639. ModeIndex = VMODE5_YUV800;
  640. break;
  641. #endif
  642. default:
  643. Status = STATUS_NOT_IMPLEMENTED;;
  644. return Status;;
  645. }
  646. DbgMsg1(("\'DCamAllocateIsochResource: ModeIndex=%d, AvgTimePerFrame=%d, FrameRate=%d\n",
  647. ModeIndex, dwAvgTimePerFrame, pDevExt->FrameRate));
  648. //
  649. // Get an Irp so we can send some allocation commands down
  650. //
  651. StackSize = pDevExt->BusDeviceObject->StackSize;
  652. Irp = IoAllocateIrp(StackSize, FALSE);
  653. if (!Irp) {
  654. return STATUS_INSUFFICIENT_RESOURCES;
  655. }
  656. //
  657. // Calculate the index to use to reference the ISOCH table
  658. //
  659. pStrmEx->idxIsochTable = ModeIndex * NUM_POSSIBLE_RATES + pDevExt->FrameRate;
  660. ASSERT(pStrmEx->pVideoInfoHeader->bmiHeader.biSizeImage == IsochInfoTable[pStrmEx->idxIsochTable].CompletePictureSize);
  661. DbgMsg2(("\'DCamAllocateIsochResource: ModeIndex=%d, idxIsochTable=%d, biSizeImage=%d, CompletePictureSize=%d\n",
  662. ModeIndex, pStrmEx->idxIsochTable, pStrmEx->pVideoInfoHeader->bmiHeader.biSizeImage, IsochInfoTable[pStrmEx->idxIsochTable].CompletePictureSize));
  663. //
  664. // 0. Determine the MAX_SPEED and not use the speed defined in the static table.
  665. //
  666. Irb->FunctionNumber = REQUEST_GET_SPEED_BETWEEN_DEVICES;
  667. Irb->Flags = 0;
  668. Irb->u.GetMaxSpeedBetweenDevices.fulFlags = USE_LOCAL_NODE;
  669. Irb->u.GetMaxSpeedBetweenDevices.ulNumberOfDestinations = 0;
  670. Status = DCamSubmitIrpSynch(pDevExt, Irp, Irb);
  671. if(Status) {
  672. ERROR_LOG(("\'DCamAllocateIsochResource: Error %x while trying to get maximun speed between devices.\n", Status));
  673. IoFreeIrp(Irp);
  674. return STATUS_INSUFFICIENT_RESOURCES;
  675. }
  676. fulSpeed = Irb->u.GetMaxSpeedBetweenDevices.fulSpeed;
  677. //
  678. // The max speed between devices should be within supported speed range, and
  679. // must be equal or greater than the required speed for the chosen format.
  680. //
  681. if(
  682. ( fulSpeed != SPEED_FLAGS_100
  683. && fulSpeed != SPEED_FLAGS_200
  684. && fulSpeed != SPEED_FLAGS_400
  685. )
  686. || fulSpeed < IsochInfoTable[pStrmEx->idxIsochTable].SpeedRequired
  687. ) {
  688. ASSERT(fulSpeed == SPEED_FLAGS_100 || fulSpeed == SPEED_FLAGS_200 || fulSpeed == SPEED_FLAGS_400);
  689. ASSERT(fulSpeed >= IsochInfoTable[pStrmEx->idxIsochTable].SpeedRequired);
  690. IoFreeIrp(Irp);
  691. return STATUS_UNSUCCESSFUL;
  692. }
  693. pDevExt->SpeedCode = fulSpeed >> 1; // Safe for S100, 200 and 400 (is checked above).
  694. DbgMsg2(("\'GetMaxSpeedBetweenDevices.fulSpeed=%x; SpeedCode:%x\n", fulSpeed, pDevExt->SpeedCode));
  695. //
  696. // 1. Allocate CHANNEL
  697. // First try to re-allocate the same channel
  698. // If it is used, try to get any channel. 1394DCam can only be on channel 0..15
  699. //
  700. Irb->FunctionNumber = REQUEST_ISOCH_ALLOCATE_CHANNEL;
  701. Irb->Flags = 0;
  702. //
  703. // ULONG nRequestedChannel; // Need a specific channel
  704. // ULONG Channel; // Returned channel
  705. // LARGE_INTEGER ChannelsAvailable; // Channels available
  706. // Instead of hardcoded '0'; use -1 to ask the bus driver to get the next available channel for us.
  707. // -1 (any channel) or an existing channel
  708. Irb->u.IsochAllocateChannel.nRequestedChannel = pDevExt->IsochChannel;
  709. Status = DCamSubmitIrpSynch(pDevExt, Irp, Irb);
  710. if(Status) {
  711. //
  712. // Due to channel change,
  713. // all Pending read will be either resubmitted,
  714. // or cancelled (if out of resource).
  715. //
  716. pDevExt->bStopIsochCallback = TRUE; // Set back to FALSE after pending buffer are attached.
  717. //
  718. // If this is an initial request and no channel available,
  719. // free all resource and abort.
  720. //
  721. if(pDevExt->IsochChannel == ISOCH_ANY_CHANNEL)
  722. goto NoResource_abort;
  723. DbgMsg1(("DCamAllocateIsochResource: last allocated channel %d is not available; pending count %d.\n",
  724. pDevExt->IsochChannel, pDevExt->PendingReadCount));
  725. // Try gettting any channel.
  726. Irb->FunctionNumber = REQUEST_ISOCH_ALLOCATE_CHANNEL;
  727. Irb->Flags = 0;
  728. Irb->u.IsochAllocateChannel.nRequestedChannel = ISOCH_ANY_CHANNEL;
  729. Status = DCamSubmitIrpSynch(pDevExt, Irp, Irb);
  730. if(Status) {
  731. ERROR_LOG(("DCamAllocateIsochResource: allocate any channel failed, status %x!\n", Status));
  732. goto NoResource_abort;
  733. }
  734. //
  735. // Channel changed, we MUST reallocate resource.
  736. // The "stale" resrouce will be free later when
  737. // pending packet are detached.
  738. //
  739. bAllocateResource = TRUE;
  740. }
  741. DbgMsg1(("**IsochAlloc: Channel(Old) %d, requested %d, got %d, HiLo(0x%x:%x), PendingRead %d\n",
  742. pDevExt->IsochChannel,
  743. Irb->u.IsochAllocateChannel.nRequestedChannel,
  744. Irb->u.IsochAllocateChannel.Channel,
  745. Irb->u.IsochAllocateChannel.ChannelsAvailable.u.HighPart,
  746. Irb->u.IsochAllocateChannel.ChannelsAvailable.u.LowPart,
  747. pDevExt->PendingReadCount));
  748. // New channel
  749. pDevExt->IsochChannel = Irb->u.IsochAllocateChannel.Channel; // Used in allocating iso. resource and reallocation
  750. //
  751. // 2. Allocate BANDWIDTH
  752. //
  753. Irb->FunctionNumber = REQUEST_ISOCH_ALLOCATE_BANDWIDTH;
  754. Irb->Flags = 0;
  755. Irb->u.IsochAllocateBandwidth.nMaxBytesPerFrameRequested = IsochInfoTable[pStrmEx->idxIsochTable].QuadletPayloadPerPacket << 2;
  756. Irb->u.IsochAllocateBandwidth.fulSpeed = fulSpeed;
  757. Irb->u.IsochAllocateBandwidth.hBandwidth = 0;
  758. Status = DCamSubmitIrpSynch(pDevExt, Irp, Irb);
  759. if(Status) {
  760. ERROR_LOG(("DCamAllocateIsochResource: Error %x while trying to allocate Isoch bandwidth\n", Status));
  761. goto NoResource_abort;
  762. }
  763. pDevExt->hBandwidth = Irb->u.IsochAllocateBandwidth.hBandwidth;
  764. DbgMsg2(("**IsochAlloc: nMaxBytesPerFrameRequested %d, fulSpeed %d; hBandWidth 0x%x\n",
  765. IsochInfoTable[pStrmEx->idxIsochTable].QuadletPayloadPerPacket << 2, fulSpeed, pDevExt->hBandwidth));
  766. //
  767. // 3. Allocate RESOURCES
  768. // Note: after a bus reset, we need not free and re-allocate this resoruce again.
  769. //
  770. if(bAllocateResource) {
  771. Irb->FunctionNumber = REQUEST_ISOCH_ALLOCATE_RESOURCES;
  772. Irb->Flags = 0;
  773. Irb->u.IsochAllocateResources.fulSpeed = fulSpeed;
  774. Irb->u.IsochAllocateResources.nChannel = pDevExt->IsochChannel;
  775. Irb->u.IsochAllocateResources.nMaxBytesPerFrame = IsochInfoTable[pStrmEx->idxIsochTable].QuadletPayloadPerPacket << 2;
  776. // For slower frame rate use smaller quadlets
  777. // smaller frame size will use more packet to fill the same amount of data
  778. // this is why smaller frame rate actually demand more resource !!
  779. Irb->u.IsochAllocateResources.nNumberOfBuffers = MAX_BUFFERS_SUPPLIED + 1; // "+1" as a "safety"
  780. Irb->u.IsochAllocateResources.nMaxBufferSize = IsochInfoTable[pStrmEx->idxIsochTable].CompletePictureSize;
  781. if (pDevExt->HostControllerInfomation.HostCapabilities & HOST_INFO_SUPPORTS_RETURNING_ISO_HDR) {
  782. Irb->u.IsochAllocateResources.nQuadletsToStrip = 1;
  783. Irb->u.IsochAllocateResources.fulFlags = RESOURCE_USED_IN_LISTENING | RESOURCE_STRIP_ADDITIONAL_QUADLETS;
  784. } else {
  785. Irb->u.IsochAllocateResources.nQuadletsToStrip = 0;
  786. Irb->u.IsochAllocateResources.fulFlags = RESOURCE_USED_IN_LISTENING;
  787. }
  788. Irb->u.IsochAllocateResources.hResource = 0;
  789. DbgMsg2(("\'DCamAllocateIsochResource: fullSpeed(%d), nMaxBytesPerFrame(%d), nMaxBufferSize(%d)\n",
  790. Irb->u.IsochAllocateResources.fulSpeed,
  791. Irb->u.IsochAllocateResources.nMaxBytesPerFrame,
  792. Irb->u.IsochAllocateResources.nMaxBufferSize));
  793. Status = DCamSubmitIrpSynch(pDevExt, Irp, Irb);
  794. if(Status) {
  795. ERROR_LOG(("DCamAllocateIsochResource: Error %x while trying to allocate Isoch resources\n", Status));
  796. goto NoResource_abort;
  797. }
  798. pDevExt->hResource = Irb->u.IsochAllocateResources.hResource;
  799. }
  800. pDevExt->CurrentModeIndex = ModeIndex;
  801. DbgMsg2(("**IsochAlloc: hResource = %x\n", pDevExt->hResource));
  802. IoFreeIrp(Irp);
  803. return STATUS_SUCCESS;
  804. NoResource_abort:
  805. // Free bandwidth
  806. if(pDevExt->hBandwidth != NULL) {
  807. Irb->FunctionNumber = REQUEST_ISOCH_FREE_BANDWIDTH;
  808. Irb->Flags = 0;
  809. Irb->u.IsochFreeBandwidth.hBandwidth = pDevExt->hBandwidth;
  810. Status = DCamSubmitIrpSynch(pDevExt, Irp, Irb);
  811. pDevExt->hBandwidth = NULL;
  812. if(Status) {
  813. ERROR_LOG(("DCamAllocateIsochResource: Error %x while trying to free Isoch bandwidth\n", Status));
  814. }
  815. }
  816. // Free channel
  817. if (pDevExt->IsochChannel != ISOCH_ANY_CHANNEL) {
  818. Irb->FunctionNumber = REQUEST_ISOCH_FREE_CHANNEL;
  819. Irb->Flags = 0;
  820. Irb->u.IsochFreeChannel.nChannel = pDevExt->IsochChannel;
  821. Status = DCamSubmitIrpSynch(pDevExt, Irp, Irb);
  822. pDevExt->IsochChannel = ISOCH_ANY_CHANNEL; // Reset it.
  823. if(Status) {
  824. ERROR_LOG(("DCamAllocateIsochResource: Error %x while trying to free Isoch channel\n", Status));
  825. }
  826. }
  827. IoFreeIrp(Irp);
  828. return STATUS_INSUFFICIENT_RESOURCES;
  829. }
  830. NTSTATUS
  831. DCamFreeIsochResource (
  832. PDCAM_EXTENSION pDevExt,
  833. PIRB Irb,
  834. BOOL bFreeResource
  835. )
  836. /*++
  837. Routine Description:
  838. Free resource allocated in DCamAllocateIsochResource().
  839. Arguments:
  840. Srb - Pointer to Stream request block
  841. Return Value:
  842. Nothing
  843. --*/
  844. {
  845. PIRP Irp;
  846. CCHAR StackSize;
  847. NTSTATUS Status = STATUS_SUCCESS;
  848. PAGED_CODE();
  849. DbgMsg2(("\'DCamFreeIsochResource: enter; DevExt=%x, Irb=%x\n", pDevExt, Irb));
  850. ASSERT(pDevExt);
  851. ASSERT(Irb);
  852. if(Irb == 0 ||
  853. pDevExt == 0) {
  854. DbgMsg2(("\'DCamFreeIsochResource: ABORTED!\n"));
  855. return STATUS_SUCCESS;
  856. }
  857. //
  858. // Get an Irp so we can send some free commands down
  859. //
  860. StackSize = pDevExt->BusDeviceObject->StackSize;
  861. Irp = IoAllocateIrp(StackSize, FALSE);
  862. if (!Irp) {
  863. ERROR_LOG(("DCamFreeIsochResource: Error %x while trying to allocate an Irp\n\n", Status));
  864. return STATUS_INSUFFICIENT_RESOURCES;
  865. }
  866. //
  867. // 1. Free Resource
  868. //
  869. if (pDevExt->hResource && bFreeResource) {
  870. DbgMsg2(("\'DCamFreeIsochResource: Attempt to free ->hResource\n"));
  871. Irb->FunctionNumber = REQUEST_ISOCH_FREE_RESOURCES;
  872. Irb->Flags = 0;
  873. Irb->u.IsochFreeResources.hResource = pDevExt->hResource;
  874. Status = DCamSubmitIrpSynch(pDevExt, Irp, Irb);
  875. pDevExt->hResource = NULL;
  876. if (Status) {
  877. ERROR_LOG(("DCamFreeIsochResource: Error %x while trying to free Isoch resources\n\n", Status));
  878. }
  879. }
  880. //
  881. // 2. Free Channel
  882. //
  883. if (pDevExt->IsochChannel != ISOCH_ANY_CHANNEL) {
  884. DbgMsg2(("\'DCamFreeIsochResource: Attempt to free ->IsochChannel\n"));
  885. Irb->FunctionNumber = REQUEST_ISOCH_FREE_CHANNEL;
  886. Irb->Flags = 0;
  887. Irb->u.IsochFreeChannel.nChannel = pDevExt->IsochChannel;
  888. Status = DCamSubmitIrpSynch(pDevExt, Irp, Irb);
  889. pDevExt->IsochChannel = ISOCH_ANY_CHANNEL;
  890. if(Status) {
  891. ERROR_LOG(("DCamFreeIsochResource: Error %x while trying to free Isoch channel\n\n", Status));
  892. }
  893. }
  894. //
  895. // 3. Free Bandwidth
  896. //
  897. if (pDevExt->hBandwidth) {
  898. DbgMsg2(("\'DCamFreeIsochResource: Attempt to free ->hBandwidth\n"));
  899. Irb->FunctionNumber = REQUEST_ISOCH_FREE_BANDWIDTH;
  900. Irb->Flags = 0;
  901. Irb->u.IsochFreeBandwidth.hBandwidth = pDevExt->hBandwidth;
  902. Status = DCamSubmitIrpSynch(pDevExt, Irp, Irb);
  903. pDevExt->hBandwidth = NULL;
  904. if (Status) {
  905. ERROR_LOG(("DCamFreeIsochResource: Error %x while trying to free Isoch bandwidth\n", Status));
  906. }
  907. }
  908. DbgMsg2(("\'DCamFreeIsochResource: hResource = %x\n", pDevExt->hResource));
  909. IoFreeIrp(Irp);
  910. return STATUS_SUCCESS;
  911. }
  912. VOID
  913. InitializeStreamExtension(
  914. PDCAM_EXTENSION pDevExt,
  915. PHW_STREAM_OBJECT pStreamObject,
  916. PSTREAMEX pStrmEx
  917. )
  918. {
  919. PAGED_CODE();
  920. pStrmEx->hMasterClock = 0;
  921. pStrmEx->FrameInfo.ExtendedHeaderSize = sizeof(KS_FRAME_INFO);
  922. pStrmEx->FrameInfo.PictureNumber = 0;
  923. pStrmEx->FrameInfo.DropCount = 0;
  924. pStrmEx->FrameInfo.dwFrameFlags = 0;
  925. pStrmEx->FirstFrameTime = 0;
  926. pStrmEx->pVideoInfoHeader = 0;
  927. pStrmEx->KSState = KSSTATE_STOP;
  928. pStrmEx->KSSavedState = KSSTATE_STOP;
  929. KeInitializeMutex( &pStrmEx->hMutex, 0); // Level 0 and in Signal state
  930. }
  931. BOOL
  932. DCamDeviceInUse(
  933. PIRB pIrb,
  934. PDCAM_EXTENSION pDevExt
  935. )
  936. /*++
  937. Routine Description:
  938. See if this device is in used.
  939. We check ISO_ENABLE since this is the only register
  940. in a 1394DCam that we can set/get and 99%+ of time
  941. this bit is set by its owner.
  942. Arguments:
  943. pIrb - Pointer to IEEE 1394 Request Block definition (IRB)
  944. pDevExt - this device extension
  945. Return Value:
  946. TRUE: Iso_enable != 0
  947. FALSE: iso_enable == 0
  948. --*/
  949. {
  950. DCamRegArea RegArea;
  951. NTSTATUS status;
  952. LONG lRetries = MAX_READ_REG_RETRIES;
  953. // If a device is removed, it is not available.
  954. if(pDevExt->bDevRemoved)
  955. return TRUE;
  956. do {
  957. RegArea.AsULONG = 0;
  958. status = DCamReadRegister(pIrb, pDevExt, FIELDOFFSET(CAMERA_REGISTER_MAP, IsoEnable), &(RegArea.AsULONG));
  959. #if DBG
  960. if(!NT_SUCCESS(status))
  961. ERROR_LOG(("**** DCamDeviceInUse: Status %x, ISO_ENABLE %x\n", status, RegArea.AsULONG));
  962. #endif
  963. } while (--lRetries > 0 && !NT_SUCCESS(status));
  964. if(NT_SUCCESS(status))
  965. return ((RegArea.AsULONG & ISO_ENABLE_BIT) == ISO_ENABLE_BIT);
  966. // failed to query the device.
  967. return TRUE; // Assume it is in use.
  968. }
  969. VOID
  970. DCamOpenStream(
  971. IN PHW_STREAM_REQUEST_BLOCK pSrb
  972. )
  973. /*++
  974. Routine Description:
  975. Called when an OpenStream Srb request is received
  976. Arguments:
  977. pSrb - Pointer to Stream request block
  978. Return Value:
  979. Nothing
  980. --*/
  981. {
  982. PIRB Irb;
  983. ULONG nSize;
  984. PDCAM_EXTENSION pDevExt;
  985. PSTREAMEX pStrmEx;
  986. PKS_DATAFORMAT_VIDEOINFOHEADER pKSDataFormat =
  987. (PKS_DATAFORMAT_VIDEOINFOHEADER) pSrb->CommandData.OpenFormat;
  988. PKS_VIDEOINFOHEADER pVideoInfoHdrRequested =
  989. &pKSDataFormat->VideoInfoHeader;
  990. PAGED_CODE();
  991. Irb = (PIRB) pSrb->SRBExtension;
  992. pDevExt = (PDCAM_EXTENSION) pSrb->HwDeviceExtension;
  993. pStrmEx = (PSTREAMEX)pSrb->StreamObject->HwStreamExtension;
  994. DbgMsg2(("\'DCamOpenStream: >>> !!! pDevEx %x; pStrmEx %x !!!\n", pDevExt, pStrmEx));
  995. //
  996. // Cache the stream extension.
  997. //
  998. pDevExt->pStrmEx = pStrmEx;
  999. //
  1000. // default to success
  1001. //
  1002. pSrb->Status = STATUS_SUCCESS;
  1003. //
  1004. // determine which stream number is being opened. This number indicates
  1005. // the offset into the array of streaminfo structures that was filled out
  1006. // in the AdapterStreamInfo call.
  1007. //
  1008. // So:
  1009. // 0 - Video data from camera
  1010. //
  1011. switch (pSrb->StreamObject->StreamNumber) {
  1012. case 0:
  1013. //
  1014. // Make sure that this device is not in used
  1015. //
  1016. if(DCamDeviceInUse(Irb, pDevExt)) {
  1017. ERROR_LOG(("Device is in used! Open Stream fail!!\n"));
  1018. pDevExt->pStrmEx = NULL;
  1019. pSrb->Status = STATUS_UNSUCCESSFUL;
  1020. return;
  1021. }
  1022. //
  1023. // Figure out what format they're trying to open first
  1024. //
  1025. if (!AdapterVerifyFormat (pDevExt->ModeSupported, pDevExt->DCamStrmModes, pKSDataFormat, pSrb->StreamObject->StreamNumber)) {
  1026. pDevExt->pStrmEx = NULL;
  1027. ERROR_LOG(("DCamOpenStream: AdapterVerifyFormat failed.\n"));
  1028. pSrb->Status = STATUS_INVALID_PARAMETER;
  1029. return;
  1030. }
  1031. InitializeStreamExtension(pDevExt, pSrb->StreamObject, pStrmEx);
  1032. // It should already been freed by DCamCloseStream()
  1033. ASSERT(pStrmEx->pVideoInfoHeader == NULL);
  1034. ASSERT(pVideoInfoHdrRequested != (PKS_VIDEOINFOHEADER) 0);
  1035. // Use this instead of sizeof(KS_VIDEOINFOHEADER) to handle variable size structure
  1036. nSize = KS_SIZE_VIDEOHEADER (pVideoInfoHdrRequested);
  1037. pStrmEx->pVideoInfoHeader = ExAllocatePoolWithTag(NonPagedPool, nSize, 'macd');
  1038. if (pStrmEx->pVideoInfoHeader == NULL) {
  1039. ERROR_LOG(("DCamOpenStream: ExAllocatePool (->pVideoInfoHeader) failed!\n"));
  1040. ASSERT(pStrmEx->pVideoInfoHeader != NULL);
  1041. pDevExt->pStrmEx = NULL;
  1042. pSrb->Status = STATUS_INSUFFICIENT_RESOURCES;
  1043. return;
  1044. }
  1045. // Copy the VIDEOINFOHEADER requested to our storage
  1046. RtlCopyMemory(
  1047. pStrmEx->pVideoInfoHeader,
  1048. pVideoInfoHdrRequested,
  1049. nSize);
  1050. DbgMsg3(("\'DCamOpenStream: Copied biSizeImage=%d Duration=%ld (100ns)\n",
  1051. pStrmEx->pVideoInfoHeader->bmiHeader.biSizeImage, (DWORD) pStrmEx->pVideoInfoHeader->AvgTimePerFrame));
  1052. // Allocate ISOCH resource
  1053. pSrb->Status = DCamAllocateIsochResource(pDevExt, pSrb->SRBExtension, TRUE);
  1054. if (pSrb->Status) {
  1055. ERROR_LOG(("DCamOpenStream: !!!! Allocate ISOCH resource failed. CanNOT STREAM!!!!!\n"));
  1056. ExFreePool(pStrmEx->pVideoInfoHeader);
  1057. pStrmEx->pVideoInfoHeader = NULL;
  1058. pDevExt->pStrmEx = NULL;
  1059. pSrb->Status = STATUS_INSUFFICIENT_RESOURCES;
  1060. return;
  1061. }
  1062. pSrb->StreamObject->ReceiveDataPacket = (PVOID) DCamReceiveDataPacket;
  1063. pSrb->StreamObject->ReceiveControlPacket = (PVOID) DCamReceiveCtrlPacket;
  1064. // If bus reset failed and user close the stream and reopen the stream successfully,
  1065. // This must be reset !!
  1066. if(pDevExt->bDevRemoved || pDevExt->bStopIsochCallback) {
  1067. DbgMsg1(("Stream Open successful, reset bDevRemoved and bStopCallback!!\n"));
  1068. pDevExt->bStopIsochCallback = FALSE;
  1069. pDevExt->bDevRemoved = FALSE;
  1070. }
  1071. //
  1072. // initialize the stream extension data handling information
  1073. //
  1074. break;
  1075. default:
  1076. ERROR_LOG(("DCamOpenStream: Hit a non-support pSrb->StreamObject->StreamNumber (%d).\n", pSrb->StreamObject->StreamNumber));
  1077. ASSERT(FALSE);
  1078. pDevExt->pStrmEx = NULL;
  1079. pSrb->Status = STATUS_INVALID_PARAMETER;
  1080. return;
  1081. }
  1082. pSrb->StreamObject->HwClockObject.ClockSupportFlags = 0;
  1083. // We don't use DMA.
  1084. pSrb->StreamObject->Dma = FALSE;
  1085. pSrb->StreamObject->StreamHeaderMediaSpecific = sizeof(KS_FRAME_INFO);
  1086. //
  1087. // The PIO flag must be set when the mini driver will be accessing the data
  1088. // buffers passed in using logical addressing. We are not going to touch these
  1089. // buffer at all.
  1090. //
  1091. pSrb->StreamObject->Pio = FALSE;
  1092. //
  1093. // Set to last saved configuration
  1094. //
  1095. SetCurrentDevicePropertyValues(pDevExt, (PIRB) pSrb->SRBExtension);
  1096. DbgMsg1((" #OPEN_STREAM#: %s DCam, Status %x, pDevExt %x, pStrmEx %x, IsochDescriptorList is at %x\n",
  1097. pDevExt->pchVendorName, pSrb->Status, pDevExt, pDevExt->pStrmEx, &pDevExt->IsochDescriptorList));
  1098. ASSERT(pSrb->Status == STATUS_SUCCESS);
  1099. }
  1100. VOID
  1101. DCamCloseStream(
  1102. IN PHW_STREAM_REQUEST_BLOCK pSrb
  1103. )
  1104. /*++
  1105. Routine Description:
  1106. Called when an CloseStream Srb request is received. We get this when calling user
  1107. application do a CloseHandle() on the pin connection handle. This can happen after
  1108. HwUninitialize().
  1109. Arguments:
  1110. pSrb - Pointer to Stream request block
  1111. Return Value:
  1112. Nothing
  1113. --*/
  1114. {
  1115. PDCAM_EXTENSION pDevExt;
  1116. PSTREAMEX pStrmEx;
  1117. PIRB pIrb;
  1118. PAGED_CODE();
  1119. pSrb->Status = STATUS_SUCCESS;
  1120. pDevExt = (PDCAM_EXTENSION) pSrb->HwDeviceExtension;
  1121. ASSERT(pDevExt);
  1122. if(!pDevExt) {
  1123. StreamClassDeviceNotification(DeviceRequestComplete, pSrb->HwDeviceExtension, pSrb);
  1124. return;
  1125. }
  1126. pStrmEx = (PSTREAMEX)pDevExt->pStrmEx;
  1127. ASSERT(pStrmEx);
  1128. if(!pStrmEx ) {
  1129. StreamClassDeviceNotification(DeviceRequestComplete, pSrb->HwDeviceExtension, pSrb);
  1130. return;
  1131. }
  1132. //
  1133. // pDevExt->Irb might have been freed in HwUninitialize()
  1134. // due to Surprise removal; so we must use this:
  1135. //
  1136. pIrb = (PIRB) pSrb->SRBExtension;
  1137. //
  1138. // If it is still in use (setting it to stop failed?),
  1139. // we will diable ISO_ENABLE so other application can use it.
  1140. //
  1141. if(!pDevExt->bDevRemoved &&
  1142. DCamDeviceInUse(pIrb, pDevExt)) {
  1143. DbgMsg1(("DCamCloseStream: Is still in use! Disable it!\n"));
  1144. // Disable EnableISO
  1145. DCamIsoEnable(pIrb, pDevExt, FALSE);
  1146. }
  1147. //
  1148. // Save current state and free resource alllocaed in OpenStream()
  1149. //
  1150. DCamSetPropertyValuesToRegistry(pDevExt);
  1151. //
  1152. // Free Isoch resource and master clock
  1153. //
  1154. DCamFreeIsochResource (pDevExt, pIrb, TRUE);
  1155. if(pStrmEx->pVideoInfoHeader) {
  1156. ExFreePool(pStrmEx->pVideoInfoHeader);
  1157. pStrmEx->pVideoInfoHeader = NULL;
  1158. }
  1159. pStrmEx->hMasterClock = 0;
  1160. //
  1161. // If there are pening read, cancel them all.
  1162. //
  1163. if(pDevExt->PendingReadCount > 0) {
  1164. DCamCancelAllPackets(
  1165. pSrb,
  1166. pDevExt,
  1167. &pDevExt->PendingReadCount
  1168. );
  1169. pDevExt->pStrmEx = 0;
  1170. return; // SRB completed in CancelAllPackets
  1171. }
  1172. pDevExt->pStrmEx = 0;
  1173. StreamClassDeviceNotification(DeviceRequestComplete, pSrb->HwDeviceExtension, pSrb);
  1174. }
  1175. VOID
  1176. DCamTimeoutHandler(
  1177. IN PHW_STREAM_REQUEST_BLOCK pSrb
  1178. )
  1179. /*++
  1180. Routine Description:
  1181. This routine is called when a packet has been in the minidriver too long (Srb->TimeoutCounter == 0).
  1182. We will cancel the SRB if we are in the RUN state; else set ->TimeoutCounter and return.
  1183. We assume the cancel SRB is serialized and in the same order as it is read. So this timeout is
  1184. applying to the head of the queue.
  1185. Arguments:
  1186. pSrb - Pointer to Stream request block that has timeout.
  1187. Return Value:
  1188. Nothing
  1189. --*/
  1190. {
  1191. PDCAM_EXTENSION pDevExt;
  1192. PSTREAMEX pStrmEx;
  1193. // Called from StreamClass at DisptchLevel
  1194. //
  1195. // We only expect stream SRB, but not device SRB.
  1196. //
  1197. if ( (pSrb->Flags & SRB_HW_FLAGS_STREAM_REQUEST) != SRB_HW_FLAGS_STREAM_REQUEST) {
  1198. ERROR_LOG(("DCamTimeoutHandler: Device SRB %x (cmd:%x) timed out!\n", pSrb, pSrb->Command));
  1199. return;
  1200. }
  1201. //
  1202. // StreamSRB only valid if we have a stream extension
  1203. //
  1204. pDevExt = (PDCAM_EXTENSION) pSrb->HwDeviceExtension;
  1205. ASSERT(pDevExt);
  1206. pStrmEx = (PSTREAMEX) pDevExt->pStrmEx;
  1207. if(!pStrmEx) {
  1208. ERROR_LOG(("DCamTimeoutHandler: Stream SRB %x timeout with pDevExt %x, pStrmEx %x\n", pSrb, pDevExt, pStrmEx));
  1209. ASSERT(pStrmEx);
  1210. return;
  1211. }
  1212. //
  1213. // Cancel IRP only if in RUN state, BUT...
  1214. // Note: if we are TIMEOUT and in RUN state, something is terribley wrong.
  1215. // but I guess that can happen when it is being suspended;
  1216. // so we will extend the time out for all states.
  1217. //
  1218. DbgMsg2(("\'DCamTimeoutHandler: pSrb %x, %s state, PendingReadCount %d.\n",
  1219. pSrb,
  1220. pStrmEx->KSState == KSSTATE_RUN ? "RUN" :
  1221. pStrmEx->KSState == KSSTATE_PAUSE ? "PAUSE":
  1222. pStrmEx->KSState == KSSTATE_STOP ? "STOP": "Unknown",
  1223. pDevExt->PendingReadCount));
  1224. // ASSERT(pStrmEx->KSState == KSSTATE_PAUSE);
  1225. //
  1226. // Reset Timeout counter, or we are going to get this call immediately.
  1227. //
  1228. pSrb->TimeoutCounter = pSrb->TimeoutOriginal;
  1229. }
  1230. NTSTATUS
  1231. DCamStartListenCR(
  1232. IN PDEVICE_OBJECT DeviceObject,
  1233. IN PIRP pIrp,
  1234. IN PDCAM_IO_CONTEXT pDCamIoContext
  1235. )
  1236. /*++
  1237. Routine Description:
  1238. Returns more processing required so the IO Manager will leave us alone
  1239. Arguments:
  1240. DriverObject - Pointer to driver object created by system.
  1241. pIrp - Irp that just completed
  1242. pDCamIoContext - Context
  1243. Return Value:
  1244. None.
  1245. --*/
  1246. {
  1247. PDCAM_EXTENSION pDevExt;
  1248. NTSTATUS Status;
  1249. PIRB pIrb;
  1250. PIO_STACK_LOCATION NextIrpStack;
  1251. #ifdef WAIT_FOR_SLOW_DEVICE
  1252. KeStallExecutionProcessor(5000); // 5 msec
  1253. #endif
  1254. DbgMsg2(("\'DCamStartListenCR: pIrp->IoStatus.Status=%x\n", pIrp->IoStatus.Status));
  1255. if(STATUS_SUCCESS != pIrp->IoStatus.Status) {
  1256. pDevExt = pDCamIoContext->pDevExt;
  1257. pIrb = pDCamIoContext->pIrb;
  1258. if(pDevExt->lRetries > 0) {
  1259. pDevExt->lRetries--;
  1260. DbgMsg1(("DCamStartListenCR: Try DCAM_RUNSTATE_SET_REQUEST_ISOCH_LISTEN again!\n"));
  1261. pIrb->FunctionNumber = REQUEST_ISOCH_LISTEN;
  1262. pIrb->Flags = 0;
  1263. pIrb->u.IsochListen.hResource = pDevExt->hResource;
  1264. pIrb->u.IsochListen.fulFlags = 0;
  1265. NextIrpStack = IoGetNextIrpStackLocation(pIrp);
  1266. NextIrpStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
  1267. NextIrpStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_1394_CLASS;
  1268. NextIrpStack->Parameters.Others.Argument1 = pIrb;
  1269. IoSetCompletionRoutine(
  1270. pIrp,
  1271. DCamStartListenCR,
  1272. pDCamIoContext,
  1273. TRUE,
  1274. TRUE,
  1275. TRUE
  1276. );
  1277. Status =
  1278. IoCallDriver(
  1279. pDevExt->BusDeviceObject,
  1280. pIrp);
  1281. return STATUS_MORE_PROCESSING_REQUIRED;
  1282. } else {
  1283. ERROR_LOG(("Start Listening has failed Status=%x; try again in next read.\n", pIrp->IoStatus.Status));
  1284. pDCamIoContext->pDevExt->bNeedToListen = TRUE;
  1285. }
  1286. }
  1287. DCamFreeIrbIrpAndContext(pDCamIoContext, pDCamIoContext->pIrb, pIrp);
  1288. // No StreamClassDeviceNotification() here since
  1289. // this is local initiated Irb (as part of AttachBufferCR().
  1290. return STATUS_MORE_PROCESSING_REQUIRED;
  1291. }
  1292. /*
  1293. ** AdapterCompareGUIDsAndFormatSize()
  1294. **
  1295. ** Checks for a match on the three GUIDs and FormatSize
  1296. **
  1297. ** Arguments:
  1298. **
  1299. ** IN DataRange1
  1300. ** IN DataRange2
  1301. **
  1302. ** Returns:
  1303. **
  1304. ** TRUE if all elements match
  1305. ** FALSE if any are different
  1306. **
  1307. ** Side Effects: none
  1308. */
  1309. BOOL
  1310. AdapterCompareGUIDsAndFormatSize(
  1311. IN PKSDATARANGE DataRange1,
  1312. IN PKSDATARANGE DataRange2)
  1313. {
  1314. PAGED_CODE();
  1315. return (
  1316. IsEqualGUID (
  1317. &DataRange1->MajorFormat,
  1318. &DataRange2->MajorFormat) &&
  1319. IsEqualGUID (
  1320. &DataRange1->SubFormat,
  1321. &DataRange2->SubFormat) &&
  1322. IsEqualGUID (
  1323. &DataRange1->Specifier,
  1324. &DataRange2->Specifier) &&
  1325. (DataRange1->FormatSize == DataRange2->FormatSize));
  1326. }
  1327. /*
  1328. ** AdapterVerifyFormat()
  1329. **
  1330. ** Checks the validity of a format request by walking through the
  1331. ** array of supported PKSDATARANGEs for a given stream.
  1332. **
  1333. ** Arguments:
  1334. **
  1335. ** pKSDataFormatVideoToVerify - pointer of a KS_DATAFORMAT_VIDEOINFOHEADER structure.
  1336. ** StreamNumber - index of the stream being queried / opened.
  1337. **
  1338. ** Returns:
  1339. **
  1340. ** TRUE if the format is supported
  1341. ** FALSE if the format cannot be suppored
  1342. **
  1343. ** Side Effects: none
  1344. */
  1345. BOOL
  1346. AdapterVerifyFormat(
  1347. ULONG VideoModesSupported,
  1348. PKSDATAFORMAT *pDCamStrmModesSupported,
  1349. PKS_DATAFORMAT_VIDEOINFOHEADER pDataFormatVideoToVerify,
  1350. int StreamNumber)
  1351. {
  1352. PKS_VIDEOINFOHEADER pVideoInfoHdrToVerify = &pDataFormatVideoToVerify->VideoInfoHeader;
  1353. PKSDATAFORMAT *paDataFormatsVideoAvail; // an array of PKSDATAFORMAT (not PKS_DATARANGE_VIDEO !!)
  1354. PKS_DATARANGE_VIDEO pDataRangeVideo;
  1355. KS_VIDEO_STREAM_CONFIG_CAPS *pConfigCaps;
  1356. PKS_BITMAPINFOHEADER pbmiHeader,
  1357. pbmiHeaderToVerify;
  1358. int j;
  1359. PAGED_CODE();
  1360. //
  1361. // Make sure the stream index is valid
  1362. // We only has one capure pin/stream (index 0).
  1363. //
  1364. if (StreamNumber >= 1) {
  1365. return FALSE;
  1366. }
  1367. //
  1368. // Get the pointer to the array of available formats
  1369. //
  1370. paDataFormatsVideoAvail = &pDCamStrmModesSupported[0]; // &pDevExt->DCamStrmModes[0];
  1371. //
  1372. // Walk the array, searching for a match
  1373. //
  1374. for (j = 0; j < (LONG) VideoModesSupported; j++, paDataFormatsVideoAvail++) {
  1375. pDataRangeVideo = (PKS_DATARANGE_VIDEO) *paDataFormatsVideoAvail;
  1376. //
  1377. // Check for matching size, Major Type, Sub Type, and Specifier
  1378. //
  1379. //
  1380. // Check for matching size, Major Type, Sub Type, and Specifier
  1381. //
  1382. if (!IsEqualGUID (&pDataRangeVideo->DataRange.MajorFormat,
  1383. &pDataFormatVideoToVerify->DataFormat.MajorFormat)) {
  1384. DbgMsg2(("\'%d) AdapterVerifyFormat: MajorFormat mismatch!\n", j));
  1385. continue;
  1386. }
  1387. if (!IsEqualGUID (&pDataRangeVideo->DataRange.SubFormat,
  1388. &pDataFormatVideoToVerify->DataFormat.SubFormat)) {
  1389. DbgMsg2(("\'%d) AdapterVerifyFormat: SubFormat mismatch!\n", j));
  1390. continue;
  1391. }
  1392. if (!IsEqualGUID (&pDataRangeVideo->DataRange.Specifier,
  1393. &pDataFormatVideoToVerify->DataFormat.Specifier)) {
  1394. DbgMsg2(("\'%d) AdapterVerifyFormat: Specifier mismatch!\n", j));
  1395. continue;
  1396. }
  1397. if(pDataFormatVideoToVerify->DataFormat.FormatSize <
  1398. sizeof(KS_DATAFORMAT_VIDEOINFOHEADER))
  1399. continue;
  1400. //
  1401. // Only if we get here, we are certain that we are dealing with video info.
  1402. //
  1403. // We do not support scaling or cropping so the dimension
  1404. // (biWidth, biHeight, biBitCount and biCompression)
  1405. // must match.
  1406. //
  1407. pbmiHeader = &pDataRangeVideo->VideoInfoHeader.bmiHeader;
  1408. pbmiHeaderToVerify = &pDataFormatVideoToVerify->VideoInfoHeader.bmiHeader;
  1409. if(pbmiHeader->biWidth != pbmiHeaderToVerify->biWidth ||
  1410. pbmiHeader->biHeight != pbmiHeaderToVerify->biHeight ||
  1411. pbmiHeader->biBitCount != pbmiHeaderToVerify->biBitCount ||
  1412. pbmiHeader->biCompression != pbmiHeaderToVerify->biCompression
  1413. ) {
  1414. DbgMsg2(("AdapterVerifyFormat: Supported: %dx%dx%d [%x] != ToVerify: %dx%dx%d [%x]\n",
  1415. pbmiHeader->biWidth, pbmiHeader->biHeight, pbmiHeader->biBitCount, pbmiHeader->biCompression,
  1416. pbmiHeaderToVerify->biWidth, pbmiHeaderToVerify->biHeight, pbmiHeaderToVerify->biBitCount, pbmiHeaderToVerify->biCompression));
  1417. continue;
  1418. }
  1419. // biSizeImage must be to be BIG ENOUGH
  1420. if(pbmiHeaderToVerify->biSizeImage < pbmiHeader->biSizeImage) {
  1421. DbgMsg2(("AdapterVerifyFormat: biSizeImageToVerify %d < required %x\n",
  1422. pbmiHeaderToVerify->biSizeImage, pbmiHeader->biSizeImage));
  1423. continue;
  1424. }
  1425. // Frame rate needs to be within range
  1426. pConfigCaps = &pDataRangeVideo->ConfigCaps;
  1427. if(pDataFormatVideoToVerify->VideoInfoHeader.AvgTimePerFrame > pConfigCaps->MaxFrameInterval &&
  1428. pDataFormatVideoToVerify->VideoInfoHeader.AvgTimePerFrame < pConfigCaps->MinFrameInterval) {
  1429. DbgMsg2(("\'format index %d) AdapterVerifyFormat: Frame rate %ld is not within range(%ld, %ld)!\n",
  1430. j, pDataFormatVideoToVerify->VideoInfoHeader.AvgTimePerFrame,
  1431. pConfigCaps->MaxFrameInterval, pConfigCaps->MinFrameInterval));
  1432. continue;
  1433. }
  1434. //
  1435. // The format passed all of the tests, so we support it
  1436. //
  1437. DbgMsg2(("\'(format idx %d) AdapterVerifyFormat: Verify!! Width=%d, Height=%d, biBitCount=%d, biSizeImage=%d\n", j,
  1438. pbmiHeaderToVerify->biWidth, pbmiHeaderToVerify->biHeight, pbmiHeaderToVerify->biBitCount,pbmiHeaderToVerify->biSizeImage));
  1439. DbgMsg2(("AdapterVerifyFormat: AvgTimePerFrame = %ld\n", pDataFormatVideoToVerify->VideoInfoHeader.AvgTimePerFrame));
  1440. DbgMsg2(("AdapterVerifyFormat: (Max %ld\n", pConfigCaps->MaxFrameInterval));
  1441. DbgMsg2(("AdapterVerifyFormat: Min %ld)\n", pConfigCaps->MinFrameInterval));
  1442. return TRUE;
  1443. }
  1444. //
  1445. // The format requested didn't match any of our listed ranges,
  1446. // so refuse the connection.
  1447. //
  1448. DbgMsg2(("AdapterVerifyFormat: This format is not supported!\n"));
  1449. return FALSE;
  1450. }
  1451. /*
  1452. ** AdapterFormatFromRange()
  1453. **
  1454. ** Examine the given data format with many key fields and
  1455. ** return a complete data format that can be used to open a stream.
  1456. **
  1457. ** Arguments:
  1458. **
  1459. ** IN PHW_STREAM_REQUEST_BLOCK Srb
  1460. **
  1461. ** Returns:
  1462. **
  1463. ** TRUE if the format is supported
  1464. ** FALSE if the format cannot be suppored
  1465. **
  1466. ** Side Effects: none
  1467. */
  1468. BOOL
  1469. AdapterFormatFromRange(
  1470. IN PHW_STREAM_REQUEST_BLOCK Srb)
  1471. {
  1472. PDCAM_EXTENSION pDevExt = (PDCAM_EXTENSION) Srb->HwDeviceExtension;
  1473. PSTREAM_DATA_INTERSECT_INFO IntersectInfo;
  1474. PKSDATARANGE DataRange,
  1475. *pAvailableFormats; // KSDATARANGE == KSDATAFORMAT
  1476. PKS_DATARANGE_VIDEO DataRangeVideoToVerify,
  1477. DataRangeVideo;
  1478. PKS_BITMAPINFOHEADER pbmiHeader,
  1479. pbmiHeaderToVerify;
  1480. ULONG FormatSize;
  1481. BOOL MatchFound = FALSE;
  1482. ULONG j;
  1483. PAGED_CODE();
  1484. Srb->Status = STATUS_SUCCESS;
  1485. IntersectInfo = Srb->CommandData.IntersectInfo;
  1486. DataRange = IntersectInfo->DataRange;
  1487. DbgMsg2(("IntersectIfo->DataFormatBuffer=%x, size=%d\n", IntersectInfo->DataFormatBuffer, IntersectInfo->SizeOfDataFormatBuffer));
  1488. //
  1489. // Check that the stream number is valid
  1490. // We support only one capture pin/stream (index 0)
  1491. //
  1492. if (IntersectInfo->StreamNumber >= 1) {
  1493. Srb->Status = STATUS_NOT_IMPLEMENTED;
  1494. ERROR_LOG(("\'AdapterFormatFromRange: StreamNumber(=%d) is not implemented.\n", IntersectInfo->StreamNumber));
  1495. ASSERT(FALSE);
  1496. return FALSE;
  1497. }
  1498. //
  1499. // Get the pointer to the array of available formats
  1500. //
  1501. pAvailableFormats = &pDevExt->DCamStrmModes[0];
  1502. //
  1503. // Walk the formats supported by the stream searching for a match
  1504. // of the three GUIDs which together define a DATARANGE
  1505. //
  1506. DataRangeVideoToVerify = (PKS_DATARANGE_VIDEO) DataRange;
  1507. for (j = 0; j < pDevExt->ModeSupported; j++, pAvailableFormats++) {
  1508. DataRangeVideo = (PKS_DATARANGE_VIDEO) *pAvailableFormats;
  1509. //
  1510. // STREAM_DATA_INTERSECT_INFO
  1511. // [IN] ULONG StreamNumber;
  1512. // [IN] PKSDATARANGE DataRange;
  1513. // [OUT] PVOID DataFormatBuffer; // == PKS_DATAFORMAT_VIDEOINFOHEADER
  1514. // [OUT] ULONG SizeOfDataFormatBuffer;
  1515. //
  1516. //
  1517. // KS_DATAFORMAT_VIDEOINFOHEADER:
  1518. // fields marked with 'm' must match;
  1519. // marked with 'r' must within range;
  1520. // marked with 'f' is filled by us
  1521. //
  1522. // KSDATAFORMAT == KSDATARANGE
  1523. // m ULONG FormatSize;
  1524. // ULONG Flags;
  1525. // ULONG SampleSize;
  1526. // ULONG Reserved;
  1527. // m GUID MajorFormat;
  1528. // m GUID SubFormat;
  1529. // m GUID Specifier;.
  1530. // m BOOL bFixedSizeSamples; // all samples same size?
  1531. // m BOOL bTemporalCompression; // all I frames?
  1532. // m DWORD StreamDescriptionFlags; // KS_VIDEO_DESC_*
  1533. // m DWORD MemoryAllocationFlags; // KS_VIDEO_ALLOC_*
  1534. // m KS_VIDEO_STREAM_CONFIG_CAPS ConfigCaps;
  1535. // KS_VIDEOINFOHEADER
  1536. // RECT rcSource; // The bit we really want to use
  1537. // RECT rcTarget; // Where the video should go
  1538. // DWORD dwBitRate; // Approximate bit data rate
  1539. // DWORD dwBitErrorRate; // Bit error rate for this stream
  1540. // r/f REFERENCE_TIME AvgTimePerFrame; // Average time per frame (100ns units)
  1541. // KS_BITMAPINFOHEADER bmiHeader;
  1542. // DWORD biSize;
  1543. // m LONG biWidth;
  1544. // m LONG biHeight;
  1545. // WORD biPlanes;
  1546. // m WORD biBitCount;
  1547. // m DWORD biCompression;
  1548. // f DWORD biSizeImage;
  1549. // LONG biXPelsPerMeter;
  1550. // LONG biYPelsPerMeter;
  1551. // DWORD biClrUsed;
  1552. // DWORD biClrImportant;
  1553. //
  1554. // Verify that it is a VIDEO format/range.
  1555. if (!AdapterCompareGUIDsAndFormatSize((PKSDATARANGE)DataRangeVideoToVerify, (PKSDATARANGE)DataRangeVideo)) {
  1556. continue;
  1557. }
  1558. //
  1559. // It is valid video format/range; now check that the other fields match
  1560. //
  1561. if ((DataRangeVideoToVerify->bFixedSizeSamples != DataRangeVideo->bFixedSizeSamples) ||
  1562. (DataRangeVideoToVerify->bTemporalCompression != DataRangeVideo->bTemporalCompression) ||
  1563. (DataRangeVideoToVerify->StreamDescriptionFlags != DataRangeVideo->StreamDescriptionFlags) ||
  1564. (DataRangeVideoToVerify->MemoryAllocationFlags != DataRangeVideo->MemoryAllocationFlags) ||
  1565. (RtlCompareMemory (&DataRangeVideoToVerify->ConfigCaps, &DataRangeVideo->ConfigCaps, sizeof(KS_VIDEO_STREAM_CONFIG_CAPS)) != sizeof(KS_VIDEO_STREAM_CONFIG_CAPS))) {
  1566. continue;
  1567. }
  1568. //
  1569. // We do not support scaling or cropping so the dimension
  1570. // (biWidth, biHeight, biBitCount and biCompression)
  1571. // must match, and we will filled in the biSizeImage and others.
  1572. //
  1573. pbmiHeader = &DataRangeVideo->VideoInfoHeader.bmiHeader;
  1574. pbmiHeaderToVerify = &DataRangeVideoToVerify->VideoInfoHeader.bmiHeader;
  1575. if(pbmiHeader->biWidth != pbmiHeaderToVerify->biWidth ||
  1576. abs(pbmiHeader->biHeight) != abs(pbmiHeaderToVerify->biHeight) ||
  1577. pbmiHeader->biBitCount != pbmiHeaderToVerify->biBitCount ||
  1578. pbmiHeader->biCompression != pbmiHeaderToVerify->biCompression
  1579. ) {
  1580. DbgMsg1(("AdapterFormatFromRange: Supported: %dx%dx%d [%x] != ToVerify: %dx%dx%d [%x]\n",
  1581. pbmiHeader->biWidth, pbmiHeader->biHeight, pbmiHeader->biBitCount, pbmiHeader->biCompression,
  1582. pbmiHeaderToVerify->biWidth, pbmiHeaderToVerify->biHeight, pbmiHeaderToVerify->biBitCount, pbmiHeaderToVerify->biCompression));
  1583. continue;
  1584. }
  1585. // MATCH FOUND!
  1586. MatchFound = TRUE;
  1587. // KS_DATAFORMAT_VIDEOINFOHEADER
  1588. // KSDATAFORMAT DataFormat;
  1589. // KS_VIDEOINFOHEADER VideoInfoHeader;
  1590. FormatSize = sizeof (KSDATAFORMAT) + KS_SIZE_VIDEOHEADER (&DataRangeVideo->VideoInfoHeader);
  1591. //
  1592. // 1st query: Srb->ActualBytesTransferred = FormatSize
  1593. //
  1594. if(IntersectInfo->SizeOfDataFormatBuffer == 0) {
  1595. Srb->Status = STATUS_BUFFER_OVERFLOW;
  1596. // We actually have not returned this much data,
  1597. // this "size" will be used by Ksproxy to send down
  1598. // a buffer of that size in next query.
  1599. Srb->ActualBytesTransferred = FormatSize;
  1600. break;
  1601. }
  1602. //
  1603. // 2nd time: pass back the format information
  1604. //
  1605. if (IntersectInfo->SizeOfDataFormatBuffer < FormatSize) {
  1606. Srb->Status = STATUS_BUFFER_TOO_SMALL;
  1607. DbgMsg2(("IntersectInfo->SizeOfDataFormatBuffer=%d, FormatSize=%d\n", IntersectInfo->SizeOfDataFormatBuffer, FormatSize));
  1608. return FALSE;
  1609. }
  1610. //
  1611. // A match is found, Copy from our supported/matched data range and set frame rate:
  1612. // KS_DATAFORMAT_VIDEOINFOHEADER
  1613. // KSDATAFORMAT DataFormat;
  1614. // KS_VIDEOINFOHEADER VideoInfoHeader;
  1615. //
  1616. RtlCopyMemory(
  1617. &((PKS_DATAFORMAT_VIDEOINFOHEADER)IntersectInfo->DataFormatBuffer)->DataFormat,
  1618. &DataRangeVideo->DataRange,
  1619. sizeof (KSDATAFORMAT));
  1620. RtlCopyMemory(
  1621. &((PKS_DATAFORMAT_VIDEOINFOHEADER) IntersectInfo->DataFormatBuffer)->VideoInfoHeader, // KS_VIDEOINFOHEADER
  1622. &DataRangeVideo->VideoInfoHeader, // KS_VIDEOINFOHEADER
  1623. KS_SIZE_VIDEOHEADER (&DataRangeVideo->VideoInfoHeader)); // Use KS_SIZE_VIDEOHEADER() since this is variable size
  1624. //
  1625. // Special atttention to these two fields: biSizeImage and AvgTimePerFrame.
  1626. // We do not scale or stretch so biSizeImage is fixed.
  1627. // However, AvgTimePerFrame (FrameRate) can/need to be within (ConfigCaps.MinFrameInterval, ConfigCaps.MaxFrameInterval)
  1628. //
  1629. if (DataRangeVideoToVerify->VideoInfoHeader.AvgTimePerFrame > DataRangeVideoToVerify->ConfigCaps.MaxFrameInterval ||
  1630. DataRangeVideoToVerify->VideoInfoHeader.AvgTimePerFrame < DataRangeVideoToVerify->ConfigCaps.MinFrameInterval) {
  1631. ((PKS_DATAFORMAT_VIDEOINFOHEADER) IntersectInfo->DataFormatBuffer)->VideoInfoHeader.AvgTimePerFrame =
  1632. DataRangeVideo->VideoInfoHeader.AvgTimePerFrame;
  1633. DbgMsg2(("AdapterFormatFromRange: out of range; so set it to default (%ld)\n",DataRangeVideo->VideoInfoHeader.AvgTimePerFrame));
  1634. } else {
  1635. ((PKS_DATAFORMAT_VIDEOINFOHEADER) IntersectInfo->DataFormatBuffer)->VideoInfoHeader.AvgTimePerFrame =
  1636. DataRangeVideoToVerify->VideoInfoHeader.AvgTimePerFrame;
  1637. }
  1638. ((PKSDATAFORMAT)IntersectInfo->DataFormatBuffer)->FormatSize = FormatSize;
  1639. Srb->ActualBytesTransferred = FormatSize;
  1640. DbgMsg2(("AdapterFormatFromRange: match found: [%x], %dx%dx%d=%d, AvgTimePerFrame %ld\n",
  1641. pbmiHeader->biCompression, pbmiHeader->biWidth, pbmiHeader->biHeight, pbmiHeader->biBitCount, pbmiHeader->biSizeImage,
  1642. ((PKS_DATAFORMAT_VIDEOINFOHEADER) IntersectInfo->DataFormatBuffer)->VideoInfoHeader.AvgTimePerFrame));
  1643. break;
  1644. } // End of loop on all formats for this stream
  1645. if(!MatchFound) {
  1646. DbgMsg2(("AdapterFormatFromRange: No match !!\n"));
  1647. Srb->Status = STATUS_NO_MATCH;
  1648. return FALSE;
  1649. }
  1650. return TRUE;
  1651. }
  1652. BOOL
  1653. DCamBuildFormatTable(
  1654. PDCAM_EXTENSION pDevExt,
  1655. PIRB pIrb
  1656. )
  1657. /*
  1658. Description:
  1659. Query Video format and mode supported by the camera.
  1660. Return:
  1661. TRUE: support at least one mode
  1662. FALSE: failed to read mode register or do not support any mode.
  1663. */
  1664. {
  1665. // Initialize
  1666. pDevExt->ModeSupported = 0;
  1667. if(DCamGetVideoMode(pDevExt, pIrb)) {
  1668. #ifdef SUPPORT_YUV444
  1669. // Mode0: 160x120 (4:4:4)
  1670. if(pDevExt->DCamVModeInq0.VMode.Mode0 == 1 && pDevExt->DecoderDCamVModeInq0.VMode.Mode0 == 1) {
  1671. pDevExt->DCamStrmModes[pDevExt->ModeSupported] = (PKSDATAFORMAT) &DCAM_StreamMode_0;
  1672. pDevExt->ModeSupported++;
  1673. }
  1674. #endif
  1675. // Mode1: 320x240 (4:2:2)
  1676. if(pDevExt->DCamVModeInq0.VMode.Mode1 == 1 && pDevExt->DecoderDCamVModeInq0.VMode.Mode1 == 1) {
  1677. pDevExt->DCamStrmModes[pDevExt->ModeSupported] = (PKSDATAFORMAT) &DCAM_StreamMode_1;
  1678. pDevExt->ModeSupported++;
  1679. }
  1680. #ifdef SUPPORT_YUV411
  1681. // Mode2: 640x480 (4:1:1)
  1682. if(pDevExt->DCamVModeInq0.VMode.Mode2 == 1 && pDevExt->DecoderDCamVModeInq0.VMode.Mode2 == 1) {
  1683. pDevExt->DCamStrmModes[pDevExt->ModeSupported] = (PKSDATAFORMAT) &DCAM_StreamMode_2;
  1684. pDevExt->ModeSupported++;
  1685. }
  1686. #endif
  1687. // Mode3: 640x480 (4:2:2)
  1688. if(pDevExt->DCamVModeInq0.VMode.Mode3 == 1 && pDevExt->DecoderDCamVModeInq0.VMode.Mode3 == 1) {
  1689. pDevExt->DCamStrmModes[pDevExt->ModeSupported] = (PKSDATAFORMAT) &DCAM_StreamMode_3;
  1690. pDevExt->ModeSupported++;
  1691. }
  1692. #ifdef SUPPORT_RGB24
  1693. // Mode4: 640x480 (RGB24)
  1694. if(pDevExt->DCamVModeInq0.VMode.Mode4 == 1 && pDevExt->DecoderDCamVModeInq0.VMode.Mode4 == 1) {
  1695. pDevExt->DCamStrmModes[pDevExt->ModeSupported] = (PKSDATAFORMAT) &DCAM_StreamMode_4;
  1696. pDevExt->ModeSupported++;
  1697. }
  1698. #endif
  1699. #ifdef SUPPORT_YUV800
  1700. // Mode5: 640x480 (Y800)
  1701. if(pDevExt->DCamVModeInq0.VMode.Mode5 == 1 && pDevExt->DecoderDCamVModeInq0.VMode.Mode5 == 1) {
  1702. pDevExt->DCamStrmModes[pDevExt->ModeSupported] = (PKSDATAFORMAT) &DCAM_StreamMode_5;
  1703. pDevExt->ModeSupported++;
  1704. }
  1705. #endif
  1706. }
  1707. DbgMsg1(("\'Support %d modes; ->DCamStrmModes[]:%x\n", pDevExt->ModeSupported, &pDevExt->DCamStrmModes[0]));
  1708. ASSERT(pDevExt->ModeSupported > 0);
  1709. return (pDevExt->ModeSupported > 0);
  1710. }
  1711. /*
  1712. ** VideoGetProperty()
  1713. **
  1714. ** Routine to process video property requests
  1715. **
  1716. ** Arguments:
  1717. **
  1718. ** Srb - pointer to the stream request block for properties
  1719. **
  1720. ** Returns:
  1721. **
  1722. ** Side Effects: none
  1723. */
  1724. VOID
  1725. VideoGetProperty(
  1726. PHW_STREAM_REQUEST_BLOCK Srb)
  1727. {
  1728. PSTREAM_PROPERTY_DESCRIPTOR pSPD = Srb->CommandData.PropertyInfo;
  1729. // preset to success
  1730. Srb->Status = STATUS_SUCCESS;
  1731. if (IsEqualGUID (&KSPROPSETID_Connection, &pSPD->Property->Set)) {
  1732. VideoStreamGetConnectionProperty (Srb);
  1733. } else if (IsEqualGUID (&PROPSETID_VIDCAP_DROPPEDFRAMES, &pSPD->Property->Set)) {
  1734. VideoStreamGetDroppedFramesProperty (Srb);
  1735. } else {
  1736. Srb->Status = STATUS_NOT_IMPLEMENTED;
  1737. }
  1738. }
  1739. /*
  1740. ** VideoGetState()
  1741. **
  1742. ** Gets the current state of the requested stream
  1743. **
  1744. ** Arguments:
  1745. **
  1746. ** Srb - pointer to the stream request block for properties
  1747. **
  1748. ** Returns:
  1749. **
  1750. ** Side Effects: none
  1751. */
  1752. VOID
  1753. VideoGetState(
  1754. PHW_STREAM_REQUEST_BLOCK Srb)
  1755. {
  1756. PDCAM_EXTENSION pDevExt = (PDCAM_EXTENSION) Srb->HwDeviceExtension;
  1757. PSTREAMEX pStrmEx = pDevExt->pStrmEx;
  1758. PAGED_CODE();
  1759. DbgMsg2(("\'%d:%s) VideoGetState: KSSTATE=%s.\n",
  1760. pDevExt->idxDev, pDevExt->pchVendorName,
  1761. pStrmEx->KSState == KSSTATE_STOP ? "STOP" :
  1762. pStrmEx->KSState == KSSTATE_PAUSE ? "PAUSE" :
  1763. pStrmEx->KSState == KSSTATE_RUN ? "RUN" : "ACQUIRE"));
  1764. Srb->CommandData.StreamState = pStrmEx->KSState;
  1765. Srb->ActualBytesTransferred = sizeof (KSSTATE);
  1766. // A very odd rule:
  1767. // When transitioning from stop to pause, DShow tries to preroll
  1768. // the graph. Capture sources can't preroll, and indicate this
  1769. // by returning VFW_S_CANT_CUE in user mode. To indicate this
  1770. // condition from drivers, they must return ERROR_NO_DATA_DETECTED
  1771. Srb->Status = STATUS_SUCCESS;
  1772. if (pStrmEx->KSState == KSSTATE_PAUSE) {
  1773. Srb->Status = STATUS_NO_DATA_DETECTED;
  1774. }
  1775. }
  1776. VOID
  1777. VideoStreamGetConnectionProperty (
  1778. PHW_STREAM_REQUEST_BLOCK Srb)
  1779. {
  1780. PDCAM_EXTENSION pDevExt = (PDCAM_EXTENSION) Srb->HwDeviceExtension;
  1781. PSTREAM_PROPERTY_DESCRIPTOR pSPD = Srb->CommandData.PropertyInfo;
  1782. ULONG Id = pSPD->Property->Id; // index of the property
  1783. PSTREAMEX pStrmEx = (PSTREAMEX) pDevExt->pStrmEx;
  1784. ASSERT(pStrmEx == (PSTREAMEX)Srb->StreamObject->HwStreamExtension);
  1785. PAGED_CODE();
  1786. switch (Id) {
  1787. case KSPROPERTY_CONNECTION_ALLOCATORFRAMING:
  1788. if (pStrmEx->pVideoInfoHeader) {
  1789. PKSALLOCATOR_FRAMING Framing =
  1790. (PKSALLOCATOR_FRAMING) pSPD->PropertyInfo;
  1791. Framing->RequirementsFlags =
  1792. KSALLOCATOR_REQUIREMENTF_SYSTEM_MEMORY |
  1793. KSALLOCATOR_REQUIREMENTF_INPLACE_MODIFIER |
  1794. KSALLOCATOR_REQUIREMENTF_PREFERENCES_ONLY;
  1795. Framing->PoolType = PagedPool;
  1796. Framing->Frames = MAX_BUFFERS_SUPPLIED;
  1797. Framing->FrameSize = pStrmEx->pVideoInfoHeader->bmiHeader.biSizeImage;
  1798. Framing->FileAlignment = FILE_BYTE_ALIGNMENT; // 0: Basically no alignment by spec
  1799. Framing->Reserved = 0;
  1800. Srb->ActualBytesTransferred = sizeof (KSALLOCATOR_FRAMING);
  1801. Srb->Status = STATUS_SUCCESS;
  1802. DbgMsg2(("\'VideoStreamGetConnectionProperty: status=0x%x, Alignment %d, Frame %d, FrameSize %d\n",
  1803. Srb->Status, Framing->FileAlignment+1, Framing->Frames, Framing->FrameSize));
  1804. } else {
  1805. Srb->Status = STATUS_INVALID_PARAMETER;
  1806. DbgMsg2(("\'VideoStreamGetConnectionProperty: status=0x\n",Srb->Status));
  1807. }
  1808. break;
  1809. default:
  1810. ERROR_LOG(("VideoStreamGetConnectionProperty: Unsupported property id=%d\n",Id));
  1811. ASSERT(FALSE);
  1812. break;
  1813. }
  1814. }
  1815. /*
  1816. ** VideoStreamGetConnectionProperty()
  1817. **
  1818. ** Gets the current state of the requested stream
  1819. **
  1820. ** Arguments:
  1821. **
  1822. ** pSrb - pointer to the stream request block for properties
  1823. **
  1824. ** Returns:
  1825. **
  1826. ** Side Effects: none
  1827. */
  1828. VOID
  1829. VideoStreamGetDroppedFramesProperty(
  1830. PHW_STREAM_REQUEST_BLOCK Srb
  1831. )
  1832. {
  1833. PSTREAMEX pStrmEx = (PSTREAMEX)Srb->StreamObject->HwStreamExtension;
  1834. PSTREAM_PROPERTY_DESCRIPTOR pSPD = Srb->CommandData.PropertyInfo;
  1835. ULONG Id = pSPD->Property->Id; // index of the property
  1836. ULONGLONG tmStream;
  1837. PAGED_CODE();
  1838. switch (Id) {
  1839. case KSPROPERTY_DROPPEDFRAMES_CURRENT:
  1840. {
  1841. PKSPROPERTY_DROPPEDFRAMES_CURRENT_S pDroppedFrames =
  1842. (PKSPROPERTY_DROPPEDFRAMES_CURRENT_S) pSPD->PropertyInfo;
  1843. if (pStrmEx->hMasterClock) {
  1844. tmGetStreamTime(Srb, pStrmEx, &tmStream);
  1845. if (tmStream < pStrmEx->FirstFrameTime) {
  1846. DbgMsg2(("\'*DroppedFP: Tm(%dms) < 1stFrameTm(%d)\n",
  1847. (LONG) tmStream/10000, (LONG)pStrmEx->FirstFrameTime));
  1848. pDroppedFrames->DropCount = 0;
  1849. } else {
  1850. pDroppedFrames->DropCount = (tmStream - pStrmEx->FirstFrameTime)
  1851. / pStrmEx->pVideoInfoHeader->AvgTimePerFrame + 1 - pStrmEx->FrameCaptured;
  1852. }
  1853. if (pDroppedFrames->DropCount < 0)
  1854. pDroppedFrames->DropCount = 0;
  1855. } else {
  1856. pDroppedFrames->DropCount = 0;
  1857. }
  1858. // Update our drop frame here. "pDroppedFrames->DropCount" is return when a frame is returned.
  1859. if (pDroppedFrames->DropCount > pStrmEx->FrameInfo.DropCount) {
  1860. pStrmEx->FrameInfo.DropCount = pDroppedFrames->DropCount;
  1861. //pStrmEx->bDiscontinue = TRUE;
  1862. } else {
  1863. pDroppedFrames->DropCount = pStrmEx->FrameInfo.DropCount;
  1864. }
  1865. pDroppedFrames->AverageFrameSize = pStrmEx->pVideoInfoHeader->bmiHeader.biSizeImage;
  1866. pDroppedFrames->PictureNumber = pStrmEx->FrameCaptured + pDroppedFrames->DropCount;
  1867. // Correction if no picture has been successfully capture in the IsochCallback.
  1868. if (pDroppedFrames->PictureNumber < pDroppedFrames->DropCount)
  1869. pDroppedFrames->PictureNumber = pDroppedFrames->DropCount;
  1870. DbgMsg2(("\'*DroppedFP: tm(%d); Pic#(%d)=?Cap(%d)+Drp(%d)\n",
  1871. (ULONG) tmStream/10000,
  1872. (LONG) pDroppedFrames->PictureNumber,
  1873. (LONG) pStrmEx->FrameCaptured,
  1874. (LONG) pDroppedFrames->DropCount));
  1875. Srb->ActualBytesTransferred = sizeof (KSPROPERTY_DROPPEDFRAMES_CURRENT_S);
  1876. Srb->Status = STATUS_SUCCESS;
  1877. }
  1878. break;
  1879. default:
  1880. ERROR_LOG(("VideoStreamGetDroppedFramesProperty: Unsupported property id=%d\n",Id));
  1881. ASSERT(FALSE);
  1882. break;
  1883. }
  1884. }
  1885. VOID
  1886. VideoIndicateMasterClock(
  1887. PHW_STREAM_REQUEST_BLOCK Srb)
  1888. /*++
  1889. Routine Description:
  1890. Assign a master clock for this stream.
  1891. Arguments:
  1892. pSrb - Pointer to Stream request block
  1893. Return Value:
  1894. Nothing
  1895. --*/
  1896. {
  1897. PDCAM_EXTENSION pDevExt = (PDCAM_EXTENSION) Srb->HwDeviceExtension;
  1898. PSTREAMEX pStrmEx = (PSTREAMEX) pDevExt->pStrmEx;
  1899. PAGED_CODE();
  1900. ASSERT(pStrmEx == (PSTREAMEX)Srb->StreamObject->HwStreamExtension);
  1901. pStrmEx->hMasterClock = Srb->CommandData.MasterClockHandle;
  1902. DbgMsg2(("\'%d:%s)VideoIndicateMasterClock: hMasterClock = 0x%x\n", pDevExt->idxDev, pDevExt->pchVendorName, pStrmEx->hMasterClock));
  1903. }
  1904. VOID
  1905. DCamReceivePacket(
  1906. IN PHW_STREAM_REQUEST_BLOCK pSrb
  1907. )
  1908. /*++
  1909. Routine Description:
  1910. This is where most of the interesting Stream requests come to us
  1911. Arguments:
  1912. pSrb - Pointer to Stream request block
  1913. Return Value:
  1914. Nothing
  1915. --*/
  1916. {
  1917. PIO_STACK_LOCATION IrpStack;
  1918. PDCAM_EXTENSION pDevExt = (PDCAM_EXTENSION) pSrb->HwDeviceExtension;
  1919. PAGED_CODE();
  1920. pSrb->Status = STATUS_SUCCESS;
  1921. //
  1922. // Switch on the command within the Srb itself
  1923. //
  1924. switch (pSrb->Command) {
  1925. case SRB_INITIALIZE_DEVICE: // Per device
  1926. pSrb->Status = DCamHwInitialize(pSrb);
  1927. break;
  1928. case SRB_INITIALIZATION_COMPLETE:
  1929. pSrb->Status = STATUS_NOT_IMPLEMENTED;
  1930. break;
  1931. case SRB_GET_STREAM_INFO: // Per Device
  1932. //
  1933. // this is a request for the driver to enumerate requested streams
  1934. //
  1935. DCamGetStreamInfo(pSrb);
  1936. break;
  1937. case SRB_OPEN_STREAM: // Per stream
  1938. DCamOpenStream(pSrb);
  1939. break;
  1940. case SRB_CLOSE_STREAM: // Per Stream
  1941. DbgMsg1((" #CLOSE_STREAM# (%d) camera: pSrb %x, pDevExt %x, pStrmEx %x, PendingRead %d\n",
  1942. pDevExt->idxDev, pSrb, pDevExt, pDevExt->pStrmEx, pDevExt->PendingReadCount));
  1943. DCamCloseStream(pSrb);
  1944. return; // SRB will finish asynchronously in its IoCompletionRoutine if there are pending reads to cancel.
  1945. case SRB_SURPRISE_REMOVAL:
  1946. DbgMsg1((" #SURPRISE_REMOVAL# (%d) camera: pSrb %x, pDevExt %x, pStrmEx %x, PendingRead %d\n",
  1947. pDevExt->idxDev, pSrb, pDevExt, pDevExt->pStrmEx, pDevExt->PendingReadCount));
  1948. DCamSurpriseRemoval(pSrb);
  1949. return; // SRB will finish asynchronously in its IoCompletionRoutine.
  1950. case SRB_UNKNOWN_DEVICE_COMMAND:
  1951. //
  1952. // We might be interested in unknown commands if they pertain
  1953. // to bus resets. We will reallocate resource (bandwidth and
  1954. // channel) if this device is streaming.
  1955. //
  1956. IrpStack = IoGetCurrentIrpStackLocation(pSrb->Irp);
  1957. if (IrpStack->MajorFunction == IRP_MJ_PNP)
  1958. DCamProcessPnpIrp(pSrb, IrpStack, pDevExt);
  1959. else
  1960. pSrb->Status = STATUS_NOT_IMPLEMENTED;
  1961. break;
  1962. case SRB_UNINITIALIZE_DEVICE: // Per device
  1963. DbgMsg1((" #UNINITIALIZE_DEVICE# (%d) %s camera : pSrb %x, pDevExt %x, pStrmEx %x\n",
  1964. pDevExt->idxDev, pDevExt->pchVendorName, pSrb, pDevExt, pDevExt->pStrmEx));
  1965. pSrb->Status = DCamHwUnInitialize(pSrb);
  1966. break;
  1967. case SRB_GET_DATA_INTERSECTION:
  1968. //
  1969. // Return a format, given a range
  1970. //
  1971. AdapterFormatFromRange(pSrb);
  1972. StreamClassDeviceNotification(DeviceRequestComplete, pSrb->HwDeviceExtension, pSrb);
  1973. return;
  1974. case SRB_CHANGE_POWER_STATE:
  1975. DCamChangePower(pSrb);
  1976. break;
  1977. // VideoProcAmp and CameraControl requests
  1978. case SRB_GET_DEVICE_PROPERTY:
  1979. AdapterGetProperty(pSrb);
  1980. break;
  1981. case SRB_SET_DEVICE_PROPERTY:
  1982. AdapterSetProperty(pSrb);
  1983. break;
  1984. case SRB_PAGING_OUT_DRIVER:
  1985. // Once we register bus reset, we can be called at any time;
  1986. // So we cannot page out.
  1987. pSrb->Status = STATUS_NOT_IMPLEMENTED;
  1988. break;
  1989. default:
  1990. DbgMsg1(("DCamReceivePacket: entry with unknown and unsupported SRB command 0x%x\n", pSrb->Command));
  1991. //
  1992. // this is a request that we do not understand. Indicate invalid
  1993. // command and complete the request
  1994. //
  1995. pSrb->Status = STATUS_NOT_IMPLEMENTED;
  1996. break;
  1997. }
  1998. //
  1999. // NOTE:
  2000. //
  2001. // all of the commands that we do, or do not understand can all be completed
  2002. // synchronously at this point, so we can use a common callback routine here.
  2003. // If any of the above commands require asynchronous processing, this will
  2004. // have to change
  2005. //
  2006. #if DBG
  2007. if (pSrb->Status != STATUS_SUCCESS &&
  2008. pSrb->Status != STATUS_NOT_IMPLEMENTED) {
  2009. DbgMsg1(("pSrb->Command(0x%x) does not return STATUS_SUCCESS or NOT_IMPLEMENTED but 0x%x\n", pSrb->Command, pSrb->Status));
  2010. }
  2011. #endif
  2012. StreamClassDeviceNotification(DeviceRequestComplete, pSrb->HwDeviceExtension, pSrb);
  2013. }