1
0

dsi_serial_libusb.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412
  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. #include "types.h"
  9. #if defined(DSI_TYPES_WINDOWS)
  10. #include "dsi_serial_libusb.hpp"
  11. #include "defines.h"
  12. #include "macros.h"
  13. #include "usb_device_handle_libusb.hpp"
  14. #include <stdio.h>
  15. #include <string.h>
  16. #include <windows.h>
  17. #if defined(_MSC_VER)
  18. #include "WinDevice.h"
  19. #endif
  20. #include <vector>
  21. using namespace std;
  22. //#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.
  23. //////////////////////////////////////////////////////////////////////////////////
  24. // Private Definitions
  25. //////////////////////////////////////////////////////////////////////////////////
  26. //////////////////////////////////////////////////////////////////////////////////
  27. // Public Methods
  28. //////////////////////////////////////////////////////////////////////////////////
  29. ///////////////////////////////////////////////////////////////////////
  30. // Constructor
  31. ///////////////////////////////////////////////////////////////////////
  32. DSISerialLibusb::DSISerialLibusb()
  33. {
  34. pclDevice = NULL;
  35. hReceiveThread = NULL;
  36. pclDeviceHandle = NULL;
  37. }
  38. ///////////////////////////////////////////////////////////////////////
  39. // Destructor
  40. ///////////////////////////////////////////////////////////////////////
  41. DSISerialLibusb::~DSISerialLibusb()
  42. {
  43. Close();
  44. }
  45. ///////////////////////////////////////////////////////////////////////
  46. // Initializes and opens the object.
  47. ///////////////////////////////////////////////////////////////////////
  48. //defines used by AutoInit
  49. //#define USB_ANT_VID ((USHORT)0x1915)
  50. //#define USB_ANT_PID ((USHORT)0x0102)
  51. BOOL DSISerialLibusb::AutoInit()
  52. {
  53. if(Init(0, USBDeviceHandle::USB_ANT_VID_TWO) == FALSE)
  54. {
  55. this->USBReset();
  56. return FALSE;
  57. }
  58. return TRUE;
  59. }
  60. ///////////////////////////////////////////////////////////////////////
  61. // Initializes the object.
  62. ///////////////////////////////////////////////////////////////////////
  63. BOOL DSISerialLibusb::Init(ULONG ulBaud_, UCHAR ucDeviceNumber_)
  64. {
  65. Close();
  66. pclDevice = NULL;
  67. ulBaud = ulBaud_;
  68. ucDeviceNumber = ucDeviceNumber_;
  69. return TRUE;
  70. }
  71. ///////////////////////////////////////////////////////////////////////
  72. // Initializes the object.
  73. ///////////////////////////////////////////////////////////////////////
  74. BOOL DSISerialLibusb::Init(ULONG ulBaud_, USHORT usVid_)
  75. {
  76. UCHAR ucDeviceNumberTemp;
  77. Close();
  78. BOOL bSuccess = GetDeviceNumberByVendorId(usVid_, ucDeviceNumberTemp);
  79. if(!bSuccess)
  80. {
  81. Close();
  82. return FALSE;
  83. }
  84. pclDevice = NULL;
  85. ulBaud = ulBaud_;
  86. ucDeviceNumber = ucDeviceNumberTemp;
  87. return TRUE;
  88. }
  89. ///////////////////////////////////////////////////////////////////////
  90. // Initializes the object.
  91. ///////////////////////////////////////////////////////////////////////
  92. BOOL DSISerialLibusb::Init(ULONG ulBaud_, const USBDeviceLibusb& clDevice_, UCHAR ucDeviceNumber_)
  93. {
  94. Close();
  95. pclDevice = &clDevice_; //!!
  96. ulBaud = ulBaud_;
  97. ucDeviceNumber = ucDeviceNumber_;
  98. return TRUE;
  99. }
  100. ///////////////////////////////////////////////////////////////////////
  101. // Returns the device serial number.
  102. ///////////////////////////////////////////////////////////////////////
  103. ULONG DSISerialLibusb::GetDeviceSerialNumber()
  104. {
  105. if(pclDeviceHandle == 0)
  106. return 0;
  107. return pclDeviceHandle->GetDevice().GetSerialNumber();
  108. }
  109. ///////////////////////////////////////////////////////////////////////
  110. // Get USB enumeration info. Not necessarily connected to USB.
  111. ///////////////////////////////////////////////////////////////////////
  112. BOOL DSISerialLibusb::GetDeviceUSBInfo(UCHAR ucDevice_, UCHAR* pucProductString_, UCHAR* pucSerialString_, USHORT usBufferSize_)
  113. {
  114. const USBDeviceListLibusb clDeviceList = USBDeviceHandleLibusb::GetAllDevices();
  115. if(clDeviceList.GetSize() <= ucDevice_)
  116. return FALSE;
  117. if(clDeviceList[ucDevice_]->GetProductDescription(pucProductString_, usBufferSize_) != TRUE)
  118. return FALSE;
  119. if(clDeviceList[ucDevice_]->GetSerialString(pucSerialString_, usBufferSize_) != TRUE)
  120. return FALSE;
  121. return TRUE;
  122. }
  123. ///////////////////////////////////////////////////////////////////////
  124. // Get USB PID. Need to be connected to USB device.
  125. ///////////////////////////////////////////////////////////////////////
  126. BOOL DSISerialLibusb::GetDevicePID(USHORT& usPid_)
  127. {
  128. if(pclDeviceHandle == NULL)
  129. return FALSE;
  130. usPid_ = pclDeviceHandle->GetDevice().GetPid();
  131. return TRUE;
  132. }
  133. ///////////////////////////////////////////////////////////////////////
  134. // Get USB VID. Need to be connected to USB device.
  135. ///////////////////////////////////////////////////////////////////////
  136. BOOL DSISerialLibusb::GetDeviceVID(USHORT& usVid_)
  137. {
  138. if(pclDeviceHandle == NULL)
  139. return FALSE;
  140. usVid_ = pclDeviceHandle->GetDevice().GetVid();
  141. return TRUE;
  142. }
  143. ///////////////////////////////////////////////////////////////////////
  144. // Opens port, starts receive thread.
  145. ///////////////////////////////////////////////////////////////////////
  146. BOOL DSISerialLibusb::Open()
  147. {
  148. // Make sure all handles are reset before opening again.
  149. Close();
  150. if (pclCallback == NULL)
  151. return FALSE;
  152. bStopReceiveThread = FALSE;
  153. //If the user specified a device number instead of a USBDevice instance, then grab it from the list
  154. const USBDeviceLibusb* pclTempDevice = pclDevice;
  155. if(pclDevice == NULL)
  156. {
  157. const USBDeviceListLibusb clDeviceList = USBDeviceHandleLibusb::GetAllDevices();
  158. if(clDeviceList.GetSize() <= ucDeviceNumber)
  159. return FALSE;
  160. pclTempDevice = clDeviceList[ucDeviceNumber];
  161. }
  162. if(USBDeviceHandleLibusb::Open(*pclTempDevice, pclDeviceHandle) == FALSE)
  163. {
  164. pclDeviceHandle = NULL;
  165. Close();
  166. return FALSE;
  167. }
  168. if(DSIThread_MutexInit(&stMutexCriticalSection) != DSI_THREAD_ENONE)
  169. {
  170. Close();
  171. return FALSE;
  172. }
  173. if(DSIThread_CondInit(&stEventReceiveThreadExit) != DSI_THREAD_ENONE)
  174. {
  175. DSIThread_MutexDestroy(&stMutexCriticalSection);
  176. Close();
  177. return FALSE;
  178. }
  179. hReceiveThread = DSIThread_CreateThread(&DSISerialLibusb::ProcessThread, this);
  180. if(hReceiveThread == NULL)
  181. {
  182. DSIThread_MutexDestroy(&stMutexCriticalSection);
  183. DSIThread_CondDestroy(&stEventReceiveThreadExit);
  184. Close();
  185. return FALSE;
  186. }
  187. return TRUE;
  188. }
  189. ///////////////////////////////////////////////////////////////////////
  190. // Closes the USB connection, kills receive thread.
  191. ///////////////////////////////////////////////////////////////////////
  192. void DSISerialLibusb::Close(BOOL bReset_)
  193. {
  194. if(hReceiveThread)
  195. {
  196. DSIThread_MutexLock(&stMutexCriticalSection);
  197. if(bStopReceiveThread == FALSE)
  198. {
  199. bStopReceiveThread = TRUE;
  200. if (DSIThread_CondTimedWait(&stEventReceiveThreadExit, &stMutexCriticalSection, 3000) != DSI_THREAD_ENONE)
  201. {
  202. // We were unable to stop the thread normally.
  203. DSIThread_DestroyThread(hReceiveThread);
  204. }
  205. }
  206. DSIThread_MutexUnlock(&stMutexCriticalSection);
  207. DSIThread_ReleaseThreadID(hReceiveThread);
  208. hReceiveThread = NULL;
  209. DSIThread_MutexDestroy(&stMutexCriticalSection);
  210. DSIThread_CondDestroy(&stEventReceiveThreadExit);
  211. }
  212. if(pclDeviceHandle)
  213. {
  214. USBDeviceHandleLibusb::Close(pclDeviceHandle, bReset_);
  215. //if(bReset_) //Note: The reset is disabled in device_handle_libusb, so this is a useless wait
  216. // DSIThread_Sleep(1750); //Stall to allow the device to reset, trying to reopen the driver too soon can cause bad things to happen.
  217. pclDeviceHandle = NULL;
  218. }
  219. return;
  220. }
  221. ///////////////////////////////////////////////////////////////////////
  222. // Writes ucSize_ bytes to USB, returns number of bytes not written.
  223. ///////////////////////////////////////////////////////////////////////
  224. BOOL DSISerialLibusb::WriteBytes(void *pvData_, USHORT usSize_)
  225. {
  226. ULONG ulActualWritten = 0;
  227. if(pclDeviceHandle == NULL || pvData_ == NULL)
  228. return FALSE;
  229. if(pclDeviceHandle->Write(pvData_, usSize_, ulActualWritten) != USBError::NONE)
  230. {
  231. pclCallback->Error(DSI_SERIAL_EWRITE);
  232. return FALSE;
  233. }
  234. return TRUE;
  235. }
  236. ///////////////////////////////////////////////////////////////////////
  237. // Returns the device port number.
  238. ///////////////////////////////////////////////////////////////////////
  239. UCHAR DSISerialLibusb::GetDeviceNumber()
  240. {
  241. return ucDeviceNumber;
  242. }
  243. //////////////////////////////////////////////////////////////////////////////////
  244. // Private Methods
  245. //////////////////////////////////////////////////////////////////////////////////
  246. ///////////////////////////////////////////////////////////////////////
  247. void DSISerialLibusb::ReceiveThread()
  248. {
  249. while(!bStopReceiveThread)
  250. {
  251. UCHAR ucRxByte;
  252. ULONG ulRxBytesRead;
  253. USBError::Enum eStatus = pclDeviceHandle->Read(&ucRxByte, 1, ulRxBytesRead, 1000);
  254. switch(eStatus)
  255. {
  256. case USBError::NONE:
  257. pclCallback->ProcessByte(ucRxByte);
  258. break;
  259. case USBError::DEVICE_GONE:
  260. pclCallback->Error(DSI_SERIAL_DEVICE_GONE);
  261. bStopReceiveThread = TRUE;
  262. break;
  263. case USBError::TIMED_OUT:
  264. break;
  265. default:
  266. pclCallback->Error(DSI_SERIAL_EREAD);
  267. bStopReceiveThread = TRUE;
  268. break;
  269. }
  270. }
  271. DSIThread_MutexLock(&stMutexCriticalSection);
  272. bStopReceiveThread = TRUE;
  273. DSIThread_CondSignal(&stEventReceiveThreadExit); // Set an event to alert the main process that Rx thread is finished and can be closed.
  274. DSIThread_MutexUnlock(&stMutexCriticalSection);
  275. }
  276. ///////////////////////////////////////////////////////////////////////
  277. DSI_THREAD_RETURN DSISerialLibusb::ProcessThread(void *pvParameter_)
  278. {
  279. DSISerialLibusb *This = (DSISerialLibusb *) pvParameter_;
  280. This->ReceiveThread();
  281. return 0;
  282. }
  283. ///////////////////////////////////////////////////////////////////////
  284. // Finds the first availible device that matches the vendor id
  285. // and returns the device number.
  286. ///////////////////////////////////////////////////////////////////////
  287. BOOL DSISerialLibusb::GetDeviceNumberByVendorId(USHORT usVid_, UCHAR& ucDeviceNumber_)
  288. {
  289. const USBDeviceListLibusb clDeviceList = USBDeviceHandleLibusb::GetAvailableDevices();
  290. ULONG ulNumOfDevices = clDeviceList.GetSize();
  291. if(ulNumOfDevices == 0)
  292. {
  293. Close();
  294. return FALSE;
  295. }
  296. BOOL bDeviceFound = FALSE;
  297. for(ULONG i=0; i<ulNumOfDevices && !bDeviceFound; i++)
  298. {
  299. const USBDeviceLibusb& clDevice = *(clDeviceList[i]);
  300. USHORT usVid = clDevice.GetVid();
  301. if(usVid != usVid_)
  302. continue;
  303. USBDeviceHandleLibusb* pclTempHandle;
  304. if(USBDeviceHandleLibusb::Open(clDevice, pclTempHandle) == FALSE)
  305. continue;
  306. USBDeviceHandleLibusb::Close(pclTempHandle);
  307. ucDeviceNumber_ = (UCHAR)i;
  308. bDeviceFound = TRUE;
  309. }
  310. return bDeviceFound;
  311. }
  312. //!!
  313. void DSISerialLibusb::USBReset(void)
  314. {
  315. #if defined(_MSC_VER)
  316. // !! Borland builder chokes on cfgmgr32
  317. TCHAR line1[64];
  318. TCHAR* argv_[2];
  319. //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)
  320. //The soft reset will have no effect on devices currently opened by other applications.
  321. argv_[0] = line1;
  322. SNPRINTF(&(line1[0]),sizeof(line1), "@USB\\VID_0FCF&PID_1008\\*"); //The string for all ANT USB Stick2s
  323. WinDevice_Disable(1,argv_);
  324. WinDevice_Enable(1,argv_);
  325. #endif
  326. }
  327. #endif //defined(DSI_TYPES_WINDOWS)