// // Console input and output, to the uart. // Reads are line at a time. // Implements special input characters: // newline -- end of line // control-h -- backspace // control-u -- kill line // control-d -- end of file // control-p -- print process list // #include #include "types.h" #include "param.h" #include "spinlock.h" #include "sleeplock.h" #include "fs.h" #include "file.h" #include "memlayout.h" #include "riscv.h" #include "defs.h" #include "proc.h" #define BACKSPACE 0x100 #define INPUT_BUF_SIZE 128 #define C(x) ((x)-'@') // Control-x struct console { struct spinlock lock; // input char buf[INPUT_BUF_SIZE]; uint r; // Read index uint w; // Write index uint e; // Edit index }; extern struct console cons; void consputc(int c); int consolewrite(int user_src, uint64 src, int n); int consoleread(int user_dst, uint64 dst, int n); void consoleintr(int c) { acquire(&cons.lock); switch(c){ case C('P'): // Print process list. procdump(); break; case C('U'): // Kill line. while(cons.e != cons.w && cons.buf[(cons.e-1) % INPUT_BUF_SIZE] != '\n'){ cons.e--; consputc(BACKSPACE); } break; case C('H'): // Backspace case '\x7f': // Delete key if(cons.e != cons.w){ cons.e--; consputc(BACKSPACE); } break; default: if(c != 0 && cons.e-cons.r < INPUT_BUF_SIZE){ c = (c == '\r') ? '\n' : c; // echo back to the user. consputc(c); // store for consumption by consoleread(). cons.buf[cons.e++ % INPUT_BUF_SIZE] = c; if(c == '\n' || c == C('D') || cons.e-cons.r == INPUT_BUF_SIZE){ // wake up consoleread() if a whole line (or end-of-file) // has arrived. cons.w = cons.e; wakeup(&cons.r); } } break; } release(&cons.lock); }