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

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [rtos/] [ecos-2.0/] [packages/] [io/] [serial/] [v2_0/] [src/] [common/] [tty.c] - Blame information for rev 308

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 27 unneback
//==========================================================================
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 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):   gthomas
44
// Contributors:  gthomas
45
// Date:        1999-02-04
46
// Purpose:     Device driver for tty I/O, layered on top of serial I/O
47
// Description: 
48
//
49
//####DESCRIPTIONEND####
50
//
51
//==========================================================================
52
 
53
#include <pkgconf/io.h>
54
#include <pkgconf/io_serial.h>
55
#ifdef CYGPKG_IO_SERIAL_TTY
56
#include <cyg/io/io.h>
57
#include <cyg/io/devtab.h>
58
#include <cyg/io/ttyio.h>
59
#include <cyg/infra/diag.h>
60
 
61
static bool tty_init(struct cyg_devtab_entry *tab);
62
static Cyg_ErrNo tty_lookup(struct cyg_devtab_entry **tab,
63
                               struct cyg_devtab_entry *sub_tab,
64
                               const char *name);
65
static Cyg_ErrNo tty_write(cyg_io_handle_t handle, const void *buf, cyg_uint32 *len);
66
static Cyg_ErrNo tty_read(cyg_io_handle_t handle, void *buf, cyg_uint32 *len);
67
static Cyg_ErrNo tty_select(cyg_io_handle_t handle, cyg_uint32 which, CYG_ADDRWORD info);
68
static Cyg_ErrNo tty_get_config(cyg_io_handle_t handle, cyg_uint32 key, void *buf, cyg_uint32 *len);
69
static Cyg_ErrNo tty_set_config(cyg_io_handle_t handle, cyg_uint32 key, const void *buf, cyg_uint32 *len);
70
 
71
struct tty_private_info {
72
    cyg_tty_info_t     dev_info;
73
    cyg_io_handle_t dev_handle;
74
};
75
 
76
static DEVIO_TABLE(tty_devio,
77
                   tty_write,
78
                   tty_read,
79
                   tty_select,
80
                   tty_get_config,
81
                   tty_set_config
82
    );
83
 
84
#ifdef CYGPKG_IO_SERIAL_TTY_TTYDIAG
85
static struct tty_private_info tty_private_info_diag;
86
DEVTAB_ENTRY(tty_io_diag,
87
//             "/dev/console",       
88
//             CYGDAT_IO_SERIAL_TTY_CONSOLE,   // Based on driver for this device
89
             "/dev/ttydiag",
90
             "/dev/haldiag",
91
             &tty_devio,
92
             tty_init,
93
             tty_lookup,      // Execute this when device is being looked up
94
             &tty_private_info_diag);
95
#endif
96
 
97
#ifdef CYGPKG_IO_SERIAL_TTY_TTY0
98
static struct tty_private_info tty_private_info0;
99
DEVTAB_ENTRY(tty_io0,
100
             "/dev/tty0",
101
             CYGDAT_IO_SERIAL_TTY_TTY0_DEV,
102
             &tty_devio,
103
             tty_init,
104
             tty_lookup,      // Execute this when device is being looked up
105
             &tty_private_info0);
106
#endif
107
 
108
#ifdef CYGPKG_IO_SERIAL_TTY_TTY1
109
static struct tty_private_info tty_private_info1;
110
DEVTAB_ENTRY(tty_io1,
111
             "/dev/tty1",
112
             CYGDAT_IO_SERIAL_TTY_TTY1_DEV,
113
             &tty_devio,
114
             tty_init,
115
             tty_lookup,      // Execute this when device is being looked up
116
             &tty_private_info1);
117
#endif
118
 
119
#ifdef CYGPKG_IO_SERIAL_TTY_TTY2
120
static struct tty_private_info tty_private_info2;
121
DEVTAB_ENTRY(tty_io2,
122
             "/dev/tty2",
123
             CYGDAT_IO_SERIAL_TTY_TTY2_DEV,
124
             &tty_devio,
125
             tty_init,
126
             tty_lookup,      // Execute this when device is being looked up
127
             &tty_private_info2);
128
#endif
129
 
