OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [ecos-3.0/] [packages/] [io/] [serial/] [current/] [src/] [common/] [tty.c] - Blame information for rev 786

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 786 skrzyp
//==========================================================================
2
//
3
//      io/serial/common/tty.c
4
//
5
//      TTY (terminal-like interface) I/O driver
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 Free Software Foundation, 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      
16
// version.                                                                 
17
//
18
// eCos is distributed in the hope that it will be useful, but WITHOUT      
19
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or    
20
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License    
21
// for more details.                                                        
22
//
23
// You should have received a copy of the GNU General Public License        
24
// along with eCos; if not, write to the Free Software Foundation, Inc.,    
25
// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.            
26
//
27
// As a special exception, if other files instantiate templates or use      
28
// macros or inline functions from this file, or you compile this file      
29
// and link it with other works to produce a work based on this file,       
30
// this file does not by itself cause the resulting work to be covered by   
31
// the GNU General Public License. However the source code for this file    
32
// must still be made available in accordance with section (3) of the GNU   
33
// General Public License v2.                                               
34
//
35
// This exception does not invalidate any other reasons why a work based    
36
// on this file might be covered by the GNU General Public License.         
37
// -------------------------------------------                              
38
// ####ECOSGPLCOPYRIGHTEND####                                              
39
//==========================================================================
40
//#####DESCRIPTIONBEGIN####
41
//
42
// Author(s):   gthomas
43
// Contributors:  gthomas
44
// Date:        1999-02-04
45
// Purpose:     Device driver for tty I/O, layered on top of serial I/O
46
// Description: 
47
//
48
//####DESCRIPTIONEND####
49
//
50
//==========================================================================
51
 
52
#include <pkgconf/io.h>
53
#include <pkgconf/io_serial.h>
54
#ifdef CYGPKG_IO_SERIAL_TTY
55
#include <cyg/io/io.h>
56
#include <cyg/io/devtab.h>
57
#include <cyg/io/ttyio.h>
58
#include <cyg/infra/diag.h>
59
 
60
static bool tty_init(struct cyg_devtab_entry *tab);
61
static Cyg_ErrNo tty_lookup(struct cyg_devtab_entry **tab,
62
                               struct cyg_devtab_entry *sub_tab,
63
                               const char *name);
64
static Cyg_ErrNo tty_write(cyg_io_handle_t handle, const void *buf, cyg_uint32 *len);
65
static Cyg_ErrNo tty_read(cyg_io_handle_t handle, void *buf, cyg_uint32 *len);
66
static cyg_bool  tty_select(cyg_io_handle_t handle, cyg_uint32 which, CYG_ADDRWORD info);
67
static Cyg_ErrNo tty_get_config(cyg_io_handle_t handle, cyg_uint32 key, void *buf, cyg_uint32 *len);
68
static Cyg_ErrNo tty_set_config(cyg_io_handle_t handle, cyg_uint32 key, const void *buf, cyg_uint32 *len);
69
 
70
struct tty_private_info {
71
    cyg_tty_info_t     dev_info;
72
    cyg_io_handle_t dev_handle;
73
};
74
 
75
static DEVIO_TABLE(tty_devio,
76
                   tty_write,
77
                   tty_read,
78
                   tty_select,
79
                   tty_get_config,
80
                   tty_set_config
81
    );
82
 
83
#ifdef CYGPKG_IO_SERIAL_TTY_TTYDIAG
84
static struct tty_private_info tty_private_info_diag;
85
DEVTAB_ENTRY(tty_io_diag,
86
//             "/dev/console",       
87
//             CYGDAT_IO_SERIAL_TTY_CONSOLE,   // Based on driver for this device
88
             "/dev/ttydiag",
89
             "/dev/haldiag",
90
             &tty_devio,
91
             tty_init,
92
             tty_lookup,      // Execute this when device is being looked up
93
             &tty_private_info_diag);
94
#endif
95
 
96
#ifdef CYGPKG_IO_SERIAL_TTY_TTY0
97
static struct tty_private_info tty_private_info0;
98
DEVTAB_ENTRY(tty_io0,
99
             "/dev/tty0",
100
             CYGDAT_IO_SERIAL_TTY_TTY0_DEV,
101
             &tty_devio,
102
             tty_init,
103
             tty_lookup,      // Execute this when device is being looked up
104
             &tty_private_info0);
105
#endif
106
 
107
#ifdef CYGPKG_IO_SERIAL_TTY_TTY1
108
static struct tty_private_info tty_private_info1;
109
DEVTAB_ENTRY(tty_io1,
110
             "/dev/tty1",
111
             CYGDAT_IO_SERIAL_TTY_TTY1_DEV,
112
             &tty_devio,
113
             tty_init,
114
             tty_lookup,      // Execute this when device is being looked up
115
             &tty_private_info1);
116
#endif
117
 
