📄 ezusbdevice.cpp
字号:
{
t << "Entering BulkReadWrite\n";
NTSTATUS status = STATUS_SUCCESS;
PBULK_TRANSFER_CONTROL p = reinterpret_cast<PBULK_TRANSFER_CONTROL>(I.IoctlBuffer());
ULONG nBufferLength = I.IoctlOutputBufferSize();
KUsbPipe* pipe = FindPipe(p->pipeNum);
if(NULL == pipe)
{
t << "Error: Invalid pipe parameter\n";
return STATUS_INVALID_PARAMETER;
}
if( nBufferLength > pipe->MaximumTransferSize() )
{
t << "Error: Invalid transfer size parameter\n";
return STATUS_INVALID_PARAMETER;
}
KMemory M( I.Mdl() );
PURB pUrb = pipe->BuildBulkTransfer(
M,
nBufferLength,
static_cast<BOOLEAN>( USB_ENDPOINT_DIRECTION_IN(pipe->EndpointAddress()) ),
NULL,
TRUE
);
if (pUrb) {
status = pipe->SubmitUrb(pUrb);
}
else {
status = STATUS_INSUFFICIENT_RESOURCES;
}
if( STATUS_SUCCESS == status )
{
I.Information() = pUrb->UrbBulkOrInterruptTransfer.TransferBufferLength;
}
delete pUrb;
return status;
}
//=============================================================================
// EzUsbDevice::OnDevicePowerUp
//
// Handler for IRP_MJ_POWER with minor function IRP_MN_SET_POWER
// for a request to go to power on state from low power state
// This routine runs at dispatch level.
//
NTSTATUS EzUsbDevice::OnDevicePowerUp(KIrp I)
{
NTSTATUS status = STATUS_SUCCESS;
t << "Entering OnDevicePowerUp\n";
return status;
UNREFERENCED_PARAMETER(I);
}
//=============================================================================
// DevicePowerStateName
//
// This routine takes as input the DEVICE_POWER_STATE value for
// a device power IRP and returns a string describing the state
//
PCHAR DevicePowerStateName(DEVICE_POWER_STATE ps)
{
#ifdef _DEBUG
static PCHAR PowerStates[] = {
"PowerDeviceUnspecified",
"PowerDeviceD0",
"PowerDeviceD1",
"PowerDeviceD2",
"PowerDeviceD3"
};
if (ps > PowerDeviceD3)
return "<undefined power state>";
else
return PowerStates[ps];
#else
return NULL;
UNREFERENCED_PARAMETER(ps);
#endif
}
//=============================================================================
// EzUsbDevice::OnDeviceSleep
//
// Handler for IRP_MJ_POWER with minor function IRP_MN_SET_POWER
// for a request to go to a low power state from a high power state
// This routine runs at passive level.
//
NTSTATUS EzUsbDevice::OnDeviceSleep(KIrp I)
{
t << "Entering OnDeviceSleep\n";
NTSTATUS status = STATUS_SUCCESS;
t << DevicePowerStateName(I.PowerStateSetting().DeviceState) << "\n" ;
return status;
}
//=============================================================================
// EzUsbDevice::IsoStreamCompleteCallback
//
// This callback routine is called when an Isochronous stream is stopped.
// All Isochronous URBs have completed. It is called from a completion
// routine so assume at DISPATCH_LEVEL.
//
VOID __stdcall EzUsbDevice::IsoStreamCompleteCallback(PVOID pContext)
{
t << "Entering IsoStreamCompleteCallback\n";
EzUsbDevice* p = (EzUsbDevice*)pContext;
ASSERT( p );
if( p )
{
//Since the Iso Transfer is completed, delete the Iso Transfer Object
delete p->m_pIsoDM;
p->m_pIsoDM = NULL;
//Matching call of IncrementOutstandingRequestCount in StartIsoStream
p->DecrementOutstandingRequestCount();
}
}
//=============================================================================
// EzUsbDevice::StartIsoStream - Handler for IOCTL_EZUSB_START_ISO_STREAM
//
// This starts continuous Isochronous Reads from the USB device. The
// data is stored in a buffer managed by the driver. The data is
// accessible to user mode by IOCTL_EZUSB_READ_ISO_BUFFER. The
// continuous Isochronous Reads are stopped either on error from the
// device or on request by IOCTL_EZUSB_STOP_ISO_STREAM.
//
NTSTATUS EzUsbDevice::StartIsoStream(KIrp I)
{
t << "Entering StartIsoStream\n";
NTSTATUS status = STATUS_SUCCESS;
PISO_TRANSFER_CONTROL p = reinterpret_cast<PISO_TRANSFER_CONTROL>(I.IoctlBuffer());
if( ! NT_SUCCESS(status = CheckIsoParameters(p)) )
{
return status;
}
if( m_pIsoDM && m_pIsoDM->IsStarted() )
{
return STATUS_DEVICE_BUSY;
}
USHORT nPacketSize = static_cast<USHORT>( p->PacketSize );
KUsbPipe* pPipe = FindPipe(p->PipeNum);
if( NULL == pPipe )
{
ASSERT( NULL != pPipe );
return STATUS_INVALID_PARAMETER;
}
m_pIsoDM = new (NonPagedPool) EzUsbDriverManagedIsoTransfer(
*pPipe,
nPacketSize * p->PacketCount, //Size of data Buffer
nPacketSize,
static_cast<UCHAR>(p->FramesPerBuffer),
static_cast<UCHAR>(p->BufferCount),
p->PacketCount //Size of Packet Buffer
);
if( NULL == m_pIsoDM )
{
ASSERT( NULL != m_pIsoDM );
return STATUS_INSUFFICIENT_RESOURCES;
}
status = m_pIsoDM->Start(
IsoStreamCompleteCallback,
this
);
if( NT_SUCCESS(status) )
{
//This will prevent removal
IncrementOutstandingRequestCount();
}
return status;
}
//=============================================================================
// EzUsbDevice::ReadIsoBuffer - Handler for IOCTL_EZUSB_READ_ISO_BUFFER
//
// This routine will read data stored in the driver from continuous
// Isochronous reads.
//
NTSTATUS EzUsbDevice::ReadIsoBuffer(KIrp I)
{
t << "Entering ReadIsoBuffer\n";
//Check input parameters
PISO_TRANSFER_CONTROL p = (PISO_TRANSFER_CONTROL)I.IoctlBuffer();
if( NULL == p )
{
t << "Error: Invalid parameter \n";
ASSERT( NULL != p );
return STATUS_INVALID_PARAMETER;
}
if(I.IoctlInputBufferSize() != sizeof(ISO_TRANSFER_CONTROL))
{
t << "Error: Invalid parameter \n";
I.Information() = 0;
return STATUS_INVALID_PARAMETER;
}
if( I.IoctlOutputBufferSize() !=
p->PacketCount *
(p->PacketSize + sizeof(USBD_ISO_PACKET_DESCRIPTOR))
)
{
t << "Error: OutputBuffer too small \n";
I.Information() = 0;
return STATUS_INVALID_PARAMETER;
}
if(NULL == m_pIsoDM)
{
I.Information() = 0;
return STATUS_UNSUCCESSFUL;
}
//done error checking. Perform the operation
KMemory M(I.Mdl());
PVOID ptr = M.MapToSystemSpace();
ASSERT( ptr );
ULONG dwDataBytesToRead = p->PacketCount * p->PacketSize;
ULONG dwDataBytesRead = m_pIsoDM->ReadBuffer(
ptr,
dwDataBytesToRead
);
if( ! p->PacketSize )
{
ASSERT( p->PacketSize );
return STATUS_INVALID_PARAMETER;
}
ULONG dwDescriptorsToRead = dwDataBytesRead / p->PacketSize;
ULONG dwDescriptorsRead = m_pIsoDM->ReadDescriptorBuffer(
reinterpret_cast<PUCHAR>(ptr) + dwDataBytesRead,
dwDescriptorsToRead
);
ULONG dwDescrBytesRead = dwDescriptorsRead * sizeof(USBD_ISO_PACKET_DESCRIPTOR);
I.Information() = dwDataBytesRead + dwDescrBytesRead;
return STATUS_SUCCESS;
}
//=============================================================================
// EzUsbDevice::CheckIsoParameters
//
// This routine performs some error checking on the PISO_TRANSFER_CONTROL
// passed down from user mode to control Isochronous transfers
//
NTSTATUS EzUsbDevice::CheckIsoParameters(PISO_TRANSFER_CONTROL p)
{
if( NULL == p )
{
ASSERT( NULL != p );
return STATUS_INVALID_PARAMETER;
}
if( p->PipeNum > m_UsbInterface.NumberOfPipes() )
{
t << "Error: Invalid pipe parameter\n";
return STATUS_INVALID_PARAMETER;
}
PUSBD_PIPE_INFORMATION pPipeInfo = m_UsbInterface.Pipes(p->PipeNum);
if (!(pPipeInfo->PipeType == UsbdPipeTypeIsochronous))
{
t << "Error: Invalid pipe parameter\n";
return STATUS_INVALID_PARAMETER;
}
USBD_PIPE_HANDLE PipeHandle = pPipeInfo->PipeHandle;
if(!PipeHandle)
{
t << "Error: Invalid pipe parameter\n";
return STATUS_UNSUCCESSFUL;
}
//Check that the FramesPerBuffer + BufferCount parameters are valid.
//This function enforces that PacketCount must be zero
//modulus (FramesPerBuffer * BufferCount).
if( p->PacketCount % (p->FramesPerBuffer * p->BufferCount) )
{
t << "Error: Invalid parameter\n";
return STATUS_INVALID_PARAMETER;
}
return STATUS_SUCCESS;
}
//=============================================================================
// EzUsbDevice::IsoReadWrite - Handler for IOCTL_EZUSB_ISO_READ and
// IOCTL_EZUSB_ISO_WRITE
//
// This starts Isochronous Transfers to/from the USB device.
// The data buffer is split into multiple URB's. A feature of the kit is
// that the USBD_ISO_PACKET_DESCRIPTOR's are made available to the
// application for analysis.
//
NTSTATUS EzUsbDevice::IsoReadWrite(KIrp I)
{
t << "Entering IsoReadWrite\n";
PISO_TRANSFER_CONTROL p = (PISO_TRANSFER_CONTROL) I.IoctlBuffer();
NTSTATUS status = STATUS_SUCCESS;
if( ! NT_SUCCESS(status = CheckIsoParameters(p)) )
{
return status;
}
USHORT nPacketSize = static_cast<USHORT>( p->PacketSize );
// Check that the caller has provided a buffer large enough for
// all of the Isochronous data and all of the Iso Packet Descriptors
// (1 descriptor for each packet transferred)
if( I.IoctlOutputBufferSize() < (p->PacketCount *
(nPacketSize + sizeof(USBD_ISO_PACKET_DESCRIPTOR)))
)
{
t << "Error: OutputBuffer too small \n";
return STATUS_UNSUCCESSFUL;
}
// Initiate the transfers
//Obtain a KUsbPipe object for the transfer
KUsbPipe* pPipe = FindPipe(p->PipeNum);
//Instance a KMemory object for the Mdl
KMemory M(I.Mdl());
//Obtain a system virtual address for the Isochronous packet descriptor buffer
PVOID ptr = reinterpret_cast<PUCHAR>(M.MapToSystemSpace()) + p->PacketCount * nPacketSize;
//Instance an object to manage the transfer
EzUsbIsoTransfer* pIsoTransfer = new (NonPagedPool) EzUsbIsoTransfer(
M, //KMemory object
nPacketSize * p->PacketCount, //Size of data Buffer in bytes
*pPipe, //KUsbPipe object
nPacketSize, //USHORT PacketSize = 0,
UCHAR(p->FramesPerBuffer), //UCHAR PacketsPerUrb = USB_MAX_NUM_ISO_PACKETS_IN_AN_URB,
(PUCHAR) ptr, //pointer to descriptor buffer
UCHAR(p->BufferCount) //UCHAR NumUrbs = 2
);
if( NULL == pIsoTransfer )
{
return STATUS_INSUFFICIENT_RESOURCES;
}
if( STATUS_SUCCESS == pIsoTransfer->Status() )
{
//start the transfer(s) using the synchronous form
status = pIsoTransfer->Start();
}
delete pIsoTransfer ;
I.Information() = 0;
return status;
}
//=============================================================================
// EzUsbDevice::OnInterrupt
//
// This routine is called when the USB device interrupts.
//
ON_INTERRUPT_STATUS EzUsbDevice::OnInterrupt(
PURB pUrb,
PVOID pContext
)
{
t << "Entering OnInterrupt\n";
ASSERT( pUrb );
if( pUrb )
{
t << *pUrb;
}
return ON_INTERRUPT_SUCCESS;
UNREFERENCED_PARAMETER(pContext);
}
//=============================================================================
// EzUsbDevice::IsFx2
//
// This routine checks if the hardware is the FX2 model. The device
// must implement the vendor specific IN SETUP command 0xAC, which returns 1
// if the chip is FX2 and 0 otherwise.
//
bool EzUsbDevice::IsFx2()
{
t << "Entering IsFx2\n";
bool bRet = false;
NTSTATUS status = STATUS_SUCCESS;
UCHAR Buffer;
PURB pUrb = m_Lower.BuildVendorRequest(
&Buffer, //PUCHAR Buffer
1, //Buffer Length
0, //RequestTypeReservedBits
EZUSB_ISFX2, //Request
0 //Value
);
if( pUrb )
{
// submit the URB with a timeout since not all
// devices will implement this command.
ULONG Timeout = 100; // Timeout in milliseconds
status = m_Lower.SubmitUrb(pUrb,NULL,NULL,Timeout);
delete pUrb;
if (STATUS_SUCCESS == status && 1 == Buffer)
bRet = true;
}
return bRet;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -