Imported Upstream version 2.9.0
[debian/cc1111] / device / examples / serialcomm / windows / serial.c
1 /*-------------------------------------------------------------------------
2    Serial library functions for the Windows OS (95-XP)
3    Tested with different versions of MS Visual Studio (C ad C++)
4
5    Written by -  Bela Torok / www.torok.info & www.belatorok.com (February 2006)
6
7    This library is free software; you can redistribute it and/or
8    modify it under the terms of the GNU General Public
9    License as published by the Free Software Foundation; either
10    version 2 of the License (http://www.gnu.org/licenses/gpl.txt).
11
12    This library is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15    Lesser General Public License for more details.
16
17    In other words, you are welcome to use, share and improve this program.
18    You are forbidden to forbid anyone else to use, share and improve
19    what you give them.   Help stamp out software-hoarding!
20 -------------------------------------------------------------------------*/
21
22 #include <Windows.h>
23 #include <stdio.h>
24
25 #include "serial.h"
26 #define ASCII_XON       0x11
27 #define ASCII_XOFF      0x13
28
29 HANDLE SerialInit(char *ComPortName, DWORD BaudRate, int ByteSize, int StopBit, char ParityChar, char Protocol, int RxTimeOut, int TxTimeOut, int RxBufSize, int TxBufSize) 
30 {
31         HANDLE                  hCom;
32         BOOL                    bPortReady;
33         DCB                             dcb;
34         COMMTIMEOUTS    CommTimeouts;
35         int                             Parity;
36
37         switch(ParityChar) {
38                 case 'N':
39                 case 'n':
40                         Parity = NOPARITY;
41                         break;
42                 case 'E':
43                 case 'e':
44                         Parity = EVENPARITY;
45                         break;
46                 case 'O':
47                 case 'o':
48                         Parity = ODDPARITY;
49                         break;
50                 default:
51                         return NULL;    // illegal parameter !
52         }
53         
54         switch(StopBit)
55         {
56                 case 1:
57                         StopBit = ONESTOPBIT;
58                         break;
59                 case 2:
60                         StopBit = TWOSTOPBITS;
61                         break;
62                 default:
63                         return NULL;    // illegal parameter !
64         }
65
66         hCom = CreateFile(      ComPortName, 
67                                                 GENERIC_READ | GENERIC_WRITE,
68                                                 0, // exclusive access
69                                                 NULL, // no security
70                                                 OPEN_EXISTING,
71                                                 0, // no overlapped I/O
72                                                 NULL); // null template 
73
74         if(hCom == INVALID_HANDLE_VALUE) return NULL;
75
76         bPortReady = SetupComm(hCom, RxBufSize, TxBufSize); // set Rx and Tx buffer sizes
77
78         // Port settings are specified in a Data Communication Block (DCB). 
79
80         bPortReady = GetCommState(hCom, &dcb);
81
82         dcb.BaudRate    = BaudRate;
83         dcb.ByteSize    = ByteSize;
84         dcb.Parity              = Parity;
85         dcb.StopBits    = StopBit;
86         dcb.fAbortOnError = TRUE;
87
88         switch(Protocol) {
89         case 'D':       // DTR/DSR
90         case 'd':
91                 // set XON/XOFF
92                 dcb.fOutX       = FALSE;
93                 dcb.fInX        = FALSE;
94                 // set RTSCTS
95                 dcb.fOutxCtsFlow = FALSE;
96                 dcb.fRtsControl = RTS_CONTROL_DISABLE; 
97                 // set DSRDTR
98                 dcb.fOutxDsrFlow = TRUE;
99                 dcb.fDtrControl = DTR_CONTROL_HANDSHAKE; 
100                 break;
101         case 'R':       // RTS/CTS
102         case 'r':
103                 // set XON/XOFF
104                 dcb.fOutX       = FALSE;
105                 dcb.fInX        = FALSE;
106                 // set RTSCTS
107                 dcb.fOutxCtsFlow = TRUE;
108                 dcb.fRtsControl = RTS_CONTROL_HANDSHAKE; 
109                 // set DSRDTR
110                 dcb.fOutxDsrFlow = FALSE;
111                 dcb.fDtrControl = DTR_CONTROL_DISABLE; 
112                 break;
113         case 'X':       // XON/XOFF
114         case 'x':
115                 // set XON/XOFF
116                 dcb.fOutX       = TRUE;
117                 dcb.fInX        = TRUE;
118                 dcb.fTXContinueOnXoff = TRUE;
119                 dcb.XoffChar = ASCII_XOFF;
120                 dcb.XoffLim = RxBufSize - (RxBufSize / 4);
121                 dcb.XonChar = ASCII_XON;
122                 dcb.XonLim = RxBufSize - (RxBufSize / 2);
123                 // set RTSCTS
124                 dcb.fOutxCtsFlow = FALSE;
125                 dcb.fRtsControl = RTS_CONTROL_DISABLE; 
126                 // set DSRDTR
127                 dcb.fOutxDsrFlow = FALSE;
128                 dcb.fDtrControl = DTR_CONTROL_DISABLE;
129                 break;
130         case 'N':       // NOPROTOCOL
131         case 'n':
132         default:
133                 // set XON/XOFF
134                 dcb.fOutX       = FALSE;
135                 dcb.fInX        = FALSE;
136                 // set RTSCTS
137                 dcb.fOutxCtsFlow = FALSE;
138                 dcb.fRtsControl = RTS_CONTROL_DISABLE; 
139                 // set DSRDTR
140                 dcb.fOutxDsrFlow = FALSE;
141                 dcb.fDtrControl = DTR_CONTROL_DISABLE; 
142                 break;
143         }
144
145         bPortReady = SetCommState(hCom, &dcb);
146
147         // Set timeouts
148         CommTimeouts.ReadIntervalTimeout = RxTimeOut;
149         CommTimeouts.ReadTotalTimeoutMultiplier = 0;
150         CommTimeouts.ReadTotalTimeoutConstant = RxTimeOut;
151
152         CommTimeouts.WriteTotalTimeoutMultiplier = 0;
153         CommTimeouts.WriteTotalTimeoutConstant = TxTimeOut;
154
155         bPortReady = SetCommTimeouts(hCom, &CommTimeouts);
156
157         return hCom;
158 }
159
160 void SerialClose(HANDLE hSerial) {
161         CloseHandle(hSerial);
162 }
163
164 int SerialGetc(HANDLE hSerial)
165 {
166         unsigned char rxchar;
167         BOOL    bReadRC;
168         static  DWORD iBytesRead, dwError;
169
170         if(hSerial == NULL) return 0;
171
172         bReadRC = ReadFile(hSerial, &rxchar, 1, &iBytesRead, NULL);
173
174         if(bReadRC == FALSE) { // error
175
176                 ClearCommError(hSerial, &dwError, NULL);
177
178 //              PurgeComm(hSerial,  PURGE_RXABORT | PURGE_RXCLEAR | PURGE_TXABORT | PURGE_TXCLEAR);
179 //              PurgeComm(hSerial,  PURGE_RXCLEAR | PURGE_TXCLEAR);
180
181                 if(dwError == 0) return TIMEOUT;                // no error, iBytesRead is probably == 0
182                 if(dwError & CE_BREAK) return BREAK;    // break detected
183                 if(dwError & CE_FRAME) return BREAK;    // framing error
184
185                 /*      One, or a combination of the following conditions:
186                         CE_IOE          -> 0x0400 I/O error during communication with the device
187                         CE_OVERRUN      -> 0x0002 character-buffer overrun, the next character is lost
188                         CE_RXOVER       -> 0x0001 input buffer overflow, no room in the input buffer,
189                                               or a character was received after the EOF character
190                         CE_RXPARITY     -> 0x0004 parity error
191                         CE_TXFULL       -> 0x0100 transmit buffer is full
192                 */
193                 if(dwError & CE_IOE) printf("SerialGetc() I/O error during communication with the device!\n");
194                 if(dwError & CE_OVERRUN) printf("SerialGetc() Character-buffer overrun, the next character is lost!\n");
195                 if(dwError & CE_RXOVER) printf("SerialGetc() Input buffer overflow!\n");
196                 if(dwError & CE_RXPARITY) printf("SerialGetc() Parity error!\n");
197                 if(dwError & CE_TXFULL) printf("SerialGetc() Transmit buffer is full!\n");
198                 return SERIAL_ERROR;
199         }
200
201         if(iBytesRead == 0) return TIMEOUT; // Timeout occured
202
203         return (int) rxchar;
204 }
205
206
207 int SerialPutc(HANDLE hCom, char txchar)
208 {
209         BOOL    bWriteRC;
210         static  DWORD   iBytesWritten;
211
212         if(hCom == NULL) return -255;
213         
214         bWriteRC = WriteFile(hCom, &txchar, 1, &iBytesWritten,NULL);
215
216         if(iBytesWritten = 1) return 0;
217
218         return TIMEOUT;
219 }
220
221 char SerialGets(char *rxstring, int MaxNumberOfCharsToRead, HANDLE hCom)
222 {
223         int c;
224         int pos = 0;
225         unsigned char success = 0; // set to error
226
227         if(hCom == NULL) return success; // Error!
228
229         while(pos <= MaxNumberOfCharsToRead) {
230                 c = SerialGetc(hCom);
231
232                 if(c == TIMEOUT) return success;  // Error
233                 if(c == '\n') break;
234                 if(c != '\r') rxstring[pos++] = (char) c;       // discard carriage return
235         }
236         rxstring[pos] = 0;
237
238         success = 1;
239
240         return success; // No errors
241 }
242
243 void SerialPuts(HANDLE hCom, char *txstring)
244 {
245         BOOL    bWriteRC;
246         static  DWORD   iBytesWritten;
247
248         if(hCom == NULL) return;
249
250         bWriteRC = WriteFile(hCom, txstring, (DWORD) strlen(txstring), &iBytesWritten,NULL);
251 }
252
253 int SerialGetModemStatus(HANDLE hCom, int Mask)
254 {
255 // The value for Mask must be one of the following definitions:
256 // MS_CTS_ON
257 // MS_DSR_ON
258 // MS_RING_ON
259         int ModemStat;
260
261         GetCommModemStatus(hCom, &ModemStat);
262
263         switch( Mask ) {
264         case MS_CTS_ON:
265         case MS_DSR_ON:
266         case MS_RING_ON:
267                 if((ModemStat & Mask) != 0) {
268                         return 1;
269                 } else {
270                         return 0;
271                 }
272         default:
273                 return -1;
274         }
275 }
276
277 void SerialClearRxBuffer(HANDLE hCom)
278 {
279         PurgeComm(hCom, PURGE_RXCLEAR);
280 }