Heyo this is a small example, how to Marshall c structures to c# for the usb chip. The example shows a static c# class :)

(Download .cs)

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