📄 iocontrol.c
字号:
//++
// File Name:
// IoControl.c
//
// Contents:
// Dispatch routines for control code: IRP_MJ_DEVICE_CONTROL
//--
//
// Driver-specific header files
//
#include "version.h"
#include "Ave2k.h"
#include "Ave2kregs.h"
#include "Ave2kOverlay.h"
#include "ave2kutil.h"
#include "saa7111.h"
#include "iic.h"
#include "AudioCtrl.h"
#include "debi.h"
//External defined global variables shared by all devices
//extern DISPLAY_PARAMETER DisplayParameter;
extern ULONG VGAAddress;
static int CheckChannel(PDEVICE_EXTENSION pDE, ULONG Channel);
void InitializeHardware(PDEVICE_EXTENSION pDE);
//
// Forward declarations of local routines
//
//
static NTSTATUS ave2kOverlayControl(PDEVICE_EXTENSION pDE);
//static BOOLEAN SetClipRect(PDEVICE_EXTENSION pDE,PAVE2KCLIPLIST pClipList);
//
// If the compiler can handle it, save space
// by making various routines pageable
//
#ifdef ALLOC_PRAGMA
#pragma alloc_text( page, Ave2kDispatchDeviceIoControl )
#endif //ALLOC_PRAGMA
//++
// Function:
// Ave2kDispatchDeviceIoControl
//
// Description:
// This function dispatches DeviceIoControl
// requests from Win32
//
// Arguments:
// Pointer to Device object
// Pointer to IRP for this request
//
// Return Value:
// This function returns STATUS_XXX
//--
NTSTATUS
Ave2kDispatchDeviceIoControl(
IN PDEVICE_OBJECT pDO,
IN PIRP Irp
)
{
NTSTATUS status;
ULONG RegIndex, RegValue;
PIO_STACK_LOCATION IrpStack =
IoGetCurrentIrpStackLocation( Irp );
PDEVICE_EXTENSION pDE =
(PDEVICE_EXTENSION)pDO->DeviceExtension;
ULONG ControlCode =
IrpStack->Parameters.
DeviceIoControl.IoControlCode;
ULONG OutBufferSize =
IrpStack->Parameters.
DeviceIoControl.OutputBufferLength;
ULONG InBufferSize =
IrpStack->Parameters.
DeviceIoControl.InputBufferLength;
// PXX_PERF_DATA pBuffer =
// (PXX_PERF_DATA)Irp->
// AssociatedIrp.SystemBuffer;
int nVT;
switch( ControlCode )
{
#if(TARGET_DEVICE==TD_TEST)
case IOCTL_READ_REGISTER:
if(OutBufferSize != sizeof(ULONG) || InBufferSize != sizeof(ULONG)){
status = STATUS_INVALID_PARAMETER;
break;
}
RegIndex=*((ULONG *)Irp->AssociatedIrp.SystemBuffer);
RegValue = Ave2kReadRegister(pDE,RegIndex);
*((ULONG *)Irp->AssociatedIrp.SystemBuffer) = RegValue;
Irp->IoStatus.Information = sizeof(RegValue);
status = STATUS_SUCCESS;
break;
case IOCTL_WRITE_REGISTER:
if(InBufferSize != 2*sizeof(ULONG) || OutBufferSize != 0){
status = STATUS_INVALID_PARAMETER;
break;
}
RegIndex=*((ULONG *)Irp->AssociatedIrp.SystemBuffer);
RegValue = *((ULONG *)Irp->AssociatedIrp.SystemBuffer +1);
Ave2kWriteRegister(pDE,RegIndex,RegValue);
status = STATUS_SUCCESS;
break;
#endif
case IOCTL_DISPLAY_PARAMETER:
if(InBufferSize != sizeof(DISPLAY_PARAMETER) || OutBufferSize != 0){
status = STATUS_INVALID_PARAMETER;
break;
}
{ PHYSICAL_ADDRESS NewBaseAddress ;
//ULONG CurrentBaseAddress = VGAAddress;
pDE->DisplayParameter = *((DISPLAY_PARAMETER *)Irp->AssociatedIrp.SystemBuffer);
if(pDE->DisplayParameter.VirtualAddress!=(ULONG)NULL){
NewBaseAddress = MmGetPhysicalAddress((PVOID)pDE->DisplayParameter.VirtualAddress);
pDE->DisplayParameter.PhysicalAddress = NewBaseAddress.LowPart;
}
else//recover original setting
pDE->DisplayParameter.PhysicalAddress = VGAAddress;
}
Irp->IoStatus.Information=0;
status=STATUS_SUCCESS;
break;
case IOCTL_OVERLAY_WINDOW:
{
POVERLAY_WINDOW pOverlayWindow=(OVERLAY_WINDOW *)Irp->AssociatedIrp.SystemBuffer;
if(InBufferSize != sizeof(OVERLAY_WINDOW) || OutBufferSize != 0)
{
status = STATUS_INVALID_PARAMETER;
break;
}
#if 0
KdPrint(("Card%d: Open=%d Pos=%d:%d - %d:%d Open2=%d Pos= %d:%d - %d:%d\n",
pDE->NtDeviceNumber+1,
pOverlayWindow->OpenClose,
pOverlayWindow->Left,
pOverlayWindow->Top,
pOverlayWindow->Right,
pOverlayWindow->Bottom,
pOverlayWindow->OpenClose2,
pOverlayWindow->Left2,
pOverlayWindow->Top2,
pOverlayWindow->Right2,
pOverlayWindow->Bottom2));
#endif
if(pOverlayWindow->OpenClose){
if(pOverlayWindow->Left<0 ||
pOverlayWindow->Top<0 ||
pOverlayWindow->Right>pDE->DisplayParameter.Width ||
pOverlayWindow->Bottom>pDE->DisplayParameter.Height)
{
status = STATUS_INVALID_PARAMETER;
break;
}
}
if(pDE->Double && pOverlayWindow->OpenClose2){
if( pOverlayWindow->Left2<0 ||
pOverlayWindow->Top2<0 ||
pOverlayWindow->Right2>pDE->DisplayParameter.Width ||
pOverlayWindow->Bottom2>pDE->DisplayParameter.Height)
{
status = STATUS_INVALID_PARAMETER;
break;
}
}
if(!pDE->Double)
pOverlayWindow->OpenClose2=0;
pDE->OverlayWindow=*pOverlayWindow;
status=ave2kOverlayControl(pDE);
}
break;
case IOCTL_DATA_STREAM:
{
// ULONG IsEnable = *(PULONG)Irp->AssociatedIrp.SystemBuffer;
//ULONG Test;
PAVE2KDATA_STREAM_CTL pDataCtrl =
(PAVE2KDATA_STREAM_CTL)Irp->AssociatedIrp.SystemBuffer;
if(!pDE->Compress ||
InBufferSize != sizeof(AVE2KDATA_STREAM_CTL) || !CheckChannel(pDE, pDataCtrl->Channel))
{
status = STATUS_INVALID_PARAMETER;
break;
}
//Test=Ave2kReadRegister(pDE, GPIO_CTRL);
//KdPrint(("GPIO=%x\n", Test));
//added on 03-3-4 by wjq
nVT=GetVideoType(pDE,(UCHAR)pDataCtrl->Channel);
if(nVT==VIDEOTYPE_NONE)
pDE->VideoType[(UCHAR)pDataCtrl->Channel]=pDE->nPreVideoType[(UCHAR)pDataCtrl->Channel];
else
pDE->VideoType[(UCHAR)pDataCtrl->Channel] =nVT;
if(pDataCtrl->Enable)
EnableAudio(pDE, (UCHAR)pDataCtrl->Channel);
else{
SetCompressFrameRate(pDE, 1, 0);
DisableAudio(pDE, pDataCtrl->Channel, TRUE);
}
status=STATUS_SUCCESS;
}
break;
#if 0
case IOCTL_FETCH_CACHE:
{
if(OutBufferSize != sizeof(AUDIOSTREAMSECTOR)){
status = STATUS_INVALID_PARAMETER;
break;
}
pDE->CurrentIrp=Irp;
if(KeSynchronizeExecution(pDE->pInterrupt,
SyncAudioRead,
pDE)){
status = STATUS_SUCCESS;
Irp->IoStatus.Information = InBufferSize/*sizeof(AUDIOSTREAMSECTOR)*/;
}
else{
status = STATUS_UNSUCCESSFUL;
Irp->IoStatus.Information = 0;
}
}
break;
#endif
case IOCTL_CLIPPING:
{
PAVE2KCLIPLIST pClipList;
pClipList=(PAVE2KCLIPLIST)Irp->AssociatedIrp.SystemBuffer;
if(InBufferSize !=sizeof(AVE2KCLIPLIST) ||
pClipList->lNumOfRect > 16)
{
status = STATUS_INVALID_PARAMETER;
break;
}
if(TRUE == SetClipRect(pDE,pClipList))
status = STATUS_SUCCESS;
else
status = STATUS_UNSUCCESSFUL;
}
break;
case IOCTL_VIDEO_DATARATE:
{
PAVE2KDATA_RATE pRate=(PAVE2KDATA_RATE)Irp->AssociatedIrp.SystemBuffer;
ULONG DataRate=pRate->DataRate;
if(!pDE->Compress ||
InBufferSize!=sizeof(AVE2KDATA_RATE) || !CheckChannel(pDE, pRate->Channel) ||
DataRate > 1151600 || DataRate < 19200)
{
status = STATUS_INVALID_PARAMETER;
break;
}
//it's NOT supported when data is being processed
if(TRUE == pDE->DataReceiving[pRate->Channel]){
status = STATUS_UNSUCCESSFUL;
break;
}
pDE->VideoDataRate[pRate->Channel] =(USHORT)(DataRate/400);
status = STATUS_SUCCESS;
}
break;
case IOCTL_AUDIO_DATARATE:
{
PAVE2KDATA_RATE pRate=(PAVE2KDATA_RATE)Irp->AssociatedIrp.SystemBuffer;
ULONG DataRate=pRate->DataRate;
if(!pDE->Compress ||
InBufferSize!=sizeof(AVE2KDATA_RATE) || !CheckChannel(pDE, pRate->Channel) ||
DataRate > ARATE_384 ||
DataRate < ARATE_32)
{
status = STATUS_INVALID_PARAMETER;
break;
}
//it's NOT supported when data is being processed
if(TRUE == pDE->DataReceiving[pRate->Channel]){
status = STATUS_UNSUCCESSFUL;
break;
}
pDE->AudioDataRate[pRate->Channel] = (USHORT)DataRate;
status = STATUS_SUCCESS;
}
break;
case IOCTL_VIDEO_PARAMETER:
{
PAVE2K_VIDEO_PARAMETER pPara;
ULONG nChannel;
pPara=(PAVE2K_VIDEO_PARAMETER)Irp->AssociatedIrp.SystemBuffer;
if(InBufferSize!=sizeof(AVE2K_VIDEO_PARAMETER) &&
InBufferSize!=sizeof(ULONG))
{
status = STATUS_INVALID_PARAMETER;
break;
}
if(InBufferSize==sizeof(AVE2K_VIDEO_PARAMETER))
{
if(!CheckChannel(pDE, pPara->Channel)){
status = STATUS_INVALID_PARAMETER;
break;
}
else{
//set parameter
SetVideoParameter(pDE, pPara, pPara->Channel);
status = STATUS_SUCCESS;
}
}
else{
nChannel=*(PULONG)Irp->AssociatedIrp.SystemBuffer;
if(OutBufferSize != sizeof(AVE2K_VIDEO_PARAMETER) || !CheckChannel(pDE, nChannel))
{
status = STATUS_INVALID_PARAMETER;
break;
}
//get parameter
GetVideoParameter(pDE, pPara, nChannel);
Irp->IoStatus.Information = sizeof(AVE2K_VIDEO_PARAMETER);
status = STATUS_SUCCESS;
}
}
break;
case IOCTL_STREAM_TYPE:
{
PAVE2K_STREAM_TYPE pType;
if(!pDE->Compress ||
(InBufferSize!=sizeof(AVE2K_STREAM_TYPE) &&
OutBufferSize != sizeof(AVE2K_STREAM_TYPE)))
{
status = STATUS_INVALID_PARAMETER;
break;
}
pType=((PAVE2K_STREAM_TYPE)Irp->AssociatedIrp.SystemBuffer);
if(!CheckChannel(pDE, pType->Channel))
{
status = STATUS_INVALID_PARAMETER;
break;
}
if(InBufferSize ==sizeof(AVE2K_STREAM_TYPE))
{
//set parameter
pDE->DataFilter[pType->Channel] = pType->Stream;
status = STATUS_SUCCESS;
}
else{
//get parameter
pType->Stream = pDE->DataFilter[pType->Channel];
Irp->IoStatus.Information = sizeof(AVE2K_STREAM_TYPE);
status = STATUS_SUCCESS;
}
break;
}
case IOCTL_VIDEO_FORMAT:
{
ULONG Format;
ULONG Channel = *(PULONG)(Irp->AssociatedIrp.SystemBuffer);
if((InBufferSize != sizeof(ULONG) && OutBufferSize != sizeof(ULONG)) || !CheckChannel(pDE, Channel))
{
status = STATUS_INVALID_PARAMETER;
break;
}
//pDE->VideoType[Channel] = GetVideoType(pDE, Channel);
nVT=GetVideoType(pDE, Channel);
switch(nVT){//pDE->VideoType[Channel]){
case VIDEOTYPE_NONE:
Format=AVE2K_VIDEO_FORMAT_NONE;
pDE->VideoType[Channel]=pDE->nPreVideoType[Channel];
break;
case VIDEOTYPE_PAL:
Format=AVE2K_VIDEO_FORMAT_PAL;
pDE->VideoType[Channel]=VIDEOTYPE_PAL;
break;
case VIDEOTYPE_NTSC:
Format=AVE2K_VIDEO_FORMAT_NTSC;
pDE->VideoType[Channel]=VIDEOTYPE_NTSC;
break;
}
*(PULONG)(Irp->AssociatedIrp.SystemBuffer)=Format;
Irp->IoStatus.Information = sizeof(ULONG);
status = STATUS_SUCCESS;
break;
}
case IOCTL_VIDEO_SOURCE:
{
PAVE2K_VIDEO_SOURCE pSource=(PAVE2K_VIDEO_SOURCE)Irp->AssociatedIrp.SystemBuffer;
ULONG VideoSource=pSource->Source;
if(! pDE->VideoSourceSelect){
status = STATUS_NOT_IMPLEMENTED;
Irp->IoStatus.Information = 0;
break;
}
if(InBufferSize!=sizeof(AVE2K_VIDEO_SOURCE) || !CheckChannel(pDE, pSource->Channel))
{
status = STATUS_INVALID_PARAMETER;
break;
}
if(VideoSource==AVE2K_VIDEO_SRC_CVBS)
SetVideoSource(pDE, VIDEOSOURCE_CVBS, pSource->Channel);
else
if(VideoSource==AVE2K_VIDEO_SRC_SVIDEO)
SetVideoSource(pDE, VIDEOSOURCE_SVIDEO, pSource->Channel);
else{
status = STATUS_INVALID_PARAMETER;
break;
}
status = STATUS_SUCCESS;
break;
}
case IOCTL_BOARD_INFO:
{
PAVE2K_BOARD_INFO pInfo;
if(OutBufferSize != sizeof(AVE2K_BOARD_INFO))
{
status = STATUS_INVALID_PARAMETER;
break;
}
pInfo=(PAVE2K_BOARD_INFO)Irp->AssociatedIrp.SystemBuffer;
pInfo->SerialsNo = pDE->SerialsNo;
pInfo->Reserved = (pDE->BusNumber<<12)|(pDE->SlotNumber<<4)|(pDE->BoardVersion);
if(pDE->Compress)
pInfo->Reserved |= 0x80000000;
if(pDE->ExtraFunctions)
pInfo->Reserved |= 0x40000000;
if(pDE->ExtraFunctions&0x02)
pInfo->Reserved |= 0x20000000;
pInfo->Double = pDE->Double;
pInfo->VideoSourceSelect = pDE->VideoSourceSelect;
if(pDE->VolumeControl != VOL_NONE){
if(pDE->VolumeControl == VOL_ANASWTCH)
pInfo->VolumeAbility= 3;
else
pInfo->VolumeAbility= 1;
}
else
pInfo->VolumeAbility= 0;
Irp->IoStatus.Information = sizeof(AVE2K_BOARD_INFO);
status = STATUS_SUCCESS;
break;
}
case IOCTL_VOLUME:
{
PAVE2K_VOLUME pVolume=(PAVE2K_VOLUME)(Irp->AssociatedIrp.SystemBuffer);
PAVE2K_VOLUME_V pVolume_V=(PAVE2K_VOLUME_V)(Irp->AssociatedIrp.SystemBuffer);
ULONG Volume=pVolume->Volume;//same position for both VOLUME and VOLUME_V
if(pDE->VolumeControl == VOL_NONE){
status = STATUS_NOT_IMPLEMENTED;
Irp->IoStatus.Information = 0;
break;
}
if((InBufferSize != sizeof(AVE2K_VOLUME) &&InBufferSize != sizeof(AVE2K_VOLUME_V) )
|| !CheckChannel(pDE, pVolume->Channel) || Volume>100)
{
status = STATUS_INVALID_PARAMETER;
break;
}
if(InBufferSize == sizeof(AVE2K_VOLUME_V)){//AVE-V
if(pVolume_V->Target)
SetM62429Volume_V0(pDE, pVolume_V->Channel, Volume);
else
SetM62429Volume_V1(pDE, pVolume_V->Channel, Volume);
status = STATUS_SUCCESS;
break;
}
//other cards
switch(pDE->VolumeControl)
{
case VOL_X9221:
//do X9221 action
break;
case VOL_X9241:
//do X9241 action
break;
case VOL_M62429:
//do M62429 action
SetM62429Volume(pDE, pVolume->Channel, Volume);
break;
case VOL_ANASWTCH:
SetAnalogSwitchVolume(pDE, Volume);
break;
}
status = STATUS_SUCCESS;
break;
}
case IOCTL_STATISTICS:
{
PAVE2K_STATISTICS pStat;
ULONG t;
ULONG Channel=*(PULONG)Irp->AssociatedIrp.SystemBuffer;
if(!pDE->Compress || InBufferSize!= sizeof(LONG) || OutBufferSize != sizeof(AVE2K_STATISTICS) || !CheckChannel(pDE, Channel))
{
status = STATUS_INVALID_PARAMETER;
break;
}
pStat=(PAVE2K_STATISTICS)Irp->AssociatedIrp.SystemBuffer;
//pDE->Stat[0].StuffPacket=Ave2kReadRegister(pDE,MC1);
//pDE->Stat[1].StuffPacket=Ave2kReadRegister(pDE,RPS_ADDR0);
*pStat=pDE->Stat[Channel];
Irp->IoStatus.Information = sizeof(AVE2K_STATISTICS);
status = STATUS_SUCCESS;
break;
}
case IOCTL_OVERLAY_FRMRATE:
{
ULONG nFrameRate;
if(InBufferSize != sizeof(ULONG)){
status = STATUS_INVALID_PARAMETER;
break;
}
nFrameRate=*((ULONG *)Irp->AssociatedIrp.SystemBuffer);
if(nFrameRate>FRMRATE_1_2){
status = STATUS_INVALID_PARAMETER;
break;
}
pDE->FrameRate=nFrameRate;
//only update when 1 picture
if(pDE->OverlayWindow.OpenClose ^ pDE->OverlayWindow.OpenClose2)
ave2kOverlayControl(pDE);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -