网上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