C#:USB设备枚举(二)设备枚举API
2011-10-30 08:45
1491 查看
/* ---------------------------------------------------------- 文件名称:WDKUsbEnum.cs 作者:秦建辉 MSN:splashcn@msn.com QQ:36748897 博客:http://blog.csdn.net/jhqin 开发环境: Visual Studio V2010 .NET Framework 4 Client Profile 版本历史: V1.0 2011年10月10日 基于WDK枚举USB设备 ------------------------------------------------------------ */ using System; using System.Collections.Generic; using System.Management; using System.Runtime.InteropServices; using System.Text; namespace Splash.IO.PORTS { /// <summary> /// USB主控制器信息 /// </summary> public struct HostControllerInfo { public String PNPDeviceID; // 设备ID public String Name; // 设备名称 } /// <summary> /// USB Hub信息 /// </summary> public struct UsbHubInfo { public String PNPDeviceID; // 设备ID public String Name; // 设备名称 public String Status; // 设备状态 } /// <summary> /// USB HUB节点信息 /// </summary> public struct UsbNodeInformation { public String DevicePath; // 设备路径 public String PNPDeviceID; // 设备ID public String Name; // 设备名称 public USB_HUB_NODE NodeType; // 节点类型 // USB_HUB_INFORMATION public Boolean HubIsBusPowered; // 供电方式:true-总线供电 false-独立供电 public Int32 NumberOfPorts; // 端口数 public Int16 HubCharacteristics; // 特征描述 public Byte PowerOnToPowerGood; // 从端口加电到端口正常工作的时间间隔(以2ms为单位) public Byte HubControlCurrent; // 设备所需最大电流 // USB_MI_PARENT_INFORMATION public Int32 NumberOfInterfaces; // 接口数 } /// <summary> /// USB设备描述符 /// </summary> public struct UsbDeviceDescriptor { public Byte bDescriptorType; // 描述符类型 USB_DEVICE_DESCRIPTOR_TYPE public String UsbVersion; // USB规格版本号 public Byte bDeviceClass; // 设备类型 public Byte bDeviceSubClass; // 设备子类型 public Byte bDeviceProtocol; // 设备协议 public Byte bMaxPacketSize0; // 最大封包大小 public UInt16 idVendor; // VID public UInt16 idProduct; // PID public String DeviceVersion; // 设备版本号 public String Manufacturer; // 制造商 public String Product; // 产品描述 public String SerialNumber; // 序列号 public Byte bNumConfigurations; // 配置总数 } /// <summary> /// USB管道信息 /// </summary> public struct UsbPipeInfo { public UInt32 ScheduleOffset; public Byte bDescriptorType; public Byte bEndpointAddress; public Byte bmAttributes; public UInt16 wMaxPacketSize; public Byte bInterval; } /// <summary> /// USB节点连接信息 /// </summary> public struct UsbNodeConnectionInformation { public String DevicePath; // 设备路径 public Int32 ConnectionIndex; // 端口号 public UsbDeviceDescriptor DeviceDescriptor; public Byte CurrentConfigurationValue; // 当前设备配置 public Byte Speed; // 设备速度 public Boolean DeviceIsHub; // 是否是集线器 public Int32 DeviceAddress; // 设备地址 public Int32 NumberOfOpenPipes; // 管道数 public USB_CONNECTION_STATUS ConnectionStatus; // 连接状态 public List<UsbPipeInfo> PipeList; // 管道信息 } /// <summary> /// USB设备枚举 /// </summary> public partial class USB { #region HostController /// <summary> /// USB主控制器 /// </summary> public static HostControllerInfo[] AllHostControllers { get { List<HostControllerInfo> HostControllers = new List<HostControllerInfo>(); // 获取USB控制器及其相关联的设备实体 ManagementObjectCollection MOC = new ManagementObjectSearcher("SELECT * FROM Win32_USBController").Get(); if (MOC != null) { foreach (ManagementObject MO in MOC) { HostControllerInfo Element; Element.PNPDeviceID = MO["PNPDeviceID"] as String; // 设备ID Element.Name = MO["Name"] as String; // 设备描述 HostControllers.Add(Element); } } if (HostControllers.Count == 0) return null; else return HostControllers.ToArray(); } } /// <summary> /// 获取驱动键名 /// </summary> /// <param name="PNPDeviceID">USB主控制器设备ID</param> /// <returns>获取设备驱动在注册表HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Class下的路径</returns> public static String GetHcdDriverKeyName(String PNPDeviceID) { if (String.IsNullOrEmpty(PNPDeviceID)) return null; // 打开设备 IntPtr hHCDev = Kernel32.CreateFile( "\\\\.\\" + PNPDeviceID.Replace('\\', '#') + "#{3ABF6F2D-71C4-462A-8A92-1E6861E6AF27}", NativeFileAccess.GENERIC_WRITE, NativeFileShare.FILE_SHARE_WRITE, IntPtr.Zero, NativeFileMode.OPEN_EXISTING, IntPtr.Zero, IntPtr.Zero); if (hHCDev == Kernel32.INVALID_HANDLE_VALUE) return null; // 获取驱动键名 Int32 nBytesReturned; USB_HCD_DRIVERKEY_NAME Buffer = new USB_HCD_DRIVERKEY_NAME(); Boolean Status = DeviceIoControl(hHCDev, IOCTL_GET_HCD_DRIVERKEY_NAME, IntPtr.Zero, 0, ref Buffer, Marshal.SizeOf(Buffer), out nBytesReturned, IntPtr.Zero); // 关闭设备 Kernel32.CloseHandle(hHCDev); return Status ? Buffer.Name : null; } #endregion #region USBHUB /// <summary> /// USB Hub信息集合 /// </summary> public static UsbHubInfo[] AllUsbHubs { get { List<UsbHubInfo> UsbHubs = new List<UsbHubInfo>(); // 获取USB控制器及其相关联的设备实体 ManagementObjectCollection MOC = new ManagementObjectSearcher("SELECT * FROM Win32_USBHub").Get(); if (MOC != null) { foreach (ManagementObject MO in MOC) { UsbHubInfo Element; Element.PNPDeviceID = MO["PNPDeviceID"] as String; // 设备ID Element.Name = MO["Name"] as String; // 设备描述 Element.Status = MO["Status"] as String; // 设备状态 UsbHubs.Add(Element); } } if (UsbHubs.Count == 0) return null; else return UsbHubs.ToArray(); } } /// <summary> /// USB ROOT HUB设备路径 /// </summary> /// <param name="PNPDeviceID">USB主控制器设备ID</param> /// <returns>USB ROOT HUB设备路径</returns> public static String GetUsbRootHubPath(String PNPDeviceID) { if (String.IsNullOrEmpty(PNPDeviceID)) return null; // 打开设备 IntPtr hHCDev = Kernel32.CreateFile( "\\\\.\\" + PNPDeviceID.Replace('\\', '#') + "#{3ABF6F2D-71C4-462A-8A92-1E6861E6AF27}", NativeFileAccess.GENERIC_WRITE, NativeFileShare.FILE_SHARE_WRITE, IntPtr.Zero, NativeFileMode.OPEN_EXISTING, IntPtr.Zero, IntPtr.Zero); if (hHCDev == Kernel32.INVALID_HANDLE_VALUE) return null; // 获取USB ROOT HUB名称 Int32 nBytesReturned; USB_HCD_DRIVERKEY_NAME Buffer = new USB_HCD_DRIVERKEY_NAME(); Boolean Status = DeviceIoControl(hHCDev, IOCTL_USB_GET_ROOT_HUB_NAME, IntPtr.Zero, 0, ref Buffer, Marshal.SizeOf(Buffer), out nBytesReturned, IntPtr.Zero); // 关闭设备 Kernel32.CloseHandle(hHCDev); return Status ? Buffer.Name : null; } /// <summary> /// USB HUB设备名称 /// </summary> /// <param name="DevicePath">设备路径</param> /// <returns>设备名称</returns> public static String GetUsbHubName(String DevicePath) { if (String.IsNullOrEmpty(DevicePath)) return null; // 从设备路径中提取设备ID String DeviceID = DevicePath.Substring(0, DevicePath.LastIndexOf('#')).Replace('#', '_'); // 从Win32_USBHub获取设备描述 ManagementObjectCollection MOC = new ManagementObjectSearcher("SELECT * FROM Win32_USBHub WHERE DeviceID LIKE '" + DeviceID + "'").Get(); if (MOC != null) { foreach (ManagementObject MO in MOC) { return MO["Name"] as String; } } return null; } /// <summary> /// 获取USB HUB节点信息 /// </summary> /// <param name="DevicePath">USB HUB设备路径</param> /// <returns>节点信息</returns> public static UsbNodeInformation[] GetUsbNodeInformation(String DevicePath) { if (String.IsNullOrEmpty(DevicePath)) return null; // 打开设备文件 IntPtr hHubDevice = Kernel32.CreateFile( "\\\\.\\" + DevicePath, NativeFileAccess.GENERIC_WRITE, NativeFileShare.FILE_SHARE_WRITE, IntPtr.Zero, NativeFileMode.OPEN_EXISTING, IntPtr.Zero, IntPtr.Zero); if (hHubDevice == Kernel32.INVALID_HANDLE_VALUE) return null; // 查询节点信息 Int32 nBytesReturned; USB_NODE_INFORMATION Buffer = new USB_NODE_INFORMATION(); Boolean Status = DeviceIoControl(hHubDevice, IOCTL_USB_GET_NODE_INFORMATION, ref Buffer, Marshal.SizeOf(Buffer), ref Buffer, Marshal.SizeOf(Buffer), out nBytesReturned, IntPtr.Zero); // 关闭设备文件 Kernel32.CloseHandle(hHubDevice); if (!Status) return null; UsbNodeInformation Node = new UsbNodeInformation(); Node.NodeType = Buffer.NodeType; // 节点类型 Node.PNPDeviceID = DevicePath.Substring(0, DevicePath.LastIndexOf('#')).Replace('#', '\\'); // 设备ID Node.DevicePath = DevicePath; // 设备路径 Node.Name = GetUsbHubName(DevicePath); // 设备名称 if (Buffer.NodeType == USB_HUB_NODE.UsbHub) { Node.NumberOfPorts = Buffer.u.HubInformation.HubDescriptor.bNumberOfPorts; // 端口数 Node.HubIsBusPowered = Convert.ToBoolean(Buffer.u.HubInformation.HubIsBusPowered); // 供电方式 Node.HubCharacteristics = Buffer.u.HubInformation.HubDescriptor.wHubCharacteristics; Node.PowerOnToPowerGood = Buffer.u.HubInformation.HubDescriptor.bPowerOnToPowerGood; Node.HubControlCurrent = Buffer.u.HubInformation.HubDescriptor.bHubControlCurrent; } else { Node.NumberOfInterfaces = Buffer.u.MiParentInformation.NumberOfInterfaces; // 接口数 } return new UsbNodeInformation[1] { Node }; } #endregion #region NODECONNECTION /// <summary> /// 获取USB节点连接信息 /// </summary> /// <param name="DevicePath">设备路径</param> /// <param name="NumberOfPorts">端口总数</param> /// <returns>USB节点信息连接信息集合</returns> public static UsbNodeConnectionInformation[] GetUsbNodeConnectionInformation(String DevicePath, Int32 NumberOfPorts) { if (String.IsNullOrEmpty(DevicePath)) return null; // 打开设备文件 IntPtr hHubDevice = Kernel32.CreateFile( "\\\\.\\" + DevicePath, NativeFileAccess.GENERIC_WRITE, NativeFileShare.FILE_SHARE_WRITE, IntPtr.Zero, NativeFileMode.OPEN_EXISTING, IntPtr.Zero, IntPtr.Zero); if (hHubDevice == Kernel32.INVALID_HANDLE_VALUE) return null; List<UsbNodeConnectionInformation> NodeCollection = new List<UsbNodeConnectionInformation>(); // 枚举端口 USB_NODE_CONNECTION_INFORMATION_EX Buffer = new USB_NODE_CONNECTION_INFORMATION_EX(); for (Int32 ConnectionIndex = 1; ConnectionIndex <= NumberOfPorts; ConnectionIndex++) { // 查询节点信息 Int32 nBytesReturned; Buffer.ConnectionIndex = ConnectionIndex; Boolean Status = DeviceIoControl(hHubDevice, IOCTL_USB_GET_NODE_CONNECTION_INFORMATION_EX, ref Buffer, Marshal.SizeOf(Buffer), ref Buffer, Marshal.SizeOf(Buffer), out nBytesReturned, IntPtr.Zero); if (Status) { // 确定语言ID UInt16 LanguageID = SelectLanguageID(hHubDevice, ConnectionIndex); // 提取信息 UsbNodeConnectionInformation Node = new UsbNodeConnectionInformation(); Node.DevicePath = DevicePath; Node.ConnectionIndex = Buffer.ConnectionIndex; Node.ConnectionStatus = Buffer.ConnectionStatus; if (Buffer.ConnectionStatus == USB_CONNECTION_STATUS.DeviceConnected) { Node.CurrentConfigurationValue = Buffer.CurrentConfigurationValue; Node.Speed = Buffer.Speed; Node.DeviceIsHub = Convert.ToBoolean(Buffer.DeviceIsHub); Node.DeviceAddress = Buffer.DeviceAddress; Node.NumberOfOpenPipes = Buffer.NumberOfOpenPipes; // 设备描述符 Node.DeviceDescriptor.bDescriptorType = Buffer.DeviceDescriptor.bDescriptorType; Node.DeviceDescriptor.bDeviceClass = Buffer.DeviceDescriptor.bDeviceClass; Node.DeviceDescriptor.bDeviceSubClass = Buffer.DeviceDescriptor.bDeviceSubClass; Node.DeviceDescriptor.bDeviceProtocol = Buffer.DeviceDescriptor.bDeviceProtocol; Node.DeviceDescriptor.UsbVersion = BcdVersionToString(Buffer.DeviceDescriptor.bcdUSB); // USB版本号 Node.DeviceDescriptor.DeviceVersion = BcdVersionToString(Buffer.DeviceDescriptor.bcdDevice); // 设备版本号 Node.DeviceDescriptor.idVendor = Buffer.DeviceDescriptor.idVendor; // 厂商标识 Node.DeviceDescriptor.idProduct = Buffer.DeviceDescriptor.idProduct; // 产品标识 if (LanguageID != 0) { if (Buffer.DeviceDescriptor.iSerialNumber != 0) { // 序列号 Node.DeviceDescriptor.SerialNumber = GetStringDescriptor(hHubDevice, Buffer.ConnectionIndex, Buffer.DeviceDescriptor.iSerialNumber, LanguageID); } if (Buffer.DeviceDescriptor.iManufacturer != 0) { // 制造商名称 Node.DeviceDescriptor.Manufacturer = GetStringDescriptor(hHubDevice, Buffer.ConnectionIndex, Buffer.DeviceDescriptor.iManufacturer, LanguageID); } if (Buffer.DeviceDescriptor.iProduct != 0) { // 产品名称 Node.DeviceDescriptor.Product = GetStringDescriptor(hHubDevice, Buffer.ConnectionIndex, Buffer.DeviceDescriptor.iProduct, LanguageID); } } Node.DeviceDescriptor.bMaxPacketSize0 = Buffer.DeviceDescriptor.bMaxPacketSize0; Node.DeviceDescriptor.bNumConfigurations = Buffer.DeviceDescriptor.bNumConfigurations; // 管道信息 Node.PipeList = new List<UsbPipeInfo>(); for (Int32 PipeIndex = 0; PipeIndex < Buffer.NumberOfOpenPipes; PipeIndex++) { UsbPipeInfo PipeInfo; PipeInfo.ScheduleOffset = Buffer.PipeList[PipeIndex].ScheduleOffset; PipeInfo.bDescriptorType = Buffer.PipeList[PipeIndex].EndpointDescriptor.bDescriptorType; PipeInfo.bEndpointAddress = Buffer.PipeList[PipeIndex].EndpointDescriptor.bEndpointAddress; PipeInfo.bmAttributes = Buffer.PipeList[PipeIndex].EndpointDescriptor.bmAttributes; PipeInfo.wMaxPacketSize = Buffer.PipeList[PipeIndex].EndpointDescriptor.wMaxPacketSize; PipeInfo.bInterval = Buffer.PipeList[PipeIndex].EndpointDescriptor.bInterval; Node.PipeList.Add(PipeInfo); } } NodeCollection.Add(Node); } } // 关闭设备文件 Kernel32.CloseHandle(hHubDevice); // 返回结果 if (NodeCollection.Count == 0) return null; else return NodeCollection.ToArray(); } /// <summary> /// 获取字符串描述符 /// </summary> /// <param name="hHubDevice">USB Hub设备句柄</param> /// <param name="ConnectionIndex">连接索引号</param> /// <param name="DescriptorIndex">描述符索引号</param> /// <param name="LanguageID">语言ID</param> /// <returns>字符串描述符</returns> public static String GetStringDescriptor(IntPtr hHubDevice, Int32 ConnectionIndex, Byte DescriptorIndex, UInt16 LanguageID) { USB_DESCRIPTOR_REQUEST Buffer = new USB_DESCRIPTOR_REQUEST(); Buffer.ConnectionIndex = ConnectionIndex; Buffer.SetupPacket.wValue = (UInt16)((USB_STRING_DESCRIPTOR_TYPE << 8) | DescriptorIndex); Buffer.SetupPacket.wIndex = LanguageID; Buffer.SetupPacket.wLength = MAXIMUM_USB_STRING_LENGTH; Int32 nBytesReturned; Boolean Status = DeviceIoControl(hHubDevice, IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION, ref Buffer, Marshal.SizeOf(Buffer), ref Buffer, Marshal.SizeOf(Buffer), out nBytesReturned, IntPtr.Zero); if (Status) return Buffer.Data.bString; else return null; } /// <summary> /// 选择语言ID /// </summary> /// <param name="hHubDevice">USB Hub设备句柄</param> /// <param name="ConnectionIndex">连接索引号</param> /// <returns></returns> public static UInt16 SelectLanguageID(IntPtr hHubDevice, Int32 ConnectionIndex) { // 获取支持的语言列表 String SupportedLanguagesString = GetStringDescriptor(hHubDevice, ConnectionIndex, 0, 0); if(String.IsNullOrEmpty(SupportedLanguagesString))return 0; UInt16 UserDefaultUILanguage = Splash.Environment.UserDefaultUILanguage; if(SupportedLanguagesString.IndexOf(Convert.ToChar(UserDefaultUILanguage)) != -1) { // 用户缺省界面语言 return UserDefaultUILanguage; } else if(SupportedLanguagesString.IndexOf(Convert.ToChar(0x0409)) != -1) { // 美国英语 0x0409 return 0x0409; } else { // 第一个可选择的LANGID return Convert.ToUInt16(SupportedLanguagesString[0]); } } #endregion #region EXTERNALHUB /// <summary> /// 获取外接Hub设备路径 /// </summary> /// <param name="ParentDevicePath">上层Hub设备路径</param> /// <param name="ConnectionIndex">连接索引号</param> /// <returns>外接Hub设备路径</returns> public static String GetExternalHubPath(String ParentDevicePath, Int32 ConnectionIndex) { if (String.IsNullOrEmpty(ParentDevicePath)) return null; // 打开设备文件 IntPtr hParentHubDevice = Kernel32.CreateFile( "\\\\.\\" + ParentDevicePath, NativeFileAccess.GENERIC_WRITE, NativeFileShare.FILE_SHARE_WRITE, IntPtr.Zero, NativeFileMode.OPEN_EXISTING, IntPtr.Zero, IntPtr.Zero); if (hParentHubDevice == Kernel32.INVALID_HANDLE_VALUE) return null; USB_NODE_CONNECTION_DRIVERKEY_NAME Buffer = new USB_NODE_CONNECTION_DRIVERKEY_NAME(); Buffer.ConnectionIndex = ConnectionIndex; Int32 nBytesReturned; Boolean Status = DeviceIoControl(hParentHubDevice, IOCTL_USB_GET_NODE_CONNECTION_NAME, ref Buffer, Marshal.SizeOf(Buffer), ref Buffer, Marshal.SizeOf(Buffer), out nBytesReturned, IntPtr.Zero); // 关闭设备文件 Kernel32.CloseHandle(hParentHubDevice); if (Status) return Buffer.DriverKeyName; else return null; } /// <summary> /// 获取外接Hub设备路径 /// </summary> /// <param name="hParentHubDevice">上层Hub设备句柄</param> /// <param name="ConnectionIndex">连接索引号</param> /// <returns>外接Hub设备路径</returns> public static String GetExternalHubPath(IntPtr hParentHubDevice, Int32 ConnectionIndex) { if (hParentHubDevice == IntPtr.Zero || ConnectionIndex <= 0) return null; USB_NODE_CONNECTION_DRIVERKEY_NAME Buffer = new USB_NODE_CONNECTION_DRIVERKEY_NAME(); Buffer.ConnectionIndex = ConnectionIndex; Int32 nBytesReturned; Boolean Status = DeviceIoControl(hParentHubDevice, IOCTL_USB_GET_NODE_CONNECTION_NAME, ref Buffer, Marshal.SizeOf(Buffer), ref Buffer, Marshal.SizeOf(Buffer), out nBytesReturned, IntPtr.Zero); if (Status) return Buffer.DriverKeyName; else return null; } #endregion #region BCDVERSION /// <summary> /// 版本BCD编码转字符串 /// </summary> /// <param name="bcd">版本BCD编码</param> /// <returns>版本字符串</returns> private static String BcdVersionToString(UInt16 bcd) { StringBuilder sb = new StringBuilder(5); // 主版本号 Int32 BIT4 = (bcd >> 12) & 0x0F; if (BIT4 != 0) sb.Append(BIT4.ToString()); BIT4 = (bcd >> 8) & 0x0F; sb.Append(BIT4.ToString()); sb.Append("."); // 子版本号 BIT4 = (bcd >> 4) & 0x0F; sb.Append(BIT4.ToString()); BIT4 = bcd & 0x0F; if (BIT4 != 0) sb.Append(BIT4.ToString()); return sb.ToString(); } #endregion } }
相关文章推荐
- C#:USB设备枚举(二)设备枚举API
- C#:USB设备枚举(八)创建基于WPF的USB设备浏览器
- C#:USB设备枚举(一)DeviceIoControl的PInvoke
- C#:USB设备枚举(四)Kernel32的PInvoke
- C#:USB设备枚举(七)WPF扩展方法
- C#:USB设备枚举(八)创建基于WPF的USB设备浏览器
- C#USB设备枚举Kernel32的PInvoke
- C#:USB设备枚举(一)DeviceIoControl的PInvoke
- C#:USB设备枚举(五)生成TreeView数据源
- C#:USB设备枚举(三)输出枚举信息到XML文档
- C#:USB设备枚举(六)生成ListView数据源
- C#:USB设备枚举(七)WPF扩展方法
- C#:USB设备枚举(六)生成ListView数据源
- C#:USB设备枚举(五)生成TreeView数据源
- C#:USB设备枚举(四)Kernel32的PInvoke
- C#:USB设备枚举(三)输出枚举信息到XML文档
- 检测 USB 设备拨插的 C# 类库:USBClassLibrary
- 浅析usb转serial串口设备在linux内核中枚举创建及生成tty设备的全过程
- 浅析usb转serial串口设备在linux内核中枚举创建及生成tty设备的全过程
- C# WPD PortableDeviceApiLib获取便携设备列表