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