Home | History | Annotate | Line # | Download | only in ir
irframe_tty.c revision 1.2
      1  1.2  augustss /*	$NetBSD: irframe_tty.c,v 1.2 2001/12/04 19:56:43 augustss Exp $	*/
      2  1.1  augustss 
      3  1.1  augustss /*
      4  1.1  augustss  * Copyright (c) 2001 The NetBSD Foundation, Inc.
      5  1.1  augustss  * All rights reserved.
      6  1.1  augustss  *
      7  1.1  augustss  * This code is derived from software contributed to The NetBSD Foundation
      8  1.1  augustss  * by Lennart Augustsson (lennart (at) augustsson.net).
      9  1.1  augustss  *
     10  1.1  augustss  * Redistribution and use in source and binary forms, with or without
     11  1.1  augustss  * modification, are permitted provided that the following conditions
     12  1.1  augustss  * are met:
     13  1.1  augustss  * 1. Redistributions of source code must retain the above copyright
     14  1.1  augustss  *    notice, this list of conditions and the following disclaimer.
     15  1.1  augustss  * 2. Redistributions in binary form must reproduce the above copyright
     16  1.1  augustss  *    notice, this list of conditions and the following disclaimer in the
     17  1.1  augustss  *    documentation and/or other materials provided with the distribution.
     18  1.1  augustss  * 3. All advertising materials mentioning features or use of this software
     19  1.1  augustss  *    must display the following acknowledgement:
     20  1.1  augustss  *        This product includes software developed by the NetBSD
     21  1.1  augustss  *        Foundation, Inc. and its contributors.
     22  1.1  augustss  * 4. Neither the name of The NetBSD Foundation nor the names of its
     23  1.1  augustss  *    contributors may be used to endorse or promote products derived
     24  1.1  augustss  *    from this software without specific prior written permission.
     25  1.1  augustss  *
     26  1.1  augustss  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     27  1.1  augustss  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     28  1.1  augustss  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     29  1.1  augustss  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     30  1.1  augustss  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     31  1.1  augustss  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     32  1.1  augustss  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     33  1.1  augustss  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     34  1.1  augustss  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     35  1.1  augustss  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     36  1.1  augustss  * POSSIBILITY OF SUCH DAMAGE.
     37  1.1  augustss  */
     38  1.1  augustss 
     39  1.1  augustss /*
     40  1.1  augustss  * Loosely based on ppp_tty.c.
     41  1.1  augustss  */
     42  1.1  augustss 
     43  1.1  augustss #include <sys/param.h>
     44  1.1  augustss #include <sys/proc.h>
     45  1.1  augustss #include <sys/ioctl.h>
     46  1.1  augustss #include <sys/tty.h>
     47  1.1  augustss #include <sys/kernel.h>
     48  1.2  augustss #include <sys/malloc.h>
     49  1.1  augustss #include <sys/conf.h>
     50  1.1  augustss #include <sys/systm.h>
     51  1.1  augustss #include <sys/device.h>
     52  1.1  augustss #include <sys/file.h>
     53  1.2  augustss #include <sys/vnode.h>
     54  1.1  augustss #include <sys/poll.h>
     55  1.1  augustss 
     56  1.1  augustss #include <dev/ir/ir.h>
     57  1.1  augustss #include <dev/ir/irdaio.h>
     58  1.1  augustss #include <dev/ir/irframevar.h>
     59  1.1  augustss 
     60  1.1  augustss /* Macros to clear/set/test flags. */
     61  1.1  augustss #define	SET(t, f)	(t) |= (f)
     62  1.2  augustss #define	CLR(t, f)	(t) &= ~(f)
     63  1.1  augustss #define	ISSET(t, f)	((t) & (f))
     64  1.1  augustss 
     65  1.1  augustss #ifdef IRFRAMET_DEBUG
     66  1.1  augustss #define DPRINTF(x)	if (irframetdebug) printf x
     67  1.2  augustss #define Static
     68  1.1  augustss int irframetdebug = 1;
     69  1.1  augustss #else
     70  1.1  augustss #define DPRINTF(x)
     71  1.2  augustss #define Static static
     72  1.1  augustss #endif
     73  1.1  augustss 
     74  1.1  augustss /* Protocol constants */
     75  1.1  augustss #define SIR_EXTRA_BOF            0xff
     76  1.1  augustss #define SIR_BOF                  0xc0
     77  1.1  augustss #define SIR_CE                   0x7d
     78  1.1  augustss #define SIR_EOF                  0xc1
     79  1.1  augustss 
     80  1.1  augustss #define SIR_ESC_BIT              0x20
     81  1.1  augustss /*****/
     82  1.1  augustss 
     83  1.1  augustss #define MAX_IRDA_FRAME 5000	/* XXX what is it? */
     84  1.1  augustss 
     85  1.2  augustss struct frame {
     86  1.2  augustss 	u_char *buf;
     87  1.2  augustss 	u_int len;
     88  1.2  augustss };
     89  1.2  augustss #define MAXFRAMES 4
     90  1.2  augustss 
     91  1.1  augustss struct irframet_softc {
     92  1.1  augustss 	struct irframe_softc sc_irp;
     93  1.1  augustss 	struct tty *sc_tp;
     94  1.2  augustss 
     95  1.2  augustss 	int sc_state;
     96  1.2  augustss #define	IRT_RSLP		0x01	/* waiting for data (read) */
     97  1.2  augustss #if 0
     98  1.2  augustss #define	IRT_WSLP		0x02	/* waiting for data (write) */
     99  1.2  augustss #define IRT_CLOSING		0x04	/* waiting for output to drain */
    100  1.2  augustss #endif
    101  1.2  augustss 
    102  1.1  augustss 	int sc_ebofs;
    103  1.2  augustss 
    104  1.2  augustss 	u_char* sc_inbuf;
    105  1.2  augustss 	int sc_maxsize;
    106  1.2  augustss 	int sc_framestate;
    107  1.2  augustss #define FRAME_OUTSIDE    0
    108  1.2  augustss #define FRAME_INSIDE     1
    109  1.2  augustss #define FRAME_ESCAPE     2
    110  1.2  augustss 	int sc_inchars;
    111  1.2  augustss 	int sc_inFCS;
    112  1.2  augustss 	struct callout sc_timeout;
    113  1.2  augustss 
    114  1.2  augustss 	u_int sc_nframes;
    115  1.2  augustss 	u_int sc_framei;
    116  1.2  augustss 	u_int sc_frameo;
    117  1.2  augustss 	struct frame sc_frames[MAXFRAMES];
    118  1.2  augustss 	struct selinfo sc_rsel;
    119  1.1  augustss };
    120  1.1  augustss 
    121  1.1  augustss /* line discipline methods */
    122  1.1  augustss int	irframetopen(dev_t dev, struct tty *tp);
    123  1.1  augustss int	irframetclose(struct tty *tp, int flag);
    124  1.1  augustss int	irframetioctl(struct tty *tp, u_long cmd, caddr_t data, int flag,
    125  1.1  augustss 		     struct proc *);
    126  1.1  augustss int	irframetinput(int c, struct tty *tp);
    127  1.1  augustss int	irframetstart(struct tty *tp);
    128  1.1  augustss 
    129  1.2  augustss /* pseudo device init */
    130  1.2  augustss void	irframettyattach(int);
    131  1.2  augustss 
    132  1.1  augustss /* irframe methods */
    133  1.2  augustss Static int	irframet_open(void *h, int flag, int mode, struct proc *p);
    134  1.2  augustss Static int	irframet_close(void *h, int flag, int mode, struct proc *p);
    135  1.2  augustss Static int	irframet_read(void *h, struct uio *uio, int flag);
    136  1.2  augustss Static int	irframet_write(void *h, struct uio *uio, int flag);
    137  1.2  augustss Static int	irframet_poll(void *h, int events, struct proc *p);
    138  1.2  augustss Static int	irframet_set_params(void *h, struct irda_params *params);
    139  1.2  augustss Static int	irframet_get_speeds(void *h, int *speeds);
    140  1.2  augustss Static int	irframet_get_turnarounds(void *h, int *times);
    141  1.2  augustss 
    142  1.2  augustss /* internal */
    143  1.2  augustss Static int	irt_write_buf(void *h, void *buf, size_t len);
    144  1.2  augustss Static int	irt_putc(int c, struct tty *tp);
    145  1.2  augustss Static int	irt_putesc(int c, struct tty *tp);
    146  1.2  augustss Static void	irt_frame(struct irframet_softc *sc, u_char *buf, u_int len);
    147  1.2  augustss Static void	irt_timeout(void *v);
    148  1.1  augustss 
    149  1.2  augustss Static struct irframe_methods irframet_methods = {
    150  1.1  augustss 	irframet_open, irframet_close, irframet_read, irframet_write,
    151  1.2  augustss 	irframet_poll, irframet_set_params,
    152  1.2  augustss 	irframet_get_speeds, irframet_get_turnarounds
    153  1.1  augustss };
    154  1.1  augustss 
    155  1.1  augustss void
    156  1.1  augustss irframettyattach(int n)
    157  1.1  augustss {
    158  1.1  augustss }
    159  1.1  augustss 
    160  1.1  augustss /*
    161  1.2  augustss  * CRC
    162  1.2  augustss  */
    163  1.2  augustss 
    164  1.2  augustss static const u_int16_t fcstab[] = {
    165  1.2  augustss   0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
    166  1.2  augustss   0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
    167  1.2  augustss   0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
    168  1.2  augustss   0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
    169  1.2  augustss   0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
    170  1.2  augustss   0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
    171  1.2  augustss   0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
    172  1.2  augustss   0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
    173  1.2  augustss   0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
    174  1.2  augustss   0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
    175  1.2  augustss   0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
    176  1.2  augustss   0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
    177  1.2  augustss   0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
    178  1.2  augustss   0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
    179  1.2  augustss   0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
    180  1.2  augustss   0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
    181  1.2  augustss   0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
    182  1.2  augustss   0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
    183  1.2  augustss   0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
    184  1.2  augustss   0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
    185  1.2  augustss   0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
    186  1.2  augustss   0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
    187  1.2  augustss   0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
    188  1.2  augustss   0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
    189  1.2  augustss   0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
    190  1.2  augustss   0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
    191  1.2  augustss   0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
    192  1.2  augustss   0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
    193  1.2  augustss   0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
    194  1.2  augustss   0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
    195  1.2  augustss   0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
    196  1.2  augustss   0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
    197  1.2  augustss };
    198  1.2  augustss 
    199  1.2  augustss static const u_int16_t INITFCS = 0xffff;
    200  1.2  augustss static const u_int16_t GOODFCS = 0xf0b8;
    201  1.2  augustss 
    202  1.2  augustss static __inline u_int16_t updateFCS(u_int16_t fcs, int c) {
    203  1.2  augustss 	return (fcs >> 8) ^ fcstab[(fcs^c) & 0xff];
    204  1.2  augustss }
    205  1.2  augustss 
    206  1.2  augustss 
    207  1.2  augustss /*
    208  1.1  augustss  * Line specific open routine for async tty devices.
    209  1.1  augustss  * Attach the given tty to the first available irframe unit.
    210  1.1  augustss  * Called from device open routine or ttioctl.
    211  1.1  augustss  */
    212  1.1  augustss /* ARGSUSED */
    213  1.1  augustss int
    214  1.1  augustss irframetopen(dev_t dev, struct tty *tp)
    215  1.1  augustss {
    216  1.1  augustss 	struct proc *p = curproc;		/* XXX */
    217  1.1  augustss 	struct irframet_softc *sc;
    218  1.1  augustss 	int error, s;
    219  1.1  augustss 
    220  1.1  augustss 	DPRINTF(("%s\n", __FUNCTION__));
    221  1.1  augustss 
    222  1.1  augustss 	if ((error = suser(p->p_ucred, &p->p_acflag)) != 0)
    223  1.1  augustss 		return (error);
    224  1.1  augustss 
    225  1.1  augustss 	s = spltty();
    226  1.1  augustss 
    227  1.1  augustss 	DPRINTF(("%s: linesw=%p disc=%d\n", __FUNCTION__, tp->t_linesw,
    228  1.1  augustss 		 tp->t_linesw->l_no));
    229  1.1  augustss 	if (tp->t_linesw->l_no == IRFRAMEDISC) {
    230  1.1  augustss 		sc = (struct irframet_softc *)tp->t_sc;
    231  1.1  augustss 		DPRINTF(("%s: sc=%p sc_tp=%p\n", __FUNCTION__, sc, sc->sc_tp));
    232  1.1  augustss 		if (sc != NULL) {
    233  1.1  augustss 			splx(s);
    234  1.1  augustss 			return (EBUSY);
    235  1.1  augustss 		}
    236  1.1  augustss 	}
    237  1.1  augustss 
    238  1.2  augustss 	printf("%s attached at tty%02d:", sc->sc_irp.sc_dev.dv_xname,
    239  1.1  augustss 	    minor(tp->t_dev));
    240  1.1  augustss 	tp->t_sc = irframe_alloc(sizeof (struct irframet_softc),
    241  1.1  augustss 			&irframet_methods, tp);
    242  1.1  augustss 	sc = (struct irframet_softc *)tp->t_sc;
    243  1.1  augustss 	sc->sc_tp = tp;
    244  1.1  augustss 
    245  1.1  augustss 	DPRINTF(("%s: set sc=%p\n", __FUNCTION__, sc));
    246  1.1  augustss 
    247  1.1  augustss 	ttyflush(tp, FREAD | FWRITE);
    248  1.1  augustss 
    249  1.1  augustss 	splx(s);
    250  1.2  augustss 
    251  1.2  augustss 	sc->sc_ebofs = IRDA_DEFAULT_EBOFS;
    252  1.2  augustss 	sc->sc_maxsize = 0;
    253  1.2  augustss 	sc->sc_framestate = FRAME_OUTSIDE;
    254  1.2  augustss 	sc->sc_nframes = 0;
    255  1.2  augustss 	sc->sc_framei = 0;
    256  1.2  augustss 	sc->sc_frameo = 0;
    257  1.2  augustss 	callout_init(&sc->sc_timeout);
    258  1.2  augustss 
    259  1.1  augustss 	return (0);
    260  1.1  augustss }
    261  1.1  augustss 
    262  1.1  augustss /*
    263  1.1  augustss  * Line specific close routine, called from device close routine
    264  1.1  augustss  * and from ttioctl.
    265  1.1  augustss  * Detach the tty from the irframe unit.
    266  1.1  augustss  * Mimics part of ttyclose().
    267  1.1  augustss  */
    268  1.1  augustss int
    269  1.1  augustss irframetclose(struct tty *tp, int flag)
    270  1.1  augustss {
    271  1.1  augustss 	struct irframet_softc *sc = (struct irframet_softc *)tp->t_sc;
    272  1.1  augustss 	int s;
    273  1.2  augustss 	int i;
    274  1.1  augustss 
    275  1.1  augustss 	DPRINTF(("%s: tp=%p\n", __FUNCTION__, tp));
    276  1.1  augustss 
    277  1.2  augustss 	callout_stop(&sc->sc_timeout);
    278  1.2  augustss 	s = splir();
    279  1.2  augustss 	if (sc->sc_inbuf != NULL) {
    280  1.2  augustss 		free(sc->sc_inbuf, M_DEVBUF);
    281  1.2  augustss 		sc->sc_inbuf = NULL;
    282  1.2  augustss 	}
    283  1.2  augustss 	for (i = 0; i < MAXFRAMES; i++) {
    284  1.2  augustss 		if (sc->sc_frames[i].buf != NULL) {
    285  1.2  augustss 			free(sc->sc_frames[i].buf, M_DEVBUF);
    286  1.2  augustss 			sc->sc_frames[i].buf = NULL;
    287  1.2  augustss 		}
    288  1.2  augustss 	}
    289  1.2  augustss 	splx(s);
    290  1.2  augustss 
    291  1.1  augustss 	s = spltty();
    292  1.1  augustss 	ttyflush(tp, FREAD | FWRITE);
    293  1.1  augustss 	tp->t_linesw = linesw[0]; /* default line discipline */
    294  1.1  augustss 	if (sc != NULL) {
    295  1.1  augustss 		tp->t_sc = NULL;
    296  1.2  augustss 		printf("%s detached from tty%02d\n", sc->sc_irp.sc_dev.dv_xname,
    297  1.1  augustss 		    minor(tp->t_dev));
    298  1.1  augustss 
    299  1.1  augustss 		if (sc->sc_tp == tp)
    300  1.1  augustss 			irframe_dealloc(&sc->sc_irp.sc_dev);
    301  1.1  augustss 	}
    302  1.1  augustss 	splx(s);
    303  1.1  augustss 	return (0);
    304  1.1  augustss }
    305  1.1  augustss 
    306  1.1  augustss /*
    307  1.1  augustss  * Line specific (tty) ioctl routine.
    308  1.1  augustss  * This discipline requires that tty device drivers call
    309  1.1  augustss  * the line specific l_ioctl routine from their ioctl routines.
    310  1.1  augustss  */
    311  1.1  augustss /* ARGSUSED */
    312  1.1  augustss int
    313  1.1  augustss irframetioctl(struct tty *tp, u_long cmd, caddr_t data, int flag,
    314  1.1  augustss 	     struct proc *p)
    315  1.1  augustss {
    316  1.1  augustss 	struct irframet_softc *sc = (struct irframet_softc *)tp->t_sc;
    317  1.1  augustss 	int error;
    318  1.1  augustss 
    319  1.1  augustss 	DPRINTF(("%s: tp=%p\n", __FUNCTION__, tp));
    320  1.1  augustss 
    321  1.1  augustss 	if (sc == NULL || tp != sc->sc_tp)
    322  1.1  augustss 		return (-1);
    323  1.1  augustss 
    324  1.1  augustss 	error = 0;
    325  1.1  augustss 	switch (cmd) {
    326  1.1  augustss 	default:
    327  1.1  augustss #if 0
    328  1.1  augustss 		error = irframeioctl(sc, cmd, data, flag, p);
    329  1.1  augustss #else
    330  1.1  augustss 		error = EINVAL;
    331  1.1  augustss #endif
    332  1.1  augustss 		break;
    333  1.1  augustss 	}
    334  1.1  augustss 
    335  1.1  augustss 	return (error);
    336  1.1  augustss }
    337  1.1  augustss 
    338  1.1  augustss /*
    339  1.1  augustss  * Start output on async tty interface.  If the transmit queue
    340  1.1  augustss  * has drained sufficiently, arrange for irframeasyncstart to be
    341  1.1  augustss  * called later at splsoftnet.
    342  1.1  augustss  * Called at spltty or higher.
    343  1.1  augustss  */
    344  1.1  augustss int
    345  1.1  augustss irframetstart(struct tty *tp)
    346  1.1  augustss {
    347  1.1  augustss 	/*struct irframet_softc *sc = (struct irframet_softc *)tp->t_sc;*/
    348  1.1  augustss 
    349  1.1  augustss 	DPRINTF(("%s: tp=%p\n", __FUNCTION__, tp));
    350  1.1  augustss 
    351  1.1  augustss 	/*
    352  1.1  augustss 	 * If there is stuff in the output queue, send it now.
    353  1.1  augustss 	 * We are being called in lieu of ttstart and must do what it would.
    354  1.1  augustss 	 */
    355  1.1  augustss 	if (tp->t_oproc != NULL)
    356  1.1  augustss 		(*tp->t_oproc)(tp);
    357  1.1  augustss 
    358  1.1  augustss 	return (0);
    359  1.1  augustss }
    360  1.1  augustss 
    361  1.2  augustss void
    362  1.2  augustss irt_frame(struct irframet_softc *sc, u_char *buf, u_int len)
    363  1.2  augustss {
    364  1.2  augustss 	if (sc->sc_nframes >= MAXFRAMES) {
    365  1.2  augustss #ifdef IRFRAMET_DEBUG
    366  1.2  augustss 		printf("%s: dropped frame\n", __FUNCTION__);
    367  1.2  augustss #endif
    368  1.2  augustss 		return;
    369  1.2  augustss 	}
    370  1.2  augustss 	if (sc->sc_frames[sc->sc_framei].buf == NULL)
    371  1.2  augustss 		return;
    372  1.2  augustss 	memcpy(sc->sc_frames[sc->sc_framei].buf, buf, len);
    373  1.2  augustss 	sc->sc_frames[sc->sc_framei].len = len;
    374  1.2  augustss 	sc->sc_framei = (sc->sc_framei+1) % MAXFRAMES;
    375  1.2  augustss 	sc->sc_nframes++;
    376  1.2  augustss 	if (sc->sc_state & IRT_RSLP) {
    377  1.2  augustss 		sc->sc_state &= ~IRT_RSLP;
    378  1.2  augustss 		DPRINTF(("%s: waking up reader\n", __FUNCTION__));
    379  1.2  augustss 		wakeup(sc->sc_frames);
    380  1.2  augustss 	}
    381  1.2  augustss 	selwakeup(&sc->sc_rsel);
    382  1.2  augustss }
    383  1.2  augustss 
    384  1.2  augustss void
    385  1.2  augustss irt_timeout(void *v)
    386  1.2  augustss {
    387  1.2  augustss 	struct irframet_softc *sc = v;
    388  1.2  augustss 
    389  1.2  augustss #ifdef IRFRAMET_DEBUG
    390  1.2  augustss 	if (sc->sc_framestate != FRAME_OUTSIDE)
    391  1.2  augustss 		printf("%s: input frame timeout\n", __FUNCTION__);
    392  1.2  augustss #endif
    393  1.2  augustss 	sc->sc_framestate = FRAME_OUTSIDE;
    394  1.2  augustss }
    395  1.2  augustss 
    396  1.1  augustss int
    397  1.1  augustss irframetinput(int c, struct tty *tp)
    398  1.1  augustss {
    399  1.1  augustss 	struct irframet_softc *sc = (struct irframet_softc *)tp->t_sc;
    400  1.1  augustss 
    401  1.1  augustss 	DPRINTF(("%s: tp=%p c=0x%0x\n", __FUNCTION__, tp, c));
    402  1.1  augustss 
    403  1.1  augustss 	if (sc == NULL || tp != (struct tty *)sc->sc_tp)
    404  1.1  augustss 		return (0);
    405  1.1  augustss 
    406  1.2  augustss 	if (sc->sc_inbuf == NULL)
    407  1.2  augustss 		return (0);
    408  1.1  augustss 
    409  1.2  augustss 	switch (c) {
    410  1.2  augustss 	case SIR_BOF:
    411  1.2  augustss 		sc->sc_framestate = FRAME_INSIDE;
    412  1.2  augustss 		sc->sc_inchars = 0;
    413  1.2  augustss 		sc->sc_inFCS = INITFCS;
    414  1.2  augustss 		break;
    415  1.2  augustss 	case SIR_EOF:
    416  1.2  augustss 		if (sc->sc_framestate == FRAME_INSIDE &&
    417  1.2  augustss 		    sc->sc_inchars >= 4 && sc->sc_inFCS == GOODFCS) {
    418  1.2  augustss 			irt_frame(sc, sc->sc_inbuf, sc->sc_inchars - 2);
    419  1.2  augustss 		} else if (sc->sc_framestate != FRAME_OUTSIDE) {
    420  1.2  augustss #ifdef IRFRAMET_DEBUG
    421  1.2  augustss 			printf("%s: malformed input frame\n", __FUNCTION__);
    422  1.2  augustss #endif
    423  1.2  augustss 		}
    424  1.2  augustss 		sc->sc_framestate = FRAME_OUTSIDE;
    425  1.2  augustss 		break;
    426  1.2  augustss 	case SIR_CE:
    427  1.2  augustss 		if (sc->sc_framestate == FRAME_INSIDE)
    428  1.2  augustss 			sc->sc_framestate = FRAME_ESCAPE;
    429  1.2  augustss 		break;
    430  1.2  augustss 	default:
    431  1.2  augustss 		if (sc->sc_framestate != FRAME_OUTSIDE) {
    432  1.2  augustss 			if (sc->sc_framestate == FRAME_ESCAPE) {
    433  1.2  augustss 				sc->sc_framestate = FRAME_INSIDE;
    434  1.2  augustss 				c ^= SIR_ESC_BIT;
    435  1.2  augustss 			}
    436  1.2  augustss 			if (sc->sc_inchars < sc->sc_maxsize + 2) {
    437  1.2  augustss 				sc->sc_inbuf[sc->sc_inchars++] = c;
    438  1.2  augustss 				sc->sc_inFCS = updateFCS(sc->sc_inFCS, c);
    439  1.2  augustss 			} else {
    440  1.2  augustss 				sc->sc_framestate = FRAME_OUTSIDE;
    441  1.2  augustss #ifdef IRFRAMET_DEBUG
    442  1.2  augustss 				printf("%s: input frame overrun\n",
    443  1.2  augustss 				       __FUNCTION__);
    444  1.2  augustss #endif
    445  1.2  augustss 			}
    446  1.2  augustss 		}
    447  1.2  augustss 		break;
    448  1.1  augustss 	}
    449  1.1  augustss 
    450  1.2  augustss 	if (sc->sc_framestate != FRAME_OUTSIDE) {
    451  1.2  augustss 		callout_reset(&sc->sc_timeout, hz/100, irt_timeout, sc);
    452  1.1  augustss 	}
    453  1.1  augustss 
    454  1.2  augustss 	return (0);
    455  1.1  augustss }
    456  1.1  augustss 
    457  1.1  augustss 
    458  1.1  augustss /*** irframe methods ***/
    459  1.1  augustss 
    460  1.1  augustss int
    461  1.1  augustss irframet_open(void *h, int flag, int mode, struct proc *p)
    462  1.1  augustss {
    463  1.1  augustss 	struct tty *tp = h;
    464  1.1  augustss 
    465  1.1  augustss 	tp = tp;
    466  1.1  augustss 	DPRINTF(("%s: tp=%p\n", __FUNCTION__, tp));
    467  1.1  augustss 	return (0);
    468  1.1  augustss }
    469  1.1  augustss 
    470  1.1  augustss int
    471  1.1  augustss irframet_close(void *h, int flag, int mode, struct proc *p)
    472  1.1  augustss {
    473  1.1  augustss 	struct tty *tp = h;
    474  1.1  augustss 
    475  1.1  augustss 	tp = tp;
    476  1.1  augustss 	DPRINTF(("%s: tp=%p\n", __FUNCTION__, tp));
    477  1.1  augustss 	return (0);
    478  1.1  augustss }
    479  1.1  augustss 
    480  1.1  augustss int
    481  1.1  augustss irframet_read(void *h, struct uio *uio, int flag)
    482  1.1  augustss {
    483  1.1  augustss 	struct tty *tp = h;
    484  1.2  augustss 	struct irframet_softc *sc = (struct irframet_softc *)tp->t_sc;
    485  1.2  augustss 	int error = 0;
    486  1.2  augustss 	int s;
    487  1.1  augustss 
    488  1.2  augustss 	DPRINTF(("%s: resid=%d, iovcnt=%d, offset=%ld\n",
    489  1.2  augustss 		 __FUNCTION__, uio->uio_resid, uio->uio_iovcnt,
    490  1.2  augustss 		 (long)uio->uio_offset));
    491  1.2  augustss 
    492  1.2  augustss 	s = splir();
    493  1.2  augustss 	while (sc->sc_nframes == 0) {
    494  1.2  augustss 		if (flag & IO_NDELAY) {
    495  1.2  augustss 			splx(s);
    496  1.2  augustss 			return (EWOULDBLOCK);
    497  1.2  augustss 		}
    498  1.2  augustss 		sc->sc_state |= IRT_RSLP;
    499  1.2  augustss 		DPRINTF(("%s: sleep\n", __FUNCTION__));
    500  1.2  augustss 		error = tsleep(sc->sc_frames, PZERO | PCATCH, "irtrd", 0);
    501  1.2  augustss 		DPRINTF(("%s: woke, error=%d\n", __FUNCTION__, error));
    502  1.2  augustss 		if (error) {
    503  1.2  augustss 			sc->sc_state &= ~IRT_RSLP;
    504  1.2  augustss 			break;
    505  1.2  augustss 		}
    506  1.2  augustss 	}
    507  1.2  augustss 
    508  1.2  augustss 	/* Do just one frame transfer per read */
    509  1.2  augustss 	if (!error) {
    510  1.2  augustss 		if (uio->uio_resid < sc->sc_frames[sc->sc_frameo].len) {
    511  1.2  augustss 			DPRINTF(("%s: uio buffer smaller than frame size (%d < %d)\n", __FUNCTION__, uio->uio_resid, sc->sc_frames[sc->sc_frameo].len));
    512  1.2  augustss 			error = EINVAL;
    513  1.2  augustss 		} else {
    514  1.2  augustss 			DPRINTF(("%s: moving %d bytes\n", __FUNCTION__,
    515  1.2  augustss 				 sc->sc_frames[sc->sc_frameo].len));
    516  1.2  augustss 				error = uiomove(sc->sc_frames[sc->sc_frameo].buf,
    517  1.2  augustss 					sc->sc_frames[sc->sc_frameo].len, uio);
    518  1.2  augustss 		}
    519  1.2  augustss 		sc->sc_frameo++;
    520  1.2  augustss 		sc->sc_nframes--;
    521  1.2  augustss 	}
    522  1.2  augustss 	splx(s);
    523  1.2  augustss 
    524  1.2  augustss 	return (error);
    525  1.1  augustss }
    526  1.1  augustss 
    527  1.2  augustss int
    528  1.2  augustss irt_putc(int c, struct tty *tp)
    529  1.1  augustss {
    530  1.1  augustss 	int s;
    531  1.1  augustss 	int error;
    532  1.1  augustss 
    533  1.1  augustss 	if (tp->t_outq.c_cc > tp->t_hiwat) {
    534  1.1  augustss 		irframetstart(tp);
    535  1.1  augustss 		s = spltty();
    536  1.1  augustss 		/*
    537  1.1  augustss 		 * This can only occur if FLUSHO is set in t_lflag,
    538  1.1  augustss 		 * or if ttstart/oproc is synchronous (or very fast).
    539  1.1  augustss 		 */
    540  1.1  augustss 		if (tp->t_outq.c_cc <= tp->t_hiwat) {
    541  1.1  augustss 			splx(s);
    542  1.1  augustss 			goto go;
    543  1.1  augustss 		}
    544  1.1  augustss 		SET(tp->t_state, TS_ASLEEP);
    545  1.1  augustss 		error = ttysleep(tp, &tp->t_outq, TTOPRI | PCATCH, ttyout, 0);
    546  1.1  augustss 		splx(s);
    547  1.1  augustss 		if (error)
    548  1.1  augustss 			return (error);
    549  1.1  augustss 	}
    550  1.1  augustss  go:
    551  1.1  augustss 	if (putc(c, &tp->t_rawq) < 0) {
    552  1.1  augustss 		printf("irframe: putc failed\n");
    553  1.1  augustss 		return (EIO);
    554  1.1  augustss 	}
    555  1.1  augustss 	return (0);
    556  1.1  augustss }
    557  1.1  augustss 
    558  1.2  augustss int
    559  1.2  augustss irt_putesc(int c, struct tty *tp)
    560  1.1  augustss {
    561  1.1  augustss 	int error;
    562  1.1  augustss 
    563  1.1  augustss 	if (c == SIR_BOF || c == SIR_EOF || c == SIR_CE) {
    564  1.2  augustss 		error = irt_putc(SIR_CE, tp);
    565  1.1  augustss 		if (!error)
    566  1.2  augustss 			error = irt_putc(SIR_ESC_BIT^c, tp);
    567  1.1  augustss 	} else {
    568  1.2  augustss 		error = irt_putc(c, tp);
    569  1.1  augustss 	}
    570  1.1  augustss 	return (error);
    571  1.1  augustss }
    572  1.1  augustss 
    573  1.1  augustss int
    574  1.1  augustss irframet_write(void *h, struct uio *uio, int flag)
    575  1.1  augustss {
    576  1.1  augustss 	u_int8_t buf[MAX_IRDA_FRAME];
    577  1.1  augustss 	size_t n;
    578  1.1  augustss 	int error;
    579  1.1  augustss 
    580  1.1  augustss 	DPRINTF(("%s\n", __FUNCTION__));
    581  1.1  augustss 
    582  1.1  augustss 	n = uio->uio_resid;
    583  1.1  augustss 	if (n > MAX_IRDA_FRAME)
    584  1.1  augustss 		return (EINVAL);
    585  1.1  augustss 	error = uiomove(buf, n, uio);
    586  1.1  augustss 	if (error)
    587  1.1  augustss 		return (error);
    588  1.2  augustss 	return (irt_write_buf(h, buf, n));
    589  1.1  augustss }
    590  1.1  augustss 
    591  1.1  augustss int
    592  1.2  augustss irt_write_buf(void *h, void *buf, size_t len)
    593  1.1  augustss {
    594  1.1  augustss 	struct tty *tp = h;
    595  1.1  augustss 	struct irframet_softc *sc = (struct irframet_softc *)tp->t_sc;
    596  1.1  augustss 	u_int8_t *cp = buf;
    597  1.1  augustss 	int c, error, ofcs, i;
    598  1.1  augustss 
    599  1.1  augustss 	DPRINTF(("%s: tp=%p len=%d\n", __FUNCTION__, tp, len));
    600  1.1  augustss 
    601  1.1  augustss 	ofcs = INITFCS;
    602  1.1  augustss 	error = 0;
    603  1.1  augustss 
    604  1.1  augustss 	for (i = 0; i < sc->sc_ebofs; i++)
    605  1.2  augustss 		irt_putc(SIR_EXTRA_BOF, tp);
    606  1.2  augustss 	irt_putc(SIR_BOF, tp);
    607  1.1  augustss 
    608  1.1  augustss 	while (len-- > 0) {
    609  1.1  augustss 		c = *cp++;
    610  1.1  augustss 		ofcs = updateFCS(ofcs, c);
    611  1.2  augustss 		error = irt_putesc(c, tp);
    612  1.1  augustss 		if (error)
    613  1.1  augustss 			return (error);
    614  1.1  augustss 	}
    615  1.1  augustss 
    616  1.1  augustss 	ofcs = ~ofcs;
    617  1.2  augustss 	error = irt_putesc(ofcs & 0xff, tp);
    618  1.1  augustss 	if (!error)
    619  1.2  augustss 		error = irt_putesc((ofcs >> 8) & 0xff, tp);
    620  1.1  augustss 	if (!error)
    621  1.2  augustss 		error = irt_putc(SIR_EOF, tp);
    622  1.1  augustss 
    623  1.1  augustss 	irframetstart(tp);
    624  1.1  augustss 
    625  1.1  augustss 	return (error);
    626  1.1  augustss }
    627  1.1  augustss 
    628  1.1  augustss int
    629  1.1  augustss irframet_poll(void *h, int events, struct proc *p)
    630  1.1  augustss {
    631  1.2  augustss 	struct tty *tp = h;
    632  1.2  augustss 	struct irframet_softc *sc = (struct irframet_softc *)tp->t_sc;
    633  1.1  augustss 	int revents = 0;
    634  1.1  augustss 	int s;
    635  1.1  augustss 
    636  1.1  augustss 	DPRINTF(("%s: sc=%p\n", __FUNCTION__, sc));
    637  1.1  augustss 
    638  1.1  augustss 	s = splir();
    639  1.1  augustss 	if (events & (POLLOUT | POLLWRNORM))
    640  1.1  augustss 		revents |= events & (POLLOUT | POLLWRNORM);
    641  1.1  augustss 	if (events & (POLLIN | POLLRDNORM)) {
    642  1.2  augustss 		if (sc->sc_nframes > 0) {
    643  1.1  augustss 			DPRINTF(("%s: have data\n", __FUNCTION__));
    644  1.1  augustss 			revents |= events & (POLLIN | POLLRDNORM);
    645  1.1  augustss 		} else {
    646  1.1  augustss 			DPRINTF(("%s: recording select", __FUNCTION__));
    647  1.1  augustss 			selrecord(p, &sc->sc_rsel);
    648  1.1  augustss 		}
    649  1.1  augustss 	}
    650  1.1  augustss 	splx(s);
    651  1.1  augustss 
    652  1.1  augustss 	return (revents);
    653  1.1  augustss }
    654  1.1  augustss 
    655  1.1  augustss int
    656  1.1  augustss irframet_set_params(void *h, struct irda_params *p)
    657  1.1  augustss {
    658  1.1  augustss 	struct tty *tp = h;
    659  1.1  augustss 	struct irframet_softc *sc = (struct irframet_softc *)tp->t_sc;
    660  1.2  augustss 	int i;
    661  1.1  augustss 
    662  1.1  augustss 	DPRINTF(("%s: tp=%p\n", __FUNCTION__, tp));
    663  1.1  augustss 
    664  1.1  augustss 	/* XXX speed */
    665  1.1  augustss 	sc->sc_ebofs = p->ebofs;
    666  1.2  augustss 	if (sc->sc_maxsize != p->maxsize) {
    667  1.2  augustss 		sc->sc_maxsize = p->maxsize;
    668  1.2  augustss 		if (sc->sc_inbuf != NULL)
    669  1.2  augustss 			free(sc->sc_inbuf, M_DEVBUF);
    670  1.2  augustss 		for (i = 0; i < MAXFRAMES; i++)
    671  1.2  augustss 			if (sc->sc_frames[i].buf != NULL)
    672  1.2  augustss 				free(sc->sc_frames[i].buf, M_DEVBUF);
    673  1.2  augustss 		if (sc->sc_maxsize != 0) {
    674  1.2  augustss 			sc->sc_inbuf = malloc(sc->sc_maxsize+2, M_DEVBUF,
    675  1.2  augustss 					      M_WAITOK);
    676  1.2  augustss 			for (i = 0; i < MAXFRAMES; i++)
    677  1.2  augustss 				sc->sc_frames[i].buf = malloc(sc->sc_maxsize,
    678  1.2  augustss 							   M_DEVBUF, M_WAITOK);
    679  1.2  augustss 		} else {
    680  1.2  augustss 			sc->sc_inbuf = NULL;
    681  1.2  augustss 			for (i = 0; i < MAXFRAMES; i++)
    682  1.2  augustss 				sc->sc_frames[i].buf = NULL;
    683  1.2  augustss 		}
    684  1.2  augustss 	}
    685  1.2  augustss 	sc->sc_framestate = FRAME_OUTSIDE;
    686  1.1  augustss 
    687  1.1  augustss 	return (0);
    688  1.1  augustss }
    689  1.1  augustss 
    690  1.1  augustss int
    691  1.1  augustss irframet_get_speeds(void *h, int *speeds)
    692  1.1  augustss {
    693  1.1  augustss 	struct tty *tp = h;
    694  1.1  augustss 
    695  1.1  augustss 	tp = tp;
    696  1.1  augustss 	DPRINTF(("%s: tp=%p\n", __FUNCTION__, tp));
    697  1.1  augustss 	*speeds = IRDA_SPEEDS_SIR;
    698  1.1  augustss 	return (0);
    699  1.1  augustss }
    700  1.1  augustss 
    701  1.1  augustss int
    702  1.1  augustss irframet_get_turnarounds(void *h, int *turnarounds)
    703  1.1  augustss {
    704  1.1  augustss 	struct tty *tp = h;
    705  1.1  augustss 
    706  1.1  augustss 	tp = tp;
    707  1.1  augustss 	DPRINTF(("%s: tp=%p\n", __FUNCTION__, tp));
    708  1.1  augustss 	*turnarounds = IRDA_TURNT_10000;
    709  1.1  augustss 	return (0);
    710  1.1  augustss }
    711