C# USB通信(调用Windows API)

 网上usb通信的案列有很多,或多或少的有点bug,我在做项目的时候,费了很大的功夫都是在调试bug,今天有空把usb通信的底层代码贴出来,方便大家使用。
 示例代码如下:

using System;
using System.Runtime.InteropServices;

namespace USB
{
public class Win32Usb
{
#region Structures
///
/// An overlapped structure used for overlapped IO operations. The structure is
/// only used by the OS to keep state on pending operations. You don’t need to fill anything in if you
/// unless you want a Windows event to fire when the operation is complete.
///
[StructLayout(LayoutKind.Sequential, Pack = 1)]
protected struct Overlapped
{
public uint Internal;
public uint InternalHigh;
public uint Offset;
public uint OffsetHigh;
public IntPtr Event;
}
///
/// Provides details about a single USB device
///
[StructLayout(LayoutKind.Sequential, Pack = 1)]
protected struct DeviceInterfaceData
{
public int Size;
public Guid InterfaceClassGuid;
public int Flags;
public IntPtr Reserved;
}
///
/// Provides the capabilities of a HID device
///
[StructLayout(LayoutKind.Sequential, Pack = 1)]
protected struct HidCaps
{
public ushort Usage;
public ushort UsagePage;
public ushort InputReportByteLength;
public ushort OutputReportByteLength;
public ushort FeatureReportByteLength;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 17)]
public ushort[] Reserved;
public ushort NumberLinkCollectionNodes;
public ushort NumberInputButtonCaps;
public ushort NumberInputValueCaps;
public ushort NumberInputDataIndices;
public ushort NumberOutputButtonCaps;
public ushort NumberOutputValueCaps;
public ushort NumberOutputDataIndices;
public ushort NumberFeatureButtonCaps;
public ushort NumberFeatureValueCaps;
public ushort NumberFeatureDataIndices;
}
///
/// Access to the path for a device
///
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct DeviceInterfaceDetailData
{
public int Size;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
public string DevicePath;
}
///
/// Used when registering a window to receive messages about devices added or removed from the system.
///
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode, Pack = 1)]
public class DeviceBroadcastInterface
{
public int Size;
public int DeviceType;
public int Reserved;
public Guid ClassGuid;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
public string Name;
}

    #region Constants
    /// Windows message sent when a device is inserted or removed
    public const int WM_DEVICECHANGE = 0x0219;
    /// WParam for above : A device was inserted
    public const int DEVICE_ARRIVAL = 0x8000;
    /// WParam for above : A device was removed
    public const int DEVICE_REMOVECOMPLETE = 0x8004;
    /// Used in SetupDiClassDevs to get devices present in the system
    protected const int DIGCF_PRESENT = 0x02;
    /// Used in SetupDiClassDevs to get device interface details
    protected const int DIGCF_DEVICEINTERFACE = 0x10;
    /// Used when registering for device insert/remove messages : specifies the type of device
    protected const int DEVTYP_DEVICEINTERFACE = 0x05;
    /// Used when registering for device insert/remove messages : we're giving the API call a window handle
    protected const int DEVICE_NOTIFY_WINDOW_HANDLE = 0;
    /// Purges Win32 transmit buffer by aborting the current transmission.
    protected const uint PURGE_TXABORT = 0x01;
    /// Purges Win32 receive buffer by aborting the current receive.
    protected const uint PURGE_RXABORT = 0x02;
    /// Purges Win32 transmit buffer by clearing it.
    protected const uint PURGE_TXCLEAR = 0x04;
    /// Purges Win32 receive buffer by clearing it.
    protected const uint PURGE_RXCLEAR = 0x08;
    /// CreateFile : Open file for read
    protected const uint GENERIC_READ = 0x80000000;
    /// CreateFile : Open file for write
    protected const uint GENERIC_WRITE = 0x40000000;
    /// CreateFile : file share for write
    protected const uint FILE_SHARE_WRITE = 0x2;
    /// CreateFile : file share for read
    protected const uint FILE_SHARE_READ = 0x1;
    /// CreateFile : Open handle for overlapped operations
    protected const uint FILE_FLAG_OVERLAPPED = 0x40000000;
    /// CreateFile : Resource to be "created" must exist
    protected const uint CREATE_NEW = 1;
    protected const uint CREATE_ALWAYS = 2;
    protected const uint OPEN_EXISTING = 3;
    /// CreateFile : Resource will be "created" or existing will be used
    protected const uint OPEN_ALWAYS = 4;
    /// ReadFile/WriteFile : Overlapped operation is incomplete.
    protected const uint ERROR_IO_PENDING = 997;
    /// Infinite timeout
    protected const uint INFINITE = 0xFFFFFFFF;
    /// Simple representation of a null handle : a closed stream will get this handle. Note it is public for comparison by higher level classes.
    public static IntPtr NullHandle = IntPtr.Zero;
    /// Simple representation of the handle returned when CreateFile fails.
    protected static IntPtr InvalidHandleValue = new IntPtr(-1);
    #endregion

    #region P/Invoke
    /// 
    /// Gets the GUID that Windows uses to represent HID class devices
    /// 
    /// An out parameter to take the Guid
    [DllImport("hid.dll", SetLastError = true)]
    protected static extern void HidD_GetHidGuid(out Guid gHid);
    /// 
    /// Allocates an InfoSet memory block within Windows that contains details of devices.
    /// 
    /// Class guid (e.g. HID guid)
    /// Not used
    /// Not used
    /// Type of device details required (DIGCF_ constants)
    /// A reference to the InfoSet
    [DllImport("setupapi.dll", SetLastError = true)]
    protected static extern IntPtr SetupDiGetClassDevs(ref Guid gClass, [MarshalAs(UnmanagedType.LPStr)] string strEnumerator, IntPtr hParent, uint nFlags);
    /// 
    /// Frees InfoSet allocated in call to above.
    /// 
    /// Reference to InfoSet
    /// true if successful
    [DllImport("setupapi.dll", SetLastError = true)]
    protected static extern int SetupDiDestroyDeviceInfoList(IntPtr lpInfoSet);
    /// 
    /// Gets the DeviceInterfaceData for a device from an InfoSet.
    /// 
    /// InfoSet to access
    /// Not used
    /// Device class guid
    /// Index into InfoSet for device
    /// DeviceInterfaceData to fill with data
    /// True if successful, false if not (e.g. when index is passed end of InfoSet)
    [DllImport("setupapi.dll", SetLastError = true)]
    protected static extern bool SetupDiEnumDeviceInterfaces(IntPtr lpDeviceInfoSet, uint nDeviceInfoData, ref Guid gClass, uint nIndex, ref DeviceInterfaceData oInterfaceData);
    /// 
    /// SetupDiGetDeviceInterfaceDetail
    /// Gets the interface detail from a DeviceInterfaceData. This is pretty much the device path.
    /// You call this twice, once to get the size of the struct you need to send (nDeviceInterfaceDetailDataSize=0)
    /// and once again when you've allocated the required space.
    /// 
    /// InfoSet to access
    /// DeviceInterfaceData to use
    /// DeviceInterfaceDetailData to fill with data
    /// The size of the above
    /// The required size of the above when above is set as zero
    /// Not used
    /// 
    [DllImport("setupapi.dll", SetLastError = true)]
    protected static extern bool SetupDiGetDeviceInterfaceDetail(IntPtr lpDeviceInfoSet, ref DeviceInterfaceData oInterfaceData, IntPtr lpDeviceInterfaceDetailData, uint nDeviceInterfaceDetailDataSize, ref uint nRequiredSize, IntPtr lpDeviceInfoData);
    /// 
    /// SetupDiGetDeviceInterfaceDetail
    /// Gets the interface detail from a DeviceInterfaceData. This is pretty much the device path.
    /// You call this twice, once to get the size of the struct you need to send (nDeviceInterfaceDetailDataSize=0)
    /// and once again when you've allocated the required space.
    /// 
    /// InfoSet to access
    /// DeviceInterfaceData to use
    /// DeviceInterfaceDetailData to fill with data
    /// The size of the above
    /// The required size of the above when above is set as zero
    /// Not used
    /// 
    [DllImport("setupapi.dll", SetLastError = true)]
    protected static extern bool SetupDiGetDeviceInterfaceDetail(IntPtr lpDeviceInfoSet, ref DeviceInterfaceData oInterfaceData, ref DeviceInterfaceDetailData oDetailData, uint nDeviceInterfaceDetailDataSize, ref uint nRequiredSize, IntPtr lpDeviceInfoData);
    /// 
    /// Registers a window for device insert/remove messages
    /// 
    /// Handle to the window that will receive the messages
    /// DeviceBroadcastInterrface structure
    /// set to DEVICE_NOTIFY_WINDOW_HANDLE
    /// A handle used when unregistering
    [DllImport("user32.dll", SetLastError = true)]
    protected static extern IntPtr RegisterDeviceNotification(IntPtr hwnd, DeviceBroadcastInterface oInterface, uint nFlags);
    /// 
    /// Unregister from above.
    /// 
    /// Handle returned in call to RegisterDeviceNotification
    /// True if success
    [DllImport("user32.dll", SetLastError = true)]
    protected static extern bool UnregisterDeviceNotification(IntPtr hHandle);
    /// 
    /// Gets details from an open device. Reserves a block of memory which must be freed.
    /// 
    /// Device file handle
    /// Reference to the preparsed data block
    /// 
    [DllImport("hid.dll", SetLastError = true)]
    protected static extern bool HidD_GetPreparsedData(IntPtr hFile, out IntPtr lpData);
    /// 
    /// Frees the memory block reserved above.
    /// 
    /// Reference to preparsed data returned in call to GetPreparsedData
    /// 
    [DllImport("hid.dll", SetLastError = true)]
    protected static extern bool HidD_FreePreparsedData(ref IntPtr pData);
    /// 
    /// Gets a device's capabilities from the preparsed data.
    /// 
    /// Preparsed data reference
    /// HidCaps structure to receive the capabilities
    /// True if successful
    [DllImport("hid.dll", SetLastError = true)]
    protected static extern int HidP_GetCaps(IntPtr lpData, out HidCaps oCaps);
    /// 
    /// Creates/opens a file, serial port, USB device... etc
    /// 
    /// Path to object to open
    /// Access mode. e.g. Read, write
    /// Sharing mode
    /// Security details (can be null)
    /// Specifies if the file is created or opened
    /// Any extra attributes? e.g. open overlapped
    /// Not used
    /// 
    [DllImport("kernel32.dll", SetLastError = true)]
    protected static extern IntPtr CreateFile([MarshalAs(UnmanagedType.LPStr)] string strName, uint nAccess, uint nShareMode, IntPtr lpSecurity, uint nCreationFlags, uint nAttributes, IntPtr lpTemplate);
    /// 
    /// Closes a window handle. File handles, event handles, mutex handles... etc
    /// 
    /// Handle to close
    /// True if successful.
    [DllImport("kernel32.dll", SetLastError = true)]
    protected static extern int CloseHandle(IntPtr hFile);

    [Serializable,StructLayout(LayoutKind.Sequential,CharSet = CharSet.Auto),BestFitMapping(false)]
    public struct WIN32_FIND_DATA
    {
        public IntPtr dwFileAttributes;
        public int ftCreationTime_dwLowDateTime;
        public int ftCreationTime_dwHighDateTime;
        public int ftLastAccessTime_dwLowDateTime;
        public int ftLastAccessTime_dwHighDateTime;
        public int ftLastWriteTime_dwLowDateTime;
        public int ftLastWriteTime_dwHighDateTime;
        public int nFileSizeHigh;
        public int nFileSizeLow;
        public IntPtr dwReserved0;
        public IntPtr dwReserved1;
        [MarshalAs(UnmanagedType.ByValTStr,SizeConst = 260)]
        public string cFileName;
        [MarshalAs(UnmanagedType.ByValTStr,SizeConst = 14)]
        public string cAlternateFileName;
    }
    [DllImport("kernel32.dll", CharSet = CharSet.Auto,
    SetLastError = true)]
    public static extern IntPtr FindFirstFile(string pFileName, ref WIN32_FIND_DATA pFindFileData);
    [DllImport("kernel32.dll",CharSet = CharSet.Auto,
    SetLastError = true)]
    public static extern bool FindNextFile(IntPtr hndFindFile, ref WIN32_FIND_DATA lpFindFileData);
    #endregion

    #region Public methods
    /// 
    /// Registers a window to receive windows messages when a device is inserted/removed. Need to call this
    /// from a form when its handle has been created, not in the form constructor. Use form's OnHandleCreated override.
    /// 
    /// Handle to window that will receive messages
    /// Class of devices to get messages for
    /// A handle used when unregistering
    public static IntPtr RegisterForUsbEvents(IntPtr hWnd, Guid gClass)
    {
        DeviceBroadcastInterface oInterfaceIn = new DeviceBroadcastInterface();
        oInterfaceIn.Size = Marshal.SizeOf(oInterfaceIn);
        oInterfaceIn.ClassGuid = gClass;
        oInterfaceIn.DeviceType = DEVTYP_DEVICEINTERFACE;
        oInterfaceIn.Reserved = 0;
        return RegisterDeviceNotification(hWnd, oInterfaceIn, DEVICE_NOTIFY_WINDOW_HANDLE);
    }
    /// 
    /// Unregisters notifications. Can be used in form dispose
    /// 
    /// Handle returned from RegisterForUSBEvents
    /// True if successful
    public static bool UnregisterForUsbEvents(IntPtr hHandle)
    {
        return UnregisterDeviceNotification(hHandle);
    }
    /// 
    /// Helper to get the HID guid.
    /// 
    public static Guid HIDGuid
    {
        get
        {
            Guid gHid;
            HidD_GetHidGuid(out gHid);
            return gHid;
        }
    }
    #endregion
}

}
usb在windows 系统里归结为了人体输入设备,那么它就有Vid(厂商号),Pid(产品号),所以在使用的时候必须的知道这个usb 的Vid和Pid,以下是usb的使用小案例:
示例代码下载地址:
https://github.com/myth158/usb.git

你可能感兴趣的:(C#,windowsAPI)