2 #include <klibc/string.h>
4 #include <lunaix/mm/valloc.h>
5 #include <lunaix/process.h>
6 #include <lunaix/spike.h>
7 #include <lunaix/status.h>
9 #include <usr/lunaix/ioctl_defs.h>
11 #define termdev(dev) ((struct term*)(dev)->underlay)
13 #define LCNTL_TABLE_LEN (sizeof(line_controls) / sizeof(struct term_lcntl*))
15 static struct devclass termdev_class = DEVCLASS(DEVIF_NON, DEVFN_TTY, DEV_VTERM);
17 struct device* sysconsole = NULL;
20 term_exec_cmd(struct device* dev, u32_t req, va_list args)
22 struct term* term = termdev(dev);
29 pid_t pgid = va_arg(args, pid_t);
39 case TDEV_TCSETCHDEV: {
40 int fd = va_arg(args, int);
43 if (vfs_getfd(fd, &vfd)) {
48 struct device* cdev = resolve_device(vfd->file->inode->data);
53 if (cdev->dev_type != DEV_IFSEQ) {
58 term_bind(term, cdev);
61 case TDEV_TCGETCHDEV: {
62 struct dev_info* devinfo = va_arg(args, struct dev_info*);
70 device_populate_info(term->chdev, devinfo);
74 case TDEV_TCGETATTR: {
75 struct termios* tios = va_arg(args, struct termios*);
76 *tios = (struct termios){.c_oflag = term->oflags,
77 .c_iflag = term->iflags,
78 .c_lflag = term->lflags,
79 .c_cflag = term->cflags};
80 memcpy(tios->c_cc, term->cc, _NCCS * sizeof(cc_t));
81 tios->c_baud = term->iospeed;
83 case TDEV_TCSETATTR: {
84 struct termport_cap_ops* cap_ops;
85 struct termios* tios = va_arg(args, struct termios*);
87 term->iflags = tios->c_iflag;
88 term->oflags = tios->c_oflag;
89 term->lflags = tios->c_lflag;
90 memcpy(term->cc, tios->c_cc, _NCCS * sizeof(cc_t));
92 tcflag_t old_cf = term->cflags;
93 term->cflags = tios->c_cflag;
99 cap_ops = term->tp_cap->cap_ops;
101 if (tios->c_baud != term->iospeed) {
102 term->iospeed = tios->c_baud;
104 cap_ops->set_speed(term->chdev, tios->c_baud);
107 if (old_cf != tios->c_cflag) {
108 cap_ops->set_cntrl_mode(term->chdev, tios->c_cflag);
122 tdev_do_write(struct device* dev, void* buf, off_t fpos, size_t len)
124 struct term* tdev = termdev(dev);
125 lbuf_ref_t current = ref_current(&tdev->line_out);
128 wrsz += rbuffer_puts(
129 deref(current), &((char*)buf)[wrsz], len - wrsz);
131 if (rbuffer_full(deref(current))) {
136 if (!rbuffer_empty(deref(current))) {
143 tdev_do_read(struct device* dev, void* buf, off_t fpos, size_t len)
145 struct term* tdev = termdev(dev);
146 lbuf_ref_t current = ref_current(&tdev->line_in);
150 while (cont && rdsz < len) {
151 cont = term_read(tdev);
152 rdsz += rbuffer_gets(
153 deref(current), &((char*)buf)[rdsz], len - rdsz);
156 tdev->line_in.sflags = 0;
160 static cc_t default_cc[_NCCS] = {4, '\n', 0x7f, 3, 1, 24, 22, 0, 0, 1, 1};
163 load_default_setting(struct term* tdev)
165 tdev->lflags = _ICANON | _IEXTEN | _ISIG | _ECHO | _ECHOE | _ECHONL;
166 tdev->iflags = _ICRNL | _IGNBRK;
167 tdev->oflags = _ONLCR | _OPOST;
168 tdev->iospeed = _B9600;
169 memcpy(tdev->cc, default_cc, _NCCS * sizeof(cc_t));
173 alloc_term_buffer(struct term* terminal, size_t sz_hlf)
175 line_alloc(&terminal->line_in, sz_hlf);
176 line_alloc(&terminal->line_out, sz_hlf);
177 terminal->scratch_pad = valloc(sz_hlf);
181 term_create(struct device* chardev, char* suffix)
183 struct term* terminal;
185 struct capability_meta* termport_cap;
186 struct capability_meta* tios_cap;
188 terminal = vzalloc(sizeof(struct term));
193 tdev = device_allocseq(NULL, terminal);
194 terminal->dev = tdev;
195 terminal->chdev = chardev;
197 tdev->ops.read = tdev_do_read;
198 tdev->ops.write = tdev_do_write;
199 tdev->ops.exec_cmd = term_exec_cmd;
201 waitq_init(&terminal->line_in_event);
203 alloc_term_buffer(terminal, 1024);
206 int cdev_var = DEV_VAR_FROM(chardev->ident.unique);
207 register_device(tdev, &termdev_class, "tty%s%d", suffix, cdev_var);
209 register_device(tdev, &termdev_class, "tty%d", termdev_class.variant++);
212 termport_cap = device_get_capability(chardev, TERMPORT_CAP);
215 get_capability(termport_cap, struct termport_capability);
217 assert(terminal->tp_cap->cap_ops);
218 terminal->tp_cap->term = terminal;
221 tios_cap = new_capability_marker(TERMIOS_CAP);
222 device_grant_capability(tdev, tios_cap);
224 load_default_setting(terminal);
230 term_bind(struct term* term, struct device* chdev)
232 device_lock(term->dev);
236 device_unlock(term->dev);
242 line_alloc(struct linebuffer* lbf, size_t sz_hlf)
244 char* buffer = valloc(sz_hlf * 2);
245 memset(lbf, 0, sizeof(*lbf));
246 lbf->current = rbuffer_create(buffer, sz_hlf);
247 lbf->next = rbuffer_create(&buffer[sz_hlf], sz_hlf);
248 lbf->sz_hlf = sz_hlf;
252 line_free(struct linebuffer* lbf, size_t sz_hlf)
255 (void*)MIN((ptr_t)lbf->current->buffer, (ptr_t)lbf->next->buffer);
260 term_sendsig(struct term* tdev, int signal)
262 if ((tdev->lflags & _ISIG)) {
263 signal_send(-tdev->fggrp, signal);