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