ANTFS_HostChannel.cs 60 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314
  1. /*
  2. This software is subject to the license described in the License.txt file
  3. included with this software distribution. You may not use this file except
  4. in compliance with this license.
  5. Copyright (c) Dynastream Innovations Inc. 2016
  6. All rights reserved.
  7. */
  8. using System;
  9. using System.Threading;
  10. using System.Collections.Generic;
  11. using System.Linq;
  12. using System.Text;
  13. using System.Runtime.InteropServices;
  14. using System.ComponentModel;
  15. using System.Reflection;
  16. using ANT_Managed_Library;
  17. namespace ANT_Managed_Library.ANTFS
  18. {
  19. /// <summary>
  20. /// ANT-FS Host
  21. /// </summary>
  22. public class ANTFS_HostChannel : IDisposable
  23. {
  24. #region Public Definitions
  25. #pragma warning disable 1591
  26. /// <summary>
  27. /// ANT-FS Responses
  28. /// </summary>
  29. /// !!! Must match the enum in antfs_host_channel.hpp
  30. public enum Response : byte
  31. {
  32. [Description("No response")]
  33. None = 0,
  34. [Description("ANT-FS Host Idle")]
  35. InitPass,
  36. [Description("Error: Serial failure")]
  37. SerialFail,
  38. [Description("Failure requesting ANT-FS session from broadcast device")]
  39. RequestSessionFail,
  40. [Description("Found remote device")]
  41. ConnectPass,
  42. [Description("Disconnected successfully")]
  43. DisconnectPass,
  44. [Description("Lost connection")]
  45. ConnectionLost,
  46. [Description("Request for serial number successful")]
  47. AuthenticateNA,
  48. [Description("Authentication passed")]
  49. AuthenticatePass,
  50. [Description("Authentication rejected")]
  51. AuthenticateReject,
  52. [Description("Authentication failed")]
  53. AuthenticateFail,
  54. [Description("Downloaded data")]
  55. DownloadPass,
  56. [Description("Download rejected")]
  57. DownloadReject,
  58. [Description("Download failed, invalid index requested")]
  59. DownloadInvalidIndex,
  60. [Description("Download failed, file not readable")]
  61. DownloadFileNotReadable,
  62. [Description("Download failed, not ready")]
  63. DownloadNotReady,
  64. [Description("Download failed, CRC rejected")]
  65. DownloadCRCRejected,
  66. [Description("Download failed")]
  67. DownloadFail,
  68. [Description("Uploaded data")]
  69. UploadPass,
  70. [Description("Upload rejected")]
  71. UploadReject,
  72. [Description("Upload failed, invalid index requested")]
  73. UploadInvalidIndex,
  74. [Description("Upload failed, file not writeable")]
  75. UploadFileNotWriteable,
  76. [Description("Upload failed, insufficient space")]
  77. UploadInsufficientSpace,
  78. [Description("Upload failed")]
  79. UploadFail,
  80. [Description("Erased data")]
  81. ErasePass,
  82. [Description("Erase failed")]
  83. EraseFail,
  84. [Description("Manual transfer complete")]
  85. ManualTransferPass,
  86. [Description("Manual transmit failed")]
  87. ManualTransferTransmitFail,
  88. [Description("Manual response failed")]
  89. ManualTransferResponseFail,
  90. [Description("Request canceled")]
  91. CancelDone
  92. };
  93. /// <summary>
  94. /// ANT-FS State
  95. /// </summary>
  96. /// !!! Must match the enum in antfs_host_channel.hpp
  97. public enum State : byte
  98. {
  99. [Description("Off, state machine not initialized")]
  100. Off = 0,
  101. [Description("Idle")]
  102. Idle,
  103. [Description("Disconnecting")]
  104. Disconnecting,
  105. [Description("Requesting an ANT-FS Session from broadcast device")]
  106. RequestingSession,
  107. [Description("Searching")] // LINK
  108. Searching,
  109. [Description("Connected")] // AUTH
  110. Connected,
  111. [Description("Authenticating")]
  112. Authenticating,
  113. [Description("Transport")]
  114. Transport,
  115. [Description("Downloading data")]
  116. Downloading,
  117. [Description("Uploading data")]
  118. Uploading,
  119. [Description("Erasing data")]
  120. Erasing,
  121. [Description("Sending")]
  122. Sending,
  123. [Description("Receiving")]
  124. Receiving
  125. };
  126. /// <summary>
  127. /// Beacon ANT-FS State
  128. /// </summary>
  129. /// !!! Must match the defs in antfsmessage.h
  130. public enum BeaconAntFsState : byte
  131. {
  132. [Description("Link State")]
  133. Link = 0x00,
  134. [Description("Link State")]
  135. Auth = 0x01,
  136. [Description("Link State")]
  137. Trans = 0x02,
  138. [Description("Link State")]
  139. Busy = 0x03,
  140. [Description("Beacon not found")]
  141. BeaconNotFound = 0x80 //Valid states are in range 0x0F, so this avoids all valid states
  142. };
  143. #pragma warning restore 1591
  144. #endregion
  145. #region Variables
  146. bool bInitialized;
  147. bool bResponseThreadExit; // Flag response thread to exit
  148. Thread ResponseThread; // This thread is in charge of monitoring the device for responses and forwarding them to the appropiate handler
  149. Object syncToken = new object();
  150. ushort? usCurrentTransfer = null; // Current transfer being processed
  151. IntPtr unmanagedHostPtr = IntPtr.Zero; // Holder for the pointer to unmanaged ANTFSHost object
  152. IntPtr unmanagedAuthBuffer = IntPtr.Zero; // Holder for pointer to unmanaged buffer for Authentication Response
  153. IntPtr unmanagedAuthSize = IntPtr.Zero; // Holder for pointer to the size of the Authentication Response
  154. GCHandle? ghUploadData = null; // Handle to allow pinning the managed upload buffer.
  155. byte networkNumber = 0; // ANT network number used for the ANT-FS host
  156. IANT_Channel channel; // ANT channel HostChannel is using
  157. dRawChannelResponseHandler rawChannelResponseHandler; // ANT channel response handler
  158. dDeviceNotificationHandler deviceNotificationHandler; // ANT device notification handler
  159. private object onResponseLock = new object();
  160. #endregion
  161. #region Events
  162. private event Action<Response> onResponse_internal;
  163. /// <summary>
  164. /// The ANT-FS host callback event, triggered every time a response is received from the ANT-FS host library
  165. /// </summary>
  166. public event Action<Response> OnResponse
  167. {
  168. add
  169. {
  170. lock (onResponseLock)
  171. {
  172. onResponse_internal += value;
  173. }
  174. }
  175. remove
  176. {
  177. lock (onResponseLock)
  178. {
  179. onResponse_internal -= value;
  180. }
  181. }
  182. }
  183. #endregion
  184. #region DLLImports
  185. [DllImport(ANT_Common.ANT_UNMANAGED_WRAPPER, CallingConvention = CallingConvention.Cdecl)]
  186. private static extern int ANTFSHost_New(ref IntPtr HostPtr);
  187. [DllImport(ANT_Common.ANT_UNMANAGED_WRAPPER, CallingConvention = CallingConvention.Cdecl)]
  188. private static extern int ANTFSHost_Init(IntPtr HostPtr, IntPtr FramerPtr, byte ucANTChannel);
  189. [DllImport(ANT_Common.ANT_UNMANAGED_WRAPPER, CallingConvention = CallingConvention.Cdecl)]
  190. private static extern void ANTFSHost_GetCurrentConfig(IntPtr HostPtr, ref ANTFS_ConfigParameters pstCfgParam);
  191. [DllImport(ANT_Common.ANT_UNMANAGED_WRAPPER, CallingConvention = CallingConvention.Cdecl)]
  192. private static extern int ANTFSHost_SetCurrentConfig(IntPtr HostPtr, ref ANTFS_ConfigParameters pstCfgParam);
  193. [DllImport(ANT_Common.ANT_UNMANAGED_WRAPPER, CallingConvention = CallingConvention.Cdecl)]
  194. private static extern int ANTFSHost_Close(IntPtr HostPtr);
  195. [DllImport(ANT_Common.ANT_UNMANAGED_WRAPPER, CallingConvention = CallingConvention.Cdecl)]
  196. private static extern int ANTFSHost_Delete(IntPtr HostPtr);
  197. [DllImport(ANT_Common.ANT_UNMANAGED_WRAPPER, CallingConvention = CallingConvention.Cdecl)]
  198. private static extern int ANTFSHost_ProcessDeviceNotification(
  199. IntPtr HostPtr,
  200. byte ucCode,
  201. IntPtr pvParameter);
  202. [DllImport(ANT_Common.ANT_UNMANAGED_WRAPPER, CallingConvention = CallingConvention.Cdecl)]
  203. private static extern int ANTFSHost_ProcessMessage(IntPtr ClientPtr, ref ANT_Device.ANTMessage pstANTMessage, ushort usMessageSize);
  204. [DllImport(ANT_Common.ANT_UNMANAGED_WRAPPER, CallingConvention = CallingConvention.Cdecl)]
  205. private static extern int ANTFSHost_SetChannelID(IntPtr HostPtr, byte ucDeviceType, byte ucTransmissionType);
  206. [DllImport(ANT_Common.ANT_UNMANAGED_WRAPPER, CallingConvention = CallingConvention.Cdecl)]
  207. private static extern int ANTFSHost_SetNetworkKey(IntPtr HostPtr, byte networkNumber, byte[] pucKey);
  208. [DllImport(ANT_Common.ANT_UNMANAGED_WRAPPER, CallingConvention = CallingConvention.Cdecl)]
  209. private static extern int ANTFSHost_SetChannelPeriod(IntPtr HostPtr, ushort usChannelPeriod);
  210. [DllImport(ANT_Common.ANT_UNMANAGED_WRAPPER, CallingConvention = CallingConvention.Cdecl)]
  211. private static extern int ANTFSHost_SetProximitySearch(IntPtr HostPtr, byte ucSearchThreshold);
  212. [DllImport(ANT_Common.ANT_UNMANAGED_WRAPPER, CallingConvention = CallingConvention.Cdecl)]
  213. private static extern int ANTFSHost_SetSerialNumber(IntPtr HostPtr, uint ulSerialNumber);
  214. [DllImport(ANT_Common.ANT_UNMANAGED_WRAPPER, CallingConvention = CallingConvention.Cdecl)]
  215. private static extern int ANTFSHost_Cancel(IntPtr HostPtr);
  216. [DllImport(ANT_Common.ANT_UNMANAGED_WRAPPER, CallingConvention = CallingConvention.Cdecl)]
  217. private static extern int ANTFSHost_ClearSearchDeviceList(IntPtr HostPtr);
  218. [DllImport(ANT_Common.ANT_UNMANAGED_WRAPPER, CallingConvention = CallingConvention.Cdecl)]
  219. private static extern ushort ANTFSHost_AddSearchDevice(
  220. IntPtr HostPtr,
  221. ref ANTFS_DeviceParameters pstDeviceSearchMask,
  222. ref ANTFS_DeviceParameters pstDeviceParameters);
  223. [DllImport(ANT_Common.ANT_UNMANAGED_WRAPPER, CallingConvention = CallingConvention.Cdecl)]
  224. private static extern int ANTFSHost_RemoveSearchDevice(IntPtr HostPtr, ushort usHandle);
  225. [DllImport(ANT_Common.ANT_UNMANAGED_WRAPPER, CallingConvention = CallingConvention.Cdecl)]
  226. private static extern byte ANTFSHost_RequestSession(IntPtr HostPtr, byte ucBroadcastFreq, byte ucConnectFreq);
  227. [DllImport(ANT_Common.ANT_UNMANAGED_WRAPPER, CallingConvention = CallingConvention.Cdecl)]
  228. private static extern byte ANTFSHost_SearchForDevice(
  229. IntPtr HostPtr,
  230. byte ucSearchRadioFrequency,
  231. byte ucConnectRadioFrequency,
  232. ushort usRadioChannelID,
  233. bool bUseRequestPage);
  234. [DllImport(ANT_Common.ANT_UNMANAGED_WRAPPER, CallingConvention = CallingConvention.Cdecl)]
  235. private static extern byte ANTFSHost_Disconnect(
  236. IntPtr HostPtr,
  237. ushort usBlackoutTime,
  238. byte ucDisconnectType,
  239. byte ucUndiscoverableDuration,
  240. byte ucAppSpecificDuration);
  241. [DllImport(ANT_Common.ANT_UNMANAGED_WRAPPER, CallingConvention = CallingConvention.Cdecl)]
  242. private static extern byte ANTFSHost_SwitchFrequency(IntPtr HostPtr, byte ucRadioFreq, byte ucChannelPeriod);
  243. [DllImport(ANT_Common.ANT_UNMANAGED_WRAPPER, CallingConvention = CallingConvention.Cdecl)]
  244. private static extern int ANTFSHost_Blackout(
  245. IntPtr HostPtr,
  246. uint ulDeviceID,
  247. ushort usManufacturerID,
  248. ushort usDeviceType,
  249. ushort usBlackoutTime);
  250. [DllImport(ANT_Common.ANT_UNMANAGED_WRAPPER, CallingConvention = CallingConvention.Cdecl)]
  251. private static extern int ANTFSHost_RemoveBlackout(
  252. IntPtr HostPtr,
  253. uint ulDeviceID,
  254. ushort usManufactuerID,
  255. ushort usDeviceType);
  256. [DllImport(ANT_Common.ANT_UNMANAGED_WRAPPER, CallingConvention = CallingConvention.Cdecl)]
  257. private static extern int ANTFSHost_ClearBlackoutList(IntPtr HostPtr);
  258. [DllImport(ANT_Common.ANT_UNMANAGED_WRAPPER, CallingConvention = CallingConvention.Cdecl)]
  259. private static extern int ANTFSHost_EnablePing(IntPtr HostPtr, bool bEnable);
  260. [DllImport(ANT_Common.ANT_UNMANAGED_WRAPPER, CallingConvention = CallingConvention.Cdecl)]
  261. private static extern byte ANTFSHost_Authenticate(
  262. IntPtr HostPtr,
  263. byte ucAuthenticationType,
  264. byte[] pucAuthString,
  265. byte ucLength,
  266. IntPtr pucResponseBuffer, // Buffer allocated in unmanaged heap
  267. IntPtr pucResponseBufferSize, // Buffer size allocated in unmanaged heap
  268. uint ulResponseTimeut);
  269. [DllImport(ANT_Common.ANT_UNMANAGED_WRAPPER, CallingConvention = CallingConvention.Cdecl)]
  270. private static extern byte ANTFSHost_Download(
  271. IntPtr HostPtr,
  272. ushort usFileIndex,
  273. uint ulDataOffset,
  274. uint ulMaxDataLength,
  275. uint ulMaxBlockSize);
  276. [DllImport(ANT_Common.ANT_UNMANAGED_WRAPPER, CallingConvention = CallingConvention.Cdecl)]
  277. private static extern byte ANTFSHost_EraseData(IntPtr HostPtr, ushort usFileIndex);
  278. [DllImport(ANT_Common.ANT_UNMANAGED_WRAPPER, CallingConvention = CallingConvention.Cdecl)]
  279. private static extern byte ANTFSHost_Upload(
  280. IntPtr HostPtr,
  281. ushort usFileIndex,
  282. uint ulDataOffset,
  283. uint ulDataLength,
  284. IntPtr pvData, // Pointer is cached by unmanaged code for use after this call has ended, so pointer needs to be pinned
  285. bool bForceOffset);
  286. [DllImport(ANT_Common.ANT_UNMANAGED_WRAPPER, CallingConvention = CallingConvention.Cdecl)]
  287. private static extern int ANTFSHost_GetEnabled(IntPtr HostPtr);
  288. [DllImport(ANT_Common.ANT_UNMANAGED_WRAPPER, CallingConvention = CallingConvention.Cdecl)]
  289. private static extern byte ANTFSHost_GetChannelNumber(IntPtr HostPtr);
  290. [DllImport(ANT_Common.ANT_UNMANAGED_WRAPPER, CallingConvention = CallingConvention.Cdecl)]
  291. private static extern byte ANTFSHost_GetStatus(IntPtr HostPtr);
  292. [DllImport(ANT_Common.ANT_UNMANAGED_WRAPPER, CallingConvention = CallingConvention.Cdecl)]
  293. private static extern byte ANTFSHost_GetConnectedDeviceBeaconAntfsState(IntPtr HostPtr);
  294. [DllImport(ANT_Common.ANT_UNMANAGED_WRAPPER, CallingConvention = CallingConvention.Cdecl)]
  295. private static extern int ANTFSHost_GetFoundDeviceParameters(
  296. IntPtr HostPtr,
  297. ref ANTFS_DeviceParameters pstDeviceParameters,
  298. [MarshalAs(UnmanagedType.LPArray)] byte[] pucFriendlyName,
  299. ref byte pucBufferSize);
  300. [DllImport(ANT_Common.ANT_UNMANAGED_WRAPPER, CallingConvention = CallingConvention.Cdecl)]
  301. private static extern int ANTFSHost_GetFoundDeviceChannelID(
  302. IntPtr HostPtr,
  303. ref ushort pusDeviceNumber,
  304. ref byte pucDeviceType,
  305. ref byte pucTransmitType);
  306. [DllImport(ANT_Common.ANT_UNMANAGED_WRAPPER, CallingConvention = CallingConvention.Cdecl)]
  307. private static extern int ANTFSHost_GetDownloadStatus(
  308. IntPtr HostPtr,
  309. ref uint pulByteProgress,
  310. ref uint pulTotalLength);
  311. [DllImport(ANT_Common.ANT_UNMANAGED_WRAPPER, CallingConvention = CallingConvention.Cdecl)]
  312. private static extern uint ANTFSHost_GetTransferSize(IntPtr HostPtr);
  313. [DllImport(ANT_Common.ANT_UNMANAGED_WRAPPER, CallingConvention = CallingConvention.Cdecl)]
  314. private static extern int ANTFSHost_GetTransferData(
  315. IntPtr HostPtr,
  316. ref uint pulDataSize,
  317. [MarshalAs(UnmanagedType.LPArray)] byte[] pucData);
  318. [DllImport(ANT_Common.ANT_UNMANAGED_WRAPPER, CallingConvention = CallingConvention.Cdecl)]
  319. private static extern int ANTFSHost_GetUploadStatus(
  320. IntPtr HostPtr,
  321. ref uint pulByteProgress,
  322. ref uint pulTotalLength);
  323. [DllImport(ANT_Common.ANT_UNMANAGED_WRAPPER, CallingConvention = CallingConvention.Cdecl)]
  324. private static extern int ANTFSHost_GetVersion(
  325. IntPtr HostPtr,
  326. [MarshalAs(UnmanagedType.LPArray)] byte[] pucVersion,
  327. byte ucBufferSize);
  328. [DllImport(ANT_Common.ANT_UNMANAGED_WRAPPER, CallingConvention = CallingConvention.Cdecl)]
  329. private static extern byte ANTFSHost_WaitForResponse(IntPtr HostPtr, uint ulMilliseconds);
  330. #endregion
  331. #region Constructor, Finalizer & Dispose
  332. /// <summary>
  333. /// Creates ANT-FS object, response thread, and allocates unmanaged buffer for use with library
  334. /// </summary>
  335. public ANTFS_HostChannel(IANT_Channel channel_)
  336. {
  337. try
  338. {
  339. channel = channel_;
  340. // Create the ANT-FS host object
  341. if (ANTFSHost_New(ref unmanagedHostPtr) == 0)
  342. throw new ANTFS_Exception("Unable to initialize ANT-FS Host");
  343. if (ANTFSHost_Init(unmanagedHostPtr, channel.getUnmgdFramer(), channel.getChannelNum()) == 0)
  344. throw new ANTFS_Exception("Unable to initialize host");
  345. bInitialized = true;
  346. rawChannelResponseHandler = new dRawChannelResponseHandler( ( msg, size ) => ANTFSHost_ProcessMessage( unmanagedHostPtr, ref msg, size ) );
  347. deviceNotificationHandler = new dDeviceNotificationHandler( channel_DeviceNotification );
  348. channel.rawChannelResponse += rawChannelResponseHandler;
  349. channel.DeviceNotification += deviceNotificationHandler;
  350. // Allocate buffer to hold authentication response in native heap
  351. try
  352. {
  353. this.unmanagedAuthBuffer = Marshal.AllocHGlobal(Byte.MaxValue);
  354. this.unmanagedAuthSize = Marshal.AllocHGlobal(1);
  355. }
  356. catch (Exception ex)
  357. {
  358. throw new ANTFS_Exception("Unable to initialize ANT-FS Host: " + ex.Message);
  359. }
  360. // Setup thread to handle responses from the ANT-FS library
  361. bResponseThreadExit = false;
  362. ResponseThread = new Thread(new ThreadStart(ResponseThreadHandler));
  363. ResponseThread.Name = "ANT-FS Host Response Thread";
  364. ResponseThread.IsBackground = true; // Make this a background thread so it will terminate when main program closes
  365. ResponseThread.Start();
  366. }
  367. catch
  368. {
  369. this.Dispose();
  370. throw;
  371. }
  372. }
  373. /// <summary>
  374. /// Destructor closes all opened resources
  375. /// </summary>
  376. ~ANTFS_HostChannel()
  377. {
  378. Dispose(false);
  379. }
  380. /// <summary>
  381. /// Dispose method for explicit resource cleanup
  382. /// </summary>
  383. public void Dispose()
  384. {
  385. Dispose(true);
  386. GC.SuppressFinalize(this);
  387. }
  388. /// <summary>
  389. /// Copy back the current configuration parameters
  390. /// </summary>
  391. public void GetCurrentConfig(ref ANTFS_ConfigParameters stConfigParamaters)
  392. {
  393. if (!bInitialized)
  394. throw new ObjectDisposedException("ANTFSHost object has been disposed");
  395. ANTFSHost_GetCurrentConfig(unmanagedHostPtr, ref stConfigParamaters);
  396. }
  397. /// <summary>
  398. /// Set current configuration parameters
  399. /// </summary>
  400. public bool SetCurrentConfig(ref ANTFS_ConfigParameters stConfigParamaters)
  401. {
  402. if (!bInitialized)
  403. throw new ObjectDisposedException("ANTFSHost object has been disposed");
  404. return 0 != ANTFSHost_SetCurrentConfig(unmanagedHostPtr, ref stConfigParamaters);
  405. }
  406. /// <summary>
  407. /// Close connection, and release all resources
  408. /// </summary>
  409. protected virtual void Dispose(bool bDisposing)
  410. {
  411. if (bInitialized)
  412. {
  413. if (bDisposing)
  414. {
  415. // Dispose of other managed resources here
  416. channel.rawChannelResponse -= rawChannelResponseHandler;
  417. channel.DeviceNotification -= deviceNotificationHandler;
  418. }
  419. // Terminate the response handler thread
  420. if (ResponseThread.IsAlive)
  421. {
  422. bResponseThreadExit = true;
  423. if (!ResponseThread.Join(3000))
  424. ResponseThread.Abort();
  425. }
  426. if (unmanagedHostPtr != IntPtr.Zero)
  427. {
  428. ANTFSHost_Cancel(unmanagedHostPtr); // Cancel any pending operations
  429. ANTFSHost_Close(unmanagedHostPtr); // Close object (incl. unmanaged thread)
  430. ANTFSHost_Delete(unmanagedHostPtr); // Delete unmanaged object
  431. unmanagedHostPtr = IntPtr.Zero;
  432. }
  433. // Free memory allocated in native heap
  434. if (unmanagedAuthBuffer != IntPtr.Zero)
  435. Marshal.FreeHGlobal(unmanagedAuthBuffer);
  436. if (unmanagedAuthSize != IntPtr.Zero)
  437. Marshal.FreeHGlobal(unmanagedAuthSize);
  438. // If upload buffer is still pinned, unpin it
  439. ReleaseUploadBuffer();
  440. bInitialized = false;
  441. }
  442. }
  443. /// <summary>
  444. /// Unpin and release buffer holding unmanaged data
  445. /// </summary>
  446. private void ReleaseUploadBuffer()
  447. {
  448. if (ghUploadData != null)
  449. {
  450. ghUploadData.Value.Free();
  451. ghUploadData = null;
  452. }
  453. }
  454. #endregion
  455. #region ANT-FS Host Functions
  456. void channel_DeviceNotification(ANT_Device.DeviceNotificationCode notification, object notificationInfo)
  457. {
  458. ANTFSHost_ProcessDeviceNotification(unmanagedHostPtr, (byte) notification, IntPtr.Zero);
  459. //TODO Once we define an object for a notification type, marshal it - pin it, etc
  460. }
  461. /// <summary>
  462. /// Set the channel ID of the ANT-FS host
  463. /// If this function is not used to explicitly configure the channel ID, the ANT-FS host will use the following defaults:
  464. /// Device type: 1
  465. /// Transmission type: 5
  466. /// </summary>
  467. /// <param name="ucDeviceType">Device type to assign to channel (ANT Channel ID). Set to 0 for receiver wild card matching</param>
  468. /// <param name="ucTransmissionType">Transmission type to assign to channel (ANT Channel ID). Set to 0 for receiver wild card matching</param>
  469. public void SetChannelID(byte ucDeviceType, byte ucTransmissionType)
  470. {
  471. if (!bInitialized)
  472. throw new ObjectDisposedException("ANTFSHost object has been disposed");
  473. ANTFSHost_SetChannelID(unmanagedHostPtr, ucDeviceType, ucTransmissionType);
  474. }
  475. /// <summary>
  476. /// Set the channel period of the ANT-FS host.
  477. /// If this function is not used to explicitly configure the channel period, the ANT-FS host will use the default value of 8Hz
  478. /// </summary>
  479. /// <param name="usChannelPeriod">Desired period in seconds * 32768</param>
  480. public void SetChannelPeriod(ushort usChannelPeriod)
  481. {
  482. if (!bInitialized)
  483. throw new ObjectDisposedException("ANTFSHost object has been disposed");
  484. ANTFSHost_SetChannelPeriod(unmanagedHostPtr, usChannelPeriod);
  485. }
  486. /// <summary>
  487. /// Set the network key for the ANT-FS host
  488. /// If this function is not used to explicitly configure the network key, the ANT-FS host will use the
  489. /// ANT-FS network key, as set in the base ANT Library
  490. /// </summary>
  491. /// <param name="netNumber">network number</param>
  492. /// <param name="networkKey">8-byte network key</param>
  493. public void SetNetworkKey(byte netNumber, byte[] networkKey)
  494. {
  495. if (!bInitialized)
  496. throw new ObjectDisposedException("ANTFSHost object has been disposed");
  497. if (networkKey.Length != 8)
  498. throw new ANTFS_Exception("Network key must be 8 bytes");
  499. networkNumber = netNumber;
  500. ANTFSHost_SetNetworkKey(unmanagedHostPtr, networkNumber, networkKey);
  501. }
  502. /// <summary>
  503. /// Sets the value for the proximity bin setting for searching.
  504. /// If applying this value fails when attempting to start search,
  505. /// it is ignored to maintain compatibility with devices that
  506. /// do not support this feature. This means that a real failure can occur
  507. /// on a device that actually does support it, and it will be missed. The
  508. /// debug log will show if this command fails.
  509. /// </summary>
  510. /// <param name="searchThreshold">Desired proximity bin from 0-10</param>
  511. public void SetProximitySearch(byte searchThreshold)
  512. {
  513. if (!bInitialized)
  514. throw new ObjectDisposedException("ANTFSHost object has been disposed");
  515. if(searchThreshold > 10)
  516. throw new ANTFS_Exception("Proximity search bin must be between 0 - 10");
  517. ANTFSHost_SetProximitySearch(unmanagedHostPtr, searchThreshold);
  518. }
  519. /// <summary>
  520. /// Sets the serial number of the host device.
  521. /// </summary>
  522. /// <param name="serialNumber">4-byte host serial number</param>
  523. public void SetSerialNumber(uint serialNumber)
  524. {
  525. if (!bInitialized)
  526. throw new ObjectDisposedException("ANTFSHost object has been disposed");
  527. ANTFSHost_SetSerialNumber(unmanagedHostPtr, serialNumber);
  528. }
  529. /// <summary>
  530. /// Clears the internal search device list
  531. /// </summary>
  532. public void ClearSearchDeviceList()
  533. {
  534. if (!bInitialized)
  535. throw new ObjectDisposedException("ANTFSHost object has been disposed");
  536. ANTFSHost_ClearSearchDeviceList(unmanagedHostPtr);
  537. }
  538. /// <overloads>
  539. /// Adds a set of parameters for which to search to the internal search device list
  540. /// </overloads>
  541. /// <summary>
  542. /// Adds a set of parameters for which to search to the internal search device list, explicitly specifying
  543. /// all parameters and search mask.
  544. /// </summary>
  545. /// <param name="stSearchMask">Device parameter search mask. Set a member to zero (0) to wildcard search for it.
  546. /// Otherwise, set the bits that you want to be matched to 1 in each member.
  547. /// Note that the default search masks or wildcards should normally be applied to the ucStatusByte1 and ucStatusByte2
  548. /// members of the search mask. Setting bits outside the masks, specially reserved bits, may lead to undesired
  549. /// behavior.</param>
  550. /// <param name="stDeviceParameters">Device Parameters to include in a search. Set the member to the desired search value.
  551. /// A member in this structure is ignored if the associated member in the Search Mask is set to zero (0) for wildcard.</param>
  552. /// <returns>A handle to the search device entry. If the return value is zero (0), the function failed adding the device entry.
  553. /// This means that the device list is already full</returns>
  554. public ushort AddSearchDevice(ref ANTFS_DeviceParameters stSearchMask, ref ANTFS_DeviceParameters stDeviceParameters)
  555. {
  556. if (!bInitialized)
  557. throw new ObjectDisposedException("ANTFSHost object has been disposed");
  558. return(ANTFSHost_AddSearchDevice(unmanagedHostPtr, ref stSearchMask, ref stDeviceParameters));
  559. }
  560. /// <summary>
  561. /// Adds a set of parameters for which to search to the internal search device list, matching only the Device ID,
  562. /// Manufacturer ID and Device Type
  563. /// </summary>
  564. /// <param name="ulDeviceID">Device ID to match</param>
  565. /// <param name="usManufacturerID">Manufacturer ID to match</param>
  566. /// <param name="usDeviceType">Device type to match</param>
  567. /// <returns>A handle to the search device entry. If the return value is zero (0), the function failed adding the device entry.
  568. /// This means that the device list is already full</returns>
  569. public ushort AddSearchDevice(uint ulDeviceID, ushort usManufacturerID, ushort usDeviceType)
  570. {
  571. if (!bInitialized)
  572. throw new ObjectDisposedException("ANTFSHost object has been disposed");
  573. ANTFS_DeviceParameters stDeviceParams;
  574. ANTFS_DeviceParameters stSearchMask;
  575. stSearchMask.DeviceID = (ulDeviceID != 0) ? (uint) 0xFFFFFFFF : (uint) 0; // Match entire Device ID, if set
  576. stSearchMask.ManufacturerID = (usManufacturerID != 0) ? (ushort) 0xFFFF : (ushort) 0; // Match entire Mfg ID, if set
  577. stSearchMask.DeviceType = (usDeviceType != 0) ? (ushort) 0xFFFF : (ushort) 0; // Match entire Device Type, if set
  578. stSearchMask.AuthenticationType = 0; // Ignore auth type
  579. stSearchMask.StatusByte1 = 0; // Ignore status 1 byte
  580. stSearchMask.StatusByte2 = 0; // Ignore status 2 byte
  581. // TODO: Fix wildcards
  582. stDeviceParams.DeviceID = ulDeviceID;
  583. stDeviceParams.ManufacturerID = usManufacturerID;
  584. stDeviceParams.DeviceType = usDeviceType;
  585. stDeviceParams.AuthenticationType = 0;
  586. stDeviceParams.StatusByte1 = 0;
  587. stDeviceParams.StatusByte2 = 0;
  588. return (ANTFSHost_AddSearchDevice(unmanagedHostPtr, ref stSearchMask, ref stDeviceParams));
  589. }
  590. /// <summary>
  591. /// Removes a device entry from the internal search list
  592. /// </summary>
  593. /// <param name="usDeviceHandle">Handle to the device entry to be removed from the list</param>
  594. public void RemoveSearchDevice(ushort usDeviceHandle)
  595. {
  596. if (!bInitialized)
  597. throw new ObjectDisposedException("ANTFSHost object has been disposed");
  598. ANTFSHost_RemoveSearchDevice(unmanagedHostPtr, usDeviceHandle);
  599. }
  600. /// <summary>
  601. /// Requests an ANT-FS session, from an already connected broadcast device.
  602. /// </summary>
  603. /// <param name="ucBroadcastRadioFrequency">The frequency of currently connected device
  604. /// This frequency is calculated as (ucSearchRadioFrequency_ * 1 MHz + 2400 MHz).</param>
  605. /// <param name="ucConnectRadioFrequency">The frequency on which the connection communication will occur.
  606. /// This frequency is calculated as (ucSearchRadioFrequency_ * 1 MHz + 2400 MHz).</param>
  607. public void RequestSession(byte ucBroadcastRadioFrequency, byte ucConnectRadioFrequency)
  608. {
  609. if (!bInitialized)
  610. throw new ObjectDisposedException("ANTFSHost object has been disposed");
  611. ReturnCode theReturn = (ReturnCode)ANTFSHost_RequestSession(unmanagedHostPtr, ucBroadcastRadioFrequency, ucConnectRadioFrequency);
  612. if (theReturn != ReturnCode.Pass)
  613. throw new ANTFS_RequestFailed_Exception("RequestSession", theReturn);
  614. }
  615. /// <overloads>
  616. /// Begins a search for ANT-FS remote devices
  617. /// Throws an exception if the library is in the wrong state or busy with another request
  618. /// </overloads>
  619. /// <summary>
  620. /// Begins a search for ANT-FS remote devices
  621. /// Throws an exception if the library is in the wrong state or busy with another request
  622. /// </summary>
  623. /// <param name="ucSearchRadioFrequency">The frequency on which to search for devices.
  624. /// This frequency is calculated as (ucSearchRadioFrequency_ * 1 MHz + 2400 MHz).</param>
  625. /// <param name="ucConnectRadioFrequency">The frequency on which the connection communication will occur.
  626. /// This frequency is calculated as (ucSearchRadioFrequency_ * 1 MHz + 2400 MHz)</param>
  627. /// <param name="usRadioChannelID">Device number to assign to channel (ANT Channel ID)</param>
  628. /// <param name="bUseRequestPage">Selects whether to search for broadcast devices, and request the beacon</param>
  629. public void SearchForDevice(byte ucSearchRadioFrequency, byte ucConnectRadioFrequency, ushort usRadioChannelID, bool bUseRequestPage)
  630. {
  631. if (!bInitialized)
  632. throw new ObjectDisposedException("ANTFSHost object has been disposed");
  633. ReturnCode theReturn = (ReturnCode) ANTFSHost_SearchForDevice(unmanagedHostPtr, ucSearchRadioFrequency, ucConnectRadioFrequency, usRadioChannelID, bUseRequestPage);
  634. if (theReturn != ReturnCode.Pass)
  635. {
  636. throw new ANTFS_RequestFailed_Exception("Search", theReturn);
  637. }
  638. }
  639. /// <summary>
  640. /// Begins a search for ANT-FS remote devices. The search will continue until a device is found,
  641. /// the Cancel() function is called, an error occurs, or the library is closed.
  642. /// Throws an exception if the library is in the wrong state or busy with another request
  643. /// </summary>
  644. /// <param name="ucSearchRadioFrequency">The frequency on which to search for devices.
  645. /// This frequency is calculated as (ucSearchRadioFrequency_ * 1 MHz + 2400 MHz).</param>
  646. /// <param name="ucConnectRadioFrequency">The frequency on which the connection communication will occur.
  647. /// This frequency is calculated as (ucSearchRadioFrequency_ * 1 MHz + 2400 MHz)</param>
  648. /// <param name="usRadioChannelID">Device number to assign to channel (ANT Channel ID)</param>
  649. public void SearchForDevice(byte ucSearchRadioFrequency, byte ucConnectRadioFrequency, ushort usRadioChannelID)
  650. {
  651. SearchForDevice(ucSearchRadioFrequency, ucConnectRadioFrequency, usRadioChannelID, false);
  652. }
  653. /// <summary>
  654. /// Begins a search for ANT-FS remote devices, using the default ANT-FS search frequency (2.450GHz) and
  655. /// an adaptive frequency hopping scheme when the connection is established.
  656. /// The host will continue to search for devices until a device is found, the Cancel() function is called,
  657. /// an error occurs, or the library is closed.
  658. /// Throws an exception if the library is in the wrong state or busy with another request
  659. /// </summary>
  660. public void SearchForDevice()
  661. {
  662. SearchForDevice((byte)RadioFrequency.ANTFSNetwork, (byte) RadioFrequency.Auto, 0, false);
  663. }
  664. /// <overloads>
  665. /// Disconnect from a remote device, going back to the state specified by the disconnect type.
  666. /// Throws an exception if the library is in the wrong state or busy with another request
  667. /// </overloads>
  668. /// <summary>
  669. /// Disconnect from a remote device. Optionally put that device on a blackout
  670. /// list for a period of time
  671. /// Throws an exception if the library is in the wrong state or busy with another request
  672. /// </summary>
  673. /// <param name="usBlackoutTime">Number of seconds the device ID should remain on
  674. /// the blackout list. If set to BlackoutTime.None, the device is not put in a blackout list.
  675. /// If set to BlackoutTime.Infinite, the device will remain in the list until explicitly
  676. /// removed or until the blackout list is reset</param>
  677. /// <param name="disconnectType">Disconnect Command type</param>
  678. /// <param name="undiscoverableTimeDuration">Time, in 30 seconds increments, the client
  679. /// device will remain undiscoverable after disconnect has been requested. Set to 0 to disable.</param>
  680. /// <param name="undiscoverableAppSpecificDuration">Application specific duration the client
  681. /// shall remain undiscoverable after disconnection</param>
  682. public void Disconnect(ushort usBlackoutTime, byte disconnectType, byte undiscoverableTimeDuration, byte undiscoverableAppSpecificDuration)
  683. {
  684. if (!bInitialized)
  685. throw new ObjectDisposedException("ANTFSHost object has been disposed");
  686. ReturnCode theReturn = (ReturnCode) ANTFSHost_Disconnect(unmanagedHostPtr, usBlackoutTime, (byte) disconnectType, undiscoverableTimeDuration, undiscoverableAppSpecificDuration);
  687. if (theReturn != ReturnCode.Pass)
  688. throw new ANTFS_RequestFailed_Exception("Disconnect", theReturn);
  689. }
  690. /// <summary>
  691. /// Disconnect from a remote device, without putting it in the blackout list
  692. /// Throws an exception if the library is in the wrong state or busy with another request
  693. /// </summary>
  694. public void Disconnect()
  695. {
  696. Disconnect((ushort) BlackoutTime.None, 0, 0, 0);
  697. }
  698. /// <summary>
  699. /// Request the connected remote device to switch to the specified
  700. /// radio frequency and channel period
  701. /// </summary>
  702. /// <param name="ucRadioFrequency">New radio frequency</param>
  703. /// <param name="beaconPeriod">New beacon period</param>
  704. public void SwitchFrequency(byte ucRadioFrequency, BeaconPeriod beaconPeriod)
  705. {
  706. if (!bInitialized)
  707. throw new ObjectDisposedException("ANTFSHost object has been disposed");
  708. ReturnCode theReturn = (ReturnCode)ANTFSHost_SwitchFrequency(unmanagedHostPtr, ucRadioFrequency, (byte) beaconPeriod);
  709. if (theReturn != ReturnCode.Pass)
  710. throw new ANTFS_RequestFailed_Exception("SwitchFrequency", theReturn);
  711. }
  712. /// <summary>
  713. /// Puts the device on a blackout list for a period of time.
  714. /// A device in the blackout list will not show up in any search results.
  715. /// A wildcard parameter (0) is not allowed for any of the device ID parameters.
  716. /// An exception is thrown if the device can not be added to the blackout list,
  717. /// either because the list is full, or the device ID is invalid
  718. /// </summary>
  719. /// <param name="ulDeviceID">The device ID of a specific device</param>
  720. /// <param name="usManufacturerID">The specific manufacturer ID</param>
  721. /// <param name="usDeviceType">The specific device type</param>
  722. /// <param name="usBlackoutTime">Number of seconds the device ID should remain on
  723. /// the blackout list. If set to BlackoutTime.None, the device is not put in a blackout list.
  724. /// If set to BlackoutTime.Infinite, the device will remain in the list until explicitly
  725. /// removed or until the blackout list is reset</param>
  726. public void Blackout(uint ulDeviceID, ushort usManufacturerID, ushort usDeviceType, ushort usBlackoutTime)
  727. {
  728. if (!bInitialized)
  729. throw new ObjectDisposedException("ANTFSHost object has been disposed");
  730. if ((ulDeviceID == 0) || (usManufacturerID == 0) || (usDeviceType == 0))
  731. throw new ANTFS_RequestFailed_Exception("Unable to add device to blackout list, wildcards not allowed");
  732. if (ANTFSHost_Blackout(unmanagedHostPtr, ulDeviceID, usManufacturerID, usDeviceType, usBlackoutTime) == 0)
  733. throw new ANTFS_RequestFailed_Exception("Unable to add device to blackout list, list is full"); // List size is 2048, so this should be very rare
  734. }
  735. /// <summary>
  736. /// Remove the device from the blackout list
  737. /// A wildcard parameter (0) is not allowed for any of the device ID parameters,
  738. /// and will result in returning False.
  739. /// Throws an exception if the device can not be removed from the list (e.g. device
  740. /// was not in list)
  741. /// </summary>
  742. /// <param name="ulDeviceID">The device ID of a specific device</param>
  743. /// <param name="usManufacturerID">The specific manufacturer ID</param>
  744. /// <param name="usDeviceType">The specific device type</param>
  745. public void RemoveBlackout(uint ulDeviceID, ushort usManufacturerID, ushort usDeviceType)
  746. {
  747. if (!bInitialized)
  748. throw new ObjectDisposedException("ANTFSHost object has been disposed");
  749. if (ANTFSHost_RemoveBlackout(unmanagedHostPtr, ulDeviceID, usManufacturerID, usDeviceType) == 0)
  750. throw new ANTFS_RequestFailed_Exception("Unable to remove device from blackout list");
  751. }
  752. /// <summary>
  753. /// Clears the blackout list
  754. /// </summary>
  755. public void ClearBlackoutList()
  756. {
  757. if (!bInitialized)
  758. throw new ObjectDisposedException("ANTFSHost object has been disposed");
  759. ANTFSHost_ClearBlackoutList(unmanagedHostPtr);
  760. }
  761. /// <summary>
  762. /// Enables ping message to be sent to the remote device periodically.
  763. /// This can be used to keep the remote device from timing out during operations
  764. /// that wait for user input.
  765. /// </summary>
  766. /// <param name="bEnable">Periodic ping enable</param>
  767. public void EnablePing(bool bEnable)
  768. {
  769. if (!bInitialized)
  770. throw new ObjectDisposedException("ANTFSHost object has been disposed");
  771. ANTFSHost_EnablePing(unmanagedHostPtr, bEnable);
  772. }
  773. /// <overloads>
  774. /// Requests to pair with the connected remote device
  775. /// Throws an exception if the library is in the wrong state or busy with another request
  776. /// </overloads>
  777. /// <summary>
  778. /// Request to pair with the connected remote device
  779. /// Throws an exception if the library is in the wrong state or busy with another request
  780. /// </summary>
  781. /// <param name="authType">The type of authentication to execute on the remote device</param>
  782. /// <param name="authString">String to be used in conjunction with the particular authentication type (e.g. passkey)</param>
  783. /// <param name="ulTimeout">Number of miliseconds to wait for a response after the authenticate command is set</param>
  784. public void Authenticate(AuthenticationType authType, byte[] authString, uint ulTimeout)
  785. {
  786. if (!bInitialized)
  787. throw new ObjectDisposedException("ANTFSHost object has been disposed");
  788. Marshal.WriteByte(unmanagedAuthSize, Byte.MaxValue); // Initialize size to max value
  789. ReturnCode theReturn = (ReturnCode) ANTFSHost_Authenticate(unmanagedHostPtr, (byte)authType, authString, (byte)authString.Length, unmanagedAuthBuffer, unmanagedAuthSize, ulTimeout);
  790. if (theReturn != ReturnCode.Pass)
  791. throw new ANTFS_RequestFailed_Exception("Authentication", theReturn);
  792. }
  793. /// <summary>
  794. /// Request to pair with the connected remote device
  795. /// Throws an exception if the library is in the wrong state or busy with another request
  796. /// </summary>
  797. /// <param name="authType">The type of authentication to execute on the remote device</param>
  798. /// <param name="authString">String to be used in conjunction with the particular authentication type (e.g. friendly name)</param>
  799. /// <param name="ulTimeout">Number of miliseconds to wait for a response after the authenticate command is sent</param>
  800. public void Authenticate(AuthenticationType authType, string authString, uint ulTimeout)
  801. {
  802. byte[] myFriendlyName = Common.ConvertToByteArray(authString);
  803. Authenticate(authType, myFriendlyName, ulTimeout);
  804. }
  805. /// <summary>
  806. /// Request to pair with the connected remote device, without specifying an authentication string
  807. /// Throws an exception if the library is in the wrong state or busy with another request
  808. /// </summary>
  809. /// <param name="authType">The type of authentication to execute on the remote device</param>
  810. /// <param name="ulTimeout">Number of miliseconds to wait for a response after the authenticate command is sent</param>
  811. public void Authenticate(AuthenticationType authType, uint ulTimeout)
  812. {
  813. byte[] emptyString = new byte[0];
  814. Authenticate(authType, emptyString, ulTimeout);
  815. }
  816. /// <overloads>
  817. /// Request a download of a file from the authenticated device
  818. /// Throws an exception if the library is in the wrong state or busy with another request
  819. /// </overloads>
  820. /// <summary>
  821. /// Request a download of a file from the authenticated device
  822. /// Throws an exception if the library is in the wrong state or busy with another request
  823. /// </summary>
  824. /// <param name="usFileIndex">The file number to be downloaded</param>
  825. /// <param name="ulDataOffset">Byte offset from where to begin transferring the data</param>
  826. /// <param name="ulMaxDataLength">Maximum number of bytes to download. Set to zero (0) if
  827. /// the host does not wish to limit the total size of the download</param>
  828. /// <param name="ulMaxBlockSize">Maximum number of bytes to download in a single block. Set
  829. /// to zero (0) if the host does not wish to limit the block size</param>
  830. public void Download(ushort usFileIndex, uint ulDataOffset, uint ulMaxDataLength, uint ulMaxBlockSize)
  831. {
  832. if (!bInitialized)
  833. throw new ObjectDisposedException("ANTFSHost object has been disposed");
  834. ReturnCode theReturn = (ReturnCode) ANTFSHost_Download(unmanagedHostPtr, usFileIndex, ulDataOffset, ulMaxDataLength, ulMaxBlockSize);
  835. if (theReturn == ReturnCode.Pass)
  836. usCurrentTransfer = usFileIndex; // Track current transfer
  837. else
  838. throw new ANTFS_RequestFailed_Exception("Download", theReturn);
  839. }
  840. /// <summary>
  841. /// Request a download of a file from the authenticated device
  842. /// Throws an exception if the library is in the wrong state or busy with another request
  843. /// </summary>
  844. /// <param name="usFileIndex">The file number to be downloaded</param>
  845. /// <param name="ulDataOffset">Byte offset from where to begin transferring the data</param>
  846. /// <param name="ulMaxDataLength">Maximum number of bytes to download. Set to zero (0) if
  847. /// the host does not wish to limit the total size of the download</param>
  848. public void Download(ushort usFileIndex, uint ulDataOffset, uint ulMaxDataLength)
  849. {
  850. Download(usFileIndex, ulDataOffset, ulMaxDataLength, 0);
  851. }
  852. /// <summary>
  853. /// Requests a download of the directory file from the authenticated device
  854. /// Throws an exception if the library is in the wrong state or busy with another request
  855. /// </summary>
  856. public void DownloadDirectory()
  857. {
  858. Download(0, 0, 0, 0);
  859. }
  860. /// <summary>
  861. /// Requests the erasure of a file on the authenticated remote device
  862. /// Throws an exception if the library is in the wrong state or busy with another request
  863. /// </summary>
  864. /// <param name="usFileIndex">The file number of the file to erase</param>
  865. public void EraseData(ushort usFileIndex)
  866. {
  867. if (!bInitialized)
  868. throw new ObjectDisposedException("ANTFSHost object has been disposed");
  869. ReturnCode theReturn = (ReturnCode) ANTFSHost_EraseData(unmanagedHostPtr, usFileIndex);
  870. if (theReturn == ReturnCode.Pass)
  871. usCurrentTransfer = usFileIndex;
  872. else
  873. throw new ANTFS_RequestFailed_Exception("Erase", theReturn);
  874. }
  875. /// <overloads>
  876. /// Requests an upload of a file to the authenticated device
  877. /// Throws an exception if the library is in the wrong state or busy with another request
  878. /// </overloads>
  879. /// <summary>
  880. /// Requests an upload of a file to the authenticated device
  881. /// Throws an exception if the library is in the wrong state or busy with another request
  882. /// </summary>
  883. /// <param name="usFileIndex">The file number to be uploaded</param>
  884. /// <param name="ulDataOffset">The byte offset from where to begin transferring the data</param>
  885. /// <param name="uploadData">Buffer where data to be sent is stored</param>
  886. /// <param name="bForceOffset">Force the offset</param>
  887. public void Upload(ushort usFileIndex, uint ulDataOffset, byte[] uploadData, bool bForceOffset)
  888. {
  889. if (!bInitialized)
  890. throw new ObjectDisposedException("ANTFSHost object has been disposed");
  891. ReleaseUploadBuffer(); // If we had not freed the handle, do it now
  892. ghUploadData = GCHandle.Alloc(uploadData, GCHandleType.Pinned); // Pin managed buffer
  893. IntPtr pvData = ghUploadData.Value.AddrOfPinnedObject(); // Get address of managed buffer
  894. if (pvData == IntPtr.Zero)
  895. {
  896. throw new ANTFS_Exception("Upload request failed: Unable to allocate response buffer");
  897. }
  898. else
  899. {
  900. ReturnCode theReturn = (ReturnCode)ANTFSHost_Upload(unmanagedHostPtr, usFileIndex, ulDataOffset, (uint)uploadData.Length, pvData, bForceOffset);
  901. if (theReturn == ReturnCode.Pass)
  902. {
  903. usCurrentTransfer = usFileIndex; // Track current transfer
  904. }
  905. else
  906. {
  907. // If the request was not successful, we should free the handle here
  908. // Otherwise, buffer needs to remain pinned while upload completes (until UploadPass, UploadFail ...)
  909. // GCHandle will be freed when we receive an ANT-FS response, or the application is terminated
  910. ReleaseUploadBuffer();
  911. throw new ANTFS_RequestFailed_Exception("Upload", theReturn);
  912. }
  913. }
  914. }
  915. /// <summary>
  916. /// Requests a new upload of a file to the authenticated device
  917. /// Throws an exception if the library is in the wrong state or busy with another request
  918. /// </summary>
  919. /// <param name="usFileIndex">The file number to be uploaded</param>
  920. /// <param name="uploadData">Buffer where data to be sent is stored</param>
  921. public void Upload(ushort usFileIndex, byte[] uploadData)
  922. {
  923. if (!bInitialized)
  924. throw new ObjectDisposedException("ANTFSHost object has been disposed");
  925. Upload(usFileIndex, 0, uploadData, true);
  926. }
  927. /// <summary>
  928. /// Retrieves the parameters of the most recently found device
  929. /// </summary>
  930. /// <returns>Parameters of the most recently found device, or null if no parameters could be retrieved</returns>
  931. public ANTFS_SearchResults GetFoundDeviceParameters()
  932. {
  933. if (!bInitialized)
  934. throw new ObjectDisposedException("ANTFSHost object has been disposed");
  935. ANTFS_SearchResults searchResults = new ANTFS_SearchResults();
  936. byte[] aucFriendlyName = new byte[Byte.MaxValue];
  937. byte ucSize = (byte) aucFriendlyName.Length;
  938. if (ANTFSHost_GetFoundDeviceParameters(unmanagedHostPtr, ref searchResults.DeviceParameters, aucFriendlyName, ref ucSize) == 0)
  939. return null;
  940. if (ucSize != 0)
  941. searchResults.FriendlyName = Common.ConvertToString(aucFriendlyName);
  942. return searchResults;
  943. }
  944. /// <summary>
  945. /// Retrieves the channel ID of the most recently found device.
  946. /// An exception will be thrown if no device has been found
  947. /// </summary>
  948. /// <returns>The Channel ID of the most recently found device.</returns>
  949. public ANT_ChannelID GetFoundDeviceChannelID()
  950. {
  951. if (!bInitialized)
  952. throw new ObjectDisposedException("ANTFSHost object has been disposed");
  953. ushort foundDeviceNumber = 0;
  954. byte foundDeviceType = 0;
  955. byte foundTransmissionType = 0;
  956. if (ANTFSHost_GetFoundDeviceChannelID(unmanagedHostPtr, ref foundDeviceNumber, ref foundDeviceType, ref foundTransmissionType) == 0)
  957. throw new ANTFS_Exception("Unable to retrieve the channel ID, no device has been found yet");
  958. return new ANT_ChannelID(foundDeviceNumber, foundDeviceType, foundTransmissionType);
  959. }
  960. /// <summary>
  961. /// Obtains the additional data received on an Authentication Response (e.g. PassKey), if available
  962. /// </summary>
  963. /// <returns>Authentication response additional parameters, or an empty array if no additional parameters were received</returns>
  964. public byte[] GetAuthResponse()
  965. {
  966. if (!bInitialized)
  967. throw new ObjectDisposedException("ANTFSHost object has been disposed");
  968. if (unmanagedAuthSize != IntPtr.Zero)
  969. {
  970. byte ucSize = Marshal.ReadByte(unmanagedAuthSize); // Retrieve size from native heap
  971. byte[] authString = new byte[ucSize];
  972. if (ucSize > 0)
  973. Marshal.Copy(unmanagedAuthBuffer, authString, 0, ucSize); // Retrieve buffer contents from native heap
  974. return authString;
  975. }
  976. else
  977. {
  978. return new byte[0];
  979. }
  980. }
  981. /// <summary>
  982. /// Gets the transfer progress of a pending or complete download
  983. /// </summary>
  984. /// <returns>The transfer status, including the current byte progress,
  985. /// total expected length of the download, and current percentage.
  986. /// Returns null if no valid status could be obtained.</returns>
  987. public TransferStatus GetDownloadStatus()
  988. {
  989. if (!bInitialized)
  990. throw new ObjectDisposedException("ANTFSHost object has been disposed");
  991. uint ulProgress = 0;
  992. uint ulLength = 0;
  993. if (ANTFSHost_GetDownloadStatus(unmanagedHostPtr, ref ulProgress, ref ulLength) != 0)
  994. {
  995. return new TransferStatus(ulProgress, ulLength);
  996. }
  997. else
  998. return null;
  999. }
  1000. /// <summary>
  1001. /// Gets the transfer progress of a pending or complete upload
  1002. /// </summary>
  1003. /// <returns>The transfer status, including the current byte progress,
  1004. /// total expected length of the upload, and current percentage.
  1005. /// Returns null if no valid status could be obtained.</returns>
  1006. public TransferStatus GetUploadStatus()
  1007. {
  1008. if (!bInitialized)
  1009. throw new ObjectDisposedException("ANTFSHost object has been disposed");
  1010. uint ulProgress = 0;
  1011. uint ulLength = 0;
  1012. if (ANTFSHost_GetUploadStatus(unmanagedHostPtr, ref ulProgress, ref ulLength) != 0)
  1013. {
  1014. return new TransferStatus(ulProgress, ulLength);
  1015. }
  1016. else
  1017. return null;
  1018. }
  1019. /// <summary>
  1020. /// Gets the received data from a transfer (download)
  1021. /// </summary>
  1022. /// <returns>Buffer containing the downloaded data.
  1023. /// Returns an empty buffer if no data is available or the download size is 0</returns>
  1024. public byte[] GetTransferData()
  1025. {
  1026. if (!bInitialized)
  1027. throw new ObjectDisposedException("ANTFSHost object has been disposed");
  1028. uint ulDataSize = GetDownloadSize(); // Get the size of the latest download
  1029. byte[] returnData = new byte[ulDataSize]; // Create buffer
  1030. if(ulDataSize > 0) // If there is data to retrieve
  1031. {
  1032. if (ANTFSHost_GetTransferData(unmanagedHostPtr, ref ulDataSize, returnData) == 0)
  1033. return new byte[0]; // Transfer failed, return empty buffer
  1034. Array.Resize(ref returnData, (int) ulDataSize); // Update buffer size
  1035. }
  1036. return returnData;
  1037. }
  1038. /// <summary>
  1039. /// Retrieves the size of a downloaded file
  1040. /// </summary>
  1041. /// <returns>Download size (in bytes)</returns>
  1042. public uint GetDownloadSize()
  1043. {
  1044. if (!bInitialized)
  1045. throw new ObjectDisposedException("ANTFSHost object has been disposed");
  1046. return ANTFSHost_GetTransferSize(unmanagedHostPtr);
  1047. }
  1048. /// <summary>
  1049. /// Returns the current library status
  1050. /// </summary>
  1051. /// <returns>Current library status</returns>
  1052. public State GetStatus()
  1053. {
  1054. if (!bInitialized)
  1055. throw new ObjectDisposedException("ANTFSHost object has been disposed");
  1056. return (State) ANTFSHost_GetStatus(unmanagedHostPtr);
  1057. }
  1058. /// <summary>
  1059. /// Returns the current ANTFS state from the last seen ANTFS beacon of the
  1060. /// connected device.
  1061. /// </summary>
  1062. /// <returns>Ant-Fs State from last received beacon or BeaconNotFound if no device is connected</returns>
  1063. public BeaconAntFsState GetConnectedDeviceBeaconAntfsState()
  1064. {
  1065. if (!bInitialized)
  1066. throw new ObjectDisposedException("ANTFSHost object has been disposed");
  1067. return (BeaconAntFsState)ANTFSHost_GetConnectedDeviceBeaconAntfsState(unmanagedHostPtr);
  1068. }
  1069. /// <summary>
  1070. /// Gets the version string of the underlying ANT-FS library
  1071. /// </summary>
  1072. /// <returns>ANT-FS Library Version String</returns>
  1073. public string GetLibraryVersion()
  1074. {
  1075. if (!bInitialized)
  1076. throw new ObjectDisposedException("ANTFSHost object has been disposed");
  1077. byte[] returnVersion = new byte[Byte.MaxValue]; // maximum size
  1078. if (ANTFSHost_GetVersion(unmanagedHostPtr, returnVersion, (byte) returnVersion.Length) == 0)
  1079. return ""; // blank string
  1080. else
  1081. return (Common.ConvertToString(returnVersion));
  1082. }
  1083. /// <summary>
  1084. /// Cancels any pending actions and returns the library to the appropiate ANT-FS layer if possible,
  1085. /// i.e. if the library was executing a download command in the transport layer, the library would
  1086. /// be returned to the Transport State.
  1087. /// A response of CancelDone will be sent back to the application when the cancel operation is complete.
  1088. /// </summary>
  1089. public void Cancel()
  1090. {
  1091. if (!bInitialized)
  1092. throw new ObjectDisposedException("ANTFSHost object has been disposed");
  1093. ANTFSHost_Cancel(unmanagedHostPtr);
  1094. }
  1095. #endregion
  1096. #region Private Methods
  1097. /// <summary>
  1098. /// Processing of incoming ANT-FS responses
  1099. /// </summary>
  1100. private void ResponseThreadHandler()
  1101. {
  1102. bResponseThreadExit = false;
  1103. Response eThreadResponse = Response.None;
  1104. while (!bResponseThreadExit)
  1105. {
  1106. eThreadResponse = (Response) ANTFSHost_WaitForResponse(unmanagedHostPtr, 999);
  1107. if (eThreadResponse != Response.None) // We got a response
  1108. {
  1109. // If we were processing an upload, release handle
  1110. ReleaseUploadBuffer();
  1111. lock (onResponseLock)
  1112. {
  1113. // Dispatch response if we got one
  1114. if (onResponse_internal != null)
  1115. {
  1116. onResponse_internal(eThreadResponse);
  1117. }
  1118. }
  1119. }
  1120. }
  1121. }
  1122. #endregion
  1123. }
  1124. }