sir.c revision 1.5.34.1 1 1.5.34.1 yamt /* $NetBSD: sir.c,v 1.5.34.1 2014/05/22 11:40:22 yamt 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) and Tommy Bohlin
9 1.1 augustss * (tommy (at) gatespace.com).
10 1.1 augustss *
11 1.1 augustss * Redistribution and use in source and binary forms, with or without
12 1.1 augustss * modification, are permitted provided that the following conditions
13 1.1 augustss * are met:
14 1.1 augustss * 1. Redistributions of source code must retain the above copyright
15 1.1 augustss * notice, this list of conditions and the following disclaimer.
16 1.1 augustss * 2. Redistributions in binary form must reproduce the above copyright
17 1.1 augustss * notice, this list of conditions and the following disclaimer in the
18 1.1 augustss * documentation and/or other materials provided with the distribution.
19 1.1 augustss *
20 1.1 augustss * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
21 1.1 augustss * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22 1.1 augustss * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23 1.1 augustss * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
24 1.1 augustss * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25 1.1 augustss * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26 1.1 augustss * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27 1.1 augustss * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 1.1 augustss * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29 1.1 augustss * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30 1.1 augustss * POSSIBILITY OF SUCH DAMAGE.
31 1.1 augustss */
32 1.1 augustss
33 1.1 augustss /*
34 1.1 augustss * Framing originally written by Tommy Bohlin.
35 1.1 augustss */
36 1.3 lukem
37 1.3 lukem #include <sys/cdefs.h>
38 1.5.34.1 yamt __KERNEL_RCSID(0, "$NetBSD: sir.c,v 1.5.34.1 2014/05/22 11:40:22 yamt Exp $");
39 1.1 augustss
40 1.1 augustss #include <sys/param.h>
41 1.1 augustss #include <sys/conf.h>
42 1.1 augustss #include <sys/systm.h>
43 1.1 augustss
44 1.1 augustss #include <dev/ir/sir.h>
45 1.1 augustss
46 1.1 augustss /*
47 1.1 augustss * CRC computation table
48 1.1 augustss */
49 1.5.34.1 yamt const uint16_t irda_fcstab[] = {
50 1.1 augustss 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
51 1.1 augustss 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
52 1.1 augustss 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
53 1.1 augustss 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
54 1.1 augustss 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
55 1.1 augustss 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
56 1.1 augustss 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
57 1.1 augustss 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
58 1.1 augustss 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
59 1.1 augustss 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
60 1.1 augustss 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
61 1.1 augustss 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
62 1.1 augustss 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
63 1.1 augustss 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
64 1.1 augustss 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
65 1.1 augustss 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
66 1.1 augustss 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
67 1.1 augustss 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
68 1.1 augustss 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
69 1.1 augustss 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
70 1.1 augustss 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
71 1.1 augustss 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
72 1.1 augustss 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
73 1.1 augustss 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
74 1.1 augustss 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
75 1.1 augustss 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
76 1.1 augustss 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
77 1.1 augustss 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
78 1.1 augustss 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
79 1.1 augustss 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
80 1.1 augustss 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
81 1.1 augustss 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
82 1.1 augustss };
83 1.1 augustss
84 1.1 augustss #define MAX_IRDA_FRAME 5000 /* XXX what is it? */
85 1.1 augustss
86 1.1 augustss #define PUTC(c) if (p < end) *p++ = (c)
87 1.1 augustss #define PUTESC(c) \
88 1.1 augustss if (c == SIR_BOF || c == SIR_EOF || c == SIR_CE) { \
89 1.1 augustss PUTC(SIR_CE); \
90 1.1 augustss PUTC(SIR_ESC_BIT^c); \
91 1.1 augustss } else { \
92 1.1 augustss PUTC(c); \
93 1.1 augustss }
94 1.1 augustss
95 1.2 augustss #define CHUNK 512
96 1.2 augustss
97 1.1 augustss int
98 1.5.34.1 yamt irda_sir_frame(uint8_t *obuf, u_int maxlen, struct uio *uio, u_int ebofs)
99 1.1 augustss {
100 1.5.34.1 yamt uint8_t ibuf[CHUNK];
101 1.5.34.1 yamt uint8_t *p, *end, *cp;
102 1.1 augustss size_t n;
103 1.1 augustss int error;
104 1.1 augustss int i;
105 1.1 augustss int c;
106 1.5.34.1 yamt uint16_t ofcs;
107 1.1 augustss
108 1.2 augustss p = obuf;
109 1.2 augustss end = p + maxlen;
110 1.1 augustss
111 1.1 augustss for (i = 0; i < ebofs; i++)
112 1.1 augustss PUTC(SIR_EXTRA_BOF);
113 1.1 augustss PUTC(SIR_BOF);
114 1.1 augustss
115 1.1 augustss ofcs = INITFCS;
116 1.2 augustss while (uio->uio_resid > 0) {
117 1.2 augustss n = uio->uio_resid;
118 1.2 augustss if (n > CHUNK)
119 1.2 augustss n = CHUNK;
120 1.2 augustss error = uiomove(ibuf, n, uio);
121 1.2 augustss if (error)
122 1.2 augustss return (-error);
123 1.2 augustss
124 1.2 augustss cp = ibuf;
125 1.2 augustss while (n-- > 0) {
126 1.2 augustss c = *cp++;
127 1.2 augustss ofcs = updateFCS(ofcs, c);
128 1.2 augustss PUTESC(c);
129 1.2 augustss }
130 1.1 augustss }
131 1.1 augustss
132 1.1 augustss ofcs = ~ofcs;
133 1.1 augustss c = ofcs & 0xff;
134 1.1 augustss PUTESC(c);
135 1.1 augustss c = (ofcs >> 8) & 0xff;
136 1.1 augustss PUTESC(c);
137 1.1 augustss PUTC(SIR_EOF);
138 1.1 augustss
139 1.1 augustss if (p < end)
140 1.1 augustss return (p - obuf);
141 1.1 augustss else
142 1.1 augustss return (-EINVAL);
143 1.1 augustss }
144 1.5.34.1 yamt
145 1.5.34.1 yamt void
146 1.5.34.1 yamt deframe_init(struct framestate *fstate, uint8_t *buf, size_t buflen)
147 1.5.34.1 yamt {
148 1.5.34.1 yamt
149 1.5.34.1 yamt fstate->buffer = buf;
150 1.5.34.1 yamt fstate->buflen = buflen;
151 1.5.34.1 yamt
152 1.5.34.1 yamt deframe_clear(fstate);
153 1.5.34.1 yamt }
154 1.5.34.1 yamt
155 1.5.34.1 yamt void
156 1.5.34.1 yamt deframe_clear(struct framestate *fstate)
157 1.5.34.1 yamt {
158 1.5.34.1 yamt
159 1.5.34.1 yamt fstate->bufindex = 0;
160 1.5.34.1 yamt fstate->fsmstate = FSTATE_END_OF_FRAME;
161 1.5.34.1 yamt fstate->escaped = 0;
162 1.5.34.1 yamt }
163 1.5.34.1 yamt
164 1.5.34.1 yamt enum frameresult
165 1.5.34.1 yamt deframe_process(struct framestate *fstate, uint8_t const **bptr, size_t *blen)
166 1.5.34.1 yamt {
167 1.5.34.1 yamt uint8_t const *cptr;
168 1.5.34.1 yamt size_t ibuflen, obufindex, obuflen;
169 1.5.34.1 yamt enum framefsmstate fsmstate;
170 1.5.34.1 yamt enum frameresult result;
171 1.5.34.1 yamt
172 1.5.34.1 yamt cptr = *bptr;
173 1.5.34.1 yamt fsmstate = fstate->fsmstate;
174 1.5.34.1 yamt obufindex = fstate->bufindex;
175 1.5.34.1 yamt obuflen = fstate->buflen;
176 1.5.34.1 yamt ibuflen = *blen;
177 1.5.34.1 yamt
178 1.5.34.1 yamt while (ibuflen-- > 0) {
179 1.5.34.1 yamt uint8_t chr;
180 1.5.34.1 yamt
181 1.5.34.1 yamt chr = *cptr++;
182 1.5.34.1 yamt
183 1.5.34.1 yamt if (fstate->escaped) {
184 1.5.34.1 yamt fstate->escaped = 0;
185 1.5.34.1 yamt chr ^= SIR_ESC_BIT;
186 1.5.34.1 yamt } else if (chr == SIR_CE) {
187 1.5.34.1 yamt fstate->escaped = 1;
188 1.5.34.1 yamt continue;
189 1.5.34.1 yamt }
190 1.5.34.1 yamt
191 1.5.34.1 yamt switch (fsmstate) {
192 1.5.34.1 yamt case FSTATE_IN_DATA:
193 1.5.34.1 yamt if (chr == SIR_EOF) {
194 1.5.34.1 yamt fsmstate = FSTATE_IN_END;
195 1.5.34.1 yamt fstate->state_index = 1;
196 1.5.34.1 yamt goto state_in_end;
197 1.5.34.1 yamt }
198 1.5.34.1 yamt if (obufindex >= obuflen) {
199 1.5.34.1 yamt result = FR_BUFFEROVERRUN;
200 1.5.34.1 yamt fsmstate = FSTATE_END_OF_FRAME;
201 1.5.34.1 yamt goto complete;
202 1.5.34.1 yamt }
203 1.5.34.1 yamt fstate->buffer[obufindex++] = chr;
204 1.5.34.1 yamt break;
205 1.5.34.1 yamt
206 1.5.34.1 yamt state_in_end:
207 1.5.34.1 yamt /* FALLTHROUGH */
208 1.5.34.1 yamt
209 1.5.34.1 yamt case FSTATE_IN_END:
210 1.5.34.1 yamt if (--fstate->state_index == 0) {
211 1.5.34.1 yamt uint32_t crc;
212 1.5.34.1 yamt const size_t fcslen = 2;
213 1.5.34.1 yamt
214 1.5.34.1 yamt fsmstate = FSTATE_END_OF_FRAME;
215 1.5.34.1 yamt
216 1.5.34.1 yamt if (obufindex < fcslen) {
217 1.5.34.1 yamt result = FR_FRAMEMALFORMED;
218 1.5.34.1 yamt goto complete;
219 1.5.34.1 yamt }
220 1.5.34.1 yamt
221 1.5.34.1 yamt crc = crc_ccitt_16(INITFCS, fstate->buffer,
222 1.5.34.1 yamt obufindex);
223 1.5.34.1 yamt
224 1.5.34.1 yamt /* Remove check bytes from buffer length */
225 1.5.34.1 yamt obufindex -= fcslen;
226 1.5.34.1 yamt
227 1.5.34.1 yamt if (crc == GOODFCS)
228 1.5.34.1 yamt result = FR_FRAMEOK;
229 1.5.34.1 yamt else
230 1.5.34.1 yamt result = FR_FRAMEBADFCS;
231 1.5.34.1 yamt
232 1.5.34.1 yamt goto complete;
233 1.5.34.1 yamt }
234 1.5.34.1 yamt break;
235 1.5.34.1 yamt
236 1.5.34.1 yamt case FSTATE_END_OF_FRAME:
237 1.5.34.1 yamt if (chr != SIR_BOF)
238 1.5.34.1 yamt break;
239 1.5.34.1 yamt
240 1.5.34.1 yamt fsmstate = FSTATE_START_OF_FRAME;
241 1.5.34.1 yamt fstate->state_index = 1;
242 1.5.34.1 yamt /* FALLTHROUGH */
243 1.5.34.1 yamt case FSTATE_START_OF_FRAME:
244 1.5.34.1 yamt if (--fstate->state_index == 0) {
245 1.5.34.1 yamt fsmstate = FSTATE_IN_DATA;
246 1.5.34.1 yamt obufindex = 0;
247 1.5.34.1 yamt }
248 1.5.34.1 yamt break;
249 1.5.34.1 yamt }
250 1.5.34.1 yamt }
251 1.5.34.1 yamt
252 1.5.34.1 yamt result = (fsmstate == FSTATE_END_OF_FRAME) ? FR_IDLE : FR_INPROGRESS;
253 1.5.34.1 yamt
254 1.5.34.1 yamt complete:
255 1.5.34.1 yamt fstate->bufindex = obufindex;
256 1.5.34.1 yamt fstate->fsmstate = fsmstate;
257 1.5.34.1 yamt *blen = ibuflen;
258 1.5.34.1 yamt
259 1.5.34.1 yamt return result;
260 1.5.34.1 yamt }
261 1.5.34.1 yamt
262 1.5.34.1 yamt uint32_t
263 1.5.34.1 yamt crc_ccitt_16(uint32_t crcinit, uint8_t const *buf, size_t blen)
264 1.5.34.1 yamt {
265 1.5.34.1 yamt
266 1.5.34.1 yamt while (blen-- > 0) {
267 1.5.34.1 yamt uint8_t chr;
268 1.5.34.1 yamt chr = *buf++;
269 1.5.34.1 yamt crcinit = updateFCS(crcinit, chr);
270 1.5.34.1 yamt }
271 1.5.34.1 yamt return crcinit;
272 1.5.34.1 yamt }
273