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