Mercurial > hg > ucis.core
comparison USBLib/Windows/USB/UsbDevice.cs @ 21:dcfec2be27c9
Added USBLib
author | Ivo Smits <Ivo@UCIS.nl> |
---|---|
date | Mon, 15 Apr 2013 01:04:59 +0200 |
parents | |
children | 5b14fed54a89 |
comparison
equal
deleted
inserted
replaced
20:c873e3dd73fe | 21:dcfec2be27c9 |
---|---|
1 using System; | |
2 using System.Collections.Generic; | |
3 using System.Collections.ObjectModel; | |
4 using System.Runtime.InteropServices; | |
5 using System.Text; | |
6 using Microsoft.Win32.SafeHandles; | |
7 using UCIS.USBLib.Internal.Windows; | |
8 using UCIS.HWLib.Windows.Devices; | |
9 | |
10 namespace UCIS.HWLib.Windows.USB { | |
11 public class UsbDevice { | |
12 public UsbDevice Parent { get; protected set; } | |
13 internal USB_NODE_CONNECTION_INFORMATION_EX NodeConnectionInfo { get; set; } | |
14 internal USB_DEVICE_DESCRIPTOR DeviceDescriptor { get; private set; } | |
15 internal IList<USB_CONFIGURATION_DESCRIPTOR> ConfigurationDescriptor { get; private set; } | |
16 internal IList<USB_INTERFACE_DESCRIPTOR> InterfaceDescriptor { get; private set; } | |
17 internal IList<USB_ENDPOINT_DESCRIPTOR> EndpointDescriptor { get; private set; } | |
18 internal IList<HID_DESCRIPTOR> HdiDescriptor { get; private set; } | |
19 public string DevicePath { get; private set; } | |
20 public uint AdapterNumber { get; internal set; } | |
21 public string DriverKey { get; private set; } | |
22 | |
23 public virtual string DeviceDescription { get { return DeviceNode.GetPropertyString(CMRDP.DEVICEDESC); } } | |
24 public string DeviceID { get { return DeviceNode.DeviceID; } } | |
25 | |
26 public bool IsConnected { get; internal set; } | |
27 public bool IsHub { get; internal set; } | |
28 public string Status { get; internal set; } | |
29 public string Speed { get; internal set; } | |
30 | |
31 public string Manufacturer { get; private set; } | |
32 public string SerialNumber { get; private set; } | |
33 public string Product { get; private set; } | |
34 | |
35 public int VendorID { get { return DeviceDescriptor.idVendor; } } | |
36 public int ProductID { get { return DeviceDescriptor.idProduct; } } | |
37 | |
38 private DeviceNode mDeviceNode; | |
39 public DeviceNode DeviceNode { | |
40 get { | |
41 if (mDeviceNode == null && DriverKey != null) { | |
42 foreach (DeviceNode node in DeviceNode.GetDevices("USB")) { | |
43 if (DriverKey.Equals(node.DriverKey, StringComparison.InvariantCultureIgnoreCase)) { | |
44 mDeviceNode = node; | |
45 break; | |
46 } | |
47 } | |
48 } | |
49 return mDeviceNode; | |
50 } | |
51 } | |
52 | |
53 internal UsbDevice(UsbDevice parent, USB_DEVICE_DESCRIPTOR deviceDescriptor, uint adapterNumber) | |
54 : this(parent, deviceDescriptor, adapterNumber, null) { } | |
55 unsafe internal UsbDevice(UsbDevice parent, USB_DEVICE_DESCRIPTOR deviceDescriptor, uint adapterNumber, string devicePath) { | |
56 this.Parent = parent; | |
57 this.AdapterNumber = adapterNumber; | |
58 this.DeviceDescriptor = deviceDescriptor; | |
59 this.DevicePath = devicePath; | |
60 ConfigurationDescriptor = new List<USB_CONFIGURATION_DESCRIPTOR>(); | |
61 InterfaceDescriptor = new List<USB_INTERFACE_DESCRIPTOR>(); | |
62 HdiDescriptor = new List<HID_DESCRIPTOR>(); | |
63 EndpointDescriptor = new List<USB_ENDPOINT_DESCRIPTOR>(); | |
64 if (devicePath == null) return; | |
65 | |
66 using (SafeFileHandle handel = Kernel32.CreateFile(devicePath, Kernel32.GENERIC_WRITE, Kernel32.FILE_SHARE_WRITE, IntPtr.Zero, Kernel32.OPEN_EXISTING, 0, IntPtr.Zero)) { | |
67 if (handel.IsInvalid) throw new System.ComponentModel.Win32Exception(Marshal.GetLastWin32Error()); | |
68 int nBytesReturned; | |
69 int nBytes = UsbApi.MAX_BUFFER_SIZE; | |
70 | |
71 USB_DESCRIPTOR_REQUEST Request1 = new USB_DESCRIPTOR_REQUEST(); | |
72 Request1.ConnectionIndex = adapterNumber;// portCount; | |
73 Request1.SetupPacket.wValue = (ushort)((UsbApi.USB_CONFIGURATION_DESCRIPTOR_TYPE << 8)); | |
74 Request1.SetupPacket.wLength = (ushort)(nBytes - Marshal.SizeOf(Request1)); | |
75 Request1.SetupPacket.wIndex = 0; // 0x409; // Language Code | |
76 | |
77 // Use an IOCTL call to request the String Descriptor | |
78 Byte[] buffer = new Byte[nBytes]; | |
79 fixed (Byte* bufferptr = buffer) { | |
80 if (!Kernel32.DeviceIoControl(handel, UsbApi.IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION, ref Request1, Marshal.SizeOf(typeof(USB_DESCRIPTOR_REQUEST)), (IntPtr)bufferptr, nBytes, out nBytesReturned, IntPtr.Zero)) { | |
81 int err = Marshal.GetLastWin32Error(); | |
82 Console.WriteLine("IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION returned {0} {1}", err, (new System.ComponentModel.Win32Exception(err)).Message); | |
83 //SerialNumber = (new System.ComponentModel.Win32Exception(err)).Message; | |
84 if (err != 2 && err != 31 && err != 87) throw new System.ComponentModel.Win32Exception(err); | |
85 } else { | |
86 if (nBytesReturned > nBytes) throw new IndexOutOfRangeException("IOCtl returned too much data"); | |
87 if (nBytesReturned < 0) throw new IndexOutOfRangeException("IOCtl returned insufficient data"); | |
88 Byte* ptr = bufferptr + Marshal.SizeOf(Request1); | |
89 nBytesReturned -= Marshal.SizeOf(Request1); | |
90 if (nBytesReturned < 0) throw new IndexOutOfRangeException("IOCtl returned insufficient data"); | |
91 | |
92 int offset = 0; | |
93 while (offset < nBytesReturned) { | |
94 if (offset + Marshal.SizeOf(typeof(USB_DESCRIPTOR)) >= nBytesReturned) throw new IndexOutOfRangeException("Error in configuration descriptor"); | |
95 USB_DESCRIPTOR* desc = (USB_DESCRIPTOR*)(ptr + offset); | |
96 offset += desc->bLength; | |
97 if (offset > nBytesReturned) throw new IndexOutOfRangeException("Error in configuration descriptor"); | |
98 Console.WriteLine("Descriptor type {0} length {1}", desc->bDescriptorType, desc->bLength); | |
99 if (desc->bDescriptorType == USB_DESCRIPTOR_TYPE.ConfigurationDescriptorType) { | |
100 if (desc->bLength < 9) throw new IndexOutOfRangeException("Error in configuration descriptor"); | |
101 USB_CONFIGURATION_DESCRIPTOR configurationDescriptor = *(USB_CONFIGURATION_DESCRIPTOR*)desc; | |
102 ConfigurationDescriptor.Add(configurationDescriptor); | |
103 } else if (desc->bDescriptorType == USB_DESCRIPTOR_TYPE.InterfaceDescriptorType) { | |
104 if (desc->bLength < 9) throw new IndexOutOfRangeException("Error in configuration descriptor"); | |
105 USB_INTERFACE_DESCRIPTOR interfaceDescriptor = *(USB_INTERFACE_DESCRIPTOR*)desc; | |
106 InterfaceDescriptor.Add(interfaceDescriptor); | |
107 } else if (desc->bDescriptorType == USB_DESCRIPTOR_TYPE.EndpointDescriptorType) { | |
108 if (desc->bLength < 7) throw new IndexOutOfRangeException("Error in configuration descriptor"); | |
109 USB_ENDPOINT_DESCRIPTOR endpointDescriptor1 = *(USB_ENDPOINT_DESCRIPTOR*)desc; | |
110 EndpointDescriptor.Add(endpointDescriptor1); | |
111 } | |
112 } | |
113 } | |
114 // The iManufacturer, iProduct and iSerialNumber entries in the | |
115 // device descriptor are really just indexes. So, we have to | |
116 // request a string descriptor to get the values for those strings. | |
117 if (DeviceDescriptor != null) { | |
118 if (DeviceDescriptor.iManufacturer > 0) Manufacturer = GetStringDescriptor(handel, DeviceDescriptor.iManufacturer); | |
119 if (DeviceDescriptor.iProduct > 0) Product = GetStringDescriptor(handel, DeviceDescriptor.iProduct); | |
120 if (DeviceDescriptor.iSerialNumber > 0) SerialNumber = GetStringDescriptor(handel, DeviceDescriptor.iSerialNumber); | |
121 } | |
122 } | |
123 // Get the Driver Key Name (usefull in locating a device) | |
124 USB_NODE_CONNECTION_DRIVERKEY_NAME DriverKeyStruct = new USB_NODE_CONNECTION_DRIVERKEY_NAME(); | |
125 DriverKeyStruct.ConnectionIndex = adapterNumber; | |
126 // Use an IOCTL call to request the Driver Key Name | |
127 if (Kernel32.DeviceIoControl(handel, UsbApi.IOCTL_USB_GET_NODE_CONNECTION_DRIVERKEY_NAME, ref DriverKeyStruct, Marshal.SizeOf(DriverKeyStruct), out DriverKeyStruct, Marshal.SizeOf(DriverKeyStruct), out nBytesReturned, IntPtr.Zero)) { | |
128 DriverKey = DriverKeyStruct.DriverKeyName; | |
129 } | |
130 } | |
131 } | |
132 | |
133 private unsafe String GetStringDescriptor(SafeFileHandle handel, Byte id) { | |
134 int nBytes = UsbApi.MAX_BUFFER_SIZE; | |
135 int nBytesReturned = 0; | |
136 Byte[] buffer = new Byte[nBytes]; | |
137 fixed (Byte* bufferptr = buffer) { | |
138 // Build a request for string descriptor. | |
139 USB_DESCRIPTOR_REQUEST Request = new USB_DESCRIPTOR_REQUEST(); | |
140 Request.ConnectionIndex = AdapterNumber; | |
141 Request.SetupPacket.wValue = (ushort)((UsbApi.USB_STRING_DESCRIPTOR_TYPE << 8) + id); | |
142 Request.SetupPacket.wLength = (ushort)(nBytes - Marshal.SizeOf(Request)); | |
143 Request.SetupPacket.wIndex = 0x409; // The language code. | |
144 // Use an IOCTL call to request the string descriptor. | |
145 if (Kernel32.DeviceIoControl(handel, UsbApi.IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION, ref Request, Marshal.SizeOf(Request), (IntPtr)bufferptr, nBytes, out nBytesReturned, IntPtr.Zero)) { | |
146 if (nBytesReturned < nBytes) buffer[nBytesReturned] = 0; | |
147 if (nBytesReturned + 1 < nBytes) buffer[nBytesReturned + 1] = 0; | |
148 // The location of the string descriptor is immediately after | |
149 // the Request structure. Because this location is not "covered" | |
150 // by the structure allocation, we're forced to zero out this | |
151 // chunk of memory by using the StringToHGlobalAuto() hack above | |
152 //*(UsbApi.USB_STRING_DESCRIPTOR*)(bufferptr + Marshal.SizeOf(Request)); | |
153 USB_STRING_DESCRIPTOR StringDesc = (USB_STRING_DESCRIPTOR)Marshal.PtrToStructure((IntPtr)(bufferptr + Marshal.SizeOf(Request)), typeof(USB_STRING_DESCRIPTOR)); | |
154 //return StringDesc.bString; | |
155 int len = Math.Min(nBytesReturned - Marshal.SizeOf(Request) - 2, StringDesc.bLength); | |
156 return Encoding.Unicode.GetString(buffer, 2 + Marshal.SizeOf(Request), len); | |
157 } else { | |
158 return null; | |
159 } | |
160 } | |
161 } | |
162 | |
163 /*public static UsbDevice GetUsbDevice(DeviceNode node) { | |
164 String[] hubinterface = node.GetInterfaces(UsbApi.GUID_DEVINTERFACE_USB_HUB); | |
165 if (hubinterface != null && hubinterface.Length > 0) return new UsbHub(null, hubinterface[0], false); | |
166 String[] devinterface = node.GetInterfaces(UsbApi.GUID_DEVINTERFACE_USB_DEVICE); | |
167 if (devinterface == null || devinterface.Length == 0) throw new InvalidOperationException("Device is not an USB device"); | |
168 DeviceNode parent = node.GetParent(); | |
169 if (parent == null) throw new InvalidOperationException("Could not find parent hub device"); | |
170 UsbHub usbhub = GetUsbDevice(parent) as UsbHub; | |
171 if (usbhub == null) throw new InvalidOperationException("Could not find parent hub device"); | |
172 String driverkey = node.DriverKey; | |
173 foreach (UsbDevice usbdev in usbhub.Devices) { | |
174 if (driverkey.Equals(usbdev.DriverKey, StringComparison.InvariantCultureIgnoreCase)) return usbdev; | |
175 } | |
176 throw new InvalidOperationException("Could not find device on parent hub"); | |
177 //return null; | |
178 }*/ | |
179 } | |
180 } |