我是靠谱客的博主 感性蓝天,最近开发中收集的这篇文章主要介绍驱动程序(7) WDF下DMA传输的驱动程序代码详细说明之应用程序application.c,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

这一篇主要说明应用程序怎么去和驱动程序通信的,包括识别打开驱动程序,传递数据到驱动程序,同时接收驱动程序返回的数据。

application.c

  1. 首先是应用程序的创建,WDF里利用模板生成驱动程序时时不带有应用程序的源文件的,需要我们自己手动生成,其实就是和创建一个C语言文件一样。找到驱动程序的解决方案,右键选择‘添加’->‘新建项目’->‘测试’->‘Applications’,选择第一个就行了,保存时注意存为.c文件,因为整个项目都是C来写的,没有用C++。需要注意的就是这个文件一定要在驱动程序的那个解决方案下才行,然后在该项目的项目依赖项里勾选上你的驱动程序,表示它是依赖于驱动程序才有用的。
    在这里插入图片描述

2.代码

/*++
Module Name: application.c
Abstract:This file contains application which communicates with driversoft, including main and GetDevicePath function.
Environment: User-mode Driver Framework
Time: 20181015
--*/

#include <windows.h>
#include <winioctl.h>
#include <setupapi.h>
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <string.h>

#include "tchar.h"
#include "../PCIe/Public.h"


HANDLE hDevice = INVALID_HANDLE_VALUE;
PCHAR GetDevicePath(IN LPGUID InterfaceGuid);

int _tmain(int argc, _TCHAR* argv[])
{
	PCHAR DevicePath;
	ULONG nOutput;
	//LPDWORD count = 0;
	UNREFERENCED_PARAMETER(argc);
	UNREFERENCED_PARAMETER(argv);

	printf("Application control test starting...n");
	//利用GUID号找到设备路径
	DevicePath = GetDevicePath((LPGUID)&GUID_DEVINTERFACE_PCIe);
	if (DevicePath == 0)
	{
		printf("ERROR: Get DevicePath failed! ErrNo:%0xn", GetLastError());
		return 0;
	}
	printf("DevicePath gets successfullyn");

	//打开设备,创建相关句柄
	//LPCWSTR name = _T(*DevicePath);
	hDevice = CreateFile(DevicePath,
		GENERIC_READ | GENERIC_WRITE,
		FILE_SHARE_READ | FILE_SHARE_WRITE,
		NULL,
		OPEN_EXISTING,
		FILE_ATTRIBUTE_NORMAL,
		NULL);
	if (hDevice == INVALID_HANDLE_VALUE) {
		//KdPrint("Error opening device:(%0x) returned from createfilen", GetLastError());
		printf("ERROR: hDevice create failed!ErrNo:%0xn", GetLastError());
		return 0;
	}
	printf("Open device successfullyn");
	fprintf(stderr, "n");

	
	//调用WDF框架下DeviceIoControl函数与驱动程序通信
	ULONG x = 0,y;
	if (!DeviceIoControl(hDevice, WDF_DMA, &x, sizeof(ULONG), &y, sizeof(ULONG), &nOutput, NULL))
	{
		printf("ERROR:DeviceIoControl 'Single_Measurement' returns falied! ErrNo: %0x.", GetLastError());
		goto exit;
	}
	printf("the returned data is %dn", y);

exit:
	if (hDevice != INVALID_HANDLE_VALUE)
	{
		CloseHandle(hDevice);
	}

	return 0;
}

//利用GUID号找到设备路径的具体函数
PCHAR GetDevicePath(IN LPGUID InterfaceGuid)
{
	//设别信息集
	HDEVINFO DeviceInfoSet;
	//设备接口信息
	SP_DEVICE_INTERFACE_DATA DeviceInterfaceData;
	//指向设备接口详细信息的指针
	PSP_DEVICE_INTERFACE_DETAIL_DATA DeviceInterfaceDetailData = NULL;
	//函数指向结果返回值
	BOOL bResult;
	//遍历
	DWORD dwIndex = 0 ;

	ULONG Length, RequiredLength = 0;

	//获取指定设备接口类的设备信息集
	DeviceInfoSet = SetupDiGetClassDevs(
		InterfaceGuid,
		NULL,   //Enumerator
		NULL,
		(DIGCF_PRESENT | DIGCF_DEVICEINTERFACE));
	printf("**************************************************n");
	printf("Getting into function 'GetDevicePath'n");
	if (DeviceInfoSet == INVALID_HANDLE_VALUE)
	{
		printf("SetupDiGetClassDevs faild! ErrNo:%dn", GetLastError());
		return 0;
	}

	//枚举设备信息集下的所有设备的设备接口
	//for (dwIndex = 0;;dwIndex++)
	//{
		DeviceInterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
		
		bResult = SetupDiEnumDeviceInterfaces(
			DeviceInfoSet,
			NULL,
			InterfaceGuid,
			dwIndex, // 第dwIndex个设备
			&DeviceInterfaceData);
		if (!bResult)
		{
			//259错误表示遍历完成
			printf("SetupDiEnumDeviceInterfaces faild! ErrNo:%dn", GetLastError());
			SetupDiDestroyDeviceInfoList(DeviceInfoSet);
			return FALSE;
			//break;
		}
		//获取设备接口详细信息
		//第一次调用,DeviceInterfaceDetailData置为NULL,获取待分配缓冲区的大小
		//根据MSDN,此次调用返回值为FALSE,而且GetLastError为122,如果进行错误检查,需要注意
		SetupDiGetDeviceInterfaceDetail(
			DeviceInfoSet,
			&DeviceInterfaceData, //待获取详细信息的设备接口
			NULL,
			0,
			&RequiredLength,
			NULL);

		DeviceInterfaceDetailData = (PSP_DEVICE_INTERFACE_DETAIL_DATA)LocalAlloc(LMEM_FIXED, RequiredLength);
		if (DeviceInterfaceDetailData == NULL)
		{
			printf("Failed to allocate memory!n");

			SetupDiDestroyDeviceInfoList(DeviceInfoSet);
			return 0;
		}

		DeviceInterfaceDetailData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
		Length = RequiredLength;

		//第二次调用,返回设备接口详细信息
		bResult = SetupDiGetDeviceInterfaceDetail(
			DeviceInfoSet,
			&DeviceInterfaceData,
			DeviceInterfaceDetailData,
			Length,
			&RequiredLength,
			NULL);

		if (!bResult)
		{
			printf("SetupDiGetDeviceInterfaceDetail failed(second)!ErrNo:%dn", GetLastError());

			SetupDiDestroyDeviceInfoList(DeviceInfoSet);
			LocalFree(DeviceInterfaceDetailData);
			return 0;
		}
		//PCHAR devPath;
		//PCHAR devPath = DeviceInterfaceDetailData->DevicePath;
		//printf(DeviceInterfaceDetailData->DevicePath);
		printf("Completed working in function 'GetDevicePath'n");
		printf("**************************************************n");
		return DeviceInterfaceDetailData->DevicePath;

		//LocalFree(DeviceInterfaceDetailData);
	//}

	//return NULL;
}

  1. application.c主要任务是找到驱动程序,然后和驱动程序进行通信。GetDevicePath函数利用之前得到的GUID号遍历设备集,找到指定的PCIe设备,并返回设备的路径。有了设备路径之后,应用程序就可以打开驱动程序的设备,并生成一个指向该设备的句柄,以后都用这个句柄来进行对设备的操作。DeviceIoControl函数则就是用来具体和驱动程序通信的。
DeviceIoControl(hDevice, WDF_DMA, &x, sizeof(ULONG), &y, sizeof(ULONG), &nOutput, NULL)

这个函数的第一个参数是CreateFile函数返回的句柄;第二个参数是应用程序调动驱动程序的控制命令;接着四个参数分为两组,一组是应用程序传递给驱动程序的数据缓冲区地址和字节数,另一组是驱动程序的返回数据所存放的缓冲区地址和可用的缓冲空间字节数;第七个参数为驱动程序实际返回的数据字节数的变量地址;最后个参数则是overlapped结构变量,同步方式置为NULL

最后

以上就是感性蓝天为你收集整理的驱动程序(7) WDF下DMA传输的驱动程序代码详细说明之应用程序application.c的全部内容,希望文章能够帮你解决驱动程序(7) WDF下DMA传输的驱动程序代码详细说明之应用程序application.c所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(51)

评论列表共有 0 条评论

立即
投稿
返回
顶部