您的位置:首页 > 其它

串口过滤驱动练习

2017-02-22 09:15 453 查看

一个简单的串口过滤驱动框架

参考《寒江独钓》完成用来对串口读写进行的过滤驱动。

注意问题:

用来和应用层通信的buffer区域有三种方式。

完成的读写分发函数的方式特殊还未搞懂?

//以下为完整代码
#include <ntddk.h>
#include <string.h>
static PDEVICE_OBJECT m_fltobj;
static PDEVICE_OBJECT m_topobj;
//定义一个读的完成处理函数
NTSTATUS fengReadComplete(IN PDEVICE_OBJECT DeviectObject, IN PIRP Irp, IN PVOID Context)
{
PIO_STACK_LOCATION IrpSp;
ULONG i;
IrpSp = IoGetCurrentIrpStackLocation(Irp);
if(NT_SUCCESS( Irp->IoStatus.Status))
{
PUCHAR buf = (PUCHAR)Irp->AssociatedIrp.SystemBuffer;
DbgPrint("Driver1 Read:");
for(i=0; i<Irp->IoStatus.Information; i++)
{
DbgPrint("%02X, ", buf[i]);
}
DbgPrint("\r\n");
}
if( Irp->PendingReturned)
IoMarkIrpPending( Irp);
return Irp->IoStatus.Status;
}
NTSTATUS DRIVER1_DispatchDeviceControl(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)
{
ULONG j;
NTSTATUS status = STATUS_SUCCESS;
PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation(Irp);
DbgPrint(("收到IRP\r\n"));
if(m_fltobj == DeviceObject)
{
if(irpSp->MajorFunction == IRP_MJ_POWER)//所有的电源操作,全部直接放过。
{
//直接发送,然后返回说已经被处理了。
PoStartNextPowerIrp(Irp);
IoSkipCurrentIrpStackLocation(Irp);
return PoCallDriver(m_topobj, Irp);
}
else if(irpSp->MajorFunction == IRP_MJ_WRITE)
{
PUCHAR buf = NULL;
if(Irp->MdlAddress != NULL)
buf = (PUCHAR)MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority);//将数据放到MdkAddress中,映射关系。
else
buf = (PUCHAR)Irp->UserBuffer;   //直接读取用户控件内存。
if(buf == NULL)
buf = (PUCHAR)Irp->AssociatedIrp.SystemBuffer;   //将用户空间内存拷贝到内核空间。
DbgPrint("Driver1 Write:");
for(j =0; j< irpSp->Parameters.Write.Length; j++)
{
DbgPrint("%02X, ", buf[j]);
}
DbgPrint("\r\n");
}
else if(irpSp->MajorFunction == IRP_MJ_READ)
{
IoCopyCurrentIrpStackLocationToNext(Irp);
IoSetCompletionRoutine(Irp, fengReadComplete, DeviceObject, TRUE, TRUE, TRUE);
return IoCallDriver(m_topobj, Irp);
}

//所有的读写请求直接下发执行即可,我们并不禁止或改变它。
IoSkipCurrentIrpStackLocation(Irp);
return IoCallDriver(m_topobj, Irp);
}

//直接返回参数错误
Irp->IoStatus.Information = 0;
Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return status;
}
VOID DRIVER1_DriverUnload(IN PDRIVER_OBJECT DriverObject)
{
LARGE_INTEGER ilval;
if(m_topobj != NULL)
IoDetachDevice(m_topobj);
ilval.QuadPart = 5 * 1000 * 1000 * (-10); //5秒
KeDelayExecutionThread(KernelMode, FALSE, &ilval);
if(m_fltobj != NULL)
IoDeleteDevice(m_fltobj);
}
#pragma code_seg("INIT")
NTSTATUS DriverEntry(IN OUT PDRIVER_OBJECT   DriverObject,IN PUNICODE_STRING  RegistryPath)
{
size_t i;
NTSTATUS status;
UNICODE_STRING namestr;
PFILE_OBJECT fileobj = NULL;
PDEVICE_OBJECT devobj = NULL;
DbgBreakPoint();
for(i = 0; i< IRP_MJ_MAXIMUM_FUNCTION; i++)
{
DriverObject->MajorFunction[i] = DRIVER1_DispatchDeviceControl;
}
DriverObject->DriverUnload = DRIVER1_DriverUnload;

//打开一个端口设备
//根据id转换成串口的名字
RtlInitUnicodeString(&namestr, L"\\Device\\Serial0");
//打开设备  //从名字获取设备对象的指针。
status = IoGetDeviceObjectPointer( &namestr,
FILE_ALL_ACCESS,    //全部读写权限
&fileobj,           //无用的文件对象指针
&devobj);           //打开串口

//如果打开成功了,记得一定要把文件对象解除引用
if(status == STATUS_SUCCESS)
ObDereferenceObject(fileobj);
if(status == STATUS_SUCCESS)
{
NTSTATUS status;
PDEVICE_OBJECT topdev = NULL;
DbgPrint(("成功打开com1\r\n"));

//生成设备然后绑定
status = IoCreateDevice(DriverObject, 0, NULL, devobj->DeviceType, 0, FALSE, &m_fltobj);
if(status != STATUS_SUCCESS)
return status;
//拷贝重要标志位   没懂这个是干啥的?
if(devobj->Flags & DO_BUFFERED_IO)
m_fltobj->Flags |= DO_BUFFERED_IO;
if(devobj->Flags & DO_DIRECT_IO)
m_fltobj->Flags |= DO_DIRECT_IO;
if(devobj->Characteristics & FILE_DEVICE_SECURE_OPEN)
m_fltobj->Characteristics |= FILE_DEVICE_SECURE_OPEN;
m_fltobj->Flags |= DO_POWER_PAGABLE;

//将一个设备绑定到另一个设备
topdev = IoAttachDeviceToDeviceStack(m_fltobj, devobj);
if(topdev == NULL)
{
//如果绑定失败了,销毁设备,返回错误
IoDeleteDevice(m_fltobj);
m_fltobj = NULL;
status = STATUS_UNSUCCESSFUL;
return status;
}
DbgPrint(("driverentry 成功\r\n"));
//设置这个设备已经启动
m_topobj= topdev;
m_fltobj->Flags &= ~DO_DEVICE_INITIALIZING;
return STATUS_SUCCESS;
}
return STATUS_SUCCESS;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  串口驱动