USB HID 驱动程序(非重叠IO操作)

using System;
using System.Runtime.InteropServices;
using Microsoft.Win32.SafeHandles;
using System.Collections.Generic;
using System.Windows.Forms;


namespace MyUsbHid
{
    public class UsbHid
    {
        public const uint GENERIC_READ = 0x80000000;
        public const uint GENERIC_WRITE = 0x40000000;
        public const int FILE_SHARE_READ = 1;
        public const int FILE_SHARE_WRITE = 2;
        public const int OPEN_EXISTING = 3;
        public const int OPEN_ALWAYS = 4;
        public const int FILE_ATTRIBUTE_NORMAL = 0x80;
        public const int FILE_FLAG_OVERLAPPED = 0x40000000;

        public const int DIGCF_DEFAULT = 0x1;
        public const int DIGCF_PRESENT = 0x2;
        public const int DIGCF_ALLCLASSES = 0x4;
        public const int DIGCF_PROFILE = 0x8;
        public const int DIGCF_DEVICEINTERFACE = 0x10;

        public struct SP_DEVINFO_DATA
        {
            public int cbSize;
            public Guid classGuid;
            public int DevInst;
            public int reserved;

        }

        public struct SP_DEVICE_INTERFACE_DATA
        {
            public int cbSize;
            public Guid InterfaceClassGuid;
            public int flags;
            public int reserved;
        }

        public struct SP_DEVICE_INTERFACE_DETAIL_DATA
        {
            public int cbSize;
            public string devicePath;
        }

        // 获得GUID
        [DllImport("hid.dll", SetLastError = true)]
        public static extern void HidD_GetHidGuid(ref Guid HidGuid);

        // 请求指向设备信息集的指针
        [DllImport("setupapi.dll", SetLastError = true, CharSet = CharSet.Auto)]
        public static extern IntPtr SetupDiGetClassDevs(
            ref Guid ClassGuid,
            IntPtr enumerator, 
            IntPtr HwndParent, 
            int flags);

        // 标识设备接口
        [DllImport("setupapi.dll", SetLastError = true, CharSet = CharSet.Auto)]
        public static extern bool SetupDiEnumDeviceInterfaces(
            IntPtr DeviceInfoSet,
            IntPtr DeviceInfoData, 
            ref Guid InterfaceClassGuid, 
            int MemberIndex, 
            ref SP_DEVICE_INTERFACE_DATA DeviceInterfaceData);

        // 请求带有设备类路径名的结构体
        [DllImport("setupapi.dll", SetLastError = true, CharSet = CharSet.Auto)]
        public static extern bool SetupDiGetDeviceInterfaceDetail(
            IntPtr DeviceInfoSet, 
            ref SP_DEVICE_INTERFACE_DATA DeviceInterfaceData, 
            IntPtr DeviceInterfaceDetailData,
            int DeviceInterfaceDetailDataSize, 
            ref int RequiredSize,
            IntPtr DeviceInfoData);

        // 释放DeviceInfoSet资源
        [DllImport("setupapi.dll", SetLastError = true, CharSet = CharSet.Auto)]
        public static extern bool SetupDiDestroyDeviceInfoList(IntPtr DeviceInfoSet);

