• USB HID通讯流程


    创建C# USB hid通讯类

    下面是应用到WIN32 API:

    1. 读取Hid设备全局id

    [DllImport("hid.dll")]

      private static extern void HidD_GetHidGuid(ref Guid HidGuid);

     

    2. 取得一个包含所有HID接口信息集合的句柄

           [DllImport("setupapi.dll", SetLastError = true)]

    private static extern IntPtr SetupDiGetClassDevs(ref Guid ClassGuid, uint Enumerator, IntPtr HwndParent, DIGCF Flags);

     

    3.遍历信息集合,得到每个设备的接口信息

     

    [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);

     

    4. 取得接口详细信息:第一次读取错误,但可以取得信息缓冲区的大小

    SetupDiGetDeviceInterfaceDetail(hidInfoSet, ref interfaceInfo, IntPtr.Zero, buffsize, ref buffsize, null);

     

    5. 取得接口详细信息: 第二次可以读取内容(内容包括VID,PID)

    SetupDiGetDeviceInterfaceDetail(hidInfoSet, ref interfaceInfo, IntPtr.Zero, buffsize, ref buffsize, null);

    6. 利用上一步读取的设备路径信息,使用CreateFile打开设备

    [DllImport("kernel32.dll", SetLastError = true)]

            protected static extern SafeFileHandle CreateFile(string strName, uint nAccess, uint nShareMode, uint lpSecurity, uint nCreationFlags, uint nAttributes, uint lpTemplate);

     

    7. 根据文件句柄,读取设备属性信息

    [DllImport("hid.dll")]

            private static extern Boolean HidD_GetAttributes(SafeFileHandle hidDeviceObject, out HIDD_ATTRIBUTES attributes);

     

    8. 根据属性信息, 判断VID和PID和下位机设备相同,得到此设备

    根据得到的匹配设备, 得到准备数据

    [DllImport("hid.dll")]

            private static extern Boolean HidD_GetPreparsedData(SafeFileHandle hidDeviceObject, out IntPtr PreparsedData);

    [DllImport("hid.dll")]

            private static extern Boolean HidD_FreePreparsedData(IntPtr PreparsedData);

     

    [DllImport("hid.dll")]

            private static extern uint HidP_GetCaps(IntPtr PreparsedData, out HIDP_CAPS Capabilities);

     

    9.创建文件流

    hidDevice = new FileStream(device, FileAccess.ReadWrite, inputReportLength, true);

     

    10. 根据文件流读写数据

    从流中读取字节块并将该数据写入给定缓冲区中。

    public override int Read(byte[] array, int offset, int count);

    使用从缓冲区读取的数据将字节块写入该流。

    public override void Write(byte[] array, int offset, int count);

     注意内容:

    发送内容的时候需要发送outputReportLength长度的内容,其中第一个字节是reportid=0x00,发送内容从第二个字节开始,这里的获取到下位机设置的outputReportLength为65

     

    接收下位机内容时,下位机需要发inputReportLength长度的内容, 这里的长度为64

     

    核心源码:

     public class Hid : object
        {
            protected const Int32 WAIT_TIMEOUT = 0X102;
            protected const Int32 WAIT_OBJECT_0 = 0;
            protected static string strDevicePath = "";
    
            public UInt16 VID = 0x0483;
            public UInt16 PID = 0x5750;
            private IntPtr INVALID_HANDLE_VALUE = new IntPtr(-1);
            private const int MAX_USB_DEVICES = 64;
            private bool deviceOpened = false;
            private FileStream  hidDevice = null;
    
            int outputReportLength;//输出报告长度,包刮一个字节的报告ID
            public int OutputReportLength { get { return outputReportLength; } }
            int inputReportLength;//输入报告长度,包刮一个字节的报告ID   
            public int InputReportLength { get { return inputReportLength; } }
    
            private Guid device_class;
            private IntPtr usb_event_handle;
            private IntPtr handle;
            private SafeFileHandle device;
            private frmMain _main;
            private Thread _readThread;
            private int _openDeviceFlag = 0;
            public int OpenDeviceFlag
            {
                get { return _openDeviceFlag; }
                set { _openDeviceFlag = value; }
            }
    
            public Hid(frmMain main)
            {
                device_class = HIDGuid;
                _main = main;
            }
    
            /// <summary>
            /// Provides details about a single USB device
            /// </summary>
            [StructLayout(LayoutKind.Sequential, Pack = 1)]
            protected struct DeviceInterfaceData
            {
                public int Size;
                public Guid InterfaceClassGuid;
                public int Flags;
                public IntPtr Reserved; // should correspond to ULONG_PTR but was an int
            }
    
            private static string GetDevicePath(IntPtr hInfoSet, ref DeviceInterfaceData oInterface)
            {
                DeviceInterfaceDetailData oDetail = new DeviceInterfaceDetailData();
                // Size workaround
                if (IntPtr.Size == 8)
                    oDetail.Size = 8;
                else
                    oDetail.Size = 5;
                Console.WriteLine("Size of struct: {0}", Marshal.SizeOf(oDetail)); // 4 + 256 = 260
    
                uint nRequiredSize = 0;
    
                // Error 0
                if (!SetupDiGetDeviceInterfaceDetail(hInfoSet, ref oInterface, IntPtr.Zero, 0, ref nRequiredSize, IntPtr.Zero))
                    // Error 122 - ERROR_INSUFFICIENT_BUFFER (not a problem, just used to set nRequiredSize)
                    if (SetupDiGetDeviceInterfaceDetail(hInfoSet, ref oInterface, ref oDetail, nRequiredSize, ref nRequiredSize, IntPtr.Zero))
                        return oDetail.DevicePath;
                   // Error 1784 - ERROR_INVALID_USER_BUFFER (unless size=5 on 32bit, size=8 on 64bit)
                return null;
            }
    
            /// <summary>
            /// 打开指定信息的设备
            /// </summary>
            /// <param name="vID">设备的vID</param>
            /// <param name="pID">设备的pID</param>
            /// <param name="serial">设备的serial</param>,string serial
            /// <returns></returns>
            
            public HID_RETURN OpenDevice(UInt16 vID,UInt16 pID)
            {
               // IntPtr hInfoSet = SetupDiGetClassDevs(ref gHid, null, IntPtr.Zero, DIGCF_DEVICEINTERFACE | DIGCF_PRESENT);
                if (deviceOpened == false)
                {
                    //获取连接的HID列表
                    List<string> deviceList = new List<string>();
                    GetHidDeviceList(ref deviceList);
                    if (deviceList.Count == 0)
                        return HID_RETURN.NO_DEVICE_CONECTED;
                    for (int i = 0; i < deviceList.Count; i++)
                    {
                          device = CreateFile(deviceList[i], DESIREDACCESS.GENERIC_READ | DESIREDACCESS.GENERIC_WRITE, 0, 0, CREATIONDISPOSITION.OPEN_EXISTING, FLAGSANDATTRIBUTES.FILE_FLAG_OVERLAPPED, 0);
                        if (!device.IsInvalid)
                        { // strDevicePath = GetDevicePath(hInfoSet, ref oInterface);
                            HIDD_ATTRIBUTES attributes;
                            //IntPtr serialBuff = Marshal.AllocHGlobal(512);
                            HidD_GetAttributes(device, out attributes);
                            //HidD_GetSerialNumberString(device, serialBuff, 512);
                            //string deviceStr = Marshal.PtrToStringAuto(serialBuff);
                            //Marshal.FreeHGlobal(serialBuff);
                            if (attributes.VendorID == vID && attributes.ProductID == pID)   // && deviceStr == serial
                            {
                                IntPtr preparseData;
                                HIDP_CAPS caps;
                                HidD_GetPreparsedData(device, out preparseData);
                                HidP_GetCaps(preparseData, out caps);
                                HidD_FreePreparsedData(preparseData);
                                outputReportLength = caps.OutputReportByteLength;
                                inputReportLength = caps.InputReportByteLength;
    
                                hidDevice = new FileStream (device, FileAccess.ReadWrite, inputReportLength, true);
                                deviceOpened = true;
                                //BeginAsyncRead();
                                Guid gHid = HIDGuid;
                                IntPtr hInfoSet = SetupDiGetClassDevs(ref gHid, null, IntPtr.Zero, DIGCF_DEVICEINTERFACE | DIGCF_PRESENT);
                                DeviceInterfaceData oInterface = new DeviceInterfaceData();
                                strDevicePath = GetDevicePath(hInfoSet, ref oInterface);
                                return HID_RETURN.SUCCESS;
                            }
                        }
                    }
                    return HID_RETURN.DEVICE_NOT_FIND;
                }
                else
                    return HID_RETURN.DEVICE_OPENED;
            }
    
            /// <summary>
            /// 关闭打开的设备
            /// </summary>
            public void CloseDevice()
            {
                if (deviceOpened == true)
                {
                    hidDevice.Close();
                    deviceOpened = false;
                }
            }
    
            /// <summary>
            /// 开始一次异步读
            /// </summary>
            private void BeginAsyncRead()
            {
                byte[] inputBuff = new byte[InputReportLength];
                hidDevice.BeginRead(inputBuff, 0, InputReportLength, new AsyncCallback(ReadCompleted), inputBuff);            
            }
    
            /// <summary>
            /// 异步读取结束,发出有数据到达事件
            /// </summary>
            /// <param name="iResult">这里是输入报告的数组</param>
            private void ReadCompleted(IAsyncResult iResult)
            {
                byte[] readBuff = (byte[])(iResult.AsyncState);
                try
                {
                    hidDevice.EndRead(iResult);//读取结束,如果读取错误就会产生一个异常
                    byte[] reportData= new byte[readBuff.Length - 1];
                    for (int i = 1; i < readBuff.Length; i++)
                        reportData[i - 1] = readBuff[i];
                    Report e = new Report(readBuff[0], reportData);
                    //OnDataReceived(e); //发出数据到达消息
                    Define.cmdRecv.ProcData(reportData,reportData.Length);
                    BeginAsyncRead();//启动下一次读操作
                }
                catch (IOException e)//读写错误,设备已经被移除
                {
                    EventArgs ex = new EventArgs();
                    OnDeviceRemoved(ex);//发出设备移除消息
                    CloseDevice();
    
                }
            }
    
            /// <summary>
            /// 事件:数据到达,处理此事件以接收输入数据
            /// </summary>
            public event EventHandler<Report> DataReceived;
            protected virtual void OnDataReceived(Report e)
            {
                if(DataReceived != null) DataReceived(this, e);
            }
    
            /// <summary>
            /// 事件:设置连接
            /// </summary>
            public event EventHandler DeviceArrived;
            protected virtual void OnDeviceArrived( EventArgs e )
            {
                if (DeviceArrived != null) DeviceArrived(this, e);
            }
    
            /// <summary>
            /// 事件:设备断开
            /// </summary>
            public event EventHandler DeviceRemoved;
            protected virtual void OnDeviceRemoved(EventArgs e)
            {
                if (DeviceRemoved != null) DeviceRemoved(this, e);
            }
    
            /// <summary>
            /// 发送report命令
            /// </summary>
            /// <param name="buffer"></param>
            /// <returns></returns>
            public string  Write(Report r)
            {
                byte[] buffer = null;
                if (deviceOpened) 
                {
                    try
                    {
                         buffer = new byte[outputReportLength];
                        buffer[0] = r.reportID;
                        int maxBufferLength = 0;
                        if (r.reportBuff.Length < outputReportLength - 1)
                            maxBufferLength = r.reportBuff.Length;
                        else
                            maxBufferLength = outputReportLength - 1;
                        for (int i = 1; i < maxBufferLength; i++)
                            buffer[i] = r.reportBuff[i - 1];
                        hidDevice.Write(buffer, 0, OutputReportLength);
                        //buffer=   DataRead();
    
                        //Hid.ByteToHexString(buffer);
                    }
                    catch
                    {
                        EventArgs ex = new EventArgs();
                        OnDeviceRemoved(ex);//发出设备移除消息
                        CloseDevice();
                        throw;
                    }
                    
                }
                return ByteToHexString(buffer);
            }
    
            /// <summary>
            /// 发送字节数组命令
            /// </summary>
            /// <param name="buffer"></param>
            /// <returns></returns>
            public bool Write(Byte[] buf)
            {
                if (deviceOpened)
                {
                    try
                    {
                        hidDevice.Write(buf, 0, OutputReportLength);
    
                        if (_readThread == null)
                        {
                            _readThread = new Thread(new ThreadStart(DataRead));
                            _readThread.IsBackground = true;
                            _readThread.Start();
                        }
                        
                       
                        //buffer = DataRead();
                        //Hid.ByteToHexString(buffer);
    
                        return true;
                    }
                    catch
                    {
                        EventArgs ex = new EventArgs();
                        OnDeviceRemoved(ex);//发出设备移除消息
                        CloseDevice();
                        return false;
                        
                    }
                }
                else
                {
                    return false;
                }
            }
    
    
            private void  DataRead()
            {
                try
                {
                    InputReportViaInterruptTransfer report = new InputReportViaInterruptTransfer();
    
                    bool foundMyDevice = false;
                    bool result = false;
                    byte[] readBuffer = new Byte[OutputReportLength];
    
                    report.Read(device, ref foundMyDevice, ref readBuffer, ref result);
                    if (result == false)
                    {
                        _main.ProgressBarEnd();
                        MessageBox.Show("更新超时!");
                    }
                    _readThread = null;
                }
                catch(Exception ex)
                {
                    _readThread = null;
                }
            }
    
            internal class InputReportViaInterruptTransfer : ReportIn
            {
                internal Boolean readyForOverlappedTransfer; //  initialize to false
    
                ///  <summary>
                ///  closes open handles to a device.
                ///  </summary>
                ///  
                ///  <param name="hidHandle"> the handle for learning about the device and exchanging Feature reports. </param>
                ///  <param name="readHandle"> the handle for reading Input reports from the device. </param>
                ///  <param name="writeHandle"> the handle for writing Output reports to the device. </param>
    
                internal void CancelTransfer(SafeFileHandle hidHandle, SafeFileHandle readHandle, SafeFileHandle writeHandle, IntPtr eventObject)
                {
                    try
                    {
                        //  ***
                        //  API function: CancelIo
    
                        //  Purpose: Cancels a call to ReadFile
    
                        //  Accepts: the device handle.
    
                        //  Returns: True on success, False on failure.
                        //  ***
    
                        CancelIo(readHandle);
    
                        //Console.WriteLine("************ReadFile error*************");
                        //String functionName = "CancelIo";
                        //Console.WriteLine(MyDebugging.ResultOfAPICall(functionName));
                        //Console.WriteLine("");
    
                        //  The failure may have been because the device was removed,
                        //  so close any open handles and
                        //  set myDeviceDetected=False to cause the application to
                        //  look for the device on the next attempt.
    
                        if ((!(hidHandle.IsInvalid)))
                        {
                            hidHandle.Close();
                        }
    
                        if ((!(readHandle.IsInvalid)))
                        {
                            readHandle.Close();
                        }
    
                        if ((!(writeHandle.IsInvalid)))
                        {
                            writeHandle.Close();
                        }
                    }
                    catch (Exception ex)
                    {
                        //DisplayException(MODULE_NAME, ex);
                        throw;
                    }
                }
    
                ///  <summary>
                ///  Creates an event object for the overlapped structure used with 
                ///  ReadFile. Called before the first call to ReadFile.
                ///  </summary>
                ///  
                ///  <param name="hidOverlapped"> the overlapped structure </param>
                ///  <param name="eventObject"> the event object </param>
    
                internal void PrepareForOverlappedTransfer(ref NativeOverlapped hidOverlapped, ref IntPtr eventObject)
                {
                    try
                    {
                        //  ***
                        //  API function: CreateEvent
    
                        //  Purpose: Creates an event object for the overlapped structure used with ReadFile.
    
                        //  Accepts:
                        //  A security attributes structure or IntPtr.Zero.
                        //  Manual Reset = False (The system automatically resets the state to nonsignaled 
                        //  after a waiting thread has been released.)
                        //  Initial state = False (not signaled)
                        //  An event object name (optional)
    
                        //  Returns: a handle to the event object
                        //  ***
    
                        eventObject = CreateEvent(IntPtr.Zero, false, false, "");
    
                        //  Console.WriteLineLine(MyDebugging.ResultOfAPICall("CreateEvent"))
    
                        //  Set the members of the overlapped structure.
    
                        hidOverlapped.OffsetLow = 0;
                        hidOverlapped.OffsetHigh = 0;
                        hidOverlapped.EventHandle = eventObject;
                        readyForOverlappedTransfer = true;
                    }
                    catch (Exception ex)
                    {
                        //DisplayException(MODULE_NAME, ex);
                        throw;
                    }
                }
    
                ///  <summary>
                ///  reads an Input report from the device using interrupt transfers.
                ///  </summary>
                ///  
                ///  <param name="hidHandle"> the handle for learning about the device and exchanging Feature reports. </param>
                ///  <param name="readHandle"> the handle for reading Input reports from the device. </param>
                ///  <param name="writeHandle"> the handle for writing Output reports to the device. </param>
                ///  <param name="myDeviceDetected"> tells whether the device is currently attached. </param>
                ///  <param name="inputReportBuffer"> contains the requested report. </param>
                ///  <param name="success"> read success </param>
               
               internal override void Read(SafeFileHandle readHandle, ref Boolean myDeviceDetected, ref  Byte[] inputReportBuffer, ref Boolean success)
                {
                    IntPtr eventObject = CreateEvent(IntPtr.Zero, false, false, "");  //IntPtr.Zero;
                    NativeOverlapped HidOverlapped = new NativeOverlapped();
                    Int32 numberOfBytesRead = 0;
                    Int32 result = 0;
                    try
                    {
                        //  If it's the first attempt to read, set up the overlapped structure for ReadFile.
    
                        if (readyForOverlappedTransfer == false)
                        {
                            PrepareForOverlappedTransfer(ref HidOverlapped, ref eventObject);
                        }
    
                        //  ***
                        //  API function: ReadFile
                        //  Purpose: Attempts to read an Input report from the device.
    
                        //  Accepts:
                        //  A device handle returned by CreateFile
                        //  (for overlapped I/O, CreateFile must have been called with FILE_FLAG_OVERLAPPED),
                        //  A pointer to a buffer for storing the report.
                        //  The Input report length in bytes returned by HidP_GetCaps,
                        //  A pointer to a variable that will hold the number of bytes read. 
                        //  An overlapped structure whose hEvent member is set to an event object.
    
                        //  Returns: the report in ReadBuffer.
    
                        //  The overlapped call returns immediately, even if the data hasn't been received yet.
    
                        //  To read multiple reports with one ReadFile, increase the size of ReadBuffer
                        //  and use NumberOfBytesRead to determine how many reports were returned.
                        //  Use a larger buffer if the application can't keep up with reading each report
                        //  individually. 
                        //  ***                    
    
                        success = ReadFile(readHandle, inputReportBuffer, inputReportBuffer.Length, ref numberOfBytesRead, ref HidOverlapped);
    
                        if (!success)
                        {
                            Console.WriteLine("waiting for ReadFile");
    
                            //  API function: WaitForSingleObject
    
                            //  Purpose: waits for at least one report or a timeout.
                            //  Used with overlapped ReadFile.
    
                            //  Accepts:
                            //  An event object created with CreateEvent
                            //  A timeout value in milliseconds.
    
                            //  Returns: A result code.
    
                            result = WaitForSingleObject(eventObject, 3000); //eventObject
    
                            //result = GetOverlappedResult(readHandle.DangerousGetHandle(), ref HidOverlapped, ref numberOfBytesRead, false);
                            //if (result != 0)
                            //    success = true;
                            //  Find out if ReadFile completed or timeout.
    
                            switch (result)
                            {
                                case (System.Int32)WAIT_OBJECT_0:
    
                                    //  ReadFile has completed
                                    success = true;
                                    Console.WriteLine("ReadFile completed successfully.");
    
                                    Define.cmdRecv.ProcData(inputReportBuffer, inputReportBuffer.Length);
    
                                    break;
                                case WAIT_TIMEOUT:
    
                                    //  Cancel the operation on timeout
                                    //  CancelTransfer(hidHandle, readHandle, writeHandle, eventObject);
                                    Console.WriteLine("Readfile timeout");
                                    success = false;
                                    myDeviceDetected = false;
                                    
                                    break;
                                default:
    
                                    //  Cancel the operation on other error.
                                    //CancelTransfer(hidHandle, readHandle, writeHandle, eventObject);
                                    Console.WriteLine("Readfile undefined error");
                                    success = false;
                                    myDeviceDetected = false;
                                    break;
                            }
    
                        }
                         
                    }
                    catch (Exception ex)
                    {
                        ////DisplayException(MODULE_NAME, ex);
                        throw;
                    }
                }
            }
            internal abstract class ReportIn
            {
                ///  <summary>
                ///  Each class that handles reading reports defines a Read method for reading 
                ///  a type of report. Read is declared as a Sub rather
                ///  than as a Function because asynchronous reads use a callback method 
                ///  that can access parameters passed by ByRef but not Function return values.
                ///  </summary>
    
                internal abstract void Read(SafeFileHandle readHandle,  ref Boolean myDeviceDetected, ref Byte[] readBuffer, ref Boolean success);
            }
    
    
            /// <summary>
            /// 获取所有连接的hid的设备路径
            /// </summary>
            /// <returns>包含每个设备路径的字符串数组</returns>
            public static void GetHidDeviceList(ref List<string> deviceList)
            {
                Guid hUSB = Guid.Empty;
                uint index = 0;
    
                deviceList.Clear();
                // 取得hid设备全局id
                HidD_GetHidGuid(ref hUSB);
                //取得一个包含所有HID接口信息集合的句柄
                IntPtr hidInfoSet = SetupDiGetClassDevs(ref hUSB, 0, IntPtr.Zero, DIGCF.DIGCF_PRESENT | DIGCF.DIGCF_DEVICEINTERFACE);
                if (hidInfoSet != IntPtr.Zero)
                {
                    SP_DEVICE_INTERFACE_DATA interfaceInfo = new SP_DEVICE_INTERFACE_DATA();
                    interfaceInfo.cbSize = Marshal.SizeOf(interfaceInfo);
                    //查询集合中每一个接口
                    for (index = 0; index < MAX_USB_DEVICES; index++)
                    {
                        //得到第index个接口信息
                        if (SetupDiEnumDeviceInterfaces(hidInfoSet, IntPtr.Zero, ref hUSB, index, ref interfaceInfo))
                        {
                            int buffsize = 0;
                            // 取得接口详细信息:第一次读取错误,但可以取得信息缓冲区的大小
                            SetupDiGetDeviceInterfaceDetail(hidInfoSet, 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));
                            Marshal.StructureToPtr(detail, pDetail, false);
                            if (SetupDiGetDeviceInterfaceDetail(hidInfoSet, ref interfaceInfo, pDetail, buffsize, ref buffsize, null))
                            {
                                deviceList.Add(Marshal.PtrToStringAuto((IntPtr)((int)pDetail + 4)));
                            }
                            Marshal.FreeHGlobal(pDetail);
                        }
                    }
                }
                SetupDiDestroyDeviceInfoList(hidInfoSet);
                //return deviceList.ToArray();
            }
    
            public void ParseMessages( ref Message m )
            {
                if (m.Msg == DEVICE_FLAG.WM_DEVICECHANGE)    // we got a device change message! A USB device was inserted or removed
                {
                    switch (m.WParam.ToInt32())    // Check the W parameter to see if a device was inserted or removed
                    {
                        case DEVICE_FLAG.DEVICE_ARRIVAL:    // inserted
                            Console.WriteLine("ParseMessages 设备连接");
                            if (DeviceArrived != null)
                            {
                                DeviceArrived(this, new EventArgs());
                            }
                            CheckDevicePresent();
                            break;
                        case DEVICE_FLAG.DEVICE_REMOVECOMPLETE:    // removed
                            Console.WriteLine("ParseMessages 设备拔除");
                            if (DeviceRemoved != null)
                            {
                                DeviceRemoved(this, new EventArgs());
                            }
                            CheckDevicePresent();
                            break;
                    }
                }
            }
    
            public void RegisterHandle( IntPtr Handle )
            {
                usb_event_handle = RegisterForUsbEvents(Handle, device_class);
                this.handle = Handle;
                //Check if the device is already present.
                CheckDevicePresent();
            }
    
            public bool CheckDevicePresent()
            {
                HID_RETURN hid_ret;
                string sSerial="";
                try
                {
                    hid_ret = OpenDevice(VID, PID);
                    if (hid_ret == HID_RETURN.SUCCESS)
                    {
                        Console.WriteLine("打开设备成功");
                        _openDeviceFlag = (int)HID_RETURN.SUCCESS;
                        return true;
                    }
                    else
                    {
                        _openDeviceFlag = (int)hid_ret;
                        return false;
                    }
                }
                catch (System.Exception ex)
                {
    
                    return false;
                }
            }
    
            /// <summary>
            /// Helper to get the HID guid.
            /// </summary>
            public static Guid HIDGuid
            {
                get
                {
                    Guid gHid = Guid.Empty;
                    HidD_GetHidGuid(ref gHid);
                    return gHid;
                    //return new Guid("A5DCBF10-6530-11D2-901F-00C04FB951ED"); //gHid;
                }
            }
  • 相关阅读:
    git_02_git常用操作命令
    git_01_上传第一个项目至git
    Jenkins持续集成_04_解决HTML测试报告样式丢失问题
    Jenkins持续集成_03_添加测试报告
    Jenkins持续集成_02_添加python项目&设置定时任务
    Jenkins持续集成_01_Mac安装配置
    Mac获取Jenkins管理员初始密码
    (appium+python)UI自动化_10_adb常用命令
    安卓monkey自动化测试,软硬回车
    冒烟测试
  • 原文地址:https://www.cnblogs.com/hdsong/p/7792694.html
Copyright © 2020-2023  润新知