unified MX27, MX25, MX37 trees
[karo-tx-redboot.git] / packages / io / serial / v2_0 / src / common / termios.c
1 /* ====================================================================
2 //
3 //      termios.c
4 //
5 //      POSIX termios API implementation
6 //
7 // ====================================================================
8 //####ECOSGPLCOPYRIGHTBEGIN####
9 // -------------------------------------------
10 // This file is part of eCos, the Embedded Configurable Operating System.
11 // Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
12 //
13 // eCos is free software; you can redistribute it and/or modify it under
14 // the terms of the GNU General Public License as published by the Free
15 // Software Foundation; either version 2 or (at your option) any later version.
16 //
17 // eCos is distributed in the hope that it will be useful, but WITHOUT ANY
18 // WARRANTY; without even the implied warranty of MERCHANTABILITY or
19 // FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
20 // for more details.
21 //
22 // You should have received a copy of the GNU General Public License along
23 // with eCos; if not, write to the Free Software Foundation, Inc.,
24 // 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
25 //
26 // As a special exception, if other files instantiate templates or use macros
27 // or inline functions from this file, or you compile this file and link it
28 // with other works to produce a work based on this file, this file does not
29 // by itself cause the resulting work to be covered by the GNU General Public
30 // License. However the source code for this file must still be made available
31 // in accordance with section (3) of the GNU General Public License.
32 //
33 // This exception does not invalidate any other reasons why a work based on
34 // this file might be covered by the GNU General Public License.
35 //
36 // Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
37 // at http://sources.redhat.com/ecos/ecos-license/
38 // -------------------------------------------
39 //####ECOSGPLCOPYRIGHTEND####
40 // ====================================================================
41 //#####DESCRIPTIONBEGIN####
42 //
43 // Author(s):    jlarmour
44 // Contributors: 
45 // Date:         2000-07-22
46 // Purpose:      POSIX termios API support
47 // Description:  Most of the real work happens in the POSIX termios tty
48 //               drivers
49 //
50 //####DESCRIPTIONEND####
51 //
52 // ==================================================================*/
53
54 // CONFIGURATION
55
56 #include <pkgconf/io_serial.h>
57
58 #ifdef CYGPKG_IO_SERIAL_TERMIOS
59
60 // INCLUDES
61
62 #include <termios.h>             // Header for this file
63 #include <cyg/infra/cyg_type.h>  // Common stuff
64 #include <cyg/infra/cyg_ass.h>   // Assertion support
65 #include <cyg/infra/cyg_trac.h>  // Tracing support
66 #include <cyg/io/serialio.h>     // eCos serial implementation
67 #include <cyg/fileio/fileio.h>   // file operations
68 #include <cyg/io/io.h>
69 #include <errno.h>               // errno
70 #include <unistd.h>              // isatty()
71
72 // TYPES
73
74 typedef struct {
75     const struct termios *termios_p;
76     int optact;
77 } setattr_struct;
78
79 // FUNCTIONS
80
81 extern speed_t
82 cfgetospeed( const struct termios *termios_p )
83 {
84     CYG_REPORT_FUNCTYPE( "returning speed code %d" );
85     CYG_CHECK_DATA_PTRC( termios_p );
86     CYG_REPORT_FUNCARG1XV( termios_p );
87     CYG_REPORT_RETVAL( termios_p->c_ospeed );
88     return termios_p->c_ospeed;
89 } // cfgetospeed()
90
91
92 extern int
93 cfsetospeed( struct termios *termios_p, speed_t speed )
94 {
95     CYG_REPORT_FUNCTYPE( "returning %d" );
96     CYG_CHECK_DATA_PTRC( termios_p );
97     CYG_REPORT_FUNCARG2( "termios_p=%08x, speed=%d", termios_p, speed );
98     CYG_REPORT_RETVAL( termios_p->c_ospeed );
99     if ( speed > B4000000 ) {
100         errno = EINVAL;
101         CYG_REPORT_RETVAL( -1 );
102         return -1;
103     }
104     termios_p->c_ospeed = speed;
105     CYG_REPORT_RETVAL( 0 );
106     return 0;
107 } // cfsetospeed()
108
109
110 extern speed_t
111 cfgetispeed( const struct termios *termios_p )
112 {
113     CYG_REPORT_FUNCTYPE( "returning speed code %d" );
114     CYG_CHECK_DATA_PTRC( termios_p );
115     CYG_REPORT_FUNCARG1XV( termios_p );
116     CYG_REPORT_RETVAL( termios_p->c_ispeed );
117     return termios_p->c_ispeed;
118 } // cfgetispeed()
119
120
121 extern int
122 cfsetispeed( struct termios *termios_p, speed_t speed )
123 {
124     CYG_REPORT_FUNCTYPE( "returning %d" );
125     CYG_CHECK_DATA_PTRC( termios_p );
126     CYG_REPORT_FUNCARG2( "termios_p=%08x, speed=%d", termios_p, speed );
127     if ( speed > B115200 ) {
128         errno = EINVAL;
129         CYG_REPORT_RETVAL( -1 );
130         return -1;
131     }
132     termios_p->c_ispeed = speed;
133     CYG_REPORT_RETVAL( 0 );
134     return 0;
135 } // cfsetispeed()
136
137
138 __externC cyg_file *
139 cyg_fp_get( int fd );
140
141 __externC void
142 cyg_fp_free( cyg_file *fp );
143
144 extern int
145 tcgetattr( int fildes, struct termios *termios_p )
146 {
147     cyg_file *fp;
148     int ret;
149     int len = sizeof( *termios_p );
150
151     CYG_REPORT_FUNCTYPE( "returning %d" );
152     CYG_REPORT_FUNCARG2( "fildes=%d, termios_p=%08x", fildes, termios_p );
153     CYG_CHECK_DATA_PTRC( termios_p );
154
155     if ( !isatty(fildes) ) {
156         errno = ENOTTY;
157         CYG_REPORT_RETVAL( -1 );
158         return -1;
159     }
160         
161     fp = cyg_fp_get( fildes );
162
163     if ( NULL == fp ) {
164         errno = EBADF;
165         CYG_REPORT_RETVAL( -1 );
166         return -1;
167     }
168
169     ret = fp->f_ops->fo_getinfo( fp, CYG_IO_GET_CONFIG_TERMIOS, termios_p,
170                                  len);
171     cyg_fp_free( fp );
172
173     if ( ret > 0 ) {
174         errno = ret;
175         CYG_REPORT_RETVAL( -1 );
176         return -1;
177     }
178     CYG_REPORT_RETVAL( 0 );
179     return 0;        
180 } // tcgetattr()
181
182
183 extern int
184 tcsetattr( int fildes, int optact, const struct termios *termios_p )
185 {
186     cyg_file *fp;
187     int ret;
188     setattr_struct attr;
189     int len = sizeof( attr );
190
191     CYG_REPORT_FUNCTYPE( "returning %d" );
192     CYG_REPORT_FUNCARG3( "fildes=%d, optact=%d, termios_p=%08x",
193                          fildes, optact, termios_p );
194     CYG_CHECK_DATA_PTRC( termios_p );
195
196     if ( !isatty(fildes) ) {
197         errno = ENOTTY;
198         CYG_REPORT_RETVAL( -1 );
199         return -1;
200     }
201
202     if ( (optact != TCSANOW) && (optact != TCSADRAIN) &&
203          (optact != TCSAFLUSH) ) {
204         errno = EINVAL;
205         CYG_REPORT_RETVAL( -1 );
206         return -1;
207     }
208         
209     fp = cyg_fp_get( fildes );
210
211     if ( NULL == fp ) {
212         errno = EBADF;
213         CYG_REPORT_RETVAL( -1 );
214         return -1;
215     }
216
217     attr.termios_p = termios_p;
218     attr.optact = optact;
219
220     ret = fp->f_ops->fo_setinfo( fp, CYG_IO_SET_CONFIG_TERMIOS, &attr,
221                                  len);
222
223     cyg_fp_free( fp );
224
225     if ( ret > 0 ) {
226         errno = ret;
227         CYG_REPORT_RETVAL( -1 );
228         return -1;
229     }
230     CYG_REPORT_RETVAL( 0 );
231     return 0;        
232 } // tcsetattr()
233
234
235 extern int
236 tcsendbreak( int fildes, int duration )
237 {
238     // FIXME
239     return -EINVAL;
240 } // tcsendbreak()
241
242 extern int
243 tcdrain( int fildes )
244 {
245     cyg_file *fp;
246     int ret;
247
248     CYG_REPORT_FUNCTYPE( "returning %d" );
249     CYG_REPORT_FUNCARG1DV( fildes );
250
251     if ( !isatty(fildes) ) {
252         errno = ENOTTY;
253         CYG_REPORT_RETVAL( -1 );
254         return -1;
255     }
256
257     fp = cyg_fp_get( fildes );
258
259     if ( NULL == fp ) {
260         errno = EBADF;
261         CYG_REPORT_RETVAL( -1 );
262         return -1;
263     }
264
265     ret = fp->f_ops->fo_getinfo( fp,
266                                  CYG_IO_GET_CONFIG_SERIAL_OUTPUT_DRAIN,
267                                  NULL, 0 );
268     cyg_fp_free( fp );
269
270     if ( ret > 0 ) {
271         errno = ret;
272         CYG_REPORT_RETVAL( -1 );
273         return -1;
274     }
275     CYG_REPORT_RETVAL( 0 );
276     return 0;        
277 } // tcdrain()
278
279 extern int
280 tcflush( int fildes, int queue_sel )
281 {
282     cyg_file *fp;
283     int ret;
284
285     CYG_REPORT_FUNCTYPE( "returning %d" );
286     CYG_REPORT_FUNCARG2DV( fildes, queue_sel );
287
288     if ( !isatty(fildes) ) {
289         errno = ENOTTY;
290         CYG_REPORT_RETVAL( -1 );
291         return -1;
292     }
293
294     fp = cyg_fp_get( fildes );
295
296     if ( NULL == fp ) {
297         errno = EBADF;
298         CYG_REPORT_RETVAL( -1 );
299         return -1;
300     }
301
302     switch( queue_sel ) {
303     case TCIOFLUSH:
304         ret = fp->f_ops->fo_getinfo( fp,
305                                      CYG_IO_GET_CONFIG_SERIAL_OUTPUT_FLUSH,
306                                      NULL, 0 );
307         // fallthrough
308     case TCIFLUSH:
309         ret = fp->f_ops->fo_getinfo( fp,
310                                      CYG_IO_GET_CONFIG_SERIAL_INPUT_FLUSH,
311                                      NULL, 0 );
312         break;
313     case TCOFLUSH:
314         ret = fp->f_ops->fo_getinfo( fp,
315                                      CYG_IO_GET_CONFIG_SERIAL_OUTPUT_FLUSH,
316                                      NULL, 0 );
317         break;
318     default:
319         ret = EINVAL;
320         break;
321     }
322
323     cyg_fp_free( fp );
324
325     if ( ret > 0 ) {
326         errno = ret;
327         CYG_REPORT_RETVAL( -1 );
328         return -1;
329     }
330     CYG_REPORT_RETVAL( 0 );
331     return 0;        
332 } // tcflush()
333
334 extern int
335 tcflow( int fildes, int action )
336 {
337     cyg_file *fp;
338     int ret;
339     cyg_uint32 forcearg;
340     int len = sizeof(forcearg);
341
342     CYG_REPORT_FUNCTYPE( "returning %d" );
343     CYG_REPORT_FUNCARG2DV( fildes, action );
344
345     if ( !isatty(fildes) ) {
346         errno = ENOTTY;
347         CYG_REPORT_RETVAL( -1 );
348         return -1;
349     }
350
351     fp = cyg_fp_get( fildes );
352
353     if ( NULL == fp ) {
354         errno = EBADF;
355         CYG_REPORT_RETVAL( -1 );
356         return -1;
357     }
358
359     switch( action ) {
360     case TCOOFF:
361         forcearg = CYGNUM_SERIAL_FLOW_THROTTLE_TX;
362         ret = fp->f_ops->fo_setinfo( fp,
363                                     CYG_IO_SET_CONFIG_SERIAL_FLOW_CONTROL_FORCE,
364                                      &forcearg, len );
365         break;
366     case TCOON:
367         forcearg = CYGNUM_SERIAL_FLOW_RESTART_TX;
368         ret = fp->f_ops->fo_setinfo( fp,
369                                     CYG_IO_SET_CONFIG_SERIAL_FLOW_CONTROL_FORCE,
370                                      &forcearg, len );
371         break;
372     case TCIOFF:
373         forcearg = CYGNUM_SERIAL_FLOW_THROTTLE_RX;
374         ret = fp->f_ops->fo_setinfo( fp,
375                                     CYG_IO_SET_CONFIG_SERIAL_FLOW_CONTROL_FORCE,
376                                      &forcearg, len );
377         break;
378     case TCION:
379         forcearg = CYGNUM_SERIAL_FLOW_RESTART_RX;
380         ret = fp->f_ops->fo_setinfo( fp,
381                                     CYG_IO_SET_CONFIG_SERIAL_FLOW_CONTROL_FORCE,
382                                      &forcearg, len );
383         break;
384     default:
385         ret = EINVAL;
386         break;
387     }
388
389     cyg_fp_free( fp );
390
391     if ( ret > 0 ) {
392         errno = ret;
393         CYG_REPORT_RETVAL( -1 );
394         return -1;
395     }
396     CYG_REPORT_RETVAL( 0 );
397     return 0;        
398 } // tcflow()
399
400 #endif // ifdef CYGPKG_IO_SERIAL_TERMIOS
401
402 // EOF termios.c