chiark / gitweb /
Follow new transport configuration interface. Add parameters for flow
[jog] / serial.c
1 /* -*-c-*-
2  *
3  * $Id: serial.c,v 1.2 2002/01/30 09:23:58 mdw Exp $
4  *
5  * Common serial functionality
6  *
7  * (c) 2001 Mark Wooding
8  */
9
10 /*----- Licensing notice --------------------------------------------------* 
11  *
12  * This file is part of Jog: Programming for a jogging machine.
13  *
14  * Jog is free software; you can redistribute it and/or modify
15  * it under the terms of the GNU General Public License as published by
16  * the Free Software Foundation; either version 2 of the License, or
17  * (at your option) any later version.
18  * 
19  * Jog is distributed in the hope that it will be useful,
20  * but WITHOUT ANY WARRANTY; without even the implied warranty of
21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22  * GNU General Public License for more details.
23  * 
24  * You should have received a copy of the GNU General Public License
25  * along with Jog; if not, write to the Free Software Foundation,
26  * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
27  */
28
29 /*----- Revision history --------------------------------------------------* 
30  *
31  * $Log: serial.c,v $
32  * Revision 1.2  2002/01/30 09:23:58  mdw
33  * Follow new transport configuration interface.  Add parameters for flow
34  * control.  Break the format into separate parameters for independent
35  * configuration.
36  *
37  * Revision 1.1  2002/01/25 19:34:45  mdw
38  * Initial revision
39  *
40  */
41
42 /*----- Header files ------------------------------------------------------*/
43
44 #include <ctype.h>
45 #include <stdlib.h>
46 #include <string.h>
47
48 #include "serial.h"
49
50 /*----- Main code ---------------------------------------------------------*/
51
52 /* --- @getbaud@ --- *
53  *
54  * Arguments:   @const char *p@ = pointer to string
55  *              @const char **pp@ = where to store final pointer
56  *
57  * Returns:     Baud rate, or @-1@ on failure.
58  *
59  * Use:         Parses a baud rate, either as a raw number or as an
60  *              expression like `9k6'.
61  */
62
63 static long getbaud(const char *p, const char **pp)
64 {
65   long x = 0;
66   long f = 1, s = 10;
67   int ok = 0;
68
69   /* --- Main loop --- */
70
71   for (;;) {
72     int ch = (unsigned char)*p;
73
74     switch (ch) {
75       case 'k':
76       case 'K':
77         f = 1000;
78         goto factor;
79       case 'm':
80       case 'M':
81         f = 1000000;
82         goto factor;
83       factor:
84         if (ok != 1)
85           return (-1);
86         x *= f;
87         s = 1;
88         ok = 2;
89         break;
90       default:
91         if (!isdigit(ch))
92           goto done;
93         if (!ok)
94           ok = 1;
95         if (ok == 2) {
96           if (f == 1)
97             return (-1);
98           f /= 10;
99         }
100         x = x * s + (ch - '0') * f;
101         break;
102     }
103     p++;
104   }
105 done:
106   if (!ok)
107     return (-1);
108   if (pp)
109     *pp = p;
110   return (x);
111 }
112
113 /* --- @getparity@ --- *
114  *
115  * Arguments:   @const char *p@ = pointer to string
116  *              @const char **pp@ = where to store final pointer
117  *
118  * Returns:     Parity constant or @-1@ on error.
119  *
120  * Use:         Parses a parity setting.
121  */
122
123 static int getparity(const char *p, const char **pp)
124 {
125   const char *q;
126
127   for (q = p; isalpha((unsigned char)*q); q++)
128     ;
129   if (q == p)
130     return (-1);
131   if (pp)
132     *pp = q;
133   if (strncmp(p, "none", q - p) == 0)
134     return (PARITY_NONE);
135   else if (strncmp(p, "odd", q - p) == 0)
136     return (PARITY_ODD);
137   else if (strncmp(p, "even", q - p) == 0)
138     return (PARITY_EVEN);
139   else
140     return (-1);
141 }
142
143 /* --- @getflow@ --- *
144  *
145  * Arguments:   @const char *p@ = pointer to string
146  *              @const char **pp@ = where to store final pointer
147  *
148  * Returns:     Flow control constant or @-1@ on error.
149  *
150  * Use:         Parses a flow control setting.
151  */
152
153 static int getflow(const char *p, const char **pp)
154 {
155   const char *q;
156
157   for (q = p; isalpha((unsigned char)*q); q++)
158     ;
159   if (q == p)
160     return (-1);
161   if (pp)
162     *pp = q;
163   if (strncmp(p, "none", q - p) == 0)
164     return (FLOW_NONE);
165   else if (strncmp(p, "soft", q - p) == 0 ||
166            strncmp(p, "xon-xoff", q - p) == 0 ||
167            strncmp(p, "xon/xoff", q - p) == 0 ||
168            strncmp(p, "xonxoff", q - p) == 0)
169     return (FLOW_XONXOFF);
170   else if (strncmp(p, "hard", q - p) == 0 ||
171            strncmp(p, "cts-rts", q - p) == 0 ||
172            strncmp(p, "cts/rts", q - p) == 0 ||
173            strncmp(p, "ctsrts", q - p) == 0 ||
174            strncmp(p, "rts/cts", q - p) == 0 ||
175            strncmp(p, "rts-cts", q - p) == 0 ||
176            strncmp(p, "rtscts", q - p) == 0)
177     return (FLOW_RTSCTS);
178   else
179     return (-1);
180 }
181
182 /* --- @serial_parse@ --- *
183  *
184  * Arguments:   @serial_config *sc@ = pointer to serial config structure
185  *              @const char *k, *v@ = keyword and value pair
186  *
187  * Returns:     Zero if OK, or @-1@ on error.
188  *
189  * Use:         Parses a serial config string into something more
190  *              reasonable.  The config structure should have been
191  *              initialized to something sensible (e.g., @SERIAL_INIT@)
192  *              already.
193  */
194
195 int serial_parse(serial_config *sc, const char *k, const char *v)
196 {
197   long x;
198   const char *q;
199   char *qq;
200
201   if (strcmp(k, "baud") == 0 || strcmp(k, "bps") == 0) {
202     if (!v || (x = getbaud(v, &q)) < 0 || *q)
203       return (-1);
204     sc->baud = x;
205   } else if (strcmp(k, "data") == 0 || strcmp(k, "data-bits") == 0 ||
206              strcmp(k, "databits") == 0 || strcmp(k, "data-len") == 0 ||
207              strcmp(k, "datalen") == 0 || strcmp(k, "word") == 0 ||
208              strcmp(k, "word-len") == 0 || strcmp(k, "wordlen") == 0) {
209     if (!v || (x = strtol(v, &qq, 10)) == 0 || *qq)
210       return (-1);
211     sc->wordlen = x;
212   } else if (strcmp(k, "parity") == 0) {
213     if (!v || (x = getparity(v, &q)) < 0 || *q)
214       return (-1);
215     sc->parity = x;
216   } else if (strcmp(k, "stop") == 0 || strcmp(k, "stop-bits") == 0 ||
217              strcmp(k, "stopbits") == 0) {
218     if (!v || (x = strtol(v, &qq, 10)) == 0 || *qq)
219       return (-1);
220     sc->stopbits = x;
221   } else if (strcmp(k, "flow") == 0 || strcmp(k, "flow-control") == 0 ||
222              strcmp(k, "flowcontrol") == 0) {
223     if (!v || (x = getflow(v, &q)) < 0 || *q)
224       return (-1);
225     sc->flow = x;
226   } else if (strcmp(k, "format") == 0) {
227     if (!v)
228       return (-1);
229     if ((x = strtol(v, &qq, 10)) == 0)
230       return (-1);
231     v = qq;
232     sc->wordlen = x;
233     if (*v == '-')
234       v++;
235     if ((x = getparity(v, &q)) < 0)
236       return (-1);
237     sc->parity = x;
238     v = q;
239     if (*v == '-')
240       v++;
241     if ((x = strtol(v, &qq, 10)) == 0)
242       return (-1);
243     v = qq;
244     sc->stopbits = x;
245     if (*v)
246       return (-1);
247   } else
248     return (-1);
249
250   return (0);
251 }
252
253 /*----- Test rig ----------------------------------------------------------*/
254
255 #ifdef TEST_RIG
256
257 #include <stdio.h>
258 #include <string.h>
259
260 int main(int argc, char *argv[])
261 {
262   int i;
263   static const char *ptab[] = { "none", "odd", "even" };
264   static const char *ftab[] = { "none", "xon/xoff", "rts/cts" };
265
266   for (i = 1; i < argc; i++) {
267     serial_config sc = SERIAL_INIT;
268     char *k, *v;
269
270     for (k = strtok(argv[i], ";"); k; k = strtok(0, ";")) {
271       if ((v = strchr(k, '=')) != 0)
272         *v++ = 0;
273       if (serial_parse(&sc, k, v)) {
274         printf("invalid serial configuration `%s=%s'\n", k, v);
275         goto next;
276       }
277     }
278     printf("%lu %u-%s-%u %s\n", sc.baud, sc.wordlen,
279            ptab[sc.parity], sc.stopbits, ftab[sc.flow]);
280   next:;
281   }
282   return (0);
283 }
284
285 #endif
286
287 /*----- That's all, folks -------------------------------------------------*/