serialib.cpp 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134
  1. /*!
  2. \file serialib.cpp
  3. \brief Source file of the class serialib. This class is used for communication over a serial device.
  4. \author Philippe Lucidarme (University of Angers)
  5. \version 2.0
  6. \date december the 27th of 2019
  7. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
  8. INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
  9. PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE X CONSORTIUM BE LIABLE FOR ANY CLAIM,
  10. DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  11. FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  12. This is a licence-free software, it can be used by anyone who try to build a better world.
  13. */
  14. #include "serialib.h"
  15. //_____________________________________
  16. // ::: Constructors and destructors :::
  17. /*!
  18. \brief Constructor of the class serialib.
  19. */
  20. serialib::serialib()
  21. //serialib()
  22. {
  23. #if defined (_WIN32) || defined( _WIN64)
  24. // Set default value for RTS and DTR (Windows only)
  25. currentStateRTS=true;
  26. currentStateDTR=true;
  27. hSerial = INVALID_HANDLE_VALUE;
  28. #endif
  29. #if defined (__linux__) || defined(__APPLE__)
  30. fd = -1;
  31. #endif
  32. }
  33. /*!
  34. \brief Destructor of the class serialib. It close the connection
  35. */
  36. // Class desctructor
  37. serialib::~serialib()
  38. {
  39. closeDevice();
  40. }
  41. //_________________________________________
  42. // ::: Configuration and initialization :::
  43. /*!
  44. \brief Open the serial port
  45. \param Device : Port name (COM1, COM2, ... for Windows ) or (/dev/ttyS0, /dev/ttyACM0, /dev/ttyUSB0 ... for linux)
  46. \param Bauds : Baud rate of the serial port.
  47. \n Supported baud rate for Windows :
  48. - 110
  49. - 300
  50. - 600
  51. - 1200
  52. - 2400
  53. - 4800
  54. - 9600
  55. - 14400
  56. - 19200
  57. - 38400
  58. - 56000
  59. - 57600
  60. - 115200
  61. - 128000
  62. - 256000
  63. \n Supported baud rate for Linux :\n
  64. - 110
  65. - 300
  66. - 600
  67. - 1200
  68. - 2400
  69. - 4800
  70. - 9600
  71. - 19200
  72. - 38400
  73. - 57600
  74. - 115200
  75. \n Optionally supported baud rates, depending on Linux kernel:\n
  76. - 230400
  77. - 460800
  78. - 500000
  79. - 576000
  80. - 921600
  81. - 1000000
  82. - 1152000
  83. - 1500000
  84. - 2000000
  85. - 2500000
  86. - 3000000
  87. - 3500000
  88. - 4000000
  89. \param Databits : Number of data bits in one UART transmission.
  90. \n Supported values: \n
  91. - SERIAL_DATABITS_5 (5)
  92. - SERIAL_DATABITS_6 (6)
  93. - SERIAL_DATABITS_7 (7)
  94. - SERIAL_DATABITS_8 (8)
  95. - SERIAL_DATABITS_16 (16) (not supported on Unix)
  96. \param Parity: Parity type
  97. \n Supported values: \n
  98. - SERIAL_PARITY_NONE (N)
  99. - SERIAL_PARITY_EVEN (E)
  100. - SERIAL_PARITY_ODD (O)
  101. - SERIAL_PARITY_MARK (MARK) (not supported on Unix)
  102. - SERIAL_PARITY_SPACE (SPACE) (not supported on Unix)
  103. \param Stopbit: Number of stop bits
  104. \n Supported values:
  105. - SERIAL_STOPBITS_1 (1)
  106. - SERIAL_STOPBITS_1_5 (1.5) (not supported on Unix)
  107. - SERIAL_STOPBITS_2 (2)
  108. \return 1 success
  109. \return -1 device not found
  110. \return -2 error while opening the device
  111. \return -3 error while getting port parameters
  112. \return -4 Speed (Bauds) not recognized
  113. \return -5 error while writing port parameters
  114. \return -6 error while writing timeout parameters
  115. \return -7 Databits not recognized
  116. \return -8 Stopbits not recognized
  117. \return -9 Parity not recognized
  118. */
  119. char serialib::openDevice(const char *Device, const unsigned int Bauds,
  120. SerialDataBits Databits,
  121. SerialParity Parity,
  122. SerialStopBits Stopbits) {
  123. #if defined (_WIN32) || defined( _WIN64)
  124. // Open serial port
  125. hSerial = CreateFileA(Device,GENERIC_READ | GENERIC_WRITE,0,0,OPEN_EXISTING,/*FILE_ATTRIBUTE_NORMAL*/0,0);
  126. if(hSerial==INVALID_HANDLE_VALUE) {
  127. if(GetLastError()==ERROR_FILE_NOT_FOUND)
  128. return -1; // Device not found
  129. // Error while opening the device
  130. return -2;
  131. }
  132. // Set parameters
  133. // Structure for the port parameters
  134. DCB dcbSerialParams;
  135. dcbSerialParams.DCBlength=sizeof(dcbSerialParams);
  136. // Get the port parameters
  137. if (!GetCommState(hSerial, &dcbSerialParams)) return -3;
  138. // Set the speed (Bauds)
  139. switch (Bauds)
  140. {
  141. case 110 : dcbSerialParams.BaudRate=CBR_110; break;
  142. case 300 : dcbSerialParams.BaudRate=CBR_300; break;
  143. case 600 : dcbSerialParams.BaudRate=CBR_600; break;
  144. case 1200 : dcbSerialParams.BaudRate=CBR_1200; break;
  145. case 2400 : dcbSerialParams.BaudRate=CBR_2400; break;
  146. case 4800 : dcbSerialParams.BaudRate=CBR_4800; break;
  147. case 9600 : dcbSerialParams.BaudRate=CBR_9600; break;
  148. case 14400 : dcbSerialParams.BaudRate=CBR_14400; break;
  149. case 19200 : dcbSerialParams.BaudRate=CBR_19200; break;
  150. case 38400 : dcbSerialParams.BaudRate=CBR_38400; break;
  151. case 56000 : dcbSerialParams.BaudRate=CBR_56000; break;
  152. case 57600 : dcbSerialParams.BaudRate=CBR_57600; break;
  153. case 115200 : dcbSerialParams.BaudRate=CBR_115200; break;
  154. case 128000 : dcbSerialParams.BaudRate=CBR_128000; break;
  155. case 256000 : dcbSerialParams.BaudRate=CBR_256000; break;
  156. default : return -4;
  157. }
  158. //select data size
  159. BYTE bytesize = 0;
  160. switch(Databits) {
  161. case SERIAL_DATABITS_5: bytesize = 5; break;
  162. case SERIAL_DATABITS_6: bytesize = 6; break;
  163. case SERIAL_DATABITS_7: bytesize = 7; break;
  164. case SERIAL_DATABITS_8: bytesize = 8; break;
  165. case SERIAL_DATABITS_16: bytesize = 16; break;
  166. default: return -7;
  167. }
  168. BYTE stopBits = 0;
  169. switch(Stopbits) {
  170. case SERIAL_STOPBITS_1: stopBits = ONESTOPBIT; break;
  171. case SERIAL_STOPBITS_1_5: stopBits = ONE5STOPBITS; break;
  172. case SERIAL_STOPBITS_2: stopBits = TWOSTOPBITS; break;
  173. default: return -8;
  174. }
  175. BYTE parity = 0;
  176. switch(Parity) {
  177. case SERIAL_PARITY_NONE: parity = NOPARITY; break;
  178. case SERIAL_PARITY_EVEN: parity = EVENPARITY; break;
  179. case SERIAL_PARITY_ODD: parity = ODDPARITY; break;
  180. case SERIAL_PARITY_MARK: parity = MARKPARITY; break;
  181. case SERIAL_PARITY_SPACE: parity = SPACEPARITY; break;
  182. default: return -9;
  183. }
  184. // configure byte size
  185. dcbSerialParams.ByteSize = bytesize;
  186. // configure stop bits
  187. dcbSerialParams.StopBits = stopBits;
  188. // configure parity
  189. dcbSerialParams.Parity = parity;
  190. // Write the parameters
  191. if(!SetCommState(hSerial, &dcbSerialParams)) return -5;
  192. // Set TimeOut
  193. // Set the Timeout parameters
  194. timeouts.ReadIntervalTimeout=0;
  195. // No TimeOut
  196. timeouts.ReadTotalTimeoutConstant=MAXDWORD;
  197. timeouts.ReadTotalTimeoutMultiplier=0;
  198. timeouts.WriteTotalTimeoutConstant=MAXDWORD;
  199. timeouts.WriteTotalTimeoutMultiplier=0;
  200. // Write the parameters
  201. if(!SetCommTimeouts(hSerial, &timeouts)) return -6;
  202. // Opening successfull
  203. return 1;
  204. #endif
  205. #if defined (__linux__) || defined(__APPLE__)
  206. // Structure with the device's options
  207. struct termios options;
  208. // Open device
  209. fd = open(Device, O_RDWR | O_NOCTTY | O_NDELAY);
  210. // If the device is not open, return -1
  211. if (fd == -1) return -2;
  212. // Open the device in nonblocking mode
  213. fcntl(fd, F_SETFL, FNDELAY);
  214. // Get the current options of the port
  215. tcgetattr(fd, &options);
  216. // Clear all the options
  217. bzero(&options, sizeof(options));
  218. // Prepare speed (Bauds)
  219. speed_t Speed;
  220. switch (Bauds)
  221. {
  222. case 110 : Speed=B110; break;
  223. case 300 : Speed=B300; break;
  224. case 600 : Speed=B600; break;
  225. case 1200 : Speed=B1200; break;
  226. case 2400 : Speed=B2400; break;
  227. case 4800 : Speed=B4800; break;
  228. case 9600 : Speed=B9600; break;
  229. case 19200 : Speed=B19200; break;
  230. case 38400 : Speed=B38400; break;
  231. case 57600 : Speed=B57600; break;
  232. case 115200 : Speed=B115200; break;
  233. #if defined (B230400)
  234. case 230400 : Speed=B230400; break;
  235. #endif
  236. #if defined (B460800)
  237. case 460800 : Speed=B460800; break;
  238. #endif
  239. #if defined (B500000)
  240. case 500000 : Speed=B500000; break;
  241. #endif
  242. #if defined (B576000)
  243. case 576000 : Speed=B576000; break;
  244. #endif
  245. #if defined (B921600)
  246. case 921600 : Speed=B921600; break;
  247. #endif
  248. #if defined (B1000000)
  249. case 1000000 : Speed=B1000000; break;
  250. #endif
  251. #if defined (B1152000)
  252. case 1152000 : Speed=B1152000; break;
  253. #endif
  254. #if defined (B1500000)
  255. case 1500000 : Speed=B1500000; break;
  256. #endif
  257. #if defined (B2000000)
  258. case 2000000 : Speed=B2000000; break;
  259. #endif
  260. #if defined (B2500000)
  261. case 2500000 : Speed=B2500000; break;
  262. #endif
  263. #if defined (B3000000)
  264. case 3000000 : Speed=B3000000; break;
  265. #endif
  266. #if defined (B3500000)
  267. case 3500000 : Speed=B3500000; break;
  268. #endif
  269. #if defined (B4000000)
  270. case 4000000 : Speed=B4000000; break;
  271. #endif
  272. default : return -4;
  273. }
  274. int databits_flag = 0;
  275. switch(Databits) {
  276. case SERIAL_DATABITS_5: databits_flag = CS5; break;
  277. case SERIAL_DATABITS_6: databits_flag = CS6; break;
  278. case SERIAL_DATABITS_7: databits_flag = CS7; break;
  279. case SERIAL_DATABITS_8: databits_flag = CS8; break;
  280. //16 bits and everything else not supported
  281. default: return -7;
  282. }
  283. int stopbits_flag = 0;
  284. switch(Stopbits) {
  285. case SERIAL_STOPBITS_1: stopbits_flag = 0; break;
  286. case SERIAL_STOPBITS_2: stopbits_flag = CSTOPB; break;
  287. //1.5 stopbits and everything else not supported
  288. default: return -8;
  289. }
  290. int parity_flag = 0;
  291. switch(Parity) {
  292. case SERIAL_PARITY_NONE: parity_flag = 0; break;
  293. case SERIAL_PARITY_EVEN: parity_flag = PARENB; break;
  294. case SERIAL_PARITY_ODD: parity_flag = (PARENB | PARODD); break;
  295. //mark and space parity not supported
  296. default: return -9;
  297. }
  298. // Set the baud rate
  299. cfsetispeed(&options, Speed);
  300. cfsetospeed(&options, Speed);
  301. // Configure the device : data bits, stop bits, parity, no control flow
  302. // Ignore modem control lines (CLOCAL) and Enable receiver (CREAD)
  303. options.c_cflag |= ( CLOCAL | CREAD | databits_flag | parity_flag | stopbits_flag);
  304. options.c_iflag |= ( IGNPAR | IGNBRK );
  305. // Timer unused
  306. options.c_cc[VTIME]=0;
  307. // At least on character before satisfy reading
  308. options.c_cc[VMIN]=0;
  309. // Activate the settings
  310. tcsetattr(fd, TCSANOW, &options);
  311. // Success
  312. return (1);
  313. #endif
  314. }
  315. bool serialib::isDeviceOpen()
  316. {
  317. #if defined (_WIN32) || defined( _WIN64)
  318. return hSerial != INVALID_HANDLE_VALUE;
  319. #endif
  320. #if defined (__linux__) || defined(__APPLE__)
  321. return fd >= 0;
  322. #endif
  323. }
  324. /*!
  325. \brief Close the connection with the current device
  326. */
  327. void serialib::closeDevice()
  328. {
  329. #if defined (_WIN32) || defined( _WIN64)
  330. CloseHandle(hSerial);
  331. hSerial = INVALID_HANDLE_VALUE;
  332. #endif
  333. #if defined (__linux__) || defined(__APPLE__)
  334. close (fd);
  335. fd = -1;
  336. #endif
  337. }
  338. //___________________________________________
  339. // ::: Read/Write operation on characters :::
  340. /*!
  341. \brief Write a char on the current serial port
  342. \param Byte : char to send on the port (must be terminated by '\0')
  343. \return 1 success
  344. \return -1 error while writting data
  345. */
  346. int serialib::writeChar(const char Byte)
  347. {
  348. #if defined (_WIN32) || defined( _WIN64)
  349. // Number of bytes written
  350. DWORD dwBytesWritten;
  351. // Write the char to the serial device
  352. // Return -1 if an error occured
  353. if(!WriteFile(hSerial,&Byte,1,&dwBytesWritten,NULL)) return -1;
  354. // Write operation successfull
  355. return 1;
  356. #endif
  357. #if defined (__linux__) || defined(__APPLE__)
  358. // Write the char
  359. if (write(fd,&Byte,1)!=1) return -1;
  360. // Write operation successfull
  361. return 1;
  362. #endif
  363. }
  364. //________________________________________
  365. // ::: Read/Write operation on strings :::
  366. /*!
  367. \brief Write a string on the current serial port
  368. \param receivedString : string to send on the port (must be terminated by '\0')
  369. \return 1 success
  370. \return -1 error while writting data
  371. */
  372. int serialib::writeString(const char *receivedString)
  373. {
  374. #if defined (_WIN32) || defined( _WIN64)
  375. // Number of bytes written
  376. DWORD dwBytesWritten;
  377. // Write the string
  378. if(!WriteFile(hSerial,receivedString,strlen(receivedString),&dwBytesWritten,NULL))
  379. // Error while writing, return -1
  380. return -1;
  381. // Write operation successfull
  382. return 1;
  383. #endif
  384. #if defined (__linux__) || defined(__APPLE__)
  385. // Lenght of the string
  386. int Lenght=strlen(receivedString);
  387. // Write the string
  388. if (write(fd,receivedString,Lenght)!=Lenght) return -1;
  389. // Write operation successfull
  390. return 1;
  391. #endif
  392. }
  393. // _____________________________________
  394. // ::: Read/Write operation on bytes :::
  395. /*!
  396. \brief Write an array of data on the current serial port
  397. \param Buffer : array of bytes to send on the port
  398. \param NbBytes : number of byte to send
  399. \return 1 success
  400. \return -1 error while writting data
  401. */
  402. int serialib::writeBytes(const void *Buffer, const unsigned int NbBytes)
  403. {
  404. #if defined (_WIN32) || defined( _WIN64)
  405. // Number of bytes written
  406. DWORD dwBytesWritten;
  407. // Write data
  408. if(!WriteFile(hSerial, Buffer, NbBytes, &dwBytesWritten, NULL))
  409. // Error while writing, return -1
  410. return -1;
  411. // Write operation successfull
  412. return 1;
  413. #endif
  414. #if defined (__linux__) || defined(__APPLE__)
  415. // Write data
  416. if (write (fd,Buffer,NbBytes)!=(ssize_t)NbBytes) return -1;
  417. // Write operation successfull
  418. return 1;
  419. #endif
  420. }
  421. /*!
  422. \brief Wait for a byte from the serial device and return the data read
  423. \param pByte : data read on the serial device
  424. \param timeOut_ms : delay of timeout before giving up the reading
  425. If set to zero, timeout is disable (Optional)
  426. \return 1 success
  427. \return 0 Timeout reached
  428. \return -1 error while setting the Timeout
  429. \return -2 error while reading the byte
  430. */
  431. int serialib::readChar(char *pByte,unsigned int timeOut_ms)
  432. {
  433. #if defined (_WIN32) || defined(_WIN64)
  434. // Number of bytes read
  435. DWORD dwBytesRead = 0;
  436. // Set the TimeOut
  437. timeouts.ReadTotalTimeoutConstant=timeOut_ms;
  438. // Write the parameters, return -1 if an error occured
  439. if(!SetCommTimeouts(hSerial, &timeouts)) return -1;
  440. // Read the byte, return -2 if an error occured
  441. if(!ReadFile(hSerial,pByte, 1, &dwBytesRead, NULL)) return -2;
  442. // Return 0 if the timeout is reached
  443. if (dwBytesRead==0) return 0;
  444. // The byte is read
  445. return 1;
  446. #endif
  447. #if defined (__linux__) || defined(__APPLE__)
  448. // Timer used for timeout
  449. timeOut timer;
  450. // Initialise the timer
  451. timer.initTimer();
  452. // While Timeout is not reached
  453. while (timer.elapsedTime_ms()<timeOut_ms || timeOut_ms==0)
  454. {
  455. // Try to read a byte on the device
  456. switch (read(fd,pByte,1)) {
  457. case 1 : return 1; // Read successfull
  458. case -1 : return -2; // Error while reading
  459. }
  460. }
  461. return 0;
  462. #endif
  463. }
  464. /*!
  465. \brief Read a string from the serial device (without TimeOut)
  466. \param receivedString : string read on the serial device
  467. \param FinalChar : final char of the string
  468. \param MaxNbBytes : maximum allowed number of bytes read
  469. \return >0 success, return the number of bytes read
  470. \return -1 error while setting the Timeout
  471. \return -2 error while reading the byte
  472. \return -3 MaxNbBytes is reached
  473. */
  474. int serialib::readStringNoTimeOut(char *receivedString,char finalChar,unsigned int maxNbBytes)
  475. {
  476. // Number of characters read
  477. unsigned int NbBytes=0;
  478. // Returned value from Read
  479. char charRead;
  480. // While the buffer is not full
  481. while (NbBytes<maxNbBytes)
  482. {
  483. // Read a character with the restant time
  484. charRead=readChar(&receivedString[NbBytes]);
  485. // Check a character has been read
  486. if (charRead==1)
  487. {
  488. // Check if this is the final char
  489. if (receivedString[NbBytes]==finalChar)
  490. {
  491. // This is the final char, add zero (end of string)
  492. receivedString [++NbBytes]=0;
  493. // Return the number of bytes read
  494. return NbBytes;
  495. }
  496. // The character is not the final char, increase the number of bytes read
  497. NbBytes++;
  498. }
  499. // An error occured while reading, return the error number
  500. if (charRead<0) return charRead;
  501. }
  502. // Buffer is full : return -3
  503. return -3;
  504. }
  505. /*!
  506. \brief Read a string from the serial device (with timeout)
  507. \param receivedString : string read on the serial device
  508. \param finalChar : final char of the string
  509. \param maxNbBytes : maximum allowed number of characters read
  510. \param timeOut_ms : delay of timeout before giving up the reading (optional)
  511. \return >0 success, return the number of bytes read (including the null character)
  512. \return 0 timeout is reached
  513. \return -1 error while setting the Timeout
  514. \return -2 error while reading the character
  515. \return -3 MaxNbBytes is reached
  516. */
  517. int serialib::readString(char *receivedString,char finalChar,unsigned int maxNbBytes,unsigned int timeOut_ms)
  518. {
  519. // Check if timeout is requested
  520. if (timeOut_ms==0) return readStringNoTimeOut(receivedString,finalChar,maxNbBytes);
  521. // Number of bytes read
  522. unsigned int nbBytes=0;
  523. // Character read on serial device
  524. char charRead;
  525. // Timer used for timeout
  526. timeOut timer;
  527. long int timeOutParam;
  528. // Initialize the timer (for timeout)
  529. timer.initTimer();
  530. // While the buffer is not full
  531. while (nbBytes<maxNbBytes)
  532. {
  533. // Compute the TimeOut for the next call of ReadChar
  534. timeOutParam = timeOut_ms-timer.elapsedTime_ms();
  535. // If there is time remaining
  536. if (timeOutParam>0)
  537. {
  538. // Wait for a byte on the serial link with the remaining time as timeout
  539. charRead=readChar(&receivedString[nbBytes],timeOutParam);
  540. // If a byte has been received
  541. if (charRead==1)
  542. {
  543. // Check if the character received is the final one
  544. if (receivedString[nbBytes]==finalChar)
  545. {
  546. // Final character: add the end character 0
  547. receivedString [++nbBytes]=0;
  548. // Return the number of bytes read
  549. return nbBytes;
  550. }
  551. // This is not the final character, just increase the number of bytes read
  552. nbBytes++;
  553. }
  554. // Check if an error occured during reading char
  555. // If an error occurend, return the error number
  556. if (charRead<0) return charRead;
  557. }
  558. // Check if timeout is reached
  559. if (timer.elapsedTime_ms()>timeOut_ms)
  560. {
  561. // Add the end caracter
  562. receivedString[nbBytes]=0;
  563. // Return 0 (timeout reached)
  564. return 0;
  565. }
  566. }
  567. // Buffer is full : return -3
  568. return -3;
  569. }
  570. /*!
  571. \brief Read an array of bytes from the serial device (with timeout)
  572. \param buffer : array of bytes read from the serial device
  573. \param maxNbBytes : maximum allowed number of bytes read
  574. \param timeOut_ms : delay of timeout before giving up the reading
  575. \param sleepDuration_us : delay of CPU relaxing in microseconds (Linux only)
  576. In the reading loop, a sleep can be performed after each reading
  577. This allows CPU to perform other tasks
  578. \return >=0 return the number of bytes read before timeout or
  579. requested data is completed
  580. \return -1 error while setting the Timeout
  581. \return -2 error while reading the byte
  582. */
  583. int serialib::readBytes (void *buffer,unsigned int maxNbBytes,unsigned int timeOut_ms, unsigned int sleepDuration_us)
  584. {
  585. #if defined (_WIN32) || defined(_WIN64)
  586. // Avoid warning while compiling
  587. UNUSED(sleepDuration_us);
  588. // Number of bytes read
  589. DWORD dwBytesRead = 0;
  590. // Set the TimeOut
  591. timeouts.ReadTotalTimeoutConstant=(DWORD)timeOut_ms;
  592. // Write the parameters and return -1 if an error occrured
  593. if(!SetCommTimeouts(hSerial, &timeouts)) return -1;
  594. // Read the bytes from the serial device, return -2 if an error occured
  595. if(!ReadFile(hSerial,buffer,(DWORD)maxNbBytes,&dwBytesRead, NULL)) return -2;
  596. // Return the byte read
  597. return dwBytesRead;
  598. #endif
  599. #if defined (__linux__) || defined(__APPLE__)
  600. // Timer used for timeout
  601. timeOut timer;
  602. // Initialise the timer
  603. timer.initTimer();
  604. unsigned int NbByteRead=0;
  605. // While Timeout is not reached
  606. while (timer.elapsedTime_ms()<timeOut_ms || timeOut_ms==0)
  607. {
  608. // Compute the position of the current byte
  609. unsigned char* Ptr=(unsigned char*)buffer+NbByteRead;
  610. // Try to read a byte on the device
  611. int Ret=read(fd,(void*)Ptr,maxNbBytes-NbByteRead);
  612. // Error while reading
  613. if (Ret==-1) return -2;
  614. // One or several byte(s) has been read on the device
  615. if (Ret>0)
  616. {
  617. // Increase the number of read bytes
  618. NbByteRead+=Ret;
  619. // Success : bytes has been read
  620. if (NbByteRead>=maxNbBytes)
  621. return NbByteRead;
  622. }
  623. // Suspend the loop to avoid charging the CPU
  624. usleep (sleepDuration_us);
  625. }
  626. // Timeout reached, return the number of bytes read
  627. return NbByteRead;
  628. #endif
  629. }
  630. // _________________________
  631. // ::: Special operation :::
  632. /*!
  633. \brief Empty receiver buffer
  634. \return If the function succeeds, the return value is nonzero.
  635. If the function fails, the return value is zero.
  636. */
  637. char serialib::flushReceiver()
  638. {
  639. #if defined (_WIN32) || defined(_WIN64)
  640. // Purge receiver
  641. return PurgeComm (hSerial, PURGE_RXCLEAR);
  642. #endif
  643. #if defined (__linux__) || defined(__APPLE__)
  644. // Purge receiver
  645. tcflush(fd,TCIFLUSH);
  646. return true;
  647. #endif
  648. }
  649. /*!
  650. \brief Return the number of bytes in the received buffer (UNIX only)
  651. \return The number of bytes received by the serial provider but not yet read.
  652. */
  653. int serialib::available()
  654. {
  655. #if defined (_WIN32) || defined(_WIN64)
  656. // Device errors
  657. DWORD commErrors;
  658. // Device status
  659. COMSTAT commStatus;
  660. // Read status
  661. ClearCommError(hSerial, &commErrors, &commStatus);
  662. // Return the number of pending bytes
  663. return commStatus.cbInQue;
  664. #endif
  665. #if defined (__linux__) || defined(__APPLE__)
  666. int nBytes=0;
  667. // Return number of pending bytes in the receiver
  668. ioctl(fd, FIONREAD, &nBytes);
  669. return nBytes;
  670. #endif
  671. }
  672. // __________________
  673. // ::: I/O Access :::
  674. /*!
  675. \brief Set or unset the bit DTR (pin 4)
  676. DTR stands for Data Terminal Ready
  677. Convenience method :This method calls setDTR and clearDTR
  678. \param status = true set DTR
  679. status = false unset DTR
  680. \return If the function fails, the return value is false
  681. If the function succeeds, the return value is true.
  682. */
  683. bool serialib::DTR(bool status)
  684. {
  685. if (status)
  686. // Set DTR
  687. return this->setDTR();
  688. else
  689. // Unset DTR
  690. return this->clearDTR();
  691. }
  692. /*!
  693. \brief Set the bit DTR (pin 4)
  694. DTR stands for Data Terminal Ready
  695. \return If the function fails, the return value is false
  696. If the function succeeds, the return value is true.
  697. */
  698. bool serialib::setDTR()
  699. {
  700. #if defined (_WIN32) || defined(_WIN64)
  701. // Set DTR
  702. currentStateDTR=true;
  703. return EscapeCommFunction(hSerial,SETDTR);
  704. #endif
  705. #if defined (__linux__) || defined(__APPLE__)
  706. // Set DTR
  707. int status_DTR=0;
  708. ioctl(fd, TIOCMGET, &status_DTR);
  709. status_DTR |= TIOCM_DTR;
  710. ioctl(fd, TIOCMSET, &status_DTR);
  711. return true;
  712. #endif
  713. }
  714. /*!
  715. \brief Clear the bit DTR (pin 4)
  716. DTR stands for Data Terminal Ready
  717. \return If the function fails, the return value is false
  718. If the function succeeds, the return value is true.
  719. */
  720. bool serialib::clearDTR()
  721. {
  722. #if defined (_WIN32) || defined(_WIN64)
  723. // Clear DTR
  724. currentStateDTR=true;
  725. return EscapeCommFunction(hSerial,CLRDTR);
  726. #endif
  727. #if defined (__linux__) || defined(__APPLE__)
  728. // Clear DTR
  729. int status_DTR=0;
  730. ioctl(fd, TIOCMGET, &status_DTR);
  731. status_DTR &= ~TIOCM_DTR;
  732. ioctl(fd, TIOCMSET, &status_DTR);
  733. return true;
  734. #endif
  735. }
  736. /*!
  737. \brief Set or unset the bit RTS (pin 7)
  738. RTS stands for Data Termina Ready
  739. Convenience method :This method calls setDTR and clearDTR
  740. \param status = true set DTR
  741. status = false unset DTR
  742. \return false if the function fails
  743. \return true if the function succeeds
  744. */
  745. bool serialib::RTS(bool status)
  746. {
  747. if (status)
  748. // Set RTS
  749. return this->setRTS();
  750. else
  751. // Unset RTS
  752. return this->clearRTS();
  753. }
  754. /*!
  755. \brief Set the bit RTS (pin 7)
  756. RTS stands for Data Terminal Ready
  757. \return If the function fails, the return value is false
  758. If the function succeeds, the return value is true.
  759. */
  760. bool serialib::setRTS()
  761. {
  762. #if defined (_WIN32) || defined(_WIN64)
  763. // Set RTS
  764. currentStateRTS=false;
  765. return EscapeCommFunction(hSerial,SETRTS);
  766. #endif
  767. #if defined (__linux__) || defined(__APPLE__)
  768. // Set RTS
  769. int status_RTS=0;
  770. ioctl(fd, TIOCMGET, &status_RTS);
  771. status_RTS |= TIOCM_RTS;
  772. ioctl(fd, TIOCMSET, &status_RTS);
  773. return true;
  774. #endif
  775. }
  776. /*!
  777. \brief Clear the bit RTS (pin 7)
  778. RTS stands for Data Terminal Ready
  779. \return If the function fails, the return value is false
  780. If the function succeeds, the return value is true.
  781. */
  782. bool serialib::clearRTS()
  783. {
  784. #if defined (_WIN32) || defined(_WIN64)
  785. // Clear RTS
  786. currentStateRTS=false;
  787. return EscapeCommFunction(hSerial,CLRRTS);
  788. #endif
  789. #if defined (__linux__) || defined(__APPLE__)
  790. // Clear RTS
  791. int status_RTS=0;
  792. ioctl(fd, TIOCMGET, &status_RTS);
  793. status_RTS &= ~TIOCM_RTS;
  794. ioctl(fd, TIOCMSET, &status_RTS);
  795. return true;
  796. #endif
  797. }
  798. /*!
  799. \brief Get the CTS's status (pin 8)
  800. CTS stands for Clear To Send
  801. \return Return true if CTS is set otherwise false
  802. */
  803. bool serialib::isCTS()
  804. {
  805. #if defined (_WIN32) || defined(_WIN64)
  806. DWORD modemStat;
  807. GetCommModemStatus(hSerial, &modemStat);
  808. return modemStat & MS_CTS_ON;
  809. #endif
  810. #if defined (__linux__) || defined(__APPLE__)
  811. int status=0;
  812. //Get the current status of the CTS bit
  813. ioctl(fd, TIOCMGET, &status);
  814. return status & TIOCM_CTS;
  815. #endif
  816. }
  817. /*!
  818. \brief Get the DSR's status (pin 6)
  819. DSR stands for Data Set Ready
  820. \return Return true if DTR is set otherwise false
  821. */
  822. bool serialib::isDSR()
  823. {
  824. #if defined (_WIN32) || defined(_WIN64)
  825. DWORD modemStat;
  826. GetCommModemStatus(hSerial, &modemStat);
  827. return modemStat & MS_DSR_ON;
  828. #endif
  829. #if defined (__linux__) || defined(__APPLE__)
  830. int status=0;
  831. //Get the current status of the DSR bit
  832. ioctl(fd, TIOCMGET, &status);
  833. return status & TIOCM_DSR;
  834. #endif
  835. }
  836. /*!
  837. \brief Get the DCD's status (pin 1)
  838. CDC stands for Data Carrier Detect
  839. \return true if DCD is set
  840. \return false otherwise
  841. */
  842. bool serialib::isDCD()
  843. {
  844. #if defined (_WIN32) || defined(_WIN64)
  845. DWORD modemStat;
  846. GetCommModemStatus(hSerial, &modemStat);
  847. return modemStat & MS_RLSD_ON;
  848. #endif
  849. #if defined (__linux__) || defined(__APPLE__)
  850. int status=0;
  851. //Get the current status of the DCD bit
  852. ioctl(fd, TIOCMGET, &status);
  853. return status & TIOCM_CAR;
  854. #endif
  855. }
  856. /*!
  857. \brief Get the RING's status (pin 9)
  858. Ring Indicator
  859. \return Return true if RING is set otherwise false
  860. */
  861. bool serialib::isRI()
  862. {
  863. #if defined (_WIN32) || defined(_WIN64)
  864. DWORD modemStat;
  865. GetCommModemStatus(hSerial, &modemStat);
  866. return modemStat & MS_RING_ON;
  867. #endif
  868. #if defined (__linux__) || defined(__APPLE__)
  869. int status=0;
  870. //Get the current status of the RING bit
  871. ioctl(fd, TIOCMGET, &status);
  872. return status & TIOCM_RNG;
  873. #endif
  874. }
  875. /*!
  876. \brief Get the DTR's status (pin 4)
  877. DTR stands for Data Terminal Ready
  878. May behave abnormally on Windows
  879. \return Return true if CTS is set otherwise false
  880. */
  881. bool serialib::isDTR()
  882. {
  883. #if defined (_WIN32) || defined( _WIN64)
  884. return currentStateDTR;
  885. #endif
  886. #if defined (__linux__) || defined(__APPLE__)
  887. int status=0;
  888. //Get the current status of the DTR bit
  889. ioctl(fd, TIOCMGET, &status);
  890. return status & TIOCM_DTR ;
  891. #endif
  892. }
  893. /*!
  894. \brief Get the RTS's status (pin 7)
  895. RTS stands for Request To Send
  896. May behave abnormally on Windows
  897. \return Return true if RTS is set otherwise false
  898. */
  899. bool serialib::isRTS()
  900. {
  901. #if defined (_WIN32) || defined(_WIN64)
  902. return currentStateRTS;
  903. #endif
  904. #if defined (__linux__) || defined(__APPLE__)
  905. int status=0;
  906. //Get the current status of the CTS bit
  907. ioctl(fd, TIOCMGET, &status);
  908. return status & TIOCM_RTS;
  909. #endif
  910. }
  911. // ******************************************
  912. // Class timeOut
  913. // ******************************************
  914. /*!
  915. \brief Constructor of the class timeOut.
  916. */
  917. // Constructor
  918. timeOut::timeOut()
  919. {}
  920. /*!
  921. \brief Initialise the timer. It writes the current time of the day in the structure PreviousTime.
  922. */
  923. //Initialize the timer
  924. void timeOut::initTimer()
  925. {
  926. #if defined (NO_POSIX_TIME)
  927. LARGE_INTEGER tmp;
  928. QueryPerformanceFrequency(&tmp);
  929. counterFrequency = tmp.QuadPart;
  930. // Used to store the previous time (for computing timeout)
  931. QueryPerformanceCounter(&tmp);
  932. previousTime = tmp.QuadPart;
  933. #else
  934. gettimeofday(&previousTime, NULL);
  935. #endif
  936. }
  937. /*!
  938. \brief Returns the time elapsed since initialization. It write the current time of the day in the structure CurrentTime.
  939. Then it returns the difference between CurrentTime and PreviousTime.
  940. \return The number of microseconds elapsed since the functions InitTimer was called.
  941. */
  942. //Return the elapsed time since initialization
  943. unsigned long int timeOut::elapsedTime_ms()
  944. {
  945. #if defined (NO_POSIX_TIME)
  946. // Current time
  947. LARGE_INTEGER CurrentTime;
  948. // Number of ticks since last call
  949. int sec;
  950. // Get current time
  951. QueryPerformanceCounter(&CurrentTime);
  952. // Compute the number of ticks elapsed since last call
  953. sec=CurrentTime.QuadPart-previousTime;
  954. // Return the elapsed time in milliseconds
  955. return sec/(counterFrequency/1000);
  956. #else
  957. // Current time
  958. struct timeval CurrentTime;
  959. // Number of seconds and microseconds since last call
  960. int sec,usec;
  961. // Get current time
  962. gettimeofday(&CurrentTime, NULL);
  963. // Compute the number of seconds and microseconds elapsed since last call
  964. sec=CurrentTime.tv_sec-previousTime.tv_sec;
  965. usec=CurrentTime.tv_usec-previousTime.tv_usec;
  966. // If the previous usec is higher than the current one
  967. if (usec<0)
  968. {
  969. // Recompute the microseonds and substract one second
  970. usec=1000000-previousTime.tv_usec+CurrentTime.tv_usec;
  971. sec--;
  972. }
  973. // Return the elapsed time in milliseconds
  974. return sec*1000+usec/1000;
  975. #endif
  976. }