📄 console.c
字号:
break; case '=': /* Appl. keypad */ set_kbd(kbdapplic); break; } return 0;}static int con_write_ctrl_ESnonstd(int currcons, struct tty_struct *tty, unsigned int c){ switch (c) { case 'P': /* palette escape sequence */ for (npar=0; npar<NPAR; npar++) par[npar] = 0 ; npar = 0 ; vc_state = con_write_ctrl_ESpalette; break; case 'R': /* reset palette */ reset_palette (currcons); default: vc_state = con_write_ctrl_ESnormal; } return 0;}static int con_write_ctrl_ESpalette(int currcons, struct tty_struct *tty, unsigned int c){ if ( (c>='0'&&c<='9') || (c>='A'&&c<='F') || (c>='a'&&c<='f') ) { par[npar++] = (c>'9' ? (c&0xDF)-'A'+10 : c-'0') ; if (npar==7) { int i = par[0]*3, j = 1; palette[i] = 16*par[j++]; palette[i++] += par[j++]; palette[i] = 16*par[j++]; palette[i++] += par[j++]; palette[i] = 16*par[j++]; palette[i] += par[j]; set_palette(currcons); vc_state = con_write_ctrl_ESnormal; } } else vc_state = con_write_ctrl_ESnormal; return 0;}static int con_write_ctrl_ESsquare(int currcons, struct tty_struct *tty, unsigned int c){ for(npar = 0 ; npar < NPAR ; npar++) par[npar] = 0; npar = 0; vc_state = con_write_ctrl_ESgetpars; if (c == '[') { /* Function key */ vc_state = con_write_ctrl_ESfunckey; return 0; } ques = (c=='?'); if (ques) return 0; return con_write_ctrl_ESgetpars(currcons, tty, c);}static int con_write_ctrl_ESgetpars(int currcons, struct tty_struct *tty, unsigned int c){ if (c==';' && npar<NPAR-1) { npar++; return 0; } else if (c>='0' && c<='9') { par[npar] *= 10; par[npar] += c-'0'; return 0; } else vc_state = con_write_ctrl_ESgotpars; return con_write_ctrl_ESgotpars(currcons, tty, c);}static int con_write_ctrl_ESgotpars(int currcons, struct tty_struct *tty, unsigned int c){ vc_state = con_write_ctrl_ESnormal; switch(c) { case 'h': set_mode(currcons,1); return 0; case 'l': set_mode(currcons,0); return 0; case 'c': if (ques) { if (par[0]) cursor_type = par[0] | (par[1]<<8) | (par[2]<<16); else cursor_type = CUR_DEFAULT; return 0; } break; case 'm': if (ques) { clear_selection(); if (par[0]) complement_mask = par[0]<<8 | par[1]; else complement_mask = s_complement_mask; return 0; } break; case 'n': if (!ques) { if (par[0] == 5) status_report(tty); else if (par[0] == 6) cursor_report(currcons,tty); } return 0; } if (ques) { ques = 0; return 0; } switch(c) { case 'G': case '`': if (par[0]) par[0]--; gotoxy(currcons,par[0],y); break; case 'A': if (!par[0]) par[0]++; gotoxy(currcons,x,y-par[0]); break; case 'B': case 'e': if (!par[0]) par[0]++; gotoxy(currcons,x,y+par[0]); break; case 'C': case 'a': if (!par[0]) par[0]++; gotoxy(currcons,x+par[0],y); break; case 'D': if (!par[0]) par[0]++; gotoxy(currcons,x-par[0],y); break; case 'E': if (!par[0]) par[0]++; gotoxy(currcons,0,y+par[0]); break; case 'F': if (!par[0]) par[0]++; gotoxy(currcons,0,y-par[0]); break; case 'd': if (par[0]) par[0]--; gotoxay(currcons,x,par[0]); break; case 'H': case 'f': if (par[0]) par[0]--; if (par[1]) par[1]--; gotoxay(currcons,par[1],par[0]); break; case 'J': csi_J(currcons,par[0]); break; case 'K': csi_K(currcons,par[0]); break; case 'L': csi_L(currcons,par[0]); break; case 'M': csi_M(currcons,par[0]); break; case 'P': csi_P(currcons,par[0]); break; case 'c': if (!par[0]) respond_ID(tty); break; case 'g': if (!par[0]) tab_stop[x >> 5] &= ~(1 << (x & 31)); else if (par[0] == 3) { tab_stop[0] = tab_stop[1] = tab_stop[2] = tab_stop[3] = tab_stop[4] = 0; } break; case 'm': csi_m(currcons); return 1; case 'q': /* DECLL - but only 3 leds */ /* map 0,1,2,3 to 0,1,2,4 */ if (par[0] < 4) setledstate(kbd_table + currcons, (par[0] < 3) ? par[0] : 4); break; case 'r': if (!par[0]) par[0]++; if (!par[1]) par[1] = video_num_lines; /* Minimum allowed region is 2 lines */ if (par[0] < par[1] && par[1] <= video_num_lines) { top=par[0]-1; bottom=par[1]; gotoxay(currcons,0,0); } break; case 's': save_cur(currcons); break; case 'u': restore_cur(currcons); return 1; case 'X': csi_X(currcons, par[0]); break; case '@': csi_at(currcons,par[0]); break; case ']': /* setterm functions */ setterm_command(currcons); break; } return 0;}static int con_write_ctrl_ESpercent(int currcons, struct tty_struct *tty, unsigned int c){ vc_state = con_write_ctrl_ESnormal; switch (c) { case '@': /* defined in ISO 2022 */ utf = 0; break; case 'G': /* prelim official escape code */ case '8': /* retained for compatibility */ utf = 1; break; } return 0;}static int con_write_ctrl_ESfunckey(int currcons, struct tty_struct *tty, unsigned int c){ vc_state = con_write_ctrl_ESnormal; return 0;}static int con_write_ctrl_EShash(int currcons, struct tty_struct *tty, unsigned int c){ vc_state = con_write_ctrl_ESnormal; if (c == '8') { /* DEC screen alignment test. kludge :-) */ video_erase_char = (video_erase_char & 0xff00) | 'E'; csi_J(currcons, 2); video_erase_char = (video_erase_char & 0xff00) | ' '; do_update_region(currcons, origin, screenbuf_size/2); } return 0;}static int con_write_ctrl_ESsetG0(int currcons, struct tty_struct *tty, unsigned int c){ switch (c) { case '0': G0_charset = GRAF_MAP; break; case 'B': G0_charset = LAT1_MAP; break; case 'U': G0_charset = IBMPC_MAP; break; case 'K': G0_charset = USER_MAP; break; } if (charset == 0) { translate = set_translate(G0_charset,currcons); return 1; } vc_state = con_write_ctrl_ESnormal; return 0;}static int con_write_ctrl_ESsetG1(int currcons, struct tty_struct *tty, unsigned int c){ switch (c) { case '0': G1_charset = GRAF_MAP; break; case 'B': G1_charset = LAT1_MAP; break; case 'U': G1_charset = IBMPC_MAP; break; case 'K': G1_charset = USER_MAP; break; } if (charset == 1) { translate = set_translate(G1_charset,currcons); return 1; } vc_state = con_write_ctrl_ESnormal; return 0;}/* This is a temporary buffer used to prepare a tty console write * so that we can easily avoid touching user space while holding the * console spinlock. It is allocated in con_init and is shared by * this code and the vc_screen read/write tty calls. * * We have to allocate this statically in the kernel data section * since console_init (and thus con_init) are called before any * kernel memory allocation is available. */char con_buf[PAGE_SIZE];#define CON_BUF_SIZE PAGE_SIZEDECLARE_MUTEX(con_buf_sem);/* acquires console_sem */static int do_con_write(struct tty_struct * tty, int from_user, const unsigned char *buf, int count){#ifdef VT_BUF_VRAM_ONLY#define FLUSH do { } while(0);#else#define FLUSH if (draw_x >= 0) { \ sw->con_putcs(vc_cons[currcons].d, (u16 *)draw_from, (u16 *)draw_to-(u16 *)draw_from, y, draw_x); \ draw_x = -1; \ }#endif int c, tc, ok, n = 0, draw_x = -1; unsigned int currcons; unsigned long draw_from = 0, draw_to = 0; struct vt_struct *vt = (struct vt_struct *)tty->driver_data; u16 himask, charmask; const unsigned char *orig_buf; int orig_count; if (in_interrupt()) return count; currcons = vt->vc_num; if (!vc_cons_allocated(currcons)) { /* could this happen? */ static int error = 0; if (!error) { error = 1; printk("con_write: tty %d not allocated\n", currcons+1); } return 0; } orig_buf = buf; orig_count = count; if (from_user) { down(&con_buf_sem);again: if (count > CON_BUF_SIZE) count = CON_BUF_SIZE; console_conditional_schedule(); if (copy_from_user(con_buf, buf, count)) { n = 0; /* ?? are error codes legal here ?? */ goto out; } buf = con_buf; } /* At this point 'buf' is guarenteed to be a kernel buffer * and therefore no access to userspace (and therefore sleeping) * will be needed. The con_buf_sem serializes all tty based * console rendering and vcs write/read operations. We hold * the console spinlock during the entire write. */ acquire_console_sem(); himask = hi_font_mask; charmask = himask ? 0x1ff : 0xff; /* undraw cursor first */ if (IS_FG) hide_cursor(currcons); while (!tty->stopped && count) { c = *buf; buf++; n++; count--; if (utf) { tc = con_write_utf(currcons, c); if (tc < 0) continue; c = tc; } else /* no utf */ tc = translate[toggle_meta ? (c|0x80) : c]; /* If the original code was a control character we * only allow a glyph to be displayed if the code is * not normally used (such as for cursor movement) or * if the disp_ctrl mode has been explicitly enabled. * Certain characters (as given by the CTRL_ALWAYS * bitmap) are always displayed as control characters, * as the console would be pretty useless without * them; to display an arbitrary font position use the * direct-to-font zone in UTF-8 mode. */ ok = tc && (c >= 32 || (!utf && !(((disp_ctrl ? CTRL_ALWAYS : CTRL_ACTION) >> c) & 1))) && (c != 127 || disp_ctrl) && (c != 128+27); if (vc_state == con_write_ctrl_ESnormal && ok) { /* Now try to find out how to display it */ tc = conv_uni_to_pc(vc_cons[currcons].d, tc); if ( tc == -4 ) { /* If we got -4 (not found) then see if we have defined a replacement character (U+FFFD) */ tc = conv_uni_to_pc(vc_cons[currcons].d, 0xfffd); /* One reason for the -4 can be that we just did a clear_unimap(); try at least to show something. */ if (tc == -4) tc = c; } else if ( tc == -3 ) { /* Bad hash table -- hope for the best */ tc = c; } if (tc & ~charmask) continue; /* Conversion failed */ if (need_wrap || decim) FLUSH if (need_wrap) { cr(currcons); lf(currcons); } if (decim) insert_char(currcons, 1); scr_writew(himask ? ((attr << 8) & ~himask) + ((tc & 0x100) ? himask : 0) + (tc & 0xff) : (attr << 8) + tc, (u16 *) pos); if (DO_UPDATE && draw_x < 0) { draw_x = x; draw_from = pos; } if (x == video_num_columns - 1) { need_wrap = decawm; draw_to = pos+2; } else { x++; draw_to = (pos+=2); } continue; } FLUSH do_con_trol(tty, currcons, c); } FLUSH console_conditional_schedule(); release_console_sem();out: if (from_user) { /* If the user requested something larger than * the CON_BUF_SIZE, and the tty is not stopped, * keep going. */ if ((orig_count > CON_BUF_SIZE) && !tty->stopped) { orig_count -= CON_BUF_SIZE; orig_buf += CON_BUF_SIZE; count = orig_count; buf = orig_buf; goto again; } up(&con_buf_sem); } return n;#undef FLUSH}/* * This is the console switching callback. * * Doing console switching in a process context allows * us to do the switches asynchronously (needed when we want * to switch due to a keyboard interrupt). Synchronization * with other console code and prevention of re-entrancy is * ensured with console_sem. */static void console_callback(void *ignored){ acquire_console_sem(); if (want_console >= 0) { if (want_console != fg_console && vc_cons_allocated(want_console)) { hide_cursor(fg_console); change_console(want_console); /* we only changed when the console had already been allocated - a new console is not created in an interrupt routine */ } want_console = -1; }#ifdef CONFIG_CONSOLE_PM // bushi if (do_poke_blanked_console) { /* do not unblank for a LED change */ do_poke_blanked_console = 0; poke_blanked_console(); }#endif if (scrollback_delta) { int currcons = fg_console; clear_selection(); if (vcmode == KD_TEXT) sw->con_scrolldelta(vc_cons[currcons].d, scrollback_delta); scrollback_delta = 0; } release_console_sem();}void set_console(int nr){ want_console = nr; schedule_console_callback();}#ifdef CONFIG_VT_CONSOLE/* * Console on virtual terminal * * The console must be locked when we get here. */void vt_console_print(struct console *co, const char * b, unsigned count){
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -