1 /*
2 +----------------------------------------------------------------------+
3 | PHP Version 7 |
4 +----------------------------------------------------------------------+
5 | Copyright (c) 2009 Melanie Rhianna Lewis |
6 +----------------------------------------------------------------------+
7 | This source file is subject to version 3.0 of the PHP license, |
8 | that is bundled with this package in the file LICENSE, and is |
9 | available through the world-wide-web at the following url: |
10 | http://www.php.net/license/3_01.txt. |
11 | If you did not receive a copy of the PHP license and are unable to |
12 | obtain it through the world-wide-web, please send a note to |
13 | license@php.net so we can mail you a copy immediately. |
14 +----------------------------------------------------------------------+
15 | Author: Melanie Rhianna Lewis <cyberspice@php.net> |
16 +----------------------------------------------------------------------+
17 */
18
19 #ifdef HAVE_CONFIG_H
20 #include "config.h"
21 #endif
22
23 #include "php.h"
24 #include "php_dio_common.h"
25
26 #ifndef ZEND_WIN32
27 #error ZEND_WIN32 not defined!
28 #endif
29
30 /* {{{ dio_last_error_php_error
31 * Generates a PHP error message based upon the last Windows error.
32 */
dio_last_error_php_error(int level,char * message)33 static void dio_last_error_php_error(int level, char * message) {
34 LPVOID msgbuf;
35 DWORD msgbuflen;
36 char * errmsg;
37 DWORD err;
38
39 #ifdef UNICODE
40 DWORD errmsglen;
41 #endif
42
43 err = GetLastError();
44 msgbuflen = FormatMessage(
45 FORMAT_MESSAGE_ALLOCATE_BUFFER|
46 FORMAT_MESSAGE_FROM_SYSTEM|
47 FORMAT_MESSAGE_IGNORE_INSERTS,
48 NULL,
49 err,
50 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
51 (LPTSTR)&msgbuf,
52 0,
53 NULL);
54
55 #ifdef UNICODE
56
57 /* Get the length of the converted message */
58 errmsglen = WideCharToMultibyte(
59 CP_ACP,
60 0
61 (LPCWSTR)msgbuf,
62 -1,
63 (LPSTR)errmsg,
64 0,
65 NULL,
66 NULL);
67
68 /* Allocate a buffer */
69 errmsg = emalloc(errmsglen);
70 if (!errmsg) {
71 php_error_docref(NULL, E_ERROR, "Out of memory in dio_last_error_php_error()!");
72 LocalFree(msgbuf);
73 return;
74 }
75
76 /* Convert the message */
77 errmsglen = WideCharToMultibyte(
78 CP_ACP,
79 0
80 (LPCWSTR)msgbuf,
81 -1,
82 (LPSTR)errmsg,
83 errmsglen,
84 NULL,
85 NULL);
86
87 #else
88 errmsg = (char *)msgbuf;
89 #endif
90
91 php_error_docref(NULL, E_WARNING, "%s[ERROR %d] %s", message, err, errmsg);
92
93 LocalFree(msgbuf);
94 #ifdef UNICODE
95 efree(errmsg);
96 #endif
97 }
98
99 /* {{{ dio_data_rate_to_define
100 * Converts a numeric data rate to a termios define
101 */
dio_data_rate_to_define(long rate,DWORD * def)102 static int dio_data_rate_to_define(long rate, DWORD *def) {
103 switch (rate) {
104 case 75:
105 case 110:
106 case 134:
107 case 150:
108 case 300:
109 case 600:
110 case 1200:
111 case 1800:
112 case 2400:
113 case 4800:
114 case 7200:
115 case 9600:
116 case 14400:
117 case 19200:
118 case 38400:
119 case 57600:
120 case 115200:
121 case 56000:
122 case 128000:
123 case 256000:
124 break;
125 default:
126 return 0;
127 }
128
129 *def = (DWORD)rate;
130 return 1;
131 }
132 /* }}} */
133
134
135 /* {{{ dio_data_bits_to_define
136 * Converts a number of data bits to a termios define
137 */
dio_data_bits_to_define(int data_bits,DWORD * def)138 static int dio_data_bits_to_define(int data_bits, DWORD *def) {
139 switch (data_bits) {
140 case 8:
141 case 7:
142 case 6:
143 case 5:
144 case 4:
145 break;
146 default:
147 return 0;
148 }
149
150 *def = (DWORD)data_bits;
151 return 1;
152 }
153 /* }}} */
154
155 /* {{{ dio_stop_bits_to_define
156 * Converts a number of stop bits to a termios define
157 */
dio_stop_bits_to_define(int stop_bits,DWORD * def)158 static int dio_stop_bits_to_define(int stop_bits, DWORD *def) {
159 DWORD val;
160
161 switch (stop_bits) {
162 case 1:
163 val = ONESTOPBIT;
164 break;
165 case 2:
166 val = TWOSTOPBITS;
167 break;
168 case 3:
169 val = ONE5STOPBITS;
170 break;
171 default:
172 return 0;
173 }
174
175 *def = val;
176 return 1;
177 }
178 /* }}} */
179
180 /* {{{ dio_parity_to_define
181 * Converts a parity type to a termios define
182 */
dio_parity_to_define(int parity,DWORD * def)183 static int dio_parity_to_define(int parity, DWORD *def) {
184 DWORD val;
185
186 switch (parity) {
187 case 0:
188 val = NOPARITY;
189 break;
190 case 1:
191 val = ODDPARITY;
192 break;
193 case 2:
194 val = EVENPARITY;
195 break;
196 default:
197 return 0;
198 }
199
200 *def = val;
201 return 1;
202 }
203 /* }}} */
204
205 /* {{{ dio_create_stream_data
206 * Creates an initialised stream data structure. Free with efree().
207 */
dio_create_stream_data(void)208 php_dio_stream_data * dio_create_stream_data(void) {
209 php_dio_win32_stream_data * data = emalloc(sizeof(php_dio_win32_stream_data));
210 memset(data, 0, sizeof(php_dio_win32_stream_data));
211 dio_init_stream_data(&(data->common));
212 data->handle = INVALID_HANDLE_VALUE;
213 data->desired_access = 0;
214 data->creation_disposition = 0;
215 data->olddcb.DCBlength = sizeof(DCB);
216
217 return (php_dio_stream_data *)data;
218 }
219 /* }}} */
220
221 /* {{{ dio_common_write
222 * Writes count chars from the buffer to the stream described by the stream data.
223 */
224 #if PHP_VERSION_ID < 70400
dio_common_write(php_dio_stream_data * data,const char * buf,size_t count)225 size_t dio_common_write(php_dio_stream_data *data, const char *buf, size_t count) {
226 #else
227 ssize_t dio_common_write(php_dio_stream_data *data, const char *buf, size_t count) {
228 #endif
229 php_dio_win32_stream_data *wdata = (php_dio_win32_stream_data*)data;
230 DWORD total = 0;
231
232 if (WriteFile(wdata->handle, buf, (DWORD)count, &total, NULL)) {
233 return (size_t)total;
234 }
235
236 #if PHP_VERSION_ID < 70400
237 return 0;
238 #else
239 return -1;
240 #endif
241 }
242 /* }}} */
243
244 /* {{{ dio_buffer_read
245 * Reads any available chars from the canonical buffer.
246 */
247 static size_t dio_buffer_read(php_dio_win32_stream_data *wdata, const char *buf, size_t count) {
248 php_dio_win32_canon_data *canon_data = wdata->canon_data;
249 size_t total = 0;
250
251 /* Read always follows write. I.e. if read ptr > write ptr buffer has
252 wrapped and so we need to copy two blocks of data. */
253 if (canon_data->read_pos > canon_data->write_pos) {
254
255 /* Check we actually need to copy both blocks */
256 if ((canon_data->size - canon_data->read_pos) > count) {
257
258 /* No we don't. Just copy as much as we were asked for. */
259 memcpy((char*)buf,
260 &(canon_data->buf[canon_data->read_pos]),
261 count);
262 /* Update the read pointer. */
263 canon_data->read_pos += count;
264
265 /* Return the amount read. */
266 return count;
267 } else {
268
269 /* We need to copy both blocks so copy data up to the end of
270 the buffer. */
271 total = canon_data->size - canon_data->read_pos;
272 memcpy((char*)buf,
273 &(canon_data->buf[canon_data->read_pos]),
274 total);
275 canon_data->read_pos = 0;
276 count -= total;
277
278 /* Now copy the data from the start of the buffer either up
279 count or the number of bytes in the buffer. */
280
281 if (canon_data->write_pos > count) {
282 memcpy((char*)buf, canon_data->buf, count);
283 canon_data->read_pos = count;
284 total += count;
285
286 return total;
287 } else {
288 memcpy((char*)buf, canon_data->buf, canon_data->write_pos);
289 canon_data->read_pos = canon_data->write_pos;
290 total += canon_data->write_pos;
291
292 return total;
293 }
294 }
295
296 /* Else if write follows read. This is a simpler case. We just copy
297 either all the data buffered or count, which ever is smaller. */
298 } else if (canon_data->write_pos > canon_data->read_pos) {
299 if ((canon_data->write_pos - canon_data->read_pos) > count) {
300 memcpy((char*)buf,
301 &(canon_data->buf[canon_data->read_pos]),
302 count);
303 canon_data->read_pos += count;
304
305 return count;
306 } else {
307 total = canon_data->write_pos - canon_data->read_pos;
308 memcpy((char*)buf,
309 &(canon_data->buf[canon_data->read_pos]),
310 total);
311 canon_data->read_pos += total;
312
313 return total;
314 }
315 }
316
317 /* Else we need to read more data from the data port. */
318 return 0;
319 }
320
321 /* {{{ dio_com_read
322 * Read chars from the data port.
323 */
324 #if PHP_VERSION_ID < 70400
325 static size_t dio_com_read(php_dio_stream_data *data, const char *buf, size_t count) {
326 #else
327 static ssize_t dio_com_read(php_dio_stream_data *data, const char *buf, size_t count) {
328 #endif
329 php_dio_win32_stream_data *wdata = (php_dio_win32_stream_data*)data;
330 DWORD err, total = 0;
331
332 if (ReadFile(wdata->handle, (void*)buf, (DWORD)count, &total, NULL)) {
333
334 if (total) {
335 return (size_t)total;
336 }
337
338 data->end_of_file = 1;
339 }
340
341 if (!data->end_of_file) {
342 err = GetLastError();
343
344 if (ERROR_HANDLE_EOF == err) {
345 data->end_of_file = 1;
346 }
347 }
348
349 #if PHP_VERSION_ID < 70400
350 return 0;
351 #else
352 return (data->end_of_file ? 0 : -1);
353 #endif
354 }
355
356 /* {{{ dio_canonical_read
357 * Reads chars from the input stream until the internal buffer is full or a new
358 * line is reached.
359 */
360 #if PHP_VERSION_ID < 70400
361 static size_t dio_canonical_read(php_dio_win32_stream_data *wdata, const char *buf, size_t count) {
362 #else
363 static ssize_t dio_canonical_read(php_dio_win32_stream_data *wdata, const char *buf, size_t count) {
364 #endif
365 php_dio_win32_canon_data *canon_data = wdata->canon_data;
366 size_t total = 0;
367 char ch;
368
369 /* See if there's any buffered data and copy it. */
370 total = dio_buffer_read(wdata, buf, count);
371 if (total) {
372 return total;
373 }
374
375 /* Need to read more data from the data port. Buffer should be empty(er)
376 by now. */
377 do {
378 /* Is the buffer full? */
379 if (((canon_data->write_pos + 1) % canon_data->size) ==
380 canon_data->read_pos) {
381 break;
382 }
383
384 /* Read a byte from the input checking for EOF. */
385 if (dio_com_read((php_dio_stream_data*)wdata, &ch, 1) < 1) {
386 break;
387 }
388
389 /* Translate CR to newlines (same as ICRNL in POSIX) */
390 ch = (ch != '\r') ? ch : '\n';
391
392 /* We read a character! So buffer it. */
393 canon_data->buf[canon_data->write_pos++] = ch;
394 if (canon_data->write_pos >= canon_data->size) {
395 canon_data->write_pos = 0;
396 }
397
398 /* End of line/input (^D)? */
399 } while ((ch != '\n') && (ch != 0x04));
400
401 return dio_buffer_read(wdata, buf, count);
402 }
403 /* }}} */
404
405 /* {{{ dio_common_read
406 * Reads count chars to the buffer to the stream described by the stream data.
407 */
408 #if PHP_VERSION_ID < 70400
409 size_t dio_common_read(php_dio_stream_data *data, const char *buf, size_t count) {
410 #else
411 ssize_t dio_common_read(php_dio_stream_data *data, const char *buf, size_t count) {
412 #endif
413
414 /* You ask for no bytes you'll get none :-) */
415 if (!count) {
416 return 0;
417 }
418
419 if (data->canonical) {
420 return dio_canonical_read((php_dio_win32_stream_data*)data, buf, count);
421 } else {
422 return dio_com_read(data, buf, count);
423 }
424 }
425 /* }}} */
426
427 /* {{{ php_dio_stream_data
428 * Closes the php_stream.
429 */
430 int dio_common_close(php_dio_stream_data *data) {
431 php_dio_win32_stream_data *wdata = (php_dio_win32_stream_data*)data;
432
433 if (data->canonical) {
434 efree(wdata->canon_data);
435 }
436
437 if (!CloseHandle(wdata->handle)) {
438 return 0;
439 }
440
441 return 1;
442 }
443 /* }}} */
444
445 /* {{{ dio_common_set_option
446 * Sets/gets stream options
447 */
448 int dio_common_set_option(php_dio_stream_data *data, int option, int value, void *ptrparam) {
449 COMMTIMEOUTS cto = { 0, 0, 0, 0, 0 };
450 int old_is_blocking = 0;
451
452 /* Can't do timeouts or non blocking with raw windows streams :-( */
453 if (DIO_STREAM_TYPE_SERIAL == data->stream_type) {
454 switch (option) {
455 case PHP_STREAM_OPTION_BLOCKING:
456 old_is_blocking = data->is_blocking;
457 data->is_blocking = value ? 1 : 0;
458
459 /* Only change values if we need to change them. */
460 if (data->is_blocking != old_is_blocking) {
461 /* If we're not blocking but don't have a timeout
462 set to return immediately */
463 if (!data->is_blocking && !data->has_timeout) {
464 cto.ReadIntervalTimeout = MAXDWORD;
465 }
466
467 /* If we have a timeout ignore the blocking and set
468 the total time in which to read the data */
469 if (data->has_timeout) {
470 cto.ReadIntervalTimeout = MAXDWORD;
471 cto.ReadTotalTimeoutMultiplier = MAXDWORD;
472 cto.ReadTotalTimeoutConstant = (data->timeout_usec / 1000) +
473 (data->timeout_sec * 1000);
474 }
475
476 if (!SetCommTimeouts(((php_dio_win32_stream_data*)data)->handle, &cto)) {
477 return PHP_STREAM_OPTION_RETURN_ERR;
478 }
479 }
480 return old_is_blocking ? PHP_STREAM_OPTION_RETURN_OK : PHP_STREAM_OPTION_RETURN_ERR;
481
482 case PHP_STREAM_OPTION_READ_TIMEOUT:
483 if (ptrparam) {
484 /* struct timeval is supported with PHP_WIN32 defined. */
485 struct timeval *tv = (struct timeval*)ptrparam;
486
487 /* A timeout of zero seconds and zero microseconds disables
488 any existing timeout. */
489 if (tv->tv_sec || tv->tv_usec) {
490 data->timeout_sec = tv->tv_sec;
491 data->timeout_usec = tv->tv_usec;
492 data->has_timeout = -1;
493
494 cto.ReadIntervalTimeout = MAXDWORD;
495 cto.ReadTotalTimeoutMultiplier = MAXDWORD;
496 cto.ReadTotalTimeoutConstant = (data->timeout_usec / 1000) +
497 (data->timeout_sec * 1000);
498 } else {
499 data->timeout_sec = 0;
500 data->timeout_usec = 0;
501 data->has_timeout = 0;
502 data->timed_out = 0;
503
504 /* If we're not blocking but don't have a timeout
505 set to return immediately */
506 if (!data->is_blocking) {
507 cto.ReadIntervalTimeout = MAXDWORD;
508 }
509 }
510
511 if (!SetCommTimeouts(((php_dio_win32_stream_data*)data)->handle, &cto)) {
512 return PHP_STREAM_OPTION_RETURN_ERR;
513 } else {
514 return PHP_STREAM_OPTION_RETURN_OK;
515 }
516 } else {
517 return PHP_STREAM_OPTION_RETURN_ERR;
518 }
519
520 default:
521 break;
522 }
523 }
524
525 return 1;
526 }
527 /* }}} */
528
529 /* {{{ dio_raw_open_stream
530 * Opens the underlying stream.
531 */
532 int dio_raw_open_stream(const char *filename, const char *mode, php_dio_stream_data *data) {
533 php_dio_win32_stream_data *wdata = (php_dio_win32_stream_data*)data;
534 DWORD err;
535
536 switch(*mode) {
537 case 'r':
538 wdata->creation_disposition = OPEN_EXISTING;
539 break;
540 case 'w':
541 wdata->creation_disposition = TRUNCATE_EXISTING;
542 break;
543 case 'a':
544 wdata->creation_disposition = OPEN_ALWAYS;
545 break;
546 case 'x':
547 wdata->creation_disposition = CREATE_NEW;
548 break;
549 }
550 mode ++;
551
552 if (*mode && (*mode != '+')) {
553 mode++;
554 }
555
556 if (*mode && (*mode == '+')) {
557 wdata->desired_access = GENERIC_READ | GENERIC_WRITE;
558 } else if (OPEN_EXISTING == wdata->creation_disposition) {
559 wdata->desired_access = GENERIC_READ;
560 } else {
561 wdata->desired_access = GENERIC_WRITE;
562 }
563
564 wdata->handle = CreateFile(filename, wdata->desired_access, 0,
565 NULL, wdata->creation_disposition, FILE_ATTRIBUTE_NORMAL, NULL);
566 if (INVALID_HANDLE_VALUE == wdata->handle) {
567 err = GetLastError();
568 switch (err) {
569 case ERROR_FILE_EXISTS:
570 php_error_docref(NULL, E_WARNING, "File exists!");
571 return 0;
572
573 case ERROR_FILE_NOT_FOUND:
574 /* ERROR_FILE_NOT_FOUND with TRUNCATE_EXISTING means that
575 * the file doesn't exist so now try to create it. */
576 if (TRUNCATE_EXISTING == wdata->creation_disposition) {
577 php_error_docref(NULL, E_NOTICE, "File does not exist, creating new file!");
578
579 wdata->handle = CreateFile(filename, wdata->desired_access, 0,
580 NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
581 if (INVALID_HANDLE_VALUE == wdata->handle) {
582 dio_last_error_php_error(E_WARNING, "CreateFile() failed:");
583 return 0;
584 }
585 } else {
586 php_error_docref(NULL, E_WARNING, "File not found!");
587 return 0;
588 }
589 break;
590
591 default:
592 dio_last_error_php_error(E_WARNING, "CreateFile() failed:");
593 return 0;
594 }
595 }
596
597 /* If canonical allocate the canonical buffer. */
598 if (data->canonical) {
599 wdata->canon_data = emalloc(sizeof(php_dio_win32_canon_data));
600 memset(wdata->canon_data, 0, sizeof(php_dio_win32_canon_data));
601 wdata->canon_data->size = DIO_WIN32_CANON_BUF_SIZE;
602 }
603
604 return 1;
605 }
606 /* }}} */
607
608 /* {{{ dio_serial_init
609 * Initialises the serial port
610 */
611 static int dio_serial_init(php_dio_stream_data *data) {
612 php_dio_win32_stream_data *wdata = (php_dio_win32_stream_data*)data;
613 DWORD rate_def, data_bits_def, stop_bits_def, parity_def;
614 DCB dcb;
615
616 if (!dio_data_rate_to_define(data->data_rate, &rate_def)) {
617 php_error_docref(NULL, E_WARNING, "invalid data_rate value (%d)", data->data_rate);
618 return 0;
619 }
620
621 if (!dio_data_bits_to_define(data->data_bits, &data_bits_def)) {
622 php_error_docref(NULL, E_WARNING, "invalid data_bits value (%d)", data->data_bits);
623 return 0;
624 }
625
626 if (!dio_stop_bits_to_define(data->stop_bits, &stop_bits_def)) {
627 php_error_docref(NULL, E_WARNING, "invalid stop_bits value (%d)", data->stop_bits);
628 return 0;
629 }
630
631 if (!dio_parity_to_define(data->parity, &parity_def)) {
632 php_error_docref(NULL, E_WARNING, "invalid parity value (%d)", data->parity);
633 return 0;
634 }
635
636 if (!GetCommState(wdata->handle, &(wdata->olddcb))) {
637 dio_last_error_php_error(E_WARNING, "GetCommState() failed:");
638 return 0;
639 }
640
641 /* Init the DCB structure */
642 memset(&dcb, 0, sizeof(DCB));
643 dcb.DCBlength = sizeof(DCB);
644
645 /* Set the communication parameters */
646 dcb.fBinary = 1;
647 dcb.BaudRate = rate_def;
648 dcb.ByteSize = (BYTE)data_bits_def;
649 dcb.StopBits = (BYTE)stop_bits_def;
650 dcb.Parity = (BYTE)parity_def;
651
652 /* Set the control line parameters */
653 dcb.fDtrControl = DTR_CONTROL_DISABLE;
654 dcb.fDsrSensitivity = FALSE;
655 dcb.fOutxDsrFlow = FALSE;
656 dcb.fTXContinueOnXoff = FALSE;
657 dcb.fOutX = FALSE;
658 dcb.fInX = FALSE;
659 dcb.fErrorChar = FALSE;
660 dcb.fNull = FALSE;
661 dcb.fAbortOnError = FALSE;
662
663 /* Hardware flow control */
664 if (data->flow_control) {
665 dcb.fOutxCtsFlow = TRUE;
666 dcb.fRtsControl = RTS_CONTROL_HANDSHAKE;
667 } else {
668 dcb.fOutxCtsFlow = FALSE;
669 dcb.fRtsControl = RTS_CONTROL_DISABLE;
670 }
671
672 if (!SetCommState(wdata->handle, &dcb)) {
673 dio_last_error_php_error(E_WARNING, "SetCommState() failed:");
674 return 0;
675 }
676
677 return 1;
678 }
679 /* }}} */
680
681
682 /* {{{ dio_serial_uninit
683 * Restores the serial settings back to their original state.
684 */
685 int dio_serial_uninit(php_dio_stream_data *data) {
686 php_dio_win32_stream_data *wdata = (php_dio_win32_stream_data*)data;
687
688 if (!SetCommState(wdata->handle, &(wdata->olddcb))) {
689 return 0;
690 }
691
692 return 1;
693 }
694 /* }}} */
695
696 /* {{{ dio_serial_flush
697 * Purges the serial buffers of data.
698 */
699 int dio_serial_purge(php_dio_stream_data *data) {
700 php_dio_win32_stream_data *wdata = (php_dio_win32_stream_data*)data;
701 BOOL ret;
702
703 /* Purge the canonical buffer if required */
704 if (data->canonical && ((wdata->desired_access & GENERIC_READ) == GENERIC_READ)) {
705 wdata->canon_data->read_pos = 0;
706 wdata->canon_data->write_pos = 0;
707 }
708
709 /* Purge the com port */
710 if ((wdata->desired_access & (GENERIC_READ|GENERIC_WRITE)) == (GENERIC_READ|GENERIC_WRITE)) {
711 ret = PurgeComm(wdata->handle, PURGE_RXCLEAR|PURGE_TXCLEAR);
712 } else if ((wdata->desired_access & GENERIC_WRITE) == GENERIC_WRITE) {
713 ret = PurgeComm(wdata->handle, PURGE_TXCLEAR);
714 } else if ((wdata->desired_access & GENERIC_READ) == GENERIC_READ) {
715 ret = PurgeComm(wdata->handle, PURGE_RXCLEAR);
716 }
717
718 return ret;
719 }
720 /* }}} */
721
722 /* {{{ dio_serial_open_stream
723 * Opens the underlying stream.
724 */
725 int dio_serial_open_stream(const char *filename, const char *mode, php_dio_stream_data *data) {
726 php_dio_win32_stream_data *wdata = (php_dio_win32_stream_data*)data;
727 COMMTIMEOUTS cto = { 0, 0, 0, 0, 0 };
728
729 php_error_docref(NULL, E_NOTICE, "Opening \"%s\" as a serial port (mode=\"%s\").", filename, mode);
730
731 if (*mode != 'r') {
732 php_error_docref(NULL, E_WARNING, "You must open serial ports in read or read/write mode!");
733 return 0;
734 }
735
736 if (!dio_raw_open_stream(filename, mode, data)) {
737 return 0;
738 }
739
740 if (!GetCommTimeouts(wdata->handle, &(wdata->oldcto))) {
741 dio_last_error_php_error(E_WARNING, "GetCommTimeouts() failed (Not a comm port?):");
742 CloseHandle(wdata->handle);
743 return 0;
744 }
745
746 /* If we're not blocking but don't have a timeout
747 set to return immediately */
748 if (!data->is_blocking && !data->has_timeout) {
749 cto.ReadIntervalTimeout = MAXDWORD;
750 }
751
752 /* If we have a timeout ignore the blocking and set
753 the total time in which to read the data */
754 if (data->has_timeout) {
755 cto.ReadIntervalTimeout = MAXDWORD;
756 cto.ReadTotalTimeoutMultiplier = MAXDWORD;
757 cto.ReadTotalTimeoutConstant = (data->timeout_usec / 1000) +
758 (data->timeout_sec * 1000);
759 }
760
761 if (!SetCommTimeouts(wdata->handle, &cto)) {
762 dio_last_error_php_error(E_WARNING, "SetCommTimeouts() failed:");
763 CloseHandle(wdata->handle);
764 return 0;
765 }
766
767 if (!dio_serial_init(data)) {
768 CloseHandle(wdata->handle);
769 return 0;
770 }
771
772 return 1;
773 }
774 /* }}} */
775
776 /*
777 * Local variables:
778 * c-basic-offset: 4
779 * tab-width: 4
780 * End:
781 * vim600: fdm=marker
782 * vim: sw=4 ts=4 noet
783 */
784