usb_device_handle_libusb.cpp 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640
  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 "types.h"
  9. #if defined(DSI_TYPES_WINDOWS)
  10. #include "usb_device_handle_libusb.hpp"
  11. #include "macros.h"
  12. #include "usb_device_list.hpp"
  13. #include "dsi_debug.hpp"
  14. #include <memory>
  15. using namespace std;
  16. //////////////////////////////////////////////////////////////////////////////////
  17. // Static declarations
  18. //////////////////////////////////////////////////////////////////////////////////
  19. USBDeviceList<const USBDeviceLibusb> USBDeviceHandleLibusb::clDeviceList;
  20. //////////////////////////////////////////////////////////////////////////////////
  21. // Private Definitions
  22. //////////////////////////////////////////////////////////////////////////////////
  23. const UCHAR USB_ANT_CONFIGURATION = 1;
  24. const UCHAR USB_ANT_INTERFACE = 0;
  25. const UCHAR USB_ANT_EP_IN = 0x81;
  26. const UCHAR USB_ANT_EP_OUT = 0x01;
  27. BOOL CanOpenDevice(const USBDeviceLibusb*const & pclDevice_) //!!Should we make a static member function that does a more efficient try open (doesn't start a receive thread, etc.)
  28. {
  29. if(pclDevice_ == FALSE)
  30. return FALSE;
  31. return USBDeviceHandleLibusb::TryOpen(*pclDevice_);
  32. }
  33. const USBDeviceListLibusb USBDeviceHandleLibusb::GetAllDevices() //!!List needs to be deleted!
  34. {
  35. USBDeviceListLibusb clList;
  36. clDeviceList = USBDeviceList<const USBDeviceLibusb>(); //clear device list
  37. //Get a reference to library
  38. auto_ptr<const LibusbLibrary> pclAutoLibusbLibrary(NULL);
  39. if(LibusbLibrary::Load(pclAutoLibusbLibrary) == FALSE)
  40. return clList;
  41. const LibusbLibrary& clLibusbLibrary = *pclAutoLibusbLibrary;
  42. int ret;
  43. //Initialize libusb
  44. clLibusbLibrary.Init();
  45. //clLibusbLibrary.SetDebug(255);
  46. //Find all USB busses on a system
  47. ret = clLibusbLibrary.FindBusses();
  48. if(ret < 0) return clList;
  49. //Find all devices on each bus
  50. ret = clLibusbLibrary.FindDevices();
  51. if(ret < 0) return clList;
  52. //Opens proper device as specified by VIDNUM
  53. for(usb_bus* bus = clLibusbLibrary.GetBusses(); bus; bus = bus->next)
  54. {
  55. struct usb_device* dev;
  56. /* //!!
  57. if(bus->root_dev)
  58. {
  59. if(dev->descriptor.idVendor == VID)
  60. {
  61. //We are communicating to the right device
  62. device = dev;
  63. return TRUE;
  64. }
  65. }
  66. */
  67. for(dev = bus->devices; dev; dev = dev->next)
  68. {
  69. clDeviceList.Add( USBDeviceLibusb(*dev) ); //save the copies to the static private list
  70. clList.Add( clDeviceList.GetAddress(clDeviceList.GetSize()-1) ); //save a pointer to the just added device
  71. }
  72. }
  73. return clList;
  74. }
  75. //!!Will we have a problem if someone asks for a device list twice? (will it dereference the pointers in the first list?)
  76. const USBDeviceListLibusb USBDeviceHandleLibusb::GetAvailableDevices() //!!List needs to be deleted!
  77. {
  78. return USBDeviceHandleLibusb::GetAllDevices().GetSubList(CanOpenDevice);
  79. }
  80. BOOL USBDeviceHandleLibusb::Open(const USBDeviceLibusb& clDevice_, USBDeviceHandleLibusb*& pclDeviceHandle_)
  81. {
  82. try
  83. {
  84. pclDeviceHandle_ = new USBDeviceHandleLibusb(clDevice_);
  85. }
  86. catch(...)
  87. {
  88. pclDeviceHandle_ = NULL;
  89. return FALSE;
  90. }
  91. return TRUE;
  92. }
  93. BOOL USBDeviceHandleLibusb::Close(USBDeviceHandleLibusb*& pclDeviceHandle_, BOOL bReset_)
  94. {
  95. if(pclDeviceHandle_ == NULL)
  96. return FALSE;
  97. pclDeviceHandle_->PClose(bReset_);
  98. delete pclDeviceHandle_;
  99. pclDeviceHandle_ = NULL;
  100. return TRUE;
  101. }
  102. //A more efficient way to test if you can open a device. For instance, this function won't create a receive loop, etc.)
  103. BOOL USBDeviceHandleLibusb::TryOpen(const USBDeviceLibusb& clDevice_)
  104. {
  105. //Get a reference to library
  106. auto_ptr<const LibusbLibrary> pclAutoLibusbLibrary(NULL);
  107. if(LibusbLibrary::Load(pclAutoLibusbLibrary) == FALSE)
  108. return FALSE;
  109. const LibusbLibrary& clLibusbLibrary = *pclAutoLibusbLibrary;
  110. clLibusbLibrary.Init();
  111. //pfSetDebug(255);
  112. usb_dev_handle* pclTempDeviceHandle;
  113. pclTempDeviceHandle = clLibusbLibrary.Open(&(clDevice_.GetRawDevice()));
  114. if(pclTempDeviceHandle == NULL)
  115. return FALSE; //Doesn't need to call Close because it wouldn't do anything
  116. int ret;
  117. ret = clLibusbLibrary.SetConfiguration(pclTempDeviceHandle, USB_ANT_CONFIGURATION);
  118. if(ret != 0)
  119. {
  120. ret = clLibusbLibrary.Close(pclTempDeviceHandle);
  121. if(ret != 0) {} //this would be an error
  122. return FALSE;
  123. }
  124. ret = clLibusbLibrary.ClaimInterface(pclTempDeviceHandle, USB_ANT_INTERFACE);
  125. if(ret != 0)
  126. {
  127. ret = clLibusbLibrary.Close(pclTempDeviceHandle);
  128. if(ret != 0) {} //this would be an error
  129. return FALSE;
  130. }
  131. ret = clLibusbLibrary.ReleaseInterface(pclTempDeviceHandle, USB_ANT_INTERFACE);
  132. if(ret != 0) {} //this would be an error
  133. ret = clLibusbLibrary.Close(pclTempDeviceHandle);
  134. if(ret != 0) {} //this would be an error
  135. return TRUE;
  136. }
  137. ///////////////////////////////////////////////////////////////////////
  138. // Constructor
  139. ///////////////////////////////////////////////////////////////////////
  140. USBDeviceHandleLibusb::USBDeviceHandleLibusb(const USBDeviceLibusb& clDevice_)
  141. try
  142. :
  143. USBDeviceHandle(),
  144. clDevice(clDevice_), //!!Copy?
  145. bDeviceGone(TRUE)
  146. {
  147. hReceiveThread = NULL;
  148. bStopReceiveThread = TRUE;
  149. device_handle = NULL;
  150. clLibusbLibrary.Init();
  151. //pfSetDebug(255);
  152. if(POpen() == FALSE)
  153. throw 0; //!!We need something to throw
  154. return;
  155. }
  156. catch(...)
  157. {
  158. throw;
  159. }
  160. ///////////////////////////////////////////////////////////////////////
  161. // Destructor
  162. ///////////////////////////////////////////////////////////////////////
  163. USBDeviceHandleLibusb::~USBDeviceHandleLibusb()
  164. {
  165. //!!Delete all the elements in the clOverflowQueue!
  166. }
  167. ///////////////////////////////////////////////////////////////////////
  168. // Opens port, starts receive thread.
  169. ///////////////////////////////////////////////////////////////////////
  170. BOOL USBDeviceHandleLibusb::POpen()
  171. {
  172. int ret;
  173. //Make sure we are not open before opening again.
  174. PClose(); //!!Do we want to reset here?
  175. device_handle = clLibusbLibrary.Open(&(clDevice.GetRawDevice()));
  176. if(device_handle == NULL)
  177. return FALSE; //Doesn't need to call Close because it wouldn't do anything
  178. bDeviceGone = FALSE;
  179. //!!Will this do a soft reset if the current configuration gets set?
  180. ret = clLibusbLibrary.SetConfiguration(device_handle, USB_ANT_CONFIGURATION);
  181. if(ret != 0)
  182. {
  183. PClose();
  184. return FALSE;
  185. }
  186. ret = clLibusbLibrary.ClaimInterface(device_handle, USB_ANT_INTERFACE);
  187. if(ret != 0)
  188. {
  189. PClose();
  190. return FALSE;
  191. }
  192. /* //!!Fails
  193. ret = usb_set_altinterface(device_handle, 0);
  194. if(ret != 0)
  195. {
  196. Close();
  197. return FALSE;
  198. }
  199. */
  200. #if !defined(DSI_TYPES_WINDOWS) //!!Fails on Windows
  201. {
  202. ret = clLibusbLibrary.ClearHalt(device_handle, USB_ANT_EP_OUT);
  203. if(ret != 0)
  204. {
  205. Close();
  206. return FALSE;
  207. }
  208. }
  209. #endif
  210. if(DSIThread_MutexInit(&stMutexCriticalSection) != DSI_THREAD_ENONE)
  211. {
  212. PClose();
  213. return FALSE;
  214. }
  215. if(DSIThread_CondInit(&stEventReceiveThreadExit) != DSI_THREAD_ENONE)
  216. {
  217. DSIThread_MutexDestroy(&stMutexCriticalSection);
  218. PClose();
  219. return FALSE;
  220. }
  221. bStopReceiveThread = FALSE;
  222. hReceiveThread = DSIThread_CreateThread(&USBDeviceHandleLibusb::ProcessThread, this);
  223. if (hReceiveThread == NULL)
  224. {
  225. DSIThread_CondDestroy(&stEventReceiveThreadExit);
  226. DSIThread_MutexDestroy(&stMutexCriticalSection);
  227. PClose();
  228. return FALSE;
  229. }
  230. return TRUE;
  231. }
  232. ///////////////////////////////////////////////////////////////////////
  233. // Closes the USB connection, kills receive thread.
  234. ///////////////////////////////////////////////////////////////////////
  235. void USBDeviceHandleLibusb::PClose(BOOL bReset_)
  236. {
  237. bDeviceGone = TRUE;
  238. if (hReceiveThread)
  239. {
  240. DSIThread_MutexLock(&stMutexCriticalSection);
  241. if(bStopReceiveThread == FALSE)
  242. {
  243. bStopReceiveThread = TRUE;
  244. if (DSIThread_CondTimedWait(&stEventReceiveThreadExit, &stMutexCriticalSection, 3000) != DSI_THREAD_ENONE)
  245. {
  246. // We were unable to stop the thread normally.
  247. DSIThread_DestroyThread(hReceiveThread);
  248. }
  249. }
  250. DSIThread_MutexUnlock(&stMutexCriticalSection);
  251. DSIThread_ReleaseThreadID(hReceiveThread);
  252. hReceiveThread = NULL;
  253. DSIThread_MutexDestroy(&stMutexCriticalSection);
  254. DSIThread_CondDestroy(&stEventReceiveThreadExit);
  255. }
  256. if(device_handle != (usb_dev_handle*)NULL)
  257. {
  258. int ret;
  259. ret = clLibusbLibrary.ReleaseInterface(device_handle, USB_ANT_INTERFACE);
  260. if(ret != 0) {} //this would be an error
  261. if(bReset_)
  262. {
  263. // ret = clLibusbLibrary.Reset(device_handle); //The library reset function can sometimes cause the device/driver to go into an unusable state, long term stability testing shows there is no benifit to including reset for this device/driver combination.
  264. ret = clLibusbLibrary.Close(device_handle);
  265. if(ret != 0) {} //this would be an error
  266. }
  267. else
  268. {
  269. ret = clLibusbLibrary.Close(device_handle);
  270. if(ret != 0) {} //this would be an error
  271. }
  272. device_handle = (usb_dev_handle*)NULL;
  273. }
  274. }
  275. ///////////////////////////////////////////////////////////////////////
  276. // Writes usSize_ bytes to USB, returns TRUE if successful.
  277. ///////////////////////////////////////////////////////////////////////
  278. //!!Return true if we wrote half the bytes successfully?
  279. USBError::Enum USBDeviceHandleLibusb::Write(void* pvData_, ULONG ulSize_, ULONG& ulBytesWritten_)
  280. {
  281. ulBytesWritten_ = 0;
  282. if(bDeviceGone)
  283. return USBError::DEVICE_GONE;
  284. if(pvData_ == NULL)
  285. return USBError::INVALID_PARAM;
  286. //!!What happens if usSize_ == 0?
  287. int theWriteCount;
  288. theWriteCount = clLibusbLibrary.InterruptWrite(device_handle, USB_ANT_EP_OUT, (char*)pvData_, ulSize_, 3000); //!!Non-blocking is supported in V1.0
  289. if(theWriteCount < 0)
  290. return USBError::FAILED;
  291. ulBytesWritten_ = theWriteCount;
  292. return USBError::NONE;
  293. }
  294. ///////////////////////////////////////////////////////////////////////
  295. USBError::Enum USBDeviceHandleLibusb::Read(void* pvData_, ULONG ulSize_, ULONG& ulBytesRead_, ULONG ulWaitTime_)
  296. {
  297. if(bDeviceGone)
  298. return USBError::DEVICE_GONE;
  299. ulBytesRead_ = clRxQueue.PopArray(reinterpret_cast<UCHAR* const>(pvData_), ulSize_, ulWaitTime_);
  300. return USBError::NONE;
  301. }
  302. void USBDeviceHandleLibusb::ReceiveThread()
  303. {
  304. #if defined(DEBUG_FILE)
  305. BOOL bRxDebug = DSIDebug::ThreadInit("ao_libusb_receive.txt");
  306. DSIDebug::ThreadEnable(TRUE);
  307. #endif
  308. UCHAR ucConsecIoErrors = 0;
  309. UCHAR aucData[4096];
  310. VOID *asyncContextObject = NULL;
  311. BOOL isRequestSubmitted = FALSE;
  312. INT iRet = clLibusbLibrary.BulkSetupAsync(device_handle, &asyncContextObject, USB_ANT_EP_IN);
  313. if(iRet < 0)
  314. {
  315. #if defined(DEBUG_FILE)
  316. char acMesg[255];
  317. SNPRINTF(acMesg, 255, "ReceiveThread(): BulkSetupAsync() Error: %d", iRet);
  318. DSIDebug::ThreadWrite(acMesg);
  319. #endif
  320. bStopReceiveThread = TRUE;
  321. }
  322. while(!bStopReceiveThread)
  323. {
  324. //size must be the largest usb message we will receive or else it will get dropped, or will
  325. // get a -1 ("permission error") and then -104 ("connection reset by peer") errors!
  326. if(!isRequestSubmitted)
  327. {
  328. iRet = clLibusbLibrary.SubmitAsync(asyncContextObject, (char*)aucData, sizeof(aucData));
  329. if(iRet >= 0)
  330. {
  331. isRequestSubmitted = TRUE;
  332. }
  333. else
  334. {
  335. #if defined(DEBUG_FILE)
  336. char acMesg[255];
  337. SNPRINTF(acMesg, 255, "ReceiveThread(): SubmitAsync() Error: %d", iRet);
  338. DSIDebug::ThreadWrite(acMesg);
  339. #endif
  340. bStopReceiveThread = TRUE;
  341. break;
  342. }
  343. }
  344. iRet = clLibusbLibrary.ReapAsyncNocancel(asyncContextObject, 1000);
  345. if(iRet > 0)
  346. {
  347. clRxQueue.PushArray(aucData, iRet);
  348. isRequestSubmitted = FALSE; //We need to resubmit the request or we will just get the same data again
  349. ucConsecIoErrors = 0;
  350. }
  351. else if(iRet == -116)
  352. {
  353. //an error occured, errno -116: Connection timed out is usually not an error for us because
  354. //we are in a read loop but this error is also returned when the Windows sleeps and the GetOverlappedResult()
  355. //call in reap_async() returns Win error 995 ERROR_OPERATION_ABORTED
  356. //When the OS goes to sleep the stick powered down and lost its config, so we are hosed and need to restart
  357. if(GetLastError() == 995)
  358. {
  359. #if defined(DEBUG_FILE)
  360. if(bRxDebug)
  361. DSIDebug::ThreadWrite("ReceiveThread(): ReapAsyncNocancel()=-116 && GetLastError()=995 => Sleep/Hibernate occured and reset device");
  362. #endif
  363. bStopReceiveThread = TRUE;
  364. }
  365. }
  366. else if(iRet < 0)
  367. {
  368. #if defined(DEBUG_FILE)
  369. if(bRxDebug)
  370. {
  371. char acMesg[255];
  372. SNPRINTF(acMesg, 255, "ReceiveThread(): ReapAsyncNocancel() Error: %d, Win_GetLastError: %lu", iRet, GetLastError());
  373. DSIDebug::ThreadWrite(acMesg);
  374. }
  375. #endif
  376. //We assume that the device is gone if we get multiple errors in a row
  377. ucConsecIoErrors++;
  378. if(ucConsecIoErrors == 10)
  379. {
  380. #if defined(DEBUG_FILE)
  381. if(bRxDebug)
  382. DSIDebug::ThreadWrite("ReceiveThread(): ReapAsyncNocancel() Had 10 IO errors in a row.");
  383. #endif
  384. bStopReceiveThread = TRUE;
  385. }
  386. else //We can try to cancel our request and start a new one to see if it fixes the problem
  387. //TODO //!!up to this point in time, we don't know what errors are actually causing this, so restarting the request may be entirely useless
  388. {
  389. if(clLibusbLibrary.CancelAsync(asyncContextObject) == 0
  390. && clLibusbLibrary.FreeAsync(&asyncContextObject) == 0
  391. && clLibusbLibrary.BulkSetupAsync(device_handle, &asyncContextObject, USB_ANT_EP_IN) == 0)
  392. {
  393. isRequestSubmitted = FALSE;
  394. }
  395. else
  396. {
  397. #if defined(DEBUG_FILE)
  398. if(bRxDebug)
  399. DSIDebug::ThreadWrite("ReceiveThread(): Failed to free old async request and create a new one.");
  400. #endif
  401. bStopReceiveThread = TRUE;
  402. }
  403. }
  404. }
  405. }
  406. bDeviceGone = TRUE; //The read loop is dead, since we can't get any info, the device might as well be gone
  407. if(asyncContextObject != NULL)
  408. {
  409. iRet = clLibusbLibrary.CancelAsync(asyncContextObject);
  410. #if defined(DEBUG_FILE)
  411. if(iRet < 0)
  412. {
  413. char acMesg[255];
  414. SNPRINTF(acMesg, 255, "ReceiveThread(): CancelAsync() Error: %d\n", iRet);
  415. DSIDebug::ThreadWrite(acMesg);
  416. }
  417. #endif
  418. iRet = clLibusbLibrary.FreeAsync(&asyncContextObject);
  419. #if defined(DEBUG_FILE)
  420. if(iRet < 0)
  421. {
  422. char acMesg[255];
  423. SNPRINTF(acMesg, 255, "ReceiveThread(): FreeAsync() Error: %d\n", iRet);
  424. DSIDebug::ThreadWrite(acMesg);
  425. }
  426. #endif
  427. asyncContextObject = NULL;
  428. }
  429. DSIThread_MutexLock(&stMutexCriticalSection);
  430. bStopReceiveThread = TRUE;
  431. DSIThread_CondSignal(&stEventReceiveThreadExit); // Set an event to alert the main process that Rx thread is finished and can be closed.
  432. DSIThread_MutexUnlock(&stMutexCriticalSection);
  433. }
  434. /*
  435. ///////////////////////////////////////////////////////////////////////
  436. USBError::Enum USBDeviceHandleLibusb::Read(void* pvData_, ULONG ulSize_, ULONG& ulBytesRead_, ULONG ulWaitTime_)
  437. {
  438. ULONG ulSizeLeft = ulSize_;
  439. //give the user any data we may have in the data queue
  440. while(ulSizeLeft != 0 && clOverflowQueue.size() != 0)
  441. {
  442. SerialData* pstFrontArray = clOverflowQueue.front();
  443. ULONG ulDataSize = pstFrontArray->iSize - pstFrontArray->iDataStart;
  444. ULONG ulTransferSize = (ulSizeLeft < ulDataSize) ? ulSizeLeft : ulDataSize; //min
  445. memcpy(pvData_, pstFrontArray->data, ulTransferSize);
  446. ulSizeLeft -= ulTransferSize;
  447. pstFrontArray->iDataStart += ulTransferSize;
  448. if(pstFrontArray->iSize - pstFrontArray->iDataStart == 0)
  449. {
  450. delete pstFrontArray;
  451. clOverflowQueue.pop_front();
  452. }
  453. }
  454. return ulSize_ - ulSizeLeft;
  455. }
  456. //!!Put read errors into the queue?
  457. void USBDeviceHandleLibusb::ReceiveThread()
  458. {
  459. UCHAR ucIoErrors = 0;
  460. while(!bStopReceiveThread)
  461. {
  462. //size must be the largest usb message we will receive or else it will get dropped, or will
  463. // get a -1 ("permission error") and then -104 ("connection reset by peer") errors!
  464. SerialData* mesgin = new SerialData();
  465. mesgin->iSize = clLibusbLibrary.BulkRead(device_handle, USB_ANT_EP_IN, mesgin->data, sizeof(mesgin->data), ulWaitTime_);
  466. if(mesgin->iSize < 0 && mesgin->iSize != -116) //errno -116: Connection timed out
  467. {
  468. //We are assuming that the device is gone if we get multiple IO errors (errno -5) in a row
  469. if(mesgin->iSize == -5)
  470. ucIoErrors++;
  471. else
  472. ucIoErrors = 0;
  473. if(ucIoErrors == 10)
  474. {
  475. bDeviceGone = TRUE;
  476. bStopReceiveThread = TRUE;
  477. }
  478. delete mesgin; //this data is no good
  479. mesgin = NULL;
  480. }
  481. else
  482. {
  483. clOverflowQueue.push_back(mesgin);
  484. }
  485. }
  486. bDeviceGone = TRUE;
  487. DSIThread_MutexLock(&stMutexCriticalSection);
  488. bStopReceiveThread = TRUE;
  489. DSIThread_CondSignal(&stEventReceiveThreadExit); // Set an event to alert the main process that Rx thread is finished and can be closed.
  490. DSIThread_MutexUnlock(&stMutexCriticalSection);
  491. }
  492. */
  493. ///////////////////////////////////////////////////////////////////////
  494. DSI_THREAD_RETURN USBDeviceHandleLibusb::ProcessThread(void* pvParameter_)
  495. {
  496. USBDeviceHandleLibusb* This = reinterpret_cast<USBDeviceHandleLibusb*>(pvParameter_);
  497. This->ReceiveThread();
  498. return 0;
  499. }
  500. #endif //defined(DSI_TYPES_WINDOWS)