sir.c revision 1.6 1 1.6 kiyohara /* $NetBSD: sir.c,v 1.6 2013/05/27 16:23:20 kiyohara 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.6 kiyohara __KERNEL_RCSID(0, "$NetBSD: sir.c,v 1.6 2013/05/27 16:23:20 kiyohara 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.6 kiyohara 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.6 kiyohara irda_sir_frame(uint8_t *obuf, u_int maxlen, struct uio *uio, u_int ebofs)
99 1.1 augustss {
100 1.6 kiyohara uint8_t ibuf[CHUNK];
101 1.6 kiyohara 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.6 kiyohara 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.6 kiyohara
145 1.6 kiyohara void
146 1.6 kiyohara deframe_init(struct framestate *fstate, uint8_t *buf, size_t buflen)
147 1.6 kiyohara {
148 1.6 kiyohara
149 1.6 kiyohara fstate->buffer = buf;
150 1.6 kiyohara fstate->buflen = buflen;
151 1.6 kiyohara
152 1.6 kiyohara deframe_clear(fstate);
153 1.6 kiyohara }
154 1.6 kiyohara
155 1.6 kiyohara void
156 1.6 kiyohara deframe_clear(struct framestate *fstate)
157 1.6 kiyohara {
158 1.6 kiyohara
159 1.6 kiyohara fstate->bufindex = 0;
160 1.6 kiyohara fstate->fsmstate = FSTATE_END_OF_FRAME;
161 1.6 kiyohara fstate->escaped = 0;
162 1.6 kiyohara }
163 1.6 kiyohara
164 1.6 kiyohara enum frameresult
165 1.6 kiyohara deframe_process(struct framestate *fstate, uint8_t const **bptr, size_t *blen)
166 1.6 kiyohara {
167 1.6 kiyohara uint8_t const *cptr;
168 1.6 kiyohara size_t ibuflen, obufindex, obuflen;
169 1.6 kiyohara enum framefsmstate fsmstate;
170 1.6 kiyohara enum frameresult result;
171 1.6 kiyohara
172 1.6 kiyohara cptr = *bptr;
173 1.6 kiyohara fsmstate = fstate->fsmstate;
174 1.6 kiyohara obufindex = fstate->bufindex;
175 1.6 kiyohara obuflen = fstate->buflen;
176 1.6 kiyohara ibuflen = *blen;
177 1.6 kiyohara
178 1.6 kiyohara while (ibuflen-- > 0) {
179 1.6 kiyohara uint8_t chr;
180 1.6 kiyohara
181 1.6 kiyohara chr = *cptr++;
182 1.6 kiyohara
183 1.6 kiyohara if (fstate->escaped) {
184 1.6 kiyohara fstate->escaped = 0;
185 1.6 kiyohara chr ^= SIR_ESC_BIT;
186 1.6 kiyohara } else if (chr == SIR_CE) {
187 1.6 kiyohara fstate->escaped = 1;
188 1.6 kiyohara continue;
189 1.6 kiyohara }
190 1.6 kiyohara
191 1.6 kiyohara switch (fsmstate) {
192 1.6 kiyohara case FSTATE_IN_DATA:
193 1.6 kiyohara if (chr == SIR_EOF) {
194 1.6 kiyohara fsmstate = FSTATE_IN_END;
195 1.6 kiyohara fstate->state_index = 1;
196 1.6 kiyohara goto state_in_end;
197 1.6 kiyohara }
198 1.6 kiyohara if (obufindex >= obuflen) {
199 1.6 kiyohara result = FR_BUFFEROVERRUN;
200 1.6 kiyohara fsmstate = FSTATE_END_OF_FRAME;
201 1.6 kiyohara goto complete;
202 1.6 kiyohara }
203 1.6 kiyohara fstate->buffer[obufindex++] = chr;
204 1.6 kiyohara break;
205 1.6 kiyohara
206 1.6 kiyohara state_in_end:
207 1.6 kiyohara /* FALLTHROUGH */
208 1.6 kiyohara
209 1.6 kiyohara case FSTATE_IN_END:
210 1.6 kiyohara if (--fstate->state_index == 0) {
211 1.6 kiyohara uint32_t crc;
212 1.6 kiyohara const size_t fcslen = 2;
213 1.6 kiyohara
214 1.6 kiyohara fsmstate = FSTATE_END_OF_FRAME;
215 1.6 kiyohara
216 1.6 kiyohara if (obufindex < fcslen) {
217 1.6 kiyohara result = FR_FRAMEMALFORMED;
218 1.6 kiyohara goto complete;
219 1.6 kiyohara }
220 1.6 kiyohara
221 1.6 kiyohara crc = crc_ccitt_16(INITFCS, fstate->buffer,
222 1.6 kiyohara obufindex);
223 1.6 kiyohara
224 1.6 kiyohara /* Remove check bytes from buffer length */
225 1.6 kiyohara obufindex -= fcslen;
226 1.6 kiyohara
227 1.6 kiyohara if (crc == GOODFCS)
228 1.6 kiyohara result = FR_FRAMEOK;
229 1.6 kiyohara else
230 1.6 kiyohara result = FR_FRAMEBADFCS;
231 1.6 kiyohara
232 1.6 kiyohara goto complete;
233 1.6 kiyohara }
234 1.6 kiyohara break;
235 1.6 kiyohara
236 1.6 kiyohara case FSTATE_END_OF_FRAME:
237 1.6 kiyohara if (chr != SIR_BOF)
238 1.6 kiyohara break;
239 1.6 kiyohara
240 1.6 kiyohara fsmstate = FSTATE_START_OF_FRAME;
241 1.6 kiyohara fstate->state_index = 1;
242 1.6 kiyohara /* FALLTHROUGH */
243 1.6 kiyohara case FSTATE_START_OF_FRAME:
244 1.6 kiyohara if (--fstate->state_index == 0) {
245 1.6 kiyohara fsmstate = FSTATE_IN_DATA;
246 1.6 kiyohara obufindex = 0;
247 1.6 kiyohara }
248 1.6 kiyohara break;
249 1.6 kiyohara }
250 1.6 kiyohara }
251 1.6 kiyohara
252 1.6 kiyohara result = (fsmstate == FSTATE_END_OF_FRAME) ? FR_IDLE : FR_INPROGRESS;
253 1.6 kiyohara
254 1.6 kiyohara complete:
255 1.6 kiyohara fstate->bufindex = obufindex;
256 1.6 kiyohara fstate->fsmstate = fsmstate;
257 1.6 kiyohara *blen = ibuflen;
258 1.6 kiyohara
259 1.6 kiyohara return result;
260 1.6 kiyohara }
261 1.6 kiyohara
262 1.6 kiyohara uint32_t
263 1.6 kiyohara crc_ccitt_16(uint32_t crcinit, uint8_t const *buf, size_t blen)
264 1.6 kiyohara {
265 1.6 kiyohara
266 1.6 kiyohara while (blen-- > 0) {
267 1.6 kiyohara uint8_t chr;
268 1.6 kiyohara chr = *buf++;
269 1.6 kiyohara crcinit = updateFCS(crcinit, chr);
270 1.6 kiyohara }
271 1.6 kiyohara return crcinit;
272 1.6 kiyohara }
273