Mercurial > flash_v2
annotate packages/io/serial/current/src/common/tty.c @ 62:7a6ac9edc838 ecos-sw-2000-01-24
Merge from eCos master repository on 2000-01-24-19:43:49-GMT
| author | jlarmour |
|---|---|
| date | Mon, 24 Jan 2000 21:43:17 +0000 |
| parents | 443894e2e912 |
| children | c38311975d4f |
| rev | line source |
|---|---|
| 2 | 1 //========================================================================== |
| 2 // | |
| 3 // io/serial/common/tty.c | |
| 4 // | |
| 5 // TTY (terminal-like interface) I/O driver | |
| 6 // | |
| 7 //========================================================================== | |
| 8 //####COPYRIGHTBEGIN#### | |
| 9 // | |
| 10 // ------------------------------------------- | |
| 11 // The contents of this file are subject to the Cygnus eCos Public License | |
| 12 // Version 1.0 (the "License"); you may not use this file except in | |
| 13 // compliance with the License. You may obtain a copy of the License at | |
| 14 // http://sourceware.cygnus.com/ecos | |
| 15 // | |
| 16 // Software distributed under the License is distributed on an "AS IS" | |
| 17 // basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the | |
| 18 // License for the specific language governing rights and limitations under | |
| 19 // the License. | |
| 20 // | |
| 21 // The Original Code is eCos - Embedded Cygnus Operating System, released | |
| 22 // September 30, 1998. | |
| 23 // | |
| 24 // The Initial Developer of the Original Code is Cygnus. Portions created | |
| 25 // by Cygnus are Copyright (C) 1998,1999 Cygnus Solutions. All Rights Reserved. | |
| 26 // ------------------------------------------- | |
| 27 // | |
| 28 //####COPYRIGHTEND#### | |
| 29 //========================================================================== | |
| 30 //#####DESCRIPTIONBEGIN#### | |
| 31 // | |
| 32 // Author(s): gthomas | |
| 33 // Contributors: gthomas | |
| 34 // Date: 1999-02-04 | |
| 35 // Purpose: Device driver for tty I/O, layered on top of serial I/O | |
| 36 // Description: | |
| 37 // | |
| 38 //####DESCRIPTIONEND#### | |
| 39 // | |
| 40 //========================================================================== | |
| 41 | |
| 42 #include <pkgconf/io.h> | |
| 43 #include <pkgconf/io_serial.h> | |
| 44 #ifdef CYGPKG_IO_SERIAL_TTY | |
| 45 #include <cyg/io/io.h> | |
| 46 #include <cyg/io/devtab.h> | |
| 47 #include <cyg/io/ttyio.h> | |
| 48 #include <cyg/infra/diag.h> | |
| 49 | |
| 50 static bool tty_init(struct cyg_devtab_entry *tab); | |
| 51 static Cyg_ErrNo tty_lookup(struct cyg_devtab_entry **tab, | |
| 52 struct cyg_devtab_entry *sub_tab, | |
| 53 const char *name); | |
| 54 static Cyg_ErrNo tty_write(cyg_io_handle_t handle, const void *buf, cyg_uint32 *len); | |
| 55 static Cyg_ErrNo tty_read(cyg_io_handle_t handle, void *buf, cyg_uint32 *len); | |
| 56 static Cyg_ErrNo tty_get_config(cyg_io_handle_t handle, cyg_uint32 key, void *buf, cyg_uint32 *len); | |
| 57 static Cyg_ErrNo tty_set_config(cyg_io_handle_t handle, cyg_uint32 key, const void *buf, cyg_uint32 *len); | |
| 58 | |
| 59 struct tty_private_info { | |
| 60 cyg_tty_info_t dev_info; | |
| 61 cyg_io_handle_t dev_handle; | |
| 62 }; | |
| 63 | |
| 64 static DEVIO_TABLE(tty_devio, | |
| 65 tty_write, | |
| 66 tty_read, | |
| 67 tty_get_config, | |
| 68 tty_set_config | |
| 69 ); | |
| 70 | |
| 71 #ifdef CYGPKG_IO_SERIAL_TTY_TTYDIAG | |
| 72 static struct tty_private_info tty_private_info_diag; | |
| 73 DEVTAB_ENTRY(tty_io_diag, | |
| 74 // "/dev/console", | |
| 75 // CYGDAT_IO_SERIAL_TTY_CONSOLE, // Based on driver for this device | |
| 76 "/dev/ttydiag", | |
| 77 "/dev/haldiag", | |
| 78 &tty_devio, | |
| 79 tty_init, | |
| 80 tty_lookup, // Execute this when device is being looked up | |
| 81 &tty_private_info_diag); | |
| 82 #endif | |
| 83 | |
| 84 #ifdef CYGPKG_IO_SERIAL_TTY_TTY0 | |
| 85 static struct tty_private_info tty_private_info0; | |
| 86 DEVTAB_ENTRY(tty_io0, | |
| 87 "/dev/tty0", | |
| 88 CYGDAT_IO_SERIAL_TTY_TTY0_DEV, | |
| 89 &tty_devio, | |
| 90 tty_init, | |
| 91 tty_lookup, // Execute this when device is being looked up | |
| 92 &tty_private_info0); | |
| 93 #endif | |
| 94 | |
| 95 #ifdef CYGPKG_IO_SERIAL_TTY_TTY1 | |
| 96 static struct tty_private_info tty_private_info1; | |
| 97 DEVTAB_ENTRY(tty_io1, | |
| 98 "/dev/tty1", | |
| 99 CYGDAT_IO_SERIAL_TTY_TTY1_DEV, | |
| 100 &tty_devio, | |
| 101 tty_init, | |
| 102 tty_lookup, // Execute this when device is being looked up | |
| 103 &tty_private_info1); | |
| 104 #endif | |
| 105 | |
| 106 #ifdef CYGPKG_IO_SERIAL_TTY_TTY2 | |
| 107 static struct tty_private_info tty_private_info2; | |
| 108 DEVTAB_ENTRY(tty_io2, | |
| 109 "/dev/tty2", | |
| 110 CYGDAT_IO_SERIAL_TTY_TTY2_DEV, | |
| 111 &tty_devio, | |
| 112 tty_init, | |
| 113 tty_lookup, // Execute this when device is being looked up | |
| 114 &tty_private_info2); | |
| 115 #endif | |
| 116 | |
| 117 static bool | |
| 118 tty_init(struct cyg_devtab_entry *tab) | |
| 119 { | |
| 120 struct tty_private_info *priv = (struct tty_private_info *)tab->priv; | |
| 121 #ifdef CYGDBG_IO_INIT | |
| 122 diag_printf("Init tty channel: %x\n", tab); | |
| 123 #endif | |
| 124 priv->dev_info.tty_out_flags = CYG_TTY_OUT_FLAGS_DEFAULT; | |
| 125 priv->dev_info.tty_in_flags = CYG_TTY_IN_FLAGS_DEFAULT; | |
| 126 return true; | |
| 127 } | |
| 128 | |
| 129 static Cyg_ErrNo | |
| 130 tty_lookup(struct cyg_devtab_entry **tab, | |
| 131 struct cyg_devtab_entry *sub_tab, | |
| 132 const char *name) | |
| 133 { | |
| 134 cyg_io_handle_t chan = (cyg_io_handle_t)sub_tab; | |
| 135 struct tty_private_info *priv = (struct tty_private_info *)(*tab)->priv; | |
| 136 #if 0 | |
| 137 cyg_int32 len; | |
| 138 #endif | |
| 139 priv->dev_handle = chan; | |
| 140 #if 0 | |
| 141 len = sizeof(cyg_serial_info_t); | |
| 142 // Initialize configuration | |
| 143 cyg_io_get_config(chan, CYG_SERIAL_GET_CONFIG, | |
| 144 (void *)&priv->dev_info.serial_config, &len); | |
| 145 #endif | |
| 146 return ENOERR; | |
| 147 } | |
| 148 | |
| 149 #define BUFSIZE 64 | |
| 150 | |
| 151 static Cyg_ErrNo | |
| 152 tty_write(cyg_io_handle_t handle, const void *_buf, cyg_uint32 *len) | |
| 153 { | |
| 154 cyg_devtab_entry_t *t = (cyg_devtab_entry_t *)handle; | |
| 155 struct tty_private_info *priv = (struct tty_private_info *)t->priv; | |
| 156 cyg_io_handle_t chan = (cyg_io_handle_t)priv->dev_handle; | |
| 157 cyg_int32 size, bytes_successful, actually_written; | |
| 158 cyg_uint8 xbuf[BUFSIZE]; | |
| 159 cyg_uint8 c; | |
| 160 cyg_uint8 *buf = (cyg_uint8 *)_buf; | |
| 161 Cyg_ErrNo res = -EBADF; | |
| 162 // assert(chan) | |
| 163 size = 0; | |
| 164 bytes_successful = 0; | |
| 165 actually_written = 0; | |
| 166 while (bytes_successful++ < *len) { | |
| 167 xbuf[size++] = (c = *buf++); | |
| 168 if ((c == '\n') && | |
| 169 (priv->dev_info.tty_out_flags & CYG_TTY_OUT_FLAGS_CRLF)) { | |
| 170 xbuf[size++] = '\r'; | |
| 171 } | |
| 172 // Always leave room for possible CR/LF expansion | |
| 173 if ((size == (BUFSIZE-1)) || | |
| 174 (bytes_successful == *len)) { | |
| 175 res = cyg_io_write(chan, xbuf, &size); | |
| 176 if (res != ENOERR) { | |
| 177 *len = actually_written; | |
| 178 return res; | |
| 179 } | |
| 180 actually_written += size; | |
| 181 size = 0; | |
| 182 } | |
| 183 } | |
| 184 *len = actually_written; | |
| 185 return res; | |
| 186 } | |
| 187 | |
| 188 static Cyg_ErrNo | |
| 189 tty_read(cyg_io_handle_t handle, void *_buf, cyg_uint32 *len) | |
| 190 { | |
| 191 cyg_devtab_entry_t *t = (cyg_devtab_entry_t *)handle; | |
| 192 struct tty_private_info *priv = (struct tty_private_info *)t->priv; | |
| 193 cyg_io_handle_t chan = (cyg_io_handle_t)priv->dev_handle; | |
| 194 cyg_uint32 size, clen; | |
| 195 Cyg_ErrNo res; | |
| 196 cyg_uint8 c; | |
| 197 cyg_uint8 *buf = (cyg_uint8 *)_buf; | |
| 198 // assert(chan) | |
| 199 size = 0; | |
| 200 while (size < *len) { | |
| 201 clen = 1; | |
| 202 res = cyg_io_read(chan, &c, &clen); | |
| 203 if (res != ENOERR) { | |
| 204 *len = size; | |
| 205 return res; | |
| 206 } | |
| 207 buf[size++] = c; | |
| 208 if ((priv->dev_info.tty_in_flags & CYG_TTY_IN_FLAGS_BINARY) == 0) { | |
| 209 if ((c == '\b') || (c == 0x7F)) { | |
| 210 size -= 2; // erase one character + 'backspace' char | |
|
62
7a6ac9edc838
Merge from eCos master repository on 2000-01-24-19:43:49-GMT
jlarmour
parents:
2
diff
changeset
|
211 if (size < 0) { |
|
7a6ac9edc838
Merge from eCos master repository on 2000-01-24-19:43:49-GMT
jlarmour
parents:
2
diff
changeset
|
212 size = 0; |
|
7a6ac9edc838
Merge from eCos master repository on 2000-01-24-19:43:49-GMT
jlarmour
parents:
2
diff
changeset
|
213 } else if (priv->dev_info.tty_in_flags & CYG_TTY_IN_FLAGS_ECHO) { |
| 2 | 214 clen = 3; |
| 215 cyg_io_write(chan, "\b \b", &clen); | |
| 216 } | |
| 217 } else if ((c == '\n') || (c == '\r')) { | |
| 218 clen = 2; | |
| 219 if (priv->dev_info.tty_in_flags & CYG_TTY_IN_FLAGS_ECHO) { | |
| 220 cyg_io_write(chan, "\n\r", &clen); | |
| 221 } | |
| 222 if (priv->dev_info.tty_in_flags & CYG_TTY_IN_FLAGS_CRLF) { | |
| 223 c = '\n'; // Map CR -> LF | |
| 224 } | |
| 225 buf[size-1] = c; | |
| 226 break; | |
| 227 } else { | |
| 228 if (priv->dev_info.tty_in_flags & CYG_TTY_IN_FLAGS_ECHO) { | |
| 229 clen = 1; | |
| 230 cyg_io_write(chan, &c, &clen); | |
| 231 } | |
| 232 } | |
| 233 } | |
| 234 } | |
| 235 *len = size; | |
| 236 return ENOERR; | |
| 237 } | |
| 238 | |
| 239 static Cyg_ErrNo | |
| 240 tty_get_config(cyg_io_handle_t handle, cyg_uint32 key, void *buf, cyg_uint32 *len) | |
| 241 { | |
| 242 cyg_devtab_entry_t *t = (cyg_devtab_entry_t *)handle; | |
| 243 struct tty_private_info *priv = (struct tty_private_info *)t->priv; | |
| 244 cyg_io_handle_t chan = (cyg_io_handle_t)priv->dev_handle; | |
| 245 Cyg_ErrNo res = ENOERR; | |
| 246 #if 0 | |
| 247 cyg_int32 current_len; | |
| 248 #endif | |
| 249 // assert(chan) | |
| 250 switch (key) { | |
| 251 case CYG_IO_GET_CONFIG_TTY_INFO: | |
| 252 if (*len < sizeof(cyg_tty_info_t)) { | |
| 253 return -EINVAL; | |
| 254 } | |
| 255 #if 0 | |
| 256 current_len = sizeof(cyg_serial_info_t); | |
| 257 res = cyg_io_get_config(chan, CYG_SERIAL_GET_CONFIG, | |
| 258 (void *)&priv->dev_info.serial_config, ¤t_len); | |
| 259 if (res != ENOERR) { | |
| 260 return res; | |
| 261 } | |
| 262 #endif | |
| 263 *(cyg_tty_info_t *)buf = priv->dev_info; | |
| 264 *len = sizeof(cyg_tty_info_t); | |
| 265 break; | |
| 266 default: // Assume this is a 'serial' driver control | |
| 267 res = cyg_io_get_config(chan, key, buf, len); | |
| 268 } | |
| 269 return res; | |
| 270 } | |
| 271 | |
| 272 static Cyg_ErrNo | |
| 273 tty_set_config(cyg_io_handle_t handle, cyg_uint32 key, const void *buf, cyg_uint32 *len) | |
| 274 { | |
| 275 cyg_devtab_entry_t *t = (cyg_devtab_entry_t *)handle; | |
| 276 struct tty_private_info *priv = (struct tty_private_info *)t->priv; | |
| 277 cyg_io_handle_t chan = (cyg_io_handle_t)priv->dev_handle; | |
| 278 #if 0 | |
| 279 cyg_int32 current_len; | |
| 280 #endif | |
| 281 Cyg_ErrNo res = ENOERR; | |
| 282 // assert(chan) | |
| 283 switch (key) { | |
| 284 case CYG_IO_SET_CONFIG_TTY_INFO: | |
| 285 if (*len != sizeof(cyg_tty_info_t)) { | |
| 286 return -EINVAL; | |
| 287 } | |
| 288 priv->dev_info = *(cyg_tty_info_t *)buf; | |
| 289 break; | |
| 290 default: // Pass on to serial driver | |
| 291 res = cyg_io_set_config(chan, key, buf, len); | |
| 292 } | |
| 293 return res; | |
| 294 } | |
| 295 #endif // CYGPKG_IO_SERIAL_TTY |