118
#ifdef CYGPKG_IO_SERIAL_TTY_TTY2
119
static struct tty_private_info tty_private_info2;
120
DEVTAB_ENTRY(tty_io2,
121
             "/dev/tty2",
122
             CYGDAT_IO_SERIAL_TTY_TTY2_DEV,
123
             &tty_devio,
124
             tty_init,
125
             tty_lookup,      // Execute this when device is being looked up
126
             &tty_private_info2);
127
#endif
128
 
129
#ifdef CYGPKG_IO_SERIAL_TTY_TTY3
130
static struct tty_private_info tty_private_info3;
131
DEVTAB_ENTRY(tty_io3,
132
             "/dev/tty3",
133
             CYGDAT_IO_SERIAL_TTY_TTY3_DEV,
134
             &tty_devio,
135
             tty_init,
136
             tty_lookup,      // Execute this when device is being looked up
137
             &tty_private_info3);
138
#endif
139
 
140
// More DEVTAB entries can be added using an inclusion
141
#ifdef CYGDAT_IO_SERIAL_TTY_ADD_INL
142
# include CYGDAT_IO_SERIAL_TTY_ADD_INL
143
#endif
144
 
145
static bool
146
tty_init(struct cyg_devtab_entry *tab)
147
{
148
    struct tty_private_info *priv = (struct tty_private_info *)tab->priv;
149
#ifdef CYGDBG_IO_INIT
150
    diag_printf("Init tty channel: %p\n", tab);
151
#endif
152
    priv->dev_info.tty_out_flags = CYG_TTY_OUT_FLAGS_DEFAULT;
153
    priv->dev_info.tty_in_flags = CYG_TTY_IN_FLAGS_DEFAULT;
154
    return true;
155
}
156
 
157
static Cyg_ErrNo
158
tty_lookup(struct cyg_devtab_entry **tab,
159
           struct cyg_devtab_entry *sub_tab,
160
           const char *name)
161
{
162
    cyg_io_handle_t chan = (cyg_io_handle_t)sub_tab;
163
    struct tty_private_info *priv = (struct tty_private_info *)(*tab)->priv;
164
#if 0
165
    cyg_int32 len;
166
#endif
167
    priv->dev_handle = chan;
168
#if 0
169
    len = sizeof(cyg_serial_info_t);
170
    // Initialize configuration
171
    cyg_io_get_config(chan, CYG_SERIAL_GET_CONFIG,
172
                      (void *)&priv->dev_info.serial_config, &len);
173
#endif
174
    return ENOERR;
175
}
176
 
177
#define BUFSIZE 64
178
 
179
static Cyg_ErrNo
180
tty_write(cyg_io_handle_t handle, const void *_buf, cyg_uint32 *len)
181
{
182
    cyg_devtab_entry_t *t = (cyg_devtab_entry_t *)handle;
183
    struct tty_private_info *priv = (struct tty_private_info *)t->priv;
184
    cyg_io_handle_t chan = (cyg_io_handle_t)priv->dev_handle;
185
    cyg_uint32 size;
186
    cyg_int32 bytes_successful, actually_written;
187
    cyg_uint8 xbuf[BUFSIZE];
188
    cyg_uint8 c;
189
    cyg_uint8 *buf = (cyg_uint8 *)_buf;
190
    Cyg_ErrNo res = -EBADF;
191
    // assert(chan)
192
    size = 0;
193
    bytes_successful = 0;
194
    actually_written = 0;
195
    while (bytes_successful++ < *len) {
196
        c = *buf++;
197
        if ((c == '\n') &&
198
            (priv->dev_info.tty_out_flags & CYG_TTY_OUT_FLAGS_CRLF)) {
199
            xbuf[size++] = '\r';
200
        }
201
        xbuf[size++] = c;
202
        // Always leave room for possible CR/LF expansion
203
        if ((size >= (BUFSIZE-1)) ||
204
            (bytes_successful == *len)) {
205
            res = cyg_io_write(chan, xbuf, &size);
206
            if (res != ENOERR) {
207
                *len = actually_written;
208
                return res;
209
            }
210
            actually_written += size;
211
            size = 0;
212
        }
213
    }
214
    return res;
215
}
216
 
