2
0

dsi_serial_generic.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442
  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 in compliance
  4. with this license.
  5. Copyright (c) Dynastream Innovations Inc. 2014
  6. All rights reserved.
  7. */
  8. #include "dsi_serial_generic.hpp"
  9. #include "types.h"
  10. #include "defines.h"
  11. #include "macros.h"
  12. #include "usb_device_handle.hpp"
  13. #include <stdio.h>
  14. #include <string.h>
  15. #include <time.h>
  16. #if defined(DSI_TYPES_WINDOWS)
  17. #include "WinDevice.h"
  18. #endif
  19. #include "usb_device_list.hpp"
  20. //#define NUMBER_OF_DEVICES_CHECK_THREAD_KILL //Only include this if we are sure we want to terminate the Rx thread if the number of devices are ever reduced.
  21. //////////////////////////////////////////////////////////////////////////////////
  22. // Private Definitions
  23. //////////////////////////////////////////////////////////////////////////////////
  24. time_t DSISerialGeneric::lastUsbResetTime = 0;
  25. //////////////////////////////////////////////////////////////////////////////////
  26. // Public Methods
  27. //////////////////////////////////////////////////////////////////////////////////
  28. ///////////////////////////////////////////////////////////////////////
  29. // Constructor
  30. ///////////////////////////////////////////////////////////////////////
  31. DSISerialGeneric::DSISerialGeneric()
  32. {
  33. pclDeviceHandle = NULL;
  34. pclDevice = NULL;
  35. hReceiveThread = NULL;
  36. bStopReceiveThread = TRUE;
  37. ucDeviceNumber = 0xFF;
  38. ulBaud = 0;
  39. return;
  40. }
  41. ///////////////////////////////////////////////////////////////////////
  42. // Destructor
  43. ///////////////////////////////////////////////////////////////////////
  44. DSISerialGeneric::~DSISerialGeneric()
  45. {
  46. Close();
  47. if (pclDevice)
  48. delete pclDevice;
  49. pclDevice = NULL;
  50. }
  51. ///////////////////////////////////////////////////////////////////////
  52. // Initializes and opens the object.
  53. ///////////////////////////////////////////////////////////////////////
  54. //defines used by AutoInit
  55. #define ANT_USB_STICK_PID 0x1004
  56. #define ANT_USB_DEV_BOARD_PID 0x1006
  57. #define ANT_USB_STICK_BAUD ((USHORT)50000)
  58. #define ANT_DEFAULT_BAUD ((USHORT)57600)
  59. BOOL DSISerialGeneric::AutoInit()
  60. {
  61. Close();
  62. if (pclDevice)
  63. delete pclDevice;
  64. pclDevice = NULL;
  65. ucDeviceNumber = 0xFF;
  66. const ANTDeviceList clDeviceList = USBDeviceHandle::GetAvailableDevices(); //saves a copy of the list and all of the elements
  67. if(clDeviceList.GetSize() == 0)
  68. {
  69. //When this is being polled repeatedly, as in the ANTFS host class, the USBReset calls to WinDevice Enable/Disable take a large amount if CPU, so we limit the
  70. //reset here to only be called a maximum of once every 30s
  71. time_t curTime = time(NULL);
  72. if(curTime - lastUsbResetTime > 30)
  73. {
  74. lastUsbResetTime = curTime;
  75. this->USBReset();
  76. }
  77. return FALSE;
  78. }
  79. USBDeviceHandle::CopyANTDevice(pclDevice, clDeviceList[0]);
  80. ucDeviceNumber = 0; //initialize it to 0 for now (all devices that use autoinit will have a 0 device number) //TODO this devicenumber is useless because it can't be used to access the list again
  81. switch (pclDevice->GetPid())
  82. {
  83. case ANT_USB_STICK_PID:
  84. ulBaud = ANT_USB_STICK_BAUD;
  85. break;
  86. case ANT_USB_DEV_BOARD_PID:
  87. default:
  88. ulBaud = ANT_DEFAULT_BAUD;
  89. break;
  90. }
  91. return TRUE;
  92. }
  93. ///////////////////////////////////////////////////////////////////////
  94. // Initializes the object.
  95. ///////////////////////////////////////////////////////////////////////
  96. BOOL DSISerialGeneric::Init(ULONG ulBaud_, UCHAR ucDeviceNumber_)
  97. {
  98. Close();
  99. if (pclDevice)
  100. delete pclDevice;
  101. pclDevice = NULL;
  102. ucDeviceNumber = 0xFF;
  103. //Note: None of the other existing classes validate the devicenumber, so
  104. // this was removed for consistency as a bonus we avoid some of the
  105. // performance issues with GetAllDevices()
  106. ////const ANTDeviceList clDeviceList = USBDeviceHandle::GetAllDevices();
  107. ////if(clDeviceList.GetSize() <= ucDeviceNumber_)
  108. ////{
  109. //// this->USBReset();
  110. //// return FALSE;
  111. ////}
  112. ulBaud = ulBaud_;
  113. ucDeviceNumber = ucDeviceNumber_;
  114. return TRUE;
  115. }
  116. ///////////////////////////////////////////////////////////////////////
  117. // Initializes the object.
  118. ///////////////////////////////////////////////////////////////////////
  119. BOOL DSISerialGeneric::Init(ULONG ulBaud_, const USBDevice& clDevice_, UCHAR ucDeviceNumber_)
  120. {
  121. Close();
  122. if (pclDevice)
  123. delete pclDevice;
  124. pclDevice = NULL;
  125. pclDevice = &clDevice_; //!!Make copy?
  126. ulBaud = ulBaud_;
  127. ucDeviceNumber = ucDeviceNumber_;
  128. return TRUE;
  129. }
  130. ///////////////////////////////////////////////////////////////////////
  131. // Returns the device serial number.
  132. ///////////////////////////////////////////////////////////////////////
  133. ULONG DSISerialGeneric::GetDeviceSerialNumber()
  134. {
  135. if(pclDeviceHandle == 0)
  136. return 0;
  137. return pclDeviceHandle->GetDevice().GetSerialNumber();
  138. }
  139. ///////////////////////////////////////////////////////////////////////
  140. // Get USB enumeration info. Not necessarily connected to USB.
  141. ///////////////////////////////////////////////////////////////////////
  142. BOOL DSISerialGeneric::GetDeviceUSBInfo(UCHAR ucDevice_, UCHAR* pucProductString_, UCHAR* pucSerialString_, USHORT usBufferSize_)
  143. {
  144. const ANTDeviceList clDeviceList = USBDeviceHandle::GetAllDevices();
  145. if(clDeviceList.GetSize() <= ucDevice_)
  146. return FALSE;
  147. if(clDeviceList[ucDevice_]->GetProductDescription(pucProductString_, usBufferSize_) != TRUE)
  148. return FALSE;
  149. if(clDeviceList[ucDevice_]->GetSerialString(pucSerialString_, usBufferSize_) != TRUE)
  150. return FALSE;
  151. return TRUE;
  152. }
  153. ///////////////////////////////////////////////////////////////////////
  154. // Get USB PID. Need to be connected to USB device.
  155. ///////////////////////////////////////////////////////////////////////
  156. BOOL DSISerialGeneric::GetDevicePID(USHORT& usPid_)
  157. {
  158. if(pclDeviceHandle == NULL)
  159. return FALSE;
  160. usPid_ = pclDeviceHandle->GetDevice().GetPid();
  161. return TRUE;
  162. }
  163. ///////////////////////////////////////////////////////////////////////
  164. // Get USB VID. Need to be connected to USB device.
  165. ///////////////////////////////////////////////////////////////////////
  166. BOOL DSISerialGeneric::GetDeviceVID(USHORT& usVid_)
  167. {
  168. if(pclDeviceHandle == NULL)
  169. return FALSE;
  170. usVid_ = pclDeviceHandle->GetDevice().GetVid();
  171. return TRUE;
  172. }
  173. ///////////////////////////////////////////////////////////////////////
  174. // Get USB Serial String. Need to be connected to USB device.
  175. ///////////////////////////////////////////////////////////////////////
  176. BOOL DSISerialGeneric::GetDeviceSerialString(UCHAR* pucSerialString_, USHORT usBufferSize_)
  177. {
  178. if(pclDeviceHandle == NULL)
  179. return FALSE;
  180. if(pclDeviceHandle->GetDevice().GetSerialString(pucSerialString_, usBufferSize_) != TRUE)
  181. return FALSE;
  182. return TRUE;
  183. }
  184. ///////////////////////////////////////////////////////////////////////
  185. // Opens port, starts receive thread.
  186. ///////////////////////////////////////////////////////////////////////
  187. BOOL DSISerialGeneric::Open(void)
  188. {
  189. // Make sure all handles are reset before opening again.
  190. Close();
  191. if (pclCallback == NULL)
  192. return FALSE;
  193. //If the user specified a device number instead of a USBDevice instance, then grab it from the list
  194. const USBDevice* pclTempDevice = pclDevice;
  195. if(pclDevice == NULL)
  196. {
  197. const USBDeviceList<const USBDevice*> clDeviceList = USBDeviceHandle::GetAllDevices();
  198. if(clDeviceList.GetSize() <= ucDeviceNumber)
  199. return FALSE;
  200. pclTempDevice = clDeviceList[ucDeviceNumber];
  201. }
  202. if(USBDeviceHandle::Open(*pclTempDevice, pclDeviceHandle, ulBaud) == FALSE)
  203. {
  204. pclDeviceHandle = NULL;
  205. Close();
  206. return FALSE;
  207. }
  208. if(DSIThread_MutexInit(&stMutexCriticalSection) != DSI_THREAD_ENONE)
  209. {
  210. Close();
  211. return FALSE;
  212. }
  213. if(DSIThread_CondInit(&stEventReceiveThreadExit) != DSI_THREAD_ENONE)
  214. {
  215. DSIThread_MutexDestroy(&stMutexCriticalSection);
  216. Close();
  217. return FALSE;
  218. }
  219. bStopReceiveThread = FALSE;
  220. hReceiveThread = DSIThread_CreateThread(&DSISerialGeneric::ProcessThread, this);
  221. if(hReceiveThread == NULL)
  222. {
  223. DSIThread_MutexDestroy(&stMutexCriticalSection);
  224. DSIThread_CondDestroy(&stEventReceiveThreadExit);
  225. Close();
  226. return FALSE;
  227. }
  228. return TRUE;
  229. }
  230. ///////////////////////////////////////////////////////////////////////
  231. // Closes the USB connection, kills receive thread.
  232. ///////////////////////////////////////////////////////////////////////
  233. void DSISerialGeneric::Close(BOOL bReset_)
  234. {
  235. if(hReceiveThread)
  236. {
  237. DSIThread_MutexLock(&stMutexCriticalSection);
  238. if(bStopReceiveThread == FALSE)
  239. {
  240. bStopReceiveThread = TRUE;
  241. if (DSIThread_CondTimedWait(&stEventReceiveThreadExit, &stMutexCriticalSection, 3000) != DSI_THREAD_ENONE)
  242. {
  243. // We were unable to stop the thread normally.
  244. DSIThread_DestroyThread(hReceiveThread);
  245. }
  246. }
  247. DSIThread_MutexUnlock(&stMutexCriticalSection);
  248. DSIThread_ReleaseThreadID(hReceiveThread);
  249. hReceiveThread = NULL;
  250. DSIThread_MutexDestroy(&stMutexCriticalSection);
  251. DSIThread_CondDestroy(&stEventReceiveThreadExit);
  252. }
  253. if(pclDeviceHandle)
  254. {
  255. USBDeviceHandle::Close(pclDeviceHandle, bReset_);
  256. //if(bReset_) //Only done for specific serial implementations
  257. // DSIThread_Sleep(1750); //Stall to allow the device to reset, trying to reopen the driver too soon can cause bad things to happen.
  258. pclDeviceHandle = NULL;
  259. }
  260. return;
  261. }
  262. ///////////////////////////////////////////////////////////////////////
  263. // Writes ucSize_ bytes to USB, returns number of bytes not written.
  264. ///////////////////////////////////////////////////////////////////////
  265. BOOL DSISerialGeneric::WriteBytes(void *pvData_, USHORT usSize_)
  266. {
  267. ULONG ulActualWritten = 0;
  268. if(pclDeviceHandle == NULL || pvData_ == NULL)
  269. return FALSE;
  270. if(pclDeviceHandle->Write(pvData_, usSize_, ulActualWritten) != USBError::NONE)
  271. {
  272. pclCallback->Error(DSI_SERIAL_EWRITE);
  273. return FALSE;
  274. }
  275. return TRUE;
  276. }
  277. ///////////////////////////////////////////////////////////////////////
  278. // Returns the device port number.
  279. ///////////////////////////////////////////////////////////////////////
  280. UCHAR DSISerialGeneric::GetDeviceNumber()
  281. {
  282. return ucDeviceNumber;
  283. }
  284. //////////////////////////////////////////////////////////////////////////////////
  285. // Private Methods
  286. //////////////////////////////////////////////////////////////////////////////////
  287. ///////////////////////////////////////////////////////////////////////
  288. void DSISerialGeneric::ReceiveThread(void)
  289. {
  290. UCHAR aucData[255];
  291. while(!bStopReceiveThread)
  292. {
  293. ULONG ulRxBytesRead;
  294. USBError::Enum eStatus = pclDeviceHandle->Read(aucData, sizeof(aucData), ulRxBytesRead, 1000);
  295. switch(eStatus)
  296. {
  297. case USBError::NONE:
  298. for(ULONG i=0; i<ulRxBytesRead; i++)
  299. pclCallback->ProcessByte(aucData[i]);
  300. break;
  301. case USBError::DEVICE_GONE:
  302. pclCallback->Error(DSI_SERIAL_DEVICE_GONE);
  303. bStopReceiveThread = TRUE;
  304. break;
  305. case USBError::TIMED_OUT:
  306. break;
  307. default:
  308. pclCallback->Error(DSI_SERIAL_EREAD);
  309. bStopReceiveThread = TRUE;
  310. break;
  311. }
  312. }
  313. DSIThread_MutexLock(&stMutexCriticalSection);
  314. bStopReceiveThread = TRUE;
  315. DSIThread_CondSignal(&stEventReceiveThreadExit); // Set an event to alert the main process that Rx thread is finished and can be closed.
  316. DSIThread_MutexUnlock(&stMutexCriticalSection);
  317. }
  318. ///////////////////////////////////////////////////////////////////////
  319. DSI_THREAD_RETURN DSISerialGeneric::ProcessThread(void* pvParameter_)
  320. {
  321. DSISerialGeneric* This = (DSISerialGeneric*)pvParameter_;
  322. This->ReceiveThread();
  323. return 0;
  324. }
  325. //NOTE: The USBReset was originally added due to issues in the USB1 (two processor) usb stick that would occasionally have synch issues requiring a reset
  326. // to remedy. It appears this reset is of no use for USB2s, and in fact is documented in device_handle_libusb PClose() as potentially causing errors with usb2s.
  327. // However, because the behavior is not fully understood and we aren't receiving complaints (beyond the cpu usage of this reset) we are leaving things 'as-is'
  328. void DSISerialGeneric::USBReset(void)
  329. {
  330. //If the user specified a device number instead of a USBDevice instance, then grab it from the list
  331. const USBDevice* pclTempDevice = pclDevice;
  332. if(pclDevice == NULL)
  333. {
  334. const ANTDeviceList clDeviceList = USBDeviceHandle::GetAllDevices();
  335. if((ucDeviceNumber == 0xFF) || (clDeviceList.GetSize() <= ucDeviceNumber))
  336. {
  337. #if defined(_MSC_VER)
  338. // !! Borland builder chokes on cfgmgr32
  339. TCHAR line1[64];
  340. TCHAR* argv_[2];
  341. //Only do the soft reset if we fail to open a device or it seems like theres no deivces to open (device in a "hosed" state)
  342. //The soft reset will have no effect on devices currently opened by other applications.
  343. argv_[0] = line1;
  344. SNPRINTF(&(line1[0]),sizeof(line1), "@USB\\VID_0FCF&PID_10*"); //The string for all ANT USB Devices
  345. WinDevice_Disable(1,argv_);
  346. WinDevice_Enable(1,argv_);
  347. #endif
  348. return;
  349. }
  350. pclTempDevice = clDeviceList[ucDeviceNumber];
  351. }
  352. pclTempDevice->USBReset();
  353. return;
  354. }