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