Heyo this is a small example, how to Marshall c structures to c# for the usb chip. The example shows a static c# class :)
1 ///
2 /// author svilen.info / svilen.de
3 ///
4 /// no copyright, however please cite source XD
5 ///
6 /// some small example, how the c -> c# marshalling works here!
7 ///
8
9 using System;
10 using System.Diagnostics;
11 using System.Runtime.InteropServices;
12 using System.Text;
13
14 namespace Zarlink.Adk.Forms
15 {
16 /// <summary>
17 /// This class will deal with the USB communication
18 /// </summary>
19 /// Here we will cast all the ftd2xx.h functions and structure that we need
20 /// and will add some other specific communaction protocols
21 static class Communication
22 {
23 #region My Variables
24
25 public static FT_STATUS status; // represents the FT status. To be updated after every action!
26
27 public static IntPtr handle; // represents the FT device handle. Should be always the same, if varies then something is wrong (like more usbs)
28
29
30 public struct Buffer
31 {
32 public byte[] data; // data from the last successful transfer
33 public DateTime lastSuccessfulUse; // if connection lost, to check the date and time of the last successful data transfer
34 }
35
36 public static Buffer inBuffer; // what we received last
37 public static Buffer outBuffer; // what we sent last
38
39 #endregion My Variables
40
41 #region Stupid defines from the dll
42
43 // FT_OpenEx Flags
44 private const UInt16 FT_OPEN_BY_SERIAL_NUMBER = 1;
45 private const UInt16 FT_OPEN_BY_DESCRIPTION = 2;
46 private const UInt16 FT_OPEN_BY_LOCATION = 4;
47
48 // Baud Rates
49 private const UInt32 FT_BAUD_300 = 300;
50 private const UInt32 FT_BAUD_600 = 600;
51 private const UInt32 FT_BAUD_1200 = 1200;
52 private const UInt32 FT_BAUD_2400 = 2400;
53 private const UInt32 FT_BAUD_4800 = 4800;
54 private const UInt32 FT_BAUD_9600 = 9600;
55 private const UInt32 FT_BAUD_14400 = 14400;
56 private const UInt32 FT_BAUD_19200 = 19200;
57 private const UInt32 FT_BAUD_38400 = 38400;
58 private const UInt32 FT_BAUD_57600 = 57600;
59 private const UInt32 FT_BAUD_115200 = 115200;
60 private const UInt32 FT_BAUD_230400 = 230400;
61 private const UInt32 FT_BAUD_460800 = 460800;
62 private const UInt32 FT_BAUD_921600 = 921600;
63
64 // Word Lengths
65 private const byte FT_BITS_8 = 8;
66 private const byte FT_BITS_7 = 7;
67 private const byte FT_BITS_6 = 6;
68 private const byte FT_BITS_5 = 5;
69
70
71 // Stop Bits
72 private const byte FT_STOP_BITS_1 = 0;
73 private const byte FT_STOP_BITS_1_5 = 1;
74 private const byte FT_STOP_BITS_2 = 2;
75
76 // Parity
77 private const byte FT_PARITY_NONE = 0;
78 private const byte FT_PARITY_ODD = 1;
79 private const byte FT_PARITY_EVEN = 2;
80 private const byte FT_PARITY_MARK = 3;
81 private const byte FT_PARITY_SPACE = 4;
82
83 // Flow Control
84 private const UInt16 FT_FLOW_NONE = 0x0000;
85 private const UInt16 FT_FLOW_RTS_CTS = 0x0100;
86 private const UInt16 FT_FLOW_DTR_DSR = 0x0200;
87 private const UInt16 FT_FLOW_XON_XOFF = 0x0400;
88
89 // Purge rx and tx buffers
90 public const byte FT_PURGE_RX = 1;
91 public const byte FT_PURGE_TX = 2;
92
93 // Events
94 public const byte FT_EVENT_RXCHAR = 1;
95 public const byte FT_EVENT_MODEM_STATUS = 2;
96 public const byte FT_EVENT_LINE_STATUS = 4;
97
98 // Timeouts
99 private const UInt32 FT_DEFAULT_RX_TIMEOUT = 300;
100 private const UInt32 FT_DEFAULT_TX_TIMEOUT = 300;
101
102 #endregion Stupid defines
103
104 #region Stupid Marshals
105
106 /// <summary>
107 /// marshalling the structure...
108 /// </summary>
109 [StructLayout(LayoutKind.Sequential)]
110 public struct LPFTDCB
111 {
112 public UInt32 DCBlength; /* sizeof(FTDCB) */
113 public UInt32 BaudRate; /* Baudrate at which running */
114
115 public UInt32 fBits; // bits layout is inportable so have the flag and take out the bits
116 //ulong fBinary: 1; /* Binary Mode (skip EOF check) */
117 //ulong fParity: 1; /* Enable parity checking */
118 //ulong fOutxCtsFlow:1; /* CTS handshaking on output */
119 //ulong fOutxDsrFlow:1; /* DSR handshaking on output */
120 //ulong fDtrControl:2; /* DTR Flow control */
121 //ulong fDsrSensitivity:1; /* DSR Sensitivity */
122 //ulong fTXContinueOnXoff: 1; /* Continue TX when Xoff sent */
123 //ulong fOutX: 1; /* Enable output X-ON/X-OFF */
124 //ulong fInX: 1; /* Enable input X-ON/X-OFF */
125 //ulong fErrorChar: 1; /* Enable Err Replacement */
126 //ulong fNull: 1; /* Enable Null stripping */
127 //ulong fRtsControl:2; /* Rts Flow control */
128 //ulong fAbortOnError:1; /* Abort all reads and writes on Error */
129 //ulong fDummy2:17; /* Reserved */
130
131 public UInt16 wReserved; /* Not currently used */
132 public UInt16 XonLim; /* Transmit X-ON threshold */
133 public UInt16 XoffLim; /* Transmit X-OFF threshold */
134
135 public byte ByteSize; /* Number of bits/byte, 4-8 */
136 public byte Parity; /* 0-4=None,Odd,Even,Mark,Space */
137 public byte StopBits; /* 0,1,2 = 1, 1.5, 2 */
138
139 public char XonChar; /* Tx and Rx X-ON character */
140 public char XoffChar; /* Tx and Rx X-OFF character */
141 public char ErrorChar; /* Error replacement char */
142 public char EofChar; /* End of Input character */
143 public char EvtChar; /* Received Event character */
144
145 public ushort wReserved1; /* Fill for now. */
146 } ;
147
148 #endregion Stupid Marshals
149
150 #region Constructors, Destructors ...
151
152 static Communication()
153 {
154 handle = IntPtr.Zero;
155
156 outBuffer = new Buffer { data = new byte[140], lastSuccessfulUse = DateTime.Now };
157 inBuffer = new Buffer { data = new byte[140], lastSuccessfulUse = DateTime.Now };
158 }
159
160 //static ~Communication()
161 //{
162 // Close();
163 //}
164
165 #endregion Constructors, Destructors ...
166
167 #region W32 Functions from the dll
168 // note: W32 should not be mixed with non W32 unless explicitly stated
169
170
171 /// <summary>
172 /// This function gets the current device state.
173 /// </summary>
174 /// <param name="ftHandle">Cast PVOID to IntPtr to have system specific handle pointer size</param>
175 /// <param name="lpftDcb">the status</param>
176 /// <returns>If the function is successful, the return value is nonzero</returns>
177 [DllImport("ftd2xx")]
178 public static extern bool FT_W32_GetCommState(IntPtr ftHandle, ref LPFTDCB lpftDcb);
179
180 #endregion W32 Functions
181
182 #region Normal Functions that we use from the dll
183
184 [DllImport("ftd2xx")]
185 public static extern FT_STATUS FT_ResetDevice(IntPtr ftHandle);
186
187 [DllImport("ftd2xx")]
188 public static extern FT_STATUS FT_ClrDtr(IntPtr ftHandle);
189
190 [DllImport("ftd2xx")]
191 public static extern FT_STATUS FT_ClrRts(IntPtr ftHandle);
192
193 [DllImport("ftd2xx")]
194 public static extern FT_STATUS FT_Open(UInt32 uiPort, IntPtr ftHandle);
195
196 [DllImport("ftd2xx")]
197 public static extern FT_STATUS FT_Close(IntPtr ftHandle);
198
199 [DllImport("ftd2xx")]
200 public static extern FT_STATUS FT_Read(IntPtr ftHandle, out byte[] lpBuffer, UInt32 dwBytesToRead, out UInt32 lpdwBytesReturned);
201
202 [DllImport("ftd2xx")]
203 public static extern FT_STATUS FT_Write(IntPtr ftHandle, IntPtr lpBuffer, UInt32 dwBytesToRead, ref UInt32 lpdwBytesWritten);
204
205 [DllImport("ftd2xx")]
206 public static extern FT_STATUS FT_SetLatencyTimer(IntPtr ftHandle, byte ucTimer);
207
208 [DllImport("ftd2xx")]
209 public static extern FT_STATUS FT_SetDataCharacteristics(IntPtr ftHandle, byte uWordLength, byte uStopBits, byte uParity);
210
211 [DllImport("ftd2xx")]
212 public static extern FT_STATUS FT_SetFlowControl(IntPtr ftHandle, ushort usFlowControl, byte uXon, byte uXoff);
213
214 [DllImport("ftd2xx")]
215 public static extern FT_STATUS FT_GetModemStatus(IntPtr ftHandle, ref UInt32 lpdwModemStatus);
216
217 [DllImport("ftd2xx")]
218 public static extern FT_STATUS FT_Purge(IntPtr ftHandle, UInt32 dwMask);
219
220 [DllImport("ftd2xx")]
221 public static extern FT_STATUS FT_SetBreakOn(IntPtr ftHandle);
222
223 [DllImport("ftd2xx")]
224 public static extern FT_STATUS FT_SetBreakOff(IntPtr ftHandle);
225
226 [DllImport("ftd2xx")]
227 public static extern FT_STATUS FT_GetStatus(IntPtr ftHandle, ref UInt32 lpdwAmountInRxQueue, ref UInt32 lpdwAmountInTxQueue, ref UInt32 lpdwEventStatus);
228
229 [DllImport("ftd2xx")]
230 public static extern FT_STATUS FT_SetDivisor(IntPtr ftHandle, char usDivisor);
231
232 #endregion Normal Functions
233
234 #region Functions written by Svilen ;)
235
236 public static void DebugInformation(string step = "")
237 {
238 Debug.WriteLine(step + " status: " + status);
239 Debug.WriteLine("handle address: " + handle);
240 unsafe
241 {
242 if (handle != null)
243 {
244 Debug.WriteLine("handle value: " + *(uint*) handle.ToPointer()); // to use in unsafed code
245 }
246 }
247 //Debug.WriteLine("handle value: " + *(uint *)handle.ToPointer()); // to use in unsafed code
248 }
249
250 public static void Init()
251 {
252 // > open >
253 FT_Open(0, handle);
254 DebugInformation("open");
255 // < open <
256
257 // > reset! >
258 FT_ResetDevice(handle);
259 DebugInformation("reset");
260 // < reset! <
261
262 // > set reply rate
263 FT_SetLatencyTimer(handle, 2);
264 DebugInformation("latency timer");
265 // < set reply rate <
266
267 // > set same flow control
268 FT_SetFlowControl(handle, FT_FLOW_RTS_CTS, 0, 0);
269 DebugInformation("flow control");
270 // < set flow control <
271
272
273 // > clear the buffers >
274 FT_Purge(handle, FT_PURGE_TX + FT_PURGE_RX);
275 DebugInformation("purge");
276 // < clear the buffers <
277 }
278
279 public static void ReadTest()
280 {
281 byte[] bytes = new byte[20];
282 IntPtr unmanagedPointer = Marshal.AllocHGlobal(bytes.Length);
283 Marshal.Copy(bytes, 0, unmanagedPointer, bytes.Length);
284 IntPtr bytesLeft = (IntPtr)10;
285
286 // FT_Read(handle, unmanagedPointer, (UInt32)bytes.Length, bytesLeft);
287 DebugInformation("read");
288
289 Marshal.Copy(unmanagedPointer, bytes, 0, bytes.Length);
290 ASCIIEncoding enc = new ASCIIEncoding();
291 Debug.WriteLine("buffer has: " + enc.GetString(bytes));
292
293 Marshal.FreeHGlobal(unmanagedPointer);
294 }
295
296 public static int ReadBuffer()
297 {
298 UInt32 bytesLeft;
299 inBuffer.data = new byte[140];
300
301 FT_Read(handle, out inBuffer.data, (UInt32)inBuffer.data.Length, out bytesLeft);
302 DebugInformation("read");
303
304 ASCIIEncoding enc = new ASCIIEncoding();
305 if (inBuffer.data != null)
306 Debug.WriteLine("buffer has: " + enc.GetString(inBuffer.data));
307
308 return 0;
309 }
310
311 public static void WriteTest()
312 {
313 IntPtr ptr = Marshal.AllocHGlobal(4);
314 Marshal.Copy(outBuffer.data, 0, ptr, 4);
315
316 uint bytesWritten = 0;
317 FT_Write(handle, ptr, 4, ref bytesWritten);
318
319 DebugInformation("write");
320 }
321
322 public static void Close()
323 {
324 if (handle == IntPtr.Zero)
325 {
326 FT_Close(handle);
327 DebugInformation("close");
328 }
329 }
330
331 #endregion Functions
332
333 #region other defines and enumerations for the communication namespace
334
335 /// <summary>
336 /// Enumaration containing the varios return status for the DLL functions.
337 /// </summary>
338 public enum FT_STATUS
339 {
340 FT_OK = 0,
341 FT_INVALID_HANDLE,
342 FT_DEVICE_NOT_FOUND,
343 FT_DEVICE_NOT_OPENED,
344 FT_IO_ERROR,
345 FT_INSUFFICIENT_RESOURCES,
346 FT_INVALID_PARAMETER,
347 FT_INVALID_BAUD_RATE,
348 FT_DEVICE_NOT_OPENED_FOR_ERASE,
349 FT_DEVICE_NOT_OPENED_FOR_WRITE,
350 FT_FAILED_TO_WRITE_DEVICE,
351 FT_EEPROM_READ_FAILED,
352 FT_EEPROM_WRITE_FAILED,
353 FT_EEPROM_ERASE_FAILED,
354 FT_EEPROM_NOT_PRESENT,
355 FT_EEPROM_NOT_PROGRAMMED,
356 FT_INVALID_ARGS,
357 FT_OTHER_ERROR
358 }
359
360 #endregion other defines and enumerations for the communication namespace
361 }
362 }
363