You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

3110 lines
80 KiB

  1. --- a/dio_posix.c
  2. +++ b/dio_posix.c
  3. @@ -1,659 +1,659 @@
  4. -/*
  5. - +----------------------------------------------------------------------+
  6. - | PHP Version 5 |
  7. - +----------------------------------------------------------------------+
  8. - | Copyright (c) 2009 Melanie Rhianna Lewis |
  9. - +----------------------------------------------------------------------+
  10. - | This source file is subject to version 3.0 of the PHP license, |
  11. - | that is bundled with this package in the file LICENSE, and is |
  12. - | available through the world-wide-web at the following url: |
  13. - | http://www.php.net/license/3_0.txt. |
  14. - | If you did not receive a copy of the PHP license and are unable to |
  15. - | obtain it through the world-wide-web, please send a note to |
  16. - | license@php.net so we can mail you a copy immediately. |
  17. - +----------------------------------------------------------------------+
  18. - | Author: Melanie Rhianna Lewis <cyberspice@php.net> |
  19. - +----------------------------------------------------------------------+
  20. - */
  21. -
  22. -#ifdef HAVE_CONFIG_H
  23. -#include "config.h"
  24. -#endif
  25. -
  26. -#include "php.h"
  27. -
  28. -#include "php_dio_common.h"
  29. -
  30. -/* {{{ dio_stream_mode_to_flags
  31. - * Convert an fopen() mode string to open() flags
  32. - */
  33. -static int dio_stream_mode_to_flags(const char *mode) {
  34. - int flags = 0, ch = 0, bin = 1;
  35. -
  36. - switch(mode[ch++]) {
  37. - case 'r':
  38. - flags = 0;
  39. - break;
  40. - case 'w':
  41. - flags = O_TRUNC | O_CREAT;
  42. - break;
  43. - case 'a':
  44. - flags = O_APPEND | O_CREAT;
  45. - break;
  46. - case 'x':
  47. - flags = O_EXCL | O_CREAT;
  48. - break;
  49. - }
  50. -
  51. - if (mode[ch] != '+') {
  52. - bin = (mode[ch++] == 'b');
  53. - }
  54. -
  55. - if (mode[ch] == '+') {
  56. - flags |= O_RDWR;
  57. - } else if (flags) {
  58. - flags |= O_WRONLY;
  59. - } else {
  60. - flags |= O_RDONLY;
  61. - }
  62. -
  63. -#if defined(_O_TEXT) && defined(O_BINARY)
  64. - if (bin) {
  65. - flags |= O_BINARY;
  66. - } else {
  67. - flags |= _O_TEXT;
  68. - }
  69. -#endif
  70. -
  71. - return flags;
  72. -}
  73. -/* }}} */
  74. -
  75. -/* {{{ dio_data_rate_to_define
  76. - * Converts a numeric data rate to a termios define
  77. - */
  78. -static int dio_data_rate_to_define(long rate, speed_t *def) {
  79. - speed_t val;
  80. -
  81. - switch (rate) {
  82. - case 0:
  83. - val = 0;
  84. - break;
  85. - case 50:
  86. - val = B50;
  87. - break;
  88. - case 75:
  89. - val = B75;
  90. - break;
  91. - case 110:
  92. - val = B110;
  93. - break;
  94. - case 134:
  95. - val = B134;
  96. - break;
  97. - case 150:
  98. - val = B150;
  99. - break;
  100. - case 200:
  101. - val = B200;
  102. - break;
  103. - case 300:
  104. - val = B300;
  105. - break;
  106. - case 600:
  107. - val = B600;
  108. - break;
  109. - case 1200:
  110. - val = B1200;
  111. - break;
  112. - case 1800:
  113. - val = B1800;
  114. - break;
  115. - case 2400:
  116. - val = B2400;
  117. - break;
  118. - case 4800:
  119. - val = B4800;
  120. - break;
  121. - case 9600:
  122. - val = B9600;
  123. - break;
  124. - case 19200:
  125. - val = B19200;
  126. - break;
  127. - case 38400:
  128. - val = B38400;
  129. - break;
  130. -#ifdef B57600
  131. - case 57600:
  132. - val = B57600;
  133. - break;
  134. -#endif
  135. -#ifdef B115200
  136. - case 115200:
  137. - val = B115200;
  138. - break;
  139. -#endif
  140. -#ifdef B230400
  141. - case 230400:
  142. - val = B230400;
  143. - break;
  144. -#endif
  145. -#ifdef B460800
  146. - case 460800:
  147. - val = B460800;
  148. - break;
  149. -#endif
  150. - default:
  151. - return 0;
  152. - }
  153. -
  154. - *def = val;
  155. - return 1;
  156. -}
  157. -
  158. -/* {{{ dio_data_bits_to_define
  159. - * Converts a number of data bits to a termios define
  160. - */
  161. -static int dio_data_bits_to_define(int data_bits, int *def) {
  162. - int val;
  163. -
  164. - switch (data_bits) {
  165. - case 8:
  166. - val = CS8;
  167. - break;
  168. - case 7:
  169. - val = CS7;
  170. - break;
  171. - case 6:
  172. - val = CS6;
  173. - break;
  174. - case 5:
  175. - val = CS5;
  176. - break;
  177. - default:
  178. - return 0;
  179. - }
  180. -
  181. - *def = val;
  182. - return 1;
  183. -}
  184. -/* }}} */
  185. -
  186. -/* {{{ dio_stop_bits_to_define
  187. - * Converts a number of stop bits to a termios define
  188. - */
  189. -static int dio_stop_bits_to_define(int stop_bits, int *def) {
  190. - int val;
  191. -
  192. - switch (stop_bits) {
  193. - case 1:
  194. - val = 0;
  195. - break;
  196. - case 2:
  197. - val = CSTOPB;
  198. - break;
  199. - default:
  200. - return 0;
  201. - }
  202. -
  203. - *def = val;
  204. - return 1;
  205. -}
  206. -/* }}} */
  207. -
  208. -/* {{{ dio_parity_to_define
  209. - * Converts a parity type to a termios define
  210. - */
  211. -static int dio_parity_to_define(int parity, int *def) {
  212. - int val;
  213. -
  214. - switch (parity) {
  215. - case 0:
  216. - val = 0;
  217. - break;
  218. - case 1:
  219. - val = PARENB | PARODD;
  220. - break;
  221. - case 2:
  222. - val = PARENB;
  223. - break;
  224. - default:
  225. - return 0;
  226. - }
  227. -
  228. - *def = val;
  229. - return 1;
  230. -}
  231. -/* }}} */
  232. -
  233. -/* {{{ dio_create_stream_data
  234. - * Creates an initialised stream data structure. Free with efree().
  235. - */
  236. -php_dio_stream_data * dio_create_stream_data(void) {
  237. - php_dio_posix_stream_data * data = emalloc(sizeof(php_dio_posix_stream_data));
  238. - dio_init_stream_data(&(data->common));
  239. - data->fd = -1;
  240. - data->flags = 0;
  241. -
  242. - return (php_dio_stream_data *)data;
  243. -}
  244. -/* }}} */
  245. -
  246. -/* {{{ dio_common_write
  247. - * Writes count chars from the buffer to the stream described by the stream data.
  248. - */
  249. -size_t dio_common_write(php_dio_stream_data *data, const char *buf, size_t count) {
  250. - size_t ret;
  251. -
  252. - /* Blocking writes can be interrupted by signals etc. If
  253. - * interrupted try again. Not sure about non-blocking
  254. - * writes but it doesn't hurt to check. */
  255. - do {
  256. - ret = write(((php_dio_posix_stream_data*)data)->fd, buf, count);
  257. - if (ret > 0) {
  258. - return ret;
  259. - }
  260. - } while (errno == EINTR);
  261. - return 0;
  262. -}
  263. -/* }}} */
  264. -
  265. -#ifdef DIO_NONBLOCK
  266. -/* {{{ dio_timeval_subtract
  267. - * Calculates the difference between two timevals returning the result in the
  268. - * structure pointed to by diffptr. Returns -1 as error if late time is
  269. - * earlier than early time.
  270. - */
  271. -static int dio_timeval_subtract(struct timeval *late, struct timeval *early, struct timeval *diff) {
  272. - struct timeval *tmp;
  273. -
  274. - /* Handle negatives */
  275. - if (late->tv_sec < early->tv_sec) {
  276. - return 0;
  277. - }
  278. -
  279. - if ((late->tv_sec == early->tv_sec) && (late->tv_usec < early->tv_usec)) {
  280. - return 0;
  281. - }
  282. -
  283. - /* Handle any carry. If later usec is smaller than earlier usec simple
  284. - * subtraction will result in negative value. Since usec has a maximum
  285. - * of one second by adding another second before the subtraction the
  286. - * result will always be positive. */
  287. - if (late->tv_usec < early->tv_usec) {
  288. - late->tv_usec += 1000000;
  289. - late->tv_sec--;
  290. - }
  291. -
  292. - /* Once adjusted can just subtract values. */
  293. - diff->tv_sec = late->tv_sec - early->tv_sec;
  294. - diff->tv_usec = late->tv_usec - early->tv_usec;
  295. -
  296. - return 1;
  297. -}
  298. -#endif
  299. -
  300. -/* {{{ dio_common_read
  301. - * Reads count chars to the buffer to the stream described by the stream data.
  302. - */
  303. -size_t dio_common_read(php_dio_stream_data *data, const char *buf, size_t count) {
  304. - int fd = ((php_dio_posix_stream_data*)data)->fd;
  305. - size_t ret, total = 0;
  306. - char *ptr = (char*)buf;
  307. -
  308. - struct timeval timeout, timeouttmp, before, after, diff;
  309. - fd_set rfds;
  310. -
  311. - if (!data->has_timeout) {
  312. - /* Blocking reads can be interrupted by signals etc. If
  313. - * interrupted try again. Not sure about non-blocking
  314. - * reads but it doesn't hurt to check. */
  315. - do {
  316. - ret = read(fd, (char*)ptr, count);
  317. - if (ret > 0) {
  318. - return ret;
  319. - } else if (!ret) {
  320. - data->end_of_file = 1;
  321. - }
  322. - } while ((errno == EINTR) && !data->end_of_file);
  323. - return 0;
  324. - }
  325. -#ifdef DIO_NONBLOCK
  326. - else {
  327. - /* Clear timed out flag */
  328. - data->timed_out = 0;
  329. -
  330. - /* The initial timeout value */
  331. - timeout.tv_sec = data->timeout_sec;
  332. - timeout.tv_usec = data->timeout_usec;
  333. -
  334. - do {
  335. - /* The semantics of select() are that you cannot guarantee
  336. - * that the timeval structure passed in has not been changed by
  337. - * the select call. So you keep a copy. */
  338. - timeouttmp = timeout;
  339. -
  340. - /* The time before we wait for data. */
  341. - (void) gettimeofday(&before, NULL);
  342. -
  343. - /* Wait for an event on our file descriptor. */
  344. - FD_ZERO(&rfds);
  345. - FD_SET(fd, &rfds);
  346. -
  347. - ret = select(fd + 1, &rfds, NULL, NULL, &timeouttmp);
  348. - /* An error. */
  349. - if ((ret < 0) && (errno != EINTR) && (errno != EAGAIN)) {
  350. - return 0;
  351. - }
  352. -
  353. - /* We have data to read. */
  354. - if ((ret > 0) && FD_ISSET(fd, &rfds)) {
  355. - ret = read(fd, ptr, count);
  356. - /* Another error */
  357. - if ((ret < 0) && (errno != EINTR) && (errno != EAGAIN)) {
  358. - return 0;
  359. - }
  360. -
  361. - if (ret > 0) {
  362. - /* Got data, add it to the buffer. */
  363. - ptr += ret;
  364. - total += ret;
  365. - count -= ret;
  366. - } else if (!ret) {
  367. - /* This should never happen since how can we have
  368. - * data to read at an end of file, but still
  369. - * just in case! */
  370. - data->end_of_file = 1;
  371. - break;
  372. - }
  373. - }
  374. -
  375. - /* If not timed out and not end of file and not all data read
  376. - * calculate how long it took us and loop if we still have time
  377. - * out time left. */
  378. - if (count) {
  379. - (void) gettimeofday(&after, NULL);
  380. -
  381. - /* Diff the timevals */
  382. - (void) dio_timeval_subtract(&after, &before, &diff);
  383. -
  384. - /* Now adjust the timeout. */
  385. - if (!dio_timeval_subtract(&timeout, &diff, &timeout)) {
  386. - /* If it errors we've run out of time. */
  387. - data->timed_out = 1;
  388. - break;
  389. - } else if (!timeout.tv_sec && !(timeout.tv_usec / 1000)) {
  390. - /* Check for rounding issues (millisecond accuracy) */
  391. - data->timed_out = 1;
  392. - break;
  393. - }
  394. - }
  395. - } while (count); /* Until time out or end of file or all data read. */
  396. -
  397. - return total;
  398. - }
  399. -#endif
  400. -}
  401. -/* }}} */
  402. -
  403. -/* {{{ php_dio_stream_data
  404. - * Closes the php_stream.
  405. - */
  406. -int dio_common_close(php_dio_stream_data *data) {
  407. - if (close(((php_dio_posix_stream_data*)data)->fd) < 0) {
  408. - return 0;
  409. - }
  410. -
  411. - return 1;
  412. -}
  413. -/* }}} */
  414. -
  415. -/* {{{ dio_common_set_option
  416. - * Sets/gets stream options
  417. - */
  418. -int dio_common_set_option(php_dio_stream_data *data, int option, int value, void *ptrparam) {
  419. - int fd = ((php_dio_posix_stream_data*)data)->fd;
  420. - int old_is_blocking;
  421. - int flags;
  422. -
  423. - switch (option) {
  424. -#ifdef DIO_NONBLOCK
  425. - case PHP_STREAM_OPTION_READ_TIMEOUT:
  426. - if (ptrparam) {
  427. - struct timeval *tv = (struct timeval*)ptrparam;
  428. -
  429. - flags = fcntl(fd, F_GETFL, 0);
  430. -
  431. - /* A timeout of zero seconds and zero microseconds disables
  432. - any existing timeout. */
  433. - if (tv->tv_sec || tv->tv_usec) {
  434. - data->timeout_sec = tv->tv_sec;
  435. - data->timeout_usec = tv->tv_usec;
  436. - data->has_timeout = -1;
  437. - (void) fcntl(fd, F_SETFL, flags & ~DIO_NONBLOCK);
  438. - } else {
  439. - data->timeout_sec = 0;
  440. - data->timeout_usec = 0;
  441. - data->has_timeout = 0;
  442. - data->timed_out = 0;
  443. - (void) fcntl(fd, F_SETFL, flags | DIO_NONBLOCK);
  444. - }
  445. -
  446. - return PHP_STREAM_OPTION_RETURN_OK;
  447. - } else {
  448. - return PHP_STREAM_OPTION_RETURN_ERR;
  449. - }
  450. -
  451. - case PHP_STREAM_OPTION_BLOCKING:
  452. - flags = fcntl(fd, F_GETFL, 0);
  453. - if (value) {
  454. - flags &= ~DIO_NONBLOCK;
  455. - } else {
  456. - flags |= DIO_NONBLOCK;
  457. - }
  458. - (void) fcntl(fd, F_SETFL, flags);
  459. -
  460. - old_is_blocking = data->is_blocking;
  461. - data->is_blocking = value;
  462. - return old_is_blocking ? PHP_STREAM_OPTION_RETURN_OK : PHP_STREAM_OPTION_RETURN_ERR;
  463. -#endif /* O_NONBLOCK */
  464. -
  465. - default:
  466. - break;
  467. - }
  468. -
  469. - return 1;
  470. -}
  471. -/* }}} */
  472. -
  473. -/* {{{ dio_raw_open_stream
  474. - * Opens the underlying stream.
  475. - */
  476. -int dio_raw_open_stream(char *filename, char *mode, php_dio_stream_data *data TSRMLS_DC) {
  477. - php_dio_posix_stream_data *pdata = (php_dio_posix_stream_data*)data;
  478. - pdata->flags = dio_stream_mode_to_flags(mode);
  479. -
  480. -#ifdef DIO_NONBLOCK
  481. - if (!data->is_blocking || data->has_timeout) {
  482. - pdata->flags |= DIO_NONBLOCK;
  483. - }
  484. -#endif
  485. -
  486. - /* Open the file and handle any errors. */
  487. -#ifdef DIO_HAS_FILEPERMS
  488. - if (data->has_perms) {
  489. - pdata->fd = open(filename, pdata->flags, (mode_t)data->perms);
  490. - } else {
  491. - pdata->fd = open(filename, pdata->flags);
  492. - }
  493. -#else
  494. - pdata->fd = open(filename, pdata->flags);
  495. -#endif
  496. -
  497. - if (pdata->fd < 0) {
  498. - switch (errno) {
  499. - case EEXIST:
  500. - php_error_docref(NULL TSRMLS_CC, E_WARNING, "File exists!");
  501. - return 0;
  502. - default:
  503. - return 0;
  504. - }
  505. - }
  506. -
  507. - return 1;
  508. -}
  509. -/* }}} */
  510. -
  511. -/* {{{ dio_serial_init
  512. - * Initialises the serial settings storing the original settings before hand.
  513. - */
  514. -static int dio_serial_init(php_dio_stream_data *data TSRMLS_DC) {
  515. - php_dio_posix_stream_data *pdata = (php_dio_posix_stream_data*)data;
  516. - int ret = 0, data_bits_def, stop_bits_def, parity_def;
  517. - struct termios tio;
  518. - speed_t rate_def;
  519. -
  520. - if (!dio_data_rate_to_define(data->data_rate, &rate_def)) {
  521. - php_error_docref(NULL TSRMLS_CC, E_WARNING, "invalid data_rate value (%ld)", data->data_rate);
  522. - return 0;
  523. - }
  524. -
  525. - if (!dio_data_bits_to_define(data->data_bits, &data_bits_def)) {
  526. - php_error_docref(NULL TSRMLS_CC, E_WARNING, "invalid data_bits value (%d)", data->data_bits);
  527. - return 0;
  528. - }
  529. -
  530. - if (!dio_stop_bits_to_define(data->stop_bits, &stop_bits_def)) {
  531. - php_error_docref(NULL TSRMLS_CC, E_WARNING, "invalid stop_bits value (%d)", data->stop_bits);
  532. - return 0;
  533. - }
  534. -
  535. - if (!dio_parity_to_define(data->parity, &parity_def)) {
  536. - php_error_docref(NULL TSRMLS_CC, E_WARNING, "invalid parity value (%d)", data->parity);
  537. - return 0;
  538. - }
  539. -
  540. - ret = tcgetattr(pdata->fd, &(pdata->oldtio));
  541. - if (ret < 0) {
  542. - if ((errno == ENOTTY) || (errno == ENODEV)) {
  543. - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Not a serial port or terminal!");
  544. - }
  545. - return 0;
  546. - }
  547. -
  548. - ret = tcgetattr(pdata->fd, &tio);
  549. - if (ret < 0) {
  550. - return 0;
  551. - }
  552. -
  553. - if (data->canonical) {
  554. - tio.c_iflag = IGNPAR | ICRNL;
  555. - tio.c_oflag = 0;
  556. - tio.c_lflag = ICANON;
  557. - } else {
  558. - cfmakeraw(&tio);
  559. - }
  560. -
  561. - cfsetispeed(&tio, rate_def);
  562. - cfsetospeed(&tio, rate_def);
  563. -
  564. - tio.c_cflag &= ~CSIZE;
  565. - tio.c_cflag |= data_bits_def;
  566. - tio.c_cflag &= ~CSTOPB;
  567. - tio.c_cflag |= stop_bits_def;
  568. - tio.c_cflag &= ~(PARENB|PARODD);
  569. - tio.c_cflag |= parity_def;
  570. -
  571. -#ifdef CRTSCTS
  572. - tio.c_cflag &= ~(CLOCAL | CRTSCTS);
  573. -#else
  574. - tio.c_cflag &= ~CLOCAL;
  575. -#endif
  576. - if (!data->flow_control) {
  577. - tio.c_cflag |= CLOCAL;
  578. -#ifdef CRTSCTS
  579. - } else {
  580. - tio.c_cflag |= CRTSCTS;
  581. -#endif
  582. - }
  583. -
  584. - ret = tcsetattr(pdata->fd, TCSANOW, &tio);
  585. - if (ret < 0) {
  586. - return 0;
  587. - }
  588. -
  589. - return 1;
  590. -}
  591. -/* }}} */
  592. -
  593. -/* {{{ dio_serial_uninit
  594. - * Restores the serial settings back to their original state.
  595. - */
  596. -int dio_serial_uninit(php_dio_stream_data *data) {
  597. - php_dio_posix_stream_data *pdata = (php_dio_posix_stream_data*)data;
  598. - int ret;
  599. -
  600. - do {
  601. - ret = tcsetattr(pdata->fd, TCSANOW, &(pdata->oldtio));
  602. - } while ((ret < 0) && (errno == EINTR));
  603. -
  604. - return 1;
  605. -}
  606. -/* }}} */
  607. -
  608. -/* {{{ dio_serial_flush
  609. - * Purges the serial buffers of data.
  610. - */
  611. -int dio_serial_purge(php_dio_stream_data *data) {
  612. - php_dio_posix_stream_data *pdata = (php_dio_posix_stream_data*)data;
  613. - int ret;
  614. -
  615. - if ((pdata->flags & O_RDWR) == O_RDWR) {
  616. - ret = tcflush(pdata->fd, TCIOFLUSH);
  617. - } else if ((pdata->flags & O_WRONLY) == O_WRONLY) {
  618. - ret = tcflush(pdata->fd, TCOFLUSH);
  619. - } else if ((pdata->flags & O_RDONLY) == O_RDONLY) {
  620. - ret = tcflush(pdata->fd, TCIFLUSH);
  621. - }
  622. -
  623. - if (ret < 0) {
  624. - return 0;
  625. - }
  626. -
  627. - return 1;
  628. -}
  629. -/* }}} */
  630. -
  631. -/* {{{ dio_serial_open_stream
  632. - * Opens the underlying stream.
  633. - */
  634. -int dio_serial_open_stream(char *filename, char *mode, php_dio_stream_data *data TSRMLS_DC) {
  635. - php_dio_posix_stream_data *pdata = (php_dio_posix_stream_data*)data;
  636. -
  637. -#ifdef O_NOCTTY
  638. - /* We don't want a controlling TTY */
  639. - pdata->flags |= O_NOCTTY;
  640. -#endif
  641. -
  642. - if (!dio_raw_open_stream(filename, mode, data TSRMLS_CC)) {
  643. - return 0;
  644. - }
  645. -
  646. - if (!dio_serial_init(data TSRMLS_CC)) {
  647. - close(pdata->fd);
  648. - return 0;
  649. - }
  650. -
  651. - return 1;
  652. -}
  653. -/* }}} */
  654. -
  655. -/*
  656. - * Local variables:
  657. - * c-basic-offset: 4
  658. - * tab-width: 4
  659. - * End:
  660. - * vim600: fdm=marker
  661. - * vim: sw=4 ts=4 noet
  662. - */
  663. +/*
  664. + +----------------------------------------------------------------------+
  665. + | PHP Version 5 |
  666. + +----------------------------------------------------------------------+
  667. + | Copyright (c) 2009 Melanie Rhianna Lewis |
  668. + +----------------------------------------------------------------------+
  669. + | This source file is subject to version 3.0 of the PHP license, |
  670. + | that is bundled with this package in the file LICENSE, and is |
  671. + | available through the world-wide-web at the following url: |
  672. + | http://www.php.net/license/3_0.txt. |
  673. + | If you did not receive a copy of the PHP license and are unable to |
  674. + | obtain it through the world-wide-web, please send a note to |
  675. + | license@php.net so we can mail you a copy immediately. |
  676. + +----------------------------------------------------------------------+
  677. + | Author: Melanie Rhianna Lewis <cyberspice@php.net> |
  678. + +----------------------------------------------------------------------+
  679. + */
  680. +
  681. +#ifdef HAVE_CONFIG_H
  682. +#include "config.h"
  683. +#endif
  684. +
  685. +#include "php.h"
  686. +
  687. +#include "php_dio_common.h"
  688. +
  689. +/* {{{ dio_stream_mode_to_flags
  690. + * Convert an fopen() mode string to open() flags
  691. + */
  692. +static int dio_stream_mode_to_flags(const char *mode) {
  693. + int flags = 0, ch = 0, bin = 1;
  694. +
  695. + switch(mode[ch++]) {
  696. + case 'r':
  697. + flags = 0;
  698. + break;
  699. + case 'w':
  700. + flags = O_TRUNC | O_CREAT;
  701. + break;
  702. + case 'a':
  703. + flags = O_APPEND | O_CREAT;
  704. + break;
  705. + case 'x':
  706. + flags = O_EXCL | O_CREAT;
  707. + break;
  708. + }
  709. +
  710. + if (mode[ch] != '+') {
  711. + bin = (mode[ch++] == 'b');
  712. + }
  713. +
  714. + if (mode[ch] == '+') {
  715. + flags |= O_RDWR;
  716. + } else if (flags) {
  717. + flags |= O_WRONLY;
  718. + } else {
  719. + flags |= O_RDONLY;
  720. + }
  721. +
  722. +#if defined(_O_TEXT) && defined(O_BINARY)
  723. + if (bin) {
  724. + flags |= O_BINARY;
  725. + } else {
  726. + flags |= _O_TEXT;
  727. + }
  728. +#endif
  729. +
  730. + return flags;
  731. +}
  732. +/* }}} */
  733. +
  734. +/* {{{ dio_data_rate_to_define
  735. + * Converts a numeric data rate to a termios define
  736. + */
  737. +static int dio_data_rate_to_define(long rate, speed_t *def) {
  738. + speed_t val;
  739. +
  740. + switch (rate) {
  741. + case 0:
  742. + val = 0;
  743. + break;
  744. + case 50:
  745. + val = B50;
  746. + break;
  747. + case 75:
  748. + val = B75;
  749. + break;
  750. + case 110:
  751. + val = B110;
  752. + break;
  753. + case 134:
  754. + val = B134;
  755. + break;
  756. + case 150:
  757. + val = B150;
  758. + break;
  759. + case 200:
  760. + val = B200;
  761. + break;
  762. + case 300:
  763. + val = B300;
  764. + break;
  765. + case 600:
  766. + val = B600;
  767. + break;
  768. + case 1200:
  769. + val = B1200;
  770. + break;
  771. + case 1800:
  772. + val = B1800;
  773. + break;
  774. + case 2400:
  775. + val = B2400;
  776. + break;
  777. + case 4800:
  778. + val = B4800;
  779. + break;
  780. + case 9600:
  781. + val = B9600;
  782. + break;
  783. + case 19200:
  784. + val = B19200;
  785. + break;
  786. + case 38400:
  787. + val = B38400;
  788. + break;
  789. +#ifdef B57600
  790. + case 57600:
  791. + val = B57600;
  792. + break;
  793. +#endif
  794. +#ifdef B115200
  795. + case 115200:
  796. + val = B115200;
  797. + break;
  798. +#endif
  799. +#ifdef B230400
  800. + case 230400:
  801. + val = B230400;
  802. + break;
  803. +#endif
  804. +#ifdef B460800
  805. + case 460800:
  806. + val = B460800;
  807. + break;
  808. +#endif
  809. + default:
  810. + return 0;
  811. + }
  812. +
  813. + *def = val;
  814. + return 1;
  815. +}
  816. +
  817. +/* {{{ dio_data_bits_to_define
  818. + * Converts a number of data bits to a termios define
  819. + */
  820. +static int dio_data_bits_to_define(int data_bits, int *def) {
  821. + int val;
  822. +
  823. + switch (data_bits) {
  824. + case 8:
  825. + val = CS8;
  826. + break;
  827. + case 7:
  828. + val = CS7;
  829. + break;
  830. + case 6:
  831. + val = CS6;
  832. + break;
  833. + case 5:
  834. + val = CS5;
  835. + break;
  836. + default:
  837. + return 0;
  838. + }
  839. +
  840. + *def = val;
  841. + return 1;
  842. +}
  843. +/* }}} */
  844. +
  845. +/* {{{ dio_stop_bits_to_define
  846. + * Converts a number of stop bits to a termios define
  847. + */
  848. +static int dio_stop_bits_to_define(int stop_bits, int *def) {
  849. + int val;
  850. +
  851. + switch (stop_bits) {
  852. + case 1:
  853. + val = 0;
  854. + break;
  855. + case 2:
  856. + val = CSTOPB;
  857. + break;
  858. + default:
  859. + return 0;
  860. + }
  861. +
  862. + *def = val;
  863. + return 1;
  864. +}
  865. +/* }}} */
  866. +
  867. +/* {{{ dio_parity_to_define
  868. + * Converts a parity type to a termios define
  869. + */
  870. +static int dio_parity_to_define(int parity, int *def) {
  871. + int val;
  872. +
  873. + switch (parity) {
  874. + case 0:
  875. + val = 0;
  876. + break;
  877. + case 1:
  878. + val = PARENB | PARODD;
  879. + break;
  880. + case 2:
  881. + val = PARENB;
  882. + break;
  883. + default:
  884. + return 0;
  885. + }
  886. +
  887. + *def = val;
  888. + return 1;
  889. +}
  890. +/* }}} */
  891. +
  892. +/* {{{ dio_create_stream_data
  893. + * Creates an initialised stream data structure. Free with efree().
  894. + */
  895. +php_dio_stream_data * dio_create_stream_data(void) {
  896. + php_dio_posix_stream_data * data = emalloc(sizeof(php_dio_posix_stream_data));
  897. + dio_init_stream_data(&(data->common));
  898. + data->fd = -1;
  899. + data->flags = 0;
  900. +
  901. + return (php_dio_stream_data *)data;
  902. +}
  903. +/* }}} */
  904. +
  905. +/* {{{ dio_common_write
  906. + * Writes count chars from the buffer to the stream described by the stream data.
  907. + */
  908. +size_t dio_common_write(php_dio_stream_data *data, const char *buf, size_t count) {
  909. + size_t ret;
  910. +
  911. + /* Blocking writes can be interrupted by signals etc. If
  912. + * interrupted try again. Not sure about non-blocking
  913. + * writes but it doesn't hurt to check. */
  914. + do {
  915. + ret = write(((php_dio_posix_stream_data*)data)->fd, buf, count);
  916. + if (ret > 0) {
  917. + return ret;
  918. + }
  919. + } while (errno == EINTR);
  920. + return 0;
  921. +}
  922. +/* }}} */
  923. +
  924. +#ifdef DIO_NONBLOCK
  925. +/* {{{ dio_timeval_subtract
  926. + * Calculates the difference between two timevals returning the result in the
  927. + * structure pointed to by diffptr. Returns -1 as error if late time is
  928. + * earlier than early time.
  929. + */
  930. +static int dio_timeval_subtract(struct timeval *late, struct timeval *early, struct timeval *diff) {
  931. + struct timeval *tmp;
  932. +
  933. + /* Handle negatives */
  934. + if (late->tv_sec < early->tv_sec) {
  935. + return 0;
  936. + }
  937. +
  938. + if ((late->tv_sec == early->tv_sec) && (late->tv_usec < early->tv_usec)) {
  939. + return 0;
  940. + }
  941. +
  942. + /* Handle any carry. If later usec is smaller than earlier usec simple
  943. + * subtraction will result in negative value. Since usec has a maximum
  944. + * of one second by adding another second before the subtraction the
  945. + * result will always be positive. */
  946. + if (late->tv_usec < early->tv_usec) {
  947. + late->tv_usec += 1000000;
  948. + late->tv_sec--;
  949. + }
  950. +
  951. + /* Once adjusted can just subtract values. */
  952. + diff->tv_sec = late->tv_sec - early->tv_sec;
  953. + diff->tv_usec = late->tv_usec - early->tv_usec;
  954. +
  955. + return 1;
  956. +}
  957. +#endif
  958. +
  959. +/* {{{ dio_common_read
  960. + * Reads count chars to the buffer to the stream described by the stream data.
  961. + */
  962. +size_t dio_common_read(php_dio_stream_data *data, const char *buf, size_t count) {
  963. + int fd = ((php_dio_posix_stream_data*)data)->fd;
  964. + size_t ret, total = 0;
  965. + char *ptr = (char*)buf;
  966. +
  967. + struct timeval timeout, timeouttmp, before, after, diff;
  968. + fd_set rfds;
  969. +
  970. + if (!data->has_timeout) {
  971. + /* Blocking reads can be interrupted by signals etc. If
  972. + * interrupted try again. Not sure about non-blocking
  973. + * reads but it doesn't hurt to check. */
  974. + do {
  975. + ret = read(fd, (char*)ptr, count);
  976. + if (ret > 0) {
  977. + return ret;
  978. + } else if (!ret) {
  979. + data->end_of_file = 1;
  980. + }
  981. + } while ((errno == EINTR) && !data->end_of_file);
  982. + return 0;
  983. + }
  984. +#ifdef DIO_NONBLOCK
  985. + else {
  986. + /* Clear timed out flag */
  987. + data->timed_out = 0;
  988. +
  989. + /* The initial timeout value */
  990. + timeout.tv_sec = data->timeout_sec;
  991. + timeout.tv_usec = data->timeout_usec;
  992. +
  993. + do {
  994. + /* The semantics of select() are that you cannot guarantee
  995. + * that the timeval structure passed in has not been changed by
  996. + * the select call. So you keep a copy. */
  997. + timeouttmp = timeout;
  998. +
  999. + /* The time before we wait for data. */
  1000. + (void) gettimeofday(&before, NULL);
  1001. +
  1002. + /* Wait for an event on our file descriptor. */
  1003. + FD_ZERO(&rfds);
  1004. + FD_SET(fd, &rfds);
  1005. +
  1006. + ret = select(fd + 1, &rfds, NULL, NULL, &timeouttmp);
  1007. + /* An error. */
  1008. + if ((ret < 0) && (errno != EINTR) && (errno != EAGAIN)) {
  1009. + return 0;
  1010. + }
  1011. +
  1012. + /* We have data to read. */
  1013. + if ((ret > 0) && FD_ISSET(fd, &rfds)) {
  1014. + ret = read(fd, ptr, count);
  1015. + /* Another error */
  1016. + if ((ret < 0) && (errno != EINTR) && (errno != EAGAIN)) {
  1017. + return 0;
  1018. + }
  1019. +
  1020. + if (ret > 0) {
  1021. + /* Got data, add it to the buffer. */
  1022. + ptr += ret;
  1023. + total += ret;
  1024. + count -= ret;
  1025. + } else if (!ret) {
  1026. + /* This should never happen since how can we have
  1027. + * data to read at an end of file, but still
  1028. + * just in case! */
  1029. + data->end_of_file = 1;
  1030. + break;
  1031. + }
  1032. + }
  1033. +
  1034. + /* If not timed out and not end of file and not all data read
  1035. + * calculate how long it took us and loop if we still have time
  1036. + * out time left. */
  1037. + if (count) {
  1038. + (void) gettimeofday(&after, NULL);
  1039. +
  1040. + /* Diff the timevals */
  1041. + (void) dio_timeval_subtract(&after, &before, &diff);
  1042. +
  1043. + /* Now adjust the timeout. */
  1044. + if (!dio_timeval_subtract(&timeout, &diff, &timeout)) {
  1045. + /* If it errors we've run out of time. */
  1046. + data->timed_out = 1;
  1047. + break;
  1048. + } else if (!timeout.tv_sec && !(timeout.tv_usec / 1000)) {
  1049. + /* Check for rounding issues (millisecond accuracy) */
  1050. + data->timed_out = 1;
  1051. + break;
  1052. + }
  1053. + }
  1054. + } while (count); /* Until time out or end of file or all data read. */
  1055. +
  1056. + return total;
  1057. + }
  1058. +#endif
  1059. +}
  1060. +/* }}} */
  1061. +
  1062. +/* {{{ php_dio_stream_data
  1063. + * Closes the php_stream.
  1064. + */
  1065. +int dio_common_close(php_dio_stream_data *data) {
  1066. + if (close(((php_dio_posix_stream_data*)data)->fd) < 0) {
  1067. + return 0;
  1068. + }
  1069. +
  1070. + return 1;
  1071. +}
  1072. +/* }}} */
  1073. +
  1074. +/* {{{ dio_common_set_option
  1075. + * Sets/gets stream options
  1076. + */
  1077. +int dio_common_set_option(php_dio_stream_data *data, int option, int value, void *ptrparam) {
  1078. + int fd = ((php_dio_posix_stream_data*)data)->fd;
  1079. + int old_is_blocking;
  1080. + int flags;
  1081. +
  1082. + switch (option) {
  1083. +#ifdef DIO_NONBLOCK
  1084. + case PHP_STREAM_OPTION_READ_TIMEOUT:
  1085. + if (ptrparam) {
  1086. + struct timeval *tv = (struct timeval*)ptrparam;
  1087. +
  1088. + flags = fcntl(fd, F_GETFL, 0);
  1089. +
  1090. + /* A timeout of zero seconds and zero microseconds disables
  1091. + any existing timeout. */
  1092. + if (tv->tv_sec || tv->tv_usec) {
  1093. + data->timeout_sec = tv->tv_sec;
  1094. + data->timeout_usec = tv->tv_usec;
  1095. + data->has_timeout = -1;
  1096. + (void) fcntl(fd, F_SETFL, flags & ~DIO_NONBLOCK);
  1097. + } else {
  1098. + data->timeout_sec = 0;
  1099. + data->timeout_usec = 0;
  1100. + data->has_timeout = 0;
  1101. + data->timed_out = 0;
  1102. + (void) fcntl(fd, F_SETFL, flags | DIO_NONBLOCK);
  1103. + }
  1104. +
  1105. + return PHP_STREAM_OPTION_RETURN_OK;
  1106. + } else {
  1107. + return PHP_STREAM_OPTION_RETURN_ERR;
  1108. + }
  1109. +
  1110. + case PHP_STREAM_OPTION_BLOCKING:
  1111. + flags = fcntl(fd, F_GETFL, 0);
  1112. + if (value) {
  1113. + flags &= ~DIO_NONBLOCK;
  1114. + } else {
  1115. + flags |= DIO_NONBLOCK;
  1116. + }
  1117. + (void) fcntl(fd, F_SETFL, flags);
  1118. +
  1119. + old_is_blocking = data->is_blocking;
  1120. + data->is_blocking = value;
  1121. + return old_is_blocking ? PHP_STREAM_OPTION_RETURN_OK : PHP_STREAM_OPTION_RETURN_ERR;
  1122. +#endif /* O_NONBLOCK */
  1123. +
  1124. + default:
  1125. + break;
  1126. + }
  1127. +
  1128. + return 1;
  1129. +}
  1130. +/* }}} */
  1131. +
  1132. +/* {{{ dio_raw_open_stream
  1133. + * Opens the underlying stream.
  1134. + */
  1135. +int dio_raw_open_stream(char *filename, char *mode, php_dio_stream_data *data TSRMLS_DC) {
  1136. + php_dio_posix_stream_data *pdata = (php_dio_posix_stream_data*)data;
  1137. + pdata->flags = dio_stream_mode_to_flags(mode);
  1138. +
  1139. +#ifdef DIO_NONBLOCK
  1140. + if (!data->is_blocking || data->has_timeout) {
  1141. + pdata->flags |= DIO_NONBLOCK;
  1142. + }
  1143. +#endif
  1144. +
  1145. + /* Open the file and handle any errors. */
  1146. +#ifdef DIO_HAS_FILEPERMS
  1147. + if (data->has_perms) {
  1148. + pdata->fd = open(filename, pdata->flags, (mode_t)data->perms);
  1149. + } else {
  1150. + pdata->fd = open(filename, pdata->flags);
  1151. + }
  1152. +#else
  1153. + pdata->fd = open(filename, pdata->flags);
  1154. +#endif
  1155. +
  1156. + if (pdata->fd < 0) {
  1157. + switch (errno) {
  1158. + case EEXIST:
  1159. + php_error_docref(NULL TSRMLS_CC, E_WARNING, "File exists!");
  1160. + return 0;
  1161. + default:
  1162. + return 0;
  1163. + }
  1164. + }
  1165. +
  1166. + return 1;
  1167. +}
  1168. +/* }}} */
  1169. +
  1170. +/* {{{ dio_serial_init
  1171. + * Initialises the serial settings storing the original settings before hand.
  1172. + */
  1173. +static int dio_serial_init(php_dio_stream_data *data TSRMLS_DC) {
  1174. + php_dio_posix_stream_data *pdata = (php_dio_posix_stream_data*)data;
  1175. + int ret = 0, data_bits_def, stop_bits_def, parity_def;
  1176. + struct termios tio;
  1177. + speed_t rate_def;
  1178. +
  1179. + if (!dio_data_rate_to_define(data->data_rate, &rate_def)) {
  1180. + php_error_docref(NULL TSRMLS_CC, E_WARNING, "invalid data_rate value (%ld)", data->data_rate);
  1181. + return 0;
  1182. + }
  1183. +
  1184. + if (!dio_data_bits_to_define(data->data_bits, &data_bits_def)) {
  1185. + php_error_docref(NULL TSRMLS_CC, E_WARNING, "invalid data_bits value (%d)", data->data_bits);
  1186. + return 0;
  1187. + }
  1188. +
  1189. + if (!dio_stop_bits_to_define(data->stop_bits, &stop_bits_def)) {
  1190. + php_error_docref(NULL TSRMLS_CC, E_WARNING, "invalid stop_bits value (%d)", data->stop_bits);
  1191. + return 0;
  1192. + }
  1193. +
  1194. + if (!dio_parity_to_define(data->parity, &parity_def)) {
  1195. + php_error_docref(NULL TSRMLS_CC, E_WARNING, "invalid parity value (%d)", data->parity);
  1196. + return 0;
  1197. + }
  1198. +
  1199. + ret = tcgetattr(pdata->fd, &(pdata->oldtio));
  1200. + if (ret < 0) {
  1201. + if ((errno == ENOTTY) || (errno == ENODEV)) {
  1202. + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Not a serial port or terminal!");
  1203. + }
  1204. + return 0;
  1205. + }
  1206. +
  1207. + ret = tcgetattr(pdata->fd, &tio);
  1208. + if (ret < 0) {
  1209. + return 0;
  1210. + }
  1211. +
  1212. + if (data->canonical) {
  1213. + tio.c_iflag = IGNPAR | ICRNL;
  1214. + tio.c_oflag = 0;
  1215. + tio.c_lflag = ICANON;
  1216. + } else {
  1217. + cfmakeraw(&tio);
  1218. + }
  1219. +
  1220. + cfsetispeed(&tio, rate_def);
  1221. + cfsetospeed(&tio, rate_def);
  1222. +
  1223. + tio.c_cflag &= ~CSIZE;
  1224. + tio.c_cflag |= data_bits_def;
  1225. + tio.c_cflag &= ~CSTOPB;
  1226. + tio.c_cflag |= stop_bits_def;
  1227. + tio.c_cflag &= ~(PARENB|PARODD);
  1228. + tio.c_cflag |= parity_def;
  1229. +
  1230. +#ifdef CRTSCTS
  1231. + tio.c_cflag &= ~(CLOCAL | CRTSCTS);
  1232. +#else
  1233. + tio.c_cflag &= ~CLOCAL;
  1234. +#endif
  1235. + if (!data->flow_control) {
  1236. + tio.c_cflag |= CLOCAL;
  1237. +#ifdef CRTSCTS
  1238. + } else {
  1239. + tio.c_cflag |= CRTSCTS;
  1240. +#endif
  1241. + }
  1242. +
  1243. + ret = tcsetattr(pdata->fd, TCSANOW, &tio);
  1244. + if (ret < 0) {
  1245. + return 0;
  1246. + }
  1247. +
  1248. + return 1;
  1249. +}
  1250. +/* }}} */
  1251. +
  1252. +/* {{{ dio_serial_uninit
  1253. + * Restores the serial settings back to their original state.
  1254. + */
  1255. +int dio_serial_uninit(php_dio_stream_data *data) {
  1256. + php_dio_posix_stream_data *pdata = (php_dio_posix_stream_data*)data;
  1257. + int ret;
  1258. +
  1259. + do {
  1260. + ret = tcsetattr(pdata->fd, TCSANOW, &(pdata->oldtio));
  1261. + } while ((ret < 0) && (errno == EINTR));
  1262. +
  1263. + return 1;
  1264. +}
  1265. +/* }}} */
  1266. +
  1267. +/* {{{ dio_serial_flush
  1268. + * Purges the serial buffers of data.
  1269. + */
  1270. +int dio_serial_purge(php_dio_stream_data *data) {
  1271. + php_dio_posix_stream_data *pdata = (php_dio_posix_stream_data*)data;
  1272. + int ret;
  1273. +
  1274. + if ((pdata->flags & O_RDWR) == O_RDWR) {
  1275. + ret = tcflush(pdata->fd, TCIOFLUSH);
  1276. + } else if ((pdata->flags & O_WRONLY) == O_WRONLY) {
  1277. + ret = tcflush(pdata->fd, TCOFLUSH);
  1278. + } else if ((pdata->flags & O_RDONLY) == O_RDONLY) {
  1279. + ret = tcflush(pdata->fd, TCIFLUSH);
  1280. + }
  1281. +
  1282. + if (ret < 0) {
  1283. + return 0;
  1284. + }
  1285. +
  1286. + return 1;
  1287. +}
  1288. +/* }}} */
  1289. +
  1290. +/* {{{ dio_serial_open_stream
  1291. + * Opens the underlying stream.
  1292. + */
  1293. +int dio_serial_open_stream(char *filename, char *mode, php_dio_stream_data *data TSRMLS_DC) {
  1294. + php_dio_posix_stream_data *pdata = (php_dio_posix_stream_data*)data;
  1295. +
  1296. +#ifdef O_NOCTTY
  1297. + /* We don't want a controlling TTY */
  1298. + pdata->flags |= O_NOCTTY;
  1299. +#endif
  1300. +
  1301. + if (!dio_raw_open_stream(filename, mode, data TSRMLS_CC)) {
  1302. + return 0;
  1303. + }
  1304. +
  1305. + if (!dio_serial_init(data TSRMLS_CC)) {
  1306. + close(pdata->fd);
  1307. + return 0;
  1308. + }
  1309. +
  1310. + return 1;
  1311. +}
  1312. +/* }}} */
  1313. +
  1314. +/*
  1315. + * Local variables:
  1316. + * c-basic-offset: 4
  1317. + * tab-width: 4
  1318. + * End:
  1319. + * vim600: fdm=marker
  1320. + * vim: sw=4 ts=4 noet
  1321. + */
  1322. --- a/dio_win32.c
  1323. +++ b/dio_win32.c
  1324. @@ -1,759 +1,759 @@
  1325. -/*
  1326. - +----------------------------------------------------------------------+
  1327. - | PHP Version 5 |
  1328. - +----------------------------------------------------------------------+
  1329. - | Copyright (c) 2009 Melanie Rhianna Lewis |
  1330. - +----------------------------------------------------------------------+
  1331. - | This source file is subject to version 3.0 of the PHP license, |
  1332. - | that is bundled with this package in the file LICENSE, and is |
  1333. - | available through the world-wide-web at the following url: |
  1334. - | http://www.php.net/license/3_0.txt. |
  1335. - | If you did not receive a copy of the PHP license and are unable to |
  1336. - | obtain it through the world-wide-web, please send a note to |
  1337. - | license@php.net so we can mail you a copy immediately. |
  1338. - +----------------------------------------------------------------------+
  1339. - | Author: Melanie Rhianna Lewis <cyberspice@php.net> |
  1340. - +----------------------------------------------------------------------+
  1341. - */
  1342. -
  1343. -#ifdef HAVE_CONFIG_H
  1344. -#include "config.h"
  1345. -#endif
  1346. -
  1347. -#include "php.h"
  1348. -#include "php_dio_common.h"
  1349. -
  1350. -#ifndef ZEND_WIN32
  1351. -#error ZEND_WIN32 not defined!
  1352. -#endif
  1353. -
  1354. -/* {{{ dio_last_error_php_error
  1355. - * Generates a PHP error message based upon the last Windows error.
  1356. - */
  1357. -static void dio_last_error_php_error(int level, char * message TSRMLS_DC) {
  1358. - LPVOID msgbuf;
  1359. - DWORD msgbuflen;
  1360. - char * errmsg;
  1361. - DWORD err;
  1362. -
  1363. -#ifdef UNICODE
  1364. - DWORD errmsglen;
  1365. -#endif
  1366. -
  1367. - err = GetLastError();
  1368. - msgbuflen = FormatMessage(
  1369. - FORMAT_MESSAGE_ALLOCATE_BUFFER|
  1370. - FORMAT_MESSAGE_FROM_SYSTEM|
  1371. - FORMAT_MESSAGE_IGNORE_INSERTS,
  1372. - NULL,
  1373. - err,
  1374. - MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
  1375. - (LPTSTR)&msgbuf,
  1376. - 0,
  1377. - NULL);
  1378. -
  1379. -#ifdef UNICODE
  1380. -
  1381. - /* Get the length of the converted message */
  1382. - errmsglen = WideCharToMultibyte(
  1383. - CP_ACP,
  1384. - 0
  1385. - (LPCWSTR)msgbuf,
  1386. - -1,
  1387. - (LPSTR)errmsg,
  1388. - 0,
  1389. - NULL,
  1390. - NULL);
  1391. -
  1392. - /* Allocate a buffer */
  1393. - errmsg = emalloc(errmsglen);
  1394. - if (!errmsg) {
  1395. - php_error_docref(NULL TSRMLS_CC, E_ERROR, "Out of memory in dio_last_error_php_error()!");
  1396. - LocalFree(msgbuf);
  1397. - return;
  1398. - }
  1399. -
  1400. - /* Convert the message */
  1401. - errmsglen = WideCharToMultibyte(
  1402. - CP_ACP,
  1403. - 0
  1404. - (LPCWSTR)msgbuf,
  1405. - -1,
  1406. - (LPSTR)errmsg,
  1407. - errmsglen,
  1408. - NULL,
  1409. - NULL);
  1410. -
  1411. -#else
  1412. - errmsg = (char *)msgbuf;
  1413. -#endif
  1414. -
  1415. - php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s[ERROR %d] %s", message, err, errmsg);
  1416. -
  1417. - LocalFree(msgbuf);
  1418. -#ifdef UNICODE
  1419. - efree(errmsg);
  1420. -#endif
  1421. -}
  1422. -
  1423. -/* {{{ dio_data_rate_to_define
  1424. - * Converts a numeric data rate to a termios define
  1425. - */
  1426. -static int dio_data_rate_to_define(long rate, DWORD *def) {
  1427. - switch (rate) {
  1428. - case 75:
  1429. - case 110:
  1430. - case 134:
  1431. - case 150:
  1432. - case 300:
  1433. - case 600:
  1434. - case 1200:
  1435. - case 1800:
  1436. - case 2400:
  1437. - case 4800:
  1438. - case 7200:
  1439. - case 9600:
  1440. - case 14400:
  1441. - case 19200:
  1442. - case 38400:
  1443. - case 57600:
  1444. - case 115200:
  1445. - case 56000:
  1446. - case 128000:
  1447. - case 256000:
  1448. - break;
  1449. - default:
  1450. - return 0;
  1451. - }
  1452. -
  1453. - *def = (DWORD)rate;
  1454. - return 1;
  1455. -}
  1456. -/* }}} */
  1457. -
  1458. -
  1459. -/* {{{ dio_data_bits_to_define
  1460. - * Converts a number of data bits to a termios define
  1461. - */
  1462. -static int dio_data_bits_to_define(int data_bits, DWORD *def) {
  1463. - switch (data_bits) {
  1464. - case 8:
  1465. - case 7:
  1466. - case 6:
  1467. - case 5:
  1468. - case 4:
  1469. - break;
  1470. - default:
  1471. - return 0;
  1472. - }
  1473. -
  1474. - *def = (DWORD)data_bits;
  1475. - return 1;
  1476. -}
  1477. -/* }}} */
  1478. -
  1479. -/* {{{ dio_stop_bits_to_define
  1480. - * Converts a number of stop bits to a termios define
  1481. - */
  1482. -static int dio_stop_bits_to_define(int stop_bits, DWORD *def) {
  1483. - DWORD val;
  1484. -
  1485. - switch (stop_bits) {
  1486. - case 1:
  1487. - val = ONESTOPBIT;
  1488. - break;
  1489. - case 2:
  1490. - val = TWOSTOPBITS;
  1491. - break;
  1492. - case 3:
  1493. - val = ONE5STOPBITS;
  1494. - break;
  1495. - default:
  1496. - return 0;
  1497. - }
  1498. -
  1499. - *def = val;
  1500. - return 1;
  1501. -}
  1502. -/* }}} */
  1503. -
  1504. -/* {{{ dio_parity_to_define
  1505. - * Converts a parity type to a termios define
  1506. - */
  1507. -static int dio_parity_to_define(int parity, DWORD *def) {
  1508. - DWORD val;
  1509. -
  1510. - switch (parity) {
  1511. - case 0:
  1512. - val = NOPARITY;
  1513. - break;
  1514. - case 1:
  1515. - val = ODDPARITY;
  1516. - break;
  1517. - case 2:
  1518. - val = EVENPARITY;
  1519. - break;
  1520. - default:
  1521. - return 0;
  1522. - }
  1523. -
  1524. - *def = val;
  1525. - return 1;
  1526. -}
  1527. -/* }}} */
  1528. -
  1529. -/* {{{ dio_create_stream_data
  1530. - * Creates an initialised stream data structure. Free with efree().
  1531. - */
  1532. -php_dio_stream_data * dio_create_stream_data(void) {
  1533. - php_dio_win32_stream_data * data = emalloc(sizeof(php_dio_win32_stream_data));
  1534. - memset(data, 0, sizeof(php_dio_win32_stream_data));
  1535. - dio_init_stream_data(&(data->common));
  1536. - data->handle = INVALID_HANDLE_VALUE;
  1537. - data->desired_access = 0;
  1538. - data->creation_disposition = 0;
  1539. - data->olddcb.DCBlength = sizeof(DCB);
  1540. -
  1541. - return (php_dio_stream_data *)data;
  1542. -}
  1543. -/* }}} */
  1544. -
  1545. -/* {{{ dio_common_write
  1546. - * Writes count chars from the buffer to the stream described by the stream data.
  1547. - */
  1548. -size_t dio_common_write(php_dio_stream_data *data, const char *buf, size_t count) {
  1549. - php_dio_win32_stream_data *wdata = (php_dio_win32_stream_data*)data;
  1550. - DWORD total = 0;
  1551. -
  1552. - if (WriteFile(wdata->handle, buf, (DWORD)count, &total, NULL)) {
  1553. - return (size_t)total;
  1554. - }
  1555. -
  1556. - return 0;
  1557. -}
  1558. -/* }}} */
  1559. -
  1560. -/* {{{ dio_buffer_read
  1561. - * Reads any available chars from the canonical buffer.
  1562. - */
  1563. -static size_t dio_buffer_read(php_dio_win32_stream_data *wdata, const char *buf, size_t count) {
  1564. - php_dio_win32_canon_data *canon_data = wdata->canon_data;
  1565. - size_t total = 0;
  1566. -
  1567. - /* Read always follows write. I.e. if read ptr > write ptr buffer has
  1568. - wrapped and so we need to copy two blocks of data. */
  1569. - if (canon_data->read_pos > canon_data->write_pos) {
  1570. -
  1571. - /* Check we actually need to copy both blocks */
  1572. - if ((canon_data->size - canon_data->read_pos) > count) {
  1573. -
  1574. - /* No we don't. Just copy as much as we were asked for. */
  1575. - memcpy((char*)buf,
  1576. - &(canon_data->buf[canon_data->read_pos]),
  1577. - count);
  1578. - /* Update the read pointer. */
  1579. - canon_data->read_pos += count;
  1580. -
  1581. - /* Return the amount read. */
  1582. - return count;
  1583. - } else {
  1584. -
  1585. - /* We need to copy both blocks so copy data up to the end of
  1586. - the buffer. */
  1587. - total = canon_data->size - canon_data->read_pos;
  1588. - memcpy((char*)buf,
  1589. - &(canon_data->buf[canon_data->read_pos]),
  1590. - total);
  1591. - canon_data->read_pos = 0;
  1592. - count -= total;
  1593. -
  1594. - /* Now copy the data from the start of the buffer either up
  1595. - count or the number of bytes in the buffer. */
  1596. -
  1597. - if (canon_data->write_pos > count) {
  1598. - memcpy((char*)buf, canon_data->buf, count);
  1599. - canon_data->read_pos = count;
  1600. - total += count;
  1601. -
  1602. - return total;
  1603. - } else {
  1604. - memcpy((char*)buf, canon_data->buf, canon_data->write_pos);
  1605. - canon_data->read_pos = canon_data->write_pos;
  1606. - total += canon_data->write_pos;
  1607. -
  1608. - return total;
  1609. - }
  1610. - }
  1611. -
  1612. - /* Else if write follows read. This is a simpler case. We just copy
  1613. - either all the data buffered or count, which ever is smaller. */
  1614. - } else if (canon_data->write_pos > canon_data->read_pos) {
  1615. - if ((canon_data->write_pos - canon_data->read_pos) > count) {
  1616. - memcpy((char*)buf,
  1617. - &(canon_data->buf[canon_data->read_pos]),
  1618. - count);
  1619. - canon_data->read_pos += count;
  1620. -
  1621. - return count;
  1622. - } else {
  1623. - total = canon_data->write_pos - canon_data->read_pos;
  1624. - memcpy((char*)buf,
  1625. - &(canon_data->buf[canon_data->read_pos]),
  1626. - total);
  1627. - canon_data->read_pos += total;
  1628. -
  1629. - return total;
  1630. - }
  1631. - }
  1632. -
  1633. - /* Else we need to read more data from the data port. */
  1634. - return 0;
  1635. -}
  1636. -
  1637. -/* {{{ dio_com_read
  1638. - * Read chars from the data port.
  1639. - */
  1640. -static size_t dio_com_read(php_dio_stream_data *data, const char *buf, size_t count) {
  1641. - php_dio_win32_stream_data *wdata = (php_dio_win32_stream_data*)data;
  1642. - DWORD err, total = 0;
  1643. -
  1644. - if (ReadFile(wdata->handle, (void*)buf, (DWORD)count, &total, NULL)) {
  1645. -
  1646. - if (total) {
  1647. - return (size_t)total;
  1648. - }
  1649. -
  1650. - data->end_of_file = 1;
  1651. - }
  1652. -
  1653. - if (!data->end_of_file) {
  1654. - err = GetLastError();
  1655. -
  1656. - if (ERROR_HANDLE_EOF == err) {
  1657. - data->end_of_file = 1;
  1658. - }
  1659. - }
  1660. -
  1661. - return 0;
  1662. -}
  1663. -
  1664. -/* {{{ dio_canonical_read
  1665. - * Reads chars from the input stream until the internal buffer is full or a new
  1666. - * line is reached.
  1667. - */
  1668. -static size_t dio_canonical_read(php_dio_win32_stream_data *wdata, const char *buf, size_t count) {
  1669. - php_dio_win32_canon_data *canon_data = wdata->canon_data;
  1670. - size_t total = 0;
  1671. - char ch;
  1672. -
  1673. - /* See if there's any buffered data and copy it. */
  1674. - total = dio_buffer_read(wdata, buf, count);
  1675. - if (total) {
  1676. - return total;
  1677. - }
  1678. -
  1679. - /* Need to read more data from the data port. Buffer should be empty(er)
  1680. - by now. */
  1681. - do {
  1682. - /* Is the buffer full? */
  1683. - if (((canon_data->write_pos + 1) % canon_data->size) ==
  1684. - canon_data->read_pos) {
  1685. - break;
  1686. - }
  1687. -
  1688. - /* Read a byte from the input checking for EOF. */
  1689. - if (!dio_com_read((php_dio_stream_data*)wdata, &ch, 1)) {
  1690. - break;
  1691. - }
  1692. -
  1693. - /* Translate CR to newlines (same as ICRNL in POSIX) */
  1694. - ch = (ch != '\r') ? ch : '\n';
  1695. -
  1696. - /* We read a character! So buffer it. */
  1697. - canon_data->buf[canon_data->write_pos++] = ch;
  1698. - if (canon_data->write_pos >= canon_data->size) {
  1699. - canon_data->write_pos = 0;
  1700. - }
  1701. -
  1702. - /* End of line/input (^D)? */
  1703. - } while ((ch != '\n') && (ch != 0x04));
  1704. -
  1705. - return dio_buffer_read(wdata, buf, count);
  1706. -}
  1707. -/* }}} */
  1708. -
  1709. -/* {{{ dio_common_read
  1710. - * Reads count chars to the buffer to the stream described by the stream data.
  1711. - */
  1712. -size_t dio_common_read(php_dio_stream_data *data, const char *buf, size_t count) {
  1713. -
  1714. - /* You ask for no bytes you'll get none :-) */
  1715. - if (!count) {
  1716. - return 0;
  1717. - }
  1718. -
  1719. - if (data->canonical) {
  1720. - return dio_canonical_read((php_dio_win32_stream_data*)data, buf, count);
  1721. - } else {
  1722. - return dio_com_read(data, buf, count);
  1723. - }
  1724. -}
  1725. -/* }}} */
  1726. -
  1727. -/* {{{ php_dio_stream_data
  1728. - * Closes the php_stream.
  1729. - */
  1730. -int dio_common_close(php_dio_stream_data *data) {
  1731. - php_dio_win32_stream_data *wdata = (php_dio_win32_stream_data*)data;
  1732. -
  1733. - if (data->canonical) {
  1734. - efree(wdata->canon_data);
  1735. - }
  1736. -
  1737. - if (!CloseHandle(wdata->handle)) {
  1738. - return 0;
  1739. - }
  1740. -
  1741. - return 1;
  1742. -}
  1743. -/* }}} */
  1744. -
  1745. -/* {{{ dio_common_set_option
  1746. - * Sets/gets stream options
  1747. - */
  1748. -int dio_common_set_option(php_dio_stream_data *data, int option, int value, void *ptrparam) {
  1749. - COMMTIMEOUTS cto = { 0, 0, 0, 0, 0 };
  1750. - int old_is_blocking = 0;
  1751. -
  1752. - /* Can't do timeouts or non blocking with raw windows streams :-( */
  1753. - if (DIO_STREAM_TYPE_SERIAL == data->stream_type) {
  1754. - switch (option) {
  1755. - case PHP_STREAM_OPTION_BLOCKING:
  1756. - old_is_blocking = data->is_blocking;
  1757. - data->is_blocking = value ? 1 : 0;
  1758. -
  1759. - /* Only change values if we need to change them. */
  1760. - if (data->is_blocking != old_is_blocking) {
  1761. - /* If we're not blocking but don't have a timeout
  1762. - set to return immediately */
  1763. - if (!data->is_blocking && !data->has_timeout) {
  1764. - cto.ReadIntervalTimeout = MAXDWORD;
  1765. - }
  1766. -
  1767. - /* If we have a timeout ignore the blocking and set
  1768. - the total time in which to read the data */
  1769. - if (data->has_timeout) {
  1770. - cto.ReadIntervalTimeout = MAXDWORD;
  1771. - cto.ReadTotalTimeoutMultiplier = MAXDWORD;
  1772. - cto.ReadTotalTimeoutConstant = (data->timeout_usec / 1000) +
  1773. - (data->timeout_sec * 1000);
  1774. - }
  1775. -
  1776. - if (!SetCommTimeouts(((php_dio_win32_stream_data*)data)->handle, &cto)) {
  1777. - return PHP_STREAM_OPTION_RETURN_ERR;
  1778. - }
  1779. - }
  1780. - return old_is_blocking ? PHP_STREAM_OPTION_RETURN_OK : PHP_STREAM_OPTION_RETURN_ERR;
  1781. -
  1782. - case PHP_STREAM_OPTION_READ_TIMEOUT:
  1783. - if (ptrparam) {
  1784. - /* struct timeval is supported with PHP_WIN32 defined. */
  1785. - struct timeval *tv = (struct timeval*)ptrparam;
  1786. -
  1787. - /* A timeout of zero seconds and zero microseconds disables
  1788. - any existing timeout. */
  1789. - if (tv->tv_sec || tv->tv_usec) {
  1790. - data->timeout_sec = tv->tv_sec;
  1791. - data->timeout_usec = tv->tv_usec;
  1792. - data->has_timeout = -1;
  1793. -
  1794. - cto.ReadIntervalTimeout = MAXDWORD;
  1795. - cto.ReadTotalTimeoutMultiplier = MAXDWORD;
  1796. - cto.ReadTotalTimeoutConstant = (data->timeout_usec / 1000) +
  1797. - (data->timeout_sec * 1000);
  1798. - } else {
  1799. - data->timeout_sec = 0;
  1800. - data->timeout_usec = 0;
  1801. - data->has_timeout = 0;
  1802. - data->timed_out = 0;
  1803. -
  1804. - /* If we're not blocking but don't have a timeout
  1805. - set to return immediately */
  1806. - if (!data->is_blocking) {
  1807. - cto.ReadIntervalTimeout = MAXDWORD;
  1808. - }
  1809. - }
  1810. -
  1811. - if (!SetCommTimeouts(((php_dio_win32_stream_data*)data)->handle, &cto)) {
  1812. - return PHP_STREAM_OPTION_RETURN_ERR;
  1813. - } else {
  1814. - return PHP_STREAM_OPTION_RETURN_OK;
  1815. - }
  1816. - } else {
  1817. - return PHP_STREAM_OPTION_RETURN_ERR;
  1818. - }
  1819. -
  1820. - default:
  1821. - break;
  1822. - }
  1823. - }
  1824. -
  1825. - return 1;
  1826. -}
  1827. -/* }}} */
  1828. -
  1829. -/* {{{ dio_raw_open_stream
  1830. - * Opens the underlying stream.
  1831. - */
  1832. -int dio_raw_open_stream(char *filename, char *mode, php_dio_stream_data *data TSRMLS_DC) {
  1833. - php_dio_win32_stream_data *wdata = (php_dio_win32_stream_data*)data;
  1834. - DWORD err;
  1835. -
  1836. - switch(*mode) {
  1837. - case 'r':
  1838. - wdata->creation_disposition = OPEN_EXISTING;
  1839. - break;
  1840. - case 'w':
  1841. - wdata->creation_disposition = TRUNCATE_EXISTING;
  1842. - break;
  1843. - case 'a':
  1844. - wdata->creation_disposition = OPEN_ALWAYS;
  1845. - break;
  1846. - case 'x':
  1847. - wdata->creation_disposition = CREATE_NEW;
  1848. - break;
  1849. - }
  1850. - mode ++;
  1851. -
  1852. - if (*mode && (*mode != '+')) {
  1853. - mode++;
  1854. - }
  1855. -
  1856. - if (*mode && (*mode == '+')) {
  1857. - wdata->desired_access = GENERIC_READ | GENERIC_WRITE;
  1858. - } else if (OPEN_EXISTING == wdata->creation_disposition) {
  1859. - wdata->desired_access = GENERIC_READ;
  1860. - } else {
  1861. - wdata->desired_access = GENERIC_WRITE;
  1862. - }
  1863. -
  1864. - wdata->handle = CreateFile(filename, wdata->desired_access, 0,
  1865. - NULL, wdata->creation_disposition, FILE_ATTRIBUTE_NORMAL, NULL);
  1866. - if (INVALID_HANDLE_VALUE == wdata->handle) {
  1867. - err = GetLastError();
  1868. - switch (err) {
  1869. - case ERROR_FILE_EXISTS:
  1870. - php_error_docref(NULL TSRMLS_CC, E_WARNING, "File exists!");
  1871. - return 0;
  1872. -
  1873. - case ERROR_FILE_NOT_FOUND:
  1874. - /* ERROR_FILE_NOT_FOUND with TRUNCATE_EXISTING means that
  1875. - * the file doesn't exist so now try to create it. */
  1876. - if (TRUNCATE_EXISTING == wdata->creation_disposition) {
  1877. - php_error_docref(NULL TSRMLS_CC, E_NOTICE, "File does not exist, creating new file!");
  1878. -
  1879. - wdata->handle = CreateFile(filename, wdata->desired_access, 0,
  1880. - NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
  1881. - if (INVALID_HANDLE_VALUE == wdata->handle) {
  1882. - dio_last_error_php_error(E_WARNING, "CreateFile() failed:" TSRMLS_CC);
  1883. - return 0;
  1884. - }
  1885. - } else {
  1886. - php_error_docref(NULL TSRMLS_CC, E_WARNING, "File not found!");
  1887. - return 0;
  1888. - }
  1889. - break;
  1890. -
  1891. - default:
  1892. - dio_last_error_php_error(E_WARNING, "CreateFile() failed:" TSRMLS_CC);
  1893. - return 0;
  1894. - }
  1895. - }
  1896. -
  1897. - /* If canonical allocate the canonical buffer. */
  1898. - if (data->canonical) {
  1899. - wdata->canon_data = emalloc(sizeof(php_dio_win32_canon_data));
  1900. - memset(wdata->canon_data, 0, sizeof(php_dio_win32_canon_data));
  1901. - wdata->canon_data->size = DIO_WIN32_CANON_BUF_SIZE;
  1902. - }
  1903. -
  1904. - return 1;
  1905. -}
  1906. -/* }}} */
  1907. -
  1908. -/* {{{ dio_serial_init
  1909. - * Initialises the serial port
  1910. - */
  1911. -static int dio_serial_init(php_dio_stream_data *data TSRMLS_DC) {
  1912. - php_dio_win32_stream_data *wdata = (php_dio_win32_stream_data*)data;
  1913. - DWORD rate_def, data_bits_def, stop_bits_def, parity_def;
  1914. - DCB dcb;
  1915. -
  1916. - if (!dio_data_rate_to_define(data->data_rate, &rate_def)) {
  1917. - php_error_docref(NULL TSRMLS_CC, E_WARNING, "invalid data_rate value (%d)", data->data_rate);
  1918. - return 0;
  1919. - }
  1920. -
  1921. - if (!dio_data_bits_to_define(data->data_bits, &data_bits_def)) {
  1922. - php_error_docref(NULL TSRMLS_CC, E_WARNING, "invalid data_bits value (%d)", data->data_bits);
  1923. - return 0;
  1924. - }
  1925. -
  1926. - if (!dio_stop_bits_to_define(data->stop_bits, &stop_bits_def)) {
  1927. - php_error_docref(NULL TSRMLS_CC, E_WARNING, "invalid stop_bits value (%d)", data->stop_bits);
  1928. - return 0;
  1929. - }
  1930. -
  1931. - if (!dio_parity_to_define(data->parity, &parity_def)) {
  1932. - php_error_docref(NULL TSRMLS_CC, E_WARNING, "invalid parity value (%d)", data->parity);
  1933. - return 0;
  1934. - }
  1935. -
  1936. - if (!GetCommState(wdata->handle, &(wdata->olddcb))) {
  1937. - dio_last_error_php_error(E_WARNING, "GetCommState() failed:" TSRMLS_CC);
  1938. - return 0;
  1939. - }
  1940. -
  1941. - /* Init the DCB structure */
  1942. - memset(&dcb, 0, sizeof(DCB));
  1943. - dcb.DCBlength = sizeof(DCB);
  1944. -
  1945. - /* Set the communication parameters */
  1946. - dcb.fBinary = 1;
  1947. - dcb.BaudRate = rate_def;
  1948. - dcb.ByteSize = (BYTE)data_bits_def;
  1949. - dcb.StopBits = (BYTE)stop_bits_def;
  1950. - dcb.Parity = (BYTE)parity_def;
  1951. -
  1952. - /* Set the control line parameters */
  1953. - dcb.fDtrControl = DTR_CONTROL_DISABLE;
  1954. - dcb.fDsrSensitivity = FALSE;
  1955. - dcb.fOutxDsrFlow = FALSE;
  1956. - dcb.fTXContinueOnXoff = FALSE;
  1957. - dcb.fOutX = FALSE;
  1958. - dcb.fInX = FALSE;
  1959. - dcb.fErrorChar = FALSE;
  1960. - dcb.fNull = FALSE;
  1961. - dcb.fAbortOnError = FALSE;
  1962. -
  1963. - /* Hardware flow control */
  1964. - if (data->flow_control) {
  1965. - dcb.fOutxCtsFlow = TRUE;
  1966. - dcb.fRtsControl = RTS_CONTROL_HANDSHAKE;
  1967. - } else {
  1968. - dcb.fOutxCtsFlow = FALSE;
  1969. - dcb.fRtsControl = RTS_CONTROL_DISABLE;
  1970. - }
  1971. -
  1972. - if (!SetCommState(wdata->handle, &dcb)) {
  1973. - dio_last_error_php_error(E_WARNING, "SetCommState() failed:" TSRMLS_CC);
  1974. - return 0;
  1975. - }
  1976. -
  1977. - return 1;
  1978. -}
  1979. -/* }}} */
  1980. -
  1981. -
  1982. -/* {{{ dio_serial_uninit
  1983. - * Restores the serial settings back to their original state.
  1984. - */
  1985. -int dio_serial_uninit(php_dio_stream_data *data) {
  1986. - php_dio_win32_stream_data *wdata = (php_dio_win32_stream_data*)data;
  1987. -
  1988. - if (!SetCommState(wdata->handle, &(wdata->olddcb))) {
  1989. - return 0;
  1990. - }
  1991. -
  1992. - return 1;
  1993. -}
  1994. -/* }}} */
  1995. -
  1996. -/* {{{ dio_serial_flush
  1997. - * Purges the serial buffers of data.
  1998. - */
  1999. -int dio_serial_purge(php_dio_stream_data *data) {
  2000. - php_dio_win32_stream_data *wdata = (php_dio_win32_stream_data*)data;
  2001. - BOOL ret;
  2002. -
  2003. - /* Purge the canonical buffer if required */
  2004. - if (data->canonical && ((wdata->desired_access & GENERIC_READ) == GENERIC_READ)) {
  2005. - wdata->canon_data->read_pos = 0;
  2006. - wdata->canon_data->write_pos = 0;
  2007. - }
  2008. -
  2009. - /* Purge the com port */
  2010. - if ((wdata->desired_access & (GENERIC_READ|GENERIC_WRITE)) == (GENERIC_READ|GENERIC_WRITE)) {
  2011. - ret = PurgeComm(wdata->handle, PURGE_RXCLEAR|PURGE_TXCLEAR);
  2012. - } else if ((wdata->desired_access & GENERIC_WRITE) == GENERIC_WRITE) {
  2013. - ret = PurgeComm(wdata->handle, PURGE_TXCLEAR);
  2014. - } else if ((wdata->desired_access & GENERIC_READ) == GENERIC_READ) {
  2015. - ret = PurgeComm(wdata->handle, PURGE_RXCLEAR);
  2016. - }
  2017. -
  2018. - return ret;
  2019. -}
  2020. -/* }}} */
  2021. -
  2022. -/* {{{ dio_serial_open_stream
  2023. - * Opens the underlying stream.
  2024. - */
  2025. -int dio_serial_open_stream(char *filename, char *mode, php_dio_stream_data *data TSRMLS_DC) {
  2026. - php_dio_win32_stream_data *wdata = (php_dio_win32_stream_data*)data;
  2027. - COMMTIMEOUTS cto = { 0, 0, 0, 0, 0 };
  2028. -
  2029. - php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Opening \"%s\" as a serial port (mode=\"%s\").", filename, mode);
  2030. -
  2031. - if (*mode != 'r') {
  2032. - php_error_docref(NULL TSRMLS_CC, E_WARNING, "You must open serial ports in read or read/write mode!");
  2033. - return 0;
  2034. - }
  2035. -
  2036. - if (!dio_raw_open_stream(filename, mode, data TSRMLS_CC)) {
  2037. - return 0;
  2038. - }
  2039. -
  2040. - if (!GetCommTimeouts(wdata->handle, &(wdata->oldcto))) {
  2041. - dio_last_error_php_error(E_WARNING, "GetCommTimeouts() failed (Not a comm port?):" TSRMLS_CC);
  2042. - CloseHandle(wdata->handle);
  2043. - return 0;
  2044. - }
  2045. -
  2046. - /* If we're not blocking but don't have a timeout
  2047. - set to return immediately */
  2048. - if (!data->is_blocking && !data->has_timeout) {
  2049. - cto.ReadIntervalTimeout = MAXDWORD;
  2050. - }
  2051. -
  2052. - /* If we have a timeout ignore the blocking and set
  2053. - the total time in which to read the data */
  2054. - if (data->has_timeout) {
  2055. - cto.ReadIntervalTimeout = MAXDWORD;
  2056. - cto.ReadTotalTimeoutMultiplier = MAXDWORD;
  2057. - cto.ReadTotalTimeoutConstant = (data->timeout_usec / 1000) +
  2058. - (data->timeout_sec * 1000);
  2059. - }
  2060. -
  2061. - if (!SetCommTimeouts(wdata->handle, &cto)) {
  2062. - dio_last_error_php_error(E_WARNING, "SetCommTimeouts() failed:" TSRMLS_CC);
  2063. - CloseHandle(wdata->handle);
  2064. - return 0;
  2065. - }
  2066. -
  2067. - if (!dio_serial_init(data TSRMLS_CC)) {
  2068. - CloseHandle(wdata->handle);
  2069. - return 0;
  2070. - }
  2071. -
  2072. - return 1;
  2073. -}
  2074. -/* }}} */
  2075. -
  2076. -/*
  2077. - * Local variables:
  2078. - * c-basic-offset: 4
  2079. - * tab-width: 4
  2080. - * End:
  2081. - * vim600: fdm=marker
  2082. - * vim: sw=4 ts=4 noet
  2083. - */
  2084. +/*
  2085. + +----------------------------------------------------------------------+
  2086. + | PHP Version 5 |
  2087. + +----------------------------------------------------------------------+
  2088. + | Copyright (c) 2009 Melanie Rhianna Lewis |
  2089. + +----------------------------------------------------------------------+
  2090. + | This source file is subject to version 3.0 of the PHP license, |
  2091. + | that is bundled with this package in the file LICENSE, and is |
  2092. + | available through the world-wide-web at the following url: |
  2093. + | http://www.php.net/license/3_0.txt. |
  2094. + | If you did not receive a copy of the PHP license and are unable to |
  2095. + | obtain it through the world-wide-web, please send a note to |
  2096. + | license@php.net so we can mail you a copy immediately. |
  2097. + +----------------------------------------------------------------------+
  2098. + | Author: Melanie Rhianna Lewis <cyberspice@php.net> |
  2099. + +----------------------------------------------------------------------+
  2100. + */
  2101. +
  2102. +#ifdef HAVE_CONFIG_H
  2103. +#include "config.h"
  2104. +#endif
  2105. +
  2106. +#include "php.h"
  2107. +#include "php_dio_common.h"
  2108. +
  2109. +#ifndef ZEND_WIN32
  2110. +#error ZEND_WIN32 not defined!
  2111. +#endif
  2112. +
  2113. +/* {{{ dio_last_error_php_error
  2114. + * Generates a PHP error message based upon the last Windows error.
  2115. + */
  2116. +static void dio_last_error_php_error(int level, char * message TSRMLS_DC) {
  2117. + LPVOID msgbuf;
  2118. + DWORD msgbuflen;
  2119. + char * errmsg;
  2120. + DWORD err;
  2121. +
  2122. +#ifdef UNICODE
  2123. + DWORD errmsglen;
  2124. +#endif
  2125. +
  2126. + err = GetLastError();
  2127. + msgbuflen = FormatMessage(
  2128. + FORMAT_MESSAGE_ALLOCATE_BUFFER|
  2129. + FORMAT_MESSAGE_FROM_SYSTEM|
  2130. + FORMAT_MESSAGE_IGNORE_INSERTS,
  2131. + NULL,
  2132. + err,
  2133. + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
  2134. + (LPTSTR)&msgbuf,
  2135. + 0,
  2136. + NULL);
  2137. +
  2138. +#ifdef UNICODE
  2139. +
  2140. + /* Get the length of the converted message */
  2141. + errmsglen = WideCharToMultibyte(
  2142. + CP_ACP,
  2143. + 0
  2144. + (LPCWSTR)msgbuf,
  2145. + -1,
  2146. + (LPSTR)errmsg,
  2147. + 0,
  2148. + NULL,
  2149. + NULL);
  2150. +
  2151. + /* Allocate a buffer */
  2152. + errmsg = emalloc(errmsglen);
  2153. + if (!errmsg) {
  2154. + php_error_docref(NULL TSRMLS_CC, E_ERROR, "Out of memory in dio_last_error_php_error()!");
  2155. + LocalFree(msgbuf);
  2156. + return;
  2157. + }
  2158. +
  2159. + /* Convert the message */
  2160. + errmsglen = WideCharToMultibyte(
  2161. + CP_ACP,
  2162. + 0
  2163. + (LPCWSTR)msgbuf,
  2164. + -1,
  2165. + (LPSTR)errmsg,
  2166. + errmsglen,
  2167. + NULL,
  2168. + NULL);
  2169. +
  2170. +#else
  2171. + errmsg = (char *)msgbuf;
  2172. +#endif
  2173. +
  2174. + php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s[ERROR %d] %s", message, err, errmsg);
  2175. +
  2176. + LocalFree(msgbuf);
  2177. +#ifdef UNICODE
  2178. + efree(errmsg);
  2179. +#endif
  2180. +}
  2181. +
  2182. +/* {{{ dio_data_rate_to_define
  2183. + * Converts a numeric data rate to a termios define
  2184. + */
  2185. +static int dio_data_rate_to_define(long rate, DWORD *def) {
  2186. + switch (rate) {
  2187. + case 75:
  2188. + case 110:
  2189. + case 134:
  2190. + case 150:
  2191. + case 300:
  2192. + case 600:
  2193. + case 1200:
  2194. + case 1800:
  2195. + case 2400:
  2196. + case 4800:
  2197. + case 7200:
  2198. + case 9600:
  2199. + case 14400:
  2200. + case 19200:
  2201. + case 38400:
  2202. + case 57600:
  2203. + case 115200:
  2204. + case 56000:
  2205. + case 128000:
  2206. + case 256000:
  2207. + break;
  2208. + default:
  2209. + return 0;
  2210. + }
  2211. +
  2212. + *def = (DWORD)rate;
  2213. + return 1;
  2214. +}
  2215. +/* }}} */
  2216. +
  2217. +
  2218. +/* {{{ dio_data_bits_to_define
  2219. + * Converts a number of data bits to a termios define
  2220. + */
  2221. +static int dio_data_bits_to_define(int data_bits, DWORD *def) {
  2222. + switch (data_bits) {
  2223. + case 8:
  2224. + case 7:
  2225. + case 6:
  2226. + case 5:
  2227. + case 4:
  2228. + break;
  2229. + default:
  2230. + return 0;
  2231. + }
  2232. +
  2233. + *def = (DWORD)data_bits;
  2234. + return 1;
  2235. +}
  2236. +/* }}} */
  2237. +
  2238. +/* {{{ dio_stop_bits_to_define
  2239. + * Converts a number of stop bits to a termios define
  2240. + */
  2241. +static int dio_stop_bits_to_define(int stop_bits, DWORD *def) {
  2242. + DWORD val;
  2243. +
  2244. + switch (stop_bits) {
  2245. + case 1:
  2246. + val = ONESTOPBIT;
  2247. + break;
  2248. + case 2:
  2249. + val = TWOSTOPBITS;
  2250. + break;
  2251. + case 3:
  2252. + val = ONE5STOPBITS;
  2253. + break;
  2254. + default:
  2255. + return 0;
  2256. + }
  2257. +
  2258. + *def = val;
  2259. + return 1;
  2260. +}
  2261. +/* }}} */
  2262. +
  2263. +/* {{{ dio_parity_to_define
  2264. + * Converts a parity type to a termios define
  2265. + */
  2266. +static int dio_parity_to_define(int parity, DWORD *def) {
  2267. + DWORD val;
  2268. +
  2269. + switch (parity) {
  2270. + case 0:
  2271. + val = NOPARITY;
  2272. + break;
  2273. + case 1:
  2274. + val = ODDPARITY;
  2275. + break;
  2276. + case 2:
  2277. + val = EVENPARITY;
  2278. + break;
  2279. + default:
  2280. + return 0;
  2281. + }
  2282. +
  2283. + *def = val;
  2284. + return 1;
  2285. +}
  2286. +/* }}} */
  2287. +
  2288. +/* {{{ dio_create_stream_data
  2289. + * Creates an initialised stream data structure. Free with efree().
  2290. + */
  2291. +php_dio_stream_data * dio_create_stream_data(void) {
  2292. + php_dio_win32_stream_data * data = emalloc(sizeof(php_dio_win32_stream_data));
  2293. + memset(data, 0, sizeof(php_dio_win32_stream_data));
  2294. + dio_init_stream_data(&(data->common));
  2295. + data->handle = INVALID_HANDLE_VALUE;
  2296. + data->desired_access = 0;
  2297. + data->creation_disposition = 0;
  2298. + data->olddcb.DCBlength = sizeof(DCB);
  2299. +
  2300. + return (php_dio_stream_data *)data;
  2301. +}
  2302. +/* }}} */
  2303. +
  2304. +/* {{{ dio_common_write
  2305. + * Writes count chars from the buffer to the stream described by the stream data.
  2306. + */
  2307. +size_t dio_common_write(php_dio_stream_data *data, const char *buf, size_t count) {
  2308. + php_dio_win32_stream_data *wdata = (php_dio_win32_stream_data*)data;
  2309. + DWORD total = 0;
  2310. +
  2311. + if (WriteFile(wdata->handle, buf, (DWORD)count, &total, NULL)) {
  2312. + return (size_t)total;
  2313. + }
  2314. +
  2315. + return 0;
  2316. +}
  2317. +/* }}} */
  2318. +
  2319. +/* {{{ dio_buffer_read
  2320. + * Reads any available chars from the canonical buffer.
  2321. + */
  2322. +static size_t dio_buffer_read(php_dio_win32_stream_data *wdata, const char *buf, size_t count) {
  2323. + php_dio_win32_canon_data *canon_data = wdata->canon_data;
  2324. + size_t total = 0;
  2325. +
  2326. + /* Read always follows write. I.e. if read ptr > write ptr buffer has
  2327. + wrapped and so we need to copy two blocks of data. */
  2328. + if (canon_data->read_pos > canon_data->write_pos) {
  2329. +
  2330. + /* Check we actually need to copy both blocks */
  2331. + if ((canon_data->size - canon_data->read_pos) > count) {
  2332. +
  2333. + /* No we don't. Just copy as much as we were asked for. */
  2334. + memcpy((char*)buf,
  2335. + &(canon_data->buf[canon_data->read_pos]),
  2336. + count);
  2337. + /* Update the read pointer. */
  2338. + canon_data->read_pos += count;
  2339. +
  2340. + /* Return the amount read. */
  2341. + return count;
  2342. + } else {
  2343. +
  2344. + /* We need to copy both blocks so copy data up to the end of
  2345. + the buffer. */
  2346. + total = canon_data->size - canon_data->read_pos;
  2347. + memcpy((char*)buf,
  2348. + &(canon_data->buf[canon_data->read_pos]),
  2349. + total);
  2350. + canon_data->read_pos = 0;
  2351. + count -= total;
  2352. +
  2353. + /* Now copy the data from the start of the buffer either up
  2354. + count or the number of bytes in the buffer. */
  2355. +
  2356. + if (canon_data->write_pos > count) {
  2357. + memcpy((char*)buf, canon_data->buf, count);
  2358. + canon_data->read_pos = count;
  2359. + total += count;
  2360. +
  2361. + return total;
  2362. + } else {
  2363. + memcpy((char*)buf, canon_data->buf, canon_data->write_pos);
  2364. + canon_data->read_pos = canon_data->write_pos;
  2365. + total += canon_data->write_pos;
  2366. +
  2367. + return total;
  2368. + }
  2369. + }
  2370. +
  2371. + /* Else if write follows read. This is a simpler case. We just copy
  2372. + either all the data buffered or count, which ever is smaller. */
  2373. + } else if (canon_data->write_pos > canon_data->read_pos) {
  2374. + if ((canon_data->write_pos - canon_data->read_pos) > count) {
  2375. + memcpy((char*)buf,
  2376. + &(canon_data->buf[canon_data->read_pos]),
  2377. + count);
  2378. + canon_data->read_pos += count;
  2379. +
  2380. + return count;
  2381. + } else {
  2382. + total = canon_data->write_pos - canon_data->read_pos;
  2383. + memcpy((char*)buf,
  2384. + &(canon_data->buf[canon_data->read_pos]),
  2385. + total);
  2386. + canon_data->read_pos += total;
  2387. +
  2388. + return total;
  2389. + }
  2390. + }
  2391. +
  2392. + /* Else we need to read more data from the data port. */
  2393. + return 0;
  2394. +}
  2395. +
  2396. +/* {{{ dio_com_read
  2397. + * Read chars from the data port.
  2398. + */
  2399. +static size_t dio_com_read(php_dio_stream_data *data, const char *buf, size_t count) {
  2400. + php_dio_win32_stream_data *wdata = (php_dio_win32_stream_data*)data;
  2401. + DWORD err, total = 0;
  2402. +
  2403. + if (ReadFile(wdata->handle, (void*)buf, (DWORD)count, &total, NULL)) {
  2404. +
  2405. + if (total) {
  2406. + return (size_t)total;
  2407. + }
  2408. +
  2409. + data->end_of_file = 1;
  2410. + }
  2411. +
  2412. + if (!data->end_of_file) {
  2413. + err = GetLastError();
  2414. +
  2415. + if (ERROR_HANDLE_EOF == err) {
  2416. + data->end_of_file = 1;
  2417. + }
  2418. + }
  2419. +
  2420. + return 0;
  2421. +}
  2422. +
  2423. +/* {{{ dio_canonical_read
  2424. + * Reads chars from the input stream until the internal buffer is full or a new
  2425. + * line is reached.
  2426. + */
  2427. +static size_t dio_canonical_read(php_dio_win32_stream_data *wdata, const char *buf, size_t count) {
  2428. + php_dio_win32_canon_data *canon_data = wdata->canon_data;
  2429. + size_t total = 0;
  2430. + char ch;
  2431. +
  2432. + /* See if there's any buffered data and copy it. */
  2433. + total = dio_buffer_read(wdata, buf, count);
  2434. + if (total) {
  2435. + return total;
  2436. + }
  2437. +
  2438. + /* Need to read more data from the data port. Buffer should be empty(er)
  2439. + by now. */
  2440. + do {
  2441. + /* Is the buffer full? */
  2442. + if (((canon_data->write_pos + 1) % canon_data->size) ==
  2443. + canon_data->read_pos) {
  2444. + break;
  2445. + }
  2446. +
  2447. + /* Read a byte from the input checking for EOF. */
  2448. + if (!dio_com_read((php_dio_stream_data*)wdata, &ch, 1)) {
  2449. + break;
  2450. + }
  2451. +
  2452. + /* Translate CR to newlines (same as ICRNL in POSIX) */
  2453. + ch = (ch != '\r') ? ch : '\n';
  2454. +
  2455. + /* We read a character! So buffer it. */
  2456. + canon_data->buf[canon_data->write_pos++] = ch;
  2457. + if (canon_data->write_pos >= canon_data->size) {
  2458. + canon_data->write_pos = 0;
  2459. + }
  2460. +
  2461. + /* End of line/input (^D)? */
  2462. + } while ((ch != '\n') && (ch != 0x04));
  2463. +
  2464. + return dio_buffer_read(wdata, buf, count);
  2465. +}
  2466. +/* }}} */
  2467. +
  2468. +/* {{{ dio_common_read
  2469. + * Reads count chars to the buffer to the stream described by the stream data.
  2470. + */
  2471. +size_t dio_common_read(php_dio_stream_data *data, const char *buf, size_t count) {
  2472. +
  2473. + /* You ask for no bytes you'll get none :-) */
  2474. + if (!count) {
  2475. + return 0;
  2476. + }
  2477. +
  2478. + if (data->canonical) {
  2479. + return dio_canonical_read((php_dio_win32_stream_data*)data, buf, count);
  2480. + } else {
  2481. + return dio_com_read(data, buf, count);
  2482. + }
  2483. +}
  2484. +/* }}} */
  2485. +
  2486. +/* {{{ php_dio_stream_data
  2487. + * Closes the php_stream.
  2488. + */
  2489. +int dio_common_close(php_dio_stream_data *data) {
  2490. + php_dio_win32_stream_data *wdata = (php_dio_win32_stream_data*)data;
  2491. +
  2492. + if (data->canonical) {
  2493. + efree(wdata->canon_data);
  2494. + }
  2495. +
  2496. + if (!CloseHandle(wdata->handle)) {
  2497. + return 0;
  2498. + }
  2499. +
  2500. + return 1;
  2501. +}
  2502. +/* }}} */
  2503. +
  2504. +/* {{{ dio_common_set_option
  2505. + * Sets/gets stream options
  2506. + */
  2507. +int dio_common_set_option(php_dio_stream_data *data, int option, int value, void *ptrparam) {
  2508. + COMMTIMEOUTS cto = { 0, 0, 0, 0, 0 };
  2509. + int old_is_blocking = 0;
  2510. +
  2511. + /* Can't do timeouts or non blocking with raw windows streams :-( */
  2512. + if (DIO_STREAM_TYPE_SERIAL == data->stream_type) {
  2513. + switch (option) {
  2514. + case PHP_STREAM_OPTION_BLOCKING:
  2515. + old_is_blocking = data->is_blocking;
  2516. + data->is_blocking = value ? 1 : 0;
  2517. +
  2518. + /* Only change values if we need to change them. */
  2519. + if (data->is_blocking != old_is_blocking) {
  2520. + /* If we're not blocking but don't have a timeout
  2521. + set to return immediately */
  2522. + if (!data->is_blocking && !data->has_timeout) {
  2523. + cto.ReadIntervalTimeout = MAXDWORD;
  2524. + }
  2525. +
  2526. + /* If we have a timeout ignore the blocking and set
  2527. + the total time in which to read the data */
  2528. + if (data->has_timeout) {
  2529. + cto.ReadIntervalTimeout = MAXDWORD;
  2530. + cto.ReadTotalTimeoutMultiplier = MAXDWORD;
  2531. + cto.ReadTotalTimeoutConstant = (data->timeout_usec / 1000) +
  2532. + (data->timeout_sec * 1000);
  2533. + }
  2534. +
  2535. + if (!SetCommTimeouts(((php_dio_win32_stream_data*)data)->handle, &cto)) {
  2536. + return PHP_STREAM_OPTION_RETURN_ERR;
  2537. + }
  2538. + }
  2539. + return old_is_blocking ? PHP_STREAM_OPTION_RETURN_OK : PHP_STREAM_OPTION_RETURN_ERR;
  2540. +
  2541. + case PHP_STREAM_OPTION_READ_TIMEOUT:
  2542. + if (ptrparam) {
  2543. + /* struct timeval is supported with PHP_WIN32 defined. */
  2544. + struct timeval *tv = (struct timeval*)ptrparam;
  2545. +
  2546. + /* A timeout of zero seconds and zero microseconds disables
  2547. + any existing timeout. */
  2548. + if (tv->tv_sec || tv->tv_usec) {
  2549. + data->timeout_sec = tv->tv_sec;
  2550. + data->timeout_usec = tv->tv_usec;
  2551. + data->has_timeout = -1;
  2552. +
  2553. + cto.ReadIntervalTimeout = MAXDWORD;
  2554. + cto.ReadTotalTimeoutMultiplier = MAXDWORD;
  2555. + cto.ReadTotalTimeoutConstant = (data->timeout_usec / 1000) +
  2556. + (data->timeout_sec * 1000);
  2557. + } else {
  2558. + data->timeout_sec = 0;
  2559. + data->timeout_usec = 0;
  2560. + data->has_timeout = 0;
  2561. + data->timed_out = 0;
  2562. +
  2563. + /* If we're not blocking but don't have a timeout
  2564. + set to return immediately */
  2565. + if (!data->is_blocking) {
  2566. + cto.ReadIntervalTimeout = MAXDWORD;
  2567. + }
  2568. + }
  2569. +
  2570. + if (!SetCommTimeouts(((php_dio_win32_stream_data*)data)->handle, &cto)) {
  2571. + return PHP_STREAM_OPTION_RETURN_ERR;
  2572. + } else {
  2573. + return PHP_STREAM_OPTION_RETURN_OK;
  2574. + }
  2575. + } else {
  2576. + return PHP_STREAM_OPTION_RETURN_ERR;
  2577. + }
  2578. +
  2579. + default:
  2580. + break;
  2581. + }
  2582. + }
  2583. +
  2584. + return 1;
  2585. +}
  2586. +/* }}} */
  2587. +
  2588. +/* {{{ dio_raw_open_stream
  2589. + * Opens the underlying stream.
  2590. + */
  2591. +int dio_raw_open_stream(char *filename, char *mode, php_dio_stream_data *data TSRMLS_DC) {
  2592. + php_dio_win32_stream_data *wdata = (php_dio_win32_stream_data*)data;
  2593. + DWORD err;
  2594. +
  2595. + switch(*mode) {
  2596. + case 'r':
  2597. + wdata->creation_disposition = OPEN_EXISTING;
  2598. + break;
  2599. + case 'w':
  2600. + wdata->creation_disposition = TRUNCATE_EXISTING;
  2601. + break;
  2602. + case 'a':
  2603. + wdata->creation_disposition = OPEN_ALWAYS;
  2604. + break;
  2605. + case 'x':
  2606. + wdata->creation_disposition = CREATE_NEW;
  2607. + break;
  2608. + }
  2609. + mode ++;
  2610. +
  2611. + if (*mode && (*mode != '+')) {
  2612. + mode++;
  2613. + }
  2614. +
  2615. + if (*mode && (*mode == '+')) {
  2616. + wdata->desired_access = GENERIC_READ | GENERIC_WRITE;
  2617. + } else if (OPEN_EXISTING == wdata->creation_disposition) {
  2618. + wdata->desired_access = GENERIC_READ;
  2619. + } else {
  2620. + wdata->desired_access = GENERIC_WRITE;
  2621. + }
  2622. +
  2623. + wdata->handle = CreateFile(filename, wdata->desired_access, 0,
  2624. + NULL, wdata->creation_disposition, FILE_ATTRIBUTE_NORMAL, NULL);
  2625. + if (INVALID_HANDLE_VALUE == wdata->handle) {
  2626. + err = GetLastError();
  2627. + switch (err) {
  2628. + case ERROR_FILE_EXISTS:
  2629. + php_error_docref(NULL TSRMLS_CC, E_WARNING, "File exists!");
  2630. + return 0;
  2631. +
  2632. + case ERROR_FILE_NOT_FOUND:
  2633. + /* ERROR_FILE_NOT_FOUND with TRUNCATE_EXISTING means that
  2634. + * the file doesn't exist so now try to create it. */
  2635. + if (TRUNCATE_EXISTING == wdata->creation_disposition) {
  2636. + php_error_docref(NULL TSRMLS_CC, E_NOTICE, "File does not exist, creating new file!");
  2637. +
  2638. + wdata->handle = CreateFile(filename, wdata->desired_access, 0,
  2639. + NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
  2640. + if (INVALID_HANDLE_VALUE == wdata->handle) {
  2641. + dio_last_error_php_error(E_WARNING, "CreateFile() failed:" TSRMLS_CC);
  2642. + return 0;
  2643. + }
  2644. + } else {
  2645. + php_error_docref(NULL TSRMLS_CC, E_WARNING, "File not found!");
  2646. + return 0;
  2647. + }
  2648. + break;
  2649. +
  2650. + default:
  2651. + dio_last_error_php_error(E_WARNING, "CreateFile() failed:" TSRMLS_CC);
  2652. + return 0;
  2653. + }
  2654. + }
  2655. +
  2656. + /* If canonical allocate the canonical buffer. */
  2657. + if (data->canonical) {
  2658. + wdata->canon_data = emalloc(sizeof(php_dio_win32_canon_data));
  2659. + memset(wdata->canon_data, 0, sizeof(php_dio_win32_canon_data));
  2660. + wdata->canon_data->size = DIO_WIN32_CANON_BUF_SIZE;
  2661. + }
  2662. +
  2663. + return 1;
  2664. +}
  2665. +/* }}} */
  2666. +
  2667. +/* {{{ dio_serial_init
  2668. + * Initialises the serial port
  2669. + */
  2670. +static int dio_serial_init(php_dio_stream_data *data TSRMLS_DC) {
  2671. + php_dio_win32_stream_data *wdata = (php_dio_win32_stream_data*)data;
  2672. + DWORD rate_def, data_bits_def, stop_bits_def, parity_def;
  2673. + DCB dcb;
  2674. +
  2675. + if (!dio_data_rate_to_define(data->data_rate, &rate_def)) {
  2676. + php_error_docref(NULL TSRMLS_CC, E_WARNING, "invalid data_rate value (%d)", data->data_rate);
  2677. + return 0;
  2678. + }
  2679. +
  2680. + if (!dio_data_bits_to_define(data->data_bits, &data_bits_def)) {
  2681. + php_error_docref(NULL TSRMLS_CC, E_WARNING, "invalid data_bits value (%d)", data->data_bits);
  2682. + return 0;
  2683. + }
  2684. +
  2685. + if (!dio_stop_bits_to_define(data->stop_bits, &stop_bits_def)) {
  2686. + php_error_docref(NULL TSRMLS_CC, E_WARNING, "invalid stop_bits value (%d)", data->stop_bits);
  2687. + return 0;
  2688. + }
  2689. +
  2690. + if (!dio_parity_to_define(data->parity, &parity_def)) {
  2691. + php_error_docref(NULL TSRMLS_CC, E_WARNING, "invalid parity value (%d)", data->parity);
  2692. + return 0;
  2693. + }
  2694. +
  2695. + if (!GetCommState(wdata->handle, &(wdata->olddcb))) {
  2696. + dio_last_error_php_error(E_WARNING, "GetCommState() failed:" TSRMLS_CC);
  2697. + return 0;
  2698. + }
  2699. +
  2700. + /* Init the DCB structure */
  2701. + memset(&dcb, 0, sizeof(DCB));
  2702. + dcb.DCBlength = sizeof(DCB);
  2703. +
  2704. + /* Set the communication parameters */
  2705. + dcb.fBinary = 1;
  2706. + dcb.BaudRate = rate_def;
  2707. + dcb.ByteSize = (BYTE)data_bits_def;
  2708. + dcb.StopBits = (BYTE)stop_bits_def;
  2709. + dcb.Parity = (BYTE)parity_def;
  2710. +
  2711. + /* Set the control line parameters */
  2712. + dcb.fDtrControl = DTR_CONTROL_DISABLE;
  2713. + dcb.fDsrSensitivity = FALSE;
  2714. + dcb.fOutxDsrFlow = FALSE;
  2715. + dcb.fTXContinueOnXoff = FALSE;
  2716. + dcb.fOutX = FALSE;
  2717. + dcb.fInX = FALSE;
  2718. + dcb.fErrorChar = FALSE;
  2719. + dcb.fNull = FALSE;
  2720. + dcb.fAbortOnError = FALSE;
  2721. +
  2722. + /* Hardware flow control */
  2723. + if (data->flow_control) {
  2724. + dcb.fOutxCtsFlow = TRUE;
  2725. + dcb.fRtsControl = RTS_CONTROL_HANDSHAKE;
  2726. + } else {
  2727. + dcb.fOutxCtsFlow = FALSE;
  2728. + dcb.fRtsControl = RTS_CONTROL_DISABLE;
  2729. + }
  2730. +
  2731. + if (!SetCommState(wdata->handle, &dcb)) {
  2732. + dio_last_error_php_error(E_WARNING, "SetCommState() failed:" TSRMLS_CC);
  2733. + return 0;
  2734. + }
  2735. +
  2736. + return 1;
  2737. +}
  2738. +/* }}} */
  2739. +
  2740. +
  2741. +/* {{{ dio_serial_uninit
  2742. + * Restores the serial settings back to their original state.
  2743. + */
  2744. +int dio_serial_uninit(php_dio_stream_data *data) {
  2745. + php_dio_win32_stream_data *wdata = (php_dio_win32_stream_data*)data;
  2746. +
  2747. + if (!SetCommState(wdata->handle, &(wdata->olddcb))) {
  2748. + return 0;
  2749. + }
  2750. +
  2751. + return 1;
  2752. +}
  2753. +/* }}} */
  2754. +
  2755. +/* {{{ dio_serial_flush
  2756. + * Purges the serial buffers of data.
  2757. + */
  2758. +int dio_serial_purge(php_dio_stream_data *data) {
  2759. + php_dio_win32_stream_data *wdata = (php_dio_win32_stream_data*)data;
  2760. + BOOL ret;
  2761. +
  2762. + /* Purge the canonical buffer if required */
  2763. + if (data->canonical && ((wdata->desired_access & GENERIC_READ) == GENERIC_READ)) {
  2764. + wdata->canon_data->read_pos = 0;
  2765. + wdata->canon_data->write_pos = 0;
  2766. + }
  2767. +
  2768. + /* Purge the com port */
  2769. + if ((wdata->desired_access & (GENERIC_READ|GENERIC_WRITE)) == (GENERIC_READ|GENERIC_WRITE)) {
  2770. + ret = PurgeComm(wdata->handle, PURGE_RXCLEAR|PURGE_TXCLEAR);
  2771. + } else if ((wdata->desired_access & GENERIC_WRITE) == GENERIC_WRITE) {
  2772. + ret = PurgeComm(wdata->handle, PURGE_TXCLEAR);
  2773. + } else if ((wdata->desired_access & GENERIC_READ) == GENERIC_READ) {
  2774. + ret = PurgeComm(wdata->handle, PURGE_RXCLEAR);
  2775. + }
  2776. +
  2777. + return ret;
  2778. +}
  2779. +/* }}} */
  2780. +
  2781. +/* {{{ dio_serial_open_stream
  2782. + * Opens the underlying stream.
  2783. + */
  2784. +int dio_serial_open_stream(char *filename, char *mode, php_dio_stream_data *data TSRMLS_DC) {
  2785. + php_dio_win32_stream_data *wdata = (php_dio_win32_stream_data*)data;
  2786. + COMMTIMEOUTS cto = { 0, 0, 0, 0, 0 };
  2787. +
  2788. + php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Opening \"%s\" as a serial port (mode=\"%s\").", filename, mode);
  2789. +
  2790. + if (*mode != 'r') {
  2791. + php_error_docref(NULL TSRMLS_CC, E_WARNING, "You must open serial ports in read or read/write mode!");
  2792. + return 0;
  2793. + }
  2794. +
  2795. + if (!dio_raw_open_stream(filename, mode, data TSRMLS_CC)) {
  2796. + return 0;
  2797. + }
  2798. +
  2799. + if (!GetCommTimeouts(wdata->handle, &(wdata->oldcto))) {
  2800. + dio_last_error_php_error(E_WARNING, "GetCommTimeouts() failed (Not a comm port?):" TSRMLS_CC);
  2801. + CloseHandle(wdata->handle);
  2802. + return 0;
  2803. + }
  2804. +
  2805. + /* If we're not blocking but don't have a timeout
  2806. + set to return immediately */
  2807. + if (!data->is_blocking && !data->has_timeout) {
  2808. + cto.ReadIntervalTimeout = MAXDWORD;
  2809. + }
  2810. +
  2811. + /* If we have a timeout ignore the blocking and set
  2812. + the total time in which to read the data */
  2813. + if (data->has_timeout) {
  2814. + cto.ReadIntervalTimeout = MAXDWORD;
  2815. + cto.ReadTotalTimeoutMultiplier = MAXDWORD;
  2816. + cto.ReadTotalTimeoutConstant = (data->timeout_usec / 1000) +
  2817. + (data->timeout_sec * 1000);
  2818. + }
  2819. +
  2820. + if (!SetCommTimeouts(wdata->handle, &cto)) {
  2821. + dio_last_error_php_error(E_WARNING, "SetCommTimeouts() failed:" TSRMLS_CC);
  2822. + CloseHandle(wdata->handle);
  2823. + return 0;
  2824. + }
  2825. +
  2826. + if (!dio_serial_init(data TSRMLS_CC)) {
  2827. + CloseHandle(wdata->handle);
  2828. + return 0;
  2829. + }
  2830. +
  2831. + return 1;
  2832. +}
  2833. +/* }}} */
  2834. +
  2835. +/*
  2836. + * Local variables:
  2837. + * c-basic-offset: 4
  2838. + * tab-width: 4
  2839. + * End:
  2840. + * vim600: fdm=marker
  2841. + * vim: sw=4 ts=4 noet
  2842. + */
  2843. --- a/php_dio_posix.h
  2844. +++ b/php_dio_posix.h
  2845. @@ -1,70 +1,70 @@
  2846. -/*
  2847. - +----------------------------------------------------------------------+
  2848. - | PHP Version 5 |
  2849. - +----------------------------------------------------------------------+
  2850. - | Copyright (c) 2009 Melanie Rhianna Lewis |
  2851. - +----------------------------------------------------------------------+
  2852. - | This source file is subject to version 3.0 of the PHP license, |
  2853. - | that is bundled with this package in the file LICENSE, and is |
  2854. - | available through the world-wide-web at the following url: |
  2855. - | http://www.php.net/license/3_0.txt. |
  2856. - | If you did not receive a copy of the PHP license and are unable to |
  2857. - | obtain it through the world-wide-web, please send a note to |
  2858. - | license@php.net so we can mail you a copy immediately. |
  2859. - +----------------------------------------------------------------------+
  2860. - | Author: Melanie Rhianna Lewis <cyberspice@php.net> |
  2861. - +----------------------------------------------------------------------+
  2862. - */
  2863. -
  2864. -#ifndef PHP_DIO_POSIX_H_
  2865. -#define PHP_DIO_POSIX_H_
  2866. -
  2867. -#include <sys/stat.h>
  2868. -#include <sys/types.h>
  2869. -#include <sys/select.h>
  2870. -#include <sys/time.h>
  2871. -
  2872. -#ifdef HAVE_UNISTD_H
  2873. -#include <unistd.h>
  2874. -#endif
  2875. -
  2876. -#include <fcntl.h>
  2877. -#include <termios.h>
  2878. -
  2879. -
  2880. -/**
  2881. +/*
  2882. + +----------------------------------------------------------------------+
  2883. + | PHP Version 5 |
  2884. + +----------------------------------------------------------------------+
  2885. + | Copyright (c) 2009 Melanie Rhianna Lewis |
  2886. + +----------------------------------------------------------------------+
  2887. + | This source file is subject to version 3.0 of the PHP license, |
  2888. + | that is bundled with this package in the file LICENSE, and is |
  2889. + | available through the world-wide-web at the following url: |
  2890. + | http://www.php.net/license/3_0.txt. |
  2891. + | If you did not receive a copy of the PHP license and are unable to |
  2892. + | obtain it through the world-wide-web, please send a note to |
  2893. + | license@php.net so we can mail you a copy immediately. |
  2894. + +----------------------------------------------------------------------+
  2895. + | Author: Melanie Rhianna Lewis <cyberspice@php.net> |
  2896. + +----------------------------------------------------------------------+
  2897. + */
  2898. +
  2899. +#ifndef PHP_DIO_POSIX_H_
  2900. +#define PHP_DIO_POSIX_H_
  2901. +
  2902. +#include <sys/stat.h>
  2903. +#include <sys/types.h>
  2904. +#include <sys/select.h>
  2905. +#include <sys/time.h>
  2906. +
  2907. +#ifdef HAVE_UNISTD_H
  2908. +#include <unistd.h>
  2909. +#endif
  2910. +
  2911. +#include <fcntl.h>
  2912. +#include <termios.h>
  2913. +
  2914. +
  2915. +/**
  2916. * Detect if we can support non blocking IO.
  2917. - */
  2918. -#ifdef O_NONBLOCK
  2919. -#define DIO_NONBLOCK O_NONBLOCK
  2920. -#else
  2921. -#ifdef O_NDELAY
  2922. -#define DIO_NONBLOCK O_NDELAY
  2923. -#endif
  2924. -#endif
  2925. -
  2926. -/**
  2927. + */
  2928. +#ifdef O_NONBLOCK
  2929. +#define DIO_NONBLOCK O_NONBLOCK
  2930. +#else
  2931. +#ifdef O_NDELAY
  2932. +#define DIO_NONBLOCK O_NDELAY
  2933. +#endif
  2934. +#endif
  2935. +
  2936. +/**
  2937. * POSIXy platforms have file permissions
  2938. - */
  2939. -#define DIO_HAS_FILEPERMS
  2940. -
  2941. -#include "php_dio_common_data.h"
  2942. -
  2943. -typedef struct _php_dio_posix_stream_data {
  2944. - php_dio_stream_data common;
  2945. - int fd;
  2946. - int flags;
  2947. - /* Serial options */
  2948. - struct termios oldtio;
  2949. -} php_dio_posix_stream_data ;
  2950. -
  2951. -#endif /* PHP_DIO_POSIX_H_ */
  2952. -
  2953. -/*
  2954. - * Local variables:
  2955. - * c-basic-offset: 4
  2956. - * tab-width: 4
  2957. - * End:
  2958. - * vim600: fdm=marker
  2959. - * vim: sw=4 ts=4 noet
  2960. - */
  2961. + */
  2962. +#define DIO_HAS_FILEPERMS
  2963. +
  2964. +#include "php_dio_common_data.h"
  2965. +
  2966. +typedef struct _php_dio_posix_stream_data {
  2967. + php_dio_stream_data common;
  2968. + int fd;
  2969. + int flags;
  2970. + /* Serial options */
  2971. + struct termios oldtio;
  2972. +} php_dio_posix_stream_data ;
  2973. +
  2974. +#endif /* PHP_DIO_POSIX_H_ */
  2975. +
  2976. +/*
  2977. + * Local variables:
  2978. + * c-basic-offset: 4
  2979. + * tab-width: 4
  2980. + * End:
  2981. + * vim600: fdm=marker
  2982. + * vim: sw=4 ts=4 noet
  2983. + */
  2984. --- a/php_dio_win32.h
  2985. +++ b/php_dio_win32.h
  2986. @@ -1,62 +1,62 @@
  2987. -/*
  2988. - +----------------------------------------------------------------------+
  2989. - | PHP Version 5 |
  2990. - +----------------------------------------------------------------------+
  2991. - | Copyright (c) 2009 Melanie Rhianna Lewis |
  2992. - +----------------------------------------------------------------------+
  2993. - | This source file is subject to version 3.0 of the PHP license, |
  2994. - | that is bundled with this package in the file LICENSE, and is |
  2995. - | available through the world-wide-web at the following url: |
  2996. - | http://www.php.net/license/3_0.txt. |
  2997. - | If you did not receive a copy of the PHP license and are unable to |
  2998. - | obtain it through the world-wide-web, please send a note to |
  2999. - | license@php.net so we can mail you a copy immediately. |
  3000. - +----------------------------------------------------------------------+
  3001. - | Author: Melanie Rhianna Lewis <cyberspice@php.net> |
  3002. - +----------------------------------------------------------------------+
  3003. - */
  3004. -
  3005. -#ifndef PHP_DIO_WIN32_H_
  3006. -#define PHP_DIO_WIN32_H_
  3007. -
  3008. -#include <windows.h>
  3009. -
  3010. -/* Windows platform can do non blocking. */
  3011. -#define DIO_NONBLOCK
  3012. -
  3013. -#include "php_dio_common_data.h"
  3014. -
  3015. -#define DIO_WIN32_CANON_BUF_SIZE 8192
  3016. -
  3017. -/* This is the buffer information when reading in canonical mode. Data is
  3018. - read right up to either buffer being full or a newline being read. Excess
  3019. - data will be retained in the buffer until the next read. */
  3020. -typedef struct _php_dio_win32_canon_data {
  3021. - size_t size;
  3022. - size_t read_pos;
  3023. - size_t write_pos;
  3024. - char buf[DIO_WIN32_CANON_BUF_SIZE];
  3025. -
  3026. -} php_dio_win32_canon_data;
  3027. -
  3028. -typedef struct _php_dio_win32_stream_data {
  3029. - php_dio_stream_data common;
  3030. - HANDLE handle;
  3031. - DWORD desired_access;
  3032. - DWORD creation_disposition;
  3033. - DCB olddcb;
  3034. - COMMTIMEOUTS oldcto;
  3035. - php_dio_win32_canon_data *canon_data;
  3036. -
  3037. -} php_dio_win32_stream_data ;
  3038. -
  3039. -#endif /* PHP_DIO_WIN32_H_ */
  3040. -
  3041. -/*
  3042. - * Local variables:
  3043. - * c-basic-offset: 4
  3044. - * tab-width: 4
  3045. - * End:
  3046. - * vim600: fdm=marker
  3047. - * vim: sw=4 ts=4 noet
  3048. - */
  3049. +/*
  3050. + +----------------------------------------------------------------------+
  3051. + | PHP Version 5 |
  3052. + +----------------------------------------------------------------------+
  3053. + | Copyright (c) 2009 Melanie Rhianna Lewis |
  3054. + +----------------------------------------------------------------------+
  3055. + | This source file is subject to version 3.0 of the PHP license, |
  3056. + | that is bundled with this package in the file LICENSE, and is |
  3057. + | available through the world-wide-web at the following url: |
  3058. + | http://www.php.net/license/3_0.txt. |
  3059. + | If you did not receive a copy of the PHP license and are unable to |
  3060. + | obtain it through the world-wide-web, please send a note to |
  3061. + | license@php.net so we can mail you a copy immediately. |
  3062. + +----------------------------------------------------------------------+
  3063. + | Author: Melanie Rhianna Lewis <cyberspice@php.net> |
  3064. + +----------------------------------------------------------------------+
  3065. + */
  3066. +
  3067. +#ifndef PHP_DIO_WIN32_H_
  3068. +#define PHP_DIO_WIN32_H_
  3069. +
  3070. +#include <windows.h>
  3071. +
  3072. +/* Windows platform can do non blocking. */
  3073. +#define DIO_NONBLOCK
  3074. +
  3075. +#include "php_dio_common_data.h"
  3076. +
  3077. +#define DIO_WIN32_CANON_BUF_SIZE 8192
  3078. +
  3079. +/* This is the buffer information when reading in canonical mode. Data is
  3080. + read right up to either buffer being full or a newline being read. Excess
  3081. + data will be retained in the buffer until the next read. */
  3082. +typedef struct _php_dio_win32_canon_data {
  3083. + size_t size;
  3084. + size_t read_pos;
  3085. + size_t write_pos;
  3086. + char buf[DIO_WIN32_CANON_BUF_SIZE];
  3087. +
  3088. +} php_dio_win32_canon_data;
  3089. +
  3090. +typedef struct _php_dio_win32_stream_data {
  3091. + php_dio_stream_data common;
  3092. + HANDLE handle;
  3093. + DWORD desired_access;
  3094. + DWORD creation_disposition;
  3095. + DCB olddcb;
  3096. + COMMTIMEOUTS oldcto;
  3097. + php_dio_win32_canon_data *canon_data;
  3098. +
  3099. +} php_dio_win32_stream_data ;
  3100. +
  3101. +#endif /* PHP_DIO_WIN32_H_ */
  3102. +
  3103. +/*
  3104. + * Local variables:
  3105. + * c-basic-offset: 4
  3106. + * tab-width: 4
  3107. + * End:
  3108. + * vim600: fdm=marker
  3109. + * vim: sw=4 ts=4 noet
  3110. + */