首先,通信流程我们先撸一边,打开USB设备-》发送数据库-》接受数据-》关闭USB设备
根据USB规范的规定,所有的USB设备都有供应商ID(VID)和产品识别码(PID),主机通过不同的VID和PID来区别不同的设备。
我们需要知道设备的VID和PID才能定位到我们需要打开的USB设备,那么我们怎么知道USB设备的VID和PID参数呢?
方法一:电脑上查看
方法二,代码查看
大家可以自己百度下,很多文章都有写。。。。。c# 查看所有USB信息
知道设备的VID和HID后,剩下的就好操作了。二话不说,直接上代码。
注意:很重要
1:大家可以网上查看其它文章,有很多USB-HID通信文章,大家可以参考和借鉴,但是实际使用过程中需要注意的是人家的文章是用于HID的设备,如果你设备不是HID的那么就用不了。
那么怎么查自己的设备是什么类型的呢?windows是通过设备接口类的GUID来区分的
常用设备接口类GUID,大家可以自己查看自己的设备是什么类别的,比如
HID: "{4D1E55B2-F16F-11CF-88CB-001111000030}"; USB_DEVICE: "{A5DCBF10-6530-11D2-901F-00C04FB951ED}"; COMPORT: "{86E0D1E0-8089-11D0-9CE4-08003E301F73}";
我们需要根据设备接口类的GUID,获取对应的设备列表,再通过VID和GUID去设备列表中匹配对应的设备,获取设备的路径,通过路径打开设备进行通信。具体的自己分析代码
using Microsoft.Win32.SafeHandles; using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Runtime.InteropServices; using System.Text; using System.Threading.Tasks;
namespace TPCL.USB { class UsbDevice { #region MyRegion private FileStream DeviceIo = null; //异步IO流 private bool is_open = false; private IntPtr device = new IntPtr(-1);
private const int MAX_USB_DEVICES = 64; private static IntPtr INVALID_HANDLE_VALUE = new IntPtr(-1); //常用设备接口类GUID private const string HidGuid = "{4D1E55B2-F16F-11CF-88CB-001111000030}"; private const string UsbDevGuid = "{A5DCBF10-6530-11D2-901F-00C04FB951ED}"; private const string UsbComPort = "{86E0D1E0-8089-11D0-9CE4-08003E301F73}";
public static void GetAllUsbDevice(ref List<string> UsbDeviceList) { UsbDeviceList.Clear(); Guid guid = Guid.Parse(UsbDevGuid); IntPtr deviceInfoSet = SetupDiGetClassDevs(ref guid, 0, IntPtr.Zero, DIGCF.DIGCF_PRESENT | DIGCF.DIGCF_DEVICEINTERFACE); if (deviceInfoSet != IntPtr.Zero) { SP_DEVICE_INTERFACE_DATA interfaceInfo = new SP_DEVICE_INTERFACE_DATA(); interfaceInfo.cbSize = Marshal.SizeOf(interfaceInfo); for (uint index = 0; index < 64; index++) { if (SetupDiEnumDeviceInterfaces(deviceInfoSet, IntPtr.Zero, ref guid, index, ref interfaceInfo)) { // 取得接口详细信息:第一次读取错误,但可以取得信息缓冲区的大小 int buffsize = 0; SetupDiGetDeviceInterfaceDetail(deviceInfoSet, ref interfaceInfo, IntPtr.Zero, buffsize, ref buffsize, null); //构建接收缓冲 IntPtr pDetail = Marshal.AllocHGlobal(buffsize); SP_DEVICE_INTERFACE_DETAIL_DATA detail = new SP_DEVICE_INTERFACE_DETAIL_DATA(); //detail.cbSize = Marshal.SizeOf(typeof(SP_DEVICE_INTERFACE_DETAIL_DATA)); if (IntPtr.Size == 8) detail.cbSize = 8; // for 64 bit operating systems else detail.cbSize = 4 + Marshal.SystemDefaultCharSize; // for 32 bit operating systems Marshal.StructureToPtr(detail, pDetail, false); if (SetupDiGetDeviceInterfaceDetail(deviceInfoSet, ref interfaceInfo, pDetail, buffsize, ref buffsize, null)) { UsbDeviceList.Add(Marshal.PtrToStringAuto((IntPtr)((int)pDetail + 4))); } // Marshal.FreeHGlobal(pDetail); } } } SetupDiDestroyDeviceInfoList(deviceInfoSet); }
public int OpenUsbDevice(UInt16 vID, UInt16 pID) { List<string> deviceList = new List<string>(); GetAllUsbDevice(ref deviceList); if (deviceList.Count == 0) return 0;
string VID = string.Format("{0:X4}", vID); string PID = string.Format("{0:X4}", pID);
foreach (string item in deviceList) { if (item.ToLower().Contains(VID.ToLower()) && item.ToLower().Contains(PID.ToLower())) //指定设备 { Debug.WriteLine(item); if (is_open == false) { device = CreateFile(item, DESIREDACCESS.GENERIC_READ | DESIREDACCESS.GENERIC_WRITE, 0, 0, CREATIONDISPOSITION.OPEN_EXISTING, 0x40000000, 0);
if (device != INVALID_HANDLE_VALUE) { Debug.WriteLine("open"); DeviceIo = new FileStream(new SafeFileHandle(device, false), FileAccess.ReadWrite,40,true); //DeviceIo = new FileStream(new SafeFileHandle(device, false), FileAccess.ReadWrite); this.is_open = true; return 1; } CloseHandle(device); } } } return 0; }
public void CloseDevice() { if (is_open == true) { is_open = false; DeviceIo.Close(); CloseHandle(device); } }
public void Send(string dataString) { if (DeviceIo == null) { Debug.WriteLine("USB Device not open"); return; } byte[] data = Encoding.GetEncoding("GBK").GetBytes(dataString); //打印机支持GBK中文 // byte[] data = System.Text.Encoding.ASCII.GetBytes(dataString); DeviceIo.Write(data, 0, data.Length); }
public void Read() { //DeviceIo.Read }
public bool GetDeviceState() { return is_open; }
#endregion
#region Win32_api public enum DIGCF { DIGCF_DEFAULT = 0x00000001, //只返回与系统默认设备相关的设备。 DIGCF_PRESENT = 0x00000002, //只返回当前存在的设备。 DIGCF_ALLCLASSES = 0x00000004, //返回所有已安装的设备。如果这个标志设置了,ClassGuid参数将被忽略 DIGCF_PROFILE = 0x00000008, //只返回当前硬件配置文件中的设备。 DIGCF_DEVICEINTERFACE = 0x00000010 //返回所有支持的设备。 }
/// <summary> /// 接口数据定义 /// </summary> public struct SP_DEVICE_INTERFACE_DATA { public int cbSize; public Guid interfaceClassGuid; public int flags; public int reserved; } /// <summary> /// 定义设备实例,该实例是设备信息集的成员 /// </summary> public class SP_DEVINFO_DATA { public int cbSize = Marshal.SizeOf(typeof(SP_DEVINFO_DATA)); public Guid classGuid = Guid.Empty; // temp public int devInst = 0; // dumy public int reserved = 0; }
internal struct SP_DEVICE_INTERFACE_DETAIL_DATA { internal int cbSize; internal short devicePath; }
/// <summary> /// 获取USB-HID设备的设备接口类GUID,即{4D1E55B2-F16F-11CF-88CB-001111000030} /// </summary> /// <param name="HidGuid"></param> [DllImport("hid.dll")] private static extern void HidD_GetHidGuid(ref Guid HidGuid);
/// <summary> /// 获取对应GUID的设备信息集(句柄) /// </summary> /// <param name="ClassGuid">设备设置类或设备接口类的guid</param> /// <param name="Enumerator">指向以空结尾的字符串的指针,该字符串提供PNP枚举器或PNP设备实例标识符的名称</param> /// <param name="HwndParent">用于用户界面的顶级窗口的句柄</param> /// <param name="Flags">一个变量,指定用于筛选添加到设备信息集中的设备信息元素的控制选项。</param> /// <returns>设备信息集的句柄</returns> [DllImport("setupapi.dll", SetLastError = true)] private static extern IntPtr SetupDiGetClassDevs(ref Guid ClassGuid, uint Enumerator, IntPtr HwndParent, DIGCF Flags);
/// <summary> /// 根据句柄,枚举设备信息集中包含的设备接口。 /// </summary> /// <param name="deviceInfoSet"></param> /// <param name="deviceInfoData"></param> /// <param name="interfaceClassGuid"></param> /// <param name="memberIndex"></param> /// <param name="deviceInterfaceData"></param> /// <returns></returns> [DllImport("setupapi.dll", CharSet = CharSet.Auto, SetLastError = true)] private static extern Boolean SetupDiEnumDeviceInterfaces(IntPtr deviceInfoSet, IntPtr deviceInfoData, ref Guid interfaceClassGuid, UInt32 memberIndex, ref SP_DEVICE_INTERFACE_DATA deviceInterfaceData);
/// <summary> /// 获取接口详细信息,在第一次主要是读取缓存信息,第二次获取详细信息(必须调用两次) /// </summary> /// <param name="deviceInfoSet">指向设备信息集的指针,它包含了所要接收信息的接口。该句柄通常由SetupDiGetClassDevs函数返回。</param> /// <param name="deviceInterfaceData">返回数据</param> /// <param name="deviceInterfaceDetailData"></param> /// <param name="deviceInterfaceDetailDataSize"></param> /// <param name="requiredSize"></param> /// <param name="deviceInfoData"></param> /// <returns></returns> [DllImport("setupapi.dll", SetLastError = true, CharSet = CharSet.Auto)] private static extern bool SetupDiGetDeviceInterfaceDetail(IntPtr deviceInfoSet, ref SP_DEVICE_INTERFACE_DATA deviceInterfaceData, IntPtr deviceInterfaceDetailData, int deviceInterfaceDetailDataSize, ref int requiredSize, SP_DEVINFO_DATA deviceInfoData);
/// <summary> /// 删除设备信息并释放内存。 /// </summary> /// <param name="HIDInfoSet"></param> /// <returns></returns> [DllImport("setupapi.dll", CharSet = CharSet.Auto, SetLastError = true)] private static extern Boolean SetupDiDestroyDeviceInfoList(IntPtr deviceInfoSet); #endregion
#region Open_Device /// <summary> /// 访问权限 /// </summary> static class DESIREDACCESS { public const uint GENERIC_READ = 0x80000000; public const uint GENERIC_WRITE = 0x40000000; public const uint GENERIC_EXECUTE = 0x20000000; public const uint GENERIC_ALL = 0x10000000; } /// <summary> /// 如何创建 /// </summary> static class CREATIONDISPOSITION { public const uint CREATE_NEW = 1; public const uint CREATE_ALWAYS = 2; public const uint OPEN_EXISTING = 3; public const uint OPEN_ALWAYS = 4; public const uint TRUNCATE_EXISTING = 5; }
/// <summary> /// /// </summary> /// <param name="lpFileName">普通文件名或设备文件名</param> /// <param name="desiredAccess">访问模式(写/读) GENERIC_READ、GENERIC_WRITE </param> /// <param name="shareMode">共享模式</param> /// <param name="securityAttributes">指向安全属性的指针</param> /// <param name="creationDisposition">如何创建</param> /// <param name="flagsAndAttributes">文件属性</param> /// <param name="templateFile">用于复制文件句柄</param> /// <returns></returns> [DllImport("kernel32.dll", SetLastError = true)] private static extern IntPtr CreateFile(string lpFileName, uint desiredAccess, uint shareMode, uint securityAttributes, uint creationDisposition, uint flagsAndAttributes, uint templateFile);
/// <summary> /// 关闭 /// </summary> /// <param name="hObject">Handle to an open object</param> /// <returns></returns> [DllImport("kernel32.dll")] private static extern int CloseHandle(IntPtr hObject);
#endregion } }
———————————————— 版权声明:本文为CSDN博主「毛小民°」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。 原文链接:https://blog.csdn.net/xiejie0226/article/details/102582053
|
请发表评论