/* tty_chu.c,v 3.1 1993/07/06 01:07:30 jbj Exp
* tty_chu.c - CHU line driver
#include "../h/chudefs.h"
* Line discipline for receiving CHU time codes.
* Does elementary noise elimination, takes time stamps after
* the arrival of each character, returns a buffer full of the
* received 10 character code and the associated time stamps.
u_char used
; /* Set to 1 when structure in use */
u_char lastindex
; /* least recently used buffer */
u_char curindex
; /* buffer to use */
u_char sleeping
; /* set to 1 when we're sleeping on a buffer */
struct chucode chubuf
[NUMCHUBUFS
];
* Number of microseconds we allow between
* character arrivals. The speed is 300 baud
* so this should be somewhat more than 30 msec
#define CHUMAXUSEC (50*1000) /* 50 msec */
* Open as CHU time discipline. Called when discipline changed
* with ioctl, and changes the interpretation of the information
register struct chudata
*chu
;
* Don't allow multiple opens. This will also protect us
* from someone opening /dev/tty
if (tp
->t_line
== CHULDISC
)
for (chu
= chu_data
; chu
< &chu_data
[NCHU
]; chu
++)
chu
->lastindex
= chu
->curindex
= 0;
chu
->chubuf
[0].ncodechars
= 0;
tp
->T_LINEP
= (caddr_t
) chu
;
* Break down... called when discipline changed or from device
((struct chudata
*) tp
->T_LINEP
)->used
= 0;
tp
->t_rawq
.c_cc
= 0; /* clear queues -- paranoid */
tp
->t_line
= 0; /* paranoid: avoid races */
* Read a CHU buffer. Sleep on the current buffer
register struct chudata
*chu
;
register struct chucode
*chucode
;
if ((tp
->t_state
&TS_CARR_ON
)==0)
chu
= (struct chudata
*) (tp
->T_LINEP
);
chucode
= &(chu
->chubuf
[chu
->lastindex
]);
while (chu
->curindex
== chu
->lastindex
) {
sleep((caddr_t
)chucode
, TTIPRI
);
if (++(chu
->lastindex
) >= NUMCHUBUFS
)
return (uiomove((caddr_t
)chucode
, sizeof(*chucode
), UIO_READ
, uio
));
* Low level character input routine.
* If the character looks okay, grab a time stamp. If the stuff in
* the buffer is too old, dump it and start fresh. If the character is
* non-BCDish, everything in the buffer too.
register struct chudata
*chu
= (struct chudata
*) tp
->T_LINEP
;
register struct chucode
*chuc
;
* Do a check on the BSDness of the character. This delays
* the time stamp a bit but saves a fair amount of overhead
* when the static is bad.
if (((c
) & 0xf) > 9 || (((c
)>>4) & 0xf) > 9) {
chuc
= &(chu
->chubuf
[chu
->curindex
]);
chuc
->ncodechars
= 0; /* blow all previous away */
* Call microtime() to get the current time of day
* Compute the difference in this character's time stamp
* and the last. If it exceeds the margin, blow away all
* the characters currently in the buffer.
chuc
= &(chu
->chubuf
[chu
->curindex
]);
i
= (int)chuc
->ncodechars
;
sec
= tv
.tv_sec
- chuc
->codetimes
[i
-1].tv_sec
;
usec
= tv
.tv_usec
- chuc
->codetimes
[i
-1].tv_usec
;
if (sec
!= 0 || usec
> CHUMAXUSEC
) {
* Store the character. If we're done, have to tell someone
chuc
->codechars
[i
] = (u_char
)c
;
* Not much to do here. Save the count and wait
chuc
->ncodechars
= (u_char
)i
;
* Mark this buffer full and point at next. If the
* next buffer is full we overwrite it by bumping the
chuc
->ncodechars
= NCHUCHARS
;
if (++(chu
->curindex
) >= NUMCHUBUFS
)
if (chu
->curindex
== chu
->lastindex
)
if (++(chu
->lastindex
) >= NUMCHUBUFS
)
chu
->chubuf
[chu
->curindex
].ncodechars
= 0;
* Wake up anyone sleeping on this. Also wake up
* selectors and/or deliver a SIGIO as required.
selwakeup(tp
->t_rsel
, tp
->t_state
&TS_RCOLL
);
tp
->t_state
&= ~TS_RCOLL
;
if (tp
->t_state
& TS_ASYNC
)
gsignal(tp
->t_pgrp
, SIGIO
);
(void) wakeup((caddr_t
)chuc
);
* Handle ioctls. We reject all tty-style except those that
* change the line discipline.
chuioctl(tp
, cmd
, data
, flag
)
return (ENOTTY
); /* not quite appropriate */
register struct tty
*tp
= &cdevsw
[major(dev
)].d_ttys
[minor(dev
)];
chu
= (struct chudata
*) (tp
->T_LINEP
);
if (chu
->curindex
!= chu
->lastindex
)
if (tp
->t_rsel
&& tp
->t_rsel
->p_wchan
== (caddr_t
)&selwait
)