//==========================================================================; // // THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY // KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE // IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR // PURPOSE. // // Copyright (c) 1992 - 1998 Microsoft Corporation. All Rights Reserved. // //==========================================================================; #include #include #include #include "kskludge.h" #include "codmain.h" #include "codstrm.h" #include "codprop.h" #include "coddebug.h" // // Fake VBI Info header. Infinite Pin Tee Filter can't pass real ones // one from capture so we rely on this. MSTee can so this gets // overwritten. // KS_VBIINFOHEADER FakeVBIInfoHeader = { 10, /* StartLine; IGNORED */ 21, /* EndLine; IGNORED */ 28636360, /* SamplingFrequency; Hz. */ 780, /* MinLineStartTime; IGNORED */ 780, /* MaxLineStartTime; IGNORED */ 780, /* ActualLineStartTime; microSec * 100 from HSync LE */ 0, /* ActualLineEndTime; IGNORED */ 0, /* VideoStandard; IGNORED */ 1600, /* SamplesPerLine; */ 1600, /* StrideInBytes; May be > SamplesPerLine */ 1600*12 /* BufferSize; Bytes */ }; /* ** DriverEntry() ** ** This routine is called when the driver is first loaded by PnP. ** It in turn, calls upon the stream class to perform registration services. ** ** Arguments: ** ** DriverObject - ** Driver object for this driver ** ** RegistryPath - ** Registry path string for this driver's key ** ** Returns: ** ** Results of StreamClassRegisterAdapter() ** ** Side Effects: none */ ULONG DriverEntry( IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath ) { ULONG status = 0; HW_INITIALIZATION_DATA HwInitData; CDebugPrint(DebugLevelTrace,(CODECNAME ":--->DriverEntry(DriverObject=%x,RegistryPath=%x)\n", DriverObject, RegistryPath)); RtlZeroMemory(&HwInitData, sizeof(HwInitData)); HwInitData.HwInitializationDataSize = sizeof(HwInitData); /*CDEBUG_BREAK();*/ // // Set the codec entry points for the driver // HwInitData.HwInterrupt = NULL; // HwInterrupt is only for HW devices HwInitData.HwReceivePacket = CodecReceivePacket; HwInitData.HwCancelPacket = CodecCancelPacket; HwInitData.HwRequestTimeoutHandler = CodecTimeoutPacket; HwInitData.DeviceExtensionSize = sizeof(HW_DEVICE_EXTENSION); HwInitData.PerRequestExtensionSize = sizeof(SRB_EXTENSION); HwInitData.FilterInstanceExtensionSize = 0; HwInitData.PerStreamExtensionSize = sizeof(STREAMEX); HwInitData.BusMasterDMA = FALSE; HwInitData.Dma24BitAddresses = FALSE; HwInitData.BufferAlignment = 3; HwInitData.TurnOffSynchronization = TRUE; HwInitData.DmaBufferSize = 0; CDebugPrint(DebugLevelVerbose,(CODECNAME ": StreamClassRegisterAdapter\n")); status = StreamClassRegisterAdapter(DriverObject, RegistryPath, &HwInitData); CDebugPrint(DebugLevelTrace,(CODECNAME ":<---DriverEntry(DriverObject=%x,RegistryPath=%x)=%d\n", DriverObject, RegistryPath, status)); return status; } //==========================================================================; // Codec Request Handling Routines //==========================================================================; /* ** CodecInitialize() ** ** This routine is called when an SRB_INITIALIZE_DEVICE request is received ** ** Arguments: ** ** pSrb - pointer to stream request block for the Initialize command ** ** Returns: ** ** Side Effects: none */ BOOLEAN CodecInitialize ( IN OUT PHW_STREAM_REQUEST_BLOCK pSrb ) { BOOLEAN bStatus = FALSE; PPORT_CONFIGURATION_INFORMATION ConfigInfo = pSrb->CommandData.ConfigInfo; PHW_DEVICE_EXTENSION pHwDevExt = (PHW_DEVICE_EXTENSION)ConfigInfo->HwDeviceExtension; CDebugPrint(DebugLevelTrace,(CODECNAME ":--->CodecInitialize(pSrb=%x)\n",pSrb)); if (ConfigInfo->NumberOfAccessRanges == 0) { CDebugPrint(DebugLevelVerbose,(CODECNAME ": CodecInitialize\n")); ConfigInfo->StreamDescriptorSize = sizeof (HW_STREAM_HEADER) + DRIVER_STREAM_COUNT * sizeof (HW_STREAM_INFORMATION); // These are the driver defaults for scanline filtering. // Modify these WHEN you change the codec type to be more correct. SETBIT( pHwDevExt->ScanlinesRequested.DwordBitArray, 21 ); // These are the driver defaults for subtream filtering. // Modify these WHEN you change the codec type pHwDevExt->SubstreamsRequested.SubstreamMask = KS_CC_SUBSTREAM_ODD; pHwDevExt->Streams = Streams; pHwDevExt->fTunerChange = FALSE; // // Allocate the results array based on the number of scanlines // pHwDevExt->DSPResultStartLine = pHwDevExt->DSPResultEndLine = 0; pHwDevExt->DSPResult = ( PDSPRESULT ) ExAllocatePool( NonPagedPool, sizeof( DSPRESULT ) * (FakeVBIInfoHeader.EndLine - FakeVBIInfoHeader.StartLine + 1) ); if( !pHwDevExt->DSPResult ) { CDebugPrint( DebugLevelError, (CODECNAME ": DSP Result array allocation FAILED\n" )); //pSrb->Status = STATUS_INVALID_PARAMETER; } else { pHwDevExt->DSPResultStartLine = FakeVBIInfoHeader.StartLine; pHwDevExt->DSPResultEndLine = FakeVBIInfoHeader.EndLine; } // Zero out the substream state information (no substreams discovered yet) RtlZeroMemory( pHwDevExt->SubStreamState, sizeof(pHwDevExt->SubStreamState) ); #ifdef CCINPUTPIN // Init LastPictureNumber's FastMutex ExInitializeFastMutex(&pHwDevExt->LastPictureMutex); #endif // CCINPUTPIN pSrb->Status = STATUS_SUCCESS; bStatus = TRUE; } else { CDebugPrint(DebugLevelError,(CODECNAME ": illegal config info\n")); pSrb->Status = STATUS_NO_SUCH_DEVICE; } CDebugPrint(DebugLevelTrace, (CODECNAME ":<---CodecInitialize(pSrb=%x)=%d\n", pSrb, bStatus)); return (bStatus); } /* ** CodecUnInitialize() ** ** This routine is called when an SRB_UNINITIALIZE_DEVICE request is received ** ** Arguments: ** ** pSrb - pointer to stream request block for the UnInitialize command ** ** Returns: ** ** Side Effects: none */ BOOLEAN CodecUnInitialize ( PHW_STREAM_REQUEST_BLOCK pSrb ) { PHW_DEVICE_EXTENSION pHwDevExt = ((PHW_DEVICE_EXTENSION)pSrb->HwDeviceExtension); CDebugPrint(DebugLevelTrace,(CODECNAME ":--->CodecUnInitialize(pSrb=%x)\n",pSrb)); pSrb->Status = STATUS_SUCCESS; CDebugPrint(DebugLevelTrace,(CODECNAME ":<---CodecUnInitialize(pSrb=%x)\n",pSrb)); // // Free up the results buffer // if (pHwDevExt->DSPResult) { ExFreePool( pHwDevExt->DSPResult ); pHwDevExt->DSPResult = NULL; pHwDevExt->DSPResultStartLine = pHwDevExt->DSPResultEndLine = 0; } return TRUE; } /* ** CodecOpenStream() ** ** This routine is called when an OpenStream SRB request is received. ** A stream is identified by a stream number, which indexes an array ** of KSDATARANGE structures. The particular KSDATAFORMAT format to ** be used is also passed in, which should be verified for validity. ** ** Arguments: ** ** pSrb - pointer to stream request block for the Open command ** ** Returns: ** ** Side Effects: none */ VOID CodecOpenStream( PHW_STREAM_REQUEST_BLOCK pSrb ) { // // the stream extension structure is allocated by the stream class driver // PSTREAMEX pStrmEx = pSrb->StreamObject->HwStreamExtension; PHW_DEVICE_EXTENSION pHwDevExt = pSrb->HwDeviceExtension; int StreamNumber = pSrb->StreamObject->StreamNumber; PKSDATAFORMAT pKSVBIDataFormat = (PKSDATAFORMAT)pSrb->CommandData.OpenFormat; CDebugPrint(DebugLevelTrace,(CODECNAME ":--->CodecOpenStream(pSrb=%x)\n", pSrb)); CDebugPrint(DebugLevelVerbose,(CODECNAME ": CodecOpenStream : StreamNumber=%d\n", StreamNumber)); RtlZeroMemory(pStrmEx, sizeof (STREAMEX)); // // check that the stream index requested isn't too high // or that the maximum number of instances hasn't been exceeded // if ( 0 <= StreamNumber && StreamNumber < DRIVER_STREAM_COUNT ) { unsigned StreamInstance; unsigned maxInstances = Streams[StreamNumber].hwStreamInfo.NumberOfPossibleInstances; // Search for next open slot for (StreamInstance=0; StreamInstance < maxInstances; ++StreamInstance) { if (pHwDevExt->pStrmEx[StreamNumber][StreamInstance] == NULL) break; } if (StreamInstance < maxInstances) { if (CodecVerifyFormat(pKSVBIDataFormat, StreamNumber, &pStrmEx->MatchedFormat)) { CASSERT (pHwDevExt->pStrmEx[StreamNumber][StreamInstance] == NULL); InitializeListHead( &pStrmEx->StreamControlQueue ); InitializeListHead( &pStrmEx->StreamDataQueue ); KeInitializeSpinLock( &pStrmEx->StreamControlSpinLock ); KeInitializeSpinLock( &pStrmEx->StreamDataSpinLock ); // Maintain an array of all the StreamEx structures in the HwDevExt // so that we can reference IRPs from any stream pHwDevExt->pStrmEx[StreamNumber][StreamInstance] = pStrmEx; // Save the Stream Format in the Stream Extension as well. pStrmEx->OpenedFormat = *pKSVBIDataFormat; // Set up pointers to the handlers for the stream data and control handlers pSrb->StreamObject->ReceiveDataPacket = (PVOID) Streams[StreamNumber].hwStreamObject.ReceiveDataPacket; pSrb->StreamObject->ReceiveControlPacket = (PVOID) Streams[StreamNumber].hwStreamObject.ReceiveControlPacket; // // The DMA flag must be set when the device will be performing DMA directly // to the data buffer addresses passed in to the ReceiceDataPacket routines. // pSrb->StreamObject->Dma = Streams[StreamNumber].hwStreamObject.Dma; // // The PIO flag must be set when the mini driver will be accessing the data // buffers passed in using logical addressing // pSrb->StreamObject->Pio = Streams[StreamNumber].hwStreamObject.Pio; pSrb->StreamObject->Allocator = Streams[StreamNumber].hwStreamObject.Allocator; // // How many extra bytes will be passed up from the driver for each frame? // pSrb->StreamObject->StreamHeaderMediaSpecific = Streams[StreamNumber].hwStreamObject.StreamHeaderMediaSpecific; pSrb->StreamObject->StreamHeaderWorkspace = Streams[StreamNumber].hwStreamObject.StreamHeaderWorkspace; // // Indicate the clock support available on this stream // pSrb->StreamObject->HwClockObject = Streams[StreamNumber].hwStreamObject.HwClockObject; // // Increment the instance count on this stream // pStrmEx->StreamInstance = StreamInstance; pHwDevExt->ActualInstances[StreamNumber]++; // Retain a private copy of the HwDevExt and StreamObject in the stream extension // so we can use a timer pStrmEx->pHwDevExt = pHwDevExt; // For timer use pStrmEx->pStreamObject = pSrb->StreamObject; // For timer use CDebugPrint( DebugLevelVerbose, ( CODECNAME ": Stream Instance %d\n", pStrmEx->StreamInstance )); // Copy the default filtering settings pStrmEx->ScanlinesRequested = pHwDevExt->ScanlinesRequested; pStrmEx->SubstreamsRequested = pHwDevExt->SubstreamsRequested; // // Load up default VBI info header RtlCopyMemory( &pStrmEx->CurrentVBIInfoHeader, &FakeVBIInfoHeader, sizeof( KS_VBIINFOHEADER ) ); #ifdef CCINPUTPIN // Init VBISrbOnHold's spin lock KeInitializeSpinLock(&pStrmEx->VBIOnHoldSpinLock); #endif // CCINPUTPIN // Init DSP state CCStateNew(&pStrmEx->State); } else { CDebugPrint(DebugLevelError, (CODECNAME ": CodecOpenStream : Invalid Stream Format=%x\n", pKSVBIDataFormat )); pSrb->Status = STATUS_INVALID_PARAMETER; } } else { CDebugPrint(DebugLevelError, (CODECNAME ": CodecOpenStream : Stream %d Too Many Instances=%d\n", StreamNumber, pHwDevExt->ActualInstances[StreamNumber] )); pSrb->Status = STATUS_INVALID_PARAMETER; } } else { CDebugPrint(DebugLevelError, (CODECNAME ": CodecOpenStream : Invalid StreamNumber=%d\n", StreamNumber )); pSrb->Status = STATUS_INVALID_PARAMETER; } CDebugPrint(DebugLevelTrace,(CODECNAME ":<---CodecOpenStream(pSrb=%x)\n", pSrb)); } /* ** CodecCloseStream() ** ** Close the requested data stream ** ** Arguments: ** ** pSrb the request block requesting to close the stream ** ** Returns: ** ** Side Effects: none */ VOID CodecCloseStream ( PHW_STREAM_REQUEST_BLOCK pSrb ) { PSTREAMEX pStrmEx = (PSTREAMEX)pSrb->StreamObject->HwStreamExtension; PHW_DEVICE_EXTENSION pHwDevExt = ((PHW_DEVICE_EXTENSION)pSrb->HwDeviceExtension); PHW_STREAM_REQUEST_BLOCK pCurrentSrb; PKSDATAFORMAT pKSDataFormat = pSrb->CommandData.OpenFormat; ULONG StreamNumber = pSrb->StreamObject->StreamNumber; ULONG StreamInstance = pStrmEx->StreamInstance; #ifdef CCINPUTPIN KIRQL Irql; #endif // CCINPUTPIN CDebugPrint(DebugLevelTrace,(CODECNAME ":--->CodecCloseStream(pSrb=%x)\n", pSrb)); // CDEBUG_BREAK(); // Uncomment this code to break here. CDebugPrint( DebugLevelVerbose, ( CODECNAME "Strm %d StrmInst %d ActualInst %d\n", StreamNumber, StreamInstance, pHwDevExt->ActualInstances[StreamNumber] )); // // Flush the stream data queue // #ifdef CCINPUTPIN // Is there an SRB 'on hold'?? KeAcquireSpinLock(&pStrmEx->VBIOnHoldSpinLock, &Irql); if (pStrmEx->pVBISrbOnHold) { PHW_STREAM_REQUEST_BLOCK pHoldSrb; pHoldSrb = pStrmEx->pVBISrbOnHold; pStrmEx->pVBISrbOnHold = NULL; KeReleaseSpinLock(&pStrmEx->VBIOnHoldSpinLock, Irql); pHoldSrb->Status = STATUS_CANCELLED; CDebugPrint(DebugLevelVerbose, (CODECNAME ":StreamClassStreamNotification(pHoldSrb->Status=0x%x)\n", pHoldSrb->Status)); StreamClassStreamNotification( StreamRequestComplete, pHoldSrb->StreamObject, pHoldSrb); pSrb = NULL; } else KeReleaseSpinLock(&pStrmEx->VBIOnHoldSpinLock, Irql); #endif // CCINPUTPIN while( QueueRemove( &pCurrentSrb, &pStrmEx->StreamDataSpinLock, &pStrmEx->StreamDataQueue )) { CDebugPrint( DebugLevelVerbose, ( CODECNAME ": Removing control SRB %x\n", pCurrentSrb )); pCurrentSrb->Status = STATUS_CANCELLED; StreamClassStreamNotification( StreamRequestComplete, pCurrentSrb->StreamObject, pCurrentSrb ); } // // Flush the stream control queue // while( QueueRemove( &pCurrentSrb, &pStrmEx->StreamControlSpinLock, &pStrmEx->StreamControlQueue )) { CDebugPrint( DebugLevelVerbose, ( CODECNAME ": Removing control SRB %x\n", pCurrentSrb )); pCurrentSrb->Status = STATUS_CANCELLED; StreamClassStreamNotification( StreamRequestComplete, pCurrentSrb->StreamObject, pCurrentSrb ); } // Destroy DSP state CCStateDestroy(&pStrmEx->State); pHwDevExt->ActualInstances[StreamNumber]--; CASSERT (pHwDevExt->pStrmEx [StreamNumber][StreamInstance] != 0); pHwDevExt->pStrmEx [StreamNumber][StreamInstance] = 0; // // the minidriver may wish to free any resources that were allocate at // open stream time etc. // pStrmEx->hMasterClock = NULL; CDebugPrint(DebugLevelTrace,(CODECNAME ":<---CodecCloseStream(pSrb=%x)\n", pSrb)); } /* ** CodecStreamInfo() ** ** Returns the information of all streams that are supported by the ** mini-driver ** ** Arguments: ** ** pSrb - Pointer to the STREAM_REQUEST_BLOCK ** pSrb->HwDeviceExtension - will be the hardware device extension for ** as initialised in HwInitialise ** ** Returns: ** ** Side Effects: none */ VOID CodecStreamInfo ( PHW_STREAM_REQUEST_BLOCK pSrb ) { int j; PHW_DEVICE_EXTENSION pHwDevExt = ((PHW_DEVICE_EXTENSION)pSrb->HwDeviceExtension); // // pick up the pointer to header which preceeds the stream info structs // PHW_STREAM_HEADER pstrhdr = (PHW_STREAM_HEADER)&(pSrb->CommandData.StreamBuffer->StreamHeader); // // pick up the pointer to the array of stream information data structures // PHW_STREAM_INFORMATION pstrinfo = (PHW_STREAM_INFORMATION)&(pSrb->CommandData.StreamBuffer->StreamInfo); CDebugPrint(DebugLevelTrace,(CODECNAME ":--->CodecStreamInfo(pSrb=%x)\n", pSrb)); // // verify that the buffer is large enough to hold our return data // CASSERT (pSrb->NumberOfBytesToTransfer >= sizeof (HW_STREAM_HEADER) + sizeof (HW_STREAM_INFORMATION) * DRIVER_STREAM_COUNT); // // Set the header // #define GLOBAL_PROPERTIES #ifdef GLOBAL_PROPERTIES StreamHeader.NumDevPropArrayEntries = NUMBER_OF_CODEC_PROPERTY_SETS; StreamHeader.DevicePropertiesArray = (PKSPROPERTY_SET) CodecPropertyTable; #else // !GLOBAL_PROPERTIES StreamHeader.NumDevPropArrayEntries = 0; StreamHeader.DevicePropertiesArray = (PKSPROPERTY_SET)NULL; #endif // GLOBAL_PROPERTIES *pstrhdr = StreamHeader; // // stuff the contents of each HW_STREAM_INFORMATION struct // for (j = 0; j < DRIVER_STREAM_COUNT; j++) { *pstrinfo++ = Streams[j].hwStreamInfo; } CDebugPrint(DebugLevelTrace,(CODECNAME ":<---CodecStreamInfo(pSrb=%x)\n", pSrb)); } /* ** CodecReceivePacket() ** ** Main entry point for receiving codec based request SRBs. This routine ** will always be called at High Priority. ** ** Note: This is an asyncronous entry point. The request does not complete ** on return from this function, the request only completes when a ** StreamClassDeviceNotification on this request block, of type ** DeviceRequestComplete, is issued. ** ** Arguments: ** ** pSrb - Pointer to the STREAM_REQUEST_BLOCK ** pSrb->HwDeviceExtension - will be the hardware device extension for ** as initialised in HwInitialise ** ** Returns: ** ** Side Effects: none */ VOID STREAMAPI CodecReceivePacket( IN PHW_STREAM_REQUEST_BLOCK pSrb ) { PHW_DEVICE_EXTENSION pHwDevExt = pSrb->HwDeviceExtension; CDebugPrint(DebugLevelTrace,(CODECNAME ":--->CodecReceivePacket(pSrb=%x)\n", pSrb)); // // Assume success // pSrb->Status = STATUS_SUCCESS; if( !pHwDevExt->bAdapterQueueInitialized ) { InitializeListHead( &pHwDevExt->AdapterSRBQueue ); KeInitializeSpinLock( &pHwDevExt->AdapterSRBSpinLock ); pHwDevExt->bAdapterQueueInitialized = TRUE; } // // determine the type of packet. // if( QueueAddIfNotEmpty( pSrb, &pHwDevExt->AdapterSRBSpinLock, &pHwDevExt->AdapterSRBQueue )) return; do { CDebugPrint(DebugLevelVerbose, (CODECNAME ": CodecReceivePacket: pSrb->Command=0x%x\n", pSrb->Command)); switch (pSrb->Command) { case SRB_INITIALIZE_DEVICE: // open the device CodecInitialize(pSrb); break; case SRB_UNINITIALIZE_DEVICE: // close the device. CodecUnInitialize(pSrb); break; case SRB_OPEN_STREAM: // open a stream CodecOpenStream(pSrb); break; case SRB_CLOSE_STREAM: // close a stream CodecCloseStream(pSrb); break; case SRB_GET_STREAM_INFO: // // return a block describing all the streams // CodecStreamInfo(pSrb); break; case SRB_GET_DATA_INTERSECTION: // // Return a format, given a range // switch( pSrb->CommandData.IntersectInfo->StreamNumber ) { case STREAM_VBI: CodecVBIFormatFromRange( pSrb ); break; #ifdef CCINPUTPIN // Both streams can use CodecCCFormatFromRange() because they // both use KSDATAFORMAT structures. case STREAM_CCINPUT: #endif // CCINPUTPIN case STREAM_CC: CodecCCFormatFromRange( pSrb ); break; default: // Unknown stream number? CDebugPrint( DebugLevelError, ( CODECNAME ": Unknown Stream Number\n" )); CDEBUG_BREAK(); pSrb->Status = STATUS_NOT_IMPLEMENTED; break; } break; // We should never get the following since this is a single instance // device case SRB_OPEN_DEVICE_INSTANCE: case SRB_CLOSE_DEVICE_INSTANCE: CDebugPrint(DebugLevelError, (CODECNAME ": CodecReceivePacket : SRB_%s_DEVICE_INSTANCE not supported\n", (pSrb->Command == SRB_OPEN_DEVICE_INSTANCE)? "OPEN":"CLOSE" )); CDEBUG_BREAK(); // Fall through to NOT IMPLEMENTED case SRB_UNKNOWN_DEVICE_COMMAND: // But this one we don't care about case SRB_INITIALIZATION_COMPLETE: // This one we don't care about case SRB_CHANGE_POWER_STATE: // This one we don't care about pSrb->Status = STATUS_NOT_IMPLEMENTED; break; case SRB_GET_DEVICE_PROPERTY: // // Get codec wide properties // CodecGetProperty (pSrb); break; case SRB_SET_DEVICE_PROPERTY: // // Set codec wide properties // CodecSetProperty (pSrb); break; case SRB_PAGING_OUT_DRIVER: case SRB_SURPRISE_REMOVAL: CDebugPrint(DebugLevelVerbose, (CODECNAME ": CodecReceivePacket: SRB_%s\n", (pSrb->Command == SRB_SURPRISE_REMOVAL)? "SURPRISE_REMOVAL" : "PAGING_OUT_DRIVER")); #if 0 { PSTREAMEX pStrmEx; unsigned StreamNumber, StreamInstance; unsigned maxInstances = Streams[StreamNumber].hwStreamInfo.NumberOfPossibleInstances; // Do we have any pins connected and paused/running? // Search any used slots... for (StreamNumber = 0; StreamNumber < DRIVER_STREAM_COUNT; ++StreamNumber) { for (StreamInstance=0; StreamInstance < maxInstances; ++StreamInstance) { pStrmEx = pHwDevExt->pStrmEx[StreamNumber][StreamInstance]; if (pStrmEx != NULL) { switch (pStrmEx->KSState) { case KSSTATE_RUN: case KSSTATE_PAUSE: CDebugPrint(DebugLevelError, (CODECNAME ": CodecReceivePacket : PAGING_OUT_DRIVER during RUN or PAUSE; failing request\n")); CDEBUG_BREAK(); pSrb->Status = STATUS_UNSUCCESSFUL; goto break3; default: // Shouldn't have to do anything here except return SUCCESS break; } } } } break3: } #endif //0 break; case SRB_UNKNOWN_STREAM_COMMAND: default: CDebugPrint(DebugLevelError, (CODECNAME ": CodecReceivePacket : UNKNOWN srb.Command = 0x%x\n", pSrb->Command)); CDEBUG_BREAK(); // // this is a request that we do not understand. Indicate invalid // command and complete the request // pSrb->Status = STATUS_NOT_IMPLEMENTED; } // // NOTE: // // all of the commands that we do, or do not understand can all be completed // syncronously at this point, so we can use a common callback routine here. // If any of the above commands require asyncronous processing, this will // have to change // CDebugPrint(DebugLevelVerbose, (CODECNAME ": CodecReceivePacket : DeviceRequestComplete(pSrb->Status=0x%x)\n", pSrb->Status)); StreamClassDeviceNotification( DeviceRequestComplete, pSrb->HwDeviceExtension, pSrb ); }while( QueueRemove( &pSrb, &pHwDevExt->AdapterSRBSpinLock, &pHwDevExt->AdapterSRBQueue )); CDebugPrint(DebugLevelTrace,(CODECNAME ":<---CodecReceivePacket(pSrb=%x)\n", pSrb)); } /* ** CodecCancelPacket () ** ** Request to cancel a packet that is currently in process in the minidriver ** ** Arguments: ** ** pSrb - pointer to request packet to cancel ** ** Returns: ** ** Side Effects: none */ VOID STREAMAPI CodecCancelPacket( PHW_STREAM_REQUEST_BLOCK pSrb ) { PSTREAMEX pStrmEx = (PSTREAMEX)pSrb->StreamObject->HwStreamExtension; PHW_DEVICE_EXTENSION pHwDevExt = ((PHW_DEVICE_EXTENSION)pSrb->HwDeviceExtension); CDebugPrint(DebugLevelTrace,(CODECNAME ":--->CodecCancelPacket(pSrb=%x)\n", pSrb)); CASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL); // // Check whether the SRB to cancel is in use by this stream // #ifdef CCINPUTPIN // Is SRB to cancel 'on hold'?? KeAcquireSpinLockAtDpcLevel(&pStrmEx->VBIOnHoldSpinLock); if (pStrmEx->pVBISrbOnHold && pSrb == pStrmEx->pVBISrbOnHold) { pStrmEx->pVBISrbOnHold = NULL; KeReleaseSpinLockFromDpcLevel(&pStrmEx->VBIOnHoldSpinLock); pSrb->Status = STATUS_CANCELLED; CDebugPrint(DebugLevelVerbose, (CODECNAME ":StreamClassStreamNotification(pSrb->Status=0x%x)\n", pSrb->Status)); StreamClassStreamNotification( StreamRequestComplete, pSrb->StreamObject, pSrb); pSrb = NULL; } else KeReleaseSpinLockFromDpcLevel(&pStrmEx->VBIOnHoldSpinLock); if (NULL == pSrb) ; // We're done; we CANCELLED the SRB above else #endif // CCINPUTPIN // // Attempt removal from data queue // if( QueueRemoveSpecific( pSrb, &pStrmEx->StreamDataSpinLock, &pStrmEx->StreamDataQueue )) { pSrb->Status = STATUS_CANCELLED; CDebugPrint(DebugLevelVerbose, (CODECNAME ":StreamRequestComplete(ReadyForNextStreamDataRequest,pSrb->Status=0x%x)\n", pSrb->Status)); StreamClassStreamNotification( StreamRequestComplete, pSrb->StreamObject, pSrb ); } else // // Attempt removal from command queue // if( QueueRemoveSpecific( pSrb, &pStrmEx->StreamControlSpinLock, &pStrmEx->StreamControlQueue )) { pSrb->Status = STATUS_CANCELLED; CDebugPrint(DebugLevelVerbose, (CODECNAME ":StreamRequestComplete(ReadyForNextStreamControlRequest,pSrb->Status=0x%x)\n", pSrb->Status)); StreamClassStreamNotification( StreamRequestComplete, pSrb->StreamObject, pSrb ); } else // // Attempt removal from adapter queue // if( QueueRemoveSpecific( pSrb, &pHwDevExt->AdapterSRBSpinLock, &pHwDevExt->AdapterSRBQueue )) { pSrb->Status = STATUS_CANCELLED; CDebugPrint(DebugLevelVerbose, (CODECNAME ":DeviceRequestComplete(pSrb->Status=0x%x)\n", pSrb->Status)); StreamClassDeviceNotification( DeviceRequestComplete, pSrb->StreamObject, pSrb ); } else CDebugPrint( DebugLevelWarning, ( CODECNAME "SRB %x not found to cancel\n", pSrb )); CDebugPrint(DebugLevelTrace,(CODECNAME ":<---CodecCancelPacket(pSrb=%x)\n", pSrb)); } /* ** CodecTimeoutPacket() ** ** This routine is called when a packet has been in the minidriver for ** too long. The codec must decide what to do with the packet ** ** Arguments: ** ** pSrb - pointer to the request packet that timed out ** ** Returns: ** ** Side Effects: none */ VOID STREAMAPI CodecTimeoutPacket( PHW_STREAM_REQUEST_BLOCK pSrb ) { CDebugPrint(DebugLevelTrace,(CODECNAME ":--->CodecTimeoutPacket(pSrb=%x)\n", pSrb)); // // if we timeout while playing, then we need to consider this // condition an error, and reset the hardware, and reset everything // as well as cancelling this and all requests // // // if we are not playing, and this is a CTRL request, we still // need to reset everything as well as cancelling this and all requests // // // if this is a data request, and the device is paused, we probably have // run out of data buffer, and need more time, so just reset the timer, // and let the packet continue // // pSrb->TimeoutCounter = pSrb->TimeoutOriginal; pSrb->TimeoutCounter = 0; CDebugPrint(DebugLevelTrace,(CODECNAME ":<---CodecTimeoutPacket(pSrb=%x)\n", pSrb)); } #if 0 /* ** CompleteStreamSRB () ** ** This routine is called when a packet is being completed. ** The optional second notification type is used to indicate ReadyForNext ** ** Arguments: ** ** pSrb - pointer to the request packet that timed out ** ** NotificationType1 - what kind of notification to return ** ** NotificationType2 - what kind of notification to return (may be 0) ** ** ** Returns: ** ** Side Effects: none */ VOID CompleteStreamSRB ( IN PHW_STREAM_REQUEST_BLOCK pSrb, STREAM_MINIDRIVER_STREAM_NOTIFICATION_TYPE NotificationType1, BOOL fUseNotification2, STREAM_MINIDRIVER_STREAM_NOTIFICATION_TYPE NotificationType2 ) { CDebugPrint(DebugLevelTrace, (CODECNAME ":--->CompleteStreamSRB(pSrb=%x)\n", pSrb)); CDebugPrint(DebugLevelVerbose, (CODECNAME ": CompleteStreamSRB : NotificationType1=%d\n", NotificationType1 )); StreamClassStreamNotification( NotificationType1, pSrb->StreamObject, pSrb); if (fUseNotification2) { // ReadyForNext CDebugPrint(DebugLevelVerbose, (CODECNAME ": CompleteStreamSRB : NotificationType2=%d\n", NotificationType2 )); StreamClassStreamNotification( NotificationType2, pSrb->StreamObject); } CDebugPrint(DebugLevelTrace,(CODECNAME ":<---CompleteStreamSRB(pSrb=%x)\n", pSrb)); } /* ** CompleteDeviceSRB () ** ** This routine is called when a packet is being completed. ** The optional second notification type is used to indicate ReadyForNext ** ** Arguments: ** ** pSrb - pointer to the request packet that timed out ** ** NotificationType - what kind of notification to return ** ** fReadyForNext - Send the "ReadyForNextSRB" ** ** ** Returns: ** ** Side Effects: none */ VOID CompleteDeviceSRB ( IN PHW_STREAM_REQUEST_BLOCK pSrb, IN STREAM_MINIDRIVER_DEVICE_NOTIFICATION_TYPE NotificationType, BOOL fReadyForNext ) { CDebugPrint(DebugLevelTrace,(CODECNAME ":--->CompleteDeviceSRB(pSrb=%x)\n", pSrb)); CDebugPrint(DebugLevelVerbose, (CODECNAME ": CompleteDeviceSRB : NotificationType=%d\n", NotificationType )); StreamClassDeviceNotification( NotificationType, pSrb->HwDeviceExtension, pSrb); if (fReadyForNext) { CDebugPrint(DebugLevelVerbose, (CODECNAME ": CompleteDeviceSRB : ReadyForNextDeviceRequest\n")); StreamClassDeviceNotification( ReadyForNextDeviceRequest, pSrb->HwDeviceExtension); } CDebugPrint(DebugLevelTrace,(CODECNAME ":<---CompleteDeviceSRB(pSrb=%x)\n", pSrb)); } #endif //0 /* ** CodecCompareGUIDsAndFormatSize() ** ** Checks for a match on the three GUIDs and FormatSize ** ** Arguments: ** ** IN DataRange1 ** IN DataRange2 ** ** Returns: ** ** TRUE if all elements match ** FALSE if any are different ** ** Side Effects: none */ BOOL CodecCompareGUIDsAndFormatSize( IN PKSDATARANGE DataRange1, IN PKSDATARANGE DataRange2, BOOLEAN bCheckSize ) { BOOL rval = FALSE; CDebugPrint(DebugLevelTrace, (CODECNAME ":--->CodecCompareGUIDsAndFormatSize(DataRange1=%x,DataRange2=%x,bCheckSize=%s)\r\n", DataRange1, DataRange2, bCheckSize ? "TRUE":"FALSE")); if ( IsEqualGUID(&DataRange1->MajorFormat, &KSDATAFORMAT_TYPE_WILDCARD) || IsEqualGUID(&DataRange2->MajorFormat, &KSDATAFORMAT_TYPE_WILDCARD) || IsEqualGUID(&DataRange1->MajorFormat, &DataRange2->MajorFormat) ) { if ( !IsEqualGUID(&DataRange1->MajorFormat, &DataRange2->MajorFormat) ) { CDebugPrint(DebugLevelVerbose, (CODECNAME ": CodecCompareGUIDsAndFormatSize : Matched MajorFormat Using Wildcard:\n\t[%s] vs. [%s]\n", &DataRange1->MajorFormat, &DataRange2->MajorFormat )); } if ( IsEqualGUID(&DataRange1->SubFormat, &KSDATAFORMAT_SUBTYPE_WILDCARD) || IsEqualGUID(&DataRange2->SubFormat, &KSDATAFORMAT_SUBTYPE_WILDCARD) || IsEqualGUID(&DataRange1->SubFormat, &DataRange2->SubFormat) ) { if ( !IsEqualGUID(&DataRange1->SubFormat, &DataRange2->SubFormat) ) { CDebugPrint(DebugLevelVerbose, (CODECNAME ": CodecCompareGUIDsAndFormatSize : Matched SubFormat Using Wildcard:\n\t[%s] vs. [%s]\n", &DataRange1->SubFormat, &DataRange2->SubFormat )); } if ( IsEqualGUID(&DataRange1->Specifier, &KSDATAFORMAT_SPECIFIER_NONE) || IsEqualGUID(&DataRange2->Specifier, &KSDATAFORMAT_SPECIFIER_NONE) || IsEqualGUID(&DataRange1->Specifier, &DataRange2->Specifier) ) { if ( !IsEqualGUID(&DataRange1->Specifier, &DataRange2->Specifier) ) { CDebugPrint(DebugLevelVerbose, (CODECNAME ": CodecCompareGUIDsAndFormatSize : Matched Specifier Using Wildcard:\n\t[%s] vs. [%s]\n", &DataRange1->Specifier, &DataRange2->Specifier )); } if ( !bCheckSize || DataRange1->FormatSize == DataRange2->FormatSize) { rval = TRUE; } else { CDebugPrint(DebugLevelVerbose, (CODECNAME ": CodecCompareGUIDsAndFormatSize : FormatSize mismatch=%d vs. %d\n", DataRange1->FormatSize, DataRange2->FormatSize )); } } else { CDebugPrint(DebugLevelVerbose, (CODECNAME ": CodecCompareGUIDsAndFormatSize : Specifier mismatch:\n\t[%s] vs. [%s]\n", &DataRange1->Specifier, &DataRange2->Specifier )); } } else { CDebugPrint(DebugLevelVerbose, (CODECNAME ": CodecCompareGUIDsAndFormatSize : Subformat mismatch:\n\t[%s] vs. [%s]\n", &DataRange1->SubFormat, &DataRange2->SubFormat )); } } else { CDebugPrint(DebugLevelVerbose, (CODECNAME ": CodecCompareGUIDsAndFormatSize : MajorFormat mismatch:\n\t[%s] vs. [%s]\n", &DataRange1->MajorFormat, &DataRange2->MajorFormat )); } CDebugPrint(DebugLevelTrace, (CODECNAME ":<---CodecCompareGUIDsAndFormatSize(DataRange1=%x,DataRange2=%x,bCheckSize=%s)=%s\n", DataRange1, DataRange2, bCheckSize ? "TRUE":"FALSE", rval? "TRUE":"FALSE")); return rval; } /* ** CodecVerifyFormat() ** ** Checks the validity of a format request ** ** Arguments: ** ** pKSDataFormat - pointer to a KS_DATAFORMAT_VBIINFOHEADER structure. ** ** Returns: ** ** TRUE if the format is supported ** FALSE if the format cannot be suppored ** ** Side Effects: none */ BOOL CodecVerifyFormat(IN KSDATAFORMAT *pKSDataFormat, UINT StreamNumber, PKSDATARANGE pMatchedFormat ) { BOOL rval = FALSE; ULONG FormatCount; PKS_DATARANGE_VIDEO ThisFormat; PKS_DATAFORMAT_VBIINFOHEADER pKSVBIDataFormat = ( PKS_DATAFORMAT_VBIINFOHEADER )pKSDataFormat; CDebugPrint(DebugLevelTrace,(CODECNAME ":--->CodecVerifyFormat(%x)\n", pKSDataFormat)); for( FormatCount = 0; rval == FALSE && FormatCount < Streams[StreamNumber].hwStreamInfo.NumberOfFormatArrayEntries; FormatCount++ ) { CDebugPrint(DebugLevelTrace,(CODECNAME , "Testing stream %d against format %x\r\n", StreamNumber, FormatCount )); ThisFormat = ( PKS_DATARANGE_VIDEO )Streams[StreamNumber].hwStreamInfo.StreamFormatsArray[FormatCount]; if( !CodecCompareGUIDsAndFormatSize( pKSDataFormat, &ThisFormat->DataRange, FALSE ) ) { CDebugPrint( DebugLevelVerbose, ( CODECNAME ": General format mismatch\n" )); continue; } if( IsEqualGUID( &ThisFormat->DataRange.Specifier, &KSDATAFORMAT_SPECIFIER_VBI ) ) { if( pKSVBIDataFormat->VBIInfoHeader.VideoStandard != KS_AnalogVideo_NTSC_M ) { CDebugPrint( DebugLevelVerbose, ( CODECNAME ": Incompatible video standard\n" )); continue; } if( pKSVBIDataFormat->VBIInfoHeader.StartLine < MIN_VBI_Y_SAMPLES ) { CDebugPrint( DebugLevelVerbose, ( CODECNAME ": VBIInfoHeader.StartLine too small %u\n", pKSVBIDataFormat->VBIInfoHeader.StartLine )); continue; } if( pKSVBIDataFormat->VBIInfoHeader.EndLine > MAX_VBI_Y_SAMPLES ) { CDebugPrint( DebugLevelVerbose, ( CODECNAME ": VBIInfoHeader.EndLine too big %u\n", pKSVBIDataFormat->VBIInfoHeader.EndLine )); continue; } if( pKSVBIDataFormat->VBIInfoHeader.SamplesPerLine < MIN_VBI_X_SAMPLES || pKSVBIDataFormat->VBIInfoHeader.SamplesPerLine > MAX_VBI_X_SAMPLES ) { CDebugPrint( DebugLevelVerbose, ( CODECNAME ": Invalid VBIInfoHeader.SamplesPerLine %u\n", pKSVBIDataFormat->VBIInfoHeader.SamplesPerLine )); continue; } rval = TRUE; } else if( IsEqualGUID( &ThisFormat->DataRange.Specifier, &KSDATAFORMAT_SPECIFIER_NONE ) ) rval = TRUE; else { CDebugPrint( DebugLevelVerbose, ( CODECNAME ": Incompatible major format\n" )); continue; } if( rval == TRUE && pMatchedFormat ) *pMatchedFormat = ThisFormat->DataRange; } CDebugPrint(DebugLevelTrace,(CODECNAME ":<---CodecVerifyFormat(%x)=%s\n", pKSDataFormat, rval? "TRUE":"FALSE")); return rval; } /* ** CodecVBIFormatFromRange() ** ** Returns a DATAFORMAT from a DATARANGE ** ** Arguments: ** ** IN PHW_STREAM_REQUEST_BLOCK pSrb ** ** Returns: ** ** TRUE if the format is supported ** FALSE if the format cannot be suppored ** ** Side Effects: none */ BOOL CodecVBIFormatFromRange( IN PHW_STREAM_REQUEST_BLOCK pSrb ) { BOOL bStatus = FALSE; PSTREAM_DATA_INTERSECT_INFO IntersectInfo; PKSDATARANGE DataRange; BOOL OnlyWantsSize; ULONG StreamNumber; ULONG j; ULONG NumberOfFormatArrayEntries; PKSDATAFORMAT *pAvailableFormats; CDebugPrint(DebugLevelTrace,(CODECNAME ":--->CodecVBIFormatFromRange(pSrb=%x)\n", pSrb)); IntersectInfo = pSrb->CommandData.IntersectInfo; StreamNumber = IntersectInfo->StreamNumber; DataRange = IntersectInfo->DataRange; pSrb->ActualBytesTransferred = 0; // // Check that the stream number is valid // // if (StreamNumber < DRIVER_STREAM_COUNT) // { NumberOfFormatArrayEntries = Streams[StreamNumber].hwStreamInfo.NumberOfFormatArrayEntries; // // Get the pointer to the array of available formats // pAvailableFormats = Streams[StreamNumber].hwStreamInfo.StreamFormatsArray; // // Is the caller trying to get the format, or the size of the format? // OnlyWantsSize = (IntersectInfo->SizeOfDataFormatBuffer == sizeof(ULONG)); // // Walk the formats supported by the stream searching for a match // of the three GUIDs which together define a DATARANGE // for (j = 0; j < NumberOfFormatArrayEntries; j++, pAvailableFormats++) { if ( CodecCompareGUIDsAndFormatSize(DataRange, *pAvailableFormats, TRUE) ) { #ifdef KS_DATARANGE_VIDEO_VBI__EQ__KS_DATAFORMAT_VBIINFOHEADER ULONG FormatSize = (*pAvailableFormats)->FormatSize; #else PKS_DATARANGE_VIDEO_VBI pDataRangeVBI = (PKS_DATARANGE_VIDEO_VBI)*pAvailableFormats; ULONG FormatSize = sizeof( KS_DATAFORMAT_VBIINFOHEADER ); #endif // Is the caller trying to get the format, or the size of the format? if ( IntersectInfo->SizeOfDataFormatBuffer == sizeof(FormatSize) ) { CDebugPrint(DebugLevelVerbose, (CODECNAME ": CodecVBIFormatFromRange : Format Size=%d\n", FormatSize)); *(PULONG)IntersectInfo->DataFormatBuffer = FormatSize; pSrb->ActualBytesTransferred = sizeof(FormatSize); bStatus = TRUE; } else { // Verify that there is enough room in the supplied buffer for the whole thing if ( IntersectInfo->SizeOfDataFormatBuffer >= FormatSize ) { #ifdef KS_DATARANGE_VIDEO_VBI__EQ__KS_DATAFORMAT_VBIINFOHEADER RtlCopyMemory(IntersectInfo->DataFormatBuffer, *pAvailableFormats, FormatSize); pSrb->ActualBytesTransferred = FormatSize; #else PKS_DATAFORMAT_VBIINFOHEADER InterVBIHdr = (PKS_DATAFORMAT_VBIINFOHEADER)IntersectInfo->DataFormatBuffer; RtlCopyMemory(&InterVBIHdr->DataFormat, &pDataRangeVBI->DataRange, sizeof(KSDATARANGE)); ((PKSDATAFORMAT)IntersectInfo->DataFormatBuffer)->FormatSize = FormatSize; RtlCopyMemory(&InterVBIHdr->VBIInfoHeader, &pDataRangeVBI->VBIInfoHeader, sizeof(KS_VBIINFOHEADER)); pSrb->ActualBytesTransferred = FormatSize; #endif bStatus = TRUE; } else { CDebugPrint(DebugLevelVerbose, (CODECNAME ": CodecVBIFormatFromRange : Buffer Too Small=%d vs. %d\n", IntersectInfo->SizeOfDataFormatBuffer, FormatSize)); pSrb->Status = STATUS_BUFFER_TOO_SMALL; } } break; } } if ( j == NumberOfFormatArrayEntries ) { CDebugPrint(DebugLevelVerbose,(CODECNAME ": CodecVBIFormatFromRange : Stream Format not found.\n" )); } // } // else // { // CDebugPrint(DebugLevelVerbose,(CODECNAME ": CodecVBIFormatFromRange : StreamNumber too big=%d\n", StreamNumber)); // pSrb->Status = STATUS_NOT_IMPLEMENTED; // bStatus = FALSE; // CDEBUG_BREAK(); // } CDebugPrint(DebugLevelTrace, (CODECNAME ":<---CodecVBIFormatFromRange(pSrb=%x)=%s\n", pSrb, bStatus ? "TRUE" : "FALSE" )); return bStatus; } /* ** CodecCCFormatFromRange() ** ** Returns a DATAFORMAT from a DATARANGE ** ** Arguments: ** ** IN PHW_STREAM_REQUEST_BLOCK pSrb ** ** Returns: ** ** TRUE if the format is supported ** FALSE if the format cannot be suppored ** ** Side Effects: none */ BOOL CodecCCFormatFromRange( IN PHW_STREAM_REQUEST_BLOCK pSrb ) { BOOL bStatus = FALSE; PSTREAM_DATA_INTERSECT_INFO IntersectInfo; PKSDATARANGE DataRange; BOOL OnlyWantsSize; ULONG StreamNumber; ULONG j; ULONG NumberOfFormatArrayEntries; PKSDATAFORMAT *pAvailableFormats; CDebugPrint(DebugLevelTrace,(CODECNAME ":--->CodecCCFormatFromRange(pSrb=%x)\n", pSrb)); IntersectInfo = pSrb->CommandData.IntersectInfo; StreamNumber = IntersectInfo->StreamNumber; DataRange = IntersectInfo->DataRange; pSrb->ActualBytesTransferred = 0; // // Check that the stream number is valid // // if (StreamNumber < DRIVER_STREAM_COUNT) // { NumberOfFormatArrayEntries = Streams[StreamNumber].hwStreamInfo.NumberOfFormatArrayEntries; // // Get the pointer to the array of available formats // pAvailableFormats = Streams[StreamNumber].hwStreamInfo.StreamFormatsArray; // // Is the caller trying to get the format, or the size of the format? // OnlyWantsSize = (IntersectInfo->SizeOfDataFormatBuffer == sizeof(ULONG)); // // Walk the formats supported by the stream searching for a match // of the three GUIDs which together define a DATARANGE // for (j = 0; j < NumberOfFormatArrayEntries; j++, pAvailableFormats++) { if ( CodecCompareGUIDsAndFormatSize(DataRange, *pAvailableFormats, TRUE) ) { PKSDATARANGE pDataRangeCC = (PKSDATARANGE)*pAvailableFormats; ULONG FormatSize = sizeof( KSDATARANGE ); // Is the caller trying to get the format, or the size of it? if ( IntersectInfo->SizeOfDataFormatBuffer == sizeof(FormatSize) ) { CDebugPrint(DebugLevelVerbose, (CODECNAME ": CodecCCFormatFromRange : Format Size=%d\n", FormatSize)); *(PULONG)IntersectInfo->DataFormatBuffer = FormatSize; pSrb->ActualBytesTransferred = sizeof(FormatSize); bStatus = TRUE; } else { // Verify that there is enough room in the supplied buffer // for the whole thing if ( IntersectInfo->SizeOfDataFormatBuffer >= FormatSize ) { PKSDATAFORMAT InterCCHdr = (PKSDATAFORMAT)IntersectInfo->DataFormatBuffer; *InterCCHdr = *pDataRangeCC; InterCCHdr->FormatSize = FormatSize; pSrb->ActualBytesTransferred = FormatSize; bStatus = TRUE; } else { CDebugPrint(DebugLevelVerbose, (CODECNAME ": CodecCCFormatFromRange : Buffer Too Small=%d vs. %d\n", IntersectInfo->SizeOfDataFormatBuffer, FormatSize)); pSrb->Status = STATUS_BUFFER_TOO_SMALL; } } break; } } if ( j == NumberOfFormatArrayEntries ) { CDebugPrint(DebugLevelVerbose,(CODECNAME ": CodecCCFormatFromRange : Stream Format not found.\n" )); } // } // else // { // CDebugPrint(DebugLevelVerbose,(CODECNAME ": CodecVBIFormatFromRange : StreamNumber too big=%d\n", StreamNumber)); // pSrb->Status = STATUS_NOT_IMPLEMENTED; // bStatus = FALSE; // CDEBUG_BREAK(); // } CDebugPrint(DebugLevelTrace, (CODECNAME ":<---CodecCCFormatFromRange(pSrb=%x)=%s\n", pSrb, bStatus ? "TRUE" : "FALSE" )); return bStatus; } /* ** QueueAddIfNotEmpty ** ** Adds an SRB to the current queue if it is not empty ** ** Arguments: ** ** IN PHW_STREAM_REQUEST_BLOCK pSrb ** IN PKSPIN_LOCK pQueueSpinLock ** IN PLIST_ENTRY pQueue ** ** Returns: ** ** TRUE if SRB was added (queue is not empty) ** FALSE if SRB was not added (queue is empty) ** Side Effects: none */ BOOL STREAMAPI QueueAddIfNotEmpty( IN PHW_STREAM_REQUEST_BLOCK pSrb, IN PKSPIN_LOCK pQueueSpinLock, IN PLIST_ENTRY pQueue ) { KIRQL Irql; PSRB_EXTENSION pSrbExtension; BOOL bAddedSRB = FALSE; CDebugPrint( DebugLevelVerbose, ( CODECNAME ":--->QueueAddIfNotEmpty %x\n", pSrb )); CASSERT( pSrb ); pSrbExtension = ( PSRB_EXTENSION )pSrb->SRBExtension; CASSERT( pSrbExtension ); KeAcquireSpinLock( pQueueSpinLock, &Irql ); if( !IsListEmpty( pQueue )) { pSrbExtension->pSrb = pSrb; InsertTailList( pQueue, &pSrbExtension->ListEntry ); bAddedSRB = TRUE; } KeReleaseSpinLock( pQueueSpinLock, Irql ); CDebugPrint( DebugLevelVerbose, ( CODECNAME ": %s%x\n", bAddedSRB ? "Added SRB to Queue " : ": Queue is empty, not adding ", pSrb )); CDebugPrint( DebugLevelVerbose, ( CODECNAME ":<---QueueAddIfNotEmpty %x\n", bAddedSRB )); return bAddedSRB; } /* ** QueueAdd ** ** Adds an SRB to the current queue unconditionally ** ** Arguments: ** ** IN PHW_STREAM_REQUEST_BLOCK pSrb ** IN PKSPIN_LOCK pQueueSpinLock ** IN PLIST_ENTRY pQueue ** ** Returns: ** ** TRUE ** Side Effects: none */ BOOL STREAMAPI QueueAdd( IN PHW_STREAM_REQUEST_BLOCK pSrb, IN PKSPIN_LOCK pQueueSpinLock, IN PLIST_ENTRY pQueue ) { KIRQL Irql; PSRB_EXTENSION pSrbExtension; CDebugPrint( DebugLevelVerbose, ( CODECNAME ":--->QueueAdd %x\n", pSrb )); CASSERT( pSrb ); pSrbExtension = ( PSRB_EXTENSION )pSrb->SRBExtension; CASSERT( pSrbExtension ); KeAcquireSpinLock( pQueueSpinLock, &Irql ); pSrbExtension->pSrb = pSrb; InsertTailList( pQueue, &pSrbExtension->ListEntry ); KeReleaseSpinLock( pQueueSpinLock, Irql ); CDebugPrint( DebugLevelVerbose, ( CODECNAME ": Added SRB %x to Queue\n", pSrb )); CDebugPrint( DebugLevelVerbose, ( CODECNAME ":<---QueueAdd\n" )); return TRUE; } /* ** QueueRemove ** ** Removes the next available SRB from the current queue ** ** Arguments: ** ** IN PHW_STREAM_REQUEST_BLOCK * pSrb ** IN PKSPIN_LOCK pQueueSpinLock ** IN PLIST_ENTRY pQueue ** ** Returns: ** ** TRUE if SRB was removed ** FALSE if SRB was not removed ** Side Effects: none */ BOOL STREAMAPI QueueRemove( IN OUT PHW_STREAM_REQUEST_BLOCK * pSrb, IN PKSPIN_LOCK pQueueSpinLock, IN PLIST_ENTRY pQueue ) { KIRQL Irql; BOOL bRemovedSRB = FALSE; CDebugPrint( DebugLevelVerbose, ( CODECNAME ":--->QueueRemove\n" )); KeAcquireSpinLock( pQueueSpinLock, &Irql ); *pSrb = ( PHW_STREAM_REQUEST_BLOCK )NULL; CDebugPrint( DebugLevelVerbose, ( CODECNAME ": QFlink %x QBlink %x\n", pQueue->Flink, pQueue->Blink )); if( !IsListEmpty( pQueue )) { PHW_STREAM_REQUEST_BLOCK * pCurrentSrb; PUCHAR Ptr = ( PUCHAR )RemoveHeadList( pQueue ); pCurrentSrb = ( PHW_STREAM_REQUEST_BLOCK * )((( PUCHAR )Ptr ) + sizeof( LIST_ENTRY )); CASSERT( *pCurrentSrb ); *pSrb = *pCurrentSrb; bRemovedSRB = TRUE; } else CDebugPrint( DebugLevelVerbose, ( CODECNAME ": Queue is empty\n" )); KeReleaseSpinLock( pQueueSpinLock, Irql ); CDebugPrint( DebugLevelVerbose, ( CODECNAME ":<---QueueRemove %x %x\n", bRemovedSRB, *pSrb )); return bRemovedSRB; } /* ** QueueRemoveSpecific ** ** Removes a specific SRB from the queue ** ** Arguments: ** ** IN PHW_STREAM_REQUEST_BLOCK pSrb ** IN PKSPIN_LOCK pQueueSpinLock ** IN PLIST_ENTRY pQueue ** ** Returns: ** ** TRUE if the SRB was found and removed ** FALSE if the SRB was not found ** ** Side Effects: none */ BOOL STREAMAPI QueueRemoveSpecific( IN PHW_STREAM_REQUEST_BLOCK pSrb, IN PKSPIN_LOCK pQueueSpinLock, IN PLIST_ENTRY pQueue ) { KIRQL Irql; PHW_STREAM_REQUEST_BLOCK * pCurrentSrb; PLIST_ENTRY pCurrentEntry; BOOL bRemovedSRB = FALSE; CASSERT( pSrb ); CDebugPrint( DebugLevelVerbose, ( CODECNAME ":--->QueueRemoveSpecific %x\n", pSrb )); KeAcquireSpinLock( pQueueSpinLock, &Irql ); if( !IsListEmpty( pQueue )) { pCurrentEntry = pQueue->Flink; while(( pCurrentEntry != pQueue ) && !bRemovedSRB ) { pCurrentSrb = ( PHW_STREAM_REQUEST_BLOCK * )((( PUCHAR )pCurrentEntry ) + sizeof( LIST_ENTRY )); CASSERT( *pCurrentSrb ); if( *pCurrentSrb == pSrb ) { RemoveEntryList( pCurrentEntry ); bRemovedSRB = TRUE; } pCurrentEntry = pCurrentEntry->Flink; } } KeReleaseSpinLock( pQueueSpinLock, Irql ); if( IsListEmpty( pQueue )) CDebugPrint( DebugLevelVerbose, ( CODECNAME ": Queue is empty\n" )); CDebugPrint( DebugLevelVerbose, ( CODECNAME ":<---QueueRemoveSpecific %x\n", bRemovedSRB )); return bRemovedSRB; } /* ** QueueEmpty ** ** Indicates whether or not the queue is empty ** ** Arguments: ** ** IN PKSPIN_LOCK pQueueSpinLock ** IN PLIST_ENTRY pQueue ** ** Returns: ** ** TRUE if queue is empty ** FALSE if queue is not empty ** Side Effects: none */ BOOL STREAMAPI QueueEmpty( IN PKSPIN_LOCK pQueueSpinLock, IN PLIST_ENTRY pQueue ) { KIRQL Irql; BOOL bEmpty = FALSE; CDebugPrint( DebugLevelVerbose, ( CODECNAME ":---> QueueEmpty\n" )); KeAcquireSpinLock( pQueueSpinLock, &Irql ); bEmpty = IsListEmpty( pQueue ); KeReleaseSpinLock( pQueueSpinLock, Irql ); CDebugPrint( DebugLevelVerbose, ( CODECNAME ":<--- QueueEmpty %x\n", bEmpty )); return bEmpty; }