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.

1512 lines
45 KiB

  1. /*++
  2. Copyright (C) 1999 Microsoft Corporation
  3. Module Name:
  4. stream.c
  5. Abstract
  6. MS AVC streaming filter driver
  7. Author:
  8. Yee Wu 01/27/2000
  9. Revision History:
  10. Date Who What
  11. ----------- --------- ------------------------------------------------------------
  12. 01/27/2000 YJW created
  13. --*/
  14. #include "filter.h"
  15. #include "ksmedia.h"
  16. NTSTATUS
  17. AVCStreamOpen(
  18. IN PIRP pIrp, // The Irp from its client
  19. IN struct DEVICE_EXTENSION * pDevExt,
  20. IN OUT AVCSTRM_OPEN_STRUCT * pOpenStruct
  21. )
  22. /*++
  23. Routine Description:
  24. Open a stream for a client based on the information in the OpenStruct.
  25. Arguments:
  26. Irp -
  27. The irp client sent us.
  28. pDevExt -
  29. This driver's extension.
  30. pOpenStruct-
  31. Strcture contains information on how to open this stream.
  32. The stream context allocated will be returned and this will be the context
  33. to be passed for subsequent call.
  34. Return Value:
  35. Status
  36. STATUS_SUCCESS
  37. STATUS_INVALID_PARAMETER
  38. STATUS_INSUFFICIENT_RESOURCES
  39. --*/
  40. {
  41. NTSTATUS Status;
  42. ULONG ulSizeAllocated;
  43. PAVC_STREAM_EXTENSION pAVCStrmExt;
  44. PAGED_CODE();
  45. ENTER("AVCStreamOpen");
  46. Status = STATUS_SUCCESS;
  47. // Validate open structures.
  48. if(pOpenStruct == NULL)
  49. return STATUS_INVALID_PARAMETER;
  50. if(pOpenStruct->AVCFormatInfo == NULL)
  51. return STATUS_INVALID_PARAMETER;
  52. // Validate open format.
  53. if(STATUS_SUCCESS != AVCStrmValidateFormat(pOpenStruct->AVCFormatInfo)) {
  54. TRACE(TL_STRM_ERROR,("StreamOpen: pAVCFormatInfo:%x; contain invalid data\n", pOpenStruct->AVCFormatInfo ));
  55. ASSERT(FALSE && "AVCFormatInfo contain invalid parameter!");
  56. return STATUS_INVALID_PARAMETER;
  57. }
  58. // If supported, open a stream based on this stream information.
  59. // Allocate a contiguous data strcutre for a
  60. ulSizeAllocated =
  61. sizeof(AVC_STREAM_EXTENSION) +
  62. sizeof(AVCSTRM_FORMAT_INFO) +
  63. sizeof(AVC_STREAM_DATA_STRUCT);
  64. pAVCStrmExt = (PAVC_STREAM_EXTENSION) ExAllocatePool(NonPagedPool, ulSizeAllocated);
  65. if(NULL == pAVCStrmExt) {
  66. return STATUS_INSUFFICIENT_RESOURCES;
  67. }
  68. //
  69. // Initialize stream extension:
  70. // Copy the stream format information which is continuation of the stream extension.
  71. //
  72. RtlZeroMemory(pAVCStrmExt, ulSizeAllocated);
  73. pAVCStrmExt->SizeOfThisPacket = sizeof(AVC_STREAM_EXTENSION);
  74. (PBYTE) pAVCStrmExt->pAVCStrmFormatInfo = ((PBYTE) pAVCStrmExt) + sizeof(AVC_STREAM_EXTENSION);
  75. RtlCopyMemory(pAVCStrmExt->pAVCStrmFormatInfo, pOpenStruct->AVCFormatInfo, sizeof(AVCSTRM_FORMAT_INFO));
  76. (PBYTE) pAVCStrmExt->pAVCStrmDataStruc = ((PBYTE) pAVCStrmExt->pAVCStrmFormatInfo) + sizeof(AVCSTRM_FORMAT_INFO);
  77. pAVCStrmExt->pAVCStrmDataStruc->SizeOfThisPacket = sizeof(AVC_STREAM_DATA_STRUCT);
  78. TRACE(TL_STRM_TRACE,("pAVCStrmExt:%x; pAVCStrmFormatInfo:%x; pAVCStrmDataStruc:%x\n", pAVCStrmExt, pAVCStrmExt->pAVCStrmFormatInfo, pAVCStrmExt->pAVCStrmDataStruc));
  79. pAVCStrmExt->hPlugLocal = pOpenStruct->hPlugLocal;
  80. pAVCStrmExt->DataFlow = pOpenStruct->DataFlow;
  81. pAVCStrmExt->StreamState = KSSTATE_STOP;
  82. pAVCStrmExt->IsochIsActive = FALSE;
  83. // Mutext for serialize setting stream state and accepting data packet
  84. KeInitializeMutex(&pAVCStrmExt->hMutexControl, 0);
  85. // Allocate resource for the common Request structure
  86. pAVCStrmExt->pIrpAVReq = IoAllocateIrp(pDevExt->physicalDevObj->StackSize, FALSE);
  87. if(!pAVCStrmExt->pIrpAVReq) {
  88. ExFreePool(pAVCStrmExt); pAVCStrmExt = NULL;
  89. return STATUS_INSUFFICIENT_RESOURCES;
  90. }
  91. KeInitializeMutex(&pAVCStrmExt->hMutexAVReq, 0);
  92. KeInitializeEvent(&pAVCStrmExt->hAbortDoneEvent, NotificationEvent, TRUE); // Signal!
  93. pAVCStrmExt->pDevExt = pDevExt;
  94. //
  95. // Get target device's plug handle
  96. //
  97. if(!NT_SUCCESS(Status =
  98. AVCStrmGetPlugHandle(
  99. pDevExt->physicalDevObj,
  100. pAVCStrmExt
  101. ))) {
  102. IoFreeIrp(pAVCStrmExt->pIrpAVReq); pAVCStrmExt->pIrpAVReq = NULL;
  103. ExFreePool(pAVCStrmExt); pAVCStrmExt = NULL;
  104. return Status;
  105. }
  106. //
  107. // Set stream state related flags
  108. //
  109. pAVCStrmExt->b1stNewFrameFromPauseState = TRUE;
  110. // Allocate PC resources
  111. // Queues
  112. //
  113. if(!NT_SUCCESS(Status =
  114. AVCStrmAllocateQueues(
  115. pDevExt,
  116. pAVCStrmExt,
  117. pAVCStrmExt->DataFlow,
  118. pAVCStrmExt->pAVCStrmDataStruc,
  119. pAVCStrmExt->pAVCStrmFormatInfo
  120. ))) {
  121. IoFreeIrp(pAVCStrmExt->pIrpAVReq); pAVCStrmExt->pIrpAVReq = NULL;
  122. ExFreePool(pAVCStrmExt); pAVCStrmExt = NULL;
  123. return Status;
  124. }
  125. // Return stream extension
  126. pOpenStruct->AVCStreamContext = pAVCStrmExt;
  127. TRACE(TL_STRM_TRACE,("Open: AVCStreamContext:%x\n", pOpenStruct->AVCStreamContext));
  128. // Cache it. This stream extension will be the context that will be
  129. // check when we are asked to provide service.
  130. pDevExt->NumberOfStreams++; pDevExt->pAVCStrmExt[pDevExt->NextStreamIndex] = pAVCStrmExt;
  131. pDevExt->NextStreamIndex = ((pDevExt->NextStreamIndex + 1) % MAX_STREAMS_PER_DEVICE);
  132. return Status;
  133. }
  134. NTSTATUS
  135. AVCStreamClose(
  136. IN PIRP pIrp, // The Irp from its client
  137. IN struct DEVICE_EXTENSION * pDevExt,
  138. IN PAVC_STREAM_EXTENSION pAVCStrmExt
  139. )
  140. /*++
  141. Routine Description:
  142. Close a stream.
  143. Arguments:
  144. Irp -
  145. The irp client sent us.
  146. pDevExt -
  147. This driver's extension.
  148. pAVCStrmExt -
  149. The stream context created when a stream is open.
  150. pOpenStruct-
  151. Strcture contains information on how to open this stream.
  152. The stream context allocated will be returned and this will be the context
  153. to be passed for subsequent call.
  154. Return Value:
  155. Status
  156. STATUS_SUCCESS
  157. STATUS_INVALID_PARAMETER
  158. --*/
  159. {
  160. NTSTATUS Status;
  161. BOOL Found;
  162. ULONG i;
  163. PAGED_CODE();
  164. ENTER("AVCStreamClose");
  165. Status = STATUS_SUCCESS;
  166. Found = FALSE;
  167. for (i=0; i < MAX_STREAMS_PER_DEVICE; i++) {
  168. // Free stream extension
  169. if(pDevExt->pAVCStrmExt[i] == pAVCStrmExt) {
  170. Found = TRUE;
  171. break;
  172. }
  173. }
  174. if(!Found) {
  175. TRACE(TL_STRM_ERROR,("AVCStreamClose: pAVCStrmExt %x not found; pDevExt:%x\n", pAVCStrmExt, pDevExt));
  176. ASSERT(Found && "pAVCStrmExt not found!\n");
  177. return STATUS_INVALID_PARAMETER;
  178. }
  179. // Stop stream if not already
  180. if(pAVCStrmExt->StreamState != KSSTATE_STOP) {
  181. // Stop isoch if necessary and then Cancel all pending IOs
  182. AVCStrmCancelIO(pDevExt->physicalDevObj, pAVCStrmExt);
  183. }
  184. // Free queue allocated if they are not being used.
  185. if(NT_SUCCESS(Status = AVCStrmFreeQueues(pAVCStrmExt->pAVCStrmDataStruc))) {
  186. ExFreePool(pAVCStrmExt); pDevExt->pAVCStrmExt[i] = NULL; pDevExt->NumberOfStreams--;
  187. } else {
  188. TRACE(TL_STRM_ERROR,("*** StreamClose: AVCStrmExt is not freed!\n"));
  189. }
  190. return Status;
  191. }
  192. NTSTATUS
  193. AVCStreamControlGetState(
  194. IN PIRP pIrp, // The Irp from its client
  195. IN struct DEVICE_EXTENSION * pDevExt,
  196. IN PAVC_STREAM_EXTENSION pAVCStrmExt,
  197. OUT KSSTATE * pKSState
  198. )
  199. /*++
  200. Routine Description:
  201. Get current stream state
  202. Arguments:
  203. Irp -
  204. The irp client sent us.
  205. pDevExt -
  206. This driver's extension.
  207. pAVCStrmExt -
  208. The stream context created when a stream is open.
  209. pKSState -
  210. Get current stream state and return.
  211. Return Value:
  212. Status
  213. STATUS_SUCCESS
  214. STATUS_INVALID_PARAMETER
  215. --*/
  216. {
  217. NTSTATUS Status;
  218. PAGED_CODE();
  219. ENTER("AVCStreamControlGetState");
  220. Status = STATUS_SUCCESS;
  221. *pKSState = pAVCStrmExt->StreamState;
  222. return Status;
  223. }
  224. NTSTATUS
  225. AVCStreamControlSetState(
  226. IN PIRP pIrp, // The Irp from its client
  227. IN struct DEVICE_EXTENSION * pDevExt,
  228. IN PAVC_STREAM_EXTENSION pAVCStrmExt,
  229. IN KSSTATE KSState
  230. )
  231. /*++
  232. Routine Description:
  233. Set to a new stream state
  234. Arguments:
  235. Irp -
  236. The irp client sent us.
  237. pDevExt -
  238. This driver's extension.
  239. pAVCStrmExt -
  240. The stream context created when a stream is open.
  241. pKSState -
  242. Get current stream state.
  243. Return Value:
  244. Status
  245. STATUS_SUCCESS
  246. STATUS_INVALID_PARAMETER
  247. --*/
  248. {
  249. NTSTATUS Status;
  250. PAGED_CODE();
  251. ENTER("AVCStreamControlSetState");
  252. TRACE(TL_STRM_WARNING,("Set stream state %d -> %d\n", pAVCStrmExt->StreamState, KSState));
  253. if(pAVCStrmExt->StreamState == KSState)
  254. return STATUS_SUCCESS;
  255. Status = STATUS_SUCCESS;
  256. switch (KSState) {
  257. case KSSTATE_STOP:
  258. if(pAVCStrmExt->StreamState != KSSTATE_STOP) {
  259. KeWaitForMutexObject(&pAVCStrmExt->hMutexControl, Executive, KernelMode, FALSE, NULL);
  260. // Once this is set, data stream will reject SRB_WRITE/READ_DATA
  261. pAVCStrmExt->StreamState = KSSTATE_STOP;
  262. KeReleaseMutex(&pAVCStrmExt->hMutexControl, FALSE);
  263. // Cancel all pending IOs
  264. AVCStrmCancelIO(pDevExt->physicalDevObj, pAVCStrmExt);
  265. // Breeak Isoch connection
  266. AVCStrmBreakConnection(pDevExt->physicalDevObj, pAVCStrmExt);
  267. }
  268. break;
  269. case KSSTATE_ACQUIRE:
  270. // Get Isoch resource
  271. if(pAVCStrmExt->StreamState == KSSTATE_STOP) {
  272. //
  273. // Reset values.for the case that the graph restart
  274. //
  275. pAVCStrmExt->pAVCStrmDataStruc->CurrentStreamTime = 0;
  276. pAVCStrmExt->pAVCStrmDataStruc->FramesProcessed = 0;
  277. pAVCStrmExt->pAVCStrmDataStruc->FramesDropped = 0;
  278. pAVCStrmExt->pAVCStrmDataStruc->cntFrameCancelled = 0;
  279. #if DBG
  280. pAVCStrmExt->pAVCStrmDataStruc->FramesAttached = 0;
  281. #endif
  282. pAVCStrmExt->pAVCStrmDataStruc->cntDataReceived = 0;
  283. // All the list should be initialized (count:0, and List is empty)
  284. TRACE(TL_STRM_TRACE,("Set to ACQUIRE state: flow %d; AQD [%d:%d:%d]\n", pAVCStrmExt->DataFlow,
  285. pAVCStrmExt->pAVCStrmDataStruc->cntDataAttached, pAVCStrmExt->pAVCStrmDataStruc->cntDataQueued, pAVCStrmExt->pAVCStrmDataStruc->cntDataDetached));
  286. ASSERT(pAVCStrmExt->pAVCStrmDataStruc->cntDataAttached == 0 && IsListEmpty(&pAVCStrmExt->pAVCStrmDataStruc->DataAttachedListHead));
  287. ASSERT(pAVCStrmExt->pAVCStrmDataStruc->cntDataQueued == 0 && IsListEmpty(&pAVCStrmExt->pAVCStrmDataStruc->DataQueuedListHead));
  288. ASSERT(pAVCStrmExt->pAVCStrmDataStruc->cntDataDetached > 0 && !IsListEmpty(&pAVCStrmExt->pAVCStrmDataStruc->DataDetachedListHead));
  289. // Cannot stream using previous stream data !!!
  290. if(pAVCStrmExt->pAVCStrmDataStruc->cntDataAttached != 0 || // Stale data ??
  291. pAVCStrmExt->pAVCStrmDataStruc->cntDataQueued != 0 || // NO data unil PAUSE ??
  292. pAVCStrmExt->pAVCStrmDataStruc->cntDataDetached == 0) { // NO avaialble queue ?
  293. TRACE(TL_STRM_ERROR,("Set to ACQUIRE State: queues not empty (stale data?); Failed!\n"));
  294. return STATUS_UNSUCCESSFUL;
  295. }
  296. //
  297. // Make connection
  298. //
  299. Status =
  300. AVCStrmMakeConnection(
  301. pDevExt->physicalDevObj,
  302. pAVCStrmExt
  303. );
  304. if(!NT_SUCCESS(Status)) {
  305. TRACE(TL_STRM_ERROR,("Acquire failed:%x\n", Status));
  306. ASSERT(NT_SUCCESS(Status));
  307. //
  308. // Change to generic insufficient resource status.
  309. //
  310. Status = STATUS_INSUFFICIENT_RESOURCES;
  311. //
  312. // Note: even setting to this state failed, KSSTATE_PAUSE will still be called;
  313. // Since hConnect is NULL, STATUS_INSUFFICIENT_RESOURCES will be returned.
  314. //
  315. }
  316. else {
  317. //
  318. // Can verify connection by query the plug state
  319. //
  320. Status =
  321. AVCStrmGetPlugState(
  322. pDevExt->physicalDevObj,
  323. pAVCStrmExt
  324. );
  325. if(NT_SUCCESS(Status)) {
  326. ASSERT(pAVCStrmExt->RemotePlugState.BC_Connections == 1 || pAVCStrmExt->RemotePlugState.PP_Connections > 0);
  327. }
  328. else {
  329. ASSERT(NT_SUCCESS(Status) && "Failed to get Plug State");
  330. }
  331. }
  332. }
  333. break;
  334. case KSSTATE_PAUSE:
  335. if(pAVCStrmExt->hConnect == NULL) {
  336. // Cannot stream without connection!
  337. // failed to get hConnect at ACQUIRE state.
  338. Status = STATUS_INSUFFICIENT_RESOURCES;
  339. break;
  340. }
  341. // The system time (1394 CycleTime) will reset when enter PAUSE state.
  342. if(pAVCStrmExt->StreamState != KSSTATE_PAUSE) {
  343. pAVCStrmExt->b1stNewFrameFromPauseState = TRUE;
  344. pAVCStrmExt->pAVCStrmDataStruc->PictureNumber = 0;
  345. }
  346. if(pAVCStrmExt->StreamState == KSSTATE_ACQUIRE ||
  347. pAVCStrmExt->StreamState == KSSTATE_STOP) {
  348. }
  349. else if (pAVCStrmExt->StreamState == KSSTATE_RUN) {
  350. //
  351. // Stop isoch transfer
  352. //
  353. AVCStrmStopIsoch(pDevExt->physicalDevObj, pAVCStrmExt);
  354. }
  355. break;
  356. case KSSTATE_RUN:
  357. // Even there is no attach data request,
  358. // 61883 has its own buffers so isoch can start now.
  359. Status =
  360. AVCStrmStartIsoch(
  361. pDevExt->physicalDevObj,
  362. pAVCStrmExt
  363. );
  364. ASSERT(NT_SUCCESS(Status));
  365. pAVCStrmExt->LastSystemTime = GetSystemTime();
  366. break;
  367. default:
  368. Status = STATUS_NOT_SUPPORTED;
  369. }
  370. if(NT_SUCCESS(Status))
  371. pAVCStrmExt->StreamState = KSState;
  372. return Status;
  373. }
  374. #if 0
  375. NTSTATUS
  376. AVCStreamControlGetProperty(
  377. IN PIRP pIrp, // The Irp from its client
  378. IN struct DEVICE_EXTENSION * pDevExt,
  379. IN PAVC_STREAM_EXTENSION pAVCStrmExt,
  380. IN PSTREAM_PROPERTY_DESCRIPTOR pSPD // BUGBUG StreamClass specific
  381. )
  382. /*++
  383. Routine Description:
  384. Get control property
  385. Arguments:
  386. Irp -
  387. The irp client sent us.
  388. pDevExt -
  389. This driver's extension.
  390. pAVCStrmExt -
  391. The stream context created when a stream is open.
  392. pSPD -
  393. Stream property descriptor
  394. Return Value:
  395. Status
  396. STATUS_SUCCESS
  397. STATUS_INVALID_PARAMETER
  398. --*/
  399. {
  400. NTSTATUS Status;
  401. ULONG ulActualBytesTransferred;
  402. PAGED_CODE();
  403. ENTER("AVCStreamControlGetProperty");
  404. Status = STATUS_NOT_SUPPORTED;
  405. if(IsEqualGUID (&KSPROPSETID_Connection, &pSPD->Property->Set)) {
  406. Status =
  407. AVCStrmGetConnectionProperty(
  408. pDevExt,
  409. pAVCStrmExt,
  410. pSPD,
  411. &ulActualBytesTransferred
  412. );
  413. }
  414. else if (IsEqualGUID (&PROPSETID_VIDCAP_DROPPEDFRAMES, &pSPD->Property->Set)) {
  415. Status =
  416. AVCStrmGetDroppedFramesProperty(
  417. pDevExt,
  418. pAVCStrmExt,
  419. pSPD,
  420. &ulActualBytesTransferred
  421. );
  422. }
  423. return Status;
  424. }
  425. NTSTATUS
  426. AVCStreamControlSetProperty(
  427. IN PIRP pIrp, // The Irp from its client
  428. IN struct DEVICE_EXTENSION * pDevExt,
  429. IN PAVC_STREAM_EXTENSION pAVCStrmExt,
  430. IN PSTREAM_PROPERTY_DESCRIPTOR pSPD // BUGBUG StreamClass specific
  431. )
  432. /*++
  433. Routine Description:
  434. Set control property
  435. Arguments:
  436. Irp -
  437. The irp client sent us.
  438. pDevExt -
  439. This driver's extension.
  440. pAVCStrmExt -
  441. The stream context created when a stream is open.
  442. pSPD -
  443. Stream property descriptor
  444. Return Value:
  445. Status
  446. STATUS_SUCCESS
  447. STATUS_INVALID_PARAMETER
  448. --*/
  449. {
  450. NTSTATUS Status;
  451. PAGED_CODE();
  452. ENTER("AVCStreamControlSetProperty");
  453. Status = STATUS_NOT_SUPPORTED;
  454. return Status;
  455. }
  456. #endif
  457. NTSTATUS
  458. AVCStreamRead(
  459. IN PIRP pIrpUpper, // The Irp from its client
  460. IN struct DEVICE_EXTENSION * pDevExt,
  461. IN PAVC_STREAM_EXTENSION pAVCStrmExt,
  462. IN AVCSTRM_BUFFER_STRUCT * pBufferStruct
  463. )
  464. /*++
  465. Routine Description:
  466. Submit a read buffer to be filled.
  467. Arguments:
  468. Irp -
  469. The irp client sent us.
  470. pDevExt -
  471. This driver's extension.
  472. pAVCStrmExt -
  473. The stream context created when a stream is open.
  474. BufferStruct -
  475. Buffer structure
  476. Return Value:
  477. Status
  478. STATUS_SUCCESS
  479. STATUS_INVALID_PARAMETER
  480. --*/
  481. {
  482. PAVC_STREAM_DATA_STRUCT pDataStruc;
  483. KIRQL oldIrql;
  484. PIO_STACK_LOCATION NextIrpStack;
  485. NTSTATUS Status;
  486. PAVCSTRM_DATA_ENTRY pDataEntry;
  487. PAGED_CODE();
  488. ENTER("AVCStreamRead");
  489. // Cancel data request if device is being removed.
  490. if( pDevExt->state == STATE_REMOVING
  491. || pDevExt->state == STATE_REMOVED) {
  492. TRACE(TL_STRM_WARNING,("Read: device is remvoved; cancel read/write request!!\n"));
  493. Status = STATUS_DEVICE_REMOVED; goto DoneStreamRead;
  494. }
  495. // If we are in the abort state, we will reject incoming data request.
  496. if(pAVCStrmExt->lAbortToken) {
  497. TRACE(TL_STRM_WARNING,("Read: aborting a stream; stop receiving data reqest!!\n"));
  498. Status = STATUS_CANCELLED; goto DoneStreamRead;
  499. }
  500. // Validate basic parameters
  501. if(pAVCStrmExt->DataFlow != KSPIN_DATAFLOW_OUT) {
  502. TRACE(TL_STRM_ERROR,("Read: invalid Wrong data flow (%d) direction!!\n", pAVCStrmExt->DataFlow));
  503. Status = STATUS_INVALID_PARAMETER; goto DoneStreamRead;
  504. }
  505. pDataStruc = pAVCStrmExt->pAVCStrmDataStruc;
  506. if(!pDataStruc) {
  507. TRACE(TL_STRM_ERROR,("Read: invalid pDataStruc:%x\n", pDataStruc));
  508. Status = STATUS_INVALID_PARAMETER; goto DoneStreamRead;
  509. }
  510. if(pBufferStruct->StreamHeader->FrameExtent < pDataStruc->FrameSize) {
  511. TRACE(TL_STRM_ERROR,("Read: invalid buffer size:%d < FrameSize:%d\n", pBufferStruct->StreamHeader->FrameExtent, pDataStruc->FrameSize));
  512. Status = STATUS_INVALID_PARAMETER; goto DoneStreamRead;
  513. }
  514. if(!pBufferStruct->FrameBuffer) {
  515. TRACE(TL_STRM_ERROR,("Read: invalid FrameBuffer:%x\n", pBufferStruct->FrameBuffer));
  516. Status = STATUS_INVALID_PARAMETER; goto DoneStreamRead;
  517. }
  518. // Only accept read requests when in either the Pause or Run state and is connected.
  519. if( pAVCStrmExt->StreamState == KSSTATE_STOP ||
  520. pAVCStrmExt->StreamState == KSSTATE_ACQUIRE ||
  521. pAVCStrmExt->hConnect == NULL
  522. ) {
  523. TRACE(TL_STRM_WARNING,("Read: StrmSt:%d and Connected:%x!!\n", pAVCStrmExt->StreamState, pAVCStrmExt->hConnect));
  524. Status = STATUS_CANCELLED; goto DoneStreamRead;
  525. }
  526. KeAcquireSpinLock(&pDataStruc->DataListLock, &oldIrql);
  527. if(IsListEmpty(&pDataStruc->DataDetachedListHead)) {
  528. TRACE(TL_STRM_ERROR,("Read:no detached buffers!\n"));
  529. ASSERT(!IsListEmpty(&pDataStruc->DataDetachedListHead));
  530. KeReleaseSpinLock(&pDataStruc->DataListLock, oldIrql);
  531. Status = STATUS_INSUFFICIENT_RESOURCES; goto DoneStreamRead;
  532. }
  533. pDataEntry = (PAVCSTRM_DATA_ENTRY)
  534. RemoveHeadList(&pDataStruc->DataDetachedListHead); InterlockedDecrement(&pDataStruc->cntDataDetached);
  535. pDataStruc->cntDataReceived++;
  536. //
  537. // Format an attach frame request
  538. //
  539. AVCStrmFormatAttachFrame(
  540. pAVCStrmExt->DataFlow,
  541. pAVCStrmExt,
  542. pAVCStrmExt->pAVCStrmFormatInfo->AVCStrmFormat,
  543. &pDataEntry->AVReq,
  544. pDataEntry,
  545. pDataStruc->SourcePacketSize,
  546. pDataStruc->FrameSize,
  547. pIrpUpper,
  548. pBufferStruct->StreamHeader,
  549. pBufferStruct->FrameBuffer
  550. );
  551. // Client's clock information
  552. pDataEntry->ClockProvider = pBufferStruct->ClockProvider;
  553. pDataEntry->ClockHandle = pBufferStruct->ClockHandle;
  554. // Add this to the attached list before it is completed since
  555. // the completion callback can be called before the IRP completion rooutine!
  556. InsertTailList(&pDataStruc->DataAttachedListHead, &pDataEntry->ListEntry); InterlockedIncrement(&pDataStruc->cntDataAttached);
  557. KeReleaseSpinLock(&pDataStruc->DataListLock, oldIrql);
  558. NextIrpStack = IoGetNextIrpStackLocation(pDataEntry->pIrpLower);
  559. NextIrpStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
  560. NextIrpStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_61883_CLASS;
  561. NextIrpStack->Parameters.Others.Argument1 = &pDataEntry->AVReq;
  562. IoSetCompletionRoutine(
  563. pDataEntry->pIrpLower,
  564. AVCStrmAttachFrameCR,
  565. pDataEntry, // Context
  566. TRUE, // Success
  567. TRUE, // Error
  568. TRUE // Cancel
  569. );
  570. pDataEntry->pIrpLower->IoStatus.Status = STATUS_SUCCESS; // Initialize it
  571. if(!NT_SUCCESS(Status = IoCallDriver(
  572. pDevExt->physicalDevObj,
  573. pDataEntry->pIrpLower
  574. ))) {
  575. //
  576. // Completion routine should have take care of this.
  577. //
  578. return Status;
  579. }
  580. //
  581. // Check the flag in pDataEntry to know the status of the IRP.
  582. //
  583. KeAcquireSpinLock(&pDataStruc->DataListLock, &oldIrql);
  584. ASSERT(IsStateSet(pDataEntry->State, DE_IRP_LOWER_ATTACHED_COMPLETED)); // Must be attached
  585. if(IsStateSet(pDataEntry->State, DE_IRP_LOWER_CALLBACK_COMPLETED)) {
  586. if(IsStateSet(pDataEntry->State, DE_IRP_UPPER_COMPLETED)) {
  587. //
  588. // How does this happen? It should be protected by spinlock! Assert() to understand!
  589. //
  590. TRACE(TL_STRM_ERROR,("Watch out! Read: pDataEntry:%x\n", pDataEntry));
  591. ASSERT(!IsStateSet(pDataEntry->State, DE_IRP_UPPER_COMPLETED));
  592. }
  593. else {
  594. IoCompleteRequest( pDataEntry->pIrpUpper, IO_NO_INCREMENT ); pDataEntry->State |= DE_IRP_UPPER_COMPLETED;
  595. //
  596. // Transfer from attach to detach list
  597. //
  598. RemoveEntryList(&pDataEntry->ListEntry); InterlockedDecrement(&pDataStruc->cntDataAttached);
  599. #if DBG
  600. if(pDataStruc->cntDataAttached < 0) {
  601. TRACE(TL_STRM_ERROR,("Read: pDataStruc:%x; pDataEntry:%x\n", pDataStruc, pDataEntry));
  602. ASSERT(pDataStruc->cntDataAttached >= 0);
  603. }
  604. #endif
  605. InsertTailList(&pDataStruc->DataDetachedListHead, &pDataEntry->ListEntry); InterlockedIncrement(&pDataStruc->cntDataDetached);
  606. }
  607. }
  608. else {
  609. //
  610. // Normal case: IrpUpper will be pending until the callback routine is called or cancelled.
  611. //
  612. IoMarkIrpPending(pDataEntry->pIrpUpper); pDataEntry->State |= DE_IRP_UPPER_PENDING_COMPLETED;
  613. Status = STATUS_PENDING; // This will be returned to IoCallDriver() from the client.
  614. }
  615. KeReleaseSpinLock(&pDataStruc->DataListLock, oldIrql);
  616. EXIT("AVCStreamRead", Status);
  617. //
  618. // If the data was attached siccessful, we must return STATUS_PENDING
  619. //
  620. return Status;
  621. DoneStreamRead:
  622. // Note: pDataStruc and pDataEntry may not be valid!
  623. pIrpUpper->IoStatus.Status = Status;
  624. IoCompleteRequest( pIrpUpper, IO_NO_INCREMENT );
  625. EXIT("AVCStreamRead", Status);
  626. return Status;
  627. }
  628. #if DBG
  629. typedef union {
  630. CYCLE_TIME CycleTime;
  631. ULONG ulCycleTime;
  632. } U_CYCLE_TIME, * PU_CYCLE_TIME;
  633. #endif
  634. NTSTATUS
  635. AVCStreamWrite(
  636. IN PIRP pIrpUpper, // The Irp from its client
  637. IN struct DEVICE_EXTENSION * pDevExt,
  638. IN PAVC_STREAM_EXTENSION pAVCStrmExt,
  639. IN AVCSTRM_BUFFER_STRUCT * pBufferStruct
  640. )
  641. /*++
  642. Routine Description:
  643. Submit a write buffer to be transmitted.
  644. Arguments:
  645. Irp -
  646. The irp client sent us.
  647. pDevExt -
  648. This driver's extension.
  649. pAVCStrmExt -
  650. The stream context created when a stream is open.
  651. BufferStruct -
  652. Buffer structure
  653. Return Value:
  654. Status
  655. STATUS_SUCCESS
  656. STATUS_INVALID_PARAMETER
  657. --*/
  658. {
  659. PAVC_STREAM_DATA_STRUCT pDataStruc;
  660. KIRQL oldIrql;
  661. PIO_STACK_LOCATION NextIrpStack;
  662. NTSTATUS Status;
  663. PAVCSTRM_DATA_ENTRY pDataEntry;
  664. PAGED_CODE();
  665. ENTER("AVCStreamWrite");
  666. // Cancel data request if device is being removed.
  667. if( pDevExt->state == STATE_REMOVING
  668. || pDevExt->state == STATE_REMOVED) {
  669. TRACE(TL_STRM_WARNING,("Write: device is remvoved; cancel read/write request!!\n"));
  670. Status = STATUS_DEVICE_REMOVED; goto DoneStreamWrite;
  671. }
  672. // If we are in the abort state, we will reject incoming data request.
  673. if(pAVCStrmExt->lAbortToken) {
  674. TRACE(TL_STRM_WARNING,("Write: aborting a stream; stop receiving data reqest!!\n"));
  675. Status = STATUS_CANCELLED; goto DoneStreamWrite;
  676. }
  677. // Validate basic parameters
  678. if(pAVCStrmExt->DataFlow != KSPIN_DATAFLOW_IN) {
  679. TRACE(TL_STRM_ERROR,("Write: invalid Wrong data flow (%d) direction!!\n", pAVCStrmExt->DataFlow));
  680. Status = STATUS_INVALID_PARAMETER; goto DoneStreamWrite;
  681. }
  682. pDataStruc = pAVCStrmExt->pAVCStrmDataStruc;
  683. if(!pDataStruc) {
  684. TRACE(TL_STRM_ERROR,("Write: invalid pDataStruc:%x\n", pDataStruc));
  685. Status = STATUS_INVALID_PARAMETER; goto DoneStreamWrite;
  686. }
  687. // The client should take care of END OF stream buffer;
  688. // If we get this flag, we will ignore it for now.
  689. if((pBufferStruct->StreamHeader->OptionsFlags & KSSTREAM_HEADER_OPTIONSF_ENDOFSTREAM)) {
  690. TRACE(TL_STRM_TRACE,("Write: End of stream\n"));
  691. // Wait until all transmit are completed.
  692. AVCStrmWaitUntilAttachedAreCompleted(pAVCStrmExt);
  693. Status = STATUS_SUCCESS; goto DoneStreamWrite;
  694. }
  695. // The client should take care of format change;
  696. // If we get this flag, we will ignore it for now.
  697. if((pBufferStruct->StreamHeader->OptionsFlags & KSSTREAM_HEADER_OPTIONSF_TYPECHANGED)) {
  698. TRACE(TL_STRM_WARNING,("Write: Format change reuqested\n"));
  699. Status = STATUS_SUCCESS; goto DoneStreamWrite;
  700. }
  701. if(pBufferStruct->StreamHeader->FrameExtent < pDataStruc->FrameSize) {
  702. TRACE(TL_STRM_ERROR,("Write: invalid buffer size:%d < FrameSize:%d\n", pBufferStruct->StreamHeader->FrameExtent, pDataStruc->FrameSize));
  703. Status = STATUS_INVALID_PARAMETER; goto DoneStreamWrite;
  704. }
  705. if(!pBufferStruct->FrameBuffer) {
  706. TRACE(TL_STRM_ERROR,("Write: invalid FrameBuffer:%x\n", pBufferStruct->FrameBuffer));
  707. Status = STATUS_INVALID_PARAMETER; goto DoneStreamWrite;
  708. }
  709. // Only accept write requests when in either the Pause or Run state and is connected.
  710. if( pAVCStrmExt->StreamState == KSSTATE_STOP ||
  711. pAVCStrmExt->StreamState == KSSTATE_ACQUIRE ||
  712. pAVCStrmExt->hConnect == NULL
  713. ) {
  714. TRACE(TL_STRM_ERROR,("Write: StrmSt:%d or hConnect:%x!!\n", pAVCStrmExt->StreamState, pAVCStrmExt->hConnect));
  715. Status = STATUS_CANCELLED; goto DoneStreamWrite;
  716. }
  717. #if DBG
  718. #define MASK_LOWER_25BIT 0x01ffffff
  719. if(pAVCStrmExt->pAVCStrmFormatInfo->AVCStrmFormat == AVCSTRM_FORMAT_MPEG2TS) {
  720. U_CYCLE_TIME TimeStamp25Bits;
  721. TimeStamp25Bits.ulCycleTime = *((PDWORD) pBufferStruct->FrameBuffer);
  722. TimeStamp25Bits.ulCycleTime = bswap(TimeStamp25Bits.ulCycleTime);
  723. TRACE(TL_CIP_TRACE,("\t%d \t%d \t%d \t%x \t%d \t%d\n",
  724. (DWORD) pDataStruc->cntDataReceived,
  725. pDataStruc->FrameSize,
  726. pDataStruc->SourcePacketSize,
  727. TimeStamp25Bits.ulCycleTime & MASK_LOWER_25BIT,
  728. TimeStamp25Bits.CycleTime.CL_CycleCount,
  729. TimeStamp25Bits.CycleTime.CL_CycleOffset));
  730. }
  731. #endif
  732. KeAcquireSpinLock(&pDataStruc->DataListLock, &oldIrql);
  733. if(IsListEmpty(&pDataStruc->DataDetachedListHead)) {
  734. KeReleaseSpinLock(&pDataStruc->DataListLock, oldIrql);
  735. TRACE(TL_STRM_ERROR,("Write:no detached buffers!\n"));
  736. ASSERT(!IsListEmpty(&pDataStruc->DataDetachedListHead));
  737. Status = STATUS_INSUFFICIENT_RESOURCES; goto DoneStreamWrite;
  738. }
  739. #if DBG
  740. //
  741. // For write operation, DataUsed <= FrameSize <= FrameExt
  742. //
  743. if(pBufferStruct->StreamHeader->DataUsed < pDataStruc->FrameSize) {
  744. // Jut to detect if this ever happen.
  745. TRACE(TL_PNP_ERROR,("**** Write: DataUsed:%d < FrameSize:%d; DataRcv:%d; AQD [%d:%d:%d]\n",
  746. pBufferStruct->StreamHeader->DataUsed, pDataStruc->FrameSize,
  747. (DWORD) pDataStruc->cntDataReceived,
  748. pAVCStrmExt->pAVCStrmDataStruc->cntDataAttached,
  749. pAVCStrmExt->pAVCStrmDataStruc->cntDataQueued,
  750. pAVCStrmExt->pAVCStrmDataStruc->cntDataDetached
  751. ));
  752. }
  753. #endif
  754. pDataEntry = (PAVCSTRM_DATA_ENTRY)
  755. RemoveHeadList(&pDataStruc->DataDetachedListHead); InterlockedDecrement(&pDataStruc->cntDataDetached);
  756. pDataStruc->cntDataReceived++;
  757. //
  758. // Format an attach frame request
  759. //
  760. AVCStrmFormatAttachFrame(
  761. pAVCStrmExt->DataFlow,
  762. pAVCStrmExt,
  763. pAVCStrmExt->pAVCStrmFormatInfo->AVCStrmFormat,
  764. &pDataEntry->AVReq,
  765. pDataEntry,
  766. pDataStruc->SourcePacketSize,
  767. #if 0
  768. pDataStruc->FrameSize,
  769. #else
  770. pBufferStruct->StreamHeader->DataUsed, // For write operation, DataUsed <= FrameSize <= FrameExt
  771. #endif
  772. pIrpUpper,
  773. pBufferStruct->StreamHeader,
  774. pBufferStruct->FrameBuffer
  775. );
  776. // Client's clock information
  777. pDataEntry->ClockProvider = pBufferStruct->ClockProvider;
  778. pDataEntry->ClockHandle = pBufferStruct->ClockHandle;
  779. // Add this to the attached list before it is completed since
  780. // the completion callback can be called before the IRP completion rooutine!
  781. InsertTailList(&pDataStruc->DataAttachedListHead, &pDataEntry->ListEntry); InterlockedIncrement(&pDataStruc->cntDataAttached);
  782. KeReleaseSpinLock(&pDataStruc->DataListLock, oldIrql);
  783. NextIrpStack = IoGetNextIrpStackLocation(pDataEntry->pIrpLower);
  784. NextIrpStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
  785. NextIrpStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_61883_CLASS;
  786. NextIrpStack->Parameters.Others.Argument1 = &pDataEntry->AVReq;
  787. IoSetCompletionRoutine(
  788. pDataEntry->pIrpLower,
  789. AVCStrmAttachFrameCR,
  790. pDataEntry,
  791. TRUE,
  792. TRUE,
  793. TRUE
  794. );
  795. IoSetCancelRoutine(
  796. pDataEntry->pIrpLower,
  797. NULL
  798. );
  799. pDataEntry->pIrpLower->IoStatus.Status = STATUS_SUCCESS; // Initialize it
  800. if(!NT_SUCCESS(Status = IoCallDriver(
  801. pDevExt->physicalDevObj,
  802. pDataEntry->pIrpLower
  803. ))) {
  804. //
  805. // Completion routine should have take care of this.
  806. //
  807. return Status;
  808. }
  809. //
  810. // Check the flag in pDataEntry to know the status of the IRP.
  811. //
  812. KeAcquireSpinLock(&pDataStruc->DataListLock, &oldIrql);
  813. ASSERT(IsStateSet(pDataEntry->State, DE_IRP_LOWER_ATTACHED_COMPLETED)); // Must be attached
  814. if(IsStateSet(pDataEntry->State, DE_IRP_LOWER_CALLBACK_COMPLETED)) {
  815. if(IsStateSet(pDataEntry->State, DE_IRP_UPPER_COMPLETED)) {
  816. //
  817. // How does this happen? It should be protected by spinlock! Assert() to understand!
  818. //
  819. TRACE(TL_STRM_ERROR,("Watch out! Write: pDataEntry:%x\n", pDataEntry));
  820. ASSERT(!IsStateSet(pDataEntry->State, DE_IRP_UPPER_COMPLETED));
  821. }
  822. else {
  823. IoCompleteRequest( pDataEntry->pIrpUpper, IO_NO_INCREMENT ); pDataEntry->State |= DE_IRP_UPPER_COMPLETED;
  824. //
  825. // Transfer from attach to detach list
  826. //
  827. RemoveEntryList(&pDataEntry->ListEntry); InterlockedDecrement(&pDataStruc->cntDataAttached);
  828. //
  829. // Signal when there is no more data buffer attached.
  830. //
  831. if(pDataStruc->cntDataAttached == 0)
  832. KeSetEvent(&pDataStruc->hNoAttachEvent, 0, FALSE);
  833. #if DBG
  834. if(pDataStruc->cntDataAttached < 0) {
  835. TRACE(TL_STRM_ERROR,("Write: pDataStruc:%x; pDataEntry:%x\n", pDataStruc, pDataEntry));
  836. ASSERT(pDataStruc->cntDataAttached >= 0);
  837. }
  838. #endif
  839. InsertTailList(&pDataStruc->DataDetachedListHead, &pDataEntry->ListEntry); InterlockedIncrement(&pDataStruc->cntDataDetached);
  840. }
  841. }
  842. else {
  843. //
  844. // Normal case: IrpUpper will be pending until the callback routine is called or cancelled.
  845. //
  846. IoMarkIrpPending(pDataEntry->pIrpUpper); pDataEntry->State |= DE_IRP_UPPER_PENDING_COMPLETED;
  847. Status = STATUS_PENDING; // This will be returned to IoCallDriver() from the client.
  848. }
  849. KeReleaseSpinLock(&pDataStruc->DataListLock, oldIrql);
  850. EXIT("AVCStreamWrite", Status);
  851. //
  852. // If the data was attached siccessful, we must return STATUS_PENDING
  853. //
  854. return Status;
  855. DoneStreamWrite:
  856. // Note: pDataStruc and pDataEntry may not be valid!
  857. pIrpUpper->IoStatus.Status = Status;
  858. IoCompleteRequest( pIrpUpper, IO_NO_INCREMENT );
  859. EXIT("AVCStreamWrite", Status);
  860. return Status;
  861. }
  862. NTSTATUS
  863. AVCStreamAbortStreaming(
  864. IN PIRP pIrp, // The Irp from its client
  865. IN struct DEVICE_EXTENSION * pDevExt,
  866. IN PAVC_STREAM_EXTENSION pAVCStrmExt
  867. )
  868. /*++
  869. Routine Description:
  870. This routine could be called at DISPATCH_LEVEL so it will create a work item
  871. to stop isoch and then cancel all pennding buffers.
  872. To cancel each individual buffer, IoCancelIrp() should be used..
  873. Arguments:
  874. Irp -
  875. The irp client sent us.
  876. pDevExt -
  877. This driver's extension.
  878. pAVCStrmExt -
  879. The stream context created when a stream is open.
  880. Return Value:
  881. Status
  882. STATUS_SUCCESS
  883. STATUS_INVALID_PARAMETER
  884. --*/
  885. {
  886. NTSTATUS Status;
  887. PAGED_CODE();
  888. ENTER("AVCStreamAbortStreaming");
  889. TRACE(TL_STRM_WARNING,("AbortStreaming: Active:%d; State:%d\n", pAVCStrmExt->IsochIsActive, pAVCStrmExt->StreamState));
  890. // Claim this token
  891. if(InterlockedExchange(&pAVCStrmExt->lAbortToken, 1) == 1) {
  892. TRACE(TL_STRM_WARNING,("AbortStreaming: One already issued.\n"));
  893. return STATUS_SUCCESS;
  894. }
  895. Status = STATUS_SUCCESS;
  896. #ifdef USE_WDM110 // Win2000 code base
  897. ASSERT(pAVCStrmExt->pIoWorkItem == NULL); // Have not yet queued work item.
  898. // We will queue work item to stop and cancel all SRBs
  899. if(pAVCStrmExt->pIoWorkItem = IoAllocateWorkItem(pDevExt->physicalDevObj)) {
  900. // Set to non-signal
  901. KeClearEvent(&pAVCStrmExt->hAbortDoneEvent); // Before queuing; just in case it return the work item is completed.
  902. IoQueueWorkItem(
  903. pAVCStrmExt->pIoWorkItem,
  904. AVCStrmAbortStreamingWorkItemRoutine,
  905. DelayedWorkQueue, // CriticalWorkQueue
  906. pAVCStrmExt
  907. );
  908. #else // Win9x code base
  909. ExInitializeWorkItem( &pAVCStrmExt->IoWorkItem, AVCStrmAbortStreamingWorkItemRoutine, pAVCStrmExt);
  910. if(TRUE) {
  911. // Set to non-signal
  912. KeClearEvent(&pAVCStrmExt->hAbortDoneEvent); // Before queuing; just in case it return the work item is completed.
  913. ExQueueWorkItem(
  914. &pAVCStrmExt->IoWorkItem,
  915. DelayedWorkQueue // CriticalWorkQueue
  916. );
  917. #endif
  918. TRACE(TL_STRM_TRACE,("AbortStreaming: CancelWorkItm queued; Pic#:%d;Prc:%d;;Drop:%d; AQD [%d:%d:%d]\n",
  919. (DWORD) pAVCStrmExt->pAVCStrmDataStruc->PictureNumber,
  920. (DWORD) pAVCStrmExt->pAVCStrmDataStruc->FramesProcessed,
  921. (DWORD) pAVCStrmExt->pAVCStrmDataStruc->FramesDropped,
  922. pAVCStrmExt->pAVCStrmDataStruc->cntDataAttached,
  923. pAVCStrmExt->pAVCStrmDataStruc->cntDataQueued,
  924. pAVCStrmExt->pAVCStrmDataStruc->cntDataDetached
  925. ));
  926. }
  927. #ifdef USE_WDM110 // Win2000 code base
  928. else {
  929. Status = STATUS_INSUFFICIENT_RESOURCES; // Only reason IoAllocateWorkItem can fail.
  930. InterlockedExchange(&pAVCStrmExt->lAbortToken, 0);
  931. ASSERT(pAVCStrmExt->pIoWorkItem && "IoAllocateWorkItem failed.\n");
  932. }
  933. #endif
  934. #define MAX_ABORT_WAIT 50000000 // max wait time (100nsec unit)
  935. if(NT_SUCCESS(Status)) {
  936. NTSTATUS StatusWait;
  937. LARGE_INTEGER tmMaxWait;
  938. tmMaxWait = RtlConvertLongToLargeInteger(-(MAX_ABORT_WAIT));
  939. //
  940. // Wait with timeout until the work item has completed.
  941. //
  942. StatusWait =
  943. KeWaitForSingleObject(
  944. &pAVCStrmExt->hAbortDoneEvent,
  945. Executive,
  946. KernelMode,
  947. FALSE,
  948. &tmMaxWait
  949. );
  950. TRACE(TL_STRM_ERROR,("**WorkItem completed! StatusWait:%x; pAVStrmExt:%x; AQD [%d:%d:%d]\n",
  951. StatusWait, pAVCStrmExt,
  952. pAVCStrmExt->pAVCStrmDataStruc->cntDataAttached,
  953. pAVCStrmExt->pAVCStrmDataStruc->cntDataQueued,
  954. pAVCStrmExt->pAVCStrmDataStruc->cntDataDetached
  955. ));
  956. ASSERT(StatusWait == STATUS_SUCCESS);
  957. }
  958. return Status;
  959. }
  960. NTSTATUS
  961. AVCStreamSurpriseRemoval(
  962. IN struct DEVICE_EXTENSION * pDevExt
  963. )
  964. /*++
  965. Routine Description:
  966. This routine is called when this device is being surprise removed
  967. with IRP_MN_SURPRISE_REMOVAL. We need to clean up and cancel any
  968. pending request before passing irp down to lower driver.
  969. Arguments:
  970. pDevExt -
  971. This driver's extension.
  972. Return Value:
  973. Status
  974. STATUS_SUCCESS
  975. STATUS_INVALID_PARAMETER
  976. --*/
  977. {
  978. NTSTATUS Status = STATUS_SUCCESS;
  979. ULONG i;
  980. for (i=0; i < pDevExt->NumberOfStreams; i++) {
  981. if(pDevExt->pAVCStrmExt[i]) {
  982. if(pDevExt->pAVCStrmExt[i]->lAbortToken == 1) {
  983. PAVC_STREAM_EXTENSION pAVCStrmExt = pDevExt->pAVCStrmExt[i];
  984. #if DBG
  985. ULONGLONG tmStart = GetSystemTime();
  986. #endif
  987. KeWaitForSingleObject(
  988. &pAVCStrmExt->hAbortDoneEvent,
  989. Executive,
  990. KernelMode,
  991. FALSE,
  992. NULL
  993. );
  994. TRACE(TL_PNP_WARNING,("** Waited %d for AbortStream to complete\n", (DWORD) (GetSystemTime() - tmStart) ));
  995. }
  996. //
  997. // Since we are already removed, go ahead and break the connection.
  998. //
  999. AVCStrmBreakConnection(pDevExt->physicalDevObj, pDevExt->pAVCStrmExt[i]);
  1000. }
  1001. }
  1002. return Status;
  1003. }
  1004. NTSTATUS
  1005. AVCStrmValidateStreamRequest(
  1006. struct DEVICE_EXTENSION *pDevExt,
  1007. PAVC_STREAM_REQUEST_BLOCK pAVCStrmReqBlk
  1008. )
  1009. /*++
  1010. Routine Description:
  1011. Validate the StreamIndex of an AVC Stream Extension according to a AVC Stream function.
  1012. Arguments:
  1013. pDevExt -
  1014. This driver's extension.
  1015. pAVCStrmReqBlk -
  1016. AVC Stream reuqest block.
  1017. Return Value:
  1018. Status
  1019. STATUS_SUCCESS
  1020. STATUS_INVALID_PARAMETER
  1021. --*/
  1022. {
  1023. NTSTATUS Status;
  1024. PAGED_CODE();
  1025. ENTER("AVCStrmValidateStreamRequest");
  1026. Status = STATUS_SUCCESS;
  1027. // Validate pointer
  1028. if(!pAVCStrmReqBlk)
  1029. return STATUS_INVALID_PARAMETER;
  1030. // Validate block size
  1031. if(pAVCStrmReqBlk->SizeOfThisBlock != sizeof(AVC_STREAM_REQUEST_BLOCK))
  1032. return STATUS_INVALID_PARAMETER;
  1033. #if 0
  1034. // Validate version supported
  1035. if( pAVCStrmReqBlk->Version != '15TN'
  1036. && pAVCStrmReqBlk->Version != ' 8XD'
  1037. )
  1038. return STATUS_INVALID_PARAMETER;
  1039. #endif
  1040. if(pAVCStrmReqBlk->Function == AVCSTRM_OPEN) {
  1041. if(pDevExt->NumberOfStreams >= MAX_STREAMS_PER_DEVICE) {
  1042. ASSERT(pDevExt->NumberOfStreams < MAX_STREAMS_PER_DEVICE && "AVCStreamOpen: Too many stream open!\n");
  1043. Status = STATUS_INSUFFICIENT_RESOURCES;
  1044. }
  1045. } else {
  1046. if(pAVCStrmReqBlk->AVCStreamContext == NULL) {
  1047. ASSERT(pAVCStrmReqBlk->AVCStreamContext != NULL && "Invalid pAVCStrmExt\n");
  1048. return STATUS_INVALID_PARAMETER;
  1049. }
  1050. // To be more robust, we may need to make sure this is
  1051. // one of the cached stream extension created by us.
  1052. // ......
  1053. }
  1054. return Status;
  1055. }
  1056. NTSTATUS
  1057. AvcStrm_IoControl(
  1058. IN PDEVICE_OBJECT DeviceObject,
  1059. IN PIRP Irp
  1060. )
  1061. {
  1062. struct DEVICE_EXTENSION *pDevExt;
  1063. PIO_STACK_LOCATION irpSp;
  1064. BOOLEAN passIrpDown = TRUE;
  1065. NTSTATUS Status;
  1066. PAVC_STREAM_REQUEST_BLOCK pAvcStrmIrb;
  1067. PAGED_CODE();
  1068. ENTER("AvcStrm_IoControl");
  1069. Status = STATUS_SUCCESS;
  1070. pDevExt = DeviceObject->DeviceExtension;
  1071. ASSERT(pDevExt->signature == DEVICE_EXTENSION_SIGNATURE);
  1072. irpSp = IoGetCurrentIrpStackLocation(Irp);
  1073. pAvcStrmIrb = irpSp->Parameters.Others.Argument1;
  1074. // Validate the stream context
  1075. if(!NT_SUCCESS(Status =
  1076. AVCStrmValidateStreamRequest(
  1077. pDevExt,
  1078. pAvcStrmIrb))) {
  1079. goto DoneIoControl;
  1080. }
  1081. switch(pAvcStrmIrb->Function) {
  1082. case AVCSTRM_OPEN:
  1083. Status = AVCStreamOpen(
  1084. Irp,
  1085. pDevExt,
  1086. &pAvcStrmIrb->CommandData.OpenStruct
  1087. );
  1088. break;
  1089. case AVCSTRM_CLOSE:
  1090. Status = AVCStreamClose(
  1091. Irp,
  1092. pDevExt,
  1093. (PAVC_STREAM_EXTENSION) pAvcStrmIrb->AVCStreamContext
  1094. );
  1095. break;
  1096. case AVCSTRM_GET_STATE:
  1097. Status = AVCStreamControlGetState(
  1098. Irp,
  1099. pDevExt,
  1100. (PAVC_STREAM_EXTENSION) pAvcStrmIrb->AVCStreamContext,
  1101. &pAvcStrmIrb->CommandData.StreamState
  1102. );
  1103. break;
  1104. case AVCSTRM_SET_STATE:
  1105. Status = AVCStreamControlSetState(
  1106. Irp,
  1107. pDevExt,
  1108. (PAVC_STREAM_EXTENSION) pAvcStrmIrb->AVCStreamContext,
  1109. pAvcStrmIrb->CommandData.StreamState
  1110. );
  1111. break;
  1112. #if 0 // Later...
  1113. case AVCSTRM_GET_PROPERTY:
  1114. Status = AVCStreamControlGetProperty(
  1115. Irp,
  1116. pDevExt,
  1117. (PAVC_STREAM_EXTENSION) pAvcStrmIrb->AVCStreamContext,
  1118. pAvcStrmIrb->CommandData.PropertyDescriptor
  1119. );
  1120. break;
  1121. case AVCSTRM_SET_PROPERTY:
  1122. Status = AVCStreamControlSetProperty(
  1123. Irp,
  1124. pDevExt,
  1125. (PAVC_STREAM_EXTENSION) pAvcStrmIrb->AVCStreamContext,
  1126. pAvcStrmIrb->CommandData.PropertyDescriptor
  1127. );
  1128. break;
  1129. #endif
  1130. case AVCSTRM_READ:
  1131. // Mutex with Cancel or setting to stop state.
  1132. KeWaitForMutexObject(&((PAVC_STREAM_EXTENSION) pAvcStrmIrb->AVCStreamContext)->hMutexControl, Executive, KernelMode, FALSE, NULL);
  1133. Status = AVCStreamRead(
  1134. Irp,
  1135. pDevExt,
  1136. (PAVC_STREAM_EXTENSION) pAvcStrmIrb->AVCStreamContext,
  1137. &pAvcStrmIrb->CommandData.BufferStruct
  1138. );
  1139. KeReleaseMutex(&((PAVC_STREAM_EXTENSION) pAvcStrmIrb->AVCStreamContext)->hMutexControl, FALSE);
  1140. return Status;
  1141. break;
  1142. case AVCSTRM_WRITE:
  1143. KeWaitForMutexObject(&((PAVC_STREAM_EXTENSION) pAvcStrmIrb->AVCStreamContext)->hMutexControl, Executive, KernelMode, FALSE, NULL);
  1144. Status = AVCStreamWrite(
  1145. Irp,
  1146. pDevExt,
  1147. (PAVC_STREAM_EXTENSION) pAvcStrmIrb->AVCStreamContext,
  1148. &pAvcStrmIrb->CommandData.BufferStruct
  1149. );
  1150. KeReleaseMutex(&((PAVC_STREAM_EXTENSION) pAvcStrmIrb->AVCStreamContext)->hMutexControl, FALSE);
  1151. return Status;
  1152. break;
  1153. case AVCSTRM_ABORT_STREAMING:
  1154. Status = AVCStreamAbortStreaming(
  1155. Irp,
  1156. pDevExt,
  1157. (PAVC_STREAM_EXTENSION) pAvcStrmIrb->AVCStreamContext
  1158. );
  1159. break;
  1160. default:
  1161. Status = STATUS_INVALID_PARAMETER;
  1162. break;
  1163. }
  1164. DoneIoControl:
  1165. #if DBG
  1166. if(!NT_SUCCESS(Status)) {
  1167. TRACE(TL_PNP_WARNING,("Av_IoControl return Status:%x\n", Status));
  1168. }
  1169. #endif
  1170. if (Status == STATUS_PENDING) {
  1171. TRACE(TL_PNP_TRACE,("Av_IoControl: returning STATUS_PENDING."));
  1172. IoMarkIrpPending(Irp);
  1173. } else {
  1174. Irp->IoStatus.Status = Status;
  1175. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  1176. }
  1177. return Status;
  1178. }