#include "chu.h"
#if NCHU > 0
#include "../h/param.h"
#include "../h/types.h"
#include "../h/systm.h"
#include "../h/dir.h"
#include "../h/user.h"
#include "../h/ioctl.h"
#include "../h/tty.h"
#include "../h/proc.h"
#include "../h/file.h"
#include "../h/conf.h"
#include "../h/buf.h"
#include "../h/uio.h"
#include "../h/chudefs.h"
#define NUMCHUBUFS 3
struct chudata {
u_char used;
u_char lastindex;
u_char curindex;
u_char sleeping;
struct chucode chubuf[NUMCHUBUFS];
} chu_data[NCHU];
#define CHUMAXUSEC (50*1000)
int chu_debug = 0;
chuopen(dev, tp)
dev_t dev;
register struct tty *tp;
{
register struct chudata *chu;
if (tp->t_line == CHULDISC)
return (EBUSY);
ttywflush(tp);
for (chu = chu_data; chu < &chu_data[NCHU]; chu++)
if (!chu->used)
break;
if (chu >= &chu[NCHU])
return (EBUSY);
chu->used++;
chu->lastindex = chu->curindex = 0;
chu->sleeping = 0;
chu->chubuf[0].ncodechars = 0;
tp->T_LINEP = (caddr_t) chu;
return (0);
}
chuclose(tp)
register struct tty *tp;
{
register int s = spl5();
((struct chudata *) tp->T_LINEP)->used = 0;
tp->t_cp = 0;
tp->t_inbuf = 0;
tp->t_rawq.c_cc = 0;
tp->t_canq.c_cc = 0;
tp->t_line = 0;
splx(s);
}
churead(tp, uio)
register struct tty *tp;
struct uio *uio;
{
register struct chudata *chu;
register struct chucode *chucode;
register int s;
if ((tp->t_state&TS_CARR_ON)==0)
return (EIO);
chu = (struct chudata *) (tp->T_LINEP);
s = spl5();
chucode = &(chu->chubuf[chu->lastindex]);
while (chu->curindex == chu->lastindex) {
chu->sleeping = 1;
sleep((caddr_t)chucode, TTIPRI);
}
chu->sleeping = 0;
if (++(chu->lastindex) >= NUMCHUBUFS)
chu->lastindex = 0;
splx(s);
return (uiomove((caddr_t)chucode, sizeof(*chucode), UIO_READ, uio));
}
chuinput(c, tp)
register int c;
register struct tty *tp;
{
register struct chudata *chu = (struct chudata *) tp->T_LINEP;
register struct chucode *chuc;
register int i;
long sec, usec;
struct timeval tv;
if (((c) & 0xf) > 9 || (((c)>>4) & 0xf) > 9) {
chuc = &(chu->chubuf[chu->curindex]);
chuc->ncodechars = 0;
return;
}
microtime(&tv);
chuc = &(chu->chubuf[chu->curindex]);
i = (int)chuc->ncodechars;
if (i > 0) {
sec = tv.tv_sec - chuc->codetimes[i-1].tv_sec;
usec = tv.tv_usec - chuc->codetimes[i-1].tv_usec;
if (usec < 0) {
sec -= 1;
usec += 1000000;
}
if (sec != 0 || usec > CHUMAXUSEC) {
i = 0;
chuc->ncodechars = 0;
}
}
chuc->codechars[i] = (u_char)c;
chuc->codetimes[i] = tv;
if (++i < NCHUCHARS) {
chuc->ncodechars = (u_char)i;
} else {
chuc->ncodechars = NCHUCHARS;
if (++(chu->curindex) >= NUMCHUBUFS)
chu->curindex = 0;
if (chu->curindex == chu->lastindex)
if (++(chu->lastindex) >= NUMCHUBUFS)
chu->lastindex = 0;
chu->chubuf[chu->curindex].ncodechars = 0;
if (tp->t_rsel) {
selwakeup(tp->t_rsel, tp->t_state&TS_RCOLL);
tp->t_state &= ~TS_RCOLL;
tp->t_rsel = 0;
}
if (tp->t_state & TS_ASYNC)
gsignal(tp->t_pgrp, SIGIO);
if (chu->sleeping)
(void) wakeup((caddr_t)chuc);
}
}
chuioctl(tp, cmd, data, flag)
struct tty *tp;
int cmd;
caddr_t data;
int flag;
{
if ((cmd>>8) != 't')
return (-1);
switch (cmd) {
case TIOCSETD:
case TIOCGETD:
case TIOCGETP:
case TIOCGETC:
return (-1);
}
return (ENOTTY);
}
chuselect(dev, rw)
dev_t dev;
int rw;
{
register struct tty *tp = &cdevsw[major(dev)].d_ttys[minor(dev)];
struct chudata *chu;
int s = spl5();
chu = (struct chudata *) (tp->T_LINEP);
switch (rw) {
case FREAD:
if (chu->curindex != chu->lastindex)
goto win;
if (tp->t_rsel && tp->t_rsel->p_wchan == (caddr_t)&selwait)
tp->t_state |= TS_RCOLL;
else
tp->t_rsel = u.u_procp;
break;
case FWRITE:
goto win;
}
splx(s);
return (0);
win:
splx(s);
return (1);
}
#endif NCHU