usb_device_handle_libusb.cpp 19 KB

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