usb_device_handle_si.cpp 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759
  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 "defines.h"
  11. #include "usb_device_handle_si.hpp"
  12. #include "macros.h"
  13. #include "dsi_debug.hpp"
  14. #if defined(_MSC_VER)
  15. #include "WinDevice.h"
  16. #endif
  17. #include "usb_device_list.hpp"
  18. #include <memory>
  19. #include <stdio.h>
  20. #include <string.h>
  21. #include <windows.h>
  22. using namespace std;
  23. //#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.
  24. //////////////////////////////////////////////////////////////////////////////////
  25. // Static declarations
  26. //////////////////////////////////////////////////////////////////////////////////
  27. USBDeviceList<const USBDeviceSI> USBDeviceHandleSI::clDeviceList;
  28. //////////////////////////////////////////////////////////////////////////////////
  29. // Private Definitions
  30. //////////////////////////////////////////////////////////////////////////////////
  31. #define INVALID_USB_DEVICE_NUMBER MAX_UCHAR
  32. #define SI_STOPBIT_1 ((WORD) 0x00)
  33. #define SI_STOPBIT_1_5 ((WORD) 0x01)
  34. #define SI_STOPBIT_2 ((WORD) 0x02)
  35. #define SI_PARITY_NONE ((WORD) 0x00)
  36. #define SI_PARITY_ODD ((WORD) 0x10)
  37. #define SI_PARITY_EVEN ((WORD) 0x20)
  38. #define SI_PARITY_MARK ((WORD) 0x30)
  39. #define SI_PARITY_SPACE ((WORD) 0x40)
  40. #define SI_BITS_5 ((WORD) 0x500)
  41. #define SI_BITS_6 ((WORD) 0x600)
  42. #define SI_BITS_7 ((WORD) 0x700)
  43. #define SI_BITS_8 ((WORD) 0x800)
  44. #define SI_WRITE_TIMEOUT ((DWORD) 3000) //3s Write timeout
  45. //////////////////////////////////////////////////////////////////////////////////
  46. // Public Methods
  47. //////////////////////////////////////////////////////////////////////////////////
  48. const USBDeviceListSI USBDeviceHandleSI::GetAllDevices()
  49. {
  50. USBDeviceListSI clList;
  51. clDeviceList = USBDeviceList<const USBDeviceSI>(); //clear device list
  52. //Get a reference to library
  53. auto_ptr<const SiLabsLibrary> pclAutoSiLibrary(NULL);
  54. if(SiLabsLibrary::Load(pclAutoSiLibrary) == FALSE)
  55. return clList;
  56. const SiLabsLibrary& clSiLibrary = *pclAutoSiLibrary;
  57. DWORD dwNumberOfDevices = 0;
  58. if(clSiLibrary.GetNumDevices(&dwNumberOfDevices) != SI_SUCCESS) //!!cast!
  59. return clList;
  60. if (dwNumberOfDevices > MAX_UCHAR)
  61. dwNumberOfDevices = MAX_UCHAR;
  62. UCHAR ucNumberOfDevices = (UCHAR)dwNumberOfDevices;
  63. for(UCHAR i=0; i<ucNumberOfDevices; i++)
  64. {
  65. clDeviceList.Add(USBDeviceSI(i) ); //save the copies to the static private list
  66. clList.Add(clDeviceList.GetAddress(i) ); //save a pointer to the just added device
  67. }
  68. return clList; //return the list of pointers
  69. }
  70. BOOL CanOpenDevice(const USBDeviceSI*const & pclDevice_)
  71. {
  72. if(pclDevice_ == FALSE)
  73. return FALSE;
  74. return USBDeviceHandleSI::TryOpen(*pclDevice_);
  75. }
  76. const USBDeviceListSI USBDeviceHandleSI::GetAvailableDevices()
  77. {
  78. /*
  79. class TryOpening : public USBDeviceListSI::CompareFunc
  80. {
  81. USBDeviceListSI::CompareFunc::result_type operator()(USBDeviceListSI::CompareFunc::argument_type pclDevice_)
  82. {
  83. if(pclDevice_ == FALSE)
  84. return FALSE;
  85. USBDeviceHandleSI* pclTempHandle;
  86. BOOL bOpened;
  87. bOpened = USBDeviceHandleSI::Open(*pclDevice_, pclTempHandle, 0);
  88. if(bOpened)
  89. USBDeviceHandleSI::Close(pclTempHandle);
  90. return bOpened;
  91. }
  92. };
  93. TryOpening blah;
  94. */
  95. return USBDeviceHandleSI::GetAllDevices().GetSubList(CanOpenDevice);
  96. }
  97. ///////////////////////////////////////////////////////////////////////
  98. // Constructor
  99. ///////////////////////////////////////////////////////////////////////
  100. USBDeviceHandleSI::USBDeviceHandleSI(const USBDeviceSI& clDevice_, ULONG ulBaudRate_)
  101. try
  102. :
  103. USBDeviceHandle(),
  104. clDevice(clDevice_),
  105. ulBaudRate(ulBaudRate_),
  106. bDeviceGone(TRUE),
  107. ucCTSCode(SI_STATUS_INPUT),
  108. ucRTSCode(SI_HELD_INACTIVE),
  109. ucDTRCode(SI_HELD_INACTIVE),
  110. ucDSRCode(SI_STATUS_INPUT),
  111. ucDCDCode(SI_STATUS_INPUT)
  112. {
  113. hReceiveThread = NULL;
  114. bStopReceiveThread = TRUE;
  115. hUSBDeviceHandle = NULL;
  116. hUSBEvent = NULL;
  117. if(POpen() == FALSE)
  118. throw 0; //!!We need something to throw
  119. return;
  120. }
  121. catch(...)
  122. {
  123. throw;
  124. }
  125. ///////////////////////////////////////////////////////////////////////
  126. // Destructor
  127. ///////////////////////////////////////////////////////////////////////
  128. USBDeviceHandleSI::~USBDeviceHandleSI()
  129. {
  130. //!!Delete all the elements in the queue?
  131. }
  132. ///////////////////////////////////////////////////////////////////////
  133. // Returns the device serial number.
  134. ///////////////////////////////////////////////////////////////////////
  135. /*
  136. USBError::Enum USBDeviceHandleSI::GetDeviceSerialNumber(ULONG& ulSerialNumber_)
  137. {
  138. if(bDeviceGone)
  139. return USBError::DEVICE_GONE;
  140. UCHAR aucSerialString[CP210x_MAX_SERIAL_STRLEN+1];
  141. UCHAR ucLength = CP210x_MAX_SERIAL_STRLEN;
  142. memset(aucSerialString, 0, sizeof(aucSerialString));
  143. if(clCmLibrary.GetDeviceSerialNumber(hUSBDeviceHandle, aucSerialString, &ucLength, TRUE) != CP210x_SUCCESS)
  144. return USBError::FAILED;
  145. ULONG ulSerial = ulSerial = atol((char*)aucSerialString);
  146. if(ulSerial == 0)
  147. return USBError::FAILED;
  148. if ((ulSerial > 10000) && (ulSerial < 10255))
  149. memcpy((UCHAR*)&ulSerial, &(aucSerialString[56]), 4);
  150. ulSerialNumber_ = ulSerial;
  151. return USBError::NONE;
  152. }
  153. */
  154. ///////////////////////////////////////////////////////////////////////
  155. // Returns the number of SILabs devices connected.
  156. // Returns 0 on error.
  157. ///////////////////////////////////////////////////////////////////////
  158. UCHAR USBDeviceHandleSI::GetNumberOfDevices() //!!Should this be in USBDeviceSI instead?
  159. {
  160. //Get a reference to library
  161. auto_ptr<const SiLabsLibrary> pclAutoSiLibrary(NULL);
  162. if(SiLabsLibrary::Load(pclAutoSiLibrary) == FALSE)
  163. return 0;
  164. ULONG ulUSBNumberOfDevices;
  165. if(pclAutoSiLibrary->GetNumDevices(&ulUSBNumberOfDevices) != SI_SUCCESS)
  166. return 0;
  167. return (UCHAR)ulUSBNumberOfDevices;
  168. }
  169. ///////////////////////////////////////////////////////////////////////
  170. // Get USB enumeration info. Not necessarily connected to USB.
  171. ///////////////////////////////////////////////////////////////////////
  172. /*
  173. USBError::Enum USBDeviceHandleSI::GetDeviceUSBInfo(UCHAR ucDevice, UCHAR* pucProductString, UCHAR* pucSerialString)
  174. {
  175. if(bDeviceGone)
  176. return USBError::DEVICE_GONE;
  177. if(clSiLibrary.GetProductString(ucDevice , pucSerialString, SI_RETURN_SERIAL_NUMBER) != SI_SUCCESS)
  178. return USBError::FAILED;
  179. if(clSiLibrary.GetProductString(ucDevice , pucProductString, SI_RETURN_DESCRIPTION) != SI_SUCCESS)
  180. return USBError::FAILED;
  181. return USBError::NONE;
  182. }
  183. */
  184. ///////////////////////////////////////////////////////////////////////
  185. // Get USB PID. Need to be connected to USB device.
  186. ///////////////////////////////////////////////////////////////////////
  187. /*
  188. USBError::Enum USBDeviceHandleSI::GetDevicePID(USHORT& usPID_) //!!Don't need this!
  189. {
  190. if(bDeviceGone)
  191. return USBError::DEVICE_GONE;
  192. if(clCmLibrary.GetDevicePid(hUSBDeviceHandle, &usPID_) != SI_SUCCESS)
  193. return USBError::FAILED;
  194. return USBError::NONE;
  195. }
  196. */
  197. //A more efficient way to test if you can open a device. For instance, this function won't create a receive loop, etc.)
  198. //Doesn't test for correct baudrate.
  199. BOOL USBDeviceHandleSI::TryOpen(const USBDeviceSI& clDevice_)
  200. {
  201. //Get a reference to library
  202. auto_ptr<const SiLabsLibrary> pclAutoSiLibrary(NULL);
  203. if(SiLabsLibrary::Load(pclAutoSiLibrary) == FALSE)
  204. return 0;
  205. const SiLabsLibrary& clSiLibrary = *pclAutoSiLibrary;
  206. HANDLE hTempHandle;
  207. if(clSiLibrary.Open(clDevice_.GetDeviceNumber(), &hTempHandle) != SI_SUCCESS)
  208. {
  209. SI_STATUS eStatus = clSiLibrary.Close(hTempHandle);
  210. if(eStatus != SI_SUCCESS) {} //would be an error
  211. return FALSE;
  212. }
  213. SI_STATUS eStatus = clSiLibrary.Close(hTempHandle);
  214. if(eStatus != SI_SUCCESS) {} //would be an error
  215. return TRUE;
  216. }
  217. ///////////////////////////////////////////////////////////////////////
  218. // Opens port, starts receive thread.
  219. ///////////////////////////////////////////////////////////////////////
  220. BOOL USBDeviceHandleSI::Open(const USBDeviceSI& clDevice_, USBDeviceHandleSI*& pclDeviceHandle_, ULONG ulBaudRate_)
  221. {
  222. try
  223. {
  224. pclDeviceHandle_ = new USBDeviceHandleSI(clDevice_, ulBaudRate_);
  225. }
  226. catch(...)
  227. {
  228. pclDeviceHandle_ = NULL;
  229. return FALSE;
  230. }
  231. return TRUE;
  232. }
  233. BOOL USBDeviceHandleSI::POpen()
  234. {
  235. DWORD ReadTimeout,WriteTimeout;
  236. // Make sure all handles are reset before opening again.
  237. PClose();
  238. if(clSiLibrary.Open(clDevice.GetDeviceNumber(), &hUSBDeviceHandle) != SI_SUCCESS)
  239. {
  240. PClose();
  241. return FALSE;
  242. }
  243. bDeviceGone = FALSE;
  244. if(clSiLibrary.GetTimeouts(&ReadTimeout, &WriteTimeout) != SI_SUCCESS)
  245. {
  246. PClose();
  247. return FALSE;
  248. }
  249. WriteTimeout = SI_WRITE_TIMEOUT; //only overwrite the write timeout
  250. if(clSiLibrary.SetTimeouts(ReadTimeout, WriteTimeout) != SI_SUCCESS)
  251. {
  252. PClose();
  253. return FALSE;
  254. }
  255. if(clSiLibrary.SetBaudRate(hUSBDeviceHandle, ulBaudRate) != SI_SUCCESS)
  256. {
  257. PClose();
  258. return FALSE;
  259. }
  260. if(clSiLibrary.SetLineControl(hUSBDeviceHandle, SI_PARITY_NONE | SI_BITS_8 | SI_STOPBIT_1) != SI_SUCCESS)
  261. {
  262. PClose();
  263. return FALSE;
  264. }
  265. ucCTSCode = SI_HANDSHAKE_LINE;
  266. ucRTSCode = SI_HELD_ACTIVE;
  267. if(clSiLibrary.SetFlowControl(hUSBDeviceHandle, ucCTSCode, ucRTSCode, ucDTRCode, ucDSRCode, ucDCDCode, FALSE) != SI_SUCCESS)
  268. {
  269. PClose();
  270. return FALSE;
  271. }
  272. // Clear the RX and TX buffers
  273. if(clSiLibrary.FlushBuffers(hUSBDeviceHandle, TRUE, TRUE) != SI_SUCCESS)
  274. {
  275. PClose();
  276. return FALSE;
  277. }
  278. hUSBEvent = CreateEvent((LPSECURITY_ATTRIBUTES) NULL, TRUE, FALSE, (LPCTSTR) NULL); // Create a manual-reset event.
  279. if(hUSBEvent == NULL)
  280. {
  281. PClose();
  282. return FALSE;
  283. }
  284. if(DSIThread_MutexInit(&stMutexCriticalSection) != DSI_THREAD_ENONE)
  285. {
  286. PClose();
  287. return FALSE;
  288. }
  289. if(DSIThread_CondInit(&stEventReceiveThreadExit) != DSI_THREAD_ENONE)
  290. {
  291. DSIThread_MutexDestroy(&stMutexCriticalSection);
  292. PClose();
  293. return FALSE;
  294. }
  295. bStopReceiveThread = FALSE;
  296. hReceiveThread = DSIThread_CreateThread(&USBDeviceHandleSI::ProcessThread, this);
  297. if(hReceiveThread == NULL)
  298. {
  299. DSIThread_CondDestroy(&stEventReceiveThreadExit);
  300. DSIThread_MutexDestroy(&stMutexCriticalSection);
  301. PClose();
  302. return FALSE;
  303. }
  304. return TRUE;
  305. }
  306. ///////////////////////////////////////////////////////////////////////
  307. // Closes the USB connection, kills receive thread.
  308. ///////////////////////////////////////////////////////////////////////
  309. //!!User is still expected to close the handle if the device is gone
  310. BOOL USBDeviceHandleSI::Close(USBDeviceHandleSI*& pclDeviceHandle_, BOOL bReset_)
  311. {
  312. if(pclDeviceHandle_ == NULL)
  313. return FALSE;
  314. pclDeviceHandle_->PClose(bReset_);
  315. delete pclDeviceHandle_;
  316. pclDeviceHandle_ = NULL;
  317. return TRUE;
  318. }
  319. void USBDeviceHandleSI::PClose(BOOL bReset_)
  320. {
  321. bDeviceGone = TRUE;
  322. if (hReceiveThread)
  323. {
  324. DSIThread_MutexLock(&stMutexCriticalSection);
  325. if(bStopReceiveThread == FALSE)
  326. {
  327. bStopReceiveThread = TRUE;
  328. if (DSIThread_CondTimedWait(&stEventReceiveThreadExit, &stMutexCriticalSection, 3000) != DSI_THREAD_ENONE)
  329. {
  330. // We were unable to stop the thread normally.
  331. DSIThread_DestroyThread(hReceiveThread);
  332. }
  333. }
  334. DSIThread_MutexUnlock(&stMutexCriticalSection);
  335. DSIThread_ReleaseThreadID(hReceiveThread);
  336. hReceiveThread = NULL;
  337. DSIThread_MutexDestroy(&stMutexCriticalSection);
  338. DSIThread_CondDestroy(&stEventReceiveThreadExit);
  339. }
  340. if(hUSBEvent)
  341. {
  342. CloseHandle(hUSBEvent);
  343. hUSBEvent = NULL;
  344. }
  345. if (hUSBDeviceHandle)
  346. {
  347. SI_STATUS eStatus;
  348. ucCTSCode = SI_STATUS_INPUT;
  349. ucRTSCode = SI_HELD_INACTIVE;
  350. ucDTRCode = SI_HELD_INACTIVE;
  351. ucDSRCode = SI_STATUS_INPUT;
  352. ucDCDCode = SI_STATUS_INPUT;
  353. eStatus = clSiLibrary.SetFlowControl(hUSBDeviceHandle, ucCTSCode, ucRTSCode, ucDTRCode, ucDSRCode, ucDCDCode, FALSE);
  354. if (eStatus != SI_INVALID_HANDLE)
  355. eStatus = clSiLibrary.FlushBuffers(hUSBDeviceHandle, TRUE, TRUE);
  356. if (eStatus != SI_INVALID_HANDLE && bReset_ == TRUE)
  357. {
  358. clCmLibrary.ResetDevice(hUSBDeviceHandle);
  359. }
  360. if (eStatus != SI_INVALID_HANDLE)
  361. eStatus = clSiLibrary.Close(hUSBDeviceHandle);
  362. hUSBDeviceHandle = NULL;
  363. if(bReset_ == TRUE)
  364. Sleep(1750); //Stall to allow the device to reset, trying to reopen the driver too soon can cause bad things to happen.
  365. }
  366. }
  367. ///////////////////////////////////////////////////////////////////////
  368. // Writes ucSize_ bytes to USB, returns number of bytes not written.
  369. ///////////////////////////////////////////////////////////////////////
  370. USBError::Enum USBDeviceHandleSI::Write(void* pvData_, ULONG ulSize_, ULONG& ulBytesWritten_) //!!Should these be ULONG?
  371. {
  372. if(bDeviceGone)
  373. return USBError::DEVICE_GONE;
  374. if(pvData_ == NULL)
  375. return USBError::INVALID_PARAM;
  376. //!!is there a max message size that we should test for?
  377. if(clSiLibrary.Write(hUSBDeviceHandle, pvData_, ulSize_, (LPDWORD)&ulBytesWritten_, (OVERLAPPED*)NULL) != SI_SUCCESS)
  378. return USBError::FAILED;
  379. if(ulBytesWritten_ != ulSize_)
  380. return USBError::FAILED;
  381. return USBError::NONE;
  382. }
  383. //////////////////////////////////////////////////////////////////////////////////
  384. // Private Methods
  385. //////////////////////////////////////////////////////////////////////////////////
  386. ///////////////////////////////////////////////////////////////////////
  387. USBError::Enum USBDeviceHandleSI::Read(void* pvData_, ULONG ulSize_, ULONG& ulBytesRead_, ULONG ulWaitTime_)
  388. {
  389. if(bDeviceGone)
  390. return USBError::DEVICE_GONE;
  391. ulBytesRead_ = clRxQueue.PopArray(reinterpret_cast<char* const>(pvData_), ulSize_, ulWaitTime_);
  392. if(ulBytesRead_ == 0)
  393. return USBError::TIMED_OUT;
  394. return USBError::NONE;
  395. }
  396. /*
  397. void USBDeviceHandleSI::ReceiveThread()
  398. {
  399. BOOL bRxDebug = DSIDebug::ThreadInit("ao_si_receive.txt");
  400. DSIDebug::ThreadEnable(TRUE);
  401. SI_STATUS eStatus = SI_SUCCESS;
  402. while (!bStopReceiveThread)
  403. {
  404. // Initialize the OVERLAPPED structure.
  405. OVERLAPPED stOverlapped;
  406. stOverlapped.Offset = 0;
  407. stOverlapped.OffsetHigh = 0;
  408. stOverlapped.hEvent = hUSBEvent;
  409. ResetEvent(hUSBEvent);
  410. UCHAR aucRxData[255];
  411. ULONG ulRxBytesRead = 0;
  412. switch (eStatus)
  413. {
  414. case SI_SUCCESS:
  415. break;
  416. case SI_IO_PENDING:
  417. {
  418. DWORD dwWaitObject;
  419. do
  420. {
  421. dwWaitObject = WaitForSingleObject(hUSBEvent, 1000);
  422. if (dwWaitObject == WAIT_TIMEOUT)
  423. {
  424. if(DeviceIsGone() == TRUE)
  425. {
  426. bDeviceGone = TRUE;
  427. bStopReceiveThread = TRUE;
  428. }
  429. }
  430. else if (GetOverlappedResult(NULL, &stOverlapped, &ulRxBytesRead, FALSE))
  431. {
  432. if(ulRxBytesRead == 1)
  433. {
  434. //ulTotalBytesRead += ulRxBytesRead;
  435. //Grab as many as you can!
  436. //clRxQueue.Push(ucRxByte);
  437. }
  438. else
  439. {
  440. //!!Do we want to do this?
  441. if(bRxDebug)
  442. DSIDebug::ThreadWrite("Error: Overlapped result has no data.\n");
  443. bDeviceGone = TRUE;
  444. bStopReceiveThread = TRUE;
  445. }
  446. }
  447. } while (!bStopReceiveThread && (dwWaitObject == WAIT_TIMEOUT));
  448. break;
  449. }
  450. case SI_RX_QUEUE_NOT_READY:
  451. if(bRxDebug)
  452. DSIDebug::ThreadWrite("Error: SI_RX_QUEUE_NOT_READY\n");
  453. //thru
  454. case SI_READ_TIMED_OUT:
  455. //minor errors, just try again
  456. break;
  457. case SI_INVALID_REQUEST_LENGTH:
  458. //Should never happen (assert?)
  459. if(bRxDebug)
  460. DSIDebug::ThreadWrite("Error: SI_INVALID_REQUEST_LENGTH\n");
  461. bDeviceGone = TRUE;
  462. bStopReceiveThread = TRUE;
  463. break;
  464. case SI_INVALID_PARAMETER:
  465. //Should never happen (assert?)
  466. if(bRxDebug)
  467. DSIDebug::ThreadWrite("Error: SI_INVALID_PARAMETER\n");
  468. bDeviceGone = TRUE;
  469. bStopReceiveThread = TRUE;
  470. break;
  471. case SI_INVALID_HANDLE:
  472. //fatal error
  473. if(bRxDebug)
  474. DSIDebug::ThreadWrite("Error: SI_INVALID_HANDLE\n");
  475. bDeviceGone = TRUE;
  476. bStopReceiveThread = TRUE;
  477. break;
  478. default:
  479. //fatal error
  480. if(bRxDebug)
  481. DSIDebug::ThreadWrite("Error: UNKNOWN\n");
  482. bDeviceGone = TRUE;
  483. bStopReceiveThread = TRUE;
  484. break;
  485. }
  486. ULONG ulTotalBytesRead = ulRxBytesRead;
  487. ULONG ulMaxBytes = sizeof(aucRxData);
  488. if(!bDeviceGone)
  489. {
  490. do
  491. {
  492. eStatus = clSiLibrary.Read(hUSBDeviceHandle, &(aucRxData[ulTotalBytesRead]), 1, &ulRxBytesRead, &stOverlapped);
  493. if(eStatus == SI_SUCCESS)
  494. ulTotalBytesRead += ulRxBytesRead;
  495. } while(eStatus == SI_SUCCESS && ulTotalBytesRead < ulMaxBytes);
  496. }
  497. if(ulTotalBytesRead != 0)
  498. clRxQueue.PushArray((char*)aucRxData, ulTotalBytesRead);
  499. }
  500. bDeviceGone = TRUE;
  501. DSIThread_MutexLock(&stMutexCriticalSection);
  502. bStopReceiveThread = TRUE;
  503. DSIThread_CondSignal(&stEventReceiveThreadExit); // Set an event to alert the main process that Rx thread is finished and can be closed.
  504. DSIThread_MutexUnlock(&stMutexCriticalSection);
  505. }
  506. */
  507. //!!Old implementation!
  508. void USBDeviceHandleSI::ReceiveThread()
  509. {
  510. while (!bStopReceiveThread)
  511. {
  512. // Initialize the OVERLAPPED structure.
  513. OVERLAPPED stOverlapped;
  514. stOverlapped.Offset = 0;
  515. stOverlapped.OffsetHigh = 0;
  516. stOverlapped.hEvent = hUSBEvent;
  517. ResetEvent(hUSBEvent);
  518. ULONG ulRxBytesRead;
  519. UCHAR ucRxByte;
  520. SI_STATUS eStatus = clSiLibrary.Read(hUSBDeviceHandle, &ucRxByte, 1, &ulRxBytesRead, &stOverlapped);
  521. switch (eStatus)
  522. {
  523. case SI_SUCCESS:
  524. //!!Grab as many as you can!
  525. clRxQueue.Push(ucRxByte);
  526. break;
  527. case SI_IO_PENDING:
  528. {
  529. DWORD dwWaitObject;
  530. do
  531. {
  532. dwWaitObject = WaitForSingleObject(hUSBEvent, 1000);
  533. if (dwWaitObject == WAIT_TIMEOUT)
  534. {
  535. if(DeviceIsGone() == TRUE)
  536. {
  537. bDeviceGone = TRUE;
  538. bStopReceiveThread = TRUE;
  539. }
  540. }
  541. else if (GetOverlappedResult(NULL, &stOverlapped, &ulRxBytesRead, FALSE))
  542. {
  543. if (ulRxBytesRead == 1)
  544. {
  545. //!!Grab as many as you can!
  546. clRxQueue.Push(ucRxByte);
  547. }
  548. else
  549. {
  550. //!!Do we want to do this?
  551. bDeviceGone = TRUE;
  552. bStopReceiveThread = TRUE;
  553. }
  554. }
  555. } while (!bStopReceiveThread && (dwWaitObject == WAIT_TIMEOUT));
  556. break;
  557. }
  558. case SI_RX_QUEUE_NOT_READY:
  559. case SI_READ_TIMED_OUT:
  560. //minor errors, just try again
  561. break;
  562. case SI_INVALID_REQUEST_LENGTH:
  563. case SI_INVALID_PARAMETER:
  564. //!!Should never happen (assert?)
  565. bDeviceGone = TRUE;
  566. bStopReceiveThread = TRUE;
  567. break;
  568. case SI_INVALID_HANDLE:
  569. default:
  570. //fatal errors
  571. bDeviceGone = TRUE;
  572. bStopReceiveThread = TRUE;
  573. break;
  574. }
  575. }
  576. bDeviceGone = TRUE;
  577. DSIThread_MutexLock(&stMutexCriticalSection);
  578. bStopReceiveThread = TRUE;
  579. DSIThread_CondSignal(&stEventReceiveThreadExit); // Set an event to alert the main process that Rx thread is finished and can be closed.
  580. DSIThread_MutexUnlock(&stMutexCriticalSection);
  581. }
  582. ///////////////////////////////////////////////////////////////////////
  583. DSI_THREAD_RETURN USBDeviceHandleSI::ProcessThread(void* pvParameter_)
  584. {
  585. USBDeviceHandleSI* This = reinterpret_cast<USBDeviceHandleSI*>(pvParameter_);
  586. This->ReceiveThread();
  587. return 0;
  588. }
  589. //Tries to talk to the device. If there is a failure, we assume the device is detached.
  590. BOOL USBDeviceHandleSI::DeviceIsGone()
  591. {
  592. if(bDeviceGone)
  593. return TRUE;
  594. UCHAR aucSerialString[255];
  595. UCHAR ucLength = 255;
  596. CP210x_STATUS eStatus = clCmLibrary.GetDeviceSerialNumber(hUSBDeviceHandle, aucSerialString, &ucLength, TRUE); //!!Or we could check make a device list and check if this device is in it.
  597. if(eStatus != CP210x_SUCCESS)
  598. return TRUE;
  599. return FALSE;
  600. }
  601. #endif //defined(DSI_TYPES_WINDOWS)