130
static bool
131
tty_init(struct cyg_devtab_entry *tab)
132
{
133
    struct tty_private_info *priv = (struct tty_private_info *)tab->priv;
134
#ifdef CYGDBG_IO_INIT
135
    diag_printf("Init tty channel: %x\n", tab);
136
#endif
137
    priv->dev_info.tty_out_flags = CYG_TTY_OUT_FLAGS_DEFAULT;
138
    priv->dev_info.tty_in_flags = CYG_TTY_IN_FLAGS_DEFAULT;
139
    return true;
140
}
141
 
142
static Cyg_ErrNo
143
tty_lookup(struct cyg_devtab_entry **tab,
144
           struct cyg_devtab_entry *sub_tab,
145
           const char *name)
146
{
147
    cyg_io_handle_t chan = (cyg_io_handle_t)sub_tab;
148
    struct tty_private_info *priv = (struct tty_private_info *)(*tab)->priv;
149
#if 0
150
    cyg_int32 len;
151
#endif
152
    priv->dev_handle = chan;
153
#if 0
154
    len = sizeof(cyg_serial_info_t);
155
    // Initialize configuration
156
    cyg_io_get_config(chan, CYG_SERIAL_GET_CONFIG,
157
                      (void *)&priv->dev_info.serial_config, &len);
158
#endif
159
    return ENOERR;
160
}
161
 
162
#define BUFSIZE 64
163
 
164
static Cyg_ErrNo
165
tty_write(cyg_io_handle_t handle, const void *_buf, cyg_uint32 *len)
166
{
167
    cyg_devtab_entry_t *t = (cyg_devtab_entry_t *)handle;
168
    struct tty_private_info *priv = (struct tty_private_info *)t->priv;
169
    cyg_io_handle_t chan = (cyg_io_handle_t)priv->dev_handle;
170
    cyg_int32 size, bytes_successful, actually_written;
171
    cyg_uint8 xbuf[BUFSIZE];
172
    cyg_uint8 c;
173
    cyg_uint8 *buf = (cyg_uint8 *)_buf;
174
    Cyg_ErrNo res = -EBADF;
175
    // assert(chan)
176
    size = 0;
177
    bytes_successful = 0;
178
    actually_written = 0;
179
    while (bytes_successful++ < *len) {
180
        c = *buf++;
181
        if ((c == '\n') &&
182
            (priv->dev_info.tty_out_flags & CYG_TTY_OUT_FLAGS_CRLF)) {
183
            xbuf[size++] = '\r';
184
        }
185
        xbuf[size++] = c;
186
        // Always leave room for possible CR/LF expansion
187
        if ((size >= (BUFSIZE-1)) ||
188
            (bytes_successful == *len)) {
189
            res = cyg_io_write(chan, xbuf, &size);
190
            if (res != ENOERR) {
191
                *len = actually_written;
192
                return res;
193
            }
194
            actually_written += size;
195
            size = 0;
196
        }
197
    }
198
    return res;
199
}
200
 
201
static Cyg_ErrNo
202
tty_read(cyg_io_handle_t handle, void *_buf, cyg_uint32 *len)
203
{
204
    cyg_devtab_entry_t *t = (cyg_devtab_entry_t *)handle;
205
    struct tty_private_info *priv = (struct tty_private_info *)t->priv;
206
    cyg_io_handle_t chan = (cyg_io_handle_t)priv->dev_handle;
207
    cyg_uint32 clen;
208
    cyg_int32 size;
209
    Cyg_ErrNo res;
210
    cyg_uint8 c;
211
    cyg_uint8 *buf = (cyg_uint8 *)_buf;
212
    // assert(chan)
213
    size = 0;
214
    while (size < *len) {
215
        clen = 1;
216
        res = cyg_io_read(chan, &c, &clen);
217
        if (res != ENOERR) {
218
            *len = size;
219
            return res;
220
        }
221
        buf[size++] = c;
222
        if ((priv->dev_info.tty_in_flags & CYG_TTY_IN_FLAGS_BINARY) == 0) {
223
            switch (c) {
224
            case '\b':    /* drop through */
225
            case 0x7f:
226
                size -= 2;  // erase one character + 'backspace' char
227
                if (size < 0) {
228
                    size = 0;
229
                } else if (priv->dev_info.tty_in_flags & CYG_TTY_IN_FLAGS_ECHO) {
230
                    clen = 3;
231
                    cyg_io_write(chan, "\b \b", &clen);
232
                }
233
                break;
234
            case '\r':
235
                if (priv->dev_info.tty_in_flags & CYG_TTY_IN_FLAGS_CRLF) {
236
                    /* Don't do anything because a '\n' will come next */
237
                    break;
238
                }
239
                if (priv->dev_info.tty_in_flags & CYG_TTY_IN_FLAGS_CR) {
240
                    c = '\n';  // Map CR -> LF
241
                }
242
                /* drop through */
243
            case '\n':
244
                if (priv->dev_info.tty_in_flags & CYG_TTY_IN_FLAGS_ECHO) {
245
                    if (priv->dev_info.tty_out_flags & CYG_TTY_OUT_FLAGS_CRLF) {
246
                        clen = 2;
247
                        cyg_io_write(chan, "\r\n", &clen);
248
                    } else {
249
                        clen = 1;
250
                        cyg_io_write(chan, &c, &clen);
251
                    }
252
                }
253
                buf[size-1] = c;
254
                *len = size;
255
                return ENOERR;
256
            default:
257
                if (priv->dev_info.tty_in_flags & CYG_TTY_IN_FLAGS_ECHO) {
258
                    clen = 1;
259
                    cyg_io_write(chan, &c, &clen);
260
                }
261
                break;
262
            }
263
        }
264
    }
265
    *len = size;
266
    return ENOERR;
267
}
268
 
