Mercurial > hg > ucis.core
annotate USBLib/Communication/WinUsb/WinUsbDevice.cs @ 42:aedd0e4adef7
FBGUI: Small cleanup
author | Ivo Smits <Ivo@UCIS.nl> |
---|---|
date | Wed, 01 May 2013 23:44:43 +0200 |
parents | c4a5dbe62513 |
children | 053cc617af54 |
rev | line source |
---|---|
21 | 1 ???using System; |
2 using System.ComponentModel; | |
3 using System.Runtime.InteropServices; | |
4 using System.Security; | |
5 using Microsoft.Win32.SafeHandles; | |
6 using UCIS.USBLib.Internal.Windows; | |
7 | |
8 namespace UCIS.USBLib.Communication.WinUsb { | |
9 class SafeWinUsbInterfaceHandle : SafeHandleZeroOrMinusOneIsInvalid { | |
10 public SafeWinUsbInterfaceHandle() : base(true) { } | |
11 protected override bool ReleaseHandle() { | |
12 if (IsInvalid) return true; | |
13 bool bSuccess = WinUsbDevice.WinUsb_Free(handle); | |
14 handle = IntPtr.Zero; | |
15 return bSuccess; | |
16 } | |
17 } | |
18 [StructLayout(LayoutKind.Sequential, Pack = 1)] | |
19 struct UsbSetupPacket { | |
20 public byte RequestType; | |
21 public byte Request; | |
22 public short Value; | |
23 public short Index; | |
24 public short Length; | |
25 public UsbSetupPacket(byte requestType, byte request, short value, short index, short length) { | |
26 RequestType = requestType; | |
27 Request = request; | |
28 Value = value; | |
29 Index = index; | |
30 Length = length; | |
31 } | |
32 } | |
33 [SuppressUnmanagedCodeSecurity] | |
34 public class WinUsbDevice : UsbInterface, IUsbDevice { | |
35 const string WIN_USB_DLL = "winusb.dll"; | |
36 [DllImport(WIN_USB_DLL, SetLastError = true)] | |
37 static extern bool WinUsb_Initialize(SafeFileHandle DeviceHandle, out SafeWinUsbInterfaceHandle InterfaceHandle); | |
38 [DllImport(WIN_USB_DLL, SetLastError = true)] | |
39 internal static extern bool WinUsb_GetAssociatedInterface(SafeWinUsbInterfaceHandle InterfaceHandle, byte AssociatedInterfaceIndex, out SafeWinUsbInterfaceHandle AssociatedInterfaceHandle); | |
40 [DllImport(WIN_USB_DLL, SetLastError = true)] | |
41 internal static extern bool WinUsb_Free(IntPtr InterfaceHandle); | |
42 [DllImport(WIN_USB_DLL, SetLastError = true)] | |
43 private static extern bool WinUsb_AbortPipe(SafeWinUsbInterfaceHandle InterfaceHandle, byte PipeID); | |
44 [DllImport(WIN_USB_DLL, SetLastError = true)] | |
45 private static extern bool WinUsb_ControlTransfer(SafeWinUsbInterfaceHandle InterfaceHandle, UsbSetupPacket SetupPacket, IntPtr Buffer, int BufferLength, out int LengthTransferred, IntPtr pOVERLAPPED); | |
46 [DllImport(WIN_USB_DLL, SetLastError = true)] | |
47 private static extern bool WinUsb_FlushPipe(SafeWinUsbInterfaceHandle InterfaceHandle, byte PipeID); | |
48 [DllImport(WIN_USB_DLL, SetLastError = true)] | |
49 private static extern bool WinUsb_GetDescriptor(SafeWinUsbInterfaceHandle InterfaceHandle, byte DescriptorType, byte Index, ushort LanguageID, IntPtr Buffer, int BufferLength, out int LengthTransferred); | |
50 [DllImport(WIN_USB_DLL, SetLastError = true)] | |
51 private static extern bool WinUsb_ReadPipe(SafeWinUsbInterfaceHandle InterfaceHandle, byte PipeID, Byte[] Buffer, int BufferLength, out int LengthTransferred, IntPtr pOVERLAPPED); | |
52 [DllImport(WIN_USB_DLL, SetLastError = true)] | |
53 private static extern bool WinUsb_ReadPipe(SafeWinUsbInterfaceHandle InterfaceHandle, byte PipeID, IntPtr pBuffer, int BufferLength, out int LengthTransferred, IntPtr pOVERLAPPED); | |
54 [DllImport(WIN_USB_DLL, SetLastError = true)] | |
55 private static extern bool WinUsb_ResetPipe(SafeWinUsbInterfaceHandle InterfaceHandle, byte PipeID); | |
56 [DllImport(WIN_USB_DLL, SetLastError = true)] | |
57 private static extern bool WinUsb_WritePipe(SafeWinUsbInterfaceHandle InterfaceHandle, byte PipeID, Byte[] Buffer, int BufferLength, out int LengthTransferred, IntPtr pOVERLAPPED); | |
58 [DllImport(WIN_USB_DLL, SetLastError = true)] | |
59 private static extern bool WinUsb_WritePipe(SafeWinUsbInterfaceHandle InterfaceHandle, byte PipeID, IntPtr pBuffer, int BufferLength, out int LengthTransferred, IntPtr pOVERLAPPED); | |
60 //[DllImport(WIN_USB_DLL, SetLastError = true)] | |
61 //private static extern bool WinUsb_SetPipePolicy(SafeWinUsbInterfaceHandle InterfaceHandle, byte PipeID, UInt32 PolicyType, UInt32 ValueLength, ref Byte Value); | |
62 SafeFileHandle DeviceHandle; | |
63 private SafeWinUsbInterfaceHandle[] InterfaceHandles = null; | |
64 private int[] EndpointToInterfaceIn = new int[0]; | |
65 private int[] EndpointToInterfaceOut = new int[0]; | |
66 public IUsbDeviceRegistry Registry { get; private set; } | |
67 | |
68 public WinUsbDevice(String path, WinUsbRegistry registry) { | |
69 this.Registry = registry; | |
70 DeviceHandle = Kernel32.CreateFile(path, | |
71 NativeFileAccess.FILE_GENERIC_WRITE | NativeFileAccess.FILE_GENERIC_READ, | |
72 NativeFileShare.FILE_SHARE_WRITE | NativeFileShare.FILE_SHARE_READ, | |
73 IntPtr.Zero, | |
74 NativeFileMode.OPEN_EXISTING, | |
75 NativeFileFlag.FILE_ATTRIBUTE_NORMAL | NativeFileFlag.FILE_FLAG_OVERLAPPED, | |
76 IntPtr.Zero); | |
77 if (DeviceHandle.IsInvalid || DeviceHandle.IsClosed) throw new Win32Exception(Marshal.GetLastWin32Error(), "Could not open device"); | |
78 SafeWinUsbInterfaceHandle InterfaceHandle; | |
79 if (!WinUsb_Initialize(DeviceHandle, out InterfaceHandle)) throw new Win32Exception(Marshal.GetLastWin32Error(), "Could not initialize WinUsb"); | |
80 if (InterfaceHandle.IsInvalid || InterfaceHandle.IsClosed) throw new Win32Exception(Marshal.GetLastWin32Error(), "Could not open interface"); | |
81 InterfaceHandles = new SafeWinUsbInterfaceHandle[1] { InterfaceHandle }; | |
82 foreach (LibUsbDotNet.Info.UsbConfigInfo ci in (new LibUsbDotNet.UsbDevice(this)).Configs) { | |
83 if (ci.Descriptor.ConfigID == Configuration) { | |
84 foreach (LibUsbDotNet.Info.UsbInterfaceInfo ifinfo in ci.InterfaceInfoList) { | |
85 foreach (LibUsbDotNet.Info.UsbEndpointInfo epinfo in ifinfo.EndpointInfoList) { | |
86 int epidx = epinfo.Descriptor.EndpointID & 0x7F; | |
87 if ((epinfo.Descriptor.EndpointID & 0x80) != 0) { | |
88 if (EndpointToInterfaceIn.Length <= epidx) Array.Resize(ref EndpointToInterfaceIn, epidx + 1); | |
89 EndpointToInterfaceIn[epidx] = ifinfo.Descriptor.InterfaceID; | |
90 } else { | |
91 if (EndpointToInterfaceOut.Length <= epidx) Array.Resize(ref EndpointToInterfaceOut, epidx + 1); | |
92 EndpointToInterfaceOut[epidx] = ifinfo.Descriptor.InterfaceID; | |
93 } | |
94 } | |
95 } | |
96 } | |
97 } | |
98 } | |
99 | |
100 public void ClaimInterface(int interfaceID) { | |
101 GetInterfaceHandle(interfaceID); | |
102 } | |
103 public void ReleaseInterface(int interfaceID) { | |
104 if (interfaceID == 0) return; | |
105 if (InterfaceHandles.Length < interfaceID || InterfaceHandles[interfaceID] == null) return; | |
106 InterfaceHandles[interfaceID].Close(); | |
107 InterfaceHandles[interfaceID] = null; | |
108 } | |
109 void IUsbDevice.ResetDevice() { | |
110 throw new NotSupportedException(); | |
111 } | |
112 private SafeWinUsbInterfaceHandle GetInterfaceHandle(int interfaceID) { | |
113 if (interfaceID == 0) return InterfaceHandles[0]; | |
114 if (interfaceID < 0 || interfaceID > 255) throw new ArgumentOutOfRangeException("interfaceID"); | |
115 if (InterfaceHandles.Length > interfaceID && InterfaceHandles[interfaceID] != null) return InterfaceHandles[interfaceID]; | |
116 SafeWinUsbInterfaceHandle ih; | |
117 if (!WinUsb_GetAssociatedInterface(InterfaceHandles[0], (Byte)(interfaceID - 1), out ih) || ih.IsInvalid || ih.IsClosed) | |
118 throw new Win32Exception(Marshal.GetLastWin32Error(), "Could not open interface"); | |
119 if (InterfaceHandles.Length <= interfaceID) Array.Resize(ref InterfaceHandles, interfaceID + 1); | |
120 InterfaceHandles[interfaceID] = ih; | |
121 return ih; | |
122 } | |
123 private SafeWinUsbInterfaceHandle GetInterfaceHandleForEndpoint(int epID) { | |
124 int epidx = epID & 0x7F; | |
125 if ((epID & 0x80) != 0) { | |
126 if (EndpointToInterfaceIn.Length <= epidx) throw new ArgumentOutOfRangeException("endpoint"); | |
127 return GetInterfaceHandle(EndpointToInterfaceIn[epidx]); | |
128 } else { | |
129 if (EndpointToInterfaceOut.Length <= epidx) throw new ArgumentOutOfRangeException("endpoint"); | |
130 return GetInterfaceHandle(EndpointToInterfaceOut[epidx]); | |
131 } | |
132 } | |
133 | |
134 public override void Close() { | |
135 foreach (SafeWinUsbInterfaceHandle ih in InterfaceHandles) ih.Close(); | |
136 InterfaceHandles = new SafeWinUsbInterfaceHandle[0]; | |
137 if (DeviceHandle != null) DeviceHandle.Close(); | |
138 } | |
139 | |
140 public override Byte Configuration { | |
141 get { return base.Configuration; } | |
142 set { | |
143 if (value == base.Configuration) return; | |
144 throw new NotSupportedException(); | |
145 } | |
146 } | |
147 | |
148 public unsafe int ControlTransfer(byte requestType, byte request, short value, short index, byte[] buffer, int offset, int length) { | |
149 if (buffer == null) buffer = new Byte[0]; | |
150 if (offset < 0 || length < 0 || length > short.MaxValue || offset + length > buffer.Length) throw new ArgumentOutOfRangeException("length"); | |
151 SafeWinUsbInterfaceHandle ih = InterfaceHandles[0]; | |
152 switch ((UsbControlRequestType)requestType & UsbControlRequestType.RecipMask) { | |
153 case UsbControlRequestType.RecipInterface: ih = GetInterfaceHandle(index & 0xff); break; | |
154 case UsbControlRequestType.RecipEndpoint: ih = GetInterfaceHandleForEndpoint(index & 0xff); break; | |
155 case UsbControlRequestType.RecipOther: break; | |
156 } | |
157 fixed (Byte* b = buffer) { | |
158 if (!WinUsb_ControlTransfer(ih, | |
159 new UsbSetupPacket(requestType, request, value, index, (short)length), | |
160 (IntPtr)(b + offset), length, out length, IntPtr.Zero)) | |
161 throw new Win32Exception(Marshal.GetLastWin32Error(), "Control transfer failed"); | |
162 return length; | |
163 } | |
164 } | |
165 | |
166 public override int ControlWrite(UsbControlRequestType requestType, byte request, short value, short index, byte[] buffer, int offset, int length) { | |
167 return ControlTransfer((byte)(requestType | UsbControlRequestType.EndpointOut), request, value, index, buffer, offset, length); | |
168 } | |
169 | |
170 public override int ControlRead(UsbControlRequestType requestType, byte request, short value, short index, byte[] buffer, int offset, int length) { | |
171 return ControlTransfer((byte)(requestType | UsbControlRequestType.EndpointIn), request, value, index, buffer, offset, length); | |
172 } | |
173 | |
174 public unsafe override int GetDescriptor(byte descriptorType, byte index, short langId, byte[] buffer, int offset, int length) { | |
36
c4a5dbe62513
USBLib: small fix in WinUSB backend bounds checking
Ivo Smits <Ivo@UCIS.nl>
parents:
21
diff
changeset
|
175 if (length > short.MaxValue || offset < 0 || length < 0 || offset + length > buffer.Length) throw new ArgumentOutOfRangeException("length"); |
21 | 176 fixed (Byte* b = buffer) { |
177 if (!WinUsb_GetDescriptor(InterfaceHandles[0], descriptorType, index, (ushort)langId, (IntPtr)(b + offset), length, out length)) | |
178 throw new Win32Exception(Marshal.GetLastWin32Error(), "Descriptor transfer failed"); | |
179 } | |
180 return length; | |
181 } | |
182 | |
183 public unsafe int PipeWrite(byte endpoint, byte[] buffer, int offset, int length) { | |
184 if (offset < 0 || length < 0 || offset + length > buffer.Length) throw new ArgumentOutOfRangeException("length", "The specified offset and length exceed the buffer length"); | |
185 SafeWinUsbInterfaceHandle ih = GetInterfaceHandleForEndpoint(endpoint); | |
186 fixed (Byte* b = buffer) { | |
187 if (!WinUsb_WritePipe(ih, endpoint, (IntPtr)(b + offset), length, out length, IntPtr.Zero)) | |
188 throw new Win32Exception(Marshal.GetLastWin32Error()); | |
189 } | |
190 return length; | |
191 } | |
192 | |
193 public unsafe int PipeRead(byte endpoint, byte[] buffer, int offset, int length) { | |
194 if (offset < 0 || length < 0 || offset + length > buffer.Length) throw new ArgumentOutOfRangeException("length", "The specified offset and length exceed the buffer length"); | |
195 SafeWinUsbInterfaceHandle ih = GetInterfaceHandleForEndpoint(endpoint); | |
196 fixed (Byte* b = buffer) { | |
197 if (!WinUsb_ReadPipe(ih, endpoint, (IntPtr)(b + offset), length, out length, IntPtr.Zero)) | |
198 throw new Win32Exception(Marshal.GetLastWin32Error()); | |
199 } | |
200 return length; | |
201 } | |
202 | |
203 public override int BulkWrite(Byte endpoint, Byte[] buffer, int offset, int length) { | |
204 return PipeWrite(endpoint, buffer, offset, length); | |
205 } | |
206 public override int BulkRead(Byte endpoint, Byte[] buffer, int offset, int length) { | |
207 return PipeRead(endpoint, buffer, offset, length); | |
208 } | |
209 public override int InterruptWrite(Byte endpoint, Byte[] buffer, int offset, int length) { | |
210 return PipeWrite(endpoint, buffer, offset, length); | |
211 } | |
212 public override int InterruptRead(Byte endpoint, Byte[] buffer, int offset, int length) { | |
213 return PipeRead(endpoint, buffer, offset, length); | |
214 } | |
215 } | |
216 } |