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