269
static cyg_bool
270
tty_select(cyg_io_handle_t handle, cyg_uint32 which, CYG_ADDRWORD info)
271
{
272
    cyg_devtab_entry_t *t = (cyg_devtab_entry_t *)handle;
273
    struct tty_private_info *priv = (struct tty_private_info *)t->priv;
274
    cyg_io_handle_t chan = (cyg_io_handle_t)priv->dev_handle;
275
 
276
    // Just pass it on to next driver level
277
    return cyg_io_select( chan, which, info );
278
}
279
 
280
static Cyg_ErrNo
281
tty_get_config(cyg_io_handle_t handle, cyg_uint32 key, void *buf, cyg_uint32 *len)
282
{
283
    cyg_devtab_entry_t *t = (cyg_devtab_entry_t *)handle;
284
    struct tty_private_info *priv = (struct tty_private_info *)t->priv;
285
    cyg_io_handle_t chan = (cyg_io_handle_t)priv->dev_handle;
286
    Cyg_ErrNo res = ENOERR;
287
#if 0
288
    cyg_int32 current_len;
289
#endif
290
    // assert(chan)
291
    switch (key) {
292
    case CYG_IO_GET_CONFIG_TTY_INFO:
293
        if (*len < sizeof(cyg_tty_info_t)) {
294
            return -EINVAL;
295
        }
296
#if 0
297
        current_len = sizeof(cyg_serial_info_t);
298
        res = cyg_io_get_config(chan, CYG_SERIAL_GET_CONFIG,
299
                                (void *)&priv->dev_info.serial_config, &current_len);
300
        if (res != ENOERR) {
301
            return res;
302
        }
303
#endif
304
        *(cyg_tty_info_t *)buf = priv->dev_info;
305
        *len = sizeof(cyg_tty_info_t);
306
        break;
307
    default:  // Assume this is a 'serial' driver control
308
        res = cyg_io_get_config(chan, key, buf, len);
309
    }
310
    return res;
311
}
312
 
313
static Cyg_ErrNo
314
tty_set_config(cyg_io_handle_t handle, cyg_uint32 key, const void *buf, cyg_uint32 *len)
315
{
316
    cyg_devtab_entry_t *t = (cyg_devtab_entry_t *)handle;
317
    struct tty_private_info *priv = (struct tty_private_info *)t->priv;
318
    cyg_io_handle_t chan = (cyg_io_handle_t)priv->dev_handle;
319
#if 0
320
    cyg_int32 current_len;
321
#endif
322
    Cyg_ErrNo res = ENOERR;
323
    // assert(chan)
324
    switch (key) {
325
    case CYG_IO_SET_CONFIG_TTY_INFO:
326
        if (*len != sizeof(cyg_tty_info_t)) {
327
            return -EINVAL;
328
        }
329
        priv->dev_info = *(cyg_tty_info_t *)buf;
330
        break;
331
    default: // Pass on to serial driver
332
        res = cyg_io_set_config(chan, key, buf, len);
333
    }
334
    return res;
335
}
336
#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.