        // 请求通讯句柄
        [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
        public static extern SafeFileHandle CreateFile(
            string lpFileName,                // 文件名
            uint dwDesiredAccess,             // 访问模式
            int dwShareMode,                  // 共享模式
            int lpSecurityAttributes,         // 安全属性
            int dwCreationDisposition,        // 如何创建
            int dwFlagsAndAttributes,         // 如何创建
            int hTemplateFile);               // 模板文件的句柄

        // 读取设备文件
        [DllImport("Kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
        public static extern bool ReadFile(
            SafeFileHandle hFile,
            byte[] lpBuffer,
            uint nNumberOfBytesToRead,
            ref uint lpNumberOfBytesRead,
            IntPtr lpOverlapped);

        // 写设备文件
        [DllImport("Kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
        public static extern bool WriteFile(
            SafeFileHandle hFile,
            byte[] lpBuffer,
            uint nNumberOfBytesToWrite,
            ref uint lpNumberOfBytesWrite,
            IntPtr lpOverlapped);

        // 发现所有已连接的HID设备
        public static void FindAllHidDevices(ref List<string> DeviceList)
        {
            Guid HidGuid = Guid.Empty;            
            HidD_GetHidGuid(ref HidGuid);

            // 请求指向设备信息集的指针
            IntPtr DeviceInfoSet;
            DeviceInfoSet = SetupDiGetClassDevs(ref HidGuid, IntPtr.Zero, IntPtr.Zero, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
            if (DeviceInfoSet == IntPtr.Zero)
            {
                return;
            }

            int MemberIndex;
            bool result = true;

            for (MemberIndex = 0; ; MemberIndex++)
            {
                SP_DEVICE_INTERFACE_DATA MyDevInterfaceData = new SP_DEVICE_INTERFACE_DATA();
                MyDevInterfaceData.cbSize = Marshal.SizeOf(MyDevInterfaceData);

                result = SetupDiEnumDeviceInterfaces(DeviceInfoSet, IntPtr.Zero, ref HidGuid, MemberIndex, ref MyDevInterfaceData);
                if (!result)
                {
                    break;
                }
                
                int BufferSize = 0;

                // 第一次调用返回BufferSize的大小
                SetupDiGetDeviceInterfaceDetail(DeviceInfoSet, ref MyDevInterfaceData, IntPtr.Zero, 0, ref BufferSize, IntPtr.Zero);

                IntPtr DetailDataBuffer = Marshal.AllocHGlobal(BufferSize);

                Marshal.WriteInt32(DetailDataBuffer, (IntPtr.Size == 4) ? (4 + Marshal.SystemDefaultCharSize) : 8);

                // 第二次调用返回含有设备路径名的结构体MyDevInterfaceData
                result = SetupDiGetDeviceInterfaceDetail(DeviceInfoSet, ref MyDevInterfaceData, DetailDataBuffer, BufferSize, ref BufferSize, IntPtr.Zero);

                if (result == true)
                {
                    // 获取设备路径
                    IntPtr pDevicePathName = new IntPtr(DetailDataBuffer.ToInt32() + 4);
                    string DevicePathName = Marshal.PtrToStringAuto(pDevicePathName);                   
                    DeviceList.Add(DevicePathName);
                }
                Marshal.FreeHGlobal(DetailDataBuffer);
            }

            SetupDiDestroyDeviceInfoList(DeviceInfoSet);
        }

    }


    public class HidDevice
    {
        string DevicePathName;
        SafeFileHandle HidHandle;
        bool OpenStatus = false;

        public HidDevice(string DevicePathName)
        {
            this.DevicePathName = DevicePathName;
        }

        // 使用阻塞调用打开文件句柄
        public void open()
        {        
            HidHandle = UsbHid.CreateFile(
                DevicePathName,
                UsbHid.GENERIC_READ | UsbHid.GENERIC_WRITE, 
                UsbHid.FILE_SHARE_READ | UsbHid.FILE_SHARE_WRITE,
                0, 
                UsbHid.OPEN_EXISTING,
                UsbHid.FILE_ATTRIBUTE_NORMAL, 
                0);

            OpenStatus = true;
        }

        // 向HID设备写入数据
        public bool WriteData(
            byte[] buffer,             // 指向一个缓冲区,放置准备写入的数据
            ref uint length)           // 指向长度单元,输入时为准备写入的长度,返回后为实际写入的长度
        {
            if (OpenStatus == false)
            {
                MessageBox.Show("请打开HID设备", "提示");
                return false;
            }

            bool result;
            uint NumOfWrite = 0;

            result = UsbHid.WriteFile(HidHandle, buffer, length, ref NumOfWrite, IntPtr.Zero);
            length = NumOfWrite;

            if (!result)
            {
                return false;
            }

            return true;
        }

        // 从HID设备读取数据
        public bool ReadData(
            byte[] buffer,             // 指向一个缓冲区,放置准备读出的数据
            ref uint length)           // 指向长度单元,输入时为准备读出的长度,返回后为实际读出的长度
        {
            if (OpenStatus == false)
            {
                MessageBox.Show("请打开HID设备", "提示");
                return false;
            }

            bool result;
            uint NumOfRead = 0;

            result = UsbHid.ReadFile(HidHandle, buffer, length, ref NumOfRead, IntPtr.Zero);
            length = NumOfRead;

            if (!result)
            {
                return false;
            }

            return true;
        }

        public void close()
        {
            if (OpenStatus == false)
            {
                return;
            }

            OpenStatus = false;
            HidHandle.Close();
        }

    }
}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值