Mercurial > hg > ucis.core
comparison USBLib/Windows/Devices/DeviceNode.cs @ 21:dcfec2be27c9
Added USBLib
author | Ivo Smits <Ivo@UCIS.nl> |
---|---|
date | Mon, 15 Apr 2013 01:04:59 +0200 |
parents | |
children | 556b4fb511bd |
comparison
equal
deleted
inserted
replaced
20:c873e3dd73fe | 21:dcfec2be27c9 |
---|---|
1 using System; | |
2 using System.Collections.Generic; | |
3 using System.ComponentModel; | |
4 using System.Runtime.InteropServices; | |
5 using System.Text; | |
6 using Microsoft.Win32; | |
7 using UCIS.USBLib.Internal.Windows; | |
8 | |
9 namespace UCIS.HWLib.Windows.Devices { | |
10 public class CMException : Exception { | |
11 internal CMException(CR result, String method) | |
12 : base(method + " returned " + result.ToString()) { | |
13 } | |
14 internal static void Throw(CR result, String method) { | |
15 if (result == CR.SUCCESS) return; | |
16 throw new CMException(result, method); | |
17 } | |
18 } | |
19 public class DeviceNode { | |
20 public static DeviceNode Root { | |
21 get { | |
22 UInt32 node; | |
23 CR ret = SetupApi.CM_Locate_DevNode(out node, null, 0); | |
24 CMException.Throw(ret, "CM_Locate_DevNode"); | |
25 return new DeviceNode(node); | |
26 } | |
27 } | |
28 public static DeviceNode GetDevice(String deviceID) { | |
29 UInt32 node; | |
30 CR ret = SetupApi.CM_Locate_DevNode(out node, deviceID, 0); | |
31 CMException.Throw(ret, "CM_Locate_DevNode"); | |
32 return new DeviceNode(node); | |
33 } | |
34 private static IList<DeviceNode> GetDevicesInSet(SafeDeviceInfoSetHandle dis) { | |
35 List<DeviceNode> list = new List<DeviceNode>(); | |
36 if (dis.IsInvalid) throw new Win32Exception(Marshal.GetLastWin32Error()); | |
37 SP_DEVINFO_DATA dd = new SP_DEVINFO_DATA(true); | |
38 for (int index = 0; ; index++) { | |
39 if (!SetupApi.SetupDiEnumDeviceInfo(dis, index, ref dd)) break; | |
40 list.Add(new DeviceNode(dd.DevInst)); | |
41 } | |
42 return list; | |
43 } | |
44 public static IList<DeviceNode> GetDevices() { | |
45 using (SafeDeviceInfoSetHandle dis = SetupApi.SetupDiGetClassDevsA(IntPtr.Zero, null, IntPtr.Zero, DICFG.PRESENT | DICFG.ALLCLASSES)) { | |
46 return GetDevicesInSet(dis); | |
47 } | |
48 } | |
49 public static IList<DeviceNode> GetDevices(Guid classGuid) { | |
50 using (SafeDeviceInfoSetHandle dis = SetupApi.SetupDiGetClassDevsA(ref classGuid, null, IntPtr.Zero, DICFG.PRESENT | DICFG.DEVICEINTERFACE)) { | |
51 return GetDevicesInSet(dis); | |
52 } | |
53 } | |
54 public static IList<DeviceNode> GetDevices(String enumerator) { | |
55 using (SafeDeviceInfoSetHandle dis = SetupApi.SetupDiGetClassDevsA(IntPtr.Zero, enumerator, IntPtr.Zero, DICFG.PRESENT | DICFG.ALLCLASSES)) { | |
56 //using (SafeDeviceInfoSetHandle dis = SetupApi.SetupDiGetClassDevsA(IntPtr.Zero, enumerator, IntPtr.Zero, DICFG.ALLCLASSES | DICFG.DEVICEINTERFACE)) { | |
57 return GetDevicesInSet(dis); | |
58 } | |
59 } | |
60 | |
61 public UInt32 DevInst { get; private set; } | |
62 private String _DeviceID = null; | |
63 internal DeviceNode(UInt32 node) { | |
64 DevInst = node; | |
65 } | |
66 public String DeviceID { | |
67 get { | |
68 if (_DeviceID == null) { | |
69 uint deviceidlen; | |
70 CR ret = SetupApi.CM_Get_Device_ID_Size(out deviceidlen, DevInst, 0); | |
71 CMException.Throw(ret, "CM_Get_Device_ID_Size"); | |
72 StringBuilder deviceid = new StringBuilder((int)deviceidlen); | |
73 ret = SetupApi.CM_Get_Device_ID(DevInst, deviceid, deviceid.MaxCapacity, 0); | |
74 CMException.Throw(ret, "CM_Get_Device_ID"); | |
75 _DeviceID = deviceid.ToString(); | |
76 } | |
77 return _DeviceID; | |
78 } | |
79 } | |
80 public Byte[] GetProperty(SPDRP property) { | |
81 using (SafeDeviceInfoSetHandle dis = SetupApi.SetupDiGetClassDevsA(IntPtr.Zero, DeviceID, IntPtr.Zero, DICFG.DEVICEINTERFACE | DICFG.ALLCLASSES)) { | |
82 if (dis.IsInvalid) throw new Win32Exception(Marshal.GetLastWin32Error()); | |
83 SP_DEVINFO_DATA dd = new SP_DEVINFO_DATA(true); | |
84 if (!SetupApi.SetupDiEnumDeviceInfo(dis, 0, ref dd)) | |
85 return null; | |
86 //throw new Win32Exception(Marshal.GetLastWin32Error()); | |
87 RegistryValueKind propertyType; | |
88 byte[] propBuffer = new byte[256]; | |
89 int requiredSize; | |
90 if (!SetupApi.SetupDiGetDeviceRegistryProperty(dis, ref dd, property, out propertyType, propBuffer, propBuffer.Length, out requiredSize)) | |
91 return null; | |
92 if (requiredSize > propBuffer.Length) { | |
93 propBuffer = new Byte[requiredSize]; | |
94 if (!SetupApi.SetupDiGetDeviceRegistryProperty(dis, ref dd, property, out propertyType, propBuffer, propBuffer.Length, out requiredSize)) | |
95 throw new Win32Exception(Marshal.GetLastWin32Error()); | |
96 } | |
97 if (requiredSize < propBuffer.Length) Array.Resize(ref propBuffer, requiredSize); | |
98 return propBuffer; | |
99 } | |
100 } | |
101 public String GetPropertyString(SPDRP property) { | |
102 Byte[] buffer = GetProperty(property); | |
103 if (buffer == null) return null; | |
104 return SetupApi.GetAsString(buffer, buffer.Length); | |
105 } | |
106 public Byte[] GetProperty(CMRDP property) { | |
107 uint proplength = 0; | |
108 uint proptype; | |
109 CR ret = SetupApi.CM_Get_DevNode_Registry_Property(DevInst, property, out proptype, null, ref proplength, 0); | |
110 if (ret == CR.NO_SUCH_VALUE) return null; | |
111 if (ret != CR.BUFFER_SMALL) CMException.Throw(ret, "CM_Get_DevNode_Registry_Property"); | |
112 Byte[] propbuffer = new Byte[proplength]; | |
113 ret = SetupApi.CM_Get_DevNode_Registry_Property(DevInst, property, out proptype, propbuffer, ref proplength, 0); | |
114 CMException.Throw(ret, "CM_Get_DevNode_Registry_Property"); | |
115 if (propbuffer.Length > proplength) Array.Resize(ref propbuffer, (int)proplength); | |
116 return propbuffer; | |
117 } | |
118 public String GetPropertyString(CMRDP property) { | |
119 Byte[] buffer = GetProperty(property); | |
120 if (buffer == null) return null; | |
121 return SetupApi.GetAsString(buffer, buffer.Length); | |
122 } | |
123 public String[] GetPropertyStringArray(CMRDP property) { | |
124 Byte[] buffer = GetProperty(property); | |
125 if (buffer == null) return null; | |
126 return SetupApi.GetAsStringArray(buffer, buffer.Length); | |
127 } | |
128 | |
129 public Byte[] GetCustomProperty(String name) { | |
130 using (SafeDeviceInfoSetHandle dis = SetupApi.SetupDiGetClassDevsA(IntPtr.Zero, DeviceID, IntPtr.Zero, DICFG.DEVICEINTERFACE | DICFG.ALLCLASSES)) { | |
131 if (dis.IsInvalid) throw new Win32Exception(Marshal.GetLastWin32Error()); | |
132 SP_DEVINFO_DATA dd = new SP_DEVINFO_DATA(true); | |
133 if (!SetupApi.SetupDiEnumDeviceInfo(dis, 0, ref dd)) | |
134 return null; | |
135 //throw new Win32Exception(Marshal.GetLastWin32Error()); | |
136 RegistryValueKind propertyType; | |
137 byte[] propBuffer = new byte[256]; | |
138 int requiredSize; | |
139 if (!SetupApi.SetupDiGetCustomDeviceProperty(dis, ref dd, name, DICUSTOMDEVPROP.NONE, out propertyType, propBuffer, propBuffer.Length, out requiredSize)) | |
140 return null; | |
141 if (requiredSize > propBuffer.Length) { | |
142 propBuffer = new Byte[requiredSize]; | |
143 if (!SetupApi.SetupDiGetCustomDeviceProperty(dis, ref dd, name, DICUSTOMDEVPROP.NONE, out propertyType, propBuffer, propBuffer.Length, out requiredSize)) | |
144 throw new Win32Exception(Marshal.GetLastWin32Error()); | |
145 } | |
146 if (requiredSize < propBuffer.Length) Array.Resize(ref propBuffer, requiredSize); | |
147 return propBuffer; | |
148 } | |
149 } | |
150 public String GetCustomPropertyString(String name) { | |
151 Byte[] buffer = GetCustomProperty(name); | |
152 if (buffer == null) return null; | |
153 return SetupApi.GetAsString(buffer, buffer.Length); | |
154 } | |
155 public String[] GetCustomPropertyStringArray(String name) { | |
156 Byte[] buffer = GetCustomProperty(name); | |
157 if (buffer == null) return null; | |
158 return SetupApi.GetAsStringArray(buffer, buffer.Length); | |
159 } | |
160 | |
161 public String DeviceDescription { get { return GetPropertyString(CMRDP.DEVICEDESC); } } | |
162 public String[] HardwareID { get { return GetPropertyStringArray(CMRDP.HARDWAREID); } } | |
163 public String[] CompatibleIDs { get { return GetPropertyStringArray(CMRDP.COMPATIBLEIDS); } } | |
164 public String Service { get { return GetPropertyString(CMRDP.SERVICE); } } | |
165 public String Class { get { return GetPropertyString(CMRDP.CLASS); } } | |
166 public String ClassGuid { get { return GetPropertyString(CMRDP.CLASSGUID); } } | |
167 public String DriverKey { get { return GetPropertyString(CMRDP.DRIVER); } } | |
168 public String Manufacturer { get { return GetPropertyString(CMRDP.MFG); } } | |
169 public String FriendlyName { get { return GetPropertyString(CMRDP.FRIENDLYNAME); } } | |
170 public String LocationInformation { get { return GetPropertyString(CMRDP.LOCATION_INFORMATION); } } | |
171 public String PhysicalDeviceObjectName { get { return GetPropertyString(CMRDP.PHYSICAL_DEVICE_OBJECT_NAME); } } | |
172 public Guid? BusTypeGuid { get { return SetupApi.GetAsGuid(GetProperty(CMRDP.BUSTYPEGUID)); } } | |
173 public Int32? BusNumber { get { return SetupApi.GetAsInt32(GetProperty(CMRDP.BUSNUMBER)); } } | |
174 public String EnumeratorName { get { return GetPropertyString(CMRDP.ENUMERATOR_NAME); } } | |
175 | |
176 public String[] GetInterfaces(String classGuid) { | |
177 return GetInterfaces(new Guid(classGuid)); | |
178 } | |
179 public String[] GetInterfaces(Guid classGuid) { | |
180 uint len; | |
181 CR ret = SetupApi.CM_Get_Device_Interface_List_Size(out len, ref classGuid, DeviceID, 0); | |
182 CMException.Throw(ret, "CM_Get_Device_Interface_List_Size"); | |
183 if (len <= 1) return null; | |
184 Byte[] buffer = new Byte[2 * len]; | |
185 ret = SetupApi.CM_Get_Device_Interface_List(ref classGuid, DeviceID, buffer, len, 0); | |
186 CMException.Throw(ret, "CM_Get_Device_Interface_List"); | |
187 return SetupApi.GetAsStringArray(buffer, 2 * (int)len); | |
188 } | |
189 public Boolean SupportsInterface(Guid classGuid) { | |
190 uint len; | |
191 CR ret = SetupApi.CM_Get_Device_Interface_List_Size(out len, ref classGuid, DeviceID, 0); | |
192 CMException.Throw(ret, "CM_Get_Device_Interface_List_Size"); | |
193 return len > 2; | |
194 } | |
195 | |
196 public IList<DeviceNode> GetChildren() { | |
197 UInt32 child; | |
198 CR ret = SetupApi.CM_Get_Child(out child, DevInst, 0); | |
199 if (ret == CR.NO_SUCH_DEVNODE) return null; | |
200 CMException.Throw(ret, "CM_Get_Child"); | |
201 List<DeviceNode> list = new List<DeviceNode>(); | |
202 while (true) { | |
203 list.Add(new DeviceNode(child)); | |
204 ret = SetupApi.CM_Get_Sibling(out child, child, 0); | |
205 if (ret == CR.NO_SUCH_DEVNODE) break; | |
206 CMException.Throw(ret, "CM_Get_Sibling"); | |
207 } | |
208 return list; | |
209 } | |
210 | |
211 public DeviceNode GetParent() { | |
212 UInt32 node; | |
213 CR ret = SetupApi.CM_Get_Parent(out node, DevInst, 0); | |
214 if (ret == CR.NO_SUCH_DEVNODE) return null; | |
215 CMException.Throw(ret, "CM_Get_Parent"); | |
216 return new DeviceNode(node); | |
217 } | |
218 | |
219 public Boolean Present { | |
220 get { | |
221 UInt32 status, problem; | |
222 CR ret = SetupApi.CM_Get_DevNode_Status(out status, out problem, DevInst, 0); | |
223 if (ret == CR.NO_SUCH_DEVNODE) return false; | |
224 CMException.Throw(ret, "CM_Get_DevNode_Status"); | |
225 if (status == 25174016) return false; | |
226 return true; | |
227 } | |
228 } | |
229 | |
230 public override bool Equals(object obj) { | |
231 DeviceNode other = obj as DeviceNode; | |
232 if (ReferenceEquals(other, null)) return false; | |
233 return DevInst == other.DevInst; | |
234 } | |
235 public override int GetHashCode() { | |
236 return (int)DevInst; | |
237 } | |
238 public static Boolean operator ==(DeviceNode x, DeviceNode y) { | |
239 if (ReferenceEquals(x, y)) return true; | |
240 if (ReferenceEquals(x, null)) return false; | |
241 if (ReferenceEquals(y, null)) return false; | |
242 return x.DevInst == y.DevInst; | |
243 } | |
244 public static Boolean operator !=(DeviceNode x, DeviceNode y) { | |
245 return !(x == y); | |
246 } | |
247 | |
248 public void SetEnabled(Boolean enabled) { | |
249 using (SafeDeviceInfoSetHandle dis = SetupApi.SetupDiGetClassDevsA(IntPtr.Zero, DeviceID, IntPtr.Zero, DICFG.DEVICEINTERFACE | DICFG.ALLCLASSES)) { | |
250 if (dis.IsInvalid) throw new Win32Exception(Marshal.GetLastWin32Error()); | |
251 SP_DEVINFO_DATA dd = new SP_DEVINFO_DATA(true); | |
252 if (!SetupApi.SetupDiEnumDeviceInfo(dis, 0, ref dd)) | |
253 throw new Win32Exception(Marshal.GetLastWin32Error()); | |
254 SP_PROPCHANGE_PARAMS PropChangeParams = new SP_PROPCHANGE_PARAMS(); | |
255 PropChangeParams.ClassInstallHeader.cbSize = Marshal.SizeOf(PropChangeParams.ClassInstallHeader); | |
256 PropChangeParams.ClassInstallHeader.InstallFunction = UsbApi.DIF_PROPERTYCHANGE; | |
257 PropChangeParams.Scope = UsbApi.DICS_FLAG_GLOBAL; // or use DICS_FLAG_CONFIGSPECIFIC to limit to current HW profile | |
258 PropChangeParams.HwProfile = 0; //Current hardware profile | |
259 PropChangeParams.StateChange = enabled ? UsbApi.DICS_ENABLE : UsbApi.DICS_DISABLE; | |
260 if (!SetupApi.SetupDiSetClassInstallParams(dis, ref dd, ref PropChangeParams.ClassInstallHeader, Marshal.SizeOf(PropChangeParams))) | |
261 throw new Win32Exception(Marshal.GetLastWin32Error()); | |
262 if (!SetupApi.SetupDiCallClassInstaller(UsbApi.DIF_PROPERTYCHANGE, dis, ref dd)) | |
263 throw new Win32Exception(Marshal.GetLastWin32Error()); | |
264 } | |
265 } | |
266 } | |
267 } |