1 /////////////////////////////////////////////////////////////////////////
2 // $Id: serial_raw.cc,v 1.22 2008/01/26 22:24:02 sshwarts Exp $
3 /////////////////////////////////////////////////////////////////////////
5 // Copyright (C) 2004 MandrakeSoft S.A.
9 // 75002 Paris - France
10 // http://www.linux-mandrake.com/
11 // http://www.mandrakesoft.com/
13 // This library is free software; you can redistribute it and/or
14 // modify it under the terms of the GNU Lesser General Public
15 // License as published by the Free Software Foundation; either
16 // version 2 of the License, or (at your option) any later version.
18 // This library is distributed in the hope that it will be useful,
19 // but WITHOUT ANY WARRANTY; without even the implied warranty of
20 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 // Lesser General Public License for more details.
23 // You should have received a copy of the GNU Lesser General Public
24 // License along with this library; if not, write to the Free Software
25 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 // Define BX_PLUGGABLE in files that can be compiled into plugins. For
29 // platforms that require a special tag on exported symbols, BX_PLUGGABLE
30 // is used to know when we are exporting symbols and when we are importing.
33 #define NO_DEVICE_INCLUDES
38 #include "serial_raw.h"
42 #ifdef WIN32_RECEIVE_RAW
43 DWORD WINAPI
RawSerialThread(VOID
*this_ptr
);
46 serial_raw::serial_raw(const char *devname
)
49 char portstr
[MAX_PATH
];
50 #ifdef WIN32_RECEIVE_RAW
58 memset(&dcb
, 0, sizeof(DCB
));
59 dcb
.DCBlength
= sizeof(DCB
);
61 dcb
.fDtrControl
= DTR_CONTROL_ENABLE
;
62 dcb
.fRtsControl
= RTS_CONTROL_ENABLE
;
63 dcb
.Parity
= NOPARITY
;
65 dcb
.StopBits
= ONESTOPBIT
;
66 dcb
.BaudRate
= CBR_115200
;
68 if (lstrlen(devname
) > 0) {
69 wsprintf(portstr
, "\\\\.\\%s", devname
);
70 hCOM
= CreateFile(portstr
, GENERIC_READ
|GENERIC_WRITE
, 0, NULL
,
71 OPEN_EXISTING
, FILE_FLAG_OVERLAPPED
, NULL
);
72 if (hCOM
!= INVALID_HANDLE_VALUE
) {
74 GetCommModemStatus(hCOM
, &MSR_value
);
75 SetupComm(hCOM
, 8192, 2048);
76 PurgeComm(hCOM
, PURGE_TXABORT
| PURGE_RXABORT
|
77 PURGE_TXCLEAR
| PURGE_RXCLEAR
);
78 #ifdef WIN32_RECEIVE_RAW
79 SetCommMask(hCOM
, EV_BREAK
| EV_CTS
| EV_DSR
| EV_ERR
| EV_RING
| EV_RLSD
| EV_RXCHAR
);
80 memset(&rx_ovl
, 0, sizeof(OVERLAPPED
));
81 rx_ovl
.hEvent
= CreateEvent(NULL
,TRUE
,FALSE
,"receive");
82 hRawSerialThread
= CreateThread(NULL
, 0, RawSerialThread
, this, 0, &threadID
);
86 BX_ERROR(("Raw device '%s' not present", devname
));
94 set_modem_control(0x00);
99 serial_raw::~serial_raw(void)
103 #ifdef WIN32_RECEIVE_RAW
105 SetCommMask(hCOM
, 0);
106 while (thread_active
) Sleep(10);
107 CloseHandle(thread_ovl
.hEvent
);
108 CloseHandle(rx_ovl
.hEvent
);
109 CloseHandle(hRawSerialThread
);
116 void serial_raw::set_baudrate(int rate
)
118 BX_DEBUG (("set_baudrate %d", rate
));
121 case 110: dcb
.BaudRate
= CBR_110
; break;
122 case 300: dcb
.BaudRate
= CBR_300
; break;
123 case 600: dcb
.BaudRate
= CBR_600
; break;
124 case 1200: dcb
.BaudRate
= CBR_1200
; break;
125 case 2400: dcb
.BaudRate
= CBR_2400
; break;
126 case 4800: dcb
.BaudRate
= CBR_4800
; break;
127 case 9600: dcb
.BaudRate
= CBR_9600
; break;
128 case 19200: dcb
.BaudRate
= CBR_19200
; break;
129 case 38400: dcb
.BaudRate
= CBR_38400
; break;
130 case 57600: dcb
.BaudRate
= CBR_57600
; break;
131 case 115200: dcb
.BaudRate
= CBR_115200
; break;
132 default: BX_ERROR(("set_baudrate(): unsupported value %d", rate
));
138 void serial_raw::set_data_bits(int val
)
140 BX_DEBUG (("set data bits (%d)", val
));
147 void serial_raw::set_stop_bits(int val
)
149 BX_DEBUG (("set stop bits (%d)", val
));
152 dcb
.StopBits
= ONESTOPBIT
;
153 } if (dcb
.ByteSize
== 5) {
154 dcb
.StopBits
= ONE5STOPBITS
;
156 dcb
.StopBits
= TWOSTOPBITS
;
162 void serial_raw::set_parity_mode(int mode
)
164 BX_DEBUG (("set parity mode %d", mode
));
169 dcb
.Parity
= NOPARITY
;
173 dcb
.Parity
= ODDPARITY
;
177 dcb
.Parity
= EVENPARITY
;
181 dcb
.Parity
= MARKPARITY
;
185 dcb
.Parity
= SPACEPARITY
;
192 void serial_raw::set_break(int mode
)
194 BX_DEBUG (("set break %s", mode
?"on":"off"));
199 ClearCommBreak(hCOM
);
204 void serial_raw::set_modem_control(int ctrl
)
206 BX_DEBUG (("set modem control 0x%02x", ctrl
));
208 EscapeCommFunction(hCOM
, (ctrl
& 0x01)?SETDTR
:CLRDTR
);
209 EscapeCommFunction(hCOM
, (ctrl
& 0x02)?SETRTS
:CLRRTS
);
213 int serial_raw::get_modem_status()
220 BX_DEBUG (("get modem status returns 0x%02x", status
));
224 void serial_raw::setup_port()
230 ClearCommError(hCOM
, &DErr
, NULL
);
231 PurgeComm(hCOM
, PURGE_TXABORT
| PURGE_RXABORT
|
232 PURGE_TXCLEAR
| PURGE_RXCLEAR
);
233 memset(&ctmo
, 0, sizeof(ctmo
));
234 SetCommTimeouts(hCOM
, &ctmo
);
235 SetCommState(hCOM
, &dcb
);
237 #ifdef WIN32_RECEIVE_RAW
238 thread_rxdata_count
= 0;
243 void serial_raw::transmit(Bit8u byte
)
250 BX_DEBUG (("transmit %d", byte
));
256 ClearCommError(hCOM
, &DErr
, NULL
);
258 memset(&tx_ovl
, 0, sizeof(OVERLAPPED
));
259 tx_ovl
.hEvent
= CreateEvent(NULL
,TRUE
,TRUE
,"transmit");
260 if (!WriteFile(hCOM
, &byte
, 1, &Len2
, &tx_ovl
)) {
261 if (GetLastError() == ERROR_IO_PENDING
) {
262 if (WaitForSingleObject(tx_ovl
.hEvent
, 100) == WAIT_OBJECT_0
) {
263 GetOverlappedResult(hCOM
, &tx_ovl
, &Len2
, FALSE
);
267 if (Len2
!= 1) BX_ERROR(("transmit failed: len = %d", Len2
));
268 ClearCommError(hCOM
, &DErr
, NULL
);
269 CloseHandle(tx_ovl
.hEvent
);
274 bx_bool
serial_raw::ready_transmit()
276 BX_DEBUG (("ready_transmit returning %d", present
));
280 bx_bool
serial_raw::ready_receive()
282 #ifdef WIN32_RECEIVE_RAW
283 if ((rxdata_count
== 0) && (thread_rxdata_count
> 0)) {
284 SetEvent(thread_ovl
.hEvent
);
285 SetEvent(rx_ovl
.hEvent
);
288 BX_DEBUG (("ready_receive returning %d", (rxdata_count
> 0)));
289 return (rxdata_count
> 0);
292 int serial_raw::receive()
303 data
= rxdata_buffer
[0];
304 if (rxdata_count
> 0) {
305 memcpy(&rxdata_buffer
[0], &rxdata_buffer
[1], sizeof(Bit16s
)*(RX_BUFSIZE
-1));
310 case RAW_EVENT_CTS_ON
:
313 case RAW_EVENT_CTS_OFF
:
316 case RAW_EVENT_DSR_ON
:
319 case RAW_EVENT_DSR_OFF
:
322 case RAW_EVENT_RING_ON
:
325 case RAW_EVENT_RING_OFF
:
328 case RAW_EVENT_RLSD_ON
:
331 case RAW_EVENT_RLSD_OFF
:
338 BX_DEBUG (("receive returning 'A'"));
342 BX_DEBUG (("receive returning 'A'"));
347 #ifdef WIN32_RECEIVE_RAW
349 DWORD WINAPI
RawSerialThread(VOID
*this_ptr
)
351 serial_raw
*class_ptr
= (serial_raw
*) this_ptr
;
352 class_ptr
->serial_thread();
356 void serial_raw::serial_thread()
359 DWORD EvtMask
, MSR
, Temp
;
362 SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_IDLE
);
363 thread_active
= TRUE
;
365 memset(&thread_ovl
, 0, sizeof(OVERLAPPED
));
366 thread_ovl
.hEvent
= CreateEvent(NULL
,TRUE
,TRUE
,"thread");
367 thread_rxdata_count
= 0;
368 while (!thread_quit
) {
369 if ((rxdata_count
== 0) && (thread_rxdata_count
> 0)) {
370 if (thread_rxdata_count
> RX_BUFSIZE
) {
371 memcpy(&rxdata_buffer
[0], &thread_rxdata_buffer
[0], sizeof(Bit16s
)*RX_BUFSIZE
);
372 memcpy(&thread_rxdata_buffer
[0], &thread_rxdata_buffer
[RX_BUFSIZE
], sizeof(Bit16s
)*(thread_rxdata_count
-RX_BUFSIZE
));
373 rxdata_count
= RX_BUFSIZE
;
374 thread_rxdata_count
-= RX_BUFSIZE
;
376 memcpy(&rxdata_buffer
[0], &thread_rxdata_buffer
[0], sizeof(Bit16s
)*thread_rxdata_count
);
377 rxdata_count
= thread_rxdata_count
;
378 thread_rxdata_count
= 0;
381 ClearCommError(hCOM
, &DErr
, NULL
);
383 if (!WaitCommEvent(hCOM
, &EvtMask
, &thread_ovl
)) {
384 if (GetLastError() == ERROR_IO_PENDING
) {
385 if (WaitForSingleObject(thread_ovl
.hEvent
, INFINITE
) == WAIT_OBJECT_0
) {
386 GetOverlappedResult(hCOM
, &thread_ovl
, &Temp
, FALSE
);
390 if (EvtMask
& EV_RXCHAR
) {
391 if (thread_rxdata_count
< THREAD_RX_BUFSIZE
) {
393 ClearCommError(hCOM
, &DErr
, NULL
);
394 if (!ReadFile(hCOM
, s1
, 1, &Len2
, &rx_ovl
)) {
395 if (GetLastError() == ERROR_IO_PENDING
) {
396 if (WaitForSingleObject(rx_ovl
.hEvent
, INFINITE
) != WAIT_OBJECT_0
) {
399 GetOverlappedResult(hCOM
, &rx_ovl
, &Len2
, FALSE
);
408 if ((rxdata_count
== 0) && (thread_rxdata_count
> 0)) {
409 if (thread_rxdata_count
> RX_BUFSIZE
) {
410 memcpy(&rxdata_buffer
[0], &thread_rxdata_buffer
[0], sizeof(Bit16s
)*RX_BUFSIZE
);
411 memcpy(&thread_rxdata_buffer
[0], &thread_rxdata_buffer
[RX_BUFSIZE
], sizeof(Bit16s
)*(thread_rxdata_count
-RX_BUFSIZE
));
412 rxdata_count
= RX_BUFSIZE
;
413 thread_rxdata_count
-= RX_BUFSIZE
;
415 memcpy(&rxdata_buffer
[0], &thread_rxdata_buffer
[0], sizeof(Bit16s
)*thread_rxdata_count
);
416 rxdata_count
= thread_rxdata_count
;
417 thread_rxdata_count
= 0;
420 } while ((Len2
!= 0) && (thread_rxdata_count
< THREAD_RX_BUFSIZE
));
421 ClearCommError(hCOM
, &DErr
, NULL
);
424 if (EvtMask
& EV_BREAK
) {
425 enq_event(RAW_EVENT_BREAK
);
427 if (EvtMask
& EV_ERR
) {
428 ClearCommError(hCOM
, &DErr
, NULL
);
429 if (DErr
& CE_FRAME
) {
430 enq_event(RAW_EVENT_FRAME
);
432 if (DErr
& CE_OVERRUN
) {
433 enq_event(RAW_EVENT_OVERRUN
);
435 if (DErr
& CE_RXPARITY
) {
436 enq_event(RAW_EVENT_PARITY
);
439 if (EvtMask
& (EV_CTS
| EV_DSR
| EV_RING
| EV_RLSD
)) {
440 GetCommModemStatus(hCOM
, &MSR
);
442 if (EvtMask
& EV_CTS
) {
443 if (MSR
& MS_CTS_ON
) {
444 enq_event(RAW_EVENT_CTS_ON
);
446 enq_event(RAW_EVENT_CTS_OFF
);
449 if (EvtMask
& EV_DSR
) {
450 if (MSR
& MS_DSR_ON
) {
451 enq_event(RAW_EVENT_DSR_ON
);
453 enq_event(RAW_EVENT_DSR_OFF
);
456 if (EvtMask
& EV_RING
) {
457 if (MSR
& MS_RING_ON
) {
458 enq_event(RAW_EVENT_RING_ON
);
460 enq_event(RAW_EVENT_RING_OFF
);
463 if (EvtMask
& EV_RLSD
) {
464 if (MSR
& MS_RLSD_ON
) {
465 enq_event(RAW_EVENT_RLSD_ON
);
467 enq_event(RAW_EVENT_RLSD_OFF
);
471 CloseHandle(thread_ovl
.hEvent
);
472 thread_active
= FALSE
;
475 void serial_raw::enq_event(Bit16s event
)
477 if (thread_rxdata_count
< THREAD_RX_BUFSIZE
) {
478 thread_rxdata_buffer
[thread_rxdata_count
++] = event
;
480 fprintf(stderr
, "receive buffer overflow\n");