irframe_tty.c revision 1.14 1 /* $NetBSD: irframe_tty.c,v 1.14 2001/12/13 15:09:07 augustss Exp $ */
2
3 /*
4 * TODO
5 * Implement dongle support.
6 * Test!!!
7 * Get rid of MAX_IRDA_FRAME
8 */
9
10 /*
11 * Copyright (c) 2001 The NetBSD Foundation, Inc.
12 * All rights reserved.
13 *
14 * This code is derived from software contributed to The NetBSD Foundation
15 * by Lennart Augustsson (lennart (at) augustsson.net) and Tommy Bohlin
16 * (tommy (at) gatespace.com).
17 *
18 * Redistribution and use in source and binary forms, with or without
19 * modification, are permitted provided that the following conditions
20 * are met:
21 * 1. Redistributions of source code must retain the above copyright
22 * notice, this list of conditions and the following disclaimer.
23 * 2. Redistributions in binary form must reproduce the above copyright
24 * notice, this list of conditions and the following disclaimer in the
25 * documentation and/or other materials provided with the distribution.
26 * 3. All advertising materials mentioning features or use of this software
27 * must display the following acknowledgement:
28 * This product includes software developed by the NetBSD
29 * Foundation, Inc. and its contributors.
30 * 4. Neither the name of The NetBSD Foundation nor the names of its
31 * contributors may be used to endorse or promote products derived
32 * from this software without specific prior written permission.
33 *
34 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
35 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
36 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
37 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
38 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
39 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
40 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
41 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
42 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
43 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
44 * POSSIBILITY OF SUCH DAMAGE.
45 */
46
47 /*
48 * Loosely based on ppp_tty.c.
49 * Framing and dongle handling written by Tommy Bohlin.
50 */
51
52 #include <sys/param.h>
53 #include <sys/proc.h>
54 #include <sys/ioctl.h>
55 #include <sys/tty.h>
56 #include <sys/kernel.h>
57 #include <sys/malloc.h>
58 #include <sys/conf.h>
59 #include <sys/systm.h>
60 #include <sys/device.h>
61 #include <sys/file.h>
62 #include <sys/vnode.h>
63 #include <sys/poll.h>
64
65 #include <dev/ir/ir.h>
66 #include <dev/ir/sir.h>
67 #include <dev/ir/irdaio.h>
68 #include <dev/ir/irframevar.h>
69
70 /* Macros to clear/set/test flags. */
71 #define SET(t, f) (t) |= (f)
72 #define CLR(t, f) (t) &= ~(f)
73 #define ISSET(t, f) ((t) & (f))
74
75 #ifdef IRFRAMET_DEBUG
76 #define DPRINTF(x) if (irframetdebug) printf x
77 #define Static
78 int irframetdebug = 0;
79 #else
80 #define DPRINTF(x)
81 #define Static static
82 #endif
83
84 /*****/
85
86 /* Max size with framing. */
87 #define MAX_IRDA_FRAME (2*IRDA_MAX_FRAME_SIZE + IRDA_MAX_EBOFS + 4)
88
89 struct frame {
90 u_char *buf;
91 u_int len;
92 };
93 #define MAXFRAMES 4
94
95 struct irframet_softc {
96 struct irframe_softc sc_irp;
97 struct tty *sc_tp;
98
99 int sc_dongle;
100 int sc_dongle_private;
101
102 int sc_state;
103 #define IRT_RSLP 0x01 /* waiting for data (read) */
104 #if 0
105 #define IRT_WSLP 0x02 /* waiting for data (write) */
106 #define IRT_CLOSING 0x04 /* waiting for output to drain */
107 #endif
108
109 int sc_ebofs;
110 int sc_speed;
111
112 u_char* sc_inbuf;
113 int sc_maxsize;
114 int sc_framestate;
115 #define FRAME_OUTSIDE 0
116 #define FRAME_INSIDE 1
117 #define FRAME_ESCAPE 2
118 int sc_inchars;
119 int sc_inFCS;
120 struct callout sc_timeout;
121
122 u_int sc_nframes;
123 u_int sc_framei;
124 u_int sc_frameo;
125 struct frame sc_frames[MAXFRAMES];
126 struct selinfo sc_rsel;
127 };
128
129 /* line discipline methods */
130 int irframetopen(dev_t dev, struct tty *tp);
131 int irframetclose(struct tty *tp, int flag);
132 int irframetioctl(struct tty *tp, u_long cmd, caddr_t data, int flag,
133 struct proc *);
134 int irframetinput(int c, struct tty *tp);
135 int irframetstart(struct tty *tp);
136
137 /* pseudo device init */
138 void irframettyattach(int);
139
140 /* irframe methods */
141 Static int irframet_open(void *h, int flag, int mode, struct proc *p);
142 Static int irframet_close(void *h, int flag, int mode, struct proc *p);
143 Static int irframet_read(void *h, struct uio *uio, int flag);
144 Static int irframet_write(void *h, struct uio *uio, int flag);
145 Static int irframet_poll(void *h, int events, struct proc *p);
146 Static int irframet_set_params(void *h, struct irda_params *params);
147 Static int irframet_get_speeds(void *h, int *speeds);
148 Static int irframet_get_turnarounds(void *h, int *times);
149
150 /* internal */
151 Static int irt_write_frame(struct tty *tp, u_int8_t *buf, size_t len);
152 Static int irt_putc(struct tty *tp, int c);
153 Static void irt_frame(struct irframet_softc *sc, u_char *buf, u_int len);
154 Static void irt_timeout(void *v);
155 Static void irt_setspeed(struct tty *tp, u_int speed);
156 Static void irt_setline(struct tty *tp, u_int line);
157 Static void irt_delay(struct tty *tp, u_int delay);
158
159 Static const struct irframe_methods irframet_methods = {
160 irframet_open, irframet_close, irframet_read, irframet_write,
161 irframet_poll, irframet_set_params,
162 irframet_get_speeds, irframet_get_turnarounds
163 };
164
165 Static void irts_none(struct tty *tp, u_int speed);
166 Static void irts_tekram(struct tty *tp, u_int speed);
167 Static void irts_jeteye(struct tty *tp, u_int speed);
168 Static void irts_actisys(struct tty *tp, u_int speed);
169 Static void irts_litelink(struct tty *tp, u_int speed);
170 Static void irts_girbil(struct tty *tp, u_int speed);
171
172 #define NORMAL_SPEEDS (IRDA_SPEEDS_SIR & ~IRDA_SPEED_2400)
173 #define TURNT_POS (IRDA_TURNT_10000 | IRDA_TURNT_5000 | IRDA_TURNT_1000 | \
174 IRDA_TURNT_500 | IRDA_TURNT_100 | IRDA_TURNT_50 | IRDA_TURNT_10)
175 Static const struct dongle {
176 void (*setspeed)(struct tty *tp, u_int speed);
177 u_int speedmask;
178 u_int turnmask;
179 } irt_dongles[DONGLE_MAX] = {
180 /* Indexed by dongle number from irdaio.h */
181 { irts_none, IRDA_SPEEDS_SIR, IRDA_TURNT_10000 },
182 { irts_tekram, IRDA_SPEEDS_SIR, IRDA_TURNT_10000 },
183 { irts_jeteye, IRDA_SPEED_9600|IRDA_SPEED_19200|IRDA_SPEED_115200,
184 IRDA_TURNT_10000 },
185 { irts_actisys, NORMAL_SPEEDS & ~IRDA_SPEED_38400, TURNT_POS },
186 { irts_actisys, NORMAL_SPEEDS, TURNT_POS },
187 { irts_litelink, NORMAL_SPEEDS, TURNT_POS },
188 { irts_girbil, IRDA_SPEEDS_SIR, IRDA_TURNT_10000 | IRDA_TURNT_5000 },
189 };
190
191 void
192 irframettyattach(int n)
193 {
194 }
195
196 /*
197 * Line specific open routine for async tty devices.
198 * Attach the given tty to the first available irframe unit.
199 * Called from device open routine or ttioctl.
200 */
201 /* ARGSUSED */
202 int
203 irframetopen(dev_t dev, struct tty *tp)
204 {
205 struct proc *p = curproc; /* XXX */
206 struct irframet_softc *sc;
207 int error, s;
208
209 DPRINTF(("%s\n", __FUNCTION__));
210
211 if ((error = suser(p->p_ucred, &p->p_acflag)) != 0)
212 return (error);
213
214 s = spltty();
215
216 DPRINTF(("%s: linesw=%p disc=%s\n", __FUNCTION__, tp->t_linesw,
217 tp->t_linesw->l_name));
218 if (strcmp(tp->t_linesw->l_name, "irframe") == 0) { /* XXX */
219 sc = (struct irframet_softc *)tp->t_sc;
220 DPRINTF(("%s: sc=%p sc_tp=%p\n", __FUNCTION__, sc, sc->sc_tp));
221 if (sc != NULL) {
222 splx(s);
223 return (EBUSY);
224 }
225 }
226
227 tp->t_sc = irframe_alloc(sizeof (struct irframet_softc),
228 &irframet_methods, tp);
229 sc = (struct irframet_softc *)tp->t_sc;
230 sc->sc_tp = tp;
231 printf("%s attached at tty%02d\n", sc->sc_irp.sc_dev.dv_xname,
232 minor(tp->t_dev));
233
234 DPRINTF(("%s: set sc=%p\n", __FUNCTION__, sc));
235
236 ttyflush(tp, FREAD | FWRITE);
237
238 sc->sc_dongle = DONGLE_NONE;
239 sc->sc_dongle_private = 0;
240
241 splx(s);
242
243 return (0);
244 }
245
246 /*
247 * Line specific close routine, called from device close routine
248 * and from ttioctl.
249 * Detach the tty from the irframe unit.
250 * Mimics part of ttyclose().
251 */
252 int
253 irframetclose(struct tty *tp, int flag)
254 {
255 struct irframet_softc *sc = (struct irframet_softc *)tp->t_sc;
256 int s;
257
258 DPRINTF(("%s: tp=%p\n", __FUNCTION__, tp));
259
260 s = spltty();
261 ttyflush(tp, FREAD | FWRITE);
262 tp->t_linesw = linesw[0]; /* default line discipline */
263 if (sc != NULL) {
264 tp->t_sc = NULL;
265 printf("%s detached from tty%02d\n", sc->sc_irp.sc_dev.dv_xname,
266 minor(tp->t_dev));
267
268 if (sc->sc_tp == tp)
269 irframe_dealloc(&sc->sc_irp.sc_dev);
270 }
271 splx(s);
272 return (0);
273 }
274
275 /*
276 * Line specific (tty) ioctl routine.
277 * This discipline requires that tty device drivers call
278 * the line specific l_ioctl routine from their ioctl routines.
279 */
280 /* ARGSUSED */
281 int
282 irframetioctl(struct tty *tp, u_long cmd, caddr_t data, int flag,
283 struct proc *p)
284 {
285 struct irframet_softc *sc = (struct irframet_softc *)tp->t_sc;
286 int error;
287 int d;
288
289 DPRINTF(("%s: tp=%p\n", __FUNCTION__, tp));
290
291 if (sc == NULL || tp != sc->sc_tp)
292 return (-1);
293
294 error = 0;
295 switch (cmd) {
296 case IRFRAMETTY_GET_DEVICE:
297 *(int *)data = sc->sc_irp.sc_dev.dv_unit;
298 break;
299 case IRFRAMETTY_GET_DONGLE:
300 *(int *)data = sc->sc_dongle;
301 break;
302 case IRFRAMETTY_SET_DONGLE:
303 d = *(int *)data;
304 if (d < 0 || d >= DONGLE_MAX)
305 return (EINVAL);
306 sc->sc_dongle = d;
307 break;
308 default:
309 error = EINVAL;
310 break;
311 }
312
313 return (error);
314 }
315
316 /*
317 * Start output on async tty interface.
318 * Called at spltty or higher.
319 */
320 int
321 irframetstart(struct tty *tp)
322 {
323 /*struct irframet_softc *sc = (struct irframet_softc *)tp->t_sc;*/
324
325 DPRINTF(("%s: tp=%p\n", __FUNCTION__, tp));
326
327 if (tp->t_oproc != NULL)
328 (*tp->t_oproc)(tp);
329
330 return (0);
331 }
332
333 void
334 irt_frame(struct irframet_softc *sc, u_char *buf, u_int len)
335 {
336 DPRINTF(("%s: nframe=%d framei=%d frameo=%d\n",
337 __FUNCTION__, sc->sc_nframes, sc->sc_framei, sc->sc_frameo));
338
339 if (sc->sc_nframes >= MAXFRAMES) {
340 #ifdef IRFRAMET_DEBUG
341 printf("%s: dropped frame\n", __FUNCTION__);
342 #endif
343 return;
344 }
345 if (sc->sc_frames[sc->sc_framei].buf == NULL)
346 return;
347 memcpy(sc->sc_frames[sc->sc_framei].buf, buf, len);
348 sc->sc_frames[sc->sc_framei].len = len;
349 sc->sc_framei = (sc->sc_framei+1) % MAXFRAMES;
350 sc->sc_nframes++;
351 if (sc->sc_state & IRT_RSLP) {
352 sc->sc_state &= ~IRT_RSLP;
353 DPRINTF(("%s: waking up reader\n", __FUNCTION__));
354 wakeup(sc->sc_frames);
355 }
356 selwakeup(&sc->sc_rsel);
357 }
358
359 void
360 irt_timeout(void *v)
361 {
362 struct irframet_softc *sc = v;
363
364 #ifdef IRFRAMET_DEBUG
365 if (sc->sc_framestate != FRAME_OUTSIDE)
366 printf("%s: input frame timeout\n", __FUNCTION__);
367 #endif
368 sc->sc_framestate = FRAME_OUTSIDE;
369 }
370
371 int
372 irframetinput(int c, struct tty *tp)
373 {
374 struct irframet_softc *sc = (struct irframet_softc *)tp->t_sc;
375
376 c &= 0xff;
377
378 #if IRFRAMET_DEBUG
379 if (irframetdebug > 1)
380 DPRINTF(("%s: tp=%p c=0x%02x\n", __FUNCTION__, tp, c));
381 #endif
382
383 if (sc == NULL || tp != (struct tty *)sc->sc_tp)
384 return (0);
385
386 if (sc->sc_inbuf == NULL)
387 return (0);
388
389 switch (c) {
390 case SIR_BOF:
391 DPRINTF(("%s: BOF\n", __FUNCTION__));
392 sc->sc_framestate = FRAME_INSIDE;
393 sc->sc_inchars = 0;
394 sc->sc_inFCS = INITFCS;
395 break;
396 case SIR_EOF:
397 DPRINTF(("%s: EOF state=%d inchars=%d fcs=0x%04x\n",
398 __FUNCTION__,
399 sc->sc_framestate, sc->sc_inchars, sc->sc_inFCS));
400 if (sc->sc_framestate == FRAME_INSIDE &&
401 sc->sc_inchars >= 4 && sc->sc_inFCS == GOODFCS) {
402 irt_frame(sc, sc->sc_inbuf, sc->sc_inchars - 2);
403 } else if (sc->sc_framestate != FRAME_OUTSIDE) {
404 #ifdef IRFRAMET_DEBUG
405 printf("%s: malformed input frame\n", __FUNCTION__);
406 #endif
407 }
408 sc->sc_framestate = FRAME_OUTSIDE;
409 break;
410 case SIR_CE:
411 DPRINTF(("%s: CE\n", __FUNCTION__));
412 if (sc->sc_framestate == FRAME_INSIDE)
413 sc->sc_framestate = FRAME_ESCAPE;
414 break;
415 default:
416 #if IRFRAMET_DEBUG
417 if (irframetdebug > 1)
418 DPRINTF(("%s: c=0x%02x, inchar=%d state=%d\n", __FUNCTION__, c,
419 sc->sc_inchars, sc->sc_state));
420 #endif
421 if (sc->sc_framestate != FRAME_OUTSIDE) {
422 if (sc->sc_framestate == FRAME_ESCAPE) {
423 sc->sc_framestate = FRAME_INSIDE;
424 c ^= SIR_ESC_BIT;
425 }
426 if (sc->sc_inchars < sc->sc_maxsize + 2) {
427 sc->sc_inbuf[sc->sc_inchars++] = c;
428 sc->sc_inFCS = updateFCS(sc->sc_inFCS, c);
429 } else {
430 sc->sc_framestate = FRAME_OUTSIDE;
431 #ifdef IRFRAMET_DEBUG
432 printf("%s: input frame overrun\n",
433 __FUNCTION__);
434 #endif
435 }
436 }
437 break;
438 }
439
440 #if 1
441 if (sc->sc_framestate != FRAME_OUTSIDE) {
442 callout_reset(&sc->sc_timeout, hz/20, irt_timeout, sc);
443 }
444 #endif
445
446 return (0);
447 }
448
449
450 /*** irframe methods ***/
451
452 int
453 irframet_open(void *h, int flag, int mode, struct proc *p)
454 {
455 struct tty *tp = h;
456 struct irframet_softc *sc = (struct irframet_softc *)tp->t_sc;
457
458 DPRINTF(("%s: tp=%p\n", __FUNCTION__, tp));
459
460 sc->sc_speed = 0;
461 sc->sc_ebofs = IRDA_DEFAULT_EBOFS;
462 sc->sc_maxsize = 0;
463 sc->sc_framestate = FRAME_OUTSIDE;
464 sc->sc_nframes = 0;
465 sc->sc_framei = 0;
466 sc->sc_frameo = 0;
467 callout_init(&sc->sc_timeout);
468
469 return (0);
470 }
471
472 int
473 irframet_close(void *h, int flag, int mode, struct proc *p)
474 {
475 struct tty *tp = h;
476 struct irframet_softc *sc = (struct irframet_softc *)tp->t_sc;
477 int i, s;
478
479 DPRINTF(("%s: tp=%p\n", __FUNCTION__, tp));
480
481 callout_stop(&sc->sc_timeout);
482 s = splir();
483 if (sc->sc_inbuf != NULL) {
484 free(sc->sc_inbuf, M_DEVBUF);
485 sc->sc_inbuf = NULL;
486 }
487 for (i = 0; i < MAXFRAMES; i++) {
488 if (sc->sc_frames[i].buf != NULL) {
489 free(sc->sc_frames[i].buf, M_DEVBUF);
490 sc->sc_frames[i].buf = NULL;
491 }
492 }
493 splx(s);
494
495 return (0);
496 }
497
498 int
499 irframet_read(void *h, struct uio *uio, int flag)
500 {
501 struct tty *tp = h;
502 struct irframet_softc *sc = (struct irframet_softc *)tp->t_sc;
503 int error = 0;
504 int s;
505
506 DPRINTF(("%s: resid=%d, iovcnt=%d, offset=%ld\n",
507 __FUNCTION__, uio->uio_resid, uio->uio_iovcnt,
508 (long)uio->uio_offset));
509 DPRINTF(("%s: nframe=%d framei=%d frameo=%d\n",
510 __FUNCTION__, sc->sc_nframes, sc->sc_framei, sc->sc_frameo));
511
512
513 s = splir();
514 while (sc->sc_nframes == 0) {
515 if (flag & IO_NDELAY) {
516 splx(s);
517 return (EWOULDBLOCK);
518 }
519 sc->sc_state |= IRT_RSLP;
520 DPRINTF(("%s: sleep\n", __FUNCTION__));
521 error = tsleep(sc->sc_frames, PZERO | PCATCH, "irtrd", 0);
522 DPRINTF(("%s: woke, error=%d\n", __FUNCTION__, error));
523 if (error) {
524 sc->sc_state &= ~IRT_RSLP;
525 break;
526 }
527 }
528
529 /* Do just one frame transfer per read */
530 if (!error) {
531 if (uio->uio_resid < sc->sc_frames[sc->sc_frameo].len) {
532 DPRINTF(("%s: uio buffer smaller than frame size (%d < %d)\n", __FUNCTION__, uio->uio_resid, sc->sc_frames[sc->sc_frameo].len));
533 error = EINVAL;
534 } else {
535 DPRINTF(("%s: moving %d bytes\n", __FUNCTION__,
536 sc->sc_frames[sc->sc_frameo].len));
537 error = uiomove(sc->sc_frames[sc->sc_frameo].buf,
538 sc->sc_frames[sc->sc_frameo].len, uio);
539 DPRINTF(("%s: error=%d\n", __FUNCTION__, error));
540 }
541 sc->sc_frameo = (sc->sc_frameo+1) % MAXFRAMES;
542 sc->sc_nframes--;
543 }
544 splx(s);
545
546 return (error);
547 }
548
549 int
550 irt_putc(struct tty *tp, int c)
551 {
552 int s;
553 int error;
554
555 #if IRFRAMET_DEBUG
556 if (irframetdebug > 3)
557 DPRINTF(("%s: tp=%p c=0x%02x cc=%d\n", __FUNCTION__, tp, c,
558 tp->t_outq.c_cc));
559 #endif
560 if (tp->t_outq.c_cc > tp->t_hiwat) {
561 irframetstart(tp);
562 s = spltty();
563 /*
564 * This can only occur if FLUSHO is set in t_lflag,
565 * or if ttstart/oproc is synchronous (or very fast).
566 */
567 if (tp->t_outq.c_cc <= tp->t_hiwat) {
568 splx(s);
569 goto go;
570 }
571 SET(tp->t_state, TS_ASLEEP);
572 error = ttysleep(tp, &tp->t_outq, TTOPRI | PCATCH, ttyout, 0);
573 splx(s);
574 if (error)
575 return (error);
576 }
577 go:
578 if (putc(c, &tp->t_outq) < 0) {
579 printf("irframe: putc failed\n");
580 return (EIO);
581 }
582 return (0);
583 }
584
585 int
586 irframet_write(void *h, struct uio *uio, int flag)
587 {
588 struct tty *tp = h;
589 struct irframet_softc *sc = (struct irframet_softc *)tp->t_sc;
590 u_int8_t buf[MAX_IRDA_FRAME];
591 int n;
592
593 DPRINTF(("%s: resid=%d, iovcnt=%d, offset=%ld\n",
594 __FUNCTION__, uio->uio_resid, uio->uio_iovcnt,
595 (long)uio->uio_offset));
596
597 n = irda_sir_frame(buf, MAX_IRDA_FRAME, uio, sc->sc_ebofs);
598 if (n < 0) {
599 #ifdef IRFRAMET_DEBUG
600 printf("%s: irda_sir_frame() error=%d\n", __FUNCTION__, -n);
601 #endif
602 return (-n);
603 }
604 return (irt_write_frame(tp, buf, n));
605 }
606
607 int
608 irt_write_frame(struct tty *tp, u_int8_t *buf, size_t len)
609 {
610 int error, i;
611
612 DPRINTF(("%s: tp=%p len=%d\n", __FUNCTION__, tp, len));
613
614 error = 0;
615 for (i = 0; !error && i < len; i++)
616 error = irt_putc(tp, buf[i]);
617
618 irframetstart(tp);
619
620 DPRINTF(("%s: done, error=%d\n", __FUNCTION__, error));
621
622 return (error);
623 }
624
625 int
626 irframet_poll(void *h, int events, struct proc *p)
627 {
628 struct tty *tp = h;
629 struct irframet_softc *sc = (struct irframet_softc *)tp->t_sc;
630 int revents = 0;
631 int s;
632
633 DPRINTF(("%s: sc=%p\n", __FUNCTION__, sc));
634
635 s = splir();
636 /* XXX is this a good check? */
637 if (events & (POLLOUT | POLLWRNORM))
638 if (tp->t_outq.c_cc <= tp->t_lowat)
639 revents |= events & (POLLOUT | POLLWRNORM);
640
641 if (events & (POLLIN | POLLRDNORM)) {
642 if (sc->sc_nframes > 0) {
643 DPRINTF(("%s: have data\n", __FUNCTION__));
644 revents |= events & (POLLIN | POLLRDNORM);
645 } else {
646 DPRINTF(("%s: recording select\n", __FUNCTION__));
647 selrecord(p, &sc->sc_rsel);
648 }
649 }
650 splx(s);
651
652 return (revents);
653 }
654
655 int
656 irframet_set_params(void *h, struct irda_params *p)
657 {
658 struct tty *tp = h;
659 struct irframet_softc *sc = (struct irframet_softc *)tp->t_sc;
660 int i;
661
662 DPRINTF(("%s: tp=%p speed=%d ebofs=%d maxsize=%d\n",
663 __FUNCTION__, tp, p->speed, p->ebofs, p->maxsize));
664
665 if (p->speed != sc->sc_speed) {
666 /* Checked in irframe.c */
667 irt_dongles[sc->sc_dongle].setspeed(tp, p->speed);
668 sc->sc_speed = p->speed;
669 }
670
671 /* Max size checked in irframe.c */
672 sc->sc_ebofs = p->ebofs;
673 /* Max size checked in irframe.c */
674 if (sc->sc_maxsize != p->maxsize) {
675 sc->sc_maxsize = p->maxsize;
676 if (sc->sc_inbuf != NULL)
677 free(sc->sc_inbuf, M_DEVBUF);
678 for (i = 0; i < MAXFRAMES; i++)
679 if (sc->sc_frames[i].buf != NULL)
680 free(sc->sc_frames[i].buf, M_DEVBUF);
681 if (sc->sc_maxsize != 0) {
682 sc->sc_inbuf = malloc(sc->sc_maxsize+2, M_DEVBUF,
683 M_WAITOK);
684 for (i = 0; i < MAXFRAMES; i++)
685 sc->sc_frames[i].buf = malloc(sc->sc_maxsize,
686 M_DEVBUF, M_WAITOK);
687 } else {
688 sc->sc_inbuf = NULL;
689 for (i = 0; i < MAXFRAMES; i++)
690 sc->sc_frames[i].buf = NULL;
691 }
692 }
693 sc->sc_framestate = FRAME_OUTSIDE;
694
695 return (0);
696 }
697
698 int
699 irframet_get_speeds(void *h, int *speeds)
700 {
701 struct tty *tp = h;
702 struct irframet_softc *sc = (struct irframet_softc *)tp->t_sc;
703
704 DPRINTF(("%s: tp=%p\n", __FUNCTION__, tp));
705
706 if (sc == NULL) /* during attach */
707 *speeds = IRDA_SPEEDS_SIR;
708 else
709 *speeds = irt_dongles[sc->sc_dongle].speedmask;
710 return (0);
711 }
712
713 int
714 irframet_get_turnarounds(void *h, int *turnarounds)
715 {
716 struct tty *tp = h;
717 struct irframet_softc *sc = (struct irframet_softc *)tp->t_sc;
718
719 DPRINTF(("%s: tp=%p\n", __FUNCTION__, tp));
720
721 *turnarounds = irt_dongles[sc->sc_dongle].turnmask;
722 return (0);
723 }
724
725 void
726 irt_setspeed(struct tty *tp, u_int speed)
727 {
728 struct termios tt;
729
730 ttioctl(tp, TIOCGETA, (caddr_t)&tt, 0, curproc);
731 tt.c_ispeed = tt.c_ospeed = speed;
732 ttioctl(tp, TIOCSETAF, (caddr_t)&tt, 0, curproc);
733 }
734
735 void
736 irt_setline(struct tty *tp, u_int line)
737 {
738 int mline = line;
739 ttioctl(tp, TIOCMSET, (caddr_t)&mline, 0, curproc);
740 }
741
742 void
743 irt_delay(struct tty *tp, u_int ms)
744 {
745 if (cold)
746 delay(ms * 1000);
747 else
748 tsleep(&irt_delay, PZERO, "irtdly", ms * hz / 1000 + 1);
749
750 }
751
752 /**********************************************************************
753 * No dongle
754 **********************************************************************/
755 void
756 irts_none(struct tty *tp, u_int speed)
757 {
758 irt_setspeed(tp, speed);
759 }
760
761 /**********************************************************************
762 * Tekram
763 **********************************************************************/
764 #define TEKRAM_PW 0x10
765
766 #define TEKRAM_115200 (TEKRAM_PW|0x00)
767 #define TEKRAM_57600 (TEKRAM_PW|0x01)
768 #define TEKRAM_38400 (TEKRAM_PW|0x02)
769 #define TEKRAM_19200 (TEKRAM_PW|0x03)
770 #define TEKRAM_9600 (TEKRAM_PW|0x04)
771 #define TEKRAM_2400 (TEKRAM_PW|0x08)
772
773 #define TEKRAM_TV (TEKRAM_PW|0x05)
774
775 void
776 irts_tekram(struct tty *tp, u_int speed)
777 {
778 int s;
779
780 irt_setspeed(tp, 9600);
781 irt_setline(tp, 0);
782 irt_delay(tp, 50);
783 irt_setline(tp, TIOCM_RTS);
784 irt_delay(tp, 1);
785 irt_setline(tp, TIOCM_DTR | TIOCM_RTS);
786 irt_delay(tp, 1); /* 50 us */
787 irt_setline(tp, TIOCM_DTR);
788 irt_delay(tp, 1); /* 7 us */
789 switch(speed) {
790 case 115200: s = TEKRAM_115200; break;
791 case 57600: s = TEKRAM_57600; break;
792 case 38400: s = TEKRAM_38400; break;
793 case 19200: s = TEKRAM_19200; break;
794 case 2400: s = TEKRAM_2400; break;
795 default: s = TEKRAM_9600; break;
796 }
797 irt_putc(tp, s);
798 irt_delay(tp, 100);
799 irt_setline(tp, TIOCM_DTR | TIOCM_RTS);
800 if (speed != 9600)
801 irt_setspeed(tp, speed);
802 irt_delay(tp, 1); /* 50 us */
803 }
804
805 /**********************************************************************
806 * Jeteye
807 **********************************************************************/
808 void
809 irts_jeteye(struct tty *tp, u_int speed)
810 {
811 switch (speed) {
812 case 19200:
813 irt_setline(tp, TIOCM_DTR);
814 break;
815 case 115200:
816 irt_setline(tp, TIOCM_DTR | TIOCM_RTS);
817 break;
818 default: /*9600*/
819 irt_setline(tp, TIOCM_RTS);
820 break;
821 }
822 irt_setspeed(tp, speed);
823 }
824
825 /**********************************************************************
826 * Actisys
827 **********************************************************************/
828 void
829 irts_actisys(struct tty *tp, u_int speed)
830 {
831 struct irframet_softc *sc = (struct irframet_softc *)tp->t_sc;
832 int pulses;
833
834 irt_setspeed(tp, speed);
835
836 switch(speed) {
837 case 19200: pulses=1; break;
838 case 57600: pulses=2; break;
839 case 115200: pulses=3; break;
840 case 38400: pulses=4; break;
841 default: /* 9600 */ pulses=0; break;
842 }
843
844 if (sc->sc_dongle_private == 0) {
845 sc->sc_dongle_private = 1;
846 irt_setline(tp, TIOCM_DTR | TIOCM_RTS);
847 /*
848 * Must wait at least 50ms after initial
849 * power on to charge internal capacitor
850 */
851 irt_delay(tp, 50);
852 }
853 irt_setline(tp, TIOCM_RTS);
854 delay(2);
855 for (;;) {
856 irt_setline(tp, TIOCM_DTR | TIOCM_RTS);
857 delay(2);
858 if (--pulses <= 0)
859 break;
860 irt_setline(tp, TIOCM_DTR);
861 delay(2);
862 }
863 }
864
865 /**********************************************************************
866 * Litelink
867 **********************************************************************/
868 void
869 irts_litelink(struct tty *tp, u_int speed)
870 {
871 struct irframet_softc *sc = (struct irframet_softc *)tp->t_sc;
872 int pulses;
873
874 irt_setspeed(tp, speed);
875
876 switch(speed) {
877 case 57600: pulses=1; break;
878 case 38400: pulses=2; break;
879 case 19200: pulses=3; break;
880 case 9600: pulses=4; break;
881 default: /* 115200 */ pulses=0; break;
882 }
883
884 if (sc->sc_dongle_private == 0) {
885 sc->sc_dongle_private = 1;
886 irt_setline(tp, TIOCM_DTR | TIOCM_RTS);
887 }
888 irt_setline(tp, TIOCM_RTS);
889 irt_delay(tp, 1); /* 15 us */;
890 for (;;) {
891 irt_setline(tp, TIOCM_DTR | TIOCM_RTS);
892 irt_delay(tp, 1); /* 15 us */;
893 if (--pulses <= 0)
894 break;
895 irt_setline(tp, TIOCM_DTR);
896 irt_delay(tp, 1); /* 15 us */;
897 }
898 }
899
900 /**********************************************************************
901 * Girbil
902 **********************************************************************/
903 /* Control register 1 */
904 #define GIRBIL_TXEN 0x01 /* Enable transmitter */
905 #define GIRBIL_RXEN 0x02 /* Enable receiver */
906 #define GIRBIL_ECAN 0x04 /* Cancel self emmited data */
907 #define GIRBIL_ECHO 0x08 /* Echo control characters */
908
909 /* LED Current Register */
910 #define GIRBIL_HIGH 0x20
911 #define GIRBIL_MEDIUM 0x21
912 #define GIRBIL_LOW 0x22
913
914 /* Baud register */
915 #define GIRBIL_2400 0x30
916 #define GIRBIL_4800 0x31
917 #define GIRBIL_9600 0x32
918 #define GIRBIL_19200 0x33
919 #define GIRBIL_38400 0x34
920 #define GIRBIL_57600 0x35
921 #define GIRBIL_115200 0x36
922
923 /* Mode register */
924 #define GIRBIL_IRDA 0x40
925 #define GIRBIL_ASK 0x41
926
927 /* Control register 2 */
928 #define GIRBIL_LOAD 0x51 /* Load the new baud rate value */
929
930 void
931 irts_girbil(struct tty *tp, u_int speed)
932 {
933 int s;
934
935 irt_setspeed(tp, 9600);
936 irt_setline(tp, TIOCM_DTR);
937 irt_delay(tp, 5);
938 irt_setline(tp, TIOCM_RTS);
939 irt_delay(tp, 20);
940 switch(speed) {
941 case 115200: s = GIRBIL_115200; break;
942 case 57600: s = GIRBIL_57600; break;
943 case 38400: s = GIRBIL_38400; break;
944 case 19200: s = GIRBIL_19200; break;
945 case 4800: s = GIRBIL_4800; break;
946 case 2400: s = GIRBIL_2400; break;
947 default: s = GIRBIL_9600; break;
948 }
949 irt_putc(tp, GIRBIL_TXEN|GIRBIL_RXEN);
950 irt_putc(tp, s);
951 irt_putc(tp, GIRBIL_LOAD);
952 irt_delay(tp, 100);
953 irt_setline(tp, TIOCM_DTR | TIOCM_RTS);
954 if (speed != 9600)
955 irt_setspeed(tp, speed);
956 }
957