1 /* $NetBSD: irframe_tty.c,v 1.55 2009/01/11 02:45:51 christos 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@augustsson.net) and Tommy Bohlin 14 * (tommy@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 * 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. 36 */ 37 38 /* 39 * Loosely based on ppp_tty.c. 40 * Framing and dongle handling written by Tommy Bohlin. 41 */ 42 43 #include <sys/cdefs.h> 44 __KERNEL_RCSID(0, "$NetBSD: irframe_tty.c,v 1.55 2009/01/11 02:45:51 christos Exp $"); 45 46 #include <sys/param.h> 47 #include <sys/proc.h> 48 #include <sys/ioctl.h> 49 #include <sys/tty.h> 50 #include <sys/kernel.h> 51 #include <sys/mutex.h> 52 #include <sys/malloc.h> 53 #include <sys/conf.h> 54 #include <sys/systm.h> 55 #include <sys/device.h> 56 #include <sys/file.h> 57 #include <sys/vnode.h> 58 #include <sys/poll.h> 59 #include <sys/kauth.h> 60 61 #include <dev/ir/ir.h> 62 #include <dev/ir/sir.h> 63 #include <dev/ir/irdaio.h> 64 #include <dev/ir/irframevar.h> 65 66 #ifdef IRFRAMET_DEBUG 67 #define DPRINTF(x) if (irframetdebug) printf x 68 int irframetdebug = 0; 69 #else 70 #define DPRINTF(x) 71 #endif 72 73 /*****/ 74 75 /* Max size with framing. */ 76 #define MAX_IRDA_FRAME (2*IRDA_MAX_FRAME_SIZE + IRDA_MAX_EBOFS + 4) 77 78 struct irt_frame { 79 u_char *buf; 80 u_int len; 81 }; 82 #define MAXFRAMES 8 83 84 struct irframet_softc { 85 struct irframe_softc sc_irp; 86 struct tty *sc_tp; 87 88 int sc_dongle; 89 int sc_dongle_private; 90 91 int sc_state; 92 #define IRT_RSLP 0x01 /* waiting for data (read) */ 93 #if 0 94 #define IRT_WSLP 0x02 /* waiting for data (write) */ 95 #define IRT_CLOSING 0x04 /* waiting for output to drain */ 96 #endif 97 kmutex_t sc_wr_lk; 98 99 struct irda_params sc_params; 100 101 u_char* sc_inbuf; 102 int sc_framestate; 103 #define FRAME_OUTSIDE 0 104 #define FRAME_INSIDE 1 105 #define FRAME_ESCAPE 2 106 int sc_inchars; 107 int sc_inFCS; 108 struct callout sc_timeout; 109 110 u_int sc_nframes; 111 u_int sc_framei; 112 u_int sc_frameo; 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; 118 }; 119 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 *); 126 127 /* pseudo device init */ 128 void irframettyattach(int); 129 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 *); 137 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 *); 141 142 /* internal */ 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 152 static const struct irframe_methods irframet_methods = { 153 irframet_open, irframet_close, irframet_read, irframet_write, 154 irframet_poll, irframet_kqfilter, irframet_set_params, 155 irframet_get_speeds, irframet_get_turnarounds 156 }; 157 158 static void irts_none(struct tty *, u_int); 159 static void irts_tekram(struct tty *, u_int); 160 static void irts_jeteye(struct tty *, u_int); 161 static void irts_actisys(struct tty *, u_int); 162 static void irts_litelink(struct tty *, u_int); 163 static void irts_girbil(struct tty *, u_int); 164 165 #define NORMAL_SPEEDS (IRDA_SPEEDS_SIR & ~IRDA_SPEED_2400) 166 #define TURNT_POS (IRDA_TURNT_10000 | IRDA_TURNT_5000 | IRDA_TURNT_1000 | \ 167 IRDA_TURNT_500 | IRDA_TURNT_100 | IRDA_TURNT_50 | IRDA_TURNT_10) 168 static const struct dongle { 169 void (*setspeed)(struct tty *, u_int); 170 u_int speedmask; 171 u_int turnmask; 172 } irt_dongles[DONGLE_MAX] = { 173 /* Indexed by dongle number from irdaio.h */ 174 { irts_none, IRDA_SPEEDS_SIR, IRDA_TURNT_10000 }, 175 { irts_tekram, IRDA_SPEEDS_SIR, IRDA_TURNT_10000 }, 176 { irts_jeteye, IRDA_SPEED_9600|IRDA_SPEED_19200|IRDA_SPEED_115200, 177 IRDA_TURNT_10000 }, 178 { irts_actisys, NORMAL_SPEEDS & ~IRDA_SPEED_38400, TURNT_POS }, 179 { irts_actisys, NORMAL_SPEEDS, TURNT_POS }, 180 { irts_litelink, NORMAL_SPEEDS, TURNT_POS }, 181 { irts_girbil, IRDA_SPEEDS_SIR, IRDA_TURNT_10000 | IRDA_TURNT_5000 }, 182 }; 183 184 static struct linesw irframet_disc = { 185 .l_name = "irframe", 186 .l_open = irframetopen, 187 .l_close = irframetclose, 188 .l_read = ttyerrio, 189 .l_write = ttyerrio, 190 .l_ioctl = irframetioctl, 191 .l_rint = irframetinput, 192 .l_start = irframetstart, 193 .l_modem = ttymodem, 194 .l_poll = ttyerrpoll 195 }; 196 197 /* glue to attach irframe device */ 198 static void irframet_attach(struct device *, struct device *, void *); 199 static int irframet_detach(struct device *, int); 200 201 CFATTACH_DECL_NEW(irframet, sizeof(struct irframet_softc), 202 NULL, irframet_attach, irframet_detach, NULL); 203 204 void 205 irframettyattach(int n) 206 { 207 extern struct cfdriver irframe_cd; 208 209 (void) ttyldisc_attach(&irframet_disc); 210 211 /* XXX might fail if "real" attachments have pulled this in */ 212 /* XXX should not be done here */ 213 config_cfdriver_attach(&irframe_cd); 214 215 config_cfattach_attach("irframe", &irframet_ca); 216 } 217 218 static void 219 irframet_attach(device_t parent, device_t self, void *aux) 220 { 221 222 /* pseudo-device attachment does not print name */ 223 aprint_normal("%s", device_xname(self)); 224 #if 0 /* XXX can't do it yet because pseudo-devices don't get aux */ 225 struct ir_attach_args ia; 226 227 ia.ia_methods = &irframet_methods; 228 ia.ia_handle = aux->xxx; 229 230 irframe_attach(parent, self, &ia); 231 #endif 232 } 233 234 static int 235 irframet_detach(struct device *dev, int flags) 236 { 237 238 return (irframe_detach(dev, flags)); 239 } 240 241 /* 242 * Line specific open routine for async tty devices. 243 * Attach the given tty to the first available irframe unit. 244 * Called from device open routine or ttioctl. 245 */ 246 /* ARGSUSED */ 247 int 248 irframetopen(dev_t dev, struct tty *tp) 249 { 250 struct lwp *l = curlwp; /* XXX */ 251 struct irframet_softc *sc; 252 int error, s; 253 struct cfdata *cfdata; 254 struct ir_attach_args ia; 255 device_t d; 256 257 DPRINTF(("%s\n", __func__)); 258 259 if ((error = kauth_authorize_device_tty(l->l_cred, 260 KAUTH_DEVICE_TTY_OPEN, tp))) 261 return (error); 262 263 s = spltty(); 264 265 DPRINTF(("%s: linesw=%p disc=%s\n", __func__, tp->t_linesw, 266 tp->t_linesw->l_name)); 267 if (tp->t_linesw == &irframet_disc) { 268 sc = (struct irframet_softc *)tp->t_sc; 269 DPRINTF(("%s: sc=%p sc_tp=%p\n", __func__, sc, sc->sc_tp)); 270 if (sc != NULL) { 271 splx(s); 272 return (EBUSY); 273 } 274 } 275 276 cfdata = malloc(sizeof(struct cfdata), M_DEVBUF, M_WAITOK); 277 cfdata->cf_name = "irframe"; 278 cfdata->cf_atname = "irframet"; 279 cfdata->cf_fstate = FSTATE_STAR; 280 cfdata->cf_unit = 0; 281 d = config_attach_pseudo(cfdata); 282 sc = device_private(d); 283 sc->sc_irp.sc_dev = d; 284 285 /* XXX should be done in irframet_attach() */ 286 ia.ia_methods = &irframet_methods; 287 ia.ia_handle = tp; 288 irframe_attach(0, d, &ia); 289 290 tp->t_sc = sc; 291 sc->sc_tp = tp; 292 aprint_normal("%s attached at tty%02d\n", device_xname(d), 293 (int)minor(tp->t_dev)); 294 295 DPRINTF(("%s: set sc=%p\n", __func__, sc)); 296 297 mutex_spin_enter(&tty_lock); 298 ttyflush(tp, FREAD | FWRITE); 299 mutex_spin_exit(&tty_lock); 300 301 sc->sc_dongle = DONGLE_NONE; 302 sc->sc_dongle_private = 0; 303 304 splx(s); 305 306 return (0); 307 } 308 309 /* 310 * Line specific close routine, called from device close routine 311 * and from ttioctl. 312 * Detach the tty from the irframe unit. 313 * Mimics part of ttyclose(). 314 */ 315 int 316 irframetclose(struct tty *tp, int flag) 317 { 318 struct irframet_softc *sc = (struct irframet_softc *)tp->t_sc; 319 int s; 320 cfdata_t cfdata; 321 322 DPRINTF(("%s: tp=%p\n", __func__, tp)); 323 324 s = spltty(); 325 mutex_spin_enter(&tty_lock); 326 ttyflush(tp, FREAD | FWRITE); 327 mutex_spin_exit(&tty_lock); /* XXX */ 328 ttyldisc_release(tp->t_linesw); 329 tp->t_linesw = ttyldisc_default(); 330 if (sc != NULL) { 331 tp->t_sc = NULL; 332 aprint_normal("%s detached from tty%02d\n", 333 device_xname(sc->sc_irp.sc_dev), (int)minor(tp->t_dev)); 334 335 if (sc->sc_tp == tp) { 336 cfdata = device_cfdata(sc->sc_irp.sc_dev); 337 config_detach(sc->sc_irp.sc_dev, 0); 338 free(cfdata, M_DEVBUF); 339 } 340 } 341 splx(s); 342 return (0); 343 } 344 345 /* 346 * Line specific (tty) ioctl routine. 347 * This discipline requires that tty device drivers call 348 * the line specific l_ioctl routine from their ioctl routines. 349 */ 350 /* ARGSUSED */ 351 int 352 irframetioctl(struct tty *tp, u_long cmd, void *data, int flag, 353 struct lwp *l) 354 { 355 struct irframet_softc *sc = (struct irframet_softc *)tp->t_sc; 356 int error; 357 int d; 358 359 DPRINTF(("%s: tp=%p\n", __func__, tp)); 360 361 if (sc == NULL || tp != sc->sc_tp) 362 return (EPASSTHROUGH); 363 364 error = 0; 365 switch (cmd) { 366 case IRFRAMETTY_GET_DEVICE: 367 *(int *)data = device_unit(sc->sc_irp.sc_dev); 368 break; 369 case IRFRAMETTY_GET_DONGLE: 370 *(int *)data = sc->sc_dongle; 371 break; 372 case IRFRAMETTY_SET_DONGLE: 373 d = *(int *)data; 374 if (d < 0 || d >= DONGLE_MAX) 375 return (EINVAL); 376 sc->sc_dongle = d; 377 break; 378 default: 379 error = EPASSTHROUGH; 380 break; 381 } 382 383 return (error); 384 } 385 386 /* 387 * Start output on async tty interface. 388 */ 389 int 390 irframetstart(struct tty *tp) 391 { 392 /*struct irframet_softc *sc = (struct irframet_softc *)tp->t_sc;*/ 393 int s; 394 395 DPRINTF(("%s: tp=%p\n", __func__, tp)); 396 397 s = spltty(); 398 if (tp->t_oproc != NULL) 399 (*tp->t_oproc)(tp); 400 splx(s); 401 402 return (0); 403 } 404 405 void 406 irt_frame(struct irframet_softc *sc, u_char *tbuf, u_int len) 407 { 408 DPRINTF(("%s: nframe=%d framei=%d frameo=%d\n", 409 __func__, sc->sc_nframes, sc->sc_framei, sc->sc_frameo)); 410 411 if (sc->sc_inbuf == NULL) /* XXX happens if device is closed? */ 412 return; 413 if (sc->sc_nframes >= MAXFRAMES) { 414 #ifdef IRFRAMET_DEBUG 415 printf("%s: dropped frame\n", __func__); 416 #endif 417 return; 418 } 419 if (sc->sc_frames[sc->sc_framei].buf == NULL) 420 return; 421 memcpy(sc->sc_frames[sc->sc_framei].buf, tbuf, len); 422 sc->sc_frames[sc->sc_framei].len = len; 423 sc->sc_framei = (sc->sc_framei+1) % MAXFRAMES; 424 sc->sc_nframes++; 425 if (sc->sc_state & IRT_RSLP) { 426 sc->sc_state &= ~IRT_RSLP; 427 DPRINTF(("%s: waking up reader\n", __func__)); 428 wakeup(sc->sc_frames); 429 } 430 selnotify(&sc->sc_rsel, 0, 0); 431 } 432 433 void 434 irt_timeout(void *v) 435 { 436 struct irframet_softc *sc = v; 437 438 #ifdef IRFRAMET_DEBUG 439 if (sc->sc_framestate != FRAME_OUTSIDE) 440 printf("%s: input frame timeout\n", __func__); 441 #endif 442 sc->sc_framestate = FRAME_OUTSIDE; 443 } 444 445 int 446 irframetinput(int c, struct tty *tp) 447 { 448 struct irframet_softc *sc = (struct irframet_softc *)tp->t_sc; 449 450 c &= 0xff; 451 452 #if IRFRAMET_DEBUG 453 if (irframetdebug > 1) 454 DPRINTF(("%s: tp=%p c=0x%02x\n", __func__, tp, c)); 455 #endif 456 457 if (sc == NULL || tp != (struct tty *)sc->sc_tp) 458 return (0); 459 460 if (sc->sc_inbuf == NULL) 461 return (0); 462 463 switch (c) { 464 case SIR_BOF: 465 DPRINTF(("%s: BOF\n", __func__)); 466 sc->sc_framestate = FRAME_INSIDE; 467 sc->sc_inchars = 0; 468 sc->sc_inFCS = INITFCS; 469 break; 470 case SIR_EOF: 471 DPRINTF(("%s: EOF state=%d inchars=%d fcs=0x%04x\n", 472 __func__, 473 sc->sc_framestate, sc->sc_inchars, sc->sc_inFCS)); 474 if (sc->sc_framestate == FRAME_INSIDE && 475 sc->sc_inchars >= 4 && sc->sc_inFCS == GOODFCS) { 476 irt_frame(sc, sc->sc_inbuf, sc->sc_inchars - 2); 477 } else if (sc->sc_framestate != FRAME_OUTSIDE) { 478 #ifdef IRFRAMET_DEBUG 479 printf("%s: malformed input frame\n", __func__); 480 #endif 481 } 482 sc->sc_framestate = FRAME_OUTSIDE; 483 break; 484 case SIR_CE: 485 DPRINTF(("%s: CE\n", __func__)); 486 if (sc->sc_framestate == FRAME_INSIDE) 487 sc->sc_framestate = FRAME_ESCAPE; 488 break; 489 default: 490 #if IRFRAMET_DEBUG 491 if (irframetdebug > 1) 492 DPRINTF(("%s: c=0x%02x, inchar=%d state=%d\n", __func__, c, 493 sc->sc_inchars, sc->sc_state)); 494 #endif 495 if (sc->sc_framestate != FRAME_OUTSIDE) { 496 if (sc->sc_framestate == FRAME_ESCAPE) { 497 sc->sc_framestate = FRAME_INSIDE; 498 c ^= SIR_ESC_BIT; 499 } 500 if (sc->sc_inchars < sc->sc_params.maxsize + 2) { 501 sc->sc_inbuf[sc->sc_inchars++] = c; 502 sc->sc_inFCS = updateFCS(sc->sc_inFCS, c); 503 } else { 504 sc->sc_framestate = FRAME_OUTSIDE; 505 #ifdef IRFRAMET_DEBUG 506 printf("%s: input frame overrun\n", 507 __func__); 508 #endif 509 } 510 } 511 break; 512 } 513 514 #if 1 515 if (sc->sc_framestate != FRAME_OUTSIDE) { 516 callout_reset(&sc->sc_timeout, hz/20, irt_timeout, sc); 517 } 518 #endif 519 520 return (0); 521 } 522 523 524 /*** irframe methods ***/ 525 526 int 527 irframet_open(void *h, int flag, int mode, 528 struct lwp *l) 529 { 530 struct tty *tp = h; 531 struct irframet_softc *sc = (struct irframet_softc *)tp->t_sc; 532 static bool again; 533 534 DPRINTF(("%s: tp=%p\n", __func__, tp)); 535 536 sc->sc_params.speed = 0; 537 sc->sc_params.ebofs = IRDA_DEFAULT_EBOFS; 538 sc->sc_params.maxsize = 0; 539 sc->sc_framestate = FRAME_OUTSIDE; 540 sc->sc_nframes = 0; 541 sc->sc_framei = 0; 542 sc->sc_frameo = 0; 543 544 /* XXX */ 545 if (!again) { 546 again = true; 547 callout_init(&sc->sc_timeout, 0); 548 mutex_init(&sc->sc_wr_lk, MUTEX_DEFAULT, IPL_NONE); 549 selinit(&sc->sc_rsel); 550 selinit(&sc->sc_wsel); 551 } 552 553 return (0); 554 } 555 556 int 557 irframet_close(void *h, int flag, int mode, 558 struct lwp *l) 559 { 560 struct tty *tp = h; 561 struct irframet_softc *sc = (struct irframet_softc *)tp->t_sc; 562 int i, s; 563 564 DPRINTF(("%s: tp=%p\n", __func__, tp)); 565 566 callout_stop(&sc->sc_timeout); 567 s = splir(); 568 if (sc->sc_inbuf != NULL) { 569 free(sc->sc_inbuf, M_DEVBUF); 570 sc->sc_inbuf = NULL; 571 } 572 for (i = 0; i < MAXFRAMES; i++) { 573 if (sc->sc_frames[i].buf != NULL) { 574 free(sc->sc_frames[i].buf, M_DEVBUF); 575 sc->sc_frames[i].buf = NULL; 576 } 577 } 578 splx(s); 579 580 return (0); 581 } 582 583 int 584 irframet_read(void *h, struct uio *uio, int flag) 585 { 586 struct tty *tp = h; 587 struct irframet_softc *sc = (struct irframet_softc *)tp->t_sc; 588 int error = 0; 589 int s; 590 591 DPRINTF(("%s: resid=%zd, iovcnt=%d, offset=%ld\n", 592 __func__, uio->uio_resid, uio->uio_iovcnt, 593 (long)uio->uio_offset)); 594 DPRINTF(("%s: nframe=%d framei=%d frameo=%d\n", 595 __func__, sc->sc_nframes, sc->sc_framei, sc->sc_frameo)); 596 597 598 s = splir(); 599 while (sc->sc_nframes == 0) { 600 if (flag & IO_NDELAY) { 601 splx(s); 602 return (EWOULDBLOCK); 603 } 604 sc->sc_state |= IRT_RSLP; 605 DPRINTF(("%s: sleep\n", __func__)); 606 error = tsleep(sc->sc_frames, PZERO | PCATCH, "irtrd", 0); 607 DPRINTF(("%s: woke, error=%d\n", __func__, error)); 608 if (error) { 609 sc->sc_state &= ~IRT_RSLP; 610 break; 611 } 612 } 613 614 /* Do just one frame transfer per read */ 615 if (!error) { 616 if (uio->uio_resid < sc->sc_frames[sc->sc_frameo].len) { 617 DPRINTF(("%s: uio buffer smaller than frame size " 618 "(%zd < %d)\n", __func__, uio->uio_resid, 619 sc->sc_frames[sc->sc_frameo].len)); 620 error = EINVAL; 621 } else { 622 DPRINTF(("%s: moving %d bytes\n", __func__, 623 sc->sc_frames[sc->sc_frameo].len)); 624 error = uiomove(sc->sc_frames[sc->sc_frameo].buf, 625 sc->sc_frames[sc->sc_frameo].len, uio); 626 DPRINTF(("%s: error=%d\n", __func__, error)); 627 } 628 sc->sc_frameo = (sc->sc_frameo+1) % MAXFRAMES; 629 sc->sc_nframes--; 630 } 631 splx(s); 632 633 return (error); 634 } 635 636 int 637 irt_putc(struct tty *tp, int c) 638 { 639 int error; 640 641 #if IRFRAMET_DEBUG 642 if (irframetdebug > 3) 643 DPRINTF(("%s: tp=%p c=0x%02x cc=%d\n", __func__, tp, c, 644 tp->t_outq.c_cc)); 645 #endif 646 if (tp->t_outq.c_cc > tp->t_hiwat) { 647 irframetstart(tp); 648 mutex_spin_enter(&tty_lock); 649 /* 650 * This can only occur if FLUSHO is set in t_lflag, 651 * or if ttstart/oproc is synchronous (or very fast). 652 */ 653 if (tp->t_outq.c_cc <= tp->t_hiwat) { 654 mutex_spin_exit(&tty_lock); 655 goto go; 656 } 657 error = ttysleep(tp, &tp->t_outcv, true, 0); 658 mutex_spin_exit(&tty_lock); 659 if (error) 660 return (error); 661 } 662 go: 663 if (putc(c, &tp->t_outq) < 0) { 664 printf("irframe: putc failed\n"); 665 return (EIO); 666 } 667 return (0); 668 } 669 670 int 671 irframet_write(void *h, struct uio *uio, int flag) 672 { 673 struct tty *tp = h; 674 struct irframet_softc *sc = (struct irframet_softc *)tp->t_sc; 675 int n; 676 677 DPRINTF(("%s: resid=%zd, iovcnt=%d, offset=%ld\n", 678 __func__, uio->uio_resid, uio->uio_iovcnt, 679 (long)uio->uio_offset)); 680 681 n = irda_sir_frame(sc->sc_buffer, sizeof(sc->sc_buffer), uio, 682 sc->sc_params.ebofs); 683 if (n < 0) { 684 #ifdef IRFRAMET_DEBUG 685 printf("%s: irda_sir_frame() error=%d\n", __func__, -n); 686 #endif 687 return (-n); 688 } 689 return (irt_write_frame(tp, sc->sc_buffer, n)); 690 } 691 692 int 693 irt_write_frame(struct tty *tp, u_int8_t *tbuf, size_t len) 694 { 695 struct irframet_softc *sc = (struct irframet_softc *)tp->t_sc; 696 int error, i; 697 698 DPRINTF(("%s: tp=%p len=%zd\n", __func__, tp, len)); 699 700 mutex_enter(&sc->sc_wr_lk); 701 error = 0; 702 for (i = 0; !error && i < len; i++) 703 error = irt_putc(tp, tbuf[i]); 704 mutex_exit(&sc->sc_wr_lk); 705 706 irframetstart(tp); 707 708 DPRINTF(("%s: done, error=%d\n", __func__, error)); 709 710 return (error); 711 } 712 713 int 714 irframet_poll(void *h, int events, struct lwp *l) 715 { 716 struct tty *tp = h; 717 struct irframet_softc *sc = (struct irframet_softc *)tp->t_sc; 718 int revents = 0; 719 int s; 720 721 DPRINTF(("%s: sc=%p\n", __func__, sc)); 722 723 s = splir(); 724 /* XXX is this a good check? */ 725 if (events & (POLLOUT | POLLWRNORM)) 726 if (tp->t_outq.c_cc <= tp->t_lowat) 727 revents |= events & (POLLOUT | POLLWRNORM); 728 729 if (events & (POLLIN | POLLRDNORM)) { 730 if (sc->sc_nframes > 0) { 731 DPRINTF(("%s: have data\n", __func__)); 732 revents |= events & (POLLIN | POLLRDNORM); 733 } else { 734 DPRINTF(("%s: recording select\n", __func__)); 735 selrecord(l, &sc->sc_rsel); 736 } 737 } 738 splx(s); 739 740 return (revents); 741 } 742 743 static void 744 filt_irframetrdetach(struct knote *kn) 745 { 746 struct tty *tp = kn->kn_hook; 747 struct irframet_softc *sc = (struct irframet_softc *)tp->t_sc; 748 int s; 749 750 s = splir(); 751 SLIST_REMOVE(&sc->sc_rsel.sel_klist, kn, knote, kn_selnext); 752 splx(s); 753 } 754 755 static int 756 filt_irframetread(struct knote *kn, long hint) 757 { 758 struct tty *tp = kn->kn_hook; 759 struct irframet_softc *sc = (struct irframet_softc *)tp->t_sc; 760 761 kn->kn_data = sc->sc_nframes; 762 return (kn->kn_data > 0); 763 } 764 765 static void 766 filt_irframetwdetach(struct knote *kn) 767 { 768 struct tty *tp = kn->kn_hook; 769 struct irframet_softc *sc = (struct irframet_softc *)tp->t_sc; 770 int s; 771 772 s = splir(); 773 SLIST_REMOVE(&sc->sc_wsel.sel_klist, kn, knote, kn_selnext); 774 splx(s); 775 } 776 777 static int 778 filt_irframetwrite(struct knote *kn, long hint) 779 { 780 struct tty *tp = kn->kn_hook; 781 782 /* XXX double-check this */ 783 784 if (tp->t_outq.c_cc <= tp->t_lowat) { 785 kn->kn_data = tp->t_lowat - tp->t_outq.c_cc; 786 return (1); 787 } 788 789 kn->kn_data = 0; 790 return (0); 791 } 792 793 static const struct filterops irframetread_filtops = 794 { 1, NULL, filt_irframetrdetach, filt_irframetread }; 795 static const struct filterops irframetwrite_filtops = 796 { 1, NULL, filt_irframetwdetach, filt_irframetwrite }; 797 798 int 799 irframet_kqfilter(void *h, struct knote *kn) 800 { 801 struct tty *tp = h; 802 struct irframet_softc *sc = (struct irframet_softc *)tp->t_sc; 803 struct klist *klist; 804 int s; 805 806 switch (kn->kn_filter) { 807 case EVFILT_READ: 808 klist = &sc->sc_rsel.sel_klist; 809 kn->kn_fop = &irframetread_filtops; 810 break; 811 case EVFILT_WRITE: 812 klist = &sc->sc_wsel.sel_klist; 813 kn->kn_fop = &irframetwrite_filtops; 814 break; 815 default: 816 return (EINVAL); 817 } 818 819 kn->kn_hook = tp; 820 821 s = splir(); 822 SLIST_INSERT_HEAD(klist, kn, kn_selnext); 823 splx(s); 824 825 return (0); 826 } 827 828 int 829 irframet_set_params(void *h, struct irda_params *p) 830 { 831 struct tty *tp = h; 832 struct irframet_softc *sc = (struct irframet_softc *)tp->t_sc; 833 int i; 834 835 DPRINTF(("%s: tp=%p speed=%d ebofs=%d maxsize=%d\n", 836 __func__, tp, p->speed, p->ebofs, p->maxsize)); 837 838 if (p->speed != sc->sc_params.speed) { 839 /* Checked in irframe.c */ 840 mutex_enter(&sc->sc_wr_lk); 841 irt_dongles[sc->sc_dongle].setspeed(tp, p->speed); 842 mutex_exit(&sc->sc_wr_lk); 843 sc->sc_params.speed = p->speed; 844 } 845 846 /* Max size checked in irframe.c */ 847 sc->sc_params.ebofs = p->ebofs; 848 /* Max size checked in irframe.c */ 849 if (sc->sc_params.maxsize != p->maxsize) { 850 sc->sc_params.maxsize = p->maxsize; 851 if (sc->sc_inbuf != NULL) 852 free(sc->sc_inbuf, M_DEVBUF); 853 for (i = 0; i < MAXFRAMES; i++) 854 if (sc->sc_frames[i].buf != NULL) 855 free(sc->sc_frames[i].buf, M_DEVBUF); 856 if (sc->sc_params.maxsize != 0) { 857 sc->sc_inbuf = malloc(sc->sc_params.maxsize+2, 858 M_DEVBUF, M_WAITOK); 859 for (i = 0; i < MAXFRAMES; i++) 860 sc->sc_frames[i].buf = 861 malloc(sc->sc_params.maxsize, 862 M_DEVBUF, M_WAITOK); 863 } else { 864 sc->sc_inbuf = NULL; 865 for (i = 0; i < MAXFRAMES; i++) 866 sc->sc_frames[i].buf = NULL; 867 } 868 } 869 sc->sc_framestate = FRAME_OUTSIDE; 870 871 return (0); 872 } 873 874 int 875 irframet_get_speeds(void *h, int *speeds) 876 { 877 struct tty *tp = h; 878 struct irframet_softc *sc = (struct irframet_softc *)tp->t_sc; 879 880 DPRINTF(("%s: tp=%p\n", __func__, tp)); 881 882 if (sc == NULL) /* during attach */ 883 *speeds = IRDA_SPEEDS_SIR; 884 else 885 *speeds = irt_dongles[sc->sc_dongle].speedmask; 886 return (0); 887 } 888 889 int 890 irframet_get_turnarounds(void *h, int *turnarounds) 891 { 892 struct tty *tp = h; 893 struct irframet_softc *sc = (struct irframet_softc *)tp->t_sc; 894 895 DPRINTF(("%s: tp=%p\n", __func__, tp)); 896 897 *turnarounds = irt_dongles[sc->sc_dongle].turnmask; 898 return (0); 899 } 900 901 void 902 irt_ioctl(struct tty *tp, u_long cmd, void *arg) 903 { 904 const struct cdevsw *cdev; 905 int error; 906 dev_t dev; 907 908 dev = tp->t_dev; 909 cdev = cdevsw_lookup(dev); 910 if (cdev != NULL) 911 error = (*cdev->d_ioctl)(dev, cmd, arg, 0, curlwp); 912 else 913 error = ENXIO; 914 #ifdef DIAGNOSTIC 915 if (error) 916 printf("irt_ioctl: cmd=0x%08lx error=%d\n", cmd, error); 917 #endif 918 } 919 920 void 921 irt_setspeed(struct tty *tp, u_int speed) 922 { 923 struct termios tt; 924 925 irt_ioctl(tp, TIOCGETA, &tt); 926 tt.c_ispeed = tt.c_ospeed = speed; 927 tt.c_cflag &= ~HUPCL; 928 tt.c_cflag |= CLOCAL; 929 irt_ioctl(tp, TIOCSETAF, &tt); 930 } 931 932 void 933 irt_setline(struct tty *tp, u_int line) 934 { 935 int mline; 936 937 irt_ioctl(tp, TIOCMGET, &mline); 938 mline &= ~(TIOCM_DTR | TIOCM_RTS); 939 mline |= line; 940 irt_ioctl(tp, TIOCMSET, (void *)&mline); 941 } 942 943 void 944 irt_delay(struct tty *tp, u_int ms) 945 { 946 if (cold) 947 delay(ms * 1000); 948 else 949 tsleep(&irt_delay, PZERO, "irtdly", ms * hz / 1000 + 1); 950 951 } 952 953 /********************************************************************** 954 * No dongle 955 **********************************************************************/ 956 void 957 irts_none(struct tty *tp, u_int speed) 958 { 959 irt_setspeed(tp, speed); 960 } 961 962 /********************************************************************** 963 * Tekram 964 **********************************************************************/ 965 #define TEKRAM_PW 0x10 966 967 #define TEKRAM_115200 (TEKRAM_PW|0x00) 968 #define TEKRAM_57600 (TEKRAM_PW|0x01) 969 #define TEKRAM_38400 (TEKRAM_PW|0x02) 970 #define TEKRAM_19200 (TEKRAM_PW|0x03) 971 #define TEKRAM_9600 (TEKRAM_PW|0x04) 972 #define TEKRAM_2400 (TEKRAM_PW|0x08) 973 974 #define TEKRAM_TV (TEKRAM_PW|0x05) 975 976 void 977 irts_tekram(struct tty *tp, u_int speed) 978 { 979 int s; 980 981 irt_setspeed(tp, 9600); 982 irt_setline(tp, 0); 983 irt_delay(tp, 50); 984 985 irt_setline(tp, TIOCM_RTS); 986 irt_delay(tp, 1); 987 988 irt_setline(tp, TIOCM_DTR | TIOCM_RTS); 989 irt_delay(tp, 1); /* 50 us */ 990 991 irt_setline(tp, TIOCM_DTR); 992 irt_delay(tp, 1); /* 7 us */ 993 994 switch(speed) { 995 case 115200: s = TEKRAM_115200; break; 996 case 57600: s = TEKRAM_57600; break; 997 case 38400: s = TEKRAM_38400; break; 998 case 19200: s = TEKRAM_19200; break; 999 case 2400: s = TEKRAM_2400; break; 1000 default: s = TEKRAM_9600; break; 1001 } 1002 irt_putc(tp, s); 1003 irframetstart(tp); 1004 1005 irt_delay(tp, 100); 1006 1007 irt_setline(tp, TIOCM_DTR | TIOCM_RTS); 1008 if (speed != 9600) 1009 irt_setspeed(tp, speed); 1010 irt_delay(tp, 1); /* 50 us */ 1011 } 1012 1013 /********************************************************************** 1014 * Jeteye 1015 **********************************************************************/ 1016 void 1017 irts_jeteye(struct tty *tp, u_int speed) 1018 { 1019 switch (speed) { 1020 case 19200: 1021 irt_setline(tp, TIOCM_DTR); 1022 break; 1023 case 115200: 1024 irt_setline(tp, TIOCM_DTR | TIOCM_RTS); 1025 break; 1026 default: /*9600*/ 1027 irt_setline(tp, TIOCM_RTS); 1028 break; 1029 } 1030 irt_setspeed(tp, speed); 1031 } 1032 1033 /********************************************************************** 1034 * Actisys 1035 **********************************************************************/ 1036 void 1037 irts_actisys(struct tty *tp, u_int speed) 1038 { 1039 struct irframet_softc *sc = (struct irframet_softc *)tp->t_sc; 1040 int pulses; 1041 1042 irt_setspeed(tp, speed); 1043 1044 switch(speed) { 1045 case 19200: pulses=1; break; 1046 case 57600: pulses=2; break; 1047 case 115200: pulses=3; break; 1048 case 38400: pulses=4; break; 1049 default: /* 9600 */ pulses=0; break; 1050 } 1051 1052 if (sc->sc_dongle_private == 0) { 1053 sc->sc_dongle_private = 1; 1054 irt_setline(tp, TIOCM_DTR | TIOCM_RTS); 1055 /* 1056 * Must wait at least 50ms after initial 1057 * power on to charge internal capacitor 1058 */ 1059 irt_delay(tp, 50); 1060 } 1061 irt_setline(tp, TIOCM_RTS); 1062 delay(2); 1063 for (;;) { 1064 irt_setline(tp, TIOCM_DTR | TIOCM_RTS); 1065 delay(2); 1066 if (--pulses <= 0) 1067 break; 1068 irt_setline(tp, TIOCM_DTR); 1069 delay(2); 1070 } 1071 } 1072 1073 /********************************************************************** 1074 * Litelink 1075 **********************************************************************/ 1076 void 1077 irts_litelink(struct tty *tp, u_int speed) 1078 { 1079 struct irframet_softc *sc = (struct irframet_softc *)tp->t_sc; 1080 int pulses; 1081 1082 irt_setspeed(tp, speed); 1083 1084 switch(speed) { 1085 case 57600: pulses=1; break; 1086 case 38400: pulses=2; break; 1087 case 19200: pulses=3; break; 1088 case 9600: pulses=4; break; 1089 default: /* 115200 */ pulses=0; break; 1090 } 1091 1092 if (sc->sc_dongle_private == 0) { 1093 sc->sc_dongle_private = 1; 1094 irt_setline(tp, TIOCM_DTR | TIOCM_RTS); 1095 } 1096 irt_setline(tp, TIOCM_RTS); 1097 irt_delay(tp, 1); /* 15 us */; 1098 for (;;) { 1099 irt_setline(tp, TIOCM_DTR | TIOCM_RTS); 1100 irt_delay(tp, 1); /* 15 us */; 1101 if (--pulses <= 0) 1102 break; 1103 irt_setline(tp, TIOCM_DTR); 1104 irt_delay(tp, 1); /* 15 us */; 1105 } 1106 } 1107 1108 /********************************************************************** 1109 * Girbil 1110 **********************************************************************/ 1111 /* Control register 1 */ 1112 #define GIRBIL_TXEN 0x01 /* Enable transmitter */ 1113 #define GIRBIL_RXEN 0x02 /* Enable receiver */ 1114 #define GIRBIL_ECAN 0x04 /* Cancel self emmited data */ 1115 #define GIRBIL_ECHO 0x08 /* Echo control characters */ 1116 1117 /* LED Current Register */ 1118 #define GIRBIL_HIGH 0x20 1119 #define GIRBIL_MEDIUM 0x21 1120 #define GIRBIL_LOW 0x22 1121 1122 /* Baud register */ 1123 #define GIRBIL_2400 0x30 1124 #define GIRBIL_4800 0x31 1125 #define GIRBIL_9600 0x32 1126 #define GIRBIL_19200 0x33 1127 #define GIRBIL_38400 0x34 1128 #define GIRBIL_57600 0x35 1129 #define GIRBIL_115200 0x36 1130 1131 /* Mode register */ 1132 #define GIRBIL_IRDA 0x40 1133 #define GIRBIL_ASK 0x41 1134 1135 /* Control register 2 */ 1136 #define GIRBIL_LOAD 0x51 /* Load the new baud rate value */ 1137 1138 void 1139 irts_girbil(struct tty *tp, u_int speed) 1140 { 1141 int s; 1142 1143 irt_setspeed(tp, 9600); 1144 irt_setline(tp, TIOCM_DTR); 1145 irt_delay(tp, 5); 1146 irt_setline(tp, TIOCM_RTS); 1147 irt_delay(tp, 20); 1148 switch(speed) { 1149 case 115200: s = GIRBIL_115200; break; 1150 case 57600: s = GIRBIL_57600; break; 1151 case 38400: s = GIRBIL_38400; break; 1152 case 19200: s = GIRBIL_19200; break; 1153 case 4800: s = GIRBIL_4800; break; 1154 case 2400: s = GIRBIL_2400; break; 1155 default: s = GIRBIL_9600; break; 1156 } 1157 irt_putc(tp, GIRBIL_TXEN|GIRBIL_RXEN); 1158 irt_putc(tp, s); 1159 irt_putc(tp, GIRBIL_LOAD); 1160 irframetstart(tp); 1161 irt_delay(tp, 100); 1162 irt_setline(tp, TIOCM_DTR | TIOCM_RTS); 1163 if (speed != 9600) 1164 irt_setspeed(tp, speed); 1165 } 1166