00001 00007 /* Embedded XINU, Copyright (C) 2007. All rights reserved. */ 00008 00009 #include <kernel.h> 00010 #include <device.h> 00011 #include <tty.h> 00012 00031 devcall ttyRead(device *pdev, char *buf, ushort len) 00032 { 00033 struct tty *ptty; 00034 device *phw; 00035 long c = 0; 00036 ushort count = 0; 00037 00038 /* Setup and error check pointers to structures */ 00039 ptty = (struct tty *)pdev->controlblk; 00040 ASSERT((NULL != ptty) && (TTY_STATE_ALLOC == ptty->state)); 00041 00042 phw = ptty->tty_phw; 00043 ASSERT(NULL != phw); 00044 00045 /* Check for EOF */ 00046 if (ptty->iflags & TTY_IFLAG_EOF) 00047 { 00048 return EOF; 00049 } 00050 00051 /* If the tty's input buffer is empty, read the next line */ 00052 /* from the underlying device into the tty's input buffer */ 00053 if (ptty->icount == 0) 00054 { 00055 /* Read characters from the underlying device while there */ 00056 /* is space in the tty's input buffer and a CR, LF, or */ 00057 /* EOT (Ctrl+D) character has not been encountered */ 00058 while (ptty->icount < TTY_IBLEN) 00059 { 00060 /* Read character from underlying device */ 00061 if (SYSERR == (c = (*phw->getc)(phw))) { break; } 00062 00063 /* If not in RAW mode, then 'cook' special characters */ 00064 if (!(ptty->iflags & TTY_IFLAG_RAW)) 00065 { 00066 /* Cook backspace and delete */ 00067 if (('\b' == c) 00068 || (0x7F == c)) 00069 { 00070 if (ptty->icount > 0) 00071 { 00072 ptty->icount--; 00073 if (ptty->iflags & TTY_IFLAG_ECHO) 00074 { ttyPutChar(ptty->tty_dev, c); } 00075 } 00076 continue; 00077 } 00078 00079 /* Drop escape sequences */ 00080 if (0x1B == c) 00081 { 00082 if (SYSERR == (c = (*phw->getc)(phw))) { break; } 00083 if (SYSERR == (c = (*phw->getc)(phw))) { break; } 00084 continue; 00085 } 00086 00087 /* Drop null characters */ 00088 if ('\0' == c) 00089 { continue; } 00090 } 00091 00092 /* Add character to input buffer */ 00093 ptty->inbuf[(ptty->istart + ptty->icount) % TTY_IBLEN] = c; 00094 ptty->icount++; 00095 00096 /* If echo is enabled, echo the character */ 00097 if (ptty->iflags & TTY_IFLAG_ECHO) 00098 { ttyPutChar(ptty->tty_dev, c); } 00099 00100 /* Stop reading into input buffer if CR, LF, or end of file */ 00101 if (('\r' == c) 00102 || ('\n' == c) 00103 || (0x04 == c)) 00104 { break; } 00105 } 00106 } 00107 00108 ptty->iflags &= ~TTY_IFLAG_CBREAK; /* Clear break (Control-C) flag */ 00109 ptty->iflags &= ~TTY_IFLAG_EOF; /* Clear EOF (Control-D) flag */ 00110 00111 /* Satisfy read request from input buffer */ 00112 while ((count < len) && (ptty->icount > 0)) 00113 { 00114 /* Check for Break character (Control-C) and set flag */ 00115 if (0x03 == c) 00116 { ptty->iflags |= TTY_IFLAG_CBREAK; } 00117 00118 /* Check for EOF character (Control-D) and set flag */ 00119 if (0x04 == c) 00120 { 00121 ptty->iflags |= TTY_IFLAG_EOF; 00122 len = count; 00123 } 00124 00125 /* Read from input buffer into user buffer; Preserve circular buffer */ 00126 *buf++ = ptty->inbuf[ptty->istart]; 00127 ptty->icount--; 00128 ptty->istart = (ptty->istart + 1) % TTY_IBLEN; 00129 count++; 00130 } 00131 00132 return count; 00133 }