217
static Cyg_ErrNo
218
tty_read(cyg_io_handle_t handle, void *_buf, cyg_uint32 *len)
219
{
220
    cyg_devtab_entry_t *t = (cyg_devtab_entry_t *)handle;
221
    struct tty_private_info *priv = (struct tty_private_info *)t->priv;
222
    cyg_io_handle_t chan = (cyg_io_handle_t)priv->dev_handle;
223
    cyg_uint32 clen;
224
    cyg_int32 size;
225
    Cyg_ErrNo res;
226
    cyg_uint8 c;
227
    cyg_uint8 *buf = (cyg_uint8 *)_buf;
228
    // assert(chan)
229
    size = 0;
230
    while (size < *len) {
231
        clen = 1;
232
        res = cyg_io_read(chan, &c, &clen);
233
        if (res != ENOERR) {
234
            *len = size;
235
            return res;
236
        }
237
        buf[size++] = c;
238
        if ((priv->dev_info.tty_in_flags & CYG_TTY_IN_FLAGS_BINARY) == 0) {
239
            switch (c) {
240
            case '\b':    /* drop through */
241
            case 0x7f:
242
                size -= 2;  // erase one character + 'backspace' char
243
                if (size < 0) {
244
                    size = 0;
245
                } else if (priv->dev_info.tty_in_flags & CYG_TTY_IN_FLAGS_ECHO) {
246
                    clen = 3;
247
                    cyg_io_write(chan, "\b \b", &clen);
248
                }
249
                break;
250
            case '\r':
251
                if (priv->dev_info.tty_in_flags & CYG_TTY_IN_FLAGS_CRLF) {
252
                    /* Don't do anything because a '\n' will come next */
253
                    break;
254
                }
255
                if (priv->dev_info.tty_in_flags & CYG_TTY_IN_FLAGS_CR) {
256
                    c = '\n';  // Map CR -> LF
257
                }
258
                /* drop through */
259
            case '\n':
260
                if (priv->dev_info.tty_in_flags & CYG_TTY_IN_FLAGS_ECHO) {
261
                    if (priv->dev_info.tty_out_flags & CYG_TTY_OUT_FLAGS_CRLF) {
262
                        clen = 2;
263
                        cyg_io_write(chan, "\r\n", &clen);
264
                    } else {
265
                        clen = 1;
266
                        cyg_io_write(chan, &c, &clen);
267
                    }
268
                }
269
                buf[size-1] = c;
270
                *len = size;
271
                return ENOERR;
272
            default:
273
                if (priv->dev_info.tty_in_flags & CYG_TTY_IN_FLAGS_ECHO) {
274
                    clen = 1;
275
                    cyg_io_write(chan, &c, &clen);
276
                }
277
                break;
278
            }
279
        }
280
    }
281
    *len = size;
282
    return ENOERR;
283
}
284
 
285
static cyg_bool
286
tty_select(cyg_io_handle_t handle, cyg_uint32 which, CYG_ADDRWORD info)
287
{
288
    cyg_devtab_entry_t *t = (cyg_devtab_entry_t *)handle;
289
    struct tty_private_info *priv = (struct tty_private_info *)t->priv;
290
    cyg_io_handle_t chan = (cyg_io_handle_t)priv->dev_handle;
291
 
292
    // Just pass it on to next driver level
293
    return cyg_io_select( chan, which, info );
294
}
295
 
296
static Cyg_ErrNo
297
tty_get_config(cyg_io_handle_t handle, cyg_uint32 key, void *buf, cyg_uint32 *len)
298
{
299
    cyg_devtab_entry_t *t = (cyg_devtab_entry_t *)handle;
300
    struct tty_private_info *priv = (struct tty_private_info *)t->priv;
301
    cyg_io_handle_t chan = (cyg_io_handle_t)priv->dev_handle;
302
    Cyg_ErrNo res = ENOERR;
303
#if 0
304
    cyg_int32 current_len;
305
#endif
306
    // assert(chan)
307
    switch (key) {
308
    case CYG_IO_GET_CONFIG_TTY_INFO:
309
        if (*len < sizeof(cyg_tty_info_t)) {
310
            return -EINVAL;
311
        }
312
#if 0
313
        current_len = sizeof(cyg_serial_info_t);
314
        res = cyg_io_get_config(chan, CYG_SERIAL_GET_CONFIG,
315
                                (void *)&priv->dev_info.serial_config, &current_len);
316
        if (res != ENOERR) {
317
            return res;
318
        }
319
#endif
320
        *(cyg_tty_info_t *)buf = priv->dev_info;
321
        *len = sizeof(cyg_tty_info_t);
322
        break;
323
    default:  // Assume this is a 'serial' driver control
324
        res = cyg_io_get_config(chan, key, buf, len);
325
    }
326
    return res;
327
}
328
 
329
static Cyg_ErrNo
330
tty_set_config(cyg_io_handle_t handle, cyg_uint32 key, const void *buf, cyg_uint32 *len)
331
{
332
    cyg_devtab_entry_t *t = (cyg_devtab_entry_t *)handle;
333
    struct tty_private_info *priv = (struct tty_private_info *)t->priv;
334
    cyg_io_handle_t chan = (cyg_io_handle_t)priv->dev_handle;
335
#if 0
336
    cyg_int32 current_len;
337
#endif
338
    Cyg_ErrNo res = ENOERR;
339
    // assert(chan)
340
    switch (key) {
341
    case CYG_IO_SET_CONFIG_TTY_INFO:
342
        if (*len != sizeof(cyg_tty_info_t)) {
343
            return -EINVAL;
344
        }
345
        priv->dev_info = *(cyg_tty_info_t *)buf;
346
        break;
347
    default: // Pass on to serial driver
348
        res = cyg_io_set_config(chan, key, buf, len);
349
    }
350
    return res;
351
}
352
#endif // CYGPKG_IO_SERIAL_TTY

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.