1 /* $NetBSD: irframe_tty.c,v 1.57 2009/05/12 12:18:09 cegger Exp $ */
9 * Copyright (c) 2001 The NetBSD Foundation, Inc.
10 * All rights reserved.
12 * This code is derived from software contributed to The NetBSD Foundation
13 * by Lennart Augustsson (lennart@augustsson.net) and Tommy Bohlin
14 * (tommy@gatespace.com).
16 * Redistribution and use in source and binary forms, with or without
17 * modification, are permitted provided that the following conditions
19 * 1. Redistributions of source code must retain the above copyright
20 * notice, this list of conditions and the following disclaimer.
21 * 2. Redistributions in binary form must reproduce the above copyright
22 * notice, this list of conditions and the following disclaimer in the
23 * documentation and/or other materials provided with the distribution.
25 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
26 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
27 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
28 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
29 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
30 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
31 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
32 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
33 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
34 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35 * POSSIBILITY OF SUCH DAMAGE.
39 * Loosely based on ppp_tty.c.
40 * Framing and dongle handling written by Tommy Bohlin.
43 #include <sys/cdefs.h>
44 __KERNEL_RCSID(0, "$NetBSD: irframe_tty.c,v 1.57 2009/05/12 12:18:09 cegger Exp $");
46 #include <sys/param.h>
48 #include <sys/ioctl.h>
50 #include <sys/kernel.h>
51 #include <sys/mutex.h>
52 #include <sys/malloc.h>
54 #include <sys/systm.h>
55 #include <sys/device.h>
57 #include <sys/vnode.h>
59 #include <sys/kauth.h>
61 #include <dev/ir/ir.h>
62 #include <dev/ir/sir.h>
63 #include <dev/ir/irdaio.h>
64 #include <dev/ir/irframevar.h>
67 #define DPRINTF(x) if (irframetdebug) printf x
68 int irframetdebug
= 0;
75 /* Max size with framing. */
76 #define MAX_IRDA_FRAME (2*IRDA_MAX_FRAME_SIZE + IRDA_MAX_EBOFS + 4)
84 struct irframet_softc
{
85 struct irframe_softc sc_irp
;
89 int sc_dongle_private
;
92 #define IRT_RSLP 0x01 /* waiting for data (read) */
94 #define IRT_WSLP 0x02 /* waiting for data (write) */
95 #define IRT_CLOSING 0x04 /* waiting for output to drain */
99 struct irda_params sc_params
;
103 #define FRAME_OUTSIDE 0
104 #define FRAME_INSIDE 1
105 #define FRAME_ESCAPE 2
108 struct callout sc_timeout
;
113 struct irt_frame sc_frames
[MAXFRAMES
];
114 u_int8_t sc_buffer
[MAX_IRDA_FRAME
];
115 struct selinfo sc_rsel
;
116 /* XXXJRT Nothing selnotify's sc_wsel */
117 struct selinfo sc_wsel
;
120 /* line discipline methods */
121 int irframetopen(dev_t
, struct tty
*);
122 int irframetclose(struct tty
*, int);
123 int irframetioctl(struct tty
*, u_long
, void *, int, struct lwp
*);
124 int irframetinput(int, struct tty
*);
125 int irframetstart(struct tty
*);
127 /* pseudo device init */
128 void irframettyattach(int);
130 /* irframe methods */
131 static int irframet_open(void *, int, int, struct lwp
*);
132 static int irframet_close(void *, int, int, struct lwp
*);
133 static int irframet_read(void *, struct uio
*, int);
134 static int irframet_write(void *, struct uio
*, int);
135 static int irframet_poll(void *, int, struct lwp
*);
136 static int irframet_kqfilter(void *, struct knote
*);
138 static int irframet_set_params(void *, struct irda_params
*);
139 static int irframet_get_speeds(void *, int *);
140 static int irframet_get_turnarounds(void *, int *);
143 static int irt_write_frame(struct tty
*, u_int8_t
*, size_t);
144 static int irt_putc(struct tty
*, int);
145 static void irt_frame(struct irframet_softc
*, u_char
*, u_int
);
146 static void irt_timeout(void *);
147 static void irt_ioctl(struct tty
*, u_long
, void *);
148 static void irt_setspeed(struct tty
*, u_int
);
149 static void irt_setline(struct tty
*, u_int
);
150 static void irt_delay(struct tty
*, u_int
);
151 static void irt_buffer(struct irframet_softc
*, u_int
);
153 static const struct irframe_methods irframet_methods
= {
154 irframet_open
, irframet_close
, irframet_read
, irframet_write
,
155 irframet_poll
, irframet_kqfilter
, irframet_set_params
,
156 irframet_get_speeds
, irframet_get_turnarounds
159 static void irts_none(struct tty
*, u_int
);
160 static void irts_tekram(struct tty
*, u_int
);
161 static void irts_jeteye(struct tty
*, u_int
);
162 static void irts_actisys(struct tty
*, u_int
);
163 static void irts_litelink(struct tty
*, u_int
);
164 static void irts_girbil(struct tty
*, u_int
);
166 #define NORMAL_SPEEDS (IRDA_SPEEDS_SIR & ~IRDA_SPEED_2400)
167 #define TURNT_POS (IRDA_TURNT_10000 | IRDA_TURNT_5000 | IRDA_TURNT_1000 | \
168 IRDA_TURNT_500 | IRDA_TURNT_100 | IRDA_TURNT_50 | IRDA_TURNT_10)
169 static const struct dongle
{
170 void (*setspeed
)(struct tty
*, u_int
);
173 } irt_dongles
[DONGLE_MAX
] = {
174 /* Indexed by dongle number from irdaio.h */
175 { irts_none
, IRDA_SPEEDS_SIR
, IRDA_TURNT_10000
},
176 { irts_tekram
, IRDA_SPEEDS_SIR
, IRDA_TURNT_10000
},
177 { irts_jeteye
, IRDA_SPEED_9600
|IRDA_SPEED_19200
|IRDA_SPEED_115200
,
179 { irts_actisys
, NORMAL_SPEEDS
& ~IRDA_SPEED_38400
, TURNT_POS
},
180 { irts_actisys
, NORMAL_SPEEDS
, TURNT_POS
},
181 { irts_litelink
, NORMAL_SPEEDS
, TURNT_POS
},
182 { irts_girbil
, IRDA_SPEEDS_SIR
, IRDA_TURNT_10000
| IRDA_TURNT_5000
},
185 static struct linesw irframet_disc
= {
187 .l_open
= irframetopen
,
188 .l_close
= irframetclose
,
191 .l_ioctl
= irframetioctl
,
192 .l_rint
= irframetinput
,
193 .l_start
= irframetstart
,
198 /* glue to attach irframe device */
199 static void irframet_attach(device_t
, device_t
, void *);
200 static int irframet_detach(device_t
, int);
202 CFATTACH_DECL_NEW(irframet
, sizeof(struct irframet_softc
),
203 NULL
, irframet_attach
, irframet_detach
, NULL
);
206 irframettyattach(int n
)
208 extern struct cfdriver irframe_cd
;
210 (void) ttyldisc_attach(&irframet_disc
);
212 /* XXX might fail if "real" attachments have pulled this in */
213 /* XXX should not be done here */
214 config_cfdriver_attach(&irframe_cd
);
216 config_cfattach_attach("irframe", &irframet_ca
);
220 irframet_attach(device_t parent
, device_t self
, void *aux
)
222 struct irframet_softc
*sc
= device_private(self
);
224 /* pseudo-device attachment does not print name */
225 aprint_normal("%s", device_xname(self
));
227 callout_init(&sc
->sc_timeout
, 0);
228 mutex_init(&sc
->sc_wr_lk
, MUTEX_DEFAULT
, IPL_NONE
);
229 selinit(&sc
->sc_rsel
);
230 selinit(&sc
->sc_wsel
);
232 #if 0 /* XXX can't do it yet because pseudo-devices don't get aux */
233 struct ir_attach_args ia
;
235 ia
.ia_methods
= &irframet_methods
;
236 ia
.ia_handle
= aux
->xxx
;
238 irframe_attach(parent
, self
, &ia
);
243 irframet_detach(device_t dev
, int flags
)
245 struct irframet_softc
*sc
= device_private(dev
);
248 callout_stop(&sc
->sc_timeout
);
250 rc
= irframe_detach(dev
, flags
);
252 callout_destroy(&sc
->sc_timeout
);
253 mutex_destroy(&sc
->sc_wr_lk
);
254 seldestroy(&sc
->sc_wsel
);
255 seldestroy(&sc
->sc_rsel
);
261 * Line specific open routine for async tty devices.
262 * Attach the given tty to the first available irframe unit.
263 * Called from device open routine or ttioctl.
267 irframetopen(dev_t dev
, struct tty
*tp
)
269 struct lwp
*l
= curlwp
; /* XXX */
270 struct irframet_softc
*sc
;
273 struct ir_attach_args ia
;
276 DPRINTF(("%s\n", __func__
));
278 if ((error
= kauth_authorize_device_tty(l
->l_cred
,
279 KAUTH_DEVICE_TTY_OPEN
, tp
)))
284 DPRINTF(("%s: linesw=%p disc=%s\n", __func__
, tp
->t_linesw
,
285 tp
->t_linesw
->l_name
));
286 if (tp
->t_linesw
== &irframet_disc
) {
287 sc
= (struct irframet_softc
*)tp
->t_sc
;
288 DPRINTF(("%s: sc=%p sc_tp=%p\n", __func__
, sc
, sc
->sc_tp
));
295 cfdata
= malloc(sizeof(struct cfdata
), M_DEVBUF
, M_WAITOK
);
296 cfdata
->cf_name
= "irframe";
297 cfdata
->cf_atname
= "irframet";
298 cfdata
->cf_fstate
= FSTATE_STAR
;
300 d
= config_attach_pseudo(cfdata
);
301 sc
= device_private(d
);
302 sc
->sc_irp
.sc_dev
= d
;
304 /* XXX should be done in irframet_attach() */
305 ia
.ia_methods
= &irframet_methods
;
307 irframe_attach(0, d
, &ia
);
311 aprint_normal("%s attached at tty%02d\n", device_xname(d
),
312 (int)minor(tp
->t_dev
));
314 DPRINTF(("%s: set sc=%p\n", __func__
, sc
));
316 mutex_spin_enter(&tty_lock
);
317 ttyflush(tp
, FREAD
| FWRITE
);
318 mutex_spin_exit(&tty_lock
);
320 sc
->sc_dongle
= DONGLE_NONE
;
321 sc
->sc_dongle_private
= 0;
329 * Line specific close routine, called from device close routine
331 * Detach the tty from the irframe unit.
332 * Mimics part of ttyclose().
335 irframetclose(struct tty
*tp
, int flag
)
337 struct irframet_softc
*sc
= (struct irframet_softc
*)tp
->t_sc
;
341 DPRINTF(("%s: tp=%p\n", __func__
, tp
));
344 mutex_spin_enter(&tty_lock
);
345 ttyflush(tp
, FREAD
| FWRITE
);
346 mutex_spin_exit(&tty_lock
); /* XXX */
347 ttyldisc_release(tp
->t_linesw
);
348 tp
->t_linesw
= ttyldisc_default(); if (sc
!= NULL
) {
351 aprint_normal("%s detached from tty%02d\n",
352 device_xname(sc
->sc_irp
.sc_dev
), (int)minor(tp
->t_dev
));
354 if (sc
->sc_tp
== tp
) {
355 cfdata
= device_cfdata(sc
->sc_irp
.sc_dev
);
356 config_detach(sc
->sc_irp
.sc_dev
, 0);
357 free(cfdata
, M_DEVBUF
);
365 * Line specific (tty) ioctl routine.
366 * This discipline requires that tty device drivers call
367 * the line specific l_ioctl routine from their ioctl routines.
371 irframetioctl(struct tty
*tp
, u_long cmd
, void *data
, int flag
,
374 struct irframet_softc
*sc
= (struct irframet_softc
*)tp
->t_sc
;
378 DPRINTF(("%s: tp=%p\n", __func__
, tp
));
380 if (sc
== NULL
|| tp
!= sc
->sc_tp
)
381 return (EPASSTHROUGH
);
385 case IRFRAMETTY_GET_DEVICE
:
386 *(int *)data
= device_unit(sc
->sc_irp
.sc_dev
);
388 case IRFRAMETTY_GET_DONGLE
:
389 *(int *)data
= sc
->sc_dongle
;
391 case IRFRAMETTY_SET_DONGLE
:
393 if (d
< 0 || d
>= DONGLE_MAX
)
398 error
= EPASSTHROUGH
;
406 * Start output on async tty interface.
409 irframetstart(struct tty
*tp
)
411 /*struct irframet_softc *sc = (struct irframet_softc *)tp->t_sc;*/
414 DPRINTF(("%s: tp=%p\n", __func__
, tp
));
417 if (tp
->t_oproc
!= NULL
)
425 irt_buffer(struct irframet_softc
*sc
, u_int maxsize
)
429 DPRINTF(("%s: sc=%p, maxsize=%u\n", __func__
, sc
, maxsize
));
431 if (sc
->sc_params
.maxsize
!= maxsize
) {
432 sc
->sc_params
.maxsize
= maxsize
;
433 if (sc
->sc_inbuf
!= NULL
)
434 free(sc
->sc_inbuf
, M_DEVBUF
);
435 for (i
= 0; i
< MAXFRAMES
; i
++)
436 if (sc
->sc_frames
[i
].buf
!= NULL
)
437 free(sc
->sc_frames
[i
].buf
, M_DEVBUF
);
438 if (sc
->sc_params
.maxsize
!= 0) {
439 sc
->sc_inbuf
= malloc(sc
->sc_params
.maxsize
+2,
441 for (i
= 0; i
< MAXFRAMES
; i
++)
442 sc
->sc_frames
[i
].buf
=
443 malloc(sc
->sc_params
.maxsize
,
447 for (i
= 0; i
< MAXFRAMES
; i
++)
448 sc
->sc_frames
[i
].buf
= NULL
;
454 irt_frame(struct irframet_softc
*sc
, u_char
*tbuf
, u_int len
)
456 DPRINTF(("%s: nframe=%d framei=%d frameo=%d\n",
457 __func__
, sc
->sc_nframes
, sc
->sc_framei
, sc
->sc_frameo
));
459 if (sc
->sc_inbuf
== NULL
) /* XXX happens if device is closed? */
461 if (sc
->sc_nframes
>= MAXFRAMES
) {
462 #ifdef IRFRAMET_DEBUG
463 printf("%s: dropped frame\n", __func__
);
467 if (sc
->sc_frames
[sc
->sc_framei
].buf
== NULL
)
469 memcpy(sc
->sc_frames
[sc
->sc_framei
].buf
, tbuf
, len
);
470 sc
->sc_frames
[sc
->sc_framei
].len
= len
;
471 sc
->sc_framei
= (sc
->sc_framei
+1) % MAXFRAMES
;
473 if (sc
->sc_state
& IRT_RSLP
) {
474 sc
->sc_state
&= ~IRT_RSLP
;
475 DPRINTF(("%s: waking up reader\n", __func__
));
476 wakeup(sc
->sc_frames
);
478 selnotify(&sc
->sc_rsel
, 0, 0);
484 struct irframet_softc
*sc
= v
;
486 #ifdef IRFRAMET_DEBUG
487 if (sc
->sc_framestate
!= FRAME_OUTSIDE
)
488 printf("%s: input frame timeout\n", __func__
);
490 sc
->sc_framestate
= FRAME_OUTSIDE
;
494 irframetinput(int c
, struct tty
*tp
)
496 struct irframet_softc
*sc
= (struct irframet_softc
*)tp
->t_sc
;
501 if (irframetdebug
> 1)
502 DPRINTF(("%s: tp=%p c=0x%02x\n", __func__
, tp
, c
));
505 if (sc
== NULL
|| tp
!= (struct tty
*)sc
->sc_tp
)
508 if (sc
->sc_inbuf
== NULL
)
513 DPRINTF(("%s: BOF\n", __func__
));
514 sc
->sc_framestate
= FRAME_INSIDE
;
516 sc
->sc_inFCS
= INITFCS
;
519 DPRINTF(("%s: EOF state=%d inchars=%d fcs=0x%04x\n",
521 sc
->sc_framestate
, sc
->sc_inchars
, sc
->sc_inFCS
));
522 if (sc
->sc_framestate
== FRAME_INSIDE
&&
523 sc
->sc_inchars
>= 4 && sc
->sc_inFCS
== GOODFCS
) {
524 irt_frame(sc
, sc
->sc_inbuf
, sc
->sc_inchars
- 2);
525 } else if (sc
->sc_framestate
!= FRAME_OUTSIDE
) {
526 #ifdef IRFRAMET_DEBUG
527 printf("%s: malformed input frame\n", __func__
);
530 sc
->sc_framestate
= FRAME_OUTSIDE
;
533 DPRINTF(("%s: CE\n", __func__
));
534 if (sc
->sc_framestate
== FRAME_INSIDE
)
535 sc
->sc_framestate
= FRAME_ESCAPE
;
539 if (irframetdebug
> 1)
540 DPRINTF(("%s: c=0x%02x, inchar=%d state=%d\n", __func__
, c
,
541 sc
->sc_inchars
, sc
->sc_state
));
543 if (sc
->sc_framestate
!= FRAME_OUTSIDE
) {
544 if (sc
->sc_framestate
== FRAME_ESCAPE
) {
545 sc
->sc_framestate
= FRAME_INSIDE
;
548 if (sc
->sc_inchars
< sc
->sc_params
.maxsize
+ 2) {
549 sc
->sc_inbuf
[sc
->sc_inchars
++] = c
;
550 sc
->sc_inFCS
= updateFCS(sc
->sc_inFCS
, c
);
552 sc
->sc_framestate
= FRAME_OUTSIDE
;
553 #ifdef IRFRAMET_DEBUG
554 printf("%s: input frame overrun\n",
563 if (sc
->sc_framestate
!= FRAME_OUTSIDE
) {
564 callout_reset(&sc
->sc_timeout
, hz
/20, irt_timeout
, sc
);
572 /*** irframe methods ***/
575 irframet_open(void *h
, int flag
, int mode
,
579 struct irframet_softc
*sc
= (struct irframet_softc
*)tp
->t_sc
;
581 DPRINTF(("%s: tp=%p\n", __func__
, tp
));
583 sc
->sc_params
.speed
= 0;
584 sc
->sc_params
.ebofs
= IRDA_DEFAULT_EBOFS
;
585 sc
->sc_params
.maxsize
= 0;
586 sc
->sc_framestate
= FRAME_OUTSIDE
;
595 irframet_close(void *h
, int flag
, int mode
,
599 struct irframet_softc
*sc
= (struct irframet_softc
*)tp
->t_sc
;
602 DPRINTF(("%s: tp=%p\n", __func__
, tp
));
604 /* line discipline was closed */
608 callout_stop(&sc
->sc_timeout
);
617 irframet_read(void *h
, struct uio
*uio
, int flag
)
620 struct irframet_softc
*sc
= (struct irframet_softc
*)tp
->t_sc
;
624 DPRINTF(("%s: resid=%zd, iovcnt=%d, offset=%ld\n",
625 __func__
, uio
->uio_resid
, uio
->uio_iovcnt
,
626 (long)uio
->uio_offset
));
627 DPRINTF(("%s: nframe=%d framei=%d frameo=%d\n",
628 __func__
, sc
->sc_nframes
, sc
->sc_framei
, sc
->sc_frameo
));
632 while (sc
->sc_nframes
== 0) {
633 if (flag
& IO_NDELAY
) {
635 return (EWOULDBLOCK
);
637 sc
->sc_state
|= IRT_RSLP
;
638 DPRINTF(("%s: sleep\n", __func__
));
639 error
= tsleep(sc
->sc_frames
, PZERO
| PCATCH
, "irtrd", 0);
640 DPRINTF(("%s: woke, error=%d\n", __func__
, error
));
642 sc
->sc_state
&= ~IRT_RSLP
;
647 /* Do just one frame transfer per read */
649 if (uio
->uio_resid
< sc
->sc_frames
[sc
->sc_frameo
].len
) {
650 DPRINTF(("%s: uio buffer smaller than frame size "
651 "(%zd < %d)\n", __func__
, uio
->uio_resid
,
652 sc
->sc_frames
[sc
->sc_frameo
].len
));
655 DPRINTF(("%s: moving %d bytes\n", __func__
,
656 sc
->sc_frames
[sc
->sc_frameo
].len
));
657 error
= uiomove(sc
->sc_frames
[sc
->sc_frameo
].buf
,
658 sc
->sc_frames
[sc
->sc_frameo
].len
, uio
);
659 DPRINTF(("%s: error=%d\n", __func__
, error
));
661 sc
->sc_frameo
= (sc
->sc_frameo
+1) % MAXFRAMES
;
670 irt_putc(struct tty
*tp
, int c
)
675 if (irframetdebug
> 3)
676 DPRINTF(("%s: tp=%p c=0x%02x cc=%d\n", __func__
, tp
, c
,
679 if (tp
->t_outq
.c_cc
> tp
->t_hiwat
) {
681 mutex_spin_enter(&tty_lock
);
683 * This can only occur if FLUSHO is set in t_lflag,
684 * or if ttstart/oproc is synchronous (or very fast).
686 if (tp
->t_outq
.c_cc
<= tp
->t_hiwat
) {
687 mutex_spin_exit(&tty_lock
);
690 error
= ttysleep(tp
, &tp
->t_outcv
, true, 0);
691 mutex_spin_exit(&tty_lock
);
696 if (putc(c
, &tp
->t_outq
) < 0) {
697 printf("irframe: putc failed\n");
704 irframet_write(void *h
, struct uio
*uio
, int flag
)
707 struct irframet_softc
*sc
= (struct irframet_softc
*)tp
->t_sc
;
710 DPRINTF(("%s: resid=%zd, iovcnt=%d, offset=%ld\n",
711 __func__
, uio
->uio_resid
, uio
->uio_iovcnt
,
712 (long)uio
->uio_offset
));
714 n
= irda_sir_frame(sc
->sc_buffer
, sizeof(sc
->sc_buffer
), uio
,
715 sc
->sc_params
.ebofs
);
717 #ifdef IRFRAMET_DEBUG
718 printf("%s: irda_sir_frame() error=%d\n", __func__
, -n
);
722 return (irt_write_frame(tp
, sc
->sc_buffer
, n
));
726 irt_write_frame(struct tty
*tp
, u_int8_t
*tbuf
, size_t len
)
728 struct irframet_softc
*sc
= (struct irframet_softc
*)tp
->t_sc
;
731 DPRINTF(("%s: tp=%p len=%zd\n", __func__
, tp
, len
));
733 mutex_enter(&sc
->sc_wr_lk
);
735 for (i
= 0; !error
&& i
< len
; i
++)
736 error
= irt_putc(tp
, tbuf
[i
]);
737 mutex_exit(&sc
->sc_wr_lk
);
741 DPRINTF(("%s: done, error=%d\n", __func__
, error
));
747 irframet_poll(void *h
, int events
, struct lwp
*l
)
750 struct irframet_softc
*sc
= (struct irframet_softc
*)tp
->t_sc
;
754 DPRINTF(("%s: sc=%p\n", __func__
, sc
));
757 /* XXX is this a good check? */
758 if (events
& (POLLOUT
| POLLWRNORM
))
759 if (tp
->t_outq
.c_cc
<= tp
->t_lowat
)
760 revents
|= events
& (POLLOUT
| POLLWRNORM
);
762 if (events
& (POLLIN
| POLLRDNORM
)) {
763 if (sc
->sc_nframes
> 0) {
764 DPRINTF(("%s: have data\n", __func__
));
765 revents
|= events
& (POLLIN
| POLLRDNORM
);
767 DPRINTF(("%s: recording select\n", __func__
));
768 selrecord(l
, &sc
->sc_rsel
);
777 filt_irframetrdetach(struct knote
*kn
)
779 struct tty
*tp
= kn
->kn_hook
;
780 struct irframet_softc
*sc
= (struct irframet_softc
*)tp
->t_sc
;
784 SLIST_REMOVE(&sc
->sc_rsel
.sel_klist
, kn
, knote
, kn_selnext
);
789 filt_irframetread(struct knote
*kn
, long hint
)
791 struct tty
*tp
= kn
->kn_hook
;
792 struct irframet_softc
*sc
= (struct irframet_softc
*)tp
->t_sc
;
794 kn
->kn_data
= sc
->sc_nframes
;
795 return (kn
->kn_data
> 0);
799 filt_irframetwdetach(struct knote
*kn
)
801 struct tty
*tp
= kn
->kn_hook
;
802 struct irframet_softc
*sc
= (struct irframet_softc
*)tp
->t_sc
;
806 SLIST_REMOVE(&sc
->sc_wsel
.sel_klist
, kn
, knote
, kn_selnext
);
811 filt_irframetwrite(struct knote
*kn
, long hint
)
813 struct tty
*tp
= kn
->kn_hook
;
815 /* XXX double-check this */
817 if (tp
->t_outq
.c_cc
<= tp
->t_lowat
) {
818 kn
->kn_data
= tp
->t_lowat
- tp
->t_outq
.c_cc
;
826 static const struct filterops irframetread_filtops
=
827 { 1, NULL
, filt_irframetrdetach
, filt_irframetread
};
828 static const struct filterops irframetwrite_filtops
=
829 { 1, NULL
, filt_irframetwdetach
, filt_irframetwrite
};
832 irframet_kqfilter(void *h
, struct knote
*kn
)
835 struct irframet_softc
*sc
= (struct irframet_softc
*)tp
->t_sc
;
839 switch (kn
->kn_filter
) {
841 klist
= &sc
->sc_rsel
.sel_klist
;
842 kn
->kn_fop
= &irframetread_filtops
;
845 klist
= &sc
->sc_wsel
.sel_klist
;
846 kn
->kn_fop
= &irframetwrite_filtops
;
855 SLIST_INSERT_HEAD(klist
, kn
, kn_selnext
);
862 irframet_set_params(void *h
, struct irda_params
*p
)
865 struct irframet_softc
*sc
= (struct irframet_softc
*)tp
->t_sc
;
867 DPRINTF(("%s: tp=%p speed=%d ebofs=%d maxsize=%d\n",
868 __func__
, tp
, p
->speed
, p
->ebofs
, p
->maxsize
));
870 if (p
->speed
!= sc
->sc_params
.speed
) {
871 /* Checked in irframe.c */
872 mutex_enter(&sc
->sc_wr_lk
);
873 irt_dongles
[sc
->sc_dongle
].setspeed(tp
, p
->speed
);
874 mutex_exit(&sc
->sc_wr_lk
);
875 sc
->sc_params
.speed
= p
->speed
;
878 /* Max size checked in irframe.c */
879 sc
->sc_params
.ebofs
= p
->ebofs
;
880 irt_buffer(sc
, p
->maxsize
);
881 sc
->sc_framestate
= FRAME_OUTSIDE
;
887 irframet_get_speeds(void *h
, int *speeds
)
890 struct irframet_softc
*sc
= (struct irframet_softc
*)tp
->t_sc
;
892 DPRINTF(("%s: tp=%p\n", __func__
, tp
));
894 if (sc
== NULL
) /* during attach */
895 *speeds
= IRDA_SPEEDS_SIR
;
897 *speeds
= irt_dongles
[sc
->sc_dongle
].speedmask
;
902 irframet_get_turnarounds(void *h
, int *turnarounds
)
905 struct irframet_softc
*sc
= (struct irframet_softc
*)tp
->t_sc
;
907 DPRINTF(("%s: tp=%p\n", __func__
, tp
));
909 *turnarounds
= irt_dongles
[sc
->sc_dongle
].turnmask
;
914 irt_ioctl(struct tty
*tp
, u_long cmd
, void *arg
)
916 const struct cdevsw
*cdev
;
921 cdev
= cdevsw_lookup(dev
);
923 error
= (*cdev
->d_ioctl
)(dev
, cmd
, arg
, 0, curlwp
);
928 printf("irt_ioctl: cmd=0x%08lx error=%d\n", cmd
, error
);
933 irt_setspeed(struct tty
*tp
, u_int speed
)
937 irt_ioctl(tp
, TIOCGETA
, &tt
);
938 tt
.c_ispeed
= tt
.c_ospeed
= speed
;
939 tt
.c_cflag
&= ~HUPCL
;
940 tt
.c_cflag
|= CLOCAL
;
941 irt_ioctl(tp
, TIOCSETAF
, &tt
);
945 irt_setline(struct tty
*tp
, u_int line
)
949 irt_ioctl(tp
, TIOCMGET
, &mline
);
950 mline
&= ~(TIOCM_DTR
| TIOCM_RTS
);
952 irt_ioctl(tp
, TIOCMSET
, (void *)&mline
);
956 irt_delay(struct tty
*tp
, u_int ms
)
961 tsleep(&irt_delay
, PZERO
, "irtdly", ms
* hz
/ 1000 + 1);
965 /**********************************************************************
967 **********************************************************************/
969 irts_none(struct tty
*tp
, u_int speed
)
971 irt_setspeed(tp
, speed
);
974 /**********************************************************************
976 **********************************************************************/
977 #define TEKRAM_PW 0x10
979 #define TEKRAM_115200 (TEKRAM_PW|0x00)
980 #define TEKRAM_57600 (TEKRAM_PW|0x01)
981 #define TEKRAM_38400 (TEKRAM_PW|0x02)
982 #define TEKRAM_19200 (TEKRAM_PW|0x03)
983 #define TEKRAM_9600 (TEKRAM_PW|0x04)
984 #define TEKRAM_2400 (TEKRAM_PW|0x08)
986 #define TEKRAM_TV (TEKRAM_PW|0x05)
989 irts_tekram(struct tty
*tp
, u_int speed
)
993 irt_setspeed(tp
, 9600);
997 irt_setline(tp
, TIOCM_RTS
);
1000 irt_setline(tp
, TIOCM_DTR
| TIOCM_RTS
);
1001 irt_delay(tp
, 1); /* 50 us */
1003 irt_setline(tp
, TIOCM_DTR
);
1004 irt_delay(tp
, 1); /* 7 us */
1007 case 115200: s
= TEKRAM_115200
; break;
1008 case 57600: s
= TEKRAM_57600
; break;
1009 case 38400: s
= TEKRAM_38400
; break;
1010 case 19200: s
= TEKRAM_19200
; break;
1011 case 2400: s
= TEKRAM_2400
; break;
1012 default: s
= TEKRAM_9600
; break;
1019 irt_setline(tp
, TIOCM_DTR
| TIOCM_RTS
);
1021 irt_setspeed(tp
, speed
);
1022 irt_delay(tp
, 1); /* 50 us */
1025 /**********************************************************************
1027 **********************************************************************/
1029 irts_jeteye(struct tty
*tp
, u_int speed
)
1033 irt_setline(tp
, TIOCM_DTR
);
1036 irt_setline(tp
, TIOCM_DTR
| TIOCM_RTS
);
1039 irt_setline(tp
, TIOCM_RTS
);
1042 irt_setspeed(tp
, speed
);
1045 /**********************************************************************
1047 **********************************************************************/
1049 irts_actisys(struct tty
*tp
, u_int speed
)
1051 struct irframet_softc
*sc
= (struct irframet_softc
*)tp
->t_sc
;
1054 irt_setspeed(tp
, speed
);
1057 case 19200: pulses
=1; break;
1058 case 57600: pulses
=2; break;
1059 case 115200: pulses
=3; break;
1060 case 38400: pulses
=4; break;
1061 default: /* 9600 */ pulses
=0; break;
1064 if (sc
->sc_dongle_private
== 0) {
1065 sc
->sc_dongle_private
= 1;
1066 irt_setline(tp
, TIOCM_DTR
| TIOCM_RTS
);
1068 * Must wait at least 50ms after initial
1069 * power on to charge internal capacitor
1073 irt_setline(tp
, TIOCM_RTS
);
1076 irt_setline(tp
, TIOCM_DTR
| TIOCM_RTS
);
1080 irt_setline(tp
, TIOCM_DTR
);
1085 /**********************************************************************
1087 **********************************************************************/
1089 irts_litelink(struct tty
*tp
, u_int speed
)
1091 struct irframet_softc
*sc
= (struct irframet_softc
*)tp
->t_sc
;
1094 irt_setspeed(tp
, speed
);
1097 case 57600: pulses
=1; break;
1098 case 38400: pulses
=2; break;
1099 case 19200: pulses
=3; break;
1100 case 9600: pulses
=4; break;
1101 default: /* 115200 */ pulses
=0; break;
1104 if (sc
->sc_dongle_private
== 0) {
1105 sc
->sc_dongle_private
= 1;
1106 irt_setline(tp
, TIOCM_DTR
| TIOCM_RTS
);
1108 irt_setline(tp
, TIOCM_RTS
);
1109 irt_delay(tp
, 1); /* 15 us */;
1111 irt_setline(tp
, TIOCM_DTR
| TIOCM_RTS
);
1112 irt_delay(tp
, 1); /* 15 us */;
1115 irt_setline(tp
, TIOCM_DTR
);
1116 irt_delay(tp
, 1); /* 15 us */;
1120 /**********************************************************************
1122 **********************************************************************/
1123 /* Control register 1 */
1124 #define GIRBIL_TXEN 0x01 /* Enable transmitter */
1125 #define GIRBIL_RXEN 0x02 /* Enable receiver */
1126 #define GIRBIL_ECAN 0x04 /* Cancel self emmited data */
1127 #define GIRBIL_ECHO 0x08 /* Echo control characters */
1129 /* LED Current Register */
1130 #define GIRBIL_HIGH 0x20
1131 #define GIRBIL_MEDIUM 0x21
1132 #define GIRBIL_LOW 0x22
1135 #define GIRBIL_2400 0x30
1136 #define GIRBIL_4800 0x31
1137 #define GIRBIL_9600 0x32
1138 #define GIRBIL_19200 0x33
1139 #define GIRBIL_38400 0x34
1140 #define GIRBIL_57600 0x35
1141 #define GIRBIL_115200 0x36
1144 #define GIRBIL_IRDA 0x40
1145 #define GIRBIL_ASK 0x41
1147 /* Control register 2 */
1148 #define GIRBIL_LOAD 0x51 /* Load the new baud rate value */
1151 irts_girbil(struct tty
*tp
, u_int speed
)
1155 irt_setspeed(tp
, 9600);
1156 irt_setline(tp
, TIOCM_DTR
);
1158 irt_setline(tp
, TIOCM_RTS
);
1161 case 115200: s
= GIRBIL_115200
; break;
1162 case 57600: s
= GIRBIL_57600
; break;
1163 case 38400: s
= GIRBIL_38400
; break;
1164 case 19200: s
= GIRBIL_19200
; break;
1165 case 4800: s
= GIRBIL_4800
; break;
1166 case 2400: s
= GIRBIL_2400
; break;
1167 default: s
= GIRBIL_9600
; break;
1169 irt_putc(tp
, GIRBIL_TXEN
|GIRBIL_RXEN
);
1171 irt_putc(tp
, GIRBIL_LOAD
);
1174 irt_setline(tp
, TIOCM_DTR
| TIOCM_RTS
);
1176 irt_setspeed(tp
, speed
);