📄 tty3270.c
字号:
tty3270_erase_line(struct tty3270 *tp, int mode){ struct tty3270_line *line; struct tty3270_cell *cell; int i; line = tp->screen + tp->cy; if (mode == 0) line->len = tp->cx; else if (mode == 1) { for (i = 0; i < tp->cx; i++) { cell = line->cells + i; cell->character = ' '; cell->highlight = TAX_RESET; cell->f_color = TAC_RESET; } if (line->len <= tp->cx) line->len = tp->cx + 1; } else if (mode == 2) line->len = 0; tty3270_convert_line(tp, tp->cy);}/* * Erase display, 3 different cases: * Esc [ 0 J Erase from current position to bottom of screen inclusive * Esc [ 1 J Erase from top of screen to current position inclusive * Esc [ 2 J Erase entire screen (without moving the cursor) */static voidtty3270_erase_display(struct tty3270 *tp, int mode){ int i; if (mode == 0) { tty3270_erase_line(tp, 0); for (i = tp->cy + 1; i < tp->view.rows - 2; i++) { tp->screen[i].len = 0; tty3270_convert_line(tp, i); } } else if (mode == 1) { for (i = 0; i < tp->cy; i++) { tp->screen[i].len = 0; tty3270_convert_line(tp, i); } tty3270_erase_line(tp, 1); } else if (mode == 2) { for (i = 0; i < tp->view.rows - 2; i++) { tp->screen[i].len = 0; tty3270_convert_line(tp, i); } } tty3270_rebuild_update(tp);}/* * Set attributes found in an escape sequence. * Esc [ <attr> ; <attr> ; ... m */static voidtty3270_set_attributes(struct tty3270 *tp){ static unsigned char f_colors[] = { TAC_DEFAULT, TAC_RED, TAC_GREEN, TAC_YELLOW, TAC_BLUE, TAC_PINK, TAC_TURQ, TAC_WHITE, 0, TAC_DEFAULT }; int i, attr; for (i = 0; i <= tp->esc_npar; i++) { attr = tp->esc_par[i]; switch (attr) { case 0: /* Reset */ tp->highlight = TAX_RESET; tp->f_color = TAC_RESET; break; /* Highlight. */ case 4: /* Start underlining. */ tp->highlight = TAX_UNDER; break; case 5: /* Start blink. */ tp->highlight = TAX_BLINK; break; case 7: /* Start reverse. */ tp->highlight = TAX_REVER; break; case 24: /* End underlining */ if (tp->highlight == TAX_UNDER) tp->highlight = TAX_RESET; break; case 25: /* End blink. */ if (tp->highlight == TAX_BLINK) tp->highlight = TAX_RESET; break; case 27: /* End reverse. */ if (tp->highlight == TAX_REVER) tp->highlight = TAX_RESET; break; /* Foreground color. */ case 30: /* Black */ case 31: /* Red */ case 32: /* Green */ case 33: /* Yellow */ case 34: /* Blue */ case 35: /* Magenta */ case 36: /* Cyan */ case 37: /* White */ case 39: /* Black */ tp->f_color = f_colors[attr - 30]; break; } }}static inline inttty3270_getpar(struct tty3270 *tp, int ix){ return (tp->esc_par[ix] > 0) ? tp->esc_par[ix] : 1;}static voidtty3270_goto_xy(struct tty3270 *tp, int cx, int cy){ tp->cx = min_t(int, tp->view.cols - 1, max_t(int, 0, cx)); cy = min_t(int, tp->view.rows - 3, max_t(int, 0, cy)); if (cy != tp->cy) { tty3270_convert_line(tp, tp->cy); tp->cy = cy; }}/* * Process escape sequences. Known sequences: * Esc 7 Save Cursor Position * Esc 8 Restore Cursor Position * Esc [ Pn ; Pn ; .. m Set attributes * Esc [ Pn ; Pn H Cursor Position * Esc [ Pn ; Pn f Cursor Position * Esc [ Pn A Cursor Up * Esc [ Pn B Cursor Down * Esc [ Pn C Cursor Forward * Esc [ Pn D Cursor Backward * Esc [ Pn G Cursor Horizontal Absolute * Esc [ Pn X Erase Characters * Esc [ Ps J Erase in Display * Esc [ Ps K Erase in Line * // FIXME: add all the new ones. * * Pn is a numeric parameter, a string of zero or more decimal digits. * Ps is a selective parameter. */static voidtty3270_escape_sequence(struct tty3270 *tp, char ch){ enum { ESnormal, ESesc, ESsquare, ESgetpars }; if (tp->esc_state == ESnormal) { if (ch == 0x1b) /* Starting new escape sequence. */ tp->esc_state = ESesc; return; } if (tp->esc_state == ESesc) { tp->esc_state = ESnormal; switch (ch) { case '[': tp->esc_state = ESsquare; break; case 'E': tty3270_cr(tp); tty3270_lf(tp); break; case 'M': tty3270_ri(tp); break; case 'D': tty3270_lf(tp); break; case 'Z': /* Respond ID. */ kbd_puts_queue(tp->tty, "\033[?6c"); break; case '7': /* Save cursor position. */ tp->saved_cx = tp->cx; tp->saved_cy = tp->cy; tp->saved_highlight = tp->highlight; tp->saved_f_color = tp->f_color; break; case '8': /* Restore cursor position. */ tty3270_convert_line(tp, tp->cy); tty3270_goto_xy(tp, tp->saved_cx, tp->saved_cy); tp->highlight = tp->saved_highlight; tp->f_color = tp->saved_f_color; break; case 'c': /* Reset terminal. */ tp->cx = tp->saved_cx = 0; tp->cy = tp->saved_cy = 0; tp->highlight = tp->saved_highlight = TAX_RESET; tp->f_color = tp->saved_f_color = TAC_RESET; tty3270_erase_display(tp, 2); break; } return; } if (tp->esc_state == ESsquare) { tp->esc_state = ESgetpars; memset(tp->esc_par, 0, sizeof(tp->esc_par)); tp->esc_npar = 0; tp->esc_ques = (ch == '?'); if (tp->esc_ques) return; } if (tp->esc_state == ESgetpars) { if (ch == ';' && tp->esc_npar < ESCAPE_NPAR - 1) { tp->esc_npar++; return; } if (ch >= '0' && ch <= '9') { tp->esc_par[tp->esc_npar] *= 10; tp->esc_par[tp->esc_npar] += ch - '0'; return; } } tp->esc_state = ESnormal; if (ch == 'n' && !tp->esc_ques) { if (tp->esc_par[0] == 5) /* Status report. */ kbd_puts_queue(tp->tty, "\033[0n"); else if (tp->esc_par[0] == 6) { /* Cursor report. */ char buf[40]; sprintf(buf, "\033[%d;%dR", tp->cy + 1, tp->cx + 1); kbd_puts_queue(tp->tty, buf); } return; } if (tp->esc_ques) return; switch (ch) { case 'm': tty3270_set_attributes(tp); break; case 'H': /* Set cursor position. */ case 'f': tty3270_goto_xy(tp, tty3270_getpar(tp, 1) - 1, tty3270_getpar(tp, 0) - 1); break; case 'd': /* Set y position. */ tty3270_goto_xy(tp, tp->cx, tty3270_getpar(tp, 0) - 1); break; case 'A': /* Cursor up. */ case 'F': tty3270_goto_xy(tp, tp->cx, tp->cy - tty3270_getpar(tp, 0)); break; case 'B': /* Cursor down. */ case 'e': case 'E': tty3270_goto_xy(tp, tp->cx, tp->cy + tty3270_getpar(tp, 0)); break; case 'C': /* Cursor forward. */ case 'a': tty3270_goto_xy(tp, tp->cx + tty3270_getpar(tp, 0), tp->cy); break; case 'D': /* Cursor backward. */ tty3270_goto_xy(tp, tp->cx - tty3270_getpar(tp, 0), tp->cy); break; case 'G': /* Set x position. */ case '`': tty3270_goto_xy(tp, tty3270_getpar(tp, 0), tp->cy); break; case 'X': /* Erase Characters. */ tty3270_erase_characters(tp, tty3270_getpar(tp, 0)); break; case 'J': /* Erase display. */ tty3270_erase_display(tp, tp->esc_par[0]); break; case 'K': /* Erase line. */ tty3270_erase_line(tp, tp->esc_par[0]); break; case 'P': /* Delete characters. */ tty3270_delete_characters(tp, tty3270_getpar(tp, 0)); break; case '@': /* Insert characters. */ tty3270_insert_characters(tp, tty3270_getpar(tp, 0)); break; case 's': /* Save cursor position. */ tp->saved_cx = tp->cx; tp->saved_cy = tp->cy; tp->saved_highlight = tp->highlight; tp->saved_f_color = tp->f_color; break; case 'u': /* Restore cursor position. */ tty3270_convert_line(tp, tp->cy); tty3270_goto_xy(tp, tp->saved_cx, tp->saved_cy); tp->highlight = tp->saved_highlight; tp->f_color = tp->saved_f_color; break; }}/* * String write routine for 3270 ttys */static voidtty3270_do_write(struct tty3270 *tp, const unsigned char *buf, int count){ int i_msg, i; spin_lock_bh(&tp->view.lock); for (i_msg = 0; !tp->tty->stopped && i_msg < count; i_msg++) { if (tp->esc_state != 0) { /* Continue escape sequence. */ tty3270_escape_sequence(tp, buf[i_msg]); continue; } switch (buf[i_msg]) { case 0x07: /* '\a' -- Alarm */ tp->wcc |= TW_PLUSALARM; break; case 0x08: /* Backspace. */ if (tp->cx > 0) { tp->cx--; tty3270_put_character(tp, ' '); } break; case 0x09: /* '\t' -- Tabulate */ for (i = tp->cx % 8; i < 8; i++) { if (tp->cx >= tp->view.cols) { tty3270_cr(tp); tty3270_lf(tp); break; } tty3270_put_character(tp, ' '); tp->cx++; } break; case 0x0a: /* '\n' -- New Line */ tty3270_cr(tp); tty3270_lf(tp); break; case 0x0c: /* '\f' -- Form Feed */ tty3270_erase_display(tp, 2); tp->cx = tp->cy = 0; break; case 0x0d: /* '\r' -- Carriage Return */ tp->cx = 0; break; case 0x0f: /* SuSE "exit alternate mode" */ break; case 0x1b: /* Start escape sequence. */ tty3270_escape_sequence(tp, buf[i_msg]); break; default: /* Insert normal character. */ if (tp->cx >= tp->view.cols) { tty3270_cr(tp); tty3270_lf(tp); } tty3270_put_character(tp, buf[i_msg]); tp->cx++; break; } } /* Convert current line to 3270 data fragment. */ tty3270_convert_line(tp, tp->cy); /* Setup timer to update display after 1/10 second */ if (!timer_pending(&tp->timer)) tty3270_set_timer(tp, HZ/10); spin_unlock_bh(&tp->view.lock);}/* * String write routine for 3270 ttys */static inttty3270_write(struct tty_struct * tty, const unsigned char *buf, int count){ struct tty3270 *tp; tp = tty->driver_data; if (!tp) return 0; if (tp->char_count > 0) { tty3270_do_write(tp, tp->char_buf, tp->char_count); tp->char_count = 0; } tty3270_do_write(tp, buf, count); return count;}/* * Put single characters to the ttys character buffer */static voidtty3270_put_char(struct tty_struct *tty, unsigned char ch){ struct tty3270 *tp; tp = tty->driver_data; if (!tp) return; if (tp->char_count < TTY3270_CHAR_BUF_SIZE) tp->char_buf[tp->char_count++] = ch;}/* * Flush all characters from the ttys characeter buffer put there * by tty3270_put_char. */static voidtty3270_flush_chars(struct tty_struct *tty){ struct tty3270 *tp; tp = tty->driver_data; if (!tp) return; if (tp->char_count > 0) { tty3270_do_write(tp, tp->char_buf, tp->char_count); tp->char_count = 0; }}/* * Returns the number of characters in the output buffer. This is * used in tty_wait_until_sent to wait until all characters have * appeared on the screen. */static inttty3270_chars_in_buffer(struct tty_struct *tty){ return 0;}static voidtty3270_flush_buffer(struct tty_struct *tty){}/* * Check for visible/invisible input switches */static voidtty3270_set_termios(struct tty_struct *tty, struct termios *old){ struct tty3270 *tp; int new; tp = tty->driver_data; if (!tp) return; spin_lock_bh(&tp->view.lock); if (L_ICANON(tty)) { new = L_ECHO(tty) ? TF_INPUT: TF_INPUTN; if (new != tp->inattr) { tp->inattr = new; tty3270_update_prompt(tp, 0, 0); tty3270_set_timer(tp, 1); } } spin_unlock_bh(&tp->view.lock);}/* * Disable reading from a 3270 tty */static voidtty3270_throttle(struct tty_struct * tty){ struct tty3270 *tp; tp = tty->driver_data; if (!tp) return; tp->throttle = 1;}/* * Enable reading from a 3270 tty */static voidtty3270_unthrottle(struct tty_struct * tty){ struct tty3270 *tp; tp = tty->driver_data; if (!tp) return; tp->throttle = 0; if (tp->attn) tty3270_issue_read(tp, 1);}/* * Hang up the tty device. */static voidtty3270_hangup(struct tty_struct *tty){ // FIXME: implement}static voidtty3270_wait_until_sent(struct tty_struct *tty, int timeout){}static inttty3270_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg){ struct tty3270 *tp; tp = tty->driver_data; if (!tp) return -ENODEV; if (tty->flags & (1 << TTY_IO_ERROR)) return -EIO; return kbd_ioctl(tp->kbd, file, cmd, arg);}static struct tty_operations tty3270_ops = { .open = tty3270_open, .close = tty3270_close, .write = tty3270_write, .put_char = tty3270_put_char, .flush_chars = tty3270_flush_chars, .write_room = tty3270_write_room, .chars_in_buffer = tty3270_chars_in_buffer, .flush_buffer = tty3270_flush_buffer, .throttle = tty3270_throttle, .unthrottle = tty3270_unthrottle, .hangup = tty3270_hangup, .wait_until_sent = tty3270_wait_until_sent, .ioctl = tty3270_ioctl, .set_termios = tty3270_set_termios};voidtty3270_notifier(int index, int active){ if (active) tty_register_device(tty3270_driver, index, 0); else tty_unregister_device(tty3270_driver, index);}/* * 3270 tty registration code called from tty_init(). * Most kernel services (incl. kmalloc) are available at this poimt. */int __inittty3270_init(void){ struct tty_driver *driver; int ret; driver = alloc_tty_driver(RAW3270_MAXDEVS); if (!driver) return -ENOMEM; /* * Initialize the tty_driver structure * Entries in tty3270_driver that are NOT initialized: * proc_entry, set_termios, flush_buffer, set_ldisc, write_proc */ driver->owner = THIS_MODULE; driver->devfs_name = "ttyTUB/"; driver->driver_name = "ttyTUB"; driver->name = "ttyTUB"; driver->major = IBM_TTY3270_MAJOR; driver->minor_start = RAW3270_FIRSTMINOR; driver->type = TTY_DRIVER_TYPE_SYSTEM; driver->subtype = SYSTEM_TYPE_TTY; driver->init_termios = tty_std_termios; driver->flags = TTY_DRIVER_RESET_TERMIOS | TTY_DRIVER_NO_DEVFS; tty_set_operations(driver, &tty3270_ops); ret = tty_register_driver(driver); if (ret) { printk(KERN_ERR "tty3270 registration failed with %d\n", ret); put_tty_driver(driver); return ret; } tty3270_driver = driver; ret = raw3270_register_notifier(tty3270_notifier); if (ret) { printk(KERN_ERR "tty3270 notifier registration failed " "with %d\n", ret); put_tty_driver(driver); return ret; } return 0;}static void __exittty3270_exit(void){ struct tty_driver *driver; raw3270_unregister_notifier(tty3270_notifier); driver = tty3270_driver; tty3270_driver = 0; tty_unregister_driver(driver); tty3270_del_views();}MODULE_LICENSE("GPL");MODULE_ALIAS_CHARDEV_MAJOR(IBM_TTY3270_MAJOR);module_init(tty3270_init);module_exit(tty3270_exit);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -