irframe_tty.c revision 1.1 1 1.1 augustss /* $NetBSD: irframe_tty.c,v 1.1 2001/12/03 23:32:32 augustss Exp $ */
2 1.1 augustss
3 1.1 augustss /*
4 1.1 augustss * Copyright (c) 2001 The NetBSD Foundation, Inc.
5 1.1 augustss * All rights reserved.
6 1.1 augustss *
7 1.1 augustss * This code is derived from software contributed to The NetBSD Foundation
8 1.1 augustss * by Lennart Augustsson (lennart (at) augustsson.net).
9 1.1 augustss *
10 1.1 augustss * Redistribution and use in source and binary forms, with or without
11 1.1 augustss * modification, are permitted provided that the following conditions
12 1.1 augustss * are met:
13 1.1 augustss * 1. Redistributions of source code must retain the above copyright
14 1.1 augustss * notice, this list of conditions and the following disclaimer.
15 1.1 augustss * 2. Redistributions in binary form must reproduce the above copyright
16 1.1 augustss * notice, this list of conditions and the following disclaimer in the
17 1.1 augustss * documentation and/or other materials provided with the distribution.
18 1.1 augustss * 3. All advertising materials mentioning features or use of this software
19 1.1 augustss * must display the following acknowledgement:
20 1.1 augustss * This product includes software developed by the NetBSD
21 1.1 augustss * Foundation, Inc. and its contributors.
22 1.1 augustss * 4. Neither the name of The NetBSD Foundation nor the names of its
23 1.1 augustss * contributors may be used to endorse or promote products derived
24 1.1 augustss * from this software without specific prior written permission.
25 1.1 augustss *
26 1.1 augustss * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
27 1.1 augustss * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
28 1.1 augustss * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29 1.1 augustss * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
30 1.1 augustss * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31 1.1 augustss * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32 1.1 augustss * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33 1.1 augustss * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34 1.1 augustss * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35 1.1 augustss * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36 1.1 augustss * POSSIBILITY OF SUCH DAMAGE.
37 1.1 augustss */
38 1.1 augustss
39 1.1 augustss /*
40 1.1 augustss * Loosely based on ppp_tty.c.
41 1.1 augustss */
42 1.1 augustss
43 1.1 augustss #include <sys/param.h>
44 1.1 augustss #include <sys/proc.h>
45 1.1 augustss #include <sys/ioctl.h>
46 1.1 augustss #include <sys/tty.h>
47 1.1 augustss #include <sys/kernel.h>
48 1.1 augustss #include <sys/conf.h>
49 1.1 augustss #include <sys/systm.h>
50 1.1 augustss #include <sys/device.h>
51 1.1 augustss #include <sys/file.h>
52 1.1 augustss #include <sys/poll.h>
53 1.1 augustss
54 1.1 augustss #include <dev/ir/ir.h>
55 1.1 augustss #include <dev/ir/irdaio.h>
56 1.1 augustss #include <dev/ir/irframevar.h>
57 1.1 augustss
58 1.1 augustss /* Macros to clear/set/test flags. */
59 1.1 augustss #define SET(t, f) (t) |= (f)
60 1.1 augustss #define CLR(t, f) (t) &= ~((unsigned)(f))
61 1.1 augustss #define ISSET(t, f) ((t) & (f))
62 1.1 augustss
63 1.1 augustss #ifdef IRFRAMET_DEBUG
64 1.1 augustss #define DPRINTF(x) if (irframetdebug) printf x
65 1.1 augustss int irframetdebug = 1;
66 1.1 augustss #else
67 1.1 augustss #define DPRINTF(x)
68 1.1 augustss #endif
69 1.1 augustss
70 1.1 augustss /* Protocol constants */
71 1.1 augustss #define SIR_EXTRA_BOF 0xff
72 1.1 augustss #define SIR_BOF 0xc0
73 1.1 augustss #define SIR_CE 0x7d
74 1.1 augustss #define SIR_EOF 0xc1
75 1.1 augustss
76 1.1 augustss #define SIR_ESC_BIT 0x20
77 1.1 augustss /*****/
78 1.1 augustss
79 1.1 augustss #define MAX_IRDA_FRAME 5000 /* XXX what is it? */
80 1.1 augustss
81 1.1 augustss struct irframet_softc {
82 1.1 augustss struct irframe_softc sc_irp;
83 1.1 augustss struct tty *sc_tp;
84 1.1 augustss int sc_ebofs;
85 1.1 augustss };
86 1.1 augustss
87 1.1 augustss /* line discipline methods */
88 1.1 augustss int irframetopen(dev_t dev, struct tty *tp);
89 1.1 augustss int irframetclose(struct tty *tp, int flag);
90 1.1 augustss int irframetioctl(struct tty *tp, u_long cmd, caddr_t data, int flag,
91 1.1 augustss struct proc *);
92 1.1 augustss int irframetinput(int c, struct tty *tp);
93 1.1 augustss int irframetstart(struct tty *tp);
94 1.1 augustss
95 1.1 augustss /* irframe methods */
96 1.1 augustss int irframet_open(void *h, int flag, int mode, struct proc *p);
97 1.1 augustss int irframet_close(void *h, int flag, int mode, struct proc *p);
98 1.1 augustss int irframet_read(void *h, struct uio *uio, int flag);
99 1.1 augustss int irframet_write(void *h, struct uio *uio, int flag);
100 1.1 augustss int irframet_poll(void *h, int events, struct proc *p);
101 1.1 augustss int irframet_set_params(void *h, struct irda_params *params);
102 1.1 augustss int irframet_reset_params(void *h);
103 1.1 augustss int irframet_get_speeds(void *h, int *speeds);
104 1.1 augustss int irframet_get_turnarounds(void *h, int *times);
105 1.1 augustss
106 1.1 augustss int irframet_write_buf(void *h, void *buf, size_t len);
107 1.1 augustss
108 1.1 augustss void irframettyattach(int);
109 1.1 augustss
110 1.1 augustss struct irframe_methods irframet_methods = {
111 1.1 augustss irframet_open, irframet_close, irframet_read, irframet_write,
112 1.1 augustss irframet_poll, irframet_set_params, irframet_reset_params,
113 1.1 augustss irframet_get_speeds, irframet_get_speeds
114 1.1 augustss };
115 1.1 augustss
116 1.1 augustss void
117 1.1 augustss irframettyattach(int n)
118 1.1 augustss {
119 1.1 augustss }
120 1.1 augustss
121 1.1 augustss /*
122 1.1 augustss * Line specific open routine for async tty devices.
123 1.1 augustss * Attach the given tty to the first available irframe unit.
124 1.1 augustss * Called from device open routine or ttioctl.
125 1.1 augustss */
126 1.1 augustss /* ARGSUSED */
127 1.1 augustss int
128 1.1 augustss irframetopen(dev_t dev, struct tty *tp)
129 1.1 augustss {
130 1.1 augustss struct proc *p = curproc; /* XXX */
131 1.1 augustss struct irframet_softc *sc;
132 1.1 augustss int error, s;
133 1.1 augustss
134 1.1 augustss DPRINTF(("%s\n", __FUNCTION__));
135 1.1 augustss
136 1.1 augustss if ((error = suser(p->p_ucred, &p->p_acflag)) != 0)
137 1.1 augustss return (error);
138 1.1 augustss
139 1.1 augustss s = spltty();
140 1.1 augustss
141 1.1 augustss DPRINTF(("%s: linesw=%p disc=%d\n", __FUNCTION__, tp->t_linesw,
142 1.1 augustss tp->t_linesw->l_no));
143 1.1 augustss if (tp->t_linesw->l_no == IRFRAMEDISC) {
144 1.1 augustss sc = (struct irframet_softc *)tp->t_sc;
145 1.1 augustss DPRINTF(("%s: sc=%p sc_tp=%p\n", __FUNCTION__, sc, sc->sc_tp));
146 1.1 augustss if (sc != NULL) {
147 1.1 augustss splx(s);
148 1.1 augustss return (EBUSY);
149 1.1 augustss }
150 1.1 augustss }
151 1.1 augustss
152 1.1 augustss printf("%s attached at tty%d:", sc->sc_irp.sc_dev.dv_xname,
153 1.1 augustss minor(tp->t_dev));
154 1.1 augustss tp->t_sc = irframe_alloc(sizeof (struct irframet_softc),
155 1.1 augustss &irframet_methods, tp);
156 1.1 augustss sc = (struct irframet_softc *)tp->t_sc;
157 1.1 augustss sc->sc_tp = tp;
158 1.1 augustss
159 1.1 augustss DPRINTF(("%s: set sc=%p\n", __FUNCTION__, sc));
160 1.1 augustss
161 1.1 augustss ttyflush(tp, FREAD | FWRITE);
162 1.1 augustss
163 1.1 augustss splx(s);
164 1.1 augustss return (0);
165 1.1 augustss }
166 1.1 augustss
167 1.1 augustss /*
168 1.1 augustss * Line specific close routine, called from device close routine
169 1.1 augustss * and from ttioctl.
170 1.1 augustss * Detach the tty from the irframe unit.
171 1.1 augustss * Mimics part of ttyclose().
172 1.1 augustss */
173 1.1 augustss int
174 1.1 augustss irframetclose(struct tty *tp, int flag)
175 1.1 augustss {
176 1.1 augustss struct irframet_softc *sc = (struct irframet_softc *)tp->t_sc;
177 1.1 augustss int s;
178 1.1 augustss
179 1.1 augustss DPRINTF(("%s: tp=%p\n", __FUNCTION__, tp));
180 1.1 augustss
181 1.1 augustss s = spltty();
182 1.1 augustss ttyflush(tp, FREAD | FWRITE);
183 1.1 augustss tp->t_linesw = linesw[0]; /* default line discipline */
184 1.1 augustss if (sc != NULL) {
185 1.1 augustss tp->t_sc = NULL;
186 1.1 augustss printf("%s detached from tty%d\n", sc->sc_irp.sc_dev.dv_xname,
187 1.1 augustss minor(tp->t_dev));
188 1.1 augustss
189 1.1 augustss if (sc->sc_tp == tp)
190 1.1 augustss irframe_dealloc(&sc->sc_irp.sc_dev);
191 1.1 augustss }
192 1.1 augustss splx(s);
193 1.1 augustss return (0);
194 1.1 augustss }
195 1.1 augustss
196 1.1 augustss /*
197 1.1 augustss * Line specific (tty) ioctl routine.
198 1.1 augustss * This discipline requires that tty device drivers call
199 1.1 augustss * the line specific l_ioctl routine from their ioctl routines.
200 1.1 augustss */
201 1.1 augustss /* ARGSUSED */
202 1.1 augustss int
203 1.1 augustss irframetioctl(struct tty *tp, u_long cmd, caddr_t data, int flag,
204 1.1 augustss struct proc *p)
205 1.1 augustss {
206 1.1 augustss struct irframet_softc *sc = (struct irframet_softc *)tp->t_sc;
207 1.1 augustss int error;
208 1.1 augustss
209 1.1 augustss DPRINTF(("%s: tp=%p\n", __FUNCTION__, tp));
210 1.1 augustss
211 1.1 augustss if (sc == NULL || tp != sc->sc_tp)
212 1.1 augustss return (-1);
213 1.1 augustss
214 1.1 augustss error = 0;
215 1.1 augustss switch (cmd) {
216 1.1 augustss default:
217 1.1 augustss #if 0
218 1.1 augustss error = irframeioctl(sc, cmd, data, flag, p);
219 1.1 augustss #else
220 1.1 augustss error = EINVAL;
221 1.1 augustss #endif
222 1.1 augustss break;
223 1.1 augustss }
224 1.1 augustss
225 1.1 augustss return (error);
226 1.1 augustss }
227 1.1 augustss
228 1.1 augustss /*
229 1.1 augustss * Start output on async tty interface. If the transmit queue
230 1.1 augustss * has drained sufficiently, arrange for irframeasyncstart to be
231 1.1 augustss * called later at splsoftnet.
232 1.1 augustss * Called at spltty or higher.
233 1.1 augustss */
234 1.1 augustss int
235 1.1 augustss irframetstart(struct tty *tp)
236 1.1 augustss {
237 1.1 augustss /*struct irframet_softc *sc = (struct irframet_softc *)tp->t_sc;*/
238 1.1 augustss
239 1.1 augustss DPRINTF(("%s: tp=%p\n", __FUNCTION__, tp));
240 1.1 augustss
241 1.1 augustss /*
242 1.1 augustss * If there is stuff in the output queue, send it now.
243 1.1 augustss * We are being called in lieu of ttstart and must do what it would.
244 1.1 augustss */
245 1.1 augustss if (tp->t_oproc != NULL)
246 1.1 augustss (*tp->t_oproc)(tp);
247 1.1 augustss
248 1.1 augustss return (0);
249 1.1 augustss }
250 1.1 augustss
251 1.1 augustss int
252 1.1 augustss irframetinput(int c, struct tty *tp)
253 1.1 augustss {
254 1.1 augustss struct irframet_softc *sc = (struct irframet_softc *)tp->t_sc;
255 1.1 augustss
256 1.1 augustss DPRINTF(("%s: tp=%p c=0x%0x\n", __FUNCTION__, tp, c));
257 1.1 augustss
258 1.1 augustss if (sc == NULL || tp != (struct tty *)sc->sc_tp)
259 1.1 augustss return (0);
260 1.1 augustss #if 0
261 1.1 augustss
262 1.1 augustss
263 1.1 augustss ++tk_nin;
264 1.1 augustss ++sc->sc_stats.irframe_ibytes;
265 1.1 augustss
266 1.1 augustss if (c & TTY_FE) {
267 1.1 augustss /* framing error or overrun on this char - abort packet */
268 1.1 augustss if (sc->sc_flags & SC_DEBUG)
269 1.1 augustss printf("%s: bad char %x\n", sc->sc_if.if_xname, c);
270 1.1 augustss goto flush;
271 1.1 augustss }
272 1.1 augustss
273 1.1 augustss c &= 0xff;
274 1.1 augustss
275 1.1 augustss /*
276 1.1 augustss * Handle software flow control of output.
277 1.1 augustss */
278 1.1 augustss if (tp->t_iflag & IXON) {
279 1.1 augustss if (c == tp->t_cc[VSTOP] && tp->t_cc[VSTOP] != _POSIX_VDISABLE) {
280 1.1 augustss if ((tp->t_state & TS_TTSTOP) == 0) {
281 1.1 augustss tp->t_state |= TS_TTSTOP;
282 1.1 augustss (*cdevsw[major(tp->t_dev)].d_stop)(tp, 0);
283 1.1 augustss }
284 1.1 augustss return 0;
285 1.1 augustss }
286 1.1 augustss if (c == tp->t_cc[VSTART] && tp->t_cc[VSTART] != _POSIX_VDISABLE) {
287 1.1 augustss tp->t_state &= ~TS_TTSTOP;
288 1.1 augustss if (tp->t_oproc != NULL)
289 1.1 augustss (*tp->t_oproc)(tp);
290 1.1 augustss return 0;
291 1.1 augustss }
292 1.1 augustss }
293 1.1 augustss
294 1.1 augustss s = spltty();
295 1.1 augustss if (c & 0x80)
296 1.1 augustss sc->sc_flags |= SC_RCV_B7_1;
297 1.1 augustss else
298 1.1 augustss sc->sc_flags |= SC_RCV_B7_0;
299 1.1 augustss if (paritytab[c >> 5] & (1 << (c & 0x1F)))
300 1.1 augustss sc->sc_flags |= SC_RCV_ODDP;
301 1.1 augustss else
302 1.1 augustss sc->sc_flags |= SC_RCV_EVNP;
303 1.1 augustss splx(s);
304 1.1 augustss
305 1.1 augustss if (sc->sc_flags & SC_LOG_RAWIN)
306 1.1 augustss irframelogchar(sc, c);
307 1.1 augustss
308 1.1 augustss if (c == IRFRAME_FLAG) {
309 1.1 augustss ilen = sc->sc_ilen;
310 1.1 augustss sc->sc_ilen = 0;
311 1.1 augustss
312 1.1 augustss if (sc->sc_rawin_count > 0)
313 1.1 augustss irframelogchar(sc, -1);
314 1.1 augustss
315 1.1 augustss /*
316 1.1 augustss * If SC_ESCAPED is set, then we've seen the packet
317 1.1 augustss * abort sequence "}~".
318 1.1 augustss */
319 1.1 augustss if (sc->sc_flags & (SC_FLUSH | SC_ESCAPED)
320 1.1 augustss || (ilen > 0 && sc->sc_fcs != IRFRAME_GOODFCS)) {
321 1.1 augustss s = spltty();
322 1.1 augustss sc->sc_flags |= SC_PKTLOST; /* note the dropped packet */
323 1.1 augustss if ((sc->sc_flags & (SC_FLUSH | SC_ESCAPED)) == 0){
324 1.1 augustss if (sc->sc_flags & SC_DEBUG)
325 1.1 augustss printf("%s: bad fcs %x\n", sc->sc_if.if_xname,
326 1.1 augustss sc->sc_fcs);
327 1.1 augustss sc->sc_if.if_ierrors++;
328 1.1 augustss sc->sc_stats.irframe_ierrors++;
329 1.1 augustss } else
330 1.1 augustss sc->sc_flags &= ~(SC_FLUSH | SC_ESCAPED);
331 1.1 augustss splx(s);
332 1.1 augustss return 0;
333 1.1 augustss }
334 1.1 augustss
335 1.1 augustss if (ilen < IRFRAME_HDRLEN + IRFRAME_FCSLEN) {
336 1.1 augustss if (ilen) {
337 1.1 augustss if (sc->sc_flags & SC_DEBUG)
338 1.1 augustss printf("%s: too short (%d)\n", sc->sc_if.if_xname, ilen);
339 1.1 augustss s = spltty();
340 1.1 augustss sc->sc_if.if_ierrors++;
341 1.1 augustss sc->sc_stats.irframe_ierrors++;
342 1.1 augustss sc->sc_flags |= SC_PKTLOST;
343 1.1 augustss splx(s);
344 1.1 augustss }
345 1.1 augustss return 0;
346 1.1 augustss }
347 1.1 augustss
348 1.1 augustss /*
349 1.1 augustss * Remove FCS trailer. Somewhat painful...
350 1.1 augustss */
351 1.1 augustss ilen -= 2;
352 1.1 augustss if (--sc->sc_mc->m_len == 0) {
353 1.1 augustss for (m = sc->sc_m; m->m_next != sc->sc_mc; m = m->m_next)
354 1.1 augustss ;
355 1.1 augustss sc->sc_mc = m;
356 1.1 augustss }
357 1.1 augustss sc->sc_mc->m_len--;
358 1.1 augustss
359 1.1 augustss /* excise this mbuf chain */
360 1.1 augustss m = sc->sc_m;
361 1.1 augustss sc->sc_m = sc->sc_mc->m_next;
362 1.1 augustss sc->sc_mc->m_next = NULL;
363 1.1 augustss
364 1.1 augustss irframepktin(sc, m, sc->sc_flags & SC_PKTLOST);
365 1.1 augustss if (sc->sc_flags & SC_PKTLOST) {
366 1.1 augustss s = spltty();
367 1.1 augustss sc->sc_flags &= ~SC_PKTLOST;
368 1.1 augustss splx(s);
369 1.1 augustss }
370 1.1 augustss
371 1.1 augustss irframegetm(sc);
372 1.1 augustss return 0;
373 1.1 augustss }
374 1.1 augustss
375 1.1 augustss if (sc->sc_flags & SC_FLUSH) {
376 1.1 augustss if (sc->sc_flags & SC_LOG_FLUSH)
377 1.1 augustss irframelogchar(sc, c);
378 1.1 augustss return 0;
379 1.1 augustss }
380 1.1 augustss
381 1.1 augustss if (c < 0x20 && (sc->sc_rasyncmap & (1 << c)))
382 1.1 augustss return 0;
383 1.1 augustss
384 1.1 augustss s = spltty();
385 1.1 augustss if (sc->sc_flags & SC_ESCAPED) {
386 1.1 augustss sc->sc_flags &= ~SC_ESCAPED;
387 1.1 augustss c ^= IRFRAME_TRANS;
388 1.1 augustss } else if (c == IRFRAME_ESCAPE) {
389 1.1 augustss sc->sc_flags |= SC_ESCAPED;
390 1.1 augustss splx(s);
391 1.1 augustss return 0;
392 1.1 augustss }
393 1.1 augustss splx(s);
394 1.1 augustss
395 1.1 augustss /*
396 1.1 augustss * Initialize buffer on first octet received.
397 1.1 augustss * First octet could be address or protocol (when compressing
398 1.1 augustss * address/control).
399 1.1 augustss * Second octet is control.
400 1.1 augustss * Third octet is first or second (when compressing protocol)
401 1.1 augustss * octet of protocol.
402 1.1 augustss * Fourth octet is second octet of protocol.
403 1.1 augustss */
404 1.1 augustss if (sc->sc_ilen == 0) {
405 1.1 augustss /* reset the first input mbuf */
406 1.1 augustss if (sc->sc_m == NULL) {
407 1.1 augustss irframegetm(sc);
408 1.1 augustss if (sc->sc_m == NULL) {
409 1.1 augustss if (sc->sc_flags & SC_DEBUG)
410 1.1 augustss printf("%s: no input mbufs!\n", sc->sc_if.if_xname);
411 1.1 augustss goto flush;
412 1.1 augustss }
413 1.1 augustss }
414 1.1 augustss m = sc->sc_m;
415 1.1 augustss m->m_len = 0;
416 1.1 augustss m->m_data = M_DATASTART(sc->sc_m);
417 1.1 augustss sc->sc_mc = m;
418 1.1 augustss sc->sc_mp = mtod(m, char *);
419 1.1 augustss sc->sc_fcs = IRFRAME_INITFCS;
420 1.1 augustss if (c != IRFRAME_ALLSTATIONS) {
421 1.1 augustss if (sc->sc_flags & SC_REJ_COMP_AC) {
422 1.1 augustss if (sc->sc_flags & SC_DEBUG)
423 1.1 augustss printf("%s: garbage received: 0x%x (need 0xFF)\n",
424 1.1 augustss sc->sc_if.if_xname, c);
425 1.1 augustss goto flush;
426 1.1 augustss }
427 1.1 augustss *sc->sc_mp++ = IRFRAME_ALLSTATIONS;
428 1.1 augustss *sc->sc_mp++ = IRFRAME_UI;
429 1.1 augustss sc->sc_ilen += 2;
430 1.1 augustss m->m_len += 2;
431 1.1 augustss }
432 1.1 augustss }
433 1.1 augustss if (sc->sc_ilen == 1 && c != IRFRAME_UI) {
434 1.1 augustss if (sc->sc_flags & SC_DEBUG)
435 1.1 augustss printf("%s: missing UI (0x3), got 0x%x\n",
436 1.1 augustss sc->sc_if.if_xname, c);
437 1.1 augustss goto flush;
438 1.1 augustss }
439 1.1 augustss if (sc->sc_ilen == 2 && (c & 1) == 1) {
440 1.1 augustss /* a compressed protocol */
441 1.1 augustss *sc->sc_mp++ = 0;
442 1.1 augustss sc->sc_ilen++;
443 1.1 augustss sc->sc_mc->m_len++;
444 1.1 augustss }
445 1.1 augustss if (sc->sc_ilen == 3 && (c & 1) == 0) {
446 1.1 augustss if (sc->sc_flags & SC_DEBUG)
447 1.1 augustss printf("%s: bad protocol %x\n", sc->sc_if.if_xname,
448 1.1 augustss (sc->sc_mp[-1] << 8) + c);
449 1.1 augustss goto flush;
450 1.1 augustss }
451 1.1 augustss
452 1.1 augustss /* packet beyond configured mru? */
453 1.1 augustss if (++sc->sc_ilen > sc->sc_mru + IRFRAME_HDRLEN + IRFRAME_FCSLEN) {
454 1.1 augustss if (sc->sc_flags & SC_DEBUG)
455 1.1 augustss printf("%s: packet too big\n", sc->sc_if.if_xname);
456 1.1 augustss goto flush;
457 1.1 augustss }
458 1.1 augustss
459 1.1 augustss /* is this mbuf full? */
460 1.1 augustss m = sc->sc_mc;
461 1.1 augustss if (M_TRAILINGSPACE(m) <= 0) {
462 1.1 augustss if (m->m_next == NULL) {
463 1.1 augustss irframegetm(sc);
464 1.1 augustss if (m->m_next == NULL) {
465 1.1 augustss if (sc->sc_flags & SC_DEBUG)
466 1.1 augustss printf("%s: too few input mbufs!\n", sc->sc_if.if_xname);
467 1.1 augustss goto flush;
468 1.1 augustss }
469 1.1 augustss }
470 1.1 augustss sc->sc_mc = m = m->m_next;
471 1.1 augustss m->m_len = 0;
472 1.1 augustss m->m_data = M_DATASTART(m);
473 1.1 augustss sc->sc_mp = mtod(m, char *);
474 1.1 augustss }
475 1.1 augustss
476 1.1 augustss ++m->m_len;
477 1.1 augustss *sc->sc_mp++ = c;
478 1.1 augustss sc->sc_fcs = IRFRAME_FCS(sc->sc_fcs, c);
479 1.1 augustss return 0;
480 1.1 augustss
481 1.1 augustss flush:
482 1.1 augustss if (!(sc->sc_flags & SC_FLUSH)) {
483 1.1 augustss s = spltty();
484 1.1 augustss sc->sc_if.if_ierrors++;
485 1.1 augustss sc->sc_stats.irframe_ierrors++;
486 1.1 augustss sc->sc_flags |= SC_FLUSH;
487 1.1 augustss splx(s);
488 1.1 augustss if (sc->sc_flags & SC_LOG_FLUSH)
489 1.1 augustss irframelogchar(sc, c);
490 1.1 augustss }
491 1.1 augustss #endif
492 1.1 augustss return 0;
493 1.1 augustss }
494 1.1 augustss
495 1.1 augustss
496 1.1 augustss /**********************************************************************
497 1.1 augustss * CRC
498 1.1 augustss **********************************************************************/
499 1.1 augustss
500 1.1 augustss static const int fcstab[] = {
501 1.1 augustss 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
502 1.1 augustss 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
503 1.1 augustss 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
504 1.1 augustss 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
505 1.1 augustss 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
506 1.1 augustss 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
507 1.1 augustss 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
508 1.1 augustss 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
509 1.1 augustss 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
510 1.1 augustss 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
511 1.1 augustss 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
512 1.1 augustss 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
513 1.1 augustss 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
514 1.1 augustss 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
515 1.1 augustss 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
516 1.1 augustss 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
517 1.1 augustss 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
518 1.1 augustss 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
519 1.1 augustss 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
520 1.1 augustss 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
521 1.1 augustss 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
522 1.1 augustss 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
523 1.1 augustss 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
524 1.1 augustss 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
525 1.1 augustss 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
526 1.1 augustss 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
527 1.1 augustss 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
528 1.1 augustss 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
529 1.1 augustss 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
530 1.1 augustss 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
531 1.1 augustss 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
532 1.1 augustss 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
533 1.1 augustss };
534 1.1 augustss
535 1.1 augustss static const int INITFCS = 0xffff;
536 1.1 augustss static const int GOODFCS = 0xf0b8;
537 1.1 augustss
538 1.1 augustss static __inline int updateFCS(int fcs, int c) {
539 1.1 augustss return (fcs >> 8) ^ fcstab[(fcs^c) & 0xff];
540 1.1 augustss }
541 1.1 augustss
542 1.1 augustss /*** irframe methods ***/
543 1.1 augustss
544 1.1 augustss int
545 1.1 augustss irframet_open(void *h, int flag, int mode, struct proc *p)
546 1.1 augustss {
547 1.1 augustss struct tty *tp = h;
548 1.1 augustss
549 1.1 augustss tp = tp;
550 1.1 augustss DPRINTF(("%s: tp=%p\n", __FUNCTION__, tp));
551 1.1 augustss return (0);
552 1.1 augustss }
553 1.1 augustss
554 1.1 augustss int
555 1.1 augustss irframet_close(void *h, int flag, int mode, struct proc *p)
556 1.1 augustss {
557 1.1 augustss struct tty *tp = h;
558 1.1 augustss
559 1.1 augustss tp = tp;
560 1.1 augustss DPRINTF(("%s: tp=%p\n", __FUNCTION__, tp));
561 1.1 augustss return (0);
562 1.1 augustss }
563 1.1 augustss
564 1.1 augustss int
565 1.1 augustss irframet_read(void *h, struct uio *uio, int flag)
566 1.1 augustss {
567 1.1 augustss struct tty *tp = h;
568 1.1 augustss
569 1.1 augustss tp = tp;
570 1.1 augustss DPRINTF(("%s: tp=%p\n", __FUNCTION__, tp));
571 1.1 augustss return (0);
572 1.1 augustss }
573 1.1 augustss
574 1.1 augustss static int
575 1.1 augustss putch(int c, struct tty *tp)
576 1.1 augustss {
577 1.1 augustss int s;
578 1.1 augustss int error;
579 1.1 augustss
580 1.1 augustss if (tp->t_outq.c_cc > tp->t_hiwat) {
581 1.1 augustss irframetstart(tp);
582 1.1 augustss s = spltty();
583 1.1 augustss /*
584 1.1 augustss * This can only occur if FLUSHO is set in t_lflag,
585 1.1 augustss * or if ttstart/oproc is synchronous (or very fast).
586 1.1 augustss */
587 1.1 augustss if (tp->t_outq.c_cc <= tp->t_hiwat) {
588 1.1 augustss splx(s);
589 1.1 augustss goto go;
590 1.1 augustss }
591 1.1 augustss SET(tp->t_state, TS_ASLEEP);
592 1.1 augustss error = ttysleep(tp, &tp->t_outq, TTOPRI | PCATCH, ttyout, 0);
593 1.1 augustss splx(s);
594 1.1 augustss if (error)
595 1.1 augustss return (error);
596 1.1 augustss }
597 1.1 augustss go:
598 1.1 augustss if (putc(c, &tp->t_rawq) < 0) {
599 1.1 augustss printf("irframe: putc failed\n");
600 1.1 augustss return (EIO);
601 1.1 augustss }
602 1.1 augustss return (0);
603 1.1 augustss }
604 1.1 augustss
605 1.1 augustss static int
606 1.1 augustss put_esc(int c, struct tty *tp)
607 1.1 augustss {
608 1.1 augustss int error;
609 1.1 augustss
610 1.1 augustss if (c == SIR_BOF || c == SIR_EOF || c == SIR_CE) {
611 1.1 augustss error = putch(SIR_CE, tp);
612 1.1 augustss if (!error)
613 1.1 augustss error = putch(SIR_ESC_BIT^c, tp);
614 1.1 augustss } else {
615 1.1 augustss error = putch(c, tp);
616 1.1 augustss }
617 1.1 augustss return (error);
618 1.1 augustss }
619 1.1 augustss
620 1.1 augustss int
621 1.1 augustss irframet_write(void *h, struct uio *uio, int flag)
622 1.1 augustss {
623 1.1 augustss u_int8_t buf[MAX_IRDA_FRAME];
624 1.1 augustss size_t n;
625 1.1 augustss int error;
626 1.1 augustss
627 1.1 augustss DPRINTF(("%s\n", __FUNCTION__));
628 1.1 augustss
629 1.1 augustss n = uio->uio_resid;
630 1.1 augustss if (n > MAX_IRDA_FRAME)
631 1.1 augustss return (EINVAL);
632 1.1 augustss error = uiomove(buf, n, uio);
633 1.1 augustss if (error)
634 1.1 augustss return (error);
635 1.1 augustss return (irframet_write_buf(h, buf, n));
636 1.1 augustss }
637 1.1 augustss
638 1.1 augustss int
639 1.1 augustss irframet_write_buf(void *h, void *buf, size_t len)
640 1.1 augustss {
641 1.1 augustss struct tty *tp = h;
642 1.1 augustss struct irframet_softc *sc = (struct irframet_softc *)tp->t_sc;
643 1.1 augustss u_int8_t *cp = buf;
644 1.1 augustss int c, error, ofcs, i;
645 1.1 augustss
646 1.1 augustss DPRINTF(("%s: tp=%p len=%d\n", __FUNCTION__, tp, len));
647 1.1 augustss
648 1.1 augustss ofcs = INITFCS;
649 1.1 augustss error = 0;
650 1.1 augustss
651 1.1 augustss for (i = 0; i < sc->sc_ebofs; i++)
652 1.1 augustss putch(SIR_EXTRA_BOF, tp);
653 1.1 augustss putch(SIR_BOF, tp);
654 1.1 augustss
655 1.1 augustss while (len-- > 0) {
656 1.1 augustss c = *cp++;
657 1.1 augustss ofcs = updateFCS(ofcs, c);
658 1.1 augustss error = put_esc(c, tp);
659 1.1 augustss if (error)
660 1.1 augustss return (error);
661 1.1 augustss }
662 1.1 augustss
663 1.1 augustss ofcs = ~ofcs;
664 1.1 augustss error = put_esc(ofcs & 0xff, tp);
665 1.1 augustss if (!error)
666 1.1 augustss error = put_esc((ofcs >> 8) & 0xff, tp);
667 1.1 augustss if (!error)
668 1.1 augustss error = putch(SIR_EOF, tp);
669 1.1 augustss
670 1.1 augustss irframetstart(tp);
671 1.1 augustss
672 1.1 augustss return (error);
673 1.1 augustss }
674 1.1 augustss
675 1.1 augustss int
676 1.1 augustss irframet_poll(void *h, int events, struct proc *p)
677 1.1 augustss {
678 1.1 augustss struct oboe_softc *sc = h;
679 1.1 augustss int revents = 0;
680 1.1 augustss int s;
681 1.1 augustss
682 1.1 augustss DPRINTF(("%s: sc=%p\n", __FUNCTION__, sc));
683 1.1 augustss
684 1.1 augustss s = splir();
685 1.1 augustss if (events & (POLLOUT | POLLWRNORM))
686 1.1 augustss revents |= events & (POLLOUT | POLLWRNORM);
687 1.1 augustss #if 0
688 1.1 augustss if (events & (POLLIN | POLLRDNORM)) {
689 1.1 augustss if (sc->sc_saved > 0) {
690 1.1 augustss DPRINTF(("%s: have data\n", __FUNCTION__));
691 1.1 augustss revents |= events & (POLLIN | POLLRDNORM);
692 1.1 augustss } else {
693 1.1 augustss DPRINTF(("%s: recording select", __FUNCTION__));
694 1.1 augustss selrecord(p, &sc->sc_rsel);
695 1.1 augustss }
696 1.1 augustss }
697 1.1 augustss #endif
698 1.1 augustss splx(s);
699 1.1 augustss
700 1.1 augustss return (revents);
701 1.1 augustss }
702 1.1 augustss
703 1.1 augustss int
704 1.1 augustss irframet_set_params(void *h, struct irda_params *p)
705 1.1 augustss {
706 1.1 augustss struct tty *tp = h;
707 1.1 augustss struct irframet_softc *sc = (struct irframet_softc *)tp->t_sc;
708 1.1 augustss
709 1.1 augustss DPRINTF(("%s: tp=%p\n", __FUNCTION__, tp));
710 1.1 augustss
711 1.1 augustss /* XXX speed */
712 1.1 augustss sc->sc_ebofs = p->ebofs;
713 1.1 augustss /* XXX maxsize */
714 1.1 augustss
715 1.1 augustss return (0);
716 1.1 augustss }
717 1.1 augustss
718 1.1 augustss int
719 1.1 augustss irframet_reset_params(void *h)
720 1.1 augustss {
721 1.1 augustss struct tty *tp = h;
722 1.1 augustss struct irframet_softc *sc = (struct irframet_softc *)tp->t_sc;
723 1.1 augustss
724 1.1 augustss DPRINTF(("%s: tp=%p\n", __FUNCTION__, tp));
725 1.1 augustss
726 1.1 augustss sc->sc_ebofs = IRDA_DEFAULT_EBOFS;
727 1.1 augustss
728 1.1 augustss return (0);
729 1.1 augustss }
730 1.1 augustss
731 1.1 augustss int
732 1.1 augustss irframet_get_speeds(void *h, int *speeds)
733 1.1 augustss {
734 1.1 augustss struct tty *tp = h;
735 1.1 augustss
736 1.1 augustss tp = tp;
737 1.1 augustss DPRINTF(("%s: tp=%p\n", __FUNCTION__, tp));
738 1.1 augustss *speeds = IRDA_SPEEDS_SIR;
739 1.1 augustss return (0);
740 1.1 augustss }
741 1.1 augustss
742 1.1 augustss int
743 1.1 augustss irframet_get_turnarounds(void *h, int *turnarounds)
744 1.1 augustss {
745 1.1 augustss struct tty *tp = h;
746 1.1 augustss
747 1.1 augustss tp = tp;
748 1.1 augustss DPRINTF(("%s: tp=%p\n", __FUNCTION__, tp));
749 1.1 augustss *turnarounds = IRDA_TURNT_10000;
750 1.1 augustss return (0);
751 1.1 augustss }
752