Mercurial > hg > ucis.core
annotate USBLib/Communication/USBIO/USBIODevice.cs @ 111:df53bdd49507 default tip
Merge
author | Ivo Smits <Ivo@UCIS.nl> |
---|---|
date | Fri, 07 Nov 2014 18:37:39 +0100 |
parents | e811297f5aa4 |
children |
rev | line source |
---|---|
35 | 1 using System; |
2 using System.Collections.Generic; | |
3 using System.ComponentModel; | |
4 using System.IO; | |
5 using System.Runtime.InteropServices; | |
6 using Microsoft.Win32.SafeHandles; | |
68
e811297f5aa4
Updated USBLib: removed old LibUsbDotNet compatibility code and added new information helper classes
Ivo Smits <Ivo@UCIS.nl>
parents:
67
diff
changeset
|
7 using UCIS.USBLib.Descriptor; |
35 | 8 using UCIS.USBLib.Internal.Windows; |
9 | |
10 namespace UCIS.USBLib.Communication.USBIO { | |
11 public class USBIODevice : UsbInterface, IUsbDevice { | |
12 public string DeviceFilename { get; private set; } | |
13 public IUsbDeviceRegistry Registry { get; private set; } | |
14 private SafeFileHandle DeviceHandle; | |
15 private SafeFileHandle[] PipeHandlesIn = null; | |
16 private SafeFileHandle[] PipeHandlesOut = null; | |
17 | |
18 static int CTL_CODE(int DeviceType, int Function, int Method, int Access) { return ((DeviceType) << 16) | ((Access) << 14) | ((Function) << 2) | (Method); } | |
19 static int _USBIO_IOCTL_CODE(int FnCode, int Method) { return CTL_CODE(0x8094, 0x800 + FnCode, Method, 0); } | |
20 const int METHOD_BUFFERED = 0; | |
21 const int METHOD_IN_DIRECT = 1; | |
22 const int METHOD_OUT_DIRECT = 2; | |
23 static readonly int IOCTL_USBIO_GET_DESCRIPTOR = _USBIO_IOCTL_CODE(1, METHOD_OUT_DIRECT); | |
24 static readonly int IOCTL_USBIO_GET_CONFIGURATION = _USBIO_IOCTL_CODE(6, METHOD_BUFFERED); | |
25 static readonly int IOCTL_USBIO_SET_CONFIGURATION = _USBIO_IOCTL_CODE(9, METHOD_BUFFERED); | |
38
a9c4fed19e99
USBLib: fixes in USBIO driver and LibUsbDotNet compatibility code
Ivo Smits <Ivo@UCIS.nl>
parents:
37
diff
changeset
|
26 static readonly int IOCTL_USBIO_UNCONFIGURE_DEVICE = _USBIO_IOCTL_CODE(10, METHOD_BUFFERED); |
35 | 27 static readonly int IOCTL_USBIO_CLASS_OR_VENDOR_IN_REQUEST = _USBIO_IOCTL_CODE(12, METHOD_OUT_DIRECT); |
28 static readonly int IOCTL_USBIO_CLASS_OR_VENDOR_OUT_REQUEST = _USBIO_IOCTL_CODE(13, METHOD_IN_DIRECT); | |
29 static readonly int IOCTL_USBIO_RESET_DEVICE = _USBIO_IOCTL_CODE(21, METHOD_BUFFERED); | |
30 static readonly int IOCTL_USBIO_BIND_PIPE = _USBIO_IOCTL_CODE(30, METHOD_BUFFERED); | |
46
053cc617af54
USBLib: added functions to clear USB endpoint halt state
Ivo Smits <Ivo@UCIS.nl>
parents:
44
diff
changeset
|
31 static readonly int IOCTL_USBIO_RESET_PIPE = _USBIO_IOCTL_CODE(32, METHOD_BUFFERED); |
67
2d16447eff12
Simplified USB communication code, added functions to abort pipe transfers
Ivo Smits <Ivo@UCIS.nl>
parents:
65
diff
changeset
|
32 static readonly int IOCTL_USBIO_ABORT_PIPE = _USBIO_IOCTL_CODE(33, METHOD_BUFFERED); |
35 | 33 |
34 [DllImport("kernel32.dll", SetLastError = true)] | |
35 static unsafe extern bool ReadFile(SafeFileHandle hFile, byte* lpBuffer, uint nNumberOfBytesToRead, out uint lpNumberOfBytesRead, IntPtr lpOverlapped); | |
36 [DllImport("kernel32.dll", SetLastError = true)] | |
37 static unsafe extern bool WriteFile(SafeFileHandle hFile, byte* lpBuffer, uint nNumberOfBytesToWrite, out uint lpNumberOfBytesWritten, IntPtr lpOverlapped); | |
38 | |
39 enum USBIO_REQUEST_RECIPIENT : uint { | |
40 Device = 0, | |
41 Interface, | |
42 Endpoint, | |
43 Other, | |
44 } | |
45 enum USBIO_REQUEST_TYPE : uint { | |
46 Class = 1, | |
47 Vendor, | |
48 } | |
49 | |
50 const UInt32 USBIO_SHORT_TRANSFER_OK = 0x00010000; | |
51 | |
52 [StructLayout(LayoutKind.Sequential, Pack = 1)] | |
53 struct USBIO_DESCRIPTOR_REQUEST { | |
54 public USBIO_REQUEST_RECIPIENT Recipient; | |
55 public Byte DescriptorType; | |
56 public Byte DescriptorIndex; | |
57 public Int16 LanguageId; | |
58 } | |
59 [StructLayout(LayoutKind.Sequential, Pack = 1)] | |
60 struct USBIO_BIND_PIPE { | |
61 public Byte EndpointAddress; | |
62 } | |
63 [StructLayout(LayoutKind.Sequential, Pack = 1, Size = 2 + 2 + 4)] | |
64 struct USBIO_INTERFACE_SETTING { | |
65 public UInt16 InterfaceIndex; | |
66 public UInt16 AlternateSettingIndex; | |
67 public UInt32 MaximumTransferSize; | |
68 } | |
69 [StructLayout(LayoutKind.Sequential, Pack = 1)] | |
70 unsafe struct USBIO_SET_CONFIGURATION{ | |
71 public UInt16 ConfigurationIndex; | |
72 public UInt16 NbOfInterfaces; | |
73 public fixed byte InterfaceList[32 * (2 + 2 + 4)]; | |
74 } | |
75 [StructLayout(LayoutKind.Sequential, Pack = 1)] | |
76 struct USBIO_CLASS_OR_VENDOR_REQUEST { | |
77 public UInt32 Flags; | |
78 public USBIO_REQUEST_TYPE Type; | |
79 public USBIO_REQUEST_RECIPIENT Recipient; | |
80 public Byte RequestTypeReservedBits; | |
81 public Byte Request; | |
82 public Int16 Value; | |
83 public Int16 Index; | |
84 } | |
85 | |
86 public USBIODevice(String path, USBIORegistry registry) { | |
87 DeviceFilename = path; | |
88 this.Registry = registry; | |
89 DeviceHandle = OpenHandle(); | |
90 } | |
91 private SafeFileHandle OpenHandle() { | |
92 SafeFileHandle handle = Kernel32.CreateFile(DeviceFilename, | |
93 NativeFileAccess.FILE_GENERIC_READ | NativeFileAccess.FILE_GENERIC_WRITE, | |
94 NativeFileShare.FILE_SHARE_WRITE | NativeFileShare.FILE_SHARE_READ, | |
95 IntPtr.Zero, | |
96 NativeFileMode.OPEN_EXISTING, | |
97 NativeFileFlag.FILE_ATTRIBUTE_NORMAL, | |
98 IntPtr.Zero); | |
99 if (handle.IsInvalid || handle.IsClosed) throw new Win32Exception(Marshal.GetLastWin32Error(), "Could not open device"); | |
100 return handle; | |
101 } | |
102 public override void Close() { | |
103 if (PipeHandlesIn != null) for (int i = 0; i < PipeHandlesIn.Length; i++) if (PipeHandlesIn[i] != null) PipeHandlesIn[i].Close(); | |
104 if (PipeHandlesOut != null) for (int i = 0; i < PipeHandlesOut.Length; i++) if (PipeHandlesOut[i] != null) PipeHandlesOut[i].Close(); | |
105 if (DeviceHandle != null) DeviceHandle.Close(); | |
106 } | |
107 | |
108 public override Byte Configuration { | |
109 get { return base.Configuration; } | |
110 set { | |
68
e811297f5aa4
Updated USBLib: removed old LibUsbDotNet compatibility code and added new information helper classes
Ivo Smits <Ivo@UCIS.nl>
parents:
67
diff
changeset
|
111 UsbConfigurationInfo configuration = UsbDeviceInfo.FromDevice(this).FindConfiguration(value); |
e811297f5aa4
Updated USBLib: removed old LibUsbDotNet compatibility code and added new information helper classes
Ivo Smits <Ivo@UCIS.nl>
parents:
67
diff
changeset
|
112 if (configuration == null) throw new InvalidOperationException("Requested configuration ID not found"); |
e811297f5aa4
Updated USBLib: removed old LibUsbDotNet compatibility code and added new information helper classes
Ivo Smits <Ivo@UCIS.nl>
parents:
67
diff
changeset
|
113 unsafe { |
e811297f5aa4
Updated USBLib: removed old LibUsbDotNet compatibility code and added new information helper classes
Ivo Smits <Ivo@UCIS.nl>
parents:
67
diff
changeset
|
114 USBIO_SET_CONFIGURATION req = new USBIO_SET_CONFIGURATION(); |
e811297f5aa4
Updated USBLib: removed old LibUsbDotNet compatibility code and added new information helper classes
Ivo Smits <Ivo@UCIS.nl>
parents:
67
diff
changeset
|
115 req.ConfigurationIndex = configuration.Index; |
e811297f5aa4
Updated USBLib: removed old LibUsbDotNet compatibility code and added new information helper classes
Ivo Smits <Ivo@UCIS.nl>
parents:
67
diff
changeset
|
116 req.NbOfInterfaces = Math.Min((ushort)32, configuration.Descriptor.NumInterfaces); |
e811297f5aa4
Updated USBLib: removed old LibUsbDotNet compatibility code and added new information helper classes
Ivo Smits <Ivo@UCIS.nl>
parents:
67
diff
changeset
|
117 for (int j = 0; j < req.NbOfInterfaces; j++) { |
e811297f5aa4
Updated USBLib: removed old LibUsbDotNet compatibility code and added new information helper classes
Ivo Smits <Ivo@UCIS.nl>
parents:
67
diff
changeset
|
118 UsbInterfaceInfo intf = configuration.Interfaces[j]; |
e811297f5aa4
Updated USBLib: removed old LibUsbDotNet compatibility code and added new information helper classes
Ivo Smits <Ivo@UCIS.nl>
parents:
67
diff
changeset
|
119 *((USBIO_INTERFACE_SETTING*)(req.InterfaceList + sizeof(USBIO_INTERFACE_SETTING) * j)) = |
e811297f5aa4
Updated USBLib: removed old LibUsbDotNet compatibility code and added new information helper classes
Ivo Smits <Ivo@UCIS.nl>
parents:
67
diff
changeset
|
120 new USBIO_INTERFACE_SETTING() { InterfaceIndex = intf.Descriptor.InterfaceNumber, AlternateSettingIndex = 0, MaximumTransferSize = UInt16.MaxValue }; |
e811297f5aa4
Updated USBLib: removed old LibUsbDotNet compatibility code and added new information helper classes
Ivo Smits <Ivo@UCIS.nl>
parents:
67
diff
changeset
|
121 } |
e811297f5aa4
Updated USBLib: removed old LibUsbDotNet compatibility code and added new information helper classes
Ivo Smits <Ivo@UCIS.nl>
parents:
67
diff
changeset
|
122 try { |
e811297f5aa4
Updated USBLib: removed old LibUsbDotNet compatibility code and added new information helper classes
Ivo Smits <Ivo@UCIS.nl>
parents:
67
diff
changeset
|
123 DeviceIoControl(DeviceHandle, IOCTL_USBIO_SET_CONFIGURATION, (IntPtr)(&req), sizeof(USBIO_SET_CONFIGURATION), IntPtr.Zero, 0); |
e811297f5aa4
Updated USBLib: removed old LibUsbDotNet compatibility code and added new information helper classes
Ivo Smits <Ivo@UCIS.nl>
parents:
67
diff
changeset
|
124 } catch (Win32Exception ex) { |
e811297f5aa4
Updated USBLib: removed old LibUsbDotNet compatibility code and added new information helper classes
Ivo Smits <Ivo@UCIS.nl>
parents:
67
diff
changeset
|
125 if (ex.NativeErrorCode == unchecked((int)0xE0001005L)) return; |
e811297f5aa4
Updated USBLib: removed old LibUsbDotNet compatibility code and added new information helper classes
Ivo Smits <Ivo@UCIS.nl>
parents:
67
diff
changeset
|
126 throw; |
35 | 127 } |
128 } | |
129 } | |
130 } | |
131 | |
132 public void ClaimInterface(int interfaceID) { | |
133 } | |
134 public void ReleaseInterface(int interfaceID) { | |
135 } | |
136 public void SetAltInterface(int interfaceID, int alternateID) { | |
137 throw new NotImplementedException(); | |
138 } | |
139 public void ResetDevice() { | |
140 DeviceIoControl(DeviceHandle, IOCTL_USBIO_RESET_DEVICE, IntPtr.Zero, 0, IntPtr.Zero, 0); | |
141 } | |
142 public unsafe override int GetDescriptor(byte descriptorType, byte index, short langId, byte[] buffer, int offset, int length) { | |
143 if (offset < 0 || length < 0 || offset + length > buffer.Length) throw new ArgumentOutOfRangeException("length", "The specified offset and length exceed the buffer length"); | |
144 USBIO_DESCRIPTOR_REQUEST req = new USBIO_DESCRIPTOR_REQUEST() { DescriptorType = descriptorType, DescriptorIndex = index, LanguageId = langId, Recipient = USBIO_REQUEST_RECIPIENT.Device }; | |
145 fixed (Byte* b = buffer) { | |
146 return DeviceIoControl(DeviceHandle, IOCTL_USBIO_GET_DESCRIPTOR, (IntPtr)(&req), sizeof(USBIO_DESCRIPTOR_REQUEST), (IntPtr)(b + offset), length); | |
147 } | |
148 } | |
67
2d16447eff12
Simplified USB communication code, added functions to abort pipe transfers
Ivo Smits <Ivo@UCIS.nl>
parents:
65
diff
changeset
|
149 public override unsafe int ControlTransfer(UsbControlRequestType requestType, byte request, short value, short index, byte[] buffer, int offset, int length) { |
35 | 150 if (buffer == null) { |
151 if (offset != 0 || length != 0) throw new ArgumentOutOfRangeException("length", "The specified offset and length exceed the buffer length"); | |
152 } else { | |
153 if (offset < 0 || length < 0 || offset + length > buffer.Length) throw new ArgumentOutOfRangeException("length", "The specified offset and length exceed the buffer length"); | |
154 } | |
155 switch (requestType & UsbControlRequestType.TypeMask) { | |
156 case UsbControlRequestType.TypeStandard: | |
157 switch ((UsbStandardRequest)request) { | |
158 case UsbStandardRequest.GetDescriptor: | |
159 return GetDescriptor((Byte)(value >> 8), (Byte)value, index, buffer, offset, length); | |
160 case UsbStandardRequest.GetConfiguration: | |
161 fixed (Byte* b = buffer) return DeviceIoControl(DeviceHandle, IOCTL_USBIO_GET_CONFIGURATION, IntPtr.Zero, 0, (IntPtr)(b + offset), length); | |
162 case UsbStandardRequest.SetConfiguration: | |
163 Configuration = (Byte)value; | |
164 return 0; | |
165 default: | |
166 throw new ArgumentException(String.Format("Invalid request: 0x{0:X8}", request)); | |
167 } | |
168 case UsbControlRequestType.TypeVendor: | |
169 case UsbControlRequestType.TypeClass: | |
170 USBIO_CLASS_OR_VENDOR_REQUEST req = new USBIO_CLASS_OR_VENDOR_REQUEST() { | |
171 Flags = USBIO_SHORT_TRANSFER_OK, | |
172 Type = (USBIO_REQUEST_TYPE)((int)(requestType & UsbControlRequestType.TypeMask) >> 5), | |
173 Recipient = (USBIO_REQUEST_RECIPIENT)((int)(requestType & UsbControlRequestType.RecipMask) >> 0), | |
174 RequestTypeReservedBits = 0, | |
175 Request = request, | |
176 Value = value, | |
177 Index = index, | |
178 }; | |
179 fixed (Byte* b = buffer) { | |
180 if ((requestType & UsbControlRequestType.EndpointMask) == UsbControlRequestType.EndpointIn) { | |
181 return DeviceIoControl(DeviceHandle, IOCTL_USBIO_CLASS_OR_VENDOR_IN_REQUEST, (IntPtr)(&req), sizeof(USBIO_CLASS_OR_VENDOR_REQUEST), (IntPtr)(b + offset), length); | |
182 } else { | |
183 return DeviceIoControl(DeviceHandle, IOCTL_USBIO_CLASS_OR_VENDOR_OUT_REQUEST, (IntPtr)(&req), sizeof(USBIO_CLASS_OR_VENDOR_REQUEST), (IntPtr)(b + offset), length); | |
184 } | |
185 } | |
186 case UsbControlRequestType.TypeReserved: | |
187 default: | |
188 throw new ArgumentException(String.Format("Invalid or unsupported request type: 0x{0:X8}", requestType)); | |
189 } | |
190 } | |
191 private unsafe SafeFileHandle OpenHandleForPipe(Byte epID) { | |
192 SafeFileHandle handle = OpenHandle(); | |
193 USBIO_BIND_PIPE req = new USBIO_BIND_PIPE() { EndpointAddress = epID }; | |
194 try { | |
195 DeviceIoControl(handle, IOCTL_USBIO_BIND_PIPE, (IntPtr)(&req), sizeof(USBIO_BIND_PIPE), IntPtr.Zero, 0); | |
196 } catch (Exception) { | |
197 handle.Close(); | |
198 throw; | |
199 } | |
200 return handle; | |
201 } | |
202 private SafeFileHandle GetHandleForPipe(Byte epID) { | |
203 int epidx = epID & 0x7F; | |
204 if ((epID & 0x80) != 0) { | |
205 if (PipeHandlesIn != null && PipeHandlesIn.Length >= epidx && PipeHandlesIn[epidx] != null) return PipeHandlesIn[epidx]; | |
206 SafeFileHandle handle = OpenHandleForPipe(epID); | |
207 if (PipeHandlesIn == null) PipeHandlesIn = new SafeFileHandle[epidx + 1]; | |
208 else Array.Resize(ref PipeHandlesIn, epidx + 1); | |
209 PipeHandlesIn[epidx] = handle; | |
210 return handle; | |
211 } else { | |
212 if (PipeHandlesOut != null && PipeHandlesOut.Length >= epidx && PipeHandlesOut[epidx] != null) return PipeHandlesOut[epidx]; | |
213 SafeFileHandle handle = OpenHandleForPipe(epID); | |
214 if (PipeHandlesOut == null) PipeHandlesOut = new SafeFileHandle[epidx + 1]; | |
215 else Array.Resize(ref PipeHandlesOut, epidx + 1); | |
216 PipeHandlesOut[epidx] = handle; | |
217 return handle; | |
218 } | |
219 } | |
67
2d16447eff12
Simplified USB communication code, added functions to abort pipe transfers
Ivo Smits <Ivo@UCIS.nl>
parents:
65
diff
changeset
|
220 public unsafe override int PipeTransfer(Byte epnum, Byte[] buffer, int offset, int length) { |
35 | 221 if (offset < 0 || length < 0 || offset + length > buffer.Length) throw new ArgumentOutOfRangeException("length", "The specified offset and length exceed the buffer length"); |
222 SafeFileHandle handle = GetHandleForPipe(epnum); | |
223 uint ret; | |
224 fixed (Byte* b = buffer) { | |
67
2d16447eff12
Simplified USB communication code, added functions to abort pipe transfers
Ivo Smits <Ivo@UCIS.nl>
parents:
65
diff
changeset
|
225 Boolean success; |
2d16447eff12
Simplified USB communication code, added functions to abort pipe transfers
Ivo Smits <Ivo@UCIS.nl>
parents:
65
diff
changeset
|
226 if ((epnum & (Byte)UsbControlRequestType.EndpointMask) == (Byte)UsbControlRequestType.EndpointIn) |
2d16447eff12
Simplified USB communication code, added functions to abort pipe transfers
Ivo Smits <Ivo@UCIS.nl>
parents:
65
diff
changeset
|
227 success = ReadFile(handle, b + offset, (uint)length, out ret, IntPtr.Zero); |
2d16447eff12
Simplified USB communication code, added functions to abort pipe transfers
Ivo Smits <Ivo@UCIS.nl>
parents:
65
diff
changeset
|
228 else |
2d16447eff12
Simplified USB communication code, added functions to abort pipe transfers
Ivo Smits <Ivo@UCIS.nl>
parents:
65
diff
changeset
|
229 success = WriteFile(handle, b + offset, (uint)length, out ret, IntPtr.Zero); |
2d16447eff12
Simplified USB communication code, added functions to abort pipe transfers
Ivo Smits <Ivo@UCIS.nl>
parents:
65
diff
changeset
|
230 if (!success) throw new Win32Exception(Marshal.GetLastWin32Error()); |
35 | 231 } |
232 return (int)ret; | |
233 } | |
67
2d16447eff12
Simplified USB communication code, added functions to abort pipe transfers
Ivo Smits <Ivo@UCIS.nl>
parents:
65
diff
changeset
|
234 public override void PipeReset(byte pipeID) { |
46
053cc617af54
USBLib: added functions to clear USB endpoint halt state
Ivo Smits <Ivo@UCIS.nl>
parents:
44
diff
changeset
|
235 SafeFileHandle handle = GetHandleForPipe(pipeID); |
053cc617af54
USBLib: added functions to clear USB endpoint halt state
Ivo Smits <Ivo@UCIS.nl>
parents:
44
diff
changeset
|
236 DeviceIoControl(handle, IOCTL_USBIO_RESET_PIPE, IntPtr.Zero, 0, IntPtr.Zero, 0); |
35 | 237 } |
67
2d16447eff12
Simplified USB communication code, added functions to abort pipe transfers
Ivo Smits <Ivo@UCIS.nl>
parents:
65
diff
changeset
|
238 public override void PipeAbort(byte pipeID) { |
2d16447eff12
Simplified USB communication code, added functions to abort pipe transfers
Ivo Smits <Ivo@UCIS.nl>
parents:
65
diff
changeset
|
239 SafeFileHandle handle = GetHandleForPipe(pipeID); |
2d16447eff12
Simplified USB communication code, added functions to abort pipe transfers
Ivo Smits <Ivo@UCIS.nl>
parents:
65
diff
changeset
|
240 DeviceIoControl(handle, IOCTL_USBIO_ABORT_PIPE, IntPtr.Zero, 0, IntPtr.Zero, 0); |
2d16447eff12
Simplified USB communication code, added functions to abort pipe transfers
Ivo Smits <Ivo@UCIS.nl>
parents:
65
diff
changeset
|
241 } |
35 | 242 |
243 private unsafe int DeviceIoControl(SafeHandle hDevice, int IoControlCode, IntPtr InBuffer, int nInBufferSize, IntPtr OutBuffer, int nOutBufferSize) { | |
244 int pBytesReturned; | |
245 if (Kernel32.DeviceIoControl(hDevice, IoControlCode, InBuffer, nInBufferSize, OutBuffer, nOutBufferSize, out pBytesReturned, null)) | |
246 return pBytesReturned; | |
247 throw new Win32Exception(Marshal.GetLastWin32Error()); | |
248 } | |
249 | |
67
2d16447eff12
Simplified USB communication code, added functions to abort pipe transfers
Ivo Smits <Ivo@UCIS.nl>
parents:
65
diff
changeset
|
250 public override UsbPipeStream GetPipeStream(byte endpoint) { |
2d16447eff12
Simplified USB communication code, added functions to abort pipe transfers
Ivo Smits <Ivo@UCIS.nl>
parents:
65
diff
changeset
|
251 return new PipeStream(this, endpoint, GetHandleForPipe(endpoint)); |
35 | 252 } |
253 | |
254 class PipeStream : UsbPipeStream { | |
255 private SafeFileHandle Handle; | |
67
2d16447eff12
Simplified USB communication code, added functions to abort pipe transfers
Ivo Smits <Ivo@UCIS.nl>
parents:
65
diff
changeset
|
256 public PipeStream(IUsbInterface device, Byte endpoint, SafeFileHandle handle) : base(device, endpoint) { |
35 | 257 this.Handle = handle; |
258 } | |
259 | |
260 public unsafe override void Write(byte[] buffer, int offset, int length) { | |
261 if (offset < 0 || length < 0 || offset + length > buffer.Length) throw new ArgumentOutOfRangeException("length", "The specified offset and length exceed the buffer length"); | |
262 uint ret; | |
263 fixed (Byte* b = buffer) { | |
264 if (!WriteFile(Handle, b + offset, (uint)length, out ret, IntPtr.Zero)) throw new Win32Exception(Marshal.GetLastWin32Error()); | |
265 } | |
266 if (ret <= 0) throw new EndOfStreamException("Could not write all data"); | |
267 } | |
268 | |
269 public unsafe override int Read(byte[] buffer, int offset, int length) { | |
270 if (offset < 0 || length < 0 || offset + length > buffer.Length) throw new ArgumentOutOfRangeException("length", "The specified offset and length exceed the buffer length"); | |
271 uint ret; | |
272 fixed (Byte* b = buffer) { | |
273 if (!WriteFile(Handle, b + offset, (uint)length, out ret, IntPtr.Zero)) throw new Win32Exception(Marshal.GetLastWin32Error()); | |
274 } | |
275 return (int)ret; | |
276 } | |
277 } | |
278 } | |
279 } |