Mercurial > hg > ucis.core
annotate USBLib/Communication/LibUsbDotNet.cs @ 67:2d16447eff12
Simplified USB communication code, added functions to abort pipe transfers
author | Ivo Smits <Ivo@UCIS.nl> |
---|---|
date | Wed, 16 Oct 2013 01:11:49 +0200 |
parents | abe0d55a2201 |
children |
rev | line source |
---|---|
21 | 1 ???using System; |
22 | 2 using System.Collections.Generic; |
21 | 3 using System.Collections.ObjectModel; |
22 | 4 using System.IO; |
21 | 5 using System.Runtime.InteropServices; |
22 | 6 using System.Text; |
21 | 7 using System.Threading; |
22 | 8 using LibUsbDotNet.Descriptors; |
9 using LibUsbDotNet.Info; | |
21 | 10 using LibUsbDotNet.Main; |
11 using UCIS.USBLib.Communication; | |
65
abe0d55a2201
Removed some redundant USB communication code
Ivo Smits <Ivo@UCIS.nl>
parents:
61
diff
changeset
|
12 using UCIS.USBLib.Descriptor; |
21 | 13 using LibUsb0Registry = UCIS.USBLib.Communication.LibUsb.LibUsb0Registry; |
14 using LibUsb1Registry = UCIS.USBLib.Communication.LibUsb1.LibUsb1Registry; | |
15 using nIUsbDevice = UCIS.USBLib.Communication.IUsbDevice; | |
16 using nIUsbInterface = UCIS.USBLib.Communication.IUsbInterface; | |
17 using WinUsbRegistry = UCIS.USBLib.Communication.WinUsb.WinUsbRegistry; | |
35
6fcedb1030bf
USBLib: Added support for USBIO driver
Ivo Smits <Ivo@UCIS.nl>
parents:
22
diff
changeset
|
18 using USBIORegistry = UCIS.USBLib.Communication.USBIO.USBIORegistry; |
21 | 19 |
20 namespace LibUsbDotNet { | |
65
abe0d55a2201
Removed some redundant USB communication code
Ivo Smits <Ivo@UCIS.nl>
parents:
61
diff
changeset
|
21 public class UsbDevice { |
21 | 22 public nIUsbInterface Device { get; private set; } |
23 public UsbDevice(nIUsbInterface dev) { | |
60
3424fa5a12c9
Updated Windows USB enumeration classes and VBoxUSB backend
Ivo Smits <Ivo@UCIS.nl>
parents:
38
diff
changeset
|
24 if (dev == null) throw new ArgumentNullException("dev"); |
21 | 25 Device = dev; |
26 } | |
27 public bool GetDescriptor(byte descriptorType, byte index, short langId, Byte[] buffer, int bufferLength, out int transferLength) { | |
28 try { | |
29 transferLength = Device.GetDescriptor(descriptorType, index, langId, buffer, 0, bufferLength); | |
30 return true; | |
31 } catch { | |
32 transferLength = 0; | |
33 return false; | |
34 } | |
35 } | |
36 public bool ControlTransfer(ref UsbSetupPacket setupPacket, Byte[] buffer, int bufferLength, out int lengthTransferred) { | |
67
2d16447eff12
Simplified USB communication code, added functions to abort pipe transfers
Ivo Smits <Ivo@UCIS.nl>
parents:
65
diff
changeset
|
37 lengthTransferred = Device.ControlTransfer((UsbControlRequestType)setupPacket.RequestType, setupPacket.Request, setupPacket.Value, setupPacket.Index, buffer, 0, bufferLength); |
21 | 38 return true; |
39 } | |
40 public UsbEndpointReader OpenEndpointReader(ReadEndpointID readEndpointID, int buffersize, EndpointType endpointType) { | |
41 UsbEndpointReader reader = new UsbEndpointReader(Device, (Byte)readEndpointID, endpointType); | |
42 reader.ReadBufferSize = buffersize; | |
43 return reader; | |
44 } | |
45 public void Close() { | |
46 Device.Dispose(); | |
47 } | |
48 public UsbDeviceInfo Info { get { return new UsbDeviceInfo(this); } } | |
49 public static IList<UsbRegistry> AllDevices { | |
50 get { | |
51 List<UsbRegistry> list = new List<UsbRegistry>(); | |
52 if (Environment.OSVersion.Platform == PlatformID.Win32NT) { | |
53 foreach (IUsbDeviceRegistry reg in WinUsbRegistry.DeviceList) list.Add(new UsbRegistry(reg)); | |
54 foreach (IUsbDeviceRegistry reg in LibUsb0Registry.DeviceList) list.Add(new UsbRegistry(reg)); | |
35
6fcedb1030bf
USBLib: Added support for USBIO driver
Ivo Smits <Ivo@UCIS.nl>
parents:
22
diff
changeset
|
55 foreach (IUsbDeviceRegistry reg in USBIORegistry.DeviceList) list.Add(new UsbRegistry(reg)); |
21 | 56 } else { |
57 foreach (IUsbDeviceRegistry reg in LibUsb1Registry.DeviceList) list.Add(new UsbRegistry(reg)); | |
58 } | |
59 return list; | |
60 } | |
61 } | |
62 public bool SetConfiguration(byte config) { | |
63 nIUsbDevice dev = Device as nIUsbDevice; | |
64 if (dev == null) return false; | |
65 try { | |
66 dev.Configuration = config; | |
67 return true; | |
68 } catch { | |
69 return false; | |
70 } | |
71 } | |
72 public bool ClaimInterface(int interfaceID) { | |
73 nIUsbDevice dev = Device as nIUsbDevice; | |
74 if (dev == null) return false; | |
75 try { | |
60
3424fa5a12c9
Updated Windows USB enumeration classes and VBoxUSB backend
Ivo Smits <Ivo@UCIS.nl>
parents:
38
diff
changeset
|
76 if (dev.Configuration == 0) dev.Configuration = 1; |
21 | 77 dev.ClaimInterface(interfaceID); |
78 return true; | |
79 } catch { | |
80 return false; | |
81 } | |
82 } | |
83 public bool ReleaseInterface(int interfaceID) { | |
84 nIUsbDevice dev = Device as nIUsbDevice; | |
85 if (dev == null) return false; | |
86 try { | |
87 dev.ReleaseInterface(interfaceID); | |
88 return true; | |
89 } catch { | |
90 return false; | |
91 } | |
92 } | |
93 public IList<UsbConfigInfo> Configs { | |
94 get { | |
95 List<UsbConfigInfo> rtnConfigs = new List<UsbConfigInfo>(); | |
65
abe0d55a2201
Removed some redundant USB communication code
Ivo Smits <Ivo@UCIS.nl>
parents:
61
diff
changeset
|
96 int iConfigs = Info.Descriptor.NumConfigurations; |
abe0d55a2201
Removed some redundant USB communication code
Ivo Smits <Ivo@UCIS.nl>
parents:
61
diff
changeset
|
97 for (Byte iConfig = 0; iConfig < iConfigs; iConfig++) { |
abe0d55a2201
Removed some redundant USB communication code
Ivo Smits <Ivo@UCIS.nl>
parents:
61
diff
changeset
|
98 UsbConfigurationDescriptor configDescriptor = UsbConfigurationDescriptor.FromDevice(Device, iConfig); |
abe0d55a2201
Removed some redundant USB communication code
Ivo Smits <Ivo@UCIS.nl>
parents:
61
diff
changeset
|
99 if (configDescriptor.Length < UsbConfigurationDescriptor.Size || configDescriptor.Type != UsbDescriptorType.Configuration) |
abe0d55a2201
Removed some redundant USB communication code
Ivo Smits <Ivo@UCIS.nl>
parents:
61
diff
changeset
|
100 throw new Exception("GetDeviceConfigs: USB config descriptor is invalid."); |
abe0d55a2201
Removed some redundant USB communication code
Ivo Smits <Ivo@UCIS.nl>
parents:
61
diff
changeset
|
101 Byte[] cfgBuffer = new Byte[configDescriptor.TotalLength]; |
21 | 102 int iBytesTransmitted; |
38
a9c4fed19e99
USBLib: fixes in USBIO driver and LibUsbDotNet compatibility code
Ivo Smits <Ivo@UCIS.nl>
parents:
35
diff
changeset
|
103 if (!GetDescriptor((byte)UsbDescriptorType.Configuration, (byte)iConfig, 0, cfgBuffer, cfgBuffer.Length, out iBytesTransmitted)) |
21 | 104 throw new Exception("Could not read configuration descriptor"); |
65
abe0d55a2201
Removed some redundant USB communication code
Ivo Smits <Ivo@UCIS.nl>
parents:
61
diff
changeset
|
105 configDescriptor = UsbConfigurationDescriptor.FromByteArray(cfgBuffer, 0, iBytesTransmitted); |
abe0d55a2201
Removed some redundant USB communication code
Ivo Smits <Ivo@UCIS.nl>
parents:
61
diff
changeset
|
106 if (configDescriptor.Length < UsbConfigurationDescriptor.Size || configDescriptor.Type != UsbDescriptorType.Configuration) |
21 | 107 throw new Exception("GetDeviceConfigs: USB config descriptor is invalid."); |
108 if (configDescriptor.TotalLength != iBytesTransmitted) throw new Exception("GetDeviceConfigs: USB config descriptor length doesn't match the length received."); | |
109 List<byte[]> rawDescriptorList = new List<byte[]>(); | |
110 int iRawLengthPosition = configDescriptor.Length; | |
111 while (iRawLengthPosition < configDescriptor.TotalLength) { | |
112 byte[] rawDescriptor = new byte[cfgBuffer[iRawLengthPosition]]; | |
113 if (iRawLengthPosition + rawDescriptor.Length > iBytesTransmitted) throw new Exception("Descriptor length is out of range."); | |
114 Array.Copy(cfgBuffer, iRawLengthPosition, rawDescriptor, 0, rawDescriptor.Length); | |
115 rawDescriptorList.Add(rawDescriptor); | |
116 iRawLengthPosition += rawDescriptor.Length; | |
117 } | |
65
abe0d55a2201
Removed some redundant USB communication code
Ivo Smits <Ivo@UCIS.nl>
parents:
61
diff
changeset
|
118 rtnConfigs.Add(new UsbConfigInfo(this, configDescriptor, rawDescriptorList)); |
21 | 119 } |
120 return rtnConfigs; | |
121 } | |
122 } | |
123 } | |
124 public class UsbEndpointReader : IDisposable { | |
125 public nIUsbInterface Device { get; private set; } | |
126 public Byte EndpointID { get; private set; } | |
127 public EndpointType EndpointType { get; private set; } | |
128 public Byte EpNum { get { return EndpointID; } } | |
129 public int ReadBufferSize { get; set; } | |
130 | |
131 public UsbEndpointReader(nIUsbInterface dev, byte epid, EndpointType eptype) { | |
132 Device = dev; | |
133 EndpointID = epid; | |
134 EndpointType = eptype; | |
135 ReadBufferSize = 4096; | |
136 } | |
137 public ErrorCode Read(byte[] buffer, int offset, int count, int timeout, out int transferLength) { | |
67
2d16447eff12
Simplified USB communication code, added functions to abort pipe transfers
Ivo Smits <Ivo@UCIS.nl>
parents:
65
diff
changeset
|
138 transferLength = Device.PipeTransfer(EndpointID, buffer, offset, count); |
21 | 139 return ErrorCode.Ok; |
140 } | |
141 public void Dispose() { DataReceivedEnabled = false; } | |
142 | |
143 private bool mDataReceivedEnabled; | |
144 private Thread mReadThread; | |
145 | |
146 public virtual bool DataReceivedEnabled { | |
147 get { return mDataReceivedEnabled; } | |
148 set { | |
149 if (value != mDataReceivedEnabled) { | |
150 if (mDataReceivedEnabled) { | |
151 mReadThread.Abort(); | |
152 } else { | |
153 mDataReceivedEnabled = true; | |
154 mReadThread = new Thread(ReadDataProcess); | |
155 mReadThread.Start(); | |
156 } | |
157 } | |
158 } | |
159 } | |
160 | |
161 private void ReadDataProcess(object state) { | |
162 byte[] buffer = new byte[ReadBufferSize]; | |
163 try { | |
164 while (mDataReceivedEnabled) { | |
165 int transferLength; | |
166 Read(buffer, 0, buffer.Length, -1, out transferLength); | |
167 EventHandler<EndpointDataEventArgs> eh = DataReceived; | |
168 if (!ReferenceEquals(eh, null)) eh(this, new EndpointDataEventArgs(buffer, transferLength)); | |
169 } | |
170 } catch (Exception ex) { | |
171 if (ReadError != null) ReadError(this, new ErrorEventArgs(ex)); | |
172 } finally { | |
173 mDataReceivedEnabled = false; | |
174 } | |
175 } | |
176 | |
177 public event EventHandler<EndpointDataEventArgs> DataReceived; | |
178 public event ErrorEventHandler ReadError; | |
179 } | |
180 } | |
181 namespace LibUsbDotNet.Main { | |
182 public class EndpointDataEventArgs : EventArgs { | |
183 internal EndpointDataEventArgs(byte[] bytes, int size) { | |
184 Buffer = bytes; | |
185 Count = size; | |
186 } | |
187 public byte[] Buffer { get; private set; } | |
188 public int Count { get; private set; } | |
189 } | |
190 [StructLayout(LayoutKind.Sequential, Pack = 1)] | |
191 public struct UsbSetupPacket { | |
192 public byte RequestType; | |
193 public byte Request; | |
194 public short Value; | |
195 public short Index; | |
196 public short Length; | |
197 public UsbSetupPacket(byte requestType, byte request, short value, short index, short length) { | |
198 RequestType = requestType; | |
199 Request = request; | |
200 Value = value; | |
201 Index = index; | |
202 Length = length; | |
203 } | |
204 } | |
205 public enum UsbEndpointDirection : byte { | |
206 EndpointIn = 0x80, | |
207 EndpointOut = 0x00, | |
208 } | |
209 public enum UsbRequestType : byte { | |
210 TypeClass = (0x01 << 5), | |
211 TypeReserved = (0x03 << 5), | |
212 TypeStandard = (0x00 << 5), | |
213 TypeVendor = (0x02 << 5), | |
214 } | |
215 public enum ReadEndpointID : byte { | |
216 Ep01 = 0x81, | |
217 Ep02 = 0x82, | |
218 Ep03 = 0x83, | |
219 Ep04 = 0x84, | |
220 Ep05 = 0x85, | |
221 Ep06 = 0x86, | |
222 Ep07 = 0x87, | |
223 Ep08 = 0x88, | |
224 Ep09 = 0x89, | |
225 Ep10 = 0x8A, | |
226 Ep11 = 0x8B, | |
227 Ep12 = 0x8C, | |
228 Ep13 = 0x8D, | |
229 Ep14 = 0x8E, | |
230 Ep15 = 0x8F, | |
231 } | |
232 public enum UsbRequestRecipient : byte { | |
233 RecipDevice = 0x00, | |
234 RecipInterface = 0x01, | |
235 RecipEndpoint = 0x02, | |
236 RecipOther = 0x03, | |
237 } | |
238 public enum EndpointType : byte { | |
239 Control, | |
240 Isochronous, | |
241 Bulk, | |
242 Interrupt | |
243 } | |
244 public enum ErrorCode { | |
245 Ok = 0, | |
246 Error = 1, | |
247 } | |
248 public class UsbRegistry { | |
249 public IUsbDeviceRegistry Registry { get; private set; } | |
250 public UsbRegistry(IUsbDeviceRegistry reg) { | |
251 Registry = reg; | |
252 } | |
253 public int Vid { get { return Registry.Vid; } } | |
254 public int Pid { get { return Registry.Pid; } } | |
255 public int Rev { get { return 0; } } | |
256 public Boolean IsAlive { get { return true; } } | |
257 public Boolean Open(out UsbDevice hand) { | |
258 hand = new UsbDevice(Registry.Open()); | |
259 return true; | |
260 } | |
261 public IDictionary<String, Object> DeviceProperties { get { return Registry.DeviceProperties; } } | |
262 public String FullName { get { return Registry.FullName; } } | |
263 public String Name { get { return Registry.Name; } } | |
264 public String SymbolicName { get { return Registry.SymbolicName; } } | |
265 } | |
266 } | |
267 namespace LibUsbDotNet.Info { | |
268 public class UsbDeviceInfo { | |
269 private readonly UsbDeviceDescriptor mDeviceDescriptor; | |
270 internal UsbDevice mUsbDevice; | |
271 internal UsbDeviceInfo(UsbDevice usbDevice) { | |
272 mUsbDevice = usbDevice; | |
65
abe0d55a2201
Removed some redundant USB communication code
Ivo Smits <Ivo@UCIS.nl>
parents:
61
diff
changeset
|
273 mDeviceDescriptor = UsbDeviceDescriptor.FromDevice(usbDevice.Device); |
21 | 274 } |
275 public UsbDeviceDescriptor Descriptor { get { return mDeviceDescriptor; } } | |
276 public String ManufacturerString { | |
277 get { | |
65
abe0d55a2201
Removed some redundant USB communication code
Ivo Smits <Ivo@UCIS.nl>
parents:
61
diff
changeset
|
278 if (Descriptor.ManufacturerStringID == 0) return null; |
abe0d55a2201
Removed some redundant USB communication code
Ivo Smits <Ivo@UCIS.nl>
parents:
61
diff
changeset
|
279 return UsbStringDescriptor.GetStringFromDevice(mUsbDevice.Device, Descriptor.ManufacturerStringID, 0); |
21 | 280 } |
281 } | |
282 public String ProductString { | |
283 get { | |
65
abe0d55a2201
Removed some redundant USB communication code
Ivo Smits <Ivo@UCIS.nl>
parents:
61
diff
changeset
|
284 if (Descriptor.ProductStringID == 0) return null; |
abe0d55a2201
Removed some redundant USB communication code
Ivo Smits <Ivo@UCIS.nl>
parents:
61
diff
changeset
|
285 return UsbStringDescriptor.GetStringFromDevice(mUsbDevice.Device, Descriptor.ProductStringID, 0); |
21 | 286 } |
287 } | |
288 public String SerialString { | |
289 get { | |
65
abe0d55a2201
Removed some redundant USB communication code
Ivo Smits <Ivo@UCIS.nl>
parents:
61
diff
changeset
|
290 if (Descriptor.SerialNumberStringID == 0) return null; |
abe0d55a2201
Removed some redundant USB communication code
Ivo Smits <Ivo@UCIS.nl>
parents:
61
diff
changeset
|
291 return UsbStringDescriptor.GetStringFromDevice(mUsbDevice.Device, Descriptor.SerialNumberStringID, 0); |
21 | 292 } |
293 } | |
294 } | |
295 public class UsbConfigInfo { | |
296 private readonly List<UsbInterfaceInfo> mInterfaceList = new List<UsbInterfaceInfo>(); | |
65
abe0d55a2201
Removed some redundant USB communication code
Ivo Smits <Ivo@UCIS.nl>
parents:
61
diff
changeset
|
297 internal readonly UsbConfigurationDescriptor mUsbConfigDescriptor; |
21 | 298 internal UsbDevice mUsbDevice; |
65
abe0d55a2201
Removed some redundant USB communication code
Ivo Smits <Ivo@UCIS.nl>
parents:
61
diff
changeset
|
299 internal UsbConfigInfo(UsbDevice usbDevice, UsbConfigurationDescriptor descriptor, IEnumerable<byte[]> rawDescriptors) { |
21 | 300 mUsbDevice = usbDevice; |
301 mUsbConfigDescriptor = descriptor; | |
302 UsbInterfaceInfo currentInterface = null; | |
65
abe0d55a2201
Removed some redundant USB communication code
Ivo Smits <Ivo@UCIS.nl>
parents:
61
diff
changeset
|
303 foreach (Byte[] bytesRawDescriptor in rawDescriptors) { |
21 | 304 switch (bytesRawDescriptor[1]) { |
305 case (byte)UsbDescriptorType.Interface: | |
306 currentInterface = new UsbInterfaceInfo(usbDevice, bytesRawDescriptor); | |
307 mInterfaceList.Add(currentInterface); | |
308 break; | |
309 case (byte)UsbDescriptorType.Endpoint: | |
310 if (currentInterface == null) throw new Exception("Recieved and endpoint descriptor before receiving an interface descriptor."); | |
311 currentInterface.mEndpointInfo.Add(new UsbEndpointInfo(bytesRawDescriptor)); | |
312 break; | |
313 } | |
314 } | |
315 } | |
65
abe0d55a2201
Removed some redundant USB communication code
Ivo Smits <Ivo@UCIS.nl>
parents:
61
diff
changeset
|
316 public UsbConfigurationDescriptor Descriptor { get { return mUsbConfigDescriptor; } } |
21 | 317 public ReadOnlyCollection<UsbInterfaceInfo> InterfaceInfoList { get { return mInterfaceList.AsReadOnly(); } } |
318 } | |
319 public class UsbInterfaceInfo { | |
320 internal readonly UsbInterfaceDescriptor mUsbInterfaceDescriptor; | |
321 internal UsbDevice mUsbDevice; | |
322 internal List<UsbEndpointInfo> mEndpointInfo = new List<UsbEndpointInfo>(); | |
323 internal UsbInterfaceInfo(UsbDevice usbDevice, byte[] descriptor) { | |
324 mUsbDevice = usbDevice; | |
65
abe0d55a2201
Removed some redundant USB communication code
Ivo Smits <Ivo@UCIS.nl>
parents:
61
diff
changeset
|
325 mUsbInterfaceDescriptor = UsbInterfaceDescriptor.FromByteArray(descriptor, 0, descriptor.Length); |
21 | 326 } |
327 public UsbInterfaceDescriptor Descriptor { get { return mUsbInterfaceDescriptor; } } | |
328 public ReadOnlyCollection<UsbEndpointInfo> EndpointInfoList { get { return mEndpointInfo.AsReadOnly(); } } | |
329 } | |
330 public class UsbEndpointInfo { | |
331 internal UsbEndpointDescriptor mUsbEndpointDescriptor; | |
332 internal UsbEndpointInfo(byte[] descriptor) { | |
65
abe0d55a2201
Removed some redundant USB communication code
Ivo Smits <Ivo@UCIS.nl>
parents:
61
diff
changeset
|
333 mUsbEndpointDescriptor = UsbEndpointDescriptor.FromByteArray(descriptor, 0, descriptor.Length); |
21 | 334 } |
335 public UsbEndpointDescriptor Descriptor { | |
336 get { return mUsbEndpointDescriptor; } | |
337 } | |
338 } | |
339 } | |
340 namespace LibUsbDotNet.Descriptors { | |
341 public enum ClassCodeType : byte { | |
342 PerInterface = 0, | |
343 Audio = 1, | |
344 Comm = 2, | |
345 Hid = 3, | |
346 Printer = 7, | |
347 Ptp = 6, | |
348 MassStorage = 8, | |
349 Hub = 9, | |
350 Data = 10, | |
351 VendorSpec = 0xff | |
352 } | |
353 } |