linux/drivers/isdn/gigaset/isocdata.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2/*
   3 * Common data handling layer for bas_gigaset
   4 *
   5 * Copyright (c) 2005 by Tilman Schmidt <tilman@imap.cc>,
   6 *                       Hansjoerg Lipp <hjlipp@web.de>.
   7 *
   8 * =====================================================================
   9 * =====================================================================
  10 */
  11
  12#include "gigaset.h"
  13#include <linux/crc-ccitt.h>
  14#include <linux/bitrev.h>
  15
  16/* access methods for isowbuf_t */
  17/* ============================ */
  18
  19/* initialize buffer structure
  20 */
  21void gigaset_isowbuf_init(struct isowbuf_t *iwb, unsigned char idle)
  22{
  23        iwb->read = 0;
  24        iwb->nextread = 0;
  25        iwb->write = 0;
  26        atomic_set(&iwb->writesem, 1);
  27        iwb->wbits = 0;
  28        iwb->idle = idle;
  29        memset(iwb->data + BAS_OUTBUFSIZE, idle, BAS_OUTBUFPAD);
  30}
  31
  32/* compute number of bytes which can be appended to buffer
  33 * so that there is still room to append a maximum frame of flags
  34 */
  35static inline int isowbuf_freebytes(struct isowbuf_t *iwb)
  36{
  37        int read, write, freebytes;
  38
  39        read = iwb->read;
  40        write = iwb->write;
  41        freebytes = read - write;
  42        if (freebytes > 0) {
  43                /* no wraparound: need padding space within regular area */
  44                return freebytes - BAS_OUTBUFPAD;
  45        } else if (read < BAS_OUTBUFPAD) {
  46                /* wraparound: can use space up to end of regular area */
  47                return BAS_OUTBUFSIZE - write;
  48        } else {
  49                /* following the wraparound yields more space */
  50                return freebytes + BAS_OUTBUFSIZE - BAS_OUTBUFPAD;
  51        }
  52}
  53
  54/* start writing
  55 * acquire the write semaphore
  56 * return 0 if acquired, <0 if busy
  57 */
  58static inline int isowbuf_startwrite(struct isowbuf_t *iwb)
  59{
  60        if (!atomic_dec_and_test(&iwb->writesem)) {
  61                atomic_inc(&iwb->writesem);
  62                gig_dbg(DEBUG_ISO, "%s: couldn't acquire iso write semaphore",
  63                        __func__);
  64                return -EBUSY;
  65        }
  66        gig_dbg(DEBUG_ISO,
  67                "%s: acquired iso write semaphore, data[write]=%02x, nbits=%d",
  68                __func__, iwb->data[iwb->write], iwb->wbits);
  69        return 0;
  70}
  71
  72/* finish writing
  73 * release the write semaphore
  74 * returns the current write position
  75 */
  76static inline int isowbuf_donewrite(struct isowbuf_t *iwb)
  77{
  78        int write = iwb->write;
  79        atomic_inc(&iwb->writesem);
  80        return write;
  81}
  82
  83/* append bits to buffer without any checks
  84 * - data contains bits to append, starting at LSB
  85 * - nbits is number of bits to append (0..24)
  86 * must be called with the write semaphore held
  87 * If more than nbits bits are set in data, the extraneous bits are set in the
  88 * buffer too, but the write position is only advanced by nbits.
  89 */
  90static inline void isowbuf_putbits(struct isowbuf_t *iwb, u32 data, int nbits)
  91{
  92        int write = iwb->write;
  93        data <<= iwb->wbits;
  94        data |= iwb->data[write];
  95        nbits += iwb->wbits;
  96        while (nbits >= 8) {
  97                iwb->data[write++] = data & 0xff;
  98                write %= BAS_OUTBUFSIZE;
  99                data >>= 8;
 100                nbits -= 8;
 101        }
 102        iwb->wbits = nbits;
 103        iwb->data[write] = data & 0xff;
 104        iwb->write = write;
 105}
 106
 107/* put final flag on HDLC bitstream
 108 * also sets the idle fill byte to the correspondingly shifted flag pattern
 109 * must be called with the write semaphore held
 110 */
 111static inline void isowbuf_putflag(struct isowbuf_t *iwb)
 112{
 113        int write;
 114
 115        /* add two flags, thus reliably covering one byte */
 116        isowbuf_putbits(iwb, 0x7e7e, 8);
 117        /* recover the idle flag byte */
 118        write = iwb->write;
 119        iwb->idle = iwb->data[write];
 120        gig_dbg(DEBUG_ISO, "idle fill byte %02x", iwb->idle);
 121        /* mask extraneous bits in buffer */
 122        iwb->data[write] &= (1 << iwb->wbits) - 1;
 123}
 124
 125/* retrieve a block of bytes for sending
 126 * The requested number of bytes is provided as a contiguous block.
 127 * If necessary, the frame is filled to the requested number of bytes
 128 * with the idle value.
 129 * returns offset to frame, < 0 on busy or error
 130 */
 131int gigaset_isowbuf_getbytes(struct isowbuf_t *iwb, int size)
 132{
 133        int read, write, limit, src, dst;
 134        unsigned char pbyte;
 135
 136        read = iwb->nextread;
 137        write = iwb->write;
 138        if (likely(read == write)) {
 139                /* return idle frame */
 140                return read < BAS_OUTBUFPAD ?
 141                        BAS_OUTBUFSIZE : read - BAS_OUTBUFPAD;
 142        }
 143
 144        limit = read + size;
 145        gig_dbg(DEBUG_STREAM, "%s: read=%d write=%d limit=%d",
 146                __func__, read, write, limit);
 147#ifdef CONFIG_GIGASET_DEBUG
 148        if (unlikely(size < 0 || size > BAS_OUTBUFPAD)) {
 149                pr_err("invalid size %d\n", size);
 150                return -EINVAL;
 151        }
 152#endif
 153
 154        if (read < write) {
 155                /* no wraparound in valid data */
 156                if (limit >= write) {
 157                        /* append idle frame */
 158                        if (isowbuf_startwrite(iwb) < 0)
 159                                return -EBUSY;
 160                        /* write position could have changed */
 161                        write = iwb->write;
 162                        if (limit >= write) {
 163                                pbyte = iwb->data[write]; /* save
 164                                                             partial byte */
 165                                limit = write + BAS_OUTBUFPAD;
 166                                gig_dbg(DEBUG_STREAM,
 167                                        "%s: filling %d->%d with %02x",
 168                                        __func__, write, limit, iwb->idle);
 169                                if (write + BAS_OUTBUFPAD < BAS_OUTBUFSIZE)
 170                                        memset(iwb->data + write, iwb->idle,
 171                                               BAS_OUTBUFPAD);
 172                                else {
 173                                        /* wraparound, fill entire pad area */
 174                                        memset(iwb->data + write, iwb->idle,
 175                                               BAS_OUTBUFSIZE + BAS_OUTBUFPAD
 176                                               - write);
 177                                        limit = 0;
 178                                }
 179                                gig_dbg(DEBUG_STREAM,
 180                                        "%s: restoring %02x at %d",
 181                                        __func__, pbyte, limit);
 182                                iwb->data[limit] = pbyte; /* restore
 183                                                             partial byte */
 184                                iwb->write = limit;
 185                        }
 186                        isowbuf_donewrite(iwb);
 187                }
 188        } else {
 189                /* valid data wraparound */
 190                if (limit >= BAS_OUTBUFSIZE) {
 191                        /* copy wrapped part into pad area */
 192                        src = 0;
 193                        dst = BAS_OUTBUFSIZE;
 194                        while (dst < limit && src < write)
 195                                iwb->data[dst++] = iwb->data[src++];
 196                        if (dst <= limit) {
 197                                /* fill pad area with idle byte */
 198                                memset(iwb->data + dst, iwb->idle,
 199                                       BAS_OUTBUFSIZE + BAS_OUTBUFPAD - dst);
 200                        }
 201                        limit = src;
 202                }
 203        }
 204        iwb->nextread = limit;
 205        return read;
 206}
 207
 208/* dump_bytes
 209 * write hex bytes to syslog for debugging
 210 */
 211static inline void dump_bytes(enum debuglevel level, const char *tag,
 212                              unsigned char *bytes, int count)
 213{
 214#ifdef CONFIG_GIGASET_DEBUG
 215        unsigned char c;
 216        static char dbgline[3 * 32 + 1];
 217        int i = 0;
 218
 219        if (!(gigaset_debuglevel & level))
 220                return;
 221
 222        while (count-- > 0) {
 223                if (i > sizeof(dbgline) - 4) {
 224                        dbgline[i] = '\0';
 225                        gig_dbg(level, "%s:%s", tag, dbgline);
 226                        i = 0;
 227                }
 228                c = *bytes++;
 229                dbgline[i] = (i && !(i % 12)) ? '-' : ' ';
 230                i++;
 231                dbgline[i++] = hex_asc_hi(c);
 232                dbgline[i++] = hex_asc_lo(c);
 233        }
 234        dbgline[i] = '\0';
 235        gig_dbg(level, "%s:%s", tag, dbgline);
 236#endif
 237}
 238
 239/*============================================================================*/
 240
 241/* bytewise HDLC bitstuffing via table lookup
 242 * lookup table: 5 subtables for 0..4 preceding consecutive '1' bits
 243 * index: 256*(number of preceding '1' bits) + (next byte to stuff)
 244 * value: bit  9.. 0 = result bits
 245 *        bit 12..10 = number of trailing '1' bits in result
 246 *        bit 14..13 = number of bits added by stuffing
 247 */
 248static const u16 stufftab[5 * 256] = {
 249/* previous 1s = 0: */
 250        0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f,
 251        0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x201f,
 252        0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f,
 253        0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x203e, 0x205f,
 254        0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
 255        0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x209f,
 256        0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f,
 257        0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, 0x0078, 0x0079, 0x007a, 0x007b, 0x207c, 0x207d, 0x20be, 0x20df,
 258        0x0480, 0x0481, 0x0482, 0x0483, 0x0484, 0x0485, 0x0486, 0x0487, 0x0488, 0x0489, 0x048a, 0x048b, 0x048c, 0x048d, 0x048e, 0x048f,
 259        0x0490, 0x0491, 0x0492, 0x0493, 0x0494, 0x0495, 0x0496, 0x0497, 0x0498, 0x0499, 0x049a, 0x049b, 0x049c, 0x049d, 0x049e, 0x251f,
 260        0x04a0, 0x04a1, 0x04a2, 0x04a3, 0x04a4, 0x04a5, 0x04a6, 0x04a7, 0x04a8, 0x04a9, 0x04aa, 0x04ab, 0x04ac, 0x04ad, 0x04ae, 0x04af,
 261        0x04b0, 0x04b1, 0x04b2, 0x04b3, 0x04b4, 0x04b5, 0x04b6, 0x04b7, 0x04b8, 0x04b9, 0x04ba, 0x04bb, 0x04bc, 0x04bd, 0x253e, 0x255f,
 262        0x08c0, 0x08c1, 0x08c2, 0x08c3, 0x08c4, 0x08c5, 0x08c6, 0x08c7, 0x08c8, 0x08c9, 0x08ca, 0x08cb, 0x08cc, 0x08cd, 0x08ce, 0x08cf,
 263        0x08d0, 0x08d1, 0x08d2, 0x08d3, 0x08d4, 0x08d5, 0x08d6, 0x08d7, 0x08d8, 0x08d9, 0x08da, 0x08db, 0x08dc, 0x08dd, 0x08de, 0x299f,
 264        0x0ce0, 0x0ce1, 0x0ce2, 0x0ce3, 0x0ce4, 0x0ce5, 0x0ce6, 0x0ce7, 0x0ce8, 0x0ce9, 0x0cea, 0x0ceb, 0x0cec, 0x0ced, 0x0cee, 0x0cef,
 265        0x10f0, 0x10f1, 0x10f2, 0x10f3, 0x10f4, 0x10f5, 0x10f6, 0x10f7, 0x20f8, 0x20f9, 0x20fa, 0x20fb, 0x257c, 0x257d, 0x29be, 0x2ddf,
 266
 267/* previous 1s = 1: */
 268        0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x200f,
 269        0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x202f,
 270        0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x204f,
 271        0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x203e, 0x206f,
 272        0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x208f,
 273        0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x20af,
 274        0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x20cf,
 275        0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, 0x0078, 0x0079, 0x007a, 0x007b, 0x207c, 0x207d, 0x20be, 0x20ef,
 276        0x0480, 0x0481, 0x0482, 0x0483, 0x0484, 0x0485, 0x0486, 0x0487, 0x0488, 0x0489, 0x048a, 0x048b, 0x048c, 0x048d, 0x048e, 0x250f,
 277        0x0490, 0x0491, 0x0492, 0x0493, 0x0494, 0x0495, 0x0496, 0x0497, 0x0498, 0x0499, 0x049a, 0x049b, 0x049c, 0x049d, 0x049e, 0x252f,
 278        0x04a0, 0x04a1, 0x04a2, 0x04a3, 0x04a4, 0x04a5, 0x04a6, 0x04a7, 0x04a8, 0x04a9, 0x04aa, 0x04ab, 0x04ac, 0x04ad, 0x04ae, 0x254f,
 279        0x04b0, 0x04b1, 0x04b2, 0x04b3, 0x04b4, 0x04b5, 0x04b6, 0x04b7, 0x04b8, 0x04b9, 0x04ba, 0x04bb, 0x04bc, 0x04bd, 0x253e, 0x256f,
 280        0x08c0, 0x08c1, 0x08c2, 0x08c3, 0x08c4, 0x08c5, 0x08c6, 0x08c7, 0x08c8, 0x08c9, 0x08ca, 0x08cb, 0x08cc, 0x08cd, 0x08ce, 0x298f,
 281        0x08d0, 0x08d1, 0x08d2, 0x08d3, 0x08d4, 0x08d5, 0x08d6, 0x08d7, 0x08d8, 0x08d9, 0x08da, 0x08db, 0x08dc, 0x08dd, 0x08de, 0x29af,
 282        0x0ce0, 0x0ce1, 0x0ce2, 0x0ce3, 0x0ce4, 0x0ce5, 0x0ce6, 0x0ce7, 0x0ce8, 0x0ce9, 0x0cea, 0x0ceb, 0x0cec, 0x0ced, 0x0cee, 0x2dcf,
 283        0x10f0, 0x10f1, 0x10f2, 0x10f3, 0x10f4, 0x10f5, 0x10f6, 0x10f7, 0x20f8, 0x20f9, 0x20fa, 0x20fb, 0x257c, 0x257d, 0x29be, 0x31ef,
 284
 285/* previous 1s = 2: */
 286        0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x2007, 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x2017,
 287        0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x2027, 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x2037,
 288        0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x2047, 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x2057,
 289        0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x2067, 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x203e, 0x2077,
 290        0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x2087, 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x2097,
 291        0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x20a7, 0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x20b7,
 292        0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x20c7, 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x20d7,
 293        0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x20e7, 0x0078, 0x0079, 0x007a, 0x007b, 0x207c, 0x207d, 0x20be, 0x20f7,
 294        0x0480, 0x0481, 0x0482, 0x0483, 0x0484, 0x0485, 0x0486, 0x2507, 0x0488, 0x0489, 0x048a, 0x048b, 0x048c, 0x048d, 0x048e, 0x2517,
 295        0x0490, 0x0491, 0x0492, 0x0493, 0x0494, 0x0495, 0x0496, 0x2527, 0x0498, 0x0499, 0x049a, 0x049b, 0x049c, 0x049d, 0x049e, 0x2537,
 296        0x04a0, 0x04a1, 0x04a2, 0x04a3, 0x04a4, 0x04a5, 0x04a6, 0x2547, 0x04a8, 0x04a9, 0x04aa, 0x04ab, 0x04ac, 0x04ad, 0x04ae, 0x2557,
 297        0x04b0, 0x04b1, 0x04b2, 0x04b3, 0x04b4, 0x04b5, 0x04b6, 0x2567, 0x04b8, 0x04b9, 0x04ba, 0x04bb, 0x04bc, 0x04bd, 0x253e, 0x2577,
 298        0x08c0, 0x08c1, 0x08c2, 0x08c3, 0x08c4, 0x08c5, 0x08c6, 0x2987, 0x08c8, 0x08c9, 0x08ca, 0x08cb, 0x08cc, 0x08cd, 0x08ce, 0x2997,
 299        0x08d0, 0x08d1, 0x08d2, 0x08d3, 0x08d4, 0x08d5, 0x08d6, 0x29a7, 0x08d8, 0x08d9, 0x08da, 0x08db, 0x08dc, 0x08dd, 0x08de, 0x29b7,
 300        0x0ce0, 0x0ce1, 0x0ce2, 0x0ce3, 0x0ce4, 0x0ce5, 0x0ce6, 0x2dc7, 0x0ce8, 0x0ce9, 0x0cea, 0x0ceb, 0x0cec, 0x0ced, 0x0cee, 0x2dd7,
 301        0x10f0, 0x10f1, 0x10f2, 0x10f3, 0x10f4, 0x10f5, 0x10f6, 0x31e7, 0x20f8, 0x20f9, 0x20fa, 0x20fb, 0x257c, 0x257d, 0x29be, 0x41f7,
 302
 303/* previous 1s = 3: */
 304        0x0000, 0x0001, 0x0002, 0x2003, 0x0004, 0x0005, 0x0006, 0x200b, 0x0008, 0x0009, 0x000a, 0x2013, 0x000c, 0x000d, 0x000e, 0x201b,
 305        0x0010, 0x0011, 0x0012, 0x2023, 0x0014, 0x0015, 0x0016, 0x202b, 0x0018, 0x0019, 0x001a, 0x2033, 0x001c, 0x001d, 0x001e, 0x203b,
 306        0x0020, 0x0021, 0x0022, 0x2043, 0x0024, 0x0025, 0x0026, 0x204b, 0x0028, 0x0029, 0x002a, 0x2053, 0x002c, 0x002d, 0x002e, 0x205b,
 307        0x0030, 0x0031, 0x0032, 0x2063, 0x0034, 0x0035, 0x0036, 0x206b, 0x0038, 0x0039, 0x003a, 0x2073, 0x003c, 0x003d, 0x203e, 0x207b,
 308        0x0040, 0x0041, 0x0042, 0x2083, 0x0044, 0x0045, 0x0046, 0x208b, 0x0048, 0x0049, 0x004a, 0x2093, 0x004c, 0x004d, 0x004e, 0x209b,
 309        0x0050, 0x0051, 0x0052, 0x20a3, 0x0054, 0x0055, 0x0056, 0x20ab, 0x0058, 0x0059, 0x005a, 0x20b3, 0x005c, 0x005d, 0x005e, 0x20bb,
 310        0x0060, 0x0061, 0x0062, 0x20c3, 0x0064, 0x0065, 0x0066, 0x20cb, 0x0068, 0x0069, 0x006a, 0x20d3, 0x006c, 0x006d, 0x006e, 0x20db,
 311        0x0070, 0x0071, 0x0072, 0x20e3, 0x0074, 0x0075, 0x0076, 0x20eb, 0x0078, 0x0079, 0x007a, 0x20f3, 0x207c, 0x207d, 0x20be, 0x40fb,
 312        0x0480, 0x0481, 0x0482, 0x2503, 0x0484, 0x0485, 0x0486, 0x250b, 0x0488, 0x0489, 0x048a, 0x2513, 0x048c, 0x048d, 0x048e, 0x251b,
 313        0x0490, 0x0491, 0x0492, 0x2523, 0x0494, 0x0495, 0x0496, 0x252b, 0x0498, 0x0499, 0x049a, 0x2533, 0x049c, 0x049d, 0x049e, 0x253b,
 314        0x04a0, 0x04a1, 0x04a2, 0x2543, 0x04a4, 0x04a5, 0x04a6, 0x254b, 0x04a8, 0x04a9, 0x04aa, 0x2553, 0x04ac, 0x04ad, 0x04ae, 0x255b,
 315        0x04b0, 0x04b1, 0x04b2, 0x2563, 0x04b4, 0x04b5, 0x04b6, 0x256b, 0x04b8, 0x04b9, 0x04ba, 0x2573, 0x04bc, 0x04bd, 0x253e, 0x257b,
 316        0x08c0, 0x08c1, 0x08c2, 0x2983, 0x08c4, 0x08c5, 0x08c6, 0x298b, 0x08c8, 0x08c9, 0x08ca, 0x2993, 0x08cc, 0x08cd, 0x08ce, 0x299b,
 317        0x08d0, 0x08d1, 0x08d2, 0x29a3, 0x08d4, 0x08d5, 0x08d6, 0x29ab, 0x08d8, 0x08d9, 0x08da, 0x29b3, 0x08dc, 0x08dd, 0x08de, 0x29bb,
 318        0x0ce0, 0x0ce1, 0x0ce2, 0x2dc3, 0x0ce4, 0x0ce5, 0x0ce6, 0x2dcb, 0x0ce8, 0x0ce9, 0x0cea, 0x2dd3, 0x0cec, 0x0ced, 0x0cee, 0x2ddb,
 319        0x10f0, 0x10f1, 0x10f2, 0x31e3, 0x10f4, 0x10f5, 0x10f6, 0x31eb, 0x20f8, 0x20f9, 0x20fa, 0x41f3, 0x257c, 0x257d, 0x29be, 0x46fb,
 320
 321/* previous 1s = 4: */
 322        0x0000, 0x2001, 0x0002, 0x2005, 0x0004, 0x2009, 0x0006, 0x200d, 0x0008, 0x2011, 0x000a, 0x2015, 0x000c, 0x2019, 0x000e, 0x201d,
 323        0x0010, 0x2021, 0x0012, 0x2025, 0x0014, 0x2029, 0x0016, 0x202d, 0x0018, 0x2031, 0x001a, 0x2035, 0x001c, 0x2039, 0x001e, 0x203d,
 324        0x0020, 0x2041, 0x0022, 0x2045, 0x0024, 0x2049, 0x0026, 0x204d, 0x0028, 0x2051, 0x002a, 0x2055, 0x002c, 0x2059, 0x002e, 0x205d,
 325        0x0030, 0x2061, 0x0032, 0x2065, 0x0034, 0x2069, 0x0036, 0x206d, 0x0038, 0x2071, 0x003a, 0x2075, 0x003c, 0x2079, 0x203e, 0x407d,
 326        0x0040, 0x2081, 0x0042, 0x2085, 0x0044, 0x2089, 0x0046, 0x208d, 0x0048, 0x2091, 0x004a, 0x2095, 0x004c, 0x2099, 0x004e, 0x209d,
 327        0x0050, 0x20a1, 0x0052, 0x20a5, 0x0054, 0x20a9, 0x0056, 0x20ad, 0x0058, 0x20b1, 0x005a, 0x20b5, 0x005c, 0x20b9, 0x005e, 0x20bd,
 328        0x0060, 0x20c1, 0x0062, 0x20c5, 0x0064, 0x20c9, 0x0066, 0x20cd, 0x0068, 0x20d1, 0x006a, 0x20d5, 0x006c, 0x20d9, 0x006e, 0x20dd,
 329        0x0070, 0x20e1, 0x0072, 0x20e5, 0x0074, 0x20e9, 0x0076, 0x20ed, 0x0078, 0x20f1, 0x007a, 0x20f5, 0x207c, 0x40f9, 0x20be, 0x417d,
 330        0x0480, 0x2501, 0x0482, 0x2505, 0x0484, 0x2509, 0x0486, 0x250d, 0x0488, 0x2511, 0x048a, 0x2515, 0x048c, 0x2519, 0x048e, 0x251d,
 331        0x0490, 0x2521, 0x0492, 0x2525, 0x0494, 0x2529, 0x0496, 0x252d, 0x0498, 0x2531, 0x049a, 0x2535, 0x049c, 0x2539, 0x049e, 0x253d,
 332        0x04a0, 0x2541, 0x04a2, 0x2545, 0x04a4, 0x2549, 0x04a6, 0x254d, 0x04a8, 0x2551, 0x04aa, 0x2555, 0x04ac, 0x2559, 0x04ae, 0x255d,
 333        0x04b0, 0x2561, 0x04b2, 0x2565, 0x04b4, 0x2569, 0x04b6, 0x256d, 0x04b8, 0x2571, 0x04ba, 0x2575, 0x04bc, 0x2579, 0x253e, 0x467d,
 334        0x08c0, 0x2981, 0x08c2, 0x2985, 0x08c4, 0x2989, 0x08c6, 0x298d, 0x08c8, 0x2991, 0x08ca, 0x2995, 0x08cc, 0x2999, 0x08ce, 0x299d,
 335        0x08d0, 0x29a1, 0x08d2, 0x29a5, 0x08d4, 0x29a9, 0x08d6, 0x29ad, 0x08d8, 0x29b1, 0x08da, 0x29b5, 0x08dc, 0x29b9, 0x08de, 0x29bd,
 336        0x0ce0, 0x2dc1, 0x0ce2, 0x2dc5, 0x0ce4, 0x2dc9, 0x0ce6, 0x2dcd, 0x0ce8, 0x2dd1, 0x0cea, 0x2dd5, 0x0cec, 0x2dd9, 0x0cee, 0x2ddd,
 337        0x10f0, 0x31e1, 0x10f2, 0x31e5, 0x10f4, 0x31e9, 0x10f6, 0x31ed, 0x20f8, 0x41f1, 0x20fa, 0x41f5, 0x257c, 0x46f9, 0x29be, 0x4b7d
 338};
 339
 340/* hdlc_bitstuff_byte
 341 * perform HDLC bitstuffing for one input byte (8 bits, LSB first)
 342 * parameters:
 343 *      cin     input byte
 344 *      ones    number of trailing '1' bits in result before this step
 345 *      iwb     pointer to output buffer structure
 346 *              (write semaphore must be held)
 347 * return value:
 348 *      number of trailing '1' bits in result after this step
 349 */
 350
 351static inline int hdlc_bitstuff_byte(struct isowbuf_t *iwb, unsigned char cin,
 352                                     int ones)
 353{
 354        u16 stuff;
 355        int shiftinc, newones;
 356
 357        /* get stuffing information for input byte
 358         * value: bit  9.. 0 = result bits
 359         *        bit 12..10 = number of trailing '1' bits in result
 360         *        bit 14..13 = number of bits added by stuffing
 361         */
 362        stuff = stufftab[256 * ones + cin];
 363        shiftinc = (stuff >> 13) & 3;
 364        newones = (stuff >> 10) & 7;
 365        stuff &= 0x3ff;
 366
 367        /* append stuffed byte to output stream */
 368        isowbuf_putbits(iwb, stuff, 8 + shiftinc);
 369        return newones;
 370}
 371
 372/* hdlc_buildframe
 373 * Perform HDLC framing with bitstuffing on a byte buffer
 374 * The input buffer is regarded as a sequence of bits, starting with the least
 375 * significant bit of the first byte and ending with the most significant bit
 376 * of the last byte. A 16 bit FCS is appended as defined by RFC 1662.
 377 * Whenever five consecutive '1' bits appear in the resulting bit sequence, a
 378 * '0' bit is inserted after them.
 379 * The resulting bit string and a closing flag pattern (PPP_FLAG, '01111110')
 380 * are appended to the output buffer starting at the given bit position, which
 381 * is assumed to already contain a leading flag.
 382 * The output buffer must have sufficient length; count + count/5 + 6 bytes
 383 * starting at *out are safe and are verified to be present.
 384 * parameters:
 385 *      in      input buffer
 386 *      count   number of bytes in input buffer
 387 *      iwb     pointer to output buffer structure
 388 *              (write semaphore must be held)
 389 * return value:
 390 *      position of end of packet in output buffer on success,
 391 *      -EAGAIN if write semaphore busy or buffer full
 392 */
 393
 394static inline int hdlc_buildframe(struct isowbuf_t *iwb,
 395                                  unsigned char *in, int count)
 396{
 397        int ones;
 398        u16 fcs;
 399        int end;
 400        unsigned char c;
 401
 402        if (isowbuf_freebytes(iwb) < count + count / 5 + 6 ||
 403            isowbuf_startwrite(iwb) < 0) {
 404                gig_dbg(DEBUG_ISO, "%s: %d bytes free -> -EAGAIN",
 405                        __func__, isowbuf_freebytes(iwb));
 406                return -EAGAIN;
 407        }
 408
 409        dump_bytes(DEBUG_STREAM_DUMP, "snd data", in, count);
 410
 411        /* bitstuff and checksum input data */
 412        fcs = PPP_INITFCS;
 413        ones = 0;
 414        while (count-- > 0) {
 415                c = *in++;
 416                ones = hdlc_bitstuff_byte(iwb, c, ones);
 417                fcs = crc_ccitt_byte(fcs, c);
 418        }
 419
 420        /* bitstuff and append FCS
 421         * (complemented, least significant byte first) */
 422        fcs ^= 0xffff;
 423        ones = hdlc_bitstuff_byte(iwb, fcs & 0x00ff, ones);
 424        ones = hdlc_bitstuff_byte(iwb, (fcs >> 8) & 0x00ff, ones);
 425
 426        /* put closing flag and repeat byte for flag idle */
 427        isowbuf_putflag(iwb);
 428        end = isowbuf_donewrite(iwb);
 429        return end;
 430}
 431
 432/* trans_buildframe
 433 * Append a block of 'transparent' data to the output buffer,
 434 * inverting the bytes.
 435 * The output buffer must have sufficient length; count bytes
 436 * starting at *out are safe and are verified to be present.
 437 * parameters:
 438 *      in      input buffer
 439 *      count   number of bytes in input buffer
 440 *      iwb     pointer to output buffer structure
 441 *              (write semaphore must be held)
 442 * return value:
 443 *      position of end of packet in output buffer on success,
 444 *      -EAGAIN if write semaphore busy or buffer full
 445 */
 446
 447static inline int trans_buildframe(struct isowbuf_t *iwb,
 448                                   unsigned char *in, int count)
 449{
 450        int write;
 451        unsigned char c;
 452
 453        if (unlikely(count <= 0))
 454                return iwb->write;
 455
 456        if (isowbuf_freebytes(iwb) < count ||
 457            isowbuf_startwrite(iwb) < 0) {
 458                gig_dbg(DEBUG_ISO, "can't put %d bytes", count);
 459                return -EAGAIN;
 460        }
 461
 462        gig_dbg(DEBUG_STREAM, "put %d bytes", count);
 463        dump_bytes(DEBUG_STREAM_DUMP, "snd data", in, count);
 464
 465        write = iwb->write;
 466        do {
 467                c = bitrev8(*in++);
 468                iwb->data[write++] = c;
 469                write %= BAS_OUTBUFSIZE;
 470        } while (--count > 0);
 471        iwb->write = write;
 472        iwb->idle = c;
 473
 474        return isowbuf_donewrite(iwb);
 475}
 476
 477int gigaset_isoc_buildframe(struct bc_state *bcs, unsigned char *in, int len)
 478{
 479        int result;
 480
 481        switch (bcs->proto2) {
 482        case L2_HDLC:
 483                result = hdlc_buildframe(bcs->hw.bas->isooutbuf, in, len);
 484                gig_dbg(DEBUG_ISO, "%s: %d bytes HDLC -> %d",
 485                        __func__, len, result);
 486                break;
 487        default:                        /* assume transparent */
 488                result = trans_buildframe(bcs->hw.bas->isooutbuf, in, len);
 489                gig_dbg(DEBUG_ISO, "%s: %d bytes trans -> %d",
 490                        __func__, len, result);
 491        }
 492        return result;
 493}
 494
 495/* hdlc_putbyte
 496 * append byte c to current skb of B channel structure *bcs, updating fcs
 497 */
 498static inline void hdlc_putbyte(unsigned char c, struct bc_state *bcs)
 499{
 500        bcs->rx_fcs = crc_ccitt_byte(bcs->rx_fcs, c);
 501        if (bcs->rx_skb == NULL)
 502                /* skipping */
 503                return;
 504        if (bcs->rx_skb->len >= bcs->rx_bufsize) {
 505                dev_warn(bcs->cs->dev, "received oversized packet discarded\n");
 506                bcs->hw.bas->giants++;
 507                dev_kfree_skb_any(bcs->rx_skb);
 508                bcs->rx_skb = NULL;
 509                return;
 510        }
 511        __skb_put_u8(bcs->rx_skb, c);
 512}
 513
 514/* hdlc_flush
 515 * drop partial HDLC data packet
 516 */
 517static inline void hdlc_flush(struct bc_state *bcs)
 518{
 519        /* clear skb or allocate new if not skipping */
 520        if (bcs->rx_skb != NULL)
 521                skb_trim(bcs->rx_skb, 0);
 522        else
 523                gigaset_new_rx_skb(bcs);
 524
 525        /* reset packet state */
 526        bcs->rx_fcs = PPP_INITFCS;
 527}
 528
 529/* hdlc_done
 530 * process completed HDLC data packet
 531 */
 532static inline void hdlc_done(struct bc_state *bcs)
 533{
 534        struct cardstate *cs = bcs->cs;
 535        struct sk_buff *procskb;
 536        unsigned int len;
 537
 538        if (unlikely(bcs->ignore)) {
 539                bcs->ignore--;
 540                hdlc_flush(bcs);
 541                return;
 542        }
 543        procskb = bcs->rx_skb;
 544        if (procskb == NULL) {
 545                /* previous error */
 546                gig_dbg(DEBUG_ISO, "%s: skb=NULL", __func__);
 547                gigaset_isdn_rcv_err(bcs);
 548        } else if (procskb->len < 2) {
 549                dev_notice(cs->dev, "received short frame (%d octets)\n",
 550                           procskb->len);
 551                bcs->hw.bas->runts++;
 552                dev_kfree_skb_any(procskb);
 553                gigaset_isdn_rcv_err(bcs);
 554        } else if (bcs->rx_fcs != PPP_GOODFCS) {
 555                dev_notice(cs->dev, "frame check error\n");
 556                bcs->hw.bas->fcserrs++;
 557                dev_kfree_skb_any(procskb);
 558                gigaset_isdn_rcv_err(bcs);
 559        } else {
 560                len = procskb->len;
 561                __skb_trim(procskb, len -= 2);  /* subtract FCS */
 562                gig_dbg(DEBUG_ISO, "%s: good frame (%d octets)", __func__, len);
 563                dump_bytes(DEBUG_STREAM_DUMP,
 564                           "rcv data", procskb->data, len);
 565                bcs->hw.bas->goodbytes += len;
 566                gigaset_skb_rcvd(bcs, procskb);
 567        }
 568        gigaset_new_rx_skb(bcs);
 569        bcs->rx_fcs = PPP_INITFCS;
 570}
 571
 572/* hdlc_frag
 573 * drop HDLC data packet with non-integral last byte
 574 */
 575static inline void hdlc_frag(struct bc_state *bcs, unsigned inbits)
 576{
 577        if (unlikely(bcs->ignore)) {
 578                bcs->ignore--;
 579                hdlc_flush(bcs);
 580                return;
 581        }
 582
 583        dev_notice(bcs->cs->dev, "received partial byte (%d bits)\n", inbits);
 584        bcs->hw.bas->alignerrs++;
 585        gigaset_isdn_rcv_err(bcs);
 586        __skb_trim(bcs->rx_skb, 0);
 587        bcs->rx_fcs = PPP_INITFCS;
 588}
 589
 590/* bit counts lookup table for HDLC bit unstuffing
 591 * index: input byte
 592 * value: bit 0..3 = number of consecutive '1' bits starting from LSB
 593 *        bit 4..6 = number of consecutive '1' bits starting from MSB
 594 *                   (replacing 8 by 7 to make it fit; the algorithm won't care)
 595 *        bit 7 set if there are 5 or more "interior" consecutive '1' bits
 596 */
 597static const unsigned char bitcounts[256] = {
 598        0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x03, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x04,
 599        0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x03, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x05,
 600        0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x03, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x04,
 601        0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x03, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x80, 0x06,
 602        0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x03, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x04,
 603        0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x03, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x05,
 604        0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x03, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x04,
 605        0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x03, 0x00, 0x01, 0x00, 0x02, 0x80, 0x81, 0x80, 0x07,
 606        0x10, 0x11, 0x10, 0x12, 0x10, 0x11, 0x10, 0x13, 0x10, 0x11, 0x10, 0x12, 0x10, 0x11, 0x10, 0x14,
 607        0x10, 0x11, 0x10, 0x12, 0x10, 0x11, 0x10, 0x13, 0x10, 0x11, 0x10, 0x12, 0x10, 0x11, 0x10, 0x15,
 608        0x10, 0x11, 0x10, 0x12, 0x10, 0x11, 0x10, 0x13, 0x10, 0x11, 0x10, 0x12, 0x10, 0x11, 0x10, 0x14,
 609        0x10, 0x11, 0x10, 0x12, 0x10, 0x11, 0x10, 0x13, 0x10, 0x11, 0x10, 0x12, 0x10, 0x11, 0x90, 0x16,
 610        0x20, 0x21, 0x20, 0x22, 0x20, 0x21, 0x20, 0x23, 0x20, 0x21, 0x20, 0x22, 0x20, 0x21, 0x20, 0x24,
 611        0x20, 0x21, 0x20, 0x22, 0x20, 0x21, 0x20, 0x23, 0x20, 0x21, 0x20, 0x22, 0x20, 0x21, 0x20, 0x25,
 612        0x30, 0x31, 0x30, 0x32, 0x30, 0x31, 0x30, 0x33, 0x30, 0x31, 0x30, 0x32, 0x30, 0x31, 0x30, 0x34,
 613        0x40, 0x41, 0x40, 0x42, 0x40, 0x41, 0x40, 0x43, 0x50, 0x51, 0x50, 0x52, 0x60, 0x61, 0x70, 0x78
 614};
 615
 616/* hdlc_unpack
 617 * perform HDLC frame processing (bit unstuffing, flag detection, FCS
 618 * calculation) on a sequence of received data bytes (8 bits each, LSB first)
 619 * pass on successfully received, complete frames as SKBs via gigaset_skb_rcvd
 620 * notify of errors via gigaset_isdn_rcv_err
 621 * tally frames, errors etc. in BC structure counters
 622 * parameters:
 623 *      src     received data
 624 *      count   number of received bytes
 625 *      bcs     receiving B channel structure
 626 */
 627static inline void hdlc_unpack(unsigned char *src, unsigned count,
 628                               struct bc_state *bcs)
 629{
 630        struct bas_bc_state *ubc = bcs->hw.bas;
 631        int inputstate;
 632        unsigned seqlen, inbyte, inbits;
 633
 634        /* load previous state:
 635         * inputstate = set of flag bits:
 636         * - INS_flag_hunt: no complete opening flag received since connection
 637         *                  setup or last abort
 638         * - INS_have_data: at least one complete data byte received since last
 639         *                  flag
 640         * seqlen = number of consecutive '1' bits in last 7 input stream bits
 641         *          (0..7)
 642         * inbyte = accumulated partial data byte (if !INS_flag_hunt)
 643         * inbits = number of valid bits in inbyte, starting at LSB (0..6)
 644         */
 645        inputstate = bcs->inputstate;
 646        seqlen = ubc->seqlen;
 647        inbyte = ubc->inbyte;
 648        inbits = ubc->inbits;
 649
 650        /* bit unstuffing a byte a time
 651         * Take your time to understand this; it's straightforward but tedious.
 652         * The "bitcounts" lookup table is used to speed up the counting of
 653         * leading and trailing '1' bits.
 654         */
 655        while (count--) {
 656                unsigned char c = *src++;
 657                unsigned char tabentry = bitcounts[c];
 658                unsigned lead1 = tabentry & 0x0f;
 659                unsigned trail1 = (tabentry >> 4) & 0x0f;
 660
 661                seqlen += lead1;
 662
 663                if (unlikely(inputstate & INS_flag_hunt)) {
 664                        if (c == PPP_FLAG) {
 665                                /* flag-in-one */
 666                                inputstate &= ~(INS_flag_hunt | INS_have_data);
 667                                inbyte = 0;
 668                                inbits = 0;
 669                        } else if (seqlen == 6 && trail1 != 7) {
 670                                /* flag completed & not followed by abort */
 671                                inputstate &= ~(INS_flag_hunt | INS_have_data);
 672                                inbyte = c >> (lead1 + 1);
 673                                inbits = 7 - lead1;
 674                                if (trail1 >= 8) {
 675                                        /* interior stuffing:
 676                                         * omitting the MSB handles most cases,
 677                                         * correct the incorrectly handled
 678                                         * cases individually */
 679                                        inbits--;
 680                                        switch (c) {
 681                                        case 0xbe:
 682                                                inbyte = 0x3f;
 683                                                break;
 684                                        }
 685                                }
 686                        }
 687                        /* else: continue flag-hunting */
 688                } else if (likely(seqlen < 5 && trail1 < 7)) {
 689                        /* streamlined case: 8 data bits, no stuffing */
 690                        inbyte |= c << inbits;
 691                        hdlc_putbyte(inbyte & 0xff, bcs);
 692                        inputstate |= INS_have_data;
 693                        inbyte >>= 8;
 694                        /* inbits unchanged */
 695                } else if (likely(seqlen == 6 && inbits == 7 - lead1 &&
 696                                  trail1 + 1 == inbits &&
 697                                  !(inputstate & INS_have_data))) {
 698                        /* streamlined case: flag idle - state unchanged */
 699                } else if (unlikely(seqlen > 6)) {
 700                        /* abort sequence */
 701                        ubc->aborts++;
 702                        hdlc_flush(bcs);
 703                        inputstate |= INS_flag_hunt;
 704                } else if (seqlen == 6) {
 705                        /* closing flag, including (6 - lead1) '1's
 706                         * and one '0' from inbits */
 707                        if (inbits > 7 - lead1) {
 708                                hdlc_frag(bcs, inbits + lead1 - 7);
 709                                inputstate &= ~INS_have_data;
 710                        } else {
 711                                if (inbits < 7 - lead1)
 712                                        ubc->stolen0s++;
 713                                if (inputstate & INS_have_data) {
 714                                        hdlc_done(bcs);
 715                                        inputstate &= ~INS_have_data;
 716                                }
 717                        }
 718
 719                        if (c == PPP_FLAG) {
 720                                /* complete flag, LSB overlaps preceding flag */
 721                                ubc->shared0s++;
 722                                inbits = 0;
 723                                inbyte = 0;
 724                        } else if (trail1 != 7) {
 725                                /* remaining bits */
 726                                inbyte = c >> (lead1 + 1);
 727                                inbits = 7 - lead1;
 728                                if (trail1 >= 8) {
 729                                        /* interior stuffing:
 730                                         * omitting the MSB handles most cases,
 731                                         * correct the incorrectly handled
 732                                         * cases individually */
 733                                        inbits--;
 734                                        switch (c) {
 735                                        case 0xbe:
 736                                                inbyte = 0x3f;
 737                                                break;
 738                                        }
 739                                }
 740                        } else {
 741                                /* abort sequence follows,
 742                                 * skb already empty anyway */
 743                                ubc->aborts++;
 744                                inputstate |= INS_flag_hunt;
 745                        }
 746                } else { /* (seqlen < 6) && (seqlen == 5 || trail1 >= 7) */
 747
 748                        if (c == PPP_FLAG) {
 749                                /* complete flag */
 750                                if (seqlen == 5)
 751                                        ubc->stolen0s++;
 752                                if (inbits) {
 753                                        hdlc_frag(bcs, inbits);
 754                                        inbits = 0;
 755                                        inbyte = 0;
 756                                } else if (inputstate & INS_have_data)
 757                                        hdlc_done(bcs);
 758                                inputstate &= ~INS_have_data;
 759                        } else if (trail1 == 7) {
 760                                /* abort sequence */
 761                                ubc->aborts++;
 762                                hdlc_flush(bcs);
 763                                inputstate |= INS_flag_hunt;
 764                        } else {
 765                                /* stuffed data */
 766                                if (trail1 < 7) { /* => seqlen == 5 */
 767                                        /* stuff bit at position lead1,
 768                                         * no interior stuffing */
 769                                        unsigned char mask = (1 << lead1) - 1;
 770                                        c = (c & mask) | ((c & ~mask) >> 1);
 771                                        inbyte |= c << inbits;
 772                                        inbits += 7;
 773                                } else if (seqlen < 5) { /* trail1 >= 8 */
 774                                        /* interior stuffing:
 775                                         * omitting the MSB handles most cases,
 776                                         * correct the incorrectly handled
 777                                         * cases individually */
 778                                        switch (c) {
 779                                        case 0xbe:
 780                                                c = 0x7e;
 781                                                break;
 782                                        }
 783                                        inbyte |= c << inbits;
 784                                        inbits += 7;
 785                                } else { /* seqlen == 5 && trail1 >= 8 */
 786
 787                                        /* stuff bit at lead1 *and* interior
 788                                         * stuffing -- unstuff individually */
 789                                        switch (c) {
 790                                        case 0x7d:
 791                                                c = 0x3f;
 792                                                break;
 793                                        case 0xbe:
 794                                                c = 0x3f;
 795                                                break;
 796                                        case 0x3e:
 797                                                c = 0x1f;
 798                                                break;
 799                                        case 0x7c:
 800                                                c = 0x3e;
 801                                                break;
 802                                        }
 803                                        inbyte |= c << inbits;
 804                                        inbits += 6;
 805                                }
 806                                if (inbits >= 8) {
 807                                        inbits -= 8;
 808                                        hdlc_putbyte(inbyte & 0xff, bcs);
 809                                        inputstate |= INS_have_data;
 810                                        inbyte >>= 8;
 811                                }
 812                        }
 813                }
 814                seqlen = trail1 & 7;
 815        }
 816
 817        /* save new state */
 818        bcs->inputstate = inputstate;
 819        ubc->seqlen = seqlen;
 820        ubc->inbyte = inbyte;
 821        ubc->inbits = inbits;
 822}
 823
 824/* trans_receive
 825 * pass on received USB frame transparently as SKB via gigaset_skb_rcvd
 826 * invert bytes
 827 * tally frames, errors etc. in BC structure counters
 828 * parameters:
 829 *      src     received data
 830 *      count   number of received bytes
 831 *      bcs     receiving B channel structure
 832 */
 833static inline void trans_receive(unsigned char *src, unsigned count,
 834                                 struct bc_state *bcs)
 835{
 836        struct sk_buff *skb;
 837        int dobytes;
 838        unsigned char *dst;
 839
 840        if (unlikely(bcs->ignore)) {
 841                bcs->ignore--;
 842                return;
 843        }
 844        skb = bcs->rx_skb;
 845        if (skb == NULL) {
 846                skb = gigaset_new_rx_skb(bcs);
 847                if (skb == NULL)
 848                        return;
 849        }
 850        dobytes = bcs->rx_bufsize - skb->len;
 851        while (count > 0) {
 852                dst = skb_put(skb, count < dobytes ? count : dobytes);
 853                while (count > 0 && dobytes > 0) {
 854                        *dst++ = bitrev8(*src++);
 855                        count--;
 856                        dobytes--;
 857                }
 858                if (dobytes == 0) {
 859                        dump_bytes(DEBUG_STREAM_DUMP,
 860                                   "rcv data", skb->data, skb->len);
 861                        bcs->hw.bas->goodbytes += skb->len;
 862                        gigaset_skb_rcvd(bcs, skb);
 863                        skb = gigaset_new_rx_skb(bcs);
 864                        if (skb == NULL)
 865                                return;
 866                        dobytes = bcs->rx_bufsize;
 867                }
 868        }
 869}
 870
 871void gigaset_isoc_receive(unsigned char *src, unsigned count,
 872                          struct bc_state *bcs)
 873{
 874        switch (bcs->proto2) {
 875        case L2_HDLC:
 876                hdlc_unpack(src, count, bcs);
 877                break;
 878        default:                /* assume transparent */
 879                trans_receive(src, count, bcs);
 880        }
 881}
 882
 883/* == data input =========================================================== */
 884
 885/* process a block of received bytes in command mode (mstate != MS_LOCKED)
 886 * Append received bytes to the command response buffer and forward them
 887 * line by line to the response handler.
 888 * Note: Received lines may be terminated by CR, LF, or CR LF, which will be
 889 * removed before passing the line to the response handler.
 890 */
 891static void cmd_loop(unsigned char *src, int numbytes, struct inbuf_t *inbuf)
 892{
 893        struct cardstate *cs = inbuf->cs;
 894        unsigned cbytes      = cs->cbytes;
 895        unsigned char c;
 896
 897        while (numbytes--) {
 898                c = *src++;
 899                switch (c) {
 900                case '\n':
 901                        if (cbytes == 0 && cs->respdata[0] == '\r') {
 902                                /* collapse LF with preceding CR */
 903                                cs->respdata[0] = 0;
 904                                break;
 905                        }
 906                        /* fall through */
 907                case '\r':
 908                        /* end of message line, pass to response handler */
 909                        if (cbytes >= MAX_RESP_SIZE) {
 910                                dev_warn(cs->dev, "response too large (%d)\n",
 911                                         cbytes);
 912                                cbytes = MAX_RESP_SIZE;
 913                        }
 914                        cs->cbytes = cbytes;
 915                        gigaset_dbg_buffer(DEBUG_TRANSCMD, "received response",
 916                                           cbytes, cs->respdata);
 917                        gigaset_handle_modem_response(cs);
 918                        cbytes = 0;
 919
 920                        /* store EOL byte for CRLF collapsing */
 921                        cs->respdata[0] = c;
 922                        break;
 923                default:
 924                        /* append to line buffer if possible */
 925                        if (cbytes < MAX_RESP_SIZE)
 926                                cs->respdata[cbytes] = c;
 927                        cbytes++;
 928                }
 929        }
 930
 931        /* save state */
 932        cs->cbytes = cbytes;
 933}
 934
 935
 936/* process a block of data received through the control channel
 937 */
 938void gigaset_isoc_input(struct inbuf_t *inbuf)
 939{
 940        struct cardstate *cs = inbuf->cs;
 941        unsigned tail, head, numbytes;
 942        unsigned char *src;
 943
 944        head = inbuf->head;
 945        while (head != (tail = inbuf->tail)) {
 946                gig_dbg(DEBUG_INTR, "buffer state: %u -> %u", head, tail);
 947                if (head > tail)
 948                        tail = RBUFSIZE;
 949                src = inbuf->data + head;
 950                numbytes = tail - head;
 951                gig_dbg(DEBUG_INTR, "processing %u bytes", numbytes);
 952
 953                if (cs->mstate == MS_LOCKED) {
 954                        gigaset_dbg_buffer(DEBUG_LOCKCMD, "received response",
 955                                           numbytes, src);
 956                        gigaset_if_receive(inbuf->cs, src, numbytes);
 957                } else {
 958                        cmd_loop(src, numbytes, inbuf);
 959                }
 960
 961                head += numbytes;
 962                if (head == RBUFSIZE)
 963                        head = 0;
 964                gig_dbg(DEBUG_INTR, "setting head to %u", head);
 965                inbuf->head = head;
 966        }
 967}
 968
 969
 970/* == data output ========================================================== */
 971
 972/**
 973 * gigaset_isoc_send_skb() - queue an skb for sending
 974 * @bcs:        B channel descriptor structure.
 975 * @skb:        data to send.
 976 *
 977 * Called by LL to queue an skb for sending, and start transmission if
 978 * necessary.
 979 * Once the payload data has been transmitted completely, gigaset_skb_sent()
 980 * will be called with the skb's link layer header preserved.
 981 *
 982 * Return value:
 983 *      number of bytes accepted for sending (skb->len) if ok,
 984 *      error code < 0 (eg. -ENODEV) on error
 985 */
 986int gigaset_isoc_send_skb(struct bc_state *bcs, struct sk_buff *skb)
 987{
 988        int len = skb->len;
 989        unsigned long flags;
 990
 991        spin_lock_irqsave(&bcs->cs->lock, flags);
 992        if (!bcs->cs->connected) {
 993                spin_unlock_irqrestore(&bcs->cs->lock, flags);
 994                return -ENODEV;
 995        }
 996
 997        skb_queue_tail(&bcs->squeue, skb);
 998        gig_dbg(DEBUG_ISO, "%s: skb queued, qlen=%d",
 999                __func__, skb_queue_len(&bcs->squeue));
1000
1001        /* tasklet submits URB if necessary */
1002        tasklet_schedule(&bcs->hw.bas->sent_tasklet);
1003        spin_unlock_irqrestore(&bcs->cs->lock, flags);
1004
1005        return len;     /* ok so far */
1006}
1007