📄 rwusb.cpp
字号:
//////////////////////////////////////////////////////////////////////////
// Copyright @2003 Peng He,Information Science Insititute,XiDian University
// MyNdis_Wdm example
//Abstract:
// USB device driver
// USB设备驱动,该模块包含涉及USB操作的IRP、URBS,但不包括NIDS的代码
//
//Environment:
// kernel mode only
//
// Version history:
//
// Peng.He - 04/17/03: this source code for USB to fast Ethernet adapter driver
// show how an NDIS miniport driver can interface with an USB device.
// 17-Apr-2003 creation
/////////////////////////////////////////////////////////////////////////
#include <ndis.h>
#include <ntdef.h>
#include <windef.h>
#include "usbdi.h"
#include "usbdlib.h"
#include "debug.h"
#include "common.h"
#include "HPNA_2k.h"
/*****************************************************************************
//
//
// InitializeReceive
//
// USB设备的初始化接收例程,处理IRP
//
//
*****************************************************************************/
NTSTATUS
InitializeReceive(
IN PUSB_DEVICE Adapter
)
{
NTSTATUS status=STATUS_SUCCESS;
DEBUGMSG(DBG_FUNC, ("+InitializeReceive\n"));
//
// 创建运行在IRQL PASSIVE_LEVEL上的线程
//
status=PsCreateSystemThread( // 创建一个在内核模块中执行的系统线程,并为这个线程返回一个句柄
&Adapter->hPassiveThread, // 指向接收这个句柄的变量
(ACCESS_MASK) 0L, // 指定访问这个被创建的线程所需要的类型,其值可能是THREAD_ALL_ACCESS或者是(ACCESS_MASK) 0L
NULL, // 指向一个指定对象属性的结构
NULL, // 为在运行线程的地址空间里的进程指定一个开放的句柄
NULL, // 指向一个接受新线程的客户标识符的结构
PassiveLevelThread, // 驱动程序线程的入口点
Adapter // 当线程开始执行时提供一个单一的参数
);
if (status!=STATUS_SUCCESS)
{
DEBUGMSG(DBG_ERROR, ("PsCreateSystemThread PassiveLevelThread failed. Returned 0x%.8x\n", status));
status = STATUS_INSUFFICIENT_RESOURCES;
goto release;
}
//
// 创建运行在IRQL PASSIVE_LEVEL上的线程,该线程用来接收
//
status=PsCreateSystemThread(
&Adapter->hPollingThread,
(ACCESS_MASK) 0L,
NULL,
NULL,
NULL,
PollingThread,
Adapter
);
if (status!=STATUS_SUCCESS)
{
DEBUGMSG(DBG_ERROR, ("PsCreateSystemThread PollingThread failed. Returned 0x%.8x\n", status));
status = STATUS_INSUFFICIENT_RESOURCES;
goto release;
}
Adapter->fReceiving = TRUE;
release:
return status;
}
/*****************************************************************************
//
//
// StartUsbRead
//
// 分配IRP,调用USB类驱动程序
//
//
*****************************************************************************/
NTSTATUS
StartUsbRead(
IN PUSB_DEVICE Adapter)
{
ULONG size;
ULONG length;
PURB urb = NULL;
PDEVICE_OBJECT urbTargetDev;
PIO_STACK_LOCATION nextStack;
NTSTATUS timeStat = STATUS_UNSUCCESSFUL;
PMDL mdl;
PRCV_BUFFER pRecBuf;
UINT Index;
ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL); // 对当前线程进行判断
size = sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER); // URB结构大小
length = MAX_PACKET_SIZE;
//
// 获取缓冲区,其状态为STATE_PENDING
//
pRecBuf = GetRcvBuf( Adapter, &Index, STATE_PENDING ); // Index为缓冲区数
if ( !pRecBuf)
{
//
// 没有可用的缓冲区
//
timeStat = STATUS_UNSUCCESSFUL;
goto release;
}
if( TRUE == Adapter->fPendingReadClearStall )
{
timeStat = STATUS_UNSUCCESSFUL;
goto release;
}
urb = ((PURB) pRecBuf->Urb);
//
// 为USB类驱动程序创建URB
//
NdisZeroMemory(urb, size);
ASSERT(Adapter->BulkInPipeHandle);
//
// URB已经创建好,下面将向USB设备发出请求
//
KeClearEvent(&pRecBuf->Event); // 将指定的事件设定为无符号状态
urbTargetDev = Adapter->pUsbDevObj; // 绑定设备对象
ASSERT(urbTargetDev);
//
// 产生并发送IRP
//
pRecBuf->Irp = IoAllocateIrp( (CCHAR)(Adapter->pUsbDevObj->StackSize +1), FALSE );
if ( NULL == pRecBuf->Irp )
{
timeStat = STATUS_INSUFFICIENT_RESOURCES;
goto release;
}
((PIRP) pRecBuf->Irp)->IoStatus.Status = STATUS_NOT_SUPPORTED;
((PIRP) pRecBuf->Irp)->IoStatus.Information = 0;
//
// 为USB类驱动程序创建URB
//
urb->UrbBulkOrInterruptTransfer.Hdr.Length = (USHORT) size;
urb->UrbBulkOrInterruptTransfer.Hdr.Function = URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER;
urb->UrbBulkOrInterruptTransfer.PipeHandle = Adapter->BulkInPipeHandle;
urb->UrbBulkOrInterruptTransfer.TransferFlags = USBD_TRANSFER_DIRECTION_IN ;
urb->UrbBulkOrInterruptTransfer.TransferFlags |= USBD_SHORT_TRANSFER_OK;
//
// 不用后继的URB
//
urb->UrbBulkOrInterruptTransfer.UrbLink = NULL;
urb->UrbBulkOrInterruptTransfer.TransferBufferMDL = NULL;
urb->UrbBulkOrInterruptTransfer.TransferBuffer = pRecBuf->dataBuf;
urb->UrbBulkOrInterruptTransfer.TransferBufferLength =length;
//
// 调用USB类驱动程序,完成操作
//
nextStack = IoGetNextIrpStackLocation((PIRP) pRecBuf->Irp );
ASSERT(nextStack != NULL);
//
// 使URB通过USB驱动程序栈
//
nextStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
nextStack->Parameters.Others.Argument1 = urb;
nextStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_INTERNAL_USB_SUBMIT_URB;
//
// 注册一个IoCompletion例程,当下一层驱动程序已经完成对给定IRP的请求操作时调用它
//
IoSetCompletionRoutine(
((PIRP) pRecBuf->Irp), // 指向驱动程序想追踪的irp
UsbIoCompleteRead, // 指定驱动程序提供的IoCompletion例程的入口,在下一层驱动程序完成信息包时调用它
pRecBuf, // 指向驱动程序决定的传递到IoCompletion例程的上下文
TRUE, // 如果IRP在I/O状态块中用STATUS_SUCCESS完成,则确定是否调用完成例程
TRUE, // 如果IRP在I/O状态块中用STATUS_XXX完成,则确定是否调用完成例程
TRUE); // 如果IRP在I/O状态块中用STATUS_CANCELLED完成,则确定是否调用完成例程
//
// 传递一个IRP到USB端口
//
UsbIncIoCount( Adapter );
timeStat=IoCallDriver(
urbTargetDev, // 指向下一层驱动程序的设备对象,该对象为请求I/O操作描述目标设备
(PIRP) pRecBuf->Irp); // 指向IRP,开始USB读取
DEBUGMSG(DBG_FUNC, (" StartUsbRead() after IoCallDriver () status = 0x%x\n", timeStat));
ASSERT( STATUS_SUCCESS != timeStat );
while ( timeStat != STATUS_SUCCESS )
{
timeStat = MyKeWaitForSingleObject( // 设置当前线程为等待状态直到给定的调用程序对象被置为信号状态,或直到等待期满
Adapter,
&pRecBuf->Event, // 等待事件
NULL, //等待的irp,在事件终止、重新配置或超时时其值为NULL
10000 * 1000 * 1 ); //1秒
}
ASSERT( NULL == pRecBuf->Irp ); // 完成例程完成时,IRP为NULL
release:
if ( !pRecBuf || ( Adapter->RcvBuffersInUse >= (NUM_RCV_BUFS -2) ) )
{
/*if ( FALSE == Device->fIndicatedMediaBusy )
{
InterlockedExchange( &Device->fMediaBusy, TRUE );
InterlockedExchange( &Device->fIndicatedMediaBusy, TRUE );
IndicateMediaBusy( Device ); // indicate to Ndis BUGBUG? NOT NEEDED HERE?
}*/
IndicateMediaBusy( Adapter );
}
return timeStat;
}
/*****************************************************************************
//
//
// UsbIoCompleteRead
//
// 对于所有挂起的,主功能为IRP_MJ_READ的 irp的读完成例程
//
//Arguments: pUsbDevObj - 指向完成指定IRP操作的设备对象的指针
// pIrp - 由该设备对象完成的IRP
// Context - 设备扩展的环境区
//
*****************************************************************************/
NTSTATUS
UsbIoCompleteRead(
IN PDEVICE_OBJECT pUsbDevObj,
IN PIRP pIrp,
IN PVOID Context
)
{
PUSB_DEVICE Adapter;
NTSTATUS status;
ULONG_PTR BytesRead;
PRCV_BUFFER pRecBuf;
LARGE_INTEGER tat;
DEBUGMSG(DBG_FUNC, ("+UsbIoCompleteRead\n"));
//
// 传递到UsbIoCompleteRead例程的上下文(环境区)是接收缓冲区
//
pRecBuf = (PRCV_BUFFER) Context;
Adapter = (PUSB_DEVICE) pRecBuf->device;
ASSERT( pRecBuf->Irp == pIrp );
ASSERT( NULL != Adapter );
if ((Adapter->fPendingHalt == TRUE) ||
(Adapter->fPendingReset == TRUE))
{
//
// 设置布尔变量fReceiving的值
//
DEBUGMSG(DBG_FUNC, ("UsbIoCompleteRead halt or reset pending setting fReceiving FALSE\n"));
Adapter->fReceiving = FALSE;
}
//
// 对于USB设备的读取有几种情况:
// 1) USB设备读超时,没有接收到数据
// 2) USB设备读超时,但接收到一些数据
// 3) USB设备读取成功,IRP缓冲已满
// 4) 读IRP被取消
// 5) USB设备对象出现了错误
//
status = pIrp->IoStatus.Status; // 获取IRP状态
//
// IoCallDriver已经被调用,传递了该IRP
// 在该IRP中保留URB结构体内的各个参数
//
pIrp->IoStatus.Information = ((PURB) pRecBuf->Urb)->UrbBulkOrInterruptTransfer.TransferBufferLength;
BytesRead = pIrp->IoStatus.Information;
Adapter->pCurrentRcvBuf = NULL;
//
// 对各种情况作响应操作
//
switch (status)
{
case STATUS_SUCCESS:
if (BytesRead > 0)
{
pRecBuf->dataLen = (UINT)pIrp->IoStatus.Information;
//
// 不必同步等待包处理而直接将它发送至高层协议驱动程序
//
#if 1 // BUGBUG? EXPERIMENT
if ( FALSE == ScheduleWorkItem(Adapter,ProcessDataCallBack,pRecBuf,sizeof(RCV_BUFFER)))
{
status = STATUS_INSUFFICIENT_RESOURCES;
}
#else
Adapter->pCurrentRcvBuf = pRecBuf; // do it in polling loop (at PASSIVE_LEVEL)
// ProcessData(
// device,
// pRecBuf
// );
#endif
}
break; // STATUS_SUCCESS
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -