]>
git.proxmox.com Git - mirror_ubuntu-focal-kernel.git/blob - drivers/isdn/gigaset/isocdata.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Common data handling layer for bas_gigaset
5 * Copyright (c) 2005 by Tilman Schmidt <tilman@imap.cc>,
6 * Hansjoerg Lipp <hjlipp@web.de>.
8 * =====================================================================
9 * =====================================================================
13 #include <linux/crc-ccitt.h>
14 #include <linux/bitrev.h>
16 /* access methods for isowbuf_t */
17 /* ============================ */
19 /* initialize buffer structure
21 void gigaset_isowbuf_init(struct isowbuf_t
*iwb
, unsigned char idle
)
26 atomic_set(&iwb
->writesem
, 1);
29 memset(iwb
->data
+ BAS_OUTBUFSIZE
, idle
, BAS_OUTBUFPAD
);
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
35 static inline int isowbuf_freebytes(struct isowbuf_t
*iwb
)
37 int read
, write
, freebytes
;
41 freebytes
= read
- write
;
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
;
49 /* following the wraparound yields more space */
50 return freebytes
+ BAS_OUTBUFSIZE
- BAS_OUTBUFPAD
;
55 * acquire the write semaphore
56 * return 0 if acquired, <0 if busy
58 static inline int isowbuf_startwrite(struct isowbuf_t
*iwb
)
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",
67 "%s: acquired iso write semaphore, data[write]=%02x, nbits=%d",
68 __func__
, iwb
->data
[iwb
->write
], iwb
->wbits
);
73 * release the write semaphore
74 * returns the current write position
76 static inline int isowbuf_donewrite(struct isowbuf_t
*iwb
)
78 int write
= iwb
->write
;
79 atomic_inc(&iwb
->writesem
);
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.
90 static inline void isowbuf_putbits(struct isowbuf_t
*iwb
, u32 data
, int nbits
)
92 int write
= iwb
->write
;
94 data
|= iwb
->data
[write
];
97 iwb
->data
[write
++] = data
& 0xff;
98 write
%= BAS_OUTBUFSIZE
;
103 iwb
->data
[write
] = data
& 0xff;
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
111 static inline void isowbuf_putflag(struct isowbuf_t
*iwb
)
115 /* add two flags, thus reliably covering one byte */
116 isowbuf_putbits(iwb
, 0x7e7e, 8);
117 /* recover the idle flag byte */
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;
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
131 int gigaset_isowbuf_getbytes(struct isowbuf_t
*iwb
, int size
)
133 int read
, write
, limit
, src
, dst
;
136 read
= iwb
->nextread
;
138 if (likely(read
== write
)) {
139 /* return idle frame */
140 return read
< BAS_OUTBUFPAD
?
141 BAS_OUTBUFSIZE
: read
- BAS_OUTBUFPAD
;
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
);
155 /* no wraparound in valid data */
156 if (limit
>= write
) {
157 /* append idle frame */
158 if (isowbuf_startwrite(iwb
) < 0)
160 /* write position could have changed */
162 if (limit
>= write
) {
163 pbyte
= iwb
->data
[write
]; /* save
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
,
173 /* wraparound, fill entire pad area */
174 memset(iwb
->data
+ write
, iwb
->idle
,
175 BAS_OUTBUFSIZE
+ BAS_OUTBUFPAD
179 gig_dbg(DEBUG_STREAM
,
180 "%s: restoring %02x at %d",
181 __func__
, pbyte
, limit
);
182 iwb
->data
[limit
] = pbyte
; /* restore
186 isowbuf_donewrite(iwb
);
189 /* valid data wraparound */
190 if (limit
>= BAS_OUTBUFSIZE
) {
191 /* copy wrapped part into pad area */
193 dst
= BAS_OUTBUFSIZE
;
194 while (dst
< limit
&& src
< write
)
195 iwb
->data
[dst
++] = iwb
->data
[src
++];
197 /* fill pad area with idle byte */
198 memset(iwb
->data
+ dst
, iwb
->idle
,
199 BAS_OUTBUFSIZE
+ BAS_OUTBUFPAD
- dst
);
204 iwb
->nextread
= limit
;
209 * write hex bytes to syslog for debugging
211 static inline void dump_bytes(enum debuglevel level
, const char *tag
,
212 unsigned char *bytes
, int count
)
214 #ifdef CONFIG_GIGASET_DEBUG
216 static char dbgline
[3 * 32 + 1];
219 if (!(gigaset_debuglevel
& level
))
222 while (count
-- > 0) {
223 if (i
> sizeof(dbgline
) - 4) {
225 gig_dbg(level
, "%s:%s", tag
, dbgline
);
229 dbgline
[i
] = (i
&& !(i
% 12)) ? '-' : ' ';
231 dbgline
[i
++] = hex_asc_hi(c
);
232 dbgline
[i
++] = hex_asc_lo(c
);
235 gig_dbg(level
, "%s:%s", tag
, dbgline
);
239 /*============================================================================*/
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
248 static 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,
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,
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,
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,
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
340 /* hdlc_bitstuff_byte
341 * perform HDLC bitstuffing for one input byte (8 bits, LSB first)
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)
348 * number of trailing '1' bits in result after this step
351 static inline int hdlc_bitstuff_byte(struct isowbuf_t
*iwb
, unsigned char cin
,
355 int shiftinc
, newones
;
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
362 stuff
= stufftab
[256 * ones
+ cin
];
363 shiftinc
= (stuff
>> 13) & 3;
364 newones
= (stuff
>> 10) & 7;
367 /* append stuffed byte to output stream */
368 isowbuf_putbits(iwb
, stuff
, 8 + shiftinc
);
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.
386 * count number of bytes in input buffer
387 * iwb pointer to output buffer structure
388 * (write semaphore must be held)
390 * position of end of packet in output buffer on success,
391 * -EAGAIN if write semaphore busy or buffer full
394 static inline int hdlc_buildframe(struct isowbuf_t
*iwb
,
395 unsigned char *in
, int count
)
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
));
409 dump_bytes(DEBUG_STREAM_DUMP
, "snd data", in
, count
);
411 /* bitstuff and checksum input data */
414 while (count
-- > 0) {
416 ones
= hdlc_bitstuff_byte(iwb
, c
, ones
);
417 fcs
= crc_ccitt_byte(fcs
, c
);
420 /* bitstuff and append FCS
421 * (complemented, least significant byte first) */
423 ones
= hdlc_bitstuff_byte(iwb
, fcs
& 0x00ff, ones
);
424 ones
= hdlc_bitstuff_byte(iwb
, (fcs
>> 8) & 0x00ff, ones
);
426 /* put closing flag and repeat byte for flag idle */
427 isowbuf_putflag(iwb
);
428 end
= isowbuf_donewrite(iwb
);
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.
439 * count number of bytes in input buffer
440 * iwb pointer to output buffer structure
441 * (write semaphore must be held)
443 * position of end of packet in output buffer on success,
444 * -EAGAIN if write semaphore busy or buffer full
447 static inline int trans_buildframe(struct isowbuf_t
*iwb
,
448 unsigned char *in
, int count
)
453 if (unlikely(count
<= 0))
456 if (isowbuf_freebytes(iwb
) < count
||
457 isowbuf_startwrite(iwb
) < 0) {
458 gig_dbg(DEBUG_ISO
, "can't put %d bytes", count
);
462 gig_dbg(DEBUG_STREAM
, "put %d bytes", count
);
463 dump_bytes(DEBUG_STREAM_DUMP
, "snd data", in
, count
);
468 iwb
->data
[write
++] = c
;
469 write
%= BAS_OUTBUFSIZE
;
470 } while (--count
> 0);
474 return isowbuf_donewrite(iwb
);
477 int gigaset_isoc_buildframe(struct bc_state
*bcs
, unsigned char *in
, int len
)
481 switch (bcs
->proto2
) {
483 result
= hdlc_buildframe(bcs
->hw
.bas
->isooutbuf
, in
, len
);
484 gig_dbg(DEBUG_ISO
, "%s: %d bytes HDLC -> %d",
485 __func__
, len
, result
);
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
);
496 * append byte c to current skb of B channel structure *bcs, updating fcs
498 static inline void hdlc_putbyte(unsigned char c
, struct bc_state
*bcs
)
500 bcs
->rx_fcs
= crc_ccitt_byte(bcs
->rx_fcs
, c
);
501 if (bcs
->rx_skb
== NULL
)
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
);
511 __skb_put_u8(bcs
->rx_skb
, c
);
515 * drop partial HDLC data packet
517 static inline void hdlc_flush(struct bc_state
*bcs
)
519 /* clear skb or allocate new if not skipping */
520 if (bcs
->rx_skb
!= NULL
)
521 skb_trim(bcs
->rx_skb
, 0);
523 gigaset_new_rx_skb(bcs
);
525 /* reset packet state */
526 bcs
->rx_fcs
= PPP_INITFCS
;
530 * process completed HDLC data packet
532 static inline void hdlc_done(struct bc_state
*bcs
)
534 struct cardstate
*cs
= bcs
->cs
;
535 struct sk_buff
*procskb
;
538 if (unlikely(bcs
->ignore
)) {
543 procskb
= bcs
->rx_skb
;
544 if (procskb
== NULL
) {
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",
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
);
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
);
568 gigaset_new_rx_skb(bcs
);
569 bcs
->rx_fcs
= PPP_INITFCS
;
573 * drop HDLC data packet with non-integral last byte
575 static inline void hdlc_frag(struct bc_state
*bcs
, unsigned inbits
)
577 if (unlikely(bcs
->ignore
)) {
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
;
590 /* bit counts lookup table for HDLC bit unstuffing
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
597 static 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
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
624 * count number of received bytes
625 * bcs receiving B channel structure
627 static inline void hdlc_unpack(unsigned char *src
, unsigned count
,
628 struct bc_state
*bcs
)
630 struct bas_bc_state
*ubc
= bcs
->hw
.bas
;
632 unsigned seqlen
, inbyte
, inbits
;
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
640 * seqlen = number of consecutive '1' bits in last 7 input stream bits
642 * inbyte = accumulated partial data byte (if !INS_flag_hunt)
643 * inbits = number of valid bits in inbyte, starting at LSB (0..6)
645 inputstate
= bcs
->inputstate
;
646 seqlen
= ubc
->seqlen
;
647 inbyte
= ubc
->inbyte
;
648 inbits
= ubc
->inbits
;
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.
656 unsigned char c
= *src
++;
657 unsigned char tabentry
= bitcounts
[c
];
658 unsigned lead1
= tabentry
& 0x0f;
659 unsigned trail1
= (tabentry
>> 4) & 0x0f;
663 if (unlikely(inputstate
& INS_flag_hunt
)) {
666 inputstate
&= ~(INS_flag_hunt
| INS_have_data
);
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);
675 /* interior stuffing:
676 * omitting the MSB handles most cases,
677 * correct the incorrectly handled
678 * cases individually */
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
;
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)) {
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
;
711 if (inbits
< 7 - lead1
)
713 if (inputstate
& INS_have_data
) {
715 inputstate
&= ~INS_have_data
;
720 /* complete flag, LSB overlaps preceding flag */
724 } else if (trail1
!= 7) {
726 inbyte
= c
>> (lead1
+ 1);
729 /* interior stuffing:
730 * omitting the MSB handles most cases,
731 * correct the incorrectly handled
732 * cases individually */
741 /* abort sequence follows,
742 * skb already empty anyway */
744 inputstate
|= INS_flag_hunt
;
746 } else { /* (seqlen < 6) && (seqlen == 5 || trail1 >= 7) */
753 hdlc_frag(bcs
, inbits
);
756 } else if (inputstate
& INS_have_data
)
758 inputstate
&= ~INS_have_data
;
759 } else if (trail1
== 7) {
763 inputstate
|= INS_flag_hunt
;
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
;
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 */
783 inbyte
|= c
<< inbits
;
785 } else { /* seqlen == 5 && trail1 >= 8 */
787 /* stuff bit at lead1 *and* interior
788 * stuffing -- unstuff individually */
803 inbyte
|= c
<< inbits
;
808 hdlc_putbyte(inbyte
& 0xff, bcs
);
809 inputstate
|= INS_have_data
;
818 bcs
->inputstate
= inputstate
;
819 ubc
->seqlen
= seqlen
;
820 ubc
->inbyte
= inbyte
;
821 ubc
->inbits
= inbits
;
825 * pass on received USB frame transparently as SKB via gigaset_skb_rcvd
827 * tally frames, errors etc. in BC structure counters
830 * count number of received bytes
831 * bcs receiving B channel structure
833 static inline void trans_receive(unsigned char *src
, unsigned count
,
834 struct bc_state
*bcs
)
840 if (unlikely(bcs
->ignore
)) {
846 skb
= gigaset_new_rx_skb(bcs
);
850 dobytes
= bcs
->rx_bufsize
- skb
->len
;
852 dst
= skb_put(skb
, count
< dobytes
? count
: dobytes
);
853 while (count
> 0 && dobytes
> 0) {
854 *dst
++ = bitrev8(*src
++);
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
);
866 dobytes
= bcs
->rx_bufsize
;
871 void gigaset_isoc_receive(unsigned char *src
, unsigned count
,
872 struct bc_state
*bcs
)
874 switch (bcs
->proto2
) {
876 hdlc_unpack(src
, count
, bcs
);
878 default: /* assume transparent */
879 trans_receive(src
, count
, bcs
);
883 /* == data input =========================================================== */
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.
891 static void cmd_loop(unsigned char *src
, int numbytes
, struct inbuf_t
*inbuf
)
893 struct cardstate
*cs
= inbuf
->cs
;
894 unsigned cbytes
= cs
->cbytes
;
901 if (cbytes
== 0 && cs
->respdata
[0] == '\r') {
902 /* collapse LF with preceding CR */
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",
912 cbytes
= MAX_RESP_SIZE
;
915 gigaset_dbg_buffer(DEBUG_TRANSCMD
, "received response",
916 cbytes
, cs
->respdata
);
917 gigaset_handle_modem_response(cs
);
920 /* store EOL byte for CRLF collapsing */
924 /* append to line buffer if possible */
925 if (cbytes
< MAX_RESP_SIZE
)
926 cs
->respdata
[cbytes
] = c
;
936 /* process a block of data received through the control channel
938 void gigaset_isoc_input(struct inbuf_t
*inbuf
)
940 struct cardstate
*cs
= inbuf
->cs
;
941 unsigned tail
, head
, numbytes
;
945 while (head
!= (tail
= inbuf
->tail
)) {
946 gig_dbg(DEBUG_INTR
, "buffer state: %u -> %u", head
, tail
);
949 src
= inbuf
->data
+ head
;
950 numbytes
= tail
- head
;
951 gig_dbg(DEBUG_INTR
, "processing %u bytes", numbytes
);
953 if (cs
->mstate
== MS_LOCKED
) {
954 gigaset_dbg_buffer(DEBUG_LOCKCMD
, "received response",
956 gigaset_if_receive(inbuf
->cs
, src
, numbytes
);
958 cmd_loop(src
, numbytes
, inbuf
);
962 if (head
== RBUFSIZE
)
964 gig_dbg(DEBUG_INTR
, "setting head to %u", head
);
970 /* == data output ========================================================== */
973 * gigaset_isoc_send_skb() - queue an skb for sending
974 * @bcs: B channel descriptor structure.
975 * @skb: data to send.
977 * Called by LL to queue an skb for sending, and start transmission if
979 * Once the payload data has been transmitted completely, gigaset_skb_sent()
980 * will be called with the skb's link layer header preserved.
983 * number of bytes accepted for sending (skb->len) if ok,
984 * error code < 0 (eg. -ENODEV) on error
986 int gigaset_isoc_send_skb(struct bc_state
*bcs
, struct sk_buff
*skb
)
991 spin_lock_irqsave(&bcs
->cs
->lock
, flags
);
992 if (!bcs
->cs
->connected
) {
993 spin_unlock_irqrestore(&bcs
->cs
->lock
, flags
);
997 skb_queue_tail(&bcs
->squeue
, skb
);
998 gig_dbg(DEBUG_ISO
, "%s: skb queued, qlen=%d",
999 __func__
, skb_queue_len(&bcs
->squeue
));
1001 /* tasklet submits URB if necessary */
1002 tasklet_schedule(&bcs
->hw
.bas
->sent_tasklet
);
1003 spin_unlock_irqrestore(&bcs
->cs
->lock
, flags
);
1005 return len
; /* ok so far */