rs232_windows.c 26 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190
  1. /*
  2. * Copyright (c) 2011 Petr Stetiar <[email protected]>, Gaben Ltd.
  3. *
  4. * Permission is hereby granted, free of charge, to any person
  5. * obtaining a copy of this software and associated documentation
  6. * files (the "Software"), to deal in the Software without
  7. * restriction, including without limitation the rights to use,
  8. * copy, modify, merge, publish, distribute, sublicense, and/or sell
  9. * copies of the Software, and to permit persons to whom the
  10. * Software is furnished to do so, subject to the following
  11. * conditions:
  12. *
  13. * The above copyright notice and this permission notice shall be
  14. * included in all copies or substantial portions of the Software.
  15. *
  16. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  17. * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
  18. * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  19. * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
  20. * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
  21. * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  22. * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  23. * OTHER DEALINGS IN THE SOFTWARE.
  24. *
  25. */
  26. #include <stdio.h>
  27. #include <stdlib.h>
  28. #include <string.h>
  29. #include <ctype.h>
  30. #include <assert.h>
  31. #ifndef UNDER_CE
  32. #include <errno.h>
  33. #endif
  34. #include "librs232/rs232.h"
  35. typedef DWORD monotonic_time_t;
  36. typedef DWORD monotonic_diff_t;
  37. static monotonic_time_t GetMonotonicTime(){
  38. return GetTickCount();
  39. }
  40. static monotonic_diff_t GetMonotonicDelta(monotonic_time_t StartTime, monotonic_time_t EndTime){
  41. if(StartTime > EndTime)
  42. return (MAXDWORD - StartTime) + EndTime;
  43. return EndTime - StartTime;
  44. }
  45. #define READ_EVENTS (EV_RXCHAR | EV_ERR | EV_BREAK)
  46. #define READ_LATENTENCY 500
  47. #define R_BUFFER_SIZE 1024
  48. #define W_BUFFER_SIZE 1024
  49. #define USE_OVERLAPPED
  50. static wchar_t *
  51. a2w(const char *astr)
  52. {
  53. size_t len = 0;
  54. wchar_t *ret = NULL;
  55. if (astr == NULL)
  56. return NULL;
  57. len = strlen(astr);
  58. if (len > 0) {
  59. ret = (wchar_t*)malloc((len*2)+1 * sizeof(wchar_t*));
  60. memset(ret, 0, (len*2));
  61. MultiByteToWideChar(CP_ACP, 0, astr, -1, ret, (int)len);
  62. ret[len] = '\0';
  63. } else
  64. ret = NULL;
  65. return ret;
  66. }
  67. #ifdef RS232_DEBUG
  68. static char * last_error(void)
  69. {
  70. DWORD err = 0;
  71. DWORD ret = 0;
  72. char errbuf[MAX_PATH+1] = {0};
  73. static char retbuf[MAX_PATH+1] = {0};
  74. err = GetLastError();
  75. ret = FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, NULL, err, 0, errbuf, MAX_PATH, NULL);
  76. if (ret != 0) {
  77. /* CRLF fun */
  78. errbuf[ret-2] = 0;
  79. snprintf(retbuf, MAX_PATH, "LastError: %s (%ld)", errbuf, ret);
  80. }
  81. else
  82. snprintf(retbuf, MAX_PATH, "LastError: %ld (FormatMessageA failed)", ret);
  83. return retbuf;
  84. }
  85. #endif
  86. RS232_LIB struct rs232_port_t *
  87. rs232_init(void)
  88. {
  89. struct rs232_port_t *p = NULL;
  90. struct rs232_windows_t *wx = NULL;
  91. p = (struct rs232_port_t *) malloc(sizeof(struct rs232_port_t));
  92. if (p == NULL)
  93. return NULL;
  94. p->pt = (struct rs232_windows_t *) malloc(sizeof(struct rs232_windows_t));
  95. if (p->pt == NULL) {
  96. free(p);
  97. return NULL;
  98. }
  99. DBG("p=%p p->pt=%p\n", (void *)p, p->pt);
  100. memset(p->dev, 0, RS232_STRLEN_DEVICE+1);
  101. strncpyz(p->dev, RS232_PORT_WIN32, RS232_STRLEN_DEVICE);
  102. p->baud = RS232_BAUD_115200;
  103. p->data = RS232_DATA_8;
  104. p->parity = RS232_PARITY_NONE;
  105. p->stop = RS232_STOP_1;
  106. p->flow = RS232_FLOW_OFF;
  107. p->status = RS232_PORT_CLOSED;
  108. p->dtr = RS232_DTR_OFF;
  109. p->rts = RS232_RTS_OFF;
  110. wx = (struct rs232_windows_t *) p->pt;
  111. wx->r_timeout = READ_LATENTENCY;
  112. wx->w_timeout = READ_LATENTENCY;
  113. wx->r_buffer = R_BUFFER_SIZE;
  114. wx->w_buffer = W_BUFFER_SIZE;
  115. return p;
  116. }
  117. static unsigned int
  118. port_buffers(struct rs232_port_t *p, unsigned int rb, unsigned int wb)
  119. {
  120. struct rs232_windows_t *wx = p->pt;
  121. DBG("p=%p p->pt=%p rb=%d wb=%d\n", (void *)p, p->pt, rb, wb);
  122. if (!SetupComm(wx->fd, rb, wb)) {
  123. DBG("SetupComm() %s\n", last_error());
  124. return RS232_ERR_UNKNOWN;
  125. }
  126. wx->r_buffer = rb;
  127. wx->w_buffer = wb;
  128. return RS232_ERR_NOERROR;
  129. }
  130. static unsigned int
  131. port_timeout(struct rs232_port_t *p, unsigned int rt, unsigned int wt)
  132. {
  133. struct rs232_windows_t *wx = p->pt;
  134. COMMTIMEOUTS t;
  135. GET_PORT_TIMEOUTS(wx->fd, &t);
  136. t.ReadIntervalTimeout = 0;
  137. t.ReadTotalTimeoutMultiplier = 0;
  138. t.ReadTotalTimeoutConstant = rt;
  139. t.WriteTotalTimeoutMultiplier = 0;
  140. t.WriteTotalTimeoutConstant = wt;
  141. SET_PORT_TIMEOUTS(wx->fd, &t);
  142. wx->w_timeout = wt;
  143. wx->r_timeout = rt;
  144. return RS232_ERR_NOERROR;
  145. }
  146. RS232_LIB void
  147. rs232_end(struct rs232_port_t *p)
  148. {
  149. struct rs232_windows_t *wx = p->pt;
  150. DBG("p=%p p->pt=%p\n", (void *)p, p->pt);
  151. if (!rs232_port_open(p)) {
  152. free(p->pt);
  153. free(p);
  154. return;
  155. }
  156. rs232_flush(p);
  157. if (!SetCommState(wx->fd, &wx->old_dcb)) {
  158. DBG("SetCommState() %s\n", last_error());
  159. return;
  160. }
  161. if (!SetCommTimeouts(wx->fd, &wx->old_tm)) {
  162. DBG("SetCommTimeouts() %s\n", last_error());
  163. return;
  164. }
  165. rs232_close(p);
  166. free(p->pt);
  167. free(p);
  168. }
  169. RS232_LIB unsigned int
  170. rs232_in_queue(struct rs232_port_t *p, unsigned int *in_bytes)
  171. {
  172. COMSTAT cs;
  173. unsigned long errmask = 0;
  174. struct rs232_windows_t *wx = p->pt;
  175. DBG("p=%p p->pt=%p\n", (void *)p, p->pt);
  176. if (!rs232_port_open(p))
  177. return RS232_ERR_PORT_CLOSED;
  178. if (!ClearCommError(wx->fd, &errmask, &cs)) {
  179. DBG("ClearCommError() %s\n", last_error());
  180. return RS232_ERR_IOCTL;
  181. }
  182. *in_bytes = cs.cbInQue;
  183. DBG("in_bytes=%d\n", cs.cbInQue);
  184. return RS232_ERR_NOERROR;
  185. }
  186. /* some USB<->RS232 converters buffer a lot, so this function tries to discard
  187. this buffer - useful mainly after rs232_open() */
  188. RS232_LIB void
  189. rs232_in_queue_clear(struct rs232_port_t *p)
  190. {
  191. struct rs232_windows_t *wx = p->pt;
  192. DBG("p=%p p->pt=%p\n", (void *)p, p->pt);
  193. if (!rs232_port_open(p))
  194. return;
  195. if (!PurgeComm(wx->fd, PURGE_RXABORT | PURGE_RXCLEAR)) {
  196. DBG("PurgeComm() %s\n", last_error());
  197. return;
  198. }
  199. return;
  200. }
  201. //{ Non overlapped IO
  202. static unsigned int
  203. rs232_read_impl(struct rs232_port_t *p, unsigned char *buf, unsigned int buf_len,
  204. unsigned int *read_len)
  205. {
  206. DWORD r = 0;
  207. struct rs232_windows_t *wx = p->pt;
  208. if (!ReadFile(wx->fd, buf, buf_len, &r, NULL)) {
  209. *read_len = 0;
  210. DBG("ReadFile() %s\n", last_error());
  211. return RS232_ERR_READ;
  212. }
  213. *read_len = r;
  214. return RS232_ERR_NOERROR;
  215. }
  216. static unsigned int
  217. rs232_read_timeout_impl(struct rs232_port_t *p, unsigned char *buf,
  218. unsigned int buf_len, unsigned int *read_len,
  219. unsigned int timeout)
  220. {
  221. DWORD r = 0;
  222. struct rs232_windows_t *wx = p->pt;
  223. unsigned int rt = wx->r_timeout;
  224. *read_len = 0;
  225. if (port_timeout(p, timeout, wx->w_timeout))
  226. return RS232_ERR_UNKNOWN;
  227. if (!ReadFile(wx->fd, buf, buf_len, &r, NULL)) {
  228. *read_len = 0;
  229. DBG("ReadFile() %s\n", last_error());
  230. return RS232_ERR_READ;
  231. }
  232. if (port_timeout(p, rt, wx->w_timeout))
  233. return RS232_ERR_UNKNOWN;
  234. *read_len = r;
  235. /* TODO - This is lame, since we rely on the fact, that if we read 0 bytes,
  236. * that the read probably timeouted. So we should rather measure the reading
  237. * interval or rework it using overlapped I/O */
  238. return *read_len == 0 ? RS232_ERR_TIMEOUT : RS232_ERR_NOERROR;
  239. }
  240. /* this function waits either for timeout or buf_len bytes,
  241. whatever happens first and doesn't return earlier */
  242. static unsigned int
  243. rs232_read_timeout_forced_impl(struct rs232_port_t *p, unsigned char *buf,
  244. unsigned int buf_len, unsigned int *read_len,
  245. unsigned int timeout)
  246. {
  247. monotonic_time_t started = GetMonotonicTime();
  248. *read_len = 0;
  249. while(*read_len < buf_len){
  250. monotonic_diff_t elapsed = GetMonotonicDelta(started, GetMonotonicTime());
  251. unsigned int ret, readed = 0;
  252. if(elapsed >= timeout){
  253. return RS232_ERR_TIMEOUT;
  254. }
  255. ret = rs232_read_timeout_impl(p, &buf[*read_len], buf_len - *read_len, &readed, timeout - elapsed);
  256. if(ret == RS232_ERR_NOERROR){
  257. *read_len += readed;
  258. }
  259. else if(ret != RS232_ERR_TIMEOUT){
  260. return ret;
  261. }
  262. }
  263. return RS232_ERR_NOERROR;
  264. }
  265. static unsigned int
  266. rs232_write_impl(struct rs232_port_t *p, const unsigned char *buf, unsigned int buf_len,
  267. unsigned int *write_len)
  268. {
  269. DWORD w = 0;
  270. struct rs232_windows_t *wx = p->pt;
  271. if (!WriteFile(wx->fd, buf, buf_len, &w, NULL)) {
  272. *write_len = 0;
  273. DBG("WriteFile() %s\n", last_error());
  274. return RS232_ERR_WRITE;
  275. }
  276. if (buf_len != w)
  277. DBG("WriteFile() %s\n", last_error());
  278. *write_len = w;
  279. return RS232_ERR_NOERROR;
  280. }
  281. static unsigned int
  282. rs232_write_timeout_impl(struct rs232_port_t *p, const unsigned char *buf,
  283. unsigned int buf_len, unsigned int *write_len,
  284. unsigned int timeout)
  285. {
  286. DWORD w = 0;
  287. struct rs232_windows_t *wx = p->pt;
  288. unsigned int wt = wx->w_timeout;
  289. if (port_timeout(p, wx->r_timeout, timeout))
  290. return RS232_ERR_UNKNOWN;
  291. if (!WriteFile(wx->fd, buf, buf_len, &w, NULL)) {
  292. *write_len = 0;
  293. DBG("WriteFile() %s\n", last_error());
  294. return RS232_ERR_WRITE;
  295. }
  296. if (port_timeout(p, wx->r_timeout, wt))
  297. return RS232_ERR_UNKNOWN;
  298. *write_len = w;
  299. return RS232_ERR_NOERROR;
  300. }
  301. //}
  302. //{ Overlapped IO
  303. static unsigned int
  304. poll_ovl(struct rs232_port_t *p, unsigned int timeout, DWORD events, DWORD *mask){
  305. struct rs232_windows_t *wx = p->pt;
  306. DWORD ret;
  307. monotonic_time_t started = GetMonotonicTime();
  308. if(!SetCommMask(wx->fd, events))
  309. return RS232_ERR_IOCTL;
  310. *mask = 0;
  311. while(1){
  312. monotonic_diff_t elapsed = GetMonotonicDelta(started, GetMonotonicTime());
  313. if(elapsed >= timeout)
  314. return RS232_ERR_TIMEOUT;
  315. if(!wx->wait_progress){
  316. wx->wait_mask = 0;
  317. if (WaitCommEvent(wx->fd, &wx->wait_mask, &wx->oWait))
  318. goto readed;
  319. if (GetLastError() != ERROR_IO_PENDING)
  320. return RS232_ERR_IOCTL;
  321. }
  322. wx->wait_progress = 1;
  323. ret = WaitForSingleObject(wx->oWait.hEvent, timeout - elapsed);
  324. if(ret != WAIT_OBJECT_0)
  325. return RS232_ERR_TIMEOUT;
  326. if(!GetOverlappedResult(wx->fd, &wx->oWait, &ret, FALSE))
  327. return RS232_ERR_IOCTL;
  328. readed:
  329. wx->wait_progress = 0;
  330. if(wx->wait_mask)
  331. break;
  332. }
  333. *mask = wx->wait_mask;
  334. return RS232_ERR_NOERROR;
  335. }
  336. static unsigned int
  337. read_n_ovl(struct rs232_port_t *p, unsigned char *buf, unsigned int buf_len,
  338. DWORD *read_len, DWORD *ermask
  339. )
  340. {
  341. /* read avaliable data without waiting */
  342. struct rs232_windows_t *wx = p->pt;
  343. OVERLAPPED ovl = {0};
  344. COMSTAT cs = {0};
  345. DWORD readed, avaliable;
  346. *read_len = 0;
  347. if (!ClearCommError(wx->fd, ermask, &cs))
  348. return RS232_ERR_IOCTL;
  349. avaliable = cs.cbInQue > buf_len ? buf_len : cs.cbInQue;
  350. if (avaliable) {
  351. if (!ReadFile(wx->fd, buf, avaliable, &readed, &ovl)) {
  352. if (GetLastError() != ERROR_IO_PENDING)
  353. return RS232_ERR_READ;
  354. if(!GetOverlappedResult(wx->fd, &ovl, &readed, TRUE))
  355. return RS232_ERR_READ;
  356. }
  357. *read_len = readed;
  358. }
  359. return RS232_ERR_NOERROR;
  360. }
  361. static unsigned int
  362. rs232_read_ovl(struct rs232_port_t *p, unsigned char *buf,
  363. unsigned int buf_len, unsigned int *read_len,
  364. unsigned int timeout, unsigned int lat,
  365. DWORD events, unsigned int *evmask
  366. )
  367. {
  368. struct rs232_windows_t *wx = p->pt;
  369. monotonic_time_t started = GetMonotonicTime();
  370. unsigned char *ptr = buf;
  371. *read_len = 0;
  372. while (1) {
  373. DWORD readed, error_mask, event_mask;
  374. unsigned int ret;
  375. monotonic_diff_t elapsed = GetMonotonicDelta(started, GetMonotonicTime());
  376. if (elapsed > timeout)
  377. return *read_len ? RS232_ERR_NOERROR : RS232_ERR_TIMEOUT;
  378. ret = read_n_ovl(p, ptr, buf_len - *read_len, &readed, &error_mask);
  379. if (error_mask) {
  380. if (error_mask & CE_BREAK)
  381. ret = RS232_ERR_BREAK;
  382. if (error_mask & CE_RXOVER)
  383. ret = RS232_ERR_RXOVERFLOW;
  384. if (error_mask & CE_OVERRUN)
  385. ret = RS232_ERR_OVERRUN;
  386. if (error_mask & CE_FRAME)
  387. ret = RS232_ERR_FRAME;
  388. if (error_mask & CE_RXPARITY)
  389. ret = RS232_ERR_PARITY;
  390. }
  391. if (ret != RS232_ERR_NOERROR)
  392. return ret;
  393. if(readed){/* reduce timeout to max latentency*/
  394. if((timeout - elapsed) > lat)
  395. timeout = elapsed + lat;
  396. }
  397. if(!readed){
  398. ret = poll_ovl(p, timeout - elapsed, events, &event_mask);
  399. if(evmask) *evmask = event_mask;
  400. if(ret != RS232_ERR_NOERROR)
  401. return *read_len ? RS232_ERR_NOERROR : RS232_ERR_TIMEOUT;
  402. //! @todo check event_mask (e.g. (event_mask & EV_BREAK) || (event_mask & EV_ERR))
  403. continue;
  404. }
  405. ptr += readed;
  406. *read_len += readed;
  407. assert(*read_len <= buf_len);
  408. if(*read_len == buf_len)
  409. break;
  410. }
  411. return RS232_ERR_NOERROR;
  412. }
  413. static unsigned int
  414. rs232_read_ovl_impl(struct rs232_port_t *p, unsigned char *buf, unsigned int buf_len,
  415. unsigned int *read_len)
  416. {
  417. struct rs232_windows_t *wx = p->pt;
  418. if (!rs232_port_open(p))
  419. return RS232_ERR_PORT_CLOSED;
  420. return rs232_read_ovl(p, buf, buf_len, read_len, INFINITE, READ_LATENTENCY, READ_EVENTS, NULL);
  421. }
  422. /* this function waits either for timeout or buf_len bytes,
  423. whatever happens first and doesn't return earlier */
  424. static unsigned int
  425. rs232_read_timeout_forced_ovl_impl(struct rs232_port_t *p, unsigned char *buf,
  426. unsigned int buf_len, unsigned int *read_len,
  427. unsigned int timeout)
  428. {
  429. struct rs232_windows_t *wx = p->pt;
  430. if (!rs232_port_open(p))
  431. return RS232_ERR_PORT_CLOSED;
  432. return rs232_read_ovl(p, buf, buf_len, read_len, timeout, timeout, READ_EVENTS, NULL);
  433. }
  434. static unsigned int
  435. rs232_read_timeout_ovl_impl(struct rs232_port_t *p, unsigned char *buf,
  436. unsigned int buf_len, unsigned int *read_len,
  437. unsigned int timeout)
  438. {
  439. struct rs232_windows_t *wx = p->pt;
  440. if (!rs232_port_open(p))
  441. return RS232_ERR_PORT_CLOSED;
  442. return rs232_read_ovl(p, buf, buf_len, read_len, timeout, READ_LATENTENCY, READ_EVENTS, NULL);
  443. }
  444. static unsigned int
  445. rs232_write_ovl(struct rs232_port_t *p, const unsigned char *buf, unsigned int buf_len,
  446. unsigned int *write_len)
  447. {
  448. OVERLAPPED oWrite = {0};
  449. DWORD w = 0;
  450. struct rs232_windows_t *wx = p->pt;
  451. *write_len = 0;
  452. if(!WriteFile(wx->fd, buf, buf_len, &w, &oWrite)){
  453. DWORD ret;
  454. if(GetLastError() != ERROR_IO_PENDING){
  455. DBG("WriteFile() %s\n", last_error());
  456. return RS232_ERR_WRITE;
  457. }
  458. if(!GetOverlappedResult(wx->fd, &oWrite, &ret, TRUE)){
  459. DBG("OverlappedResult() %s\n", last_error());
  460. // wtf? If we get error how cancel current write operation?
  461. return RS232_ERR_WRITE;
  462. }
  463. w = ret;
  464. }
  465. *write_len = w;
  466. return RS232_ERR_NOERROR;
  467. }
  468. static unsigned int
  469. rs232_write_ovl_impl(struct rs232_port_t *p, const unsigned char *buf, unsigned int buf_len,
  470. unsigned int *write_len)
  471. {
  472. struct rs232_windows_t *wx = p->pt;
  473. unsigned int ret;
  474. DBG("p=%p p->pt=%p buf_len:%d\n", (void *)p, p->pt, buf_len);
  475. if (!rs232_port_open(p))
  476. return RS232_ERR_PORT_CLOSED;
  477. ret = rs232_write_ovl(p, buf, buf_len, write_len);
  478. if (ret != RS232_ERR_NOERROR) {
  479. return ret;
  480. }
  481. if (buf_len != *write_len)
  482. DBG("WriteFile() %s\n", last_error());
  483. DBG("write_len=%d hex='%s' ascii='%s'\n", *write_len, rs232_hex_dump(buf, w),
  484. rs232_ascii_dump(buf, w));
  485. return RS232_ERR_NOERROR;
  486. }
  487. static unsigned int
  488. rs232_write_timeout_ovl_impl(struct rs232_port_t *p, const unsigned char *buf,
  489. unsigned int buf_len, unsigned int *write_len,
  490. unsigned int timeout)
  491. {
  492. struct rs232_windows_t *wx = p->pt;
  493. unsigned int wt = wx->w_timeout;
  494. unsigned int ret;
  495. if (port_timeout(p, wx->r_timeout, timeout))
  496. return RS232_ERR_UNKNOWN;
  497. ret = rs232_write_ovl(p, buf, buf_len, write_len);
  498. if (ret != RS232_ERR_NOERROR)
  499. return ret;
  500. if (port_timeout(p, wx->r_timeout, wt))
  501. return RS232_ERR_UNKNOWN;
  502. return RS232_ERR_NOERROR;
  503. }
  504. //}
  505. //{ Public API IP
  506. RS232_LIB unsigned int
  507. rs232_read(struct rs232_port_t *p, unsigned char *buf, unsigned int buf_len,
  508. unsigned int *read_len)
  509. {
  510. unsigned int ret;
  511. DBG("p=%p p->pt=%p buf_len:%d\n", (void *)p, p->pt, buf_len);
  512. if (!rs232_port_open(p))
  513. return RS232_ERR_PORT_CLOSED;
  514. #ifdef USE_OVERLAPPED
  515. ret = rs232_read_ovl_impl(p, buf, buf_len, read_len);
  516. #else
  517. ret = rs232_read_impl(p, buf, buf_len, read_len);
  518. #endif
  519. DBG("read_len=%d hex='%s' ascii='%s'\n", r, rs232_hex_dump(buf, *read_len),
  520. rs232_ascii_dump(buf, *read_len));
  521. return ret;
  522. }
  523. /* this function waits either for timeout or buf_len bytes,
  524. whatever happens first and doesn't return earlier */
  525. RS232_LIB unsigned int
  526. rs232_read_timeout_forced(struct rs232_port_t *p, unsigned char *buf,
  527. unsigned int buf_len, unsigned int *read_len,
  528. unsigned int timeout)
  529. {
  530. unsigned int ret;
  531. DBG("p=%p p->pt=%p buf_len:%d timeout:%d\n", (void *)p, p->pt, buf_len, timeout);
  532. if (!rs232_port_open(p))
  533. return RS232_ERR_PORT_CLOSED;
  534. #ifdef USE_OVERLAPPED
  535. ret = rs232_read_timeout_forced_ovl_impl(p, buf, buf_len, read_len, timeout);
  536. #else
  537. ret = rs232_read_timeout_forced_impl(p, buf, buf_len, read_len, timeout);
  538. #endif
  539. DBG("read_len=%d hex='%s' ascii='%s'\n", r, rs232_hex_dump(buf, *read_len),
  540. rs232_ascii_dump(buf, *read_len));
  541. return ret;
  542. }
  543. RS232_LIB unsigned int
  544. rs232_read_timeout(struct rs232_port_t *p, unsigned char *buf,
  545. unsigned int buf_len, unsigned int *read_len,
  546. unsigned int timeout)
  547. {
  548. unsigned int ret;
  549. DBG("p=%p p->pt=%p buf_len:%d timeout:%d\n", (void *)p, p->pt, buf_len, timeout);
  550. if (!rs232_port_open(p))
  551. return RS232_ERR_PORT_CLOSED;
  552. #ifdef USE_OVERLAPPED
  553. ret = rs232_read_timeout_ovl_impl(p, buf, buf_len, read_len, timeout);
  554. #else
  555. ret = rs232_read_timeout_impl(p, buf, buf_len, read_len, timeout);
  556. #endif
  557. DBG("read_len=%d hex='%s' ascii='%s'\n", r, rs232_hex_dump(buf, *read_len),
  558. rs232_ascii_dump(buf, *read_len));
  559. return ret;
  560. }
  561. RS232_LIB unsigned int
  562. rs232_write(struct rs232_port_t *p, const unsigned char *buf, unsigned int buf_len,
  563. unsigned int *write_len)
  564. {
  565. unsigned int ret;
  566. DBG("p=%p p->pt=%p buf_len:%d\n", (void *)p, p->pt, buf_len);
  567. if (!rs232_port_open(p))
  568. return RS232_ERR_PORT_CLOSED;
  569. #ifdef USE_OVERLAPPED
  570. ret = rs232_write_ovl_impl(p, buf, buf_len, write_len);
  571. #else
  572. ret = rs232_write_impl(p, buf, buf_len, write_len);
  573. #endif
  574. DBG("write_len=%d hex='%s' ascii='%s'\n", w, rs232_hex_dump(buf, *write_len),
  575. rs232_ascii_dump(buf, *write_len));
  576. return ret;
  577. }
  578. RS232_LIB unsigned int
  579. rs232_write_timeout(struct rs232_port_t *p, const unsigned char *buf,
  580. unsigned int buf_len, unsigned int *write_len,
  581. unsigned int timeout)
  582. {
  583. unsigned int ret;
  584. DBG("p=%p p->pt=%p buf_len:%d timeout: %d\n", (void *)p, p->pt, buf_len, timeout);
  585. if (!rs232_port_open(p))
  586. return RS232_ERR_PORT_CLOSED;
  587. #ifdef USE_OVERLAPPED
  588. ret = rs232_write_timeout_ovl_impl(p, buf, buf_len, write_len, timeout);
  589. #else
  590. ret = rs232_write_timeout_impl(p, buf, buf_len, write_len, timeout);
  591. #endif
  592. DBG("write_len=%d hex='%s' ascii='%s'\n", w, rs232_hex_dump(buf, *write_len),
  593. rs232_ascii_dump(buf, *write_len));
  594. return ret;
  595. }
  596. //}
  597. static char *
  598. fix_device_name(char *device, char *ret)
  599. {
  600. char *s = device;
  601. /* meh, Windows CE is special and can't handle URN path, just COM1: format */
  602. if((s[0] == '\\')&&(s[1] == '\\')&&(s[2] == '.')&&(s[3] == '\\')){
  603. #ifdef UNDER_CE
  604. /* remove URN prefix */
  605. snprintf(ret, RS232_STRLEN_DEVICE, "%s", s + 4);
  606. return ret;
  607. #else
  608. return s;
  609. #endif
  610. }
  611. #ifdef UNDER_CE
  612. return s;
  613. #else
  614. snprintf(ret, RS232_STRLEN_DEVICE, "\\\\.\\%s", s);
  615. return ret;
  616. #endif
  617. }
  618. RS232_LIB unsigned int
  619. rs232_open(struct rs232_port_t *p)
  620. {
  621. char tmp[RS232_STRLEN_DEVICE+1] = {0};
  622. wchar_t *wname = a2w(fix_device_name(p->dev, tmp));
  623. struct rs232_windows_t *wx = p->pt;
  624. DBG("p=%p p->pt=%p name='%s' fix='%s'\n",
  625. (void *)p, p->pt, p->dev, fix_device_name(p->dev, tmp));
  626. if (wname == NULL)
  627. return RS232_ERR_UNKNOWN;
  628. wx->fd = CreateFileW(wname, GENERIC_READ | GENERIC_WRITE,
  629. 0, NULL, OPEN_EXISTING,
  630. #ifdef USE_OVERLAPPED
  631. FILE_FLAG_OVERLAPPED,
  632. #else
  633. 0,
  634. #endif
  635. NULL);
  636. if (wname)
  637. free(wname);
  638. if (wx->fd == INVALID_HANDLE_VALUE) {
  639. DBG("CreateFile() %s\n", last_error());
  640. return RS232_ERR_OPEN;
  641. }
  642. #ifdef USE_OVERLAPPED
  643. memset(&wx->oWait, 0, sizeof(wx->oWait));
  644. wx->oWait.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
  645. if(wx->oWait.hEvent == NULL){
  646. CloseHandle(wx->fd);
  647. wx->fd = INVALID_HANDLE_VALUE;
  648. return RS232_ERR_OPEN;
  649. }
  650. wx->wait_progress = 0;
  651. #endif
  652. p->status = RS232_PORT_OPEN;
  653. rs232_flush(p);
  654. GET_PORT_STATE(wx->fd, &wx->old_dcb);
  655. GET_PORT_TIMEOUTS(wx->fd, &wx->old_tm);
  656. port_timeout(p, wx->r_timeout, wx->w_timeout);
  657. port_buffers(p, wx->r_buffer, wx->w_buffer);
  658. rs232_set_baud(p, p->baud);
  659. rs232_set_data(p, p->data);
  660. rs232_set_parity(p, p->parity);
  661. rs232_set_stop(p, p->stop);
  662. rs232_set_flow(p, p->flow);
  663. return RS232_ERR_NOERROR;
  664. }
  665. RS232_LIB void
  666. rs232_set_device(struct rs232_port_t *p, const char *device)
  667. {
  668. DBG("p=%p old=%s new=%s\n", (void *)p, p->dev, device);
  669. strncpyz(p->dev, device, RS232_STRLEN_DEVICE);
  670. return;
  671. }
  672. RS232_LIB unsigned int
  673. rs232_set_baud(struct rs232_port_t *p, enum rs232_baud_e baud)
  674. {
  675. DCB pdcb;
  676. struct rs232_windows_t *wx = p->pt;
  677. DBG("p=%p p->pt=%p baud=%d (%s bauds)\n",
  678. (void *)p, p->pt, baud, rs232_strbaud(baud));
  679. if (!rs232_port_open(p))
  680. return RS232_ERR_PORT_CLOSED;
  681. GET_PORT_STATE(wx->fd, &pdcb);
  682. switch (baud) {
  683. case RS232_BAUD_300:
  684. pdcb.BaudRate = CBR_300;
  685. break;
  686. case RS232_BAUD_2400:
  687. pdcb.BaudRate = CBR_2400;
  688. break;
  689. case RS232_BAUD_4800:
  690. pdcb.BaudRate = CBR_4800;
  691. break;
  692. case RS232_BAUD_9600:
  693. pdcb.BaudRate = CBR_9600;
  694. break;
  695. case RS232_BAUD_19200:
  696. pdcb.BaudRate = CBR_19200;
  697. break;
  698. case RS232_BAUD_38400:
  699. pdcb.BaudRate = CBR_38400;
  700. break;
  701. case RS232_BAUD_57600:
  702. pdcb.BaudRate = CBR_57600;
  703. break;
  704. case RS232_BAUD_115200:
  705. pdcb.BaudRate = CBR_115200;
  706. break;
  707. case RS232_BAUD_460800:
  708. pdcb.BaudRate = CBR_460800;
  709. break;
  710. default:
  711. return RS232_ERR_UNKNOWN;
  712. }
  713. SET_PORT_STATE(wx->fd, &pdcb);
  714. p->baud = baud;
  715. return RS232_ERR_NOERROR;
  716. }
  717. RS232_LIB unsigned int
  718. rs232_set_dtr(struct rs232_port_t *p, enum rs232_dtr_e state)
  719. {
  720. DCB pdcb;
  721. struct rs232_windows_t *wx = p->pt;
  722. DBG("p=%p p->pt=%p dtr=%d (dtr control %s)\n",
  723. (void *)p, p->pt, state, rs232_strdtr(state));
  724. if (!rs232_port_open(p))
  725. return RS232_ERR_PORT_CLOSED;
  726. GET_PORT_STATE(wx->fd, &pdcb);
  727. switch (state) {
  728. case RS232_DTR_OFF:
  729. pdcb.fDtrControl = DTR_CONTROL_DISABLE;
  730. break;
  731. case RS232_DTR_ON:
  732. pdcb.fDtrControl = DTR_CONTROL_ENABLE;
  733. break;
  734. default:
  735. return RS232_ERR_UNKNOWN;
  736. }
  737. SET_PORT_STATE(wx->fd, &pdcb);
  738. p->dtr = state;
  739. return RS232_ERR_NOERROR;
  740. }
  741. RS232_LIB unsigned int
  742. rs232_set_rts(struct rs232_port_t *p, enum rs232_rts_e state)
  743. {
  744. DCB pdcb;
  745. struct rs232_windows_t *wx = p->pt;
  746. DBG("p=%p p->pt=%p rts=%d (rts control %s)\n",
  747. (void *)p, p->pt, state, rs232_strrts(state));
  748. if (!rs232_port_open(p))
  749. return RS232_ERR_PORT_CLOSED;
  750. GET_PORT_STATE(wx->fd, &pdcb);
  751. switch (state) {
  752. case RS232_RTS_OFF:
  753. pdcb.fRtsControl = RTS_CONTROL_DISABLE;
  754. break;
  755. case RS232_RTS_ON:
  756. pdcb.fRtsControl = RTS_CONTROL_ENABLE;
  757. break;
  758. default:
  759. return RS232_ERR_UNKNOWN;
  760. }
  761. SET_PORT_STATE(wx->fd, &pdcb);
  762. p->rts = state;
  763. return RS232_ERR_NOERROR;
  764. }
  765. RS232_LIB unsigned int
  766. rs232_set_parity(struct rs232_port_t *p, enum rs232_parity_e parity)
  767. {
  768. DCB pdcb;
  769. struct rs232_windows_t *wx = p->pt;
  770. DBG("p=%p p->pt=%p parity=%d (parity %s)\n",
  771. (void *)p, p->pt, parity, rs232_strparity(parity));
  772. if (!rs232_port_open(p))
  773. return RS232_ERR_PORT_CLOSED;
  774. GET_PORT_STATE(wx->fd, &pdcb);
  775. switch (parity) {
  776. case RS232_PARITY_NONE:
  777. pdcb.Parity = NOPARITY;
  778. break;
  779. case RS232_PARITY_ODD:
  780. pdcb.Parity = ODDPARITY;
  781. break;
  782. case RS232_PARITY_EVEN:
  783. pdcb.Parity = EVENPARITY;
  784. break;
  785. default:
  786. return RS232_ERR_UNKNOWN;
  787. }
  788. SET_PORT_STATE(wx->fd, &pdcb);
  789. p->parity = parity;
  790. return RS232_ERR_NOERROR;
  791. }
  792. RS232_LIB unsigned int
  793. rs232_set_stop(struct rs232_port_t *p, enum rs232_stop_e stop)
  794. {
  795. DCB pdcb;
  796. struct rs232_windows_t *wx = p->pt;
  797. DBG("p=%p p->pt=%p stop=%d (%s stop bits)\n",
  798. (void *)p, p->pt, stop, rs232_strstop(stop));
  799. if (!rs232_port_open(p))
  800. return RS232_ERR_PORT_CLOSED;
  801. GET_PORT_STATE(wx->fd, &pdcb);
  802. switch (stop) {
  803. case RS232_STOP_1:
  804. pdcb.StopBits = ONESTOPBIT;
  805. break;
  806. case RS232_STOP_2:
  807. pdcb.StopBits = TWOSTOPBITS;
  808. break;
  809. default:
  810. return RS232_ERR_UNKNOWN;
  811. }
  812. SET_PORT_STATE(wx->fd, &pdcb);
  813. p->stop = stop;
  814. return RS232_ERR_NOERROR;
  815. }
  816. RS232_LIB unsigned int
  817. rs232_set_data(struct rs232_port_t *p, enum rs232_data_e data)
  818. {
  819. DCB pdcb;
  820. struct rs232_windows_t *wx = p->pt;
  821. DBG("p=%p p->pt=%p data=%d (%s data bits)\n",
  822. (void *)p, p->pt, data, rs232_strdata(data));
  823. if (!rs232_port_open(p))
  824. return RS232_ERR_PORT_CLOSED;
  825. GET_PORT_STATE(wx->fd, &pdcb);
  826. switch (data) {
  827. case RS232_DATA_5:
  828. pdcb.ByteSize = 5;
  829. break;
  830. case RS232_DATA_6:
  831. pdcb.ByteSize = 6;
  832. break;
  833. case RS232_DATA_7:
  834. pdcb.ByteSize = 7;
  835. break;
  836. case RS232_DATA_8:
  837. pdcb.ByteSize = 8;
  838. break;
  839. default:
  840. return RS232_ERR_UNKNOWN;
  841. }
  842. SET_PORT_STATE(wx->fd, &pdcb);
  843. p->data = data;
  844. return RS232_ERR_NOERROR;
  845. }
  846. RS232_LIB unsigned int
  847. rs232_set_flow(struct rs232_port_t *p, enum rs232_flow_e flow)
  848. {
  849. DCB pdcb;
  850. struct rs232_windows_t *wx = p->pt;
  851. DBG("p=%p p->pt=%p flow=%d (flow control %s)\n",
  852. (void *)p, p->pt, flow, rs232_strflow(flow));
  853. if (!rs232_port_open(p))
  854. return RS232_ERR_PORT_CLOSED;
  855. GET_PORT_STATE(wx->fd, &pdcb);
  856. switch (flow) {
  857. case RS232_FLOW_OFF:
  858. pdcb.fOutxCtsFlow = FALSE;
  859. pdcb.fRtsControl = RTS_CONTROL_DISABLE;
  860. pdcb.fInX = FALSE;
  861. pdcb.fOutX = FALSE;
  862. break;
  863. case RS232_FLOW_HW:
  864. pdcb.fOutxCtsFlow = TRUE;
  865. pdcb.fRtsControl = RTS_CONTROL_HANDSHAKE;
  866. pdcb.fInX = FALSE;
  867. pdcb.fOutX = FALSE;
  868. break;
  869. case RS232_FLOW_XON_XOFF:
  870. pdcb.fOutxCtsFlow = FALSE;
  871. pdcb.fRtsControl = RTS_CONTROL_DISABLE;
  872. pdcb.fInX = TRUE;
  873. pdcb.fOutX = TRUE;
  874. break;
  875. default:
  876. return RS232_ERR_UNKNOWN;
  877. }
  878. SET_PORT_STATE(wx->fd, &pdcb);
  879. p->flow = flow;
  880. return RS232_ERR_NOERROR;
  881. }
  882. RS232_LIB unsigned int
  883. rs232_flush(struct rs232_port_t *p)
  884. {
  885. struct rs232_windows_t *wx = p->pt;
  886. DBG("p=%p p->pt=%p\n", (void *)p, p->pt);
  887. if (!rs232_port_open(p))
  888. return RS232_ERR_PORT_CLOSED;
  889. if (!FlushFileBuffers(wx->fd)) {
  890. DBG("FlushFileBuffers() %s\n", last_error());
  891. return RS232_ERR_FLUSH;
  892. }
  893. if (!PurgeComm(wx->fd, PURGE_TXABORT | PURGE_RXABORT |
  894. PURGE_TXCLEAR | PURGE_RXCLEAR)) {
  895. DBG("PurgeComm() %s\n", last_error());
  896. return RS232_ERR_FLUSH;
  897. }
  898. return RS232_ERR_NOERROR;
  899. }
  900. RS232_LIB unsigned int
  901. rs232_close(struct rs232_port_t *p)
  902. {
  903. int ret;
  904. struct rs232_windows_t *wx = p->pt;
  905. DBG("p=%p p->pt=%p\n", (void *)p, p->pt);
  906. if (!rs232_port_open(p))
  907. return RS232_ERR_PORT_CLOSED;
  908. ret = CloseHandle(wx->fd);
  909. if (ret == 0) {
  910. DBG("CloseHandle() %s\n", last_error());
  911. return RS232_ERR_CLOSE;
  912. }
  913. #ifdef USE_OVERLAPPED
  914. ret = CloseHandle(wx->oWait.hEvent);
  915. if (ret == 0) {
  916. DBG("CloseHandle() %s\n", last_error());
  917. return RS232_ERR_CLOSE;
  918. }
  919. wx->wait_progress = 0;
  920. #endif
  921. return RS232_ERR_NOERROR;
  922. }
  923. RS232_LIB unsigned int
  924. rs232_fd(struct rs232_port_t *p)
  925. {
  926. struct rs232_windows_t *wx = p->pt;
  927. DBG("p=%p p->pt=%p wx->fd=%d\n", (void *)p, p->pt, wx->fd);
  928. return (unsigned int) wx->fd;
  929. }