2 * Common data handling layer for bas_gigaset
4 * Copyright (c) 2005 by Tilman Schmidt <tilman@imap.cc>,
5 * Hansjoerg Lipp <hjlipp@web.de>.
7 * =====================================================================
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License as
10 * published by the Free Software Foundation; either version 2 of
11 * the License, or (at your option) any later version.
12 * =====================================================================
16 #include <linux/crc-ccitt.h>
17 #include <linux/bitrev.h>
19 /* access methods for isowbuf_t */
20 /* ============================ */
22 /* initialize buffer structure
24 void gigaset_isowbuf_init(struct isowbuf_t
*iwb
, unsigned char idle
)
29 atomic_set(&iwb
->writesem
, 1);
32 memset(iwb
->data
+ BAS_OUTBUFSIZE
, idle
, BAS_OUTBUFPAD
);
35 /* compute number of bytes which can be appended to buffer
36 * so that there is still room to append a maximum frame of flags
38 static inline int isowbuf_freebytes(struct isowbuf_t
*iwb
)
40 int read
, write
, freebytes
;
44 if ((freebytes
= read
- write
) > 0) {
45 /* no wraparound: need padding space within regular area */
46 return freebytes
- BAS_OUTBUFPAD
;
47 } else if (read
< BAS_OUTBUFPAD
) {
48 /* wraparound: can use space up to end of regular area */
49 return BAS_OUTBUFSIZE
- write
;
51 /* following the wraparound yields more space */
52 return freebytes
+ BAS_OUTBUFSIZE
- BAS_OUTBUFPAD
;
56 /* compare two offsets within the buffer
57 * The buffer is seen as circular, with the read position as start
58 * returns -1/0/1 if position a </=/> position b without crossing 'read'
60 static inline int isowbuf_poscmp(struct isowbuf_t
*iwb
, int a
, int b
)
67 if (a
< read
&& read
<= b
)
72 if (b
< read
&& read
<= a
)
80 * acquire the write semaphore
81 * return true if acquired, false if busy
83 static inline int isowbuf_startwrite(struct isowbuf_t
*iwb
)
85 if (!atomic_dec_and_test(&iwb
->writesem
)) {
86 atomic_inc(&iwb
->writesem
);
87 gig_dbg(DEBUG_ISO
, "%s: couldn't acquire iso write semaphore",
92 "%s: acquired iso write semaphore, data[write]=%02x, nbits=%d",
93 __func__
, iwb
->data
[iwb
->write
], iwb
->wbits
);
98 * release the write semaphore
99 * returns the current write position
101 static inline int isowbuf_donewrite(struct isowbuf_t
*iwb
)
103 int write
= iwb
->write
;
104 atomic_inc(&iwb
->writesem
);
108 /* append bits to buffer without any checks
109 * - data contains bits to append, starting at LSB
110 * - nbits is number of bits to append (0..24)
111 * must be called with the write semaphore held
112 * If more than nbits bits are set in data, the extraneous bits are set in the
113 * buffer too, but the write position is only advanced by nbits.
115 static inline void isowbuf_putbits(struct isowbuf_t
*iwb
, u32 data
, int nbits
)
117 int write
= iwb
->write
;
119 data
|= iwb
->data
[write
];
122 iwb
->data
[write
++] = data
& 0xff;
123 write
%= BAS_OUTBUFSIZE
;
128 iwb
->data
[write
] = data
& 0xff;
132 /* put final flag on HDLC bitstream
133 * also sets the idle fill byte to the correspondingly shifted flag pattern
134 * must be called with the write semaphore held
136 static inline void isowbuf_putflag(struct isowbuf_t
*iwb
)
140 /* add two flags, thus reliably covering one byte */
141 isowbuf_putbits(iwb
, 0x7e7e, 8);
142 /* recover the idle flag byte */
144 iwb
->idle
= iwb
->data
[write
];
145 gig_dbg(DEBUG_ISO
, "idle fill byte %02x", iwb
->idle
);
146 /* mask extraneous bits in buffer */
147 iwb
->data
[write
] &= (1 << iwb
->wbits
) - 1;
150 /* retrieve a block of bytes for sending
151 * The requested number of bytes is provided as a contiguous block.
152 * If necessary, the frame is filled to the requested number of bytes
153 * with the idle value.
154 * returns offset to frame, < 0 on busy or error
156 int gigaset_isowbuf_getbytes(struct isowbuf_t
*iwb
, int size
)
158 int read
, write
, limit
, src
, dst
;
161 read
= iwb
->nextread
;
163 if (likely(read
== write
)) {
164 /* return idle frame */
165 return read
< BAS_OUTBUFPAD
?
166 BAS_OUTBUFSIZE
: read
- BAS_OUTBUFPAD
;
170 gig_dbg(DEBUG_STREAM
, "%s: read=%d write=%d limit=%d",
171 __func__
, read
, write
, limit
);
172 #ifdef CONFIG_GIGASET_DEBUG
173 if (unlikely(size
< 0 || size
> BAS_OUTBUFPAD
)) {
174 pr_err("invalid size %d\n", size
);
178 if (unlikely(limit
>= BAS_OUTBUFSIZE
+ BAS_OUTBUFPAD
||
179 (read
< src
&& limit
>= src
))) {
180 pr_err("isoc write buffer frame reservation violated\n");
186 /* no wraparound in valid data */
187 if (limit
>= write
) {
188 /* append idle frame */
189 if (!isowbuf_startwrite(iwb
))
191 /* write position could have changed */
193 if (limit
>= write
) {
194 pbyte
= iwb
->data
[write
]; /* save
196 limit
= write
+ BAS_OUTBUFPAD
;
197 gig_dbg(DEBUG_STREAM
,
198 "%s: filling %d->%d with %02x",
199 __func__
, write
, limit
, iwb
->idle
);
200 if (write
+ BAS_OUTBUFPAD
< BAS_OUTBUFSIZE
)
201 memset(iwb
->data
+ write
, iwb
->idle
,
204 /* wraparound, fill entire pad area */
205 memset(iwb
->data
+ write
, iwb
->idle
,
206 BAS_OUTBUFSIZE
+ BAS_OUTBUFPAD
210 gig_dbg(DEBUG_STREAM
,
211 "%s: restoring %02x at %d",
212 __func__
, pbyte
, limit
);
213 iwb
->data
[limit
] = pbyte
; /* restore
217 isowbuf_donewrite(iwb
);
220 /* valid data wraparound */
221 if (limit
>= BAS_OUTBUFSIZE
) {
222 /* copy wrapped part into pad area */
224 dst
= BAS_OUTBUFSIZE
;
225 while (dst
< limit
&& src
< write
)
226 iwb
->data
[dst
++] = iwb
->data
[src
++];
228 /* fill pad area with idle byte */
229 memset(iwb
->data
+ dst
, iwb
->idle
,
230 BAS_OUTBUFSIZE
+ BAS_OUTBUFPAD
- dst
);
235 iwb
->nextread
= limit
;
240 * write hex bytes to syslog for debugging
242 static inline void dump_bytes(enum debuglevel level
, const char *tag
,
243 unsigned char *bytes
, int count
)
245 #ifdef CONFIG_GIGASET_DEBUG
247 static char dbgline
[3 * 32 + 1];
250 if (!(gigaset_debuglevel
& level
))
253 while (count
-- > 0) {
254 if (i
> sizeof(dbgline
) - 4) {
256 gig_dbg(level
, "%s:%s", tag
, dbgline
);
260 dbgline
[i
] = (i
&& !(i
% 12)) ? '-' : ' ';
262 dbgline
[i
++] = hex_asc_hi(c
);
263 dbgline
[i
++] = hex_asc_lo(c
);
266 gig_dbg(level
, "%s:%s", tag
, dbgline
);
270 /*============================================================================*/
272 /* bytewise HDLC bitstuffing via table lookup
273 * lookup table: 5 subtables for 0..4 preceding consecutive '1' bits
274 * index: 256*(number of preceding '1' bits) + (next byte to stuff)
275 * value: bit 9.. 0 = result bits
276 * bit 12..10 = number of trailing '1' bits in result
277 * bit 14..13 = number of bits added by stuffing
279 static const u16 stufftab
[5 * 256] = {
281 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f,
282 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x201f,
283 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f,
284 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x203e, 0x205f,
285 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
286 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x209f,
287 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f,
288 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, 0x0078, 0x0079, 0x007a, 0x007b, 0x207c, 0x207d, 0x20be, 0x20df,
289 0x0480, 0x0481, 0x0482, 0x0483, 0x0484, 0x0485, 0x0486, 0x0487, 0x0488, 0x0489, 0x048a, 0x048b, 0x048c, 0x048d, 0x048e, 0x048f,
290 0x0490, 0x0491, 0x0492, 0x0493, 0x0494, 0x0495, 0x0496, 0x0497, 0x0498, 0x0499, 0x049a, 0x049b, 0x049c, 0x049d, 0x049e, 0x251f,
291 0x04a0, 0x04a1, 0x04a2, 0x04a3, 0x04a4, 0x04a5, 0x04a6, 0x04a7, 0x04a8, 0x04a9, 0x04aa, 0x04ab, 0x04ac, 0x04ad, 0x04ae, 0x04af,
292 0x04b0, 0x04b1, 0x04b2, 0x04b3, 0x04b4, 0x04b5, 0x04b6, 0x04b7, 0x04b8, 0x04b9, 0x04ba, 0x04bb, 0x04bc, 0x04bd, 0x253e, 0x255f,
293 0x08c0, 0x08c1, 0x08c2, 0x08c3, 0x08c4, 0x08c5, 0x08c6, 0x08c7, 0x08c8, 0x08c9, 0x08ca, 0x08cb, 0x08cc, 0x08cd, 0x08ce, 0x08cf,
294 0x08d0, 0x08d1, 0x08d2, 0x08d3, 0x08d4, 0x08d5, 0x08d6, 0x08d7, 0x08d8, 0x08d9, 0x08da, 0x08db, 0x08dc, 0x08dd, 0x08de, 0x299f,
295 0x0ce0, 0x0ce1, 0x0ce2, 0x0ce3, 0x0ce4, 0x0ce5, 0x0ce6, 0x0ce7, 0x0ce8, 0x0ce9, 0x0cea, 0x0ceb, 0x0cec, 0x0ced, 0x0cee, 0x0cef,
296 0x10f0, 0x10f1, 0x10f2, 0x10f3, 0x10f4, 0x10f5, 0x10f6, 0x10f7, 0x20f8, 0x20f9, 0x20fa, 0x20fb, 0x257c, 0x257d, 0x29be, 0x2ddf,
299 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x200f,
300 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x202f,
301 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x204f,
302 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x203e, 0x206f,
303 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x208f,
304 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x20af,
305 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x20cf,
306 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, 0x0078, 0x0079, 0x007a, 0x007b, 0x207c, 0x207d, 0x20be, 0x20ef,
307 0x0480, 0x0481, 0x0482, 0x0483, 0x0484, 0x0485, 0x0486, 0x0487, 0x0488, 0x0489, 0x048a, 0x048b, 0x048c, 0x048d, 0x048e, 0x250f,
308 0x0490, 0x0491, 0x0492, 0x0493, 0x0494, 0x0495, 0x0496, 0x0497, 0x0498, 0x0499, 0x049a, 0x049b, 0x049c, 0x049d, 0x049e, 0x252f,
309 0x04a0, 0x04a1, 0x04a2, 0x04a3, 0x04a4, 0x04a5, 0x04a6, 0x04a7, 0x04a8, 0x04a9, 0x04aa, 0x04ab, 0x04ac, 0x04ad, 0x04ae, 0x254f,
310 0x04b0, 0x04b1, 0x04b2, 0x04b3, 0x04b4, 0x04b5, 0x04b6, 0x04b7, 0x04b8, 0x04b9, 0x04ba, 0x04bb, 0x04bc, 0x04bd, 0x253e, 0x256f,
311 0x08c0, 0x08c1, 0x08c2, 0x08c3, 0x08c4, 0x08c5, 0x08c6, 0x08c7, 0x08c8, 0x08c9, 0x08ca, 0x08cb, 0x08cc, 0x08cd, 0x08ce, 0x298f,
312 0x08d0, 0x08d1, 0x08d2, 0x08d3, 0x08d4, 0x08d5, 0x08d6, 0x08d7, 0x08d8, 0x08d9, 0x08da, 0x08db, 0x08dc, 0x08dd, 0x08de, 0x29af,
313 0x0ce0, 0x0ce1, 0x0ce2, 0x0ce3, 0x0ce4, 0x0ce5, 0x0ce6, 0x0ce7, 0x0ce8, 0x0ce9, 0x0cea, 0x0ceb, 0x0cec, 0x0ced, 0x0cee, 0x2dcf,
314 0x10f0, 0x10f1, 0x10f2, 0x10f3, 0x10f4, 0x10f5, 0x10f6, 0x10f7, 0x20f8, 0x20f9, 0x20fa, 0x20fb, 0x257c, 0x257d, 0x29be, 0x31ef,
317 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x2007, 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x2017,
318 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x2027, 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x2037,
319 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x2047, 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x2057,
320 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x2067, 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x203e, 0x2077,
321 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x2087, 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x2097,
322 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x20a7, 0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x20b7,
323 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x20c7, 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x20d7,
324 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x20e7, 0x0078, 0x0079, 0x007a, 0x007b, 0x207c, 0x207d, 0x20be, 0x20f7,
325 0x0480, 0x0481, 0x0482, 0x0483, 0x0484, 0x0485, 0x0486, 0x2507, 0x0488, 0x0489, 0x048a, 0x048b, 0x048c, 0x048d, 0x048e, 0x2517,
326 0x0490, 0x0491, 0x0492, 0x0493, 0x0494, 0x0495, 0x0496, 0x2527, 0x0498, 0x0499, 0x049a, 0x049b, 0x049c, 0x049d, 0x049e, 0x2537,
327 0x04a0, 0x04a1, 0x04a2, 0x04a3, 0x04a4, 0x04a5, 0x04a6, 0x2547, 0x04a8, 0x04a9, 0x04aa, 0x04ab, 0x04ac, 0x04ad, 0x04ae, 0x2557,
328 0x04b0, 0x04b1, 0x04b2, 0x04b3, 0x04b4, 0x04b5, 0x04b6, 0x2567, 0x04b8, 0x04b9, 0x04ba, 0x04bb, 0x04bc, 0x04bd, 0x253e, 0x2577,
329 0x08c0, 0x08c1, 0x08c2, 0x08c3, 0x08c4, 0x08c5, 0x08c6, 0x2987, 0x08c8, 0x08c9, 0x08ca, 0x08cb, 0x08cc, 0x08cd, 0x08ce, 0x2997,
330 0x08d0, 0x08d1, 0x08d2, 0x08d3, 0x08d4, 0x08d5, 0x08d6, 0x29a7, 0x08d8, 0x08d9, 0x08da, 0x08db, 0x08dc, 0x08dd, 0x08de, 0x29b7,
331 0x0ce0, 0x0ce1, 0x0ce2, 0x0ce3, 0x0ce4, 0x0ce5, 0x0ce6, 0x2dc7, 0x0ce8, 0x0ce9, 0x0cea, 0x0ceb, 0x0cec, 0x0ced, 0x0cee, 0x2dd7,
332 0x10f0, 0x10f1, 0x10f2, 0x10f3, 0x10f4, 0x10f5, 0x10f6, 0x31e7, 0x20f8, 0x20f9, 0x20fa, 0x20fb, 0x257c, 0x257d, 0x29be, 0x41f7,
335 0x0000, 0x0001, 0x0002, 0x2003, 0x0004, 0x0005, 0x0006, 0x200b, 0x0008, 0x0009, 0x000a, 0x2013, 0x000c, 0x000d, 0x000e, 0x201b,
336 0x0010, 0x0011, 0x0012, 0x2023, 0x0014, 0x0015, 0x0016, 0x202b, 0x0018, 0x0019, 0x001a, 0x2033, 0x001c, 0x001d, 0x001e, 0x203b,
337 0x0020, 0x0021, 0x0022, 0x2043, 0x0024, 0x0025, 0x0026, 0x204b, 0x0028, 0x0029, 0x002a, 0x2053, 0x002c, 0x002d, 0x002e, 0x205b,
338 0x0030, 0x0031, 0x0032, 0x2063, 0x0034, 0x0035, 0x0036, 0x206b, 0x0038, 0x0039, 0x003a, 0x2073, 0x003c, 0x003d, 0x203e, 0x207b,
339 0x0040, 0x0041, 0x0042, 0x2083, 0x0044, 0x0045, 0x0046, 0x208b, 0x0048, 0x0049, 0x004a, 0x2093, 0x004c, 0x004d, 0x004e, 0x209b,
340 0x0050, 0x0051, 0x0052, 0x20a3, 0x0054, 0x0055, 0x0056, 0x20ab, 0x0058, 0x0059, 0x005a, 0x20b3, 0x005c, 0x005d, 0x005e, 0x20bb,
341 0x0060, 0x0061, 0x0062, 0x20c3, 0x0064, 0x0065, 0x0066, 0x20cb, 0x0068, 0x0069, 0x006a, 0x20d3, 0x006c, 0x006d, 0x006e, 0x20db,
342 0x0070, 0x0071, 0x0072, 0x20e3, 0x0074, 0x0075, 0x0076, 0x20eb, 0x0078, 0x0079, 0x007a, 0x20f3, 0x207c, 0x207d, 0x20be, 0x40fb,
343 0x0480, 0x0481, 0x0482, 0x2503, 0x0484, 0x0485, 0x0486, 0x250b, 0x0488, 0x0489, 0x048a, 0x2513, 0x048c, 0x048d, 0x048e, 0x251b,
344 0x0490, 0x0491, 0x0492, 0x2523, 0x0494, 0x0495, 0x0496, 0x252b, 0x0498, 0x0499, 0x049a, 0x2533, 0x049c, 0x049d, 0x049e, 0x253b,
345 0x04a0, 0x04a1, 0x04a2, 0x2543, 0x04a4, 0x04a5, 0x04a6, 0x254b, 0x04a8, 0x04a9, 0x04aa, 0x2553, 0x04ac, 0x04ad, 0x04ae, 0x255b,
346 0x04b0, 0x04b1, 0x04b2, 0x2563, 0x04b4, 0x04b5, 0x04b6, 0x256b, 0x04b8, 0x04b9, 0x04ba, 0x2573, 0x04bc, 0x04bd, 0x253e, 0x257b,
347 0x08c0, 0x08c1, 0x08c2, 0x2983, 0x08c4, 0x08c5, 0x08c6, 0x298b, 0x08c8, 0x08c9, 0x08ca, 0x2993, 0x08cc, 0x08cd, 0x08ce, 0x299b,
348 0x08d0, 0x08d1, 0x08d2, 0x29a3, 0x08d4, 0x08d5, 0x08d6, 0x29ab, 0x08d8, 0x08d9, 0x08da, 0x29b3, 0x08dc, 0x08dd, 0x08de, 0x29bb,
349 0x0ce0, 0x0ce1, 0x0ce2, 0x2dc3, 0x0ce4, 0x0ce5, 0x0ce6, 0x2dcb, 0x0ce8, 0x0ce9, 0x0cea, 0x2dd3, 0x0cec, 0x0ced, 0x0cee, 0x2ddb,
350 0x10f0, 0x10f1, 0x10f2, 0x31e3, 0x10f4, 0x10f5, 0x10f6, 0x31eb, 0x20f8, 0x20f9, 0x20fa, 0x41f3, 0x257c, 0x257d, 0x29be, 0x46fb,
353 0x0000, 0x2001, 0x0002, 0x2005, 0x0004, 0x2009, 0x0006, 0x200d, 0x0008, 0x2011, 0x000a, 0x2015, 0x000c, 0x2019, 0x000e, 0x201d,
354 0x0010, 0x2021, 0x0012, 0x2025, 0x0014, 0x2029, 0x0016, 0x202d, 0x0018, 0x2031, 0x001a, 0x2035, 0x001c, 0x2039, 0x001e, 0x203d,
355 0x0020, 0x2041, 0x0022, 0x2045, 0x0024, 0x2049, 0x0026, 0x204d, 0x0028, 0x2051, 0x002a, 0x2055, 0x002c, 0x2059, 0x002e, 0x205d,
356 0x0030, 0x2061, 0x0032, 0x2065, 0x0034, 0x2069, 0x0036, 0x206d, 0x0038, 0x2071, 0x003a, 0x2075, 0x003c, 0x2079, 0x203e, 0x407d,
357 0x0040, 0x2081, 0x0042, 0x2085, 0x0044, 0x2089, 0x0046, 0x208d, 0x0048, 0x2091, 0x004a, 0x2095, 0x004c, 0x2099, 0x004e, 0x209d,
358 0x0050, 0x20a1, 0x0052, 0x20a5, 0x0054, 0x20a9, 0x0056, 0x20ad, 0x0058, 0x20b1, 0x005a, 0x20b5, 0x005c, 0x20b9, 0x005e, 0x20bd,
359 0x0060, 0x20c1, 0x0062, 0x20c5, 0x0064, 0x20c9, 0x0066, 0x20cd, 0x0068, 0x20d1, 0x006a, 0x20d5, 0x006c, 0x20d9, 0x006e, 0x20dd,
360 0x0070, 0x20e1, 0x0072, 0x20e5, 0x0074, 0x20e9, 0x0076, 0x20ed, 0x0078, 0x20f1, 0x007a, 0x20f5, 0x207c, 0x40f9, 0x20be, 0x417d,
361 0x0480, 0x2501, 0x0482, 0x2505, 0x0484, 0x2509, 0x0486, 0x250d, 0x0488, 0x2511, 0x048a, 0x2515, 0x048c, 0x2519, 0x048e, 0x251d,
362 0x0490, 0x2521, 0x0492, 0x2525, 0x0494, 0x2529, 0x0496, 0x252d, 0x0498, 0x2531, 0x049a, 0x2535, 0x049c, 0x2539, 0x049e, 0x253d,
363 0x04a0, 0x2541, 0x04a2, 0x2545, 0x04a4, 0x2549, 0x04a6, 0x254d, 0x04a8, 0x2551, 0x04aa, 0x2555, 0x04ac, 0x2559, 0x04ae, 0x255d,
364 0x04b0, 0x2561, 0x04b2, 0x2565, 0x04b4, 0x2569, 0x04b6, 0x256d, 0x04b8, 0x2571, 0x04ba, 0x2575, 0x04bc, 0x2579, 0x253e, 0x467d,
365 0x08c0, 0x2981, 0x08c2, 0x2985, 0x08c4, 0x2989, 0x08c6, 0x298d, 0x08c8, 0x2991, 0x08ca, 0x2995, 0x08cc, 0x2999, 0x08ce, 0x299d,
366 0x08d0, 0x29a1, 0x08d2, 0x29a5, 0x08d4, 0x29a9, 0x08d6, 0x29ad, 0x08d8, 0x29b1, 0x08da, 0x29b5, 0x08dc, 0x29b9, 0x08de, 0x29bd,
367 0x0ce0, 0x2dc1, 0x0ce2, 0x2dc5, 0x0ce4, 0x2dc9, 0x0ce6, 0x2dcd, 0x0ce8, 0x2dd1, 0x0cea, 0x2dd5, 0x0cec, 0x2dd9, 0x0cee, 0x2ddd,
368 0x10f0, 0x31e1, 0x10f2, 0x31e5, 0x10f4, 0x31e9, 0x10f6, 0x31ed, 0x20f8, 0x41f1, 0x20fa, 0x41f5, 0x257c, 0x46f9, 0x29be, 0x4b7d
371 /* hdlc_bitstuff_byte
372 * perform HDLC bitstuffing for one input byte (8 bits, LSB first)
375 * ones number of trailing '1' bits in result before this step
376 * iwb pointer to output buffer structure (write semaphore must be held)
378 * number of trailing '1' bits in result after this step
381 static inline int hdlc_bitstuff_byte(struct isowbuf_t
*iwb
, unsigned char cin
,
385 int shiftinc
, newones
;
387 /* get stuffing information for input byte
388 * value: bit 9.. 0 = result bits
389 * bit 12..10 = number of trailing '1' bits in result
390 * bit 14..13 = number of bits added by stuffing
392 stuff
= stufftab
[256 * ones
+ cin
];
393 shiftinc
= (stuff
>> 13) & 3;
394 newones
= (stuff
>> 10) & 7;
397 /* append stuffed byte to output stream */
398 isowbuf_putbits(iwb
, stuff
, 8 + shiftinc
);
403 * Perform HDLC framing with bitstuffing on a byte buffer
404 * The input buffer is regarded as a sequence of bits, starting with the least
405 * significant bit of the first byte and ending with the most significant bit
406 * of the last byte. A 16 bit FCS is appended as defined by RFC 1662.
407 * Whenever five consecutive '1' bits appear in the resulting bit sequence, a
408 * '0' bit is inserted after them.
409 * The resulting bit string and a closing flag pattern (PPP_FLAG, '01111110')
410 * are appended to the output buffer starting at the given bit position, which
411 * is assumed to already contain a leading flag.
412 * The output buffer must have sufficient length; count + count/5 + 6 bytes
413 * starting at *out are safe and are verified to be present.
416 * count number of bytes in input buffer
417 * iwb pointer to output buffer structure (write semaphore must be held)
419 * position of end of packet in output buffer on success,
420 * -EAGAIN if write semaphore busy or buffer full
423 static inline int hdlc_buildframe(struct isowbuf_t
*iwb
,
424 unsigned char *in
, int count
)
431 if (isowbuf_freebytes(iwb
) < count
+ count
/ 5 + 6 ||
432 !isowbuf_startwrite(iwb
)) {
433 gig_dbg(DEBUG_ISO
, "%s: %d bytes free -> -EAGAIN",
434 __func__
, isowbuf_freebytes(iwb
));
438 dump_bytes(DEBUG_STREAM
, "snd data", in
, count
);
440 /* bitstuff and checksum input data */
443 while (count
-- > 0) {
445 ones
= hdlc_bitstuff_byte(iwb
, c
, ones
);
446 fcs
= crc_ccitt_byte(fcs
, c
);
449 /* bitstuff and append FCS (complemented, least significant byte first) */
451 ones
= hdlc_bitstuff_byte(iwb
, fcs
& 0x00ff, ones
);
452 ones
= hdlc_bitstuff_byte(iwb
, (fcs
>> 8) & 0x00ff, ones
);
454 /* put closing flag and repeat byte for flag idle */
455 isowbuf_putflag(iwb
);
456 end
= isowbuf_donewrite(iwb
);
457 dump_bytes(DEBUG_STREAM_DUMP
, "isowbuf", iwb
->data
, end
+ 1);
462 * Append a block of 'transparent' data to the output buffer,
463 * inverting the bytes.
464 * The output buffer must have sufficient length; count bytes
465 * starting at *out are safe and are verified to be present.
468 * count number of bytes in input buffer
469 * iwb pointer to output buffer structure (write semaphore must be held)
471 * position of end of packet in output buffer on success,
472 * -EAGAIN if write semaphore busy or buffer full
475 static inline int trans_buildframe(struct isowbuf_t
*iwb
,
476 unsigned char *in
, int count
)
481 if (unlikely(count
<= 0))
484 if (isowbuf_freebytes(iwb
) < count
||
485 !isowbuf_startwrite(iwb
)) {
486 gig_dbg(DEBUG_ISO
, "can't put %d bytes", count
);
490 gig_dbg(DEBUG_STREAM
, "put %d bytes", count
);
494 iwb
->data
[write
++] = c
;
495 write
%= BAS_OUTBUFSIZE
;
496 } while (--count
> 0);
500 return isowbuf_donewrite(iwb
);
503 int gigaset_isoc_buildframe(struct bc_state
*bcs
, unsigned char *in
, int len
)
507 switch (bcs
->proto2
) {
508 case ISDN_PROTO_L2_HDLC
:
509 result
= hdlc_buildframe(bcs
->hw
.bas
->isooutbuf
, in
, len
);
510 gig_dbg(DEBUG_ISO
, "%s: %d bytes HDLC -> %d",
511 __func__
, len
, result
);
513 default: /* assume transparent */
514 result
= trans_buildframe(bcs
->hw
.bas
->isooutbuf
, in
, len
);
515 gig_dbg(DEBUG_ISO
, "%s: %d bytes trans -> %d",
516 __func__
, len
, result
);
522 * append byte c to current skb of B channel structure *bcs, updating fcs
524 static inline void hdlc_putbyte(unsigned char c
, struct bc_state
*bcs
)
526 bcs
->fcs
= crc_ccitt_byte(bcs
->fcs
, c
);
527 if (unlikely(bcs
->skb
== NULL
)) {
531 if (unlikely(bcs
->skb
->len
== SBUFSIZE
)) {
532 dev_warn(bcs
->cs
->dev
, "received oversized packet discarded\n");
533 bcs
->hw
.bas
->giants
++;
534 dev_kfree_skb_any(bcs
->skb
);
538 *__skb_put(bcs
->skb
, 1) = c
;
542 * drop partial HDLC data packet
544 static inline void hdlc_flush(struct bc_state
*bcs
)
546 /* clear skb or allocate new if not skipping */
547 if (likely(bcs
->skb
!= NULL
))
548 skb_trim(bcs
->skb
, 0);
549 else if (!bcs
->ignore
) {
550 if ((bcs
->skb
= dev_alloc_skb(SBUFSIZE
+ HW_HDR_LEN
)) != NULL
)
551 skb_reserve(bcs
->skb
, HW_HDR_LEN
);
553 dev_err(bcs
->cs
->dev
, "could not allocate skb\n");
556 /* reset packet state */
557 bcs
->fcs
= PPP_INITFCS
;
561 * process completed HDLC data packet
563 static inline void hdlc_done(struct bc_state
*bcs
)
565 struct sk_buff
*procskb
;
567 if (unlikely(bcs
->ignore
)) {
573 if ((procskb
= bcs
->skb
) == NULL
) {
575 gig_dbg(DEBUG_ISO
, "%s: skb=NULL", __func__
);
576 gigaset_rcv_error(NULL
, bcs
->cs
, bcs
);
577 } else if (procskb
->len
< 2) {
578 dev_notice(bcs
->cs
->dev
, "received short frame (%d octets)\n",
580 bcs
->hw
.bas
->runts
++;
581 gigaset_rcv_error(procskb
, bcs
->cs
, bcs
);
582 } else if (bcs
->fcs
!= PPP_GOODFCS
) {
583 dev_notice(bcs
->cs
->dev
, "frame check error (0x%04x)\n",
585 bcs
->hw
.bas
->fcserrs
++;
586 gigaset_rcv_error(procskb
, bcs
->cs
, bcs
);
588 procskb
->len
-= 2; /* subtract FCS */
590 gig_dbg(DEBUG_ISO
, "%s: good frame (%d octets)",
591 __func__
, procskb
->len
);
592 dump_bytes(DEBUG_STREAM
,
593 "rcv data", procskb
->data
, procskb
->len
);
594 bcs
->hw
.bas
->goodbytes
+= procskb
->len
;
595 gigaset_rcv_skb(procskb
, bcs
->cs
, bcs
);
598 if ((bcs
->skb
= dev_alloc_skb(SBUFSIZE
+ HW_HDR_LEN
)) != NULL
)
599 skb_reserve(bcs
->skb
, HW_HDR_LEN
);
601 dev_err(bcs
->cs
->dev
, "could not allocate skb\n");
602 bcs
->fcs
= PPP_INITFCS
;
606 * drop HDLC data packet with non-integral last byte
608 static inline void hdlc_frag(struct bc_state
*bcs
, unsigned inbits
)
610 if (unlikely(bcs
->ignore
)) {
616 dev_notice(bcs
->cs
->dev
, "received partial byte (%d bits)\n", inbits
);
617 bcs
->hw
.bas
->alignerrs
++;
618 gigaset_rcv_error(bcs
->skb
, bcs
->cs
, bcs
);
620 if ((bcs
->skb
= dev_alloc_skb(SBUFSIZE
+ HW_HDR_LEN
)) != NULL
)
621 skb_reserve(bcs
->skb
, HW_HDR_LEN
);
623 dev_err(bcs
->cs
->dev
, "could not allocate skb\n");
624 bcs
->fcs
= PPP_INITFCS
;
627 /* bit counts lookup table for HDLC bit unstuffing
629 * value: bit 0..3 = number of consecutive '1' bits starting from LSB
630 * bit 4..6 = number of consecutive '1' bits starting from MSB
631 * (replacing 8 by 7 to make it fit; the algorithm won't care)
632 * bit 7 set if there are 5 or more "interior" consecutive '1' bits
634 static const unsigned char bitcounts
[256] = {
635 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x03, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x04,
636 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x03, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x05,
637 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x03, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x04,
638 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x03, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x80, 0x06,
639 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x03, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x04,
640 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x03, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x05,
641 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x03, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x04,
642 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x03, 0x00, 0x01, 0x00, 0x02, 0x80, 0x81, 0x80, 0x07,
643 0x10, 0x11, 0x10, 0x12, 0x10, 0x11, 0x10, 0x13, 0x10, 0x11, 0x10, 0x12, 0x10, 0x11, 0x10, 0x14,
644 0x10, 0x11, 0x10, 0x12, 0x10, 0x11, 0x10, 0x13, 0x10, 0x11, 0x10, 0x12, 0x10, 0x11, 0x10, 0x15,
645 0x10, 0x11, 0x10, 0x12, 0x10, 0x11, 0x10, 0x13, 0x10, 0x11, 0x10, 0x12, 0x10, 0x11, 0x10, 0x14,
646 0x10, 0x11, 0x10, 0x12, 0x10, 0x11, 0x10, 0x13, 0x10, 0x11, 0x10, 0x12, 0x10, 0x11, 0x90, 0x16,
647 0x20, 0x21, 0x20, 0x22, 0x20, 0x21, 0x20, 0x23, 0x20, 0x21, 0x20, 0x22, 0x20, 0x21, 0x20, 0x24,
648 0x20, 0x21, 0x20, 0x22, 0x20, 0x21, 0x20, 0x23, 0x20, 0x21, 0x20, 0x22, 0x20, 0x21, 0x20, 0x25,
649 0x30, 0x31, 0x30, 0x32, 0x30, 0x31, 0x30, 0x33, 0x30, 0x31, 0x30, 0x32, 0x30, 0x31, 0x30, 0x34,
650 0x40, 0x41, 0x40, 0x42, 0x40, 0x41, 0x40, 0x43, 0x50, 0x51, 0x50, 0x52, 0x60, 0x61, 0x70, 0x78
654 * perform HDLC frame processing (bit unstuffing, flag detection, FCS calculation)
655 * on a sequence of received data bytes (8 bits each, LSB first)
656 * pass on successfully received, complete frames as SKBs via gigaset_rcv_skb
657 * notify of errors via gigaset_rcv_error
658 * tally frames, errors etc. in BC structure counters
661 * count number of received bytes
662 * bcs receiving B channel structure
664 static inline void hdlc_unpack(unsigned char *src
, unsigned count
,
665 struct bc_state
*bcs
)
667 struct bas_bc_state
*ubc
= bcs
->hw
.bas
;
669 unsigned seqlen
, inbyte
, inbits
;
671 /* load previous state:
672 * inputstate = set of flag bits:
673 * - INS_flag_hunt: no complete opening flag received since connection setup or last abort
674 * - INS_have_data: at least one complete data byte received since last flag
675 * seqlen = number of consecutive '1' bits in last 7 input stream bits (0..7)
676 * inbyte = accumulated partial data byte (if !INS_flag_hunt)
677 * inbits = number of valid bits in inbyte, starting at LSB (0..6)
679 inputstate
= bcs
->inputstate
;
680 seqlen
= ubc
->seqlen
;
681 inbyte
= ubc
->inbyte
;
682 inbits
= ubc
->inbits
;
684 /* bit unstuffing a byte a time
685 * Take your time to understand this; it's straightforward but tedious.
686 * The "bitcounts" lookup table is used to speed up the counting of
687 * leading and trailing '1' bits.
690 unsigned char c
= *src
++;
691 unsigned char tabentry
= bitcounts
[c
];
692 unsigned lead1
= tabentry
& 0x0f;
693 unsigned trail1
= (tabentry
>> 4) & 0x0f;
697 if (unlikely(inputstate
& INS_flag_hunt
)) {
700 inputstate
&= ~(INS_flag_hunt
| INS_have_data
);
703 } else if (seqlen
== 6 && trail1
!= 7) {
704 /* flag completed & not followed by abort */
705 inputstate
&= ~(INS_flag_hunt
| INS_have_data
);
706 inbyte
= c
>> (lead1
+ 1);
709 /* interior stuffing: omitting the MSB handles most cases */
711 /* correct the incorrectly handled cases individually */
719 /* else: continue flag-hunting */
720 } else if (likely(seqlen
< 5 && trail1
< 7)) {
721 /* streamlined case: 8 data bits, no stuffing */
722 inbyte
|= c
<< inbits
;
723 hdlc_putbyte(inbyte
& 0xff, bcs
);
724 inputstate
|= INS_have_data
;
726 /* inbits unchanged */
727 } else if (likely(seqlen
== 6 && inbits
== 7 - lead1
&&
728 trail1
+ 1 == inbits
&&
729 !(inputstate
& INS_have_data
))) {
730 /* streamlined case: flag idle - state unchanged */
731 } else if (unlikely(seqlen
> 6)) {
735 inputstate
|= INS_flag_hunt
;
736 } else if (seqlen
== 6) {
737 /* closing flag, including (6 - lead1) '1's and one '0' from inbits */
738 if (inbits
> 7 - lead1
) {
739 hdlc_frag(bcs
, inbits
+ lead1
- 7);
740 inputstate
&= ~INS_have_data
;
742 if (inbits
< 7 - lead1
)
744 if (inputstate
& INS_have_data
) {
746 inputstate
&= ~INS_have_data
;
751 /* complete flag, LSB overlaps preceding flag */
755 } else if (trail1
!= 7) {
757 inbyte
= c
>> (lead1
+ 1);
760 /* interior stuffing: omitting the MSB handles most cases */
762 /* correct the incorrectly handled cases individually */
770 /* abort sequence follows, skb already empty anyway */
772 inputstate
|= INS_flag_hunt
;
774 } else { /* (seqlen < 6) && (seqlen == 5 || trail1 >= 7) */
781 hdlc_frag(bcs
, inbits
);
784 } else if (inputstate
& INS_have_data
)
786 inputstate
&= ~INS_have_data
;
787 } else if (trail1
== 7) {
791 inputstate
|= INS_flag_hunt
;
794 if (trail1
< 7) { /* => seqlen == 5 */
795 /* stuff bit at position lead1, no interior stuffing */
796 unsigned char mask
= (1 << lead1
) - 1;
797 c
= (c
& mask
) | ((c
& ~mask
) >> 1);
798 inbyte
|= c
<< inbits
;
800 } else if (seqlen
< 5) { /* trail1 >= 8 */
801 /* interior stuffing: omitting the MSB handles most cases */
802 /* correct the incorrectly handled cases individually */
808 inbyte
|= c
<< inbits
;
810 } else { /* seqlen == 5 && trail1 >= 8 */
812 /* stuff bit at lead1 *and* interior stuffing */
813 switch (c
) { /* unstuff individually */
827 inbyte
|= c
<< inbits
;
832 hdlc_putbyte(inbyte
& 0xff, bcs
);
833 inputstate
|= INS_have_data
;
842 bcs
->inputstate
= inputstate
;
843 ubc
->seqlen
= seqlen
;
844 ubc
->inbyte
= inbyte
;
845 ubc
->inbits
= inbits
;
849 * pass on received USB frame transparently as SKB via gigaset_rcv_skb
851 * tally frames, errors etc. in BC structure counters
854 * count number of received bytes
855 * bcs receiving B channel structure
857 static inline void trans_receive(unsigned char *src
, unsigned count
,
858 struct bc_state
*bcs
)
864 if (unlikely(bcs
->ignore
)) {
869 if (unlikely((skb
= bcs
->skb
) == NULL
)) {
870 bcs
->skb
= skb
= dev_alloc_skb(SBUFSIZE
+ HW_HDR_LEN
);
872 dev_err(bcs
->cs
->dev
, "could not allocate skb\n");
875 skb_reserve(skb
, HW_HDR_LEN
);
877 bcs
->hw
.bas
->goodbytes
+= skb
->len
;
878 dobytes
= TRANSBUFSIZE
- skb
->len
;
880 dst
= skb_put(skb
, count
< dobytes
? count
: dobytes
);
881 while (count
> 0 && dobytes
> 0) {
882 *dst
++ = bitrev8(*src
++);
887 gigaset_rcv_skb(skb
, bcs
->cs
, bcs
);
888 bcs
->skb
= skb
= dev_alloc_skb(SBUFSIZE
+ HW_HDR_LEN
);
890 dev_err(bcs
->cs
->dev
,
891 "could not allocate skb\n");
894 skb_reserve(bcs
->skb
, HW_HDR_LEN
);
895 dobytes
= TRANSBUFSIZE
;
900 void gigaset_isoc_receive(unsigned char *src
, unsigned count
, struct bc_state
*bcs
)
902 switch (bcs
->proto2
) {
903 case ISDN_PROTO_L2_HDLC
:
904 hdlc_unpack(src
, count
, bcs
);
906 default: /* assume transparent */
907 trans_receive(src
, count
, bcs
);
911 /* == data input =========================================================== */
913 static void cmd_loop(unsigned char *src
, int numbytes
, struct inbuf_t
*inbuf
)
915 struct cardstate
*cs
= inbuf
->cs
;
916 unsigned cbytes
= cs
->cbytes
;
919 /* copy next character, check for end of line */
920 switch (cs
->respdata
[cbytes
] = *src
++) {
924 gig_dbg(DEBUG_TRANSCMD
, "%s: End of Command (%d Bytes)",
926 if (cbytes
>= MAX_RESP_SIZE
- 1)
927 dev_warn(cs
->dev
, "response too large\n");
929 gigaset_handle_modem_response(cs
);
933 /* advance in line buffer, checking for overflow */
934 if (cbytes
< MAX_RESP_SIZE
- 1)
944 /* process a block of data received through the control channel
946 void gigaset_isoc_input(struct inbuf_t
*inbuf
)
948 struct cardstate
*cs
= inbuf
->cs
;
949 unsigned tail
, head
, numbytes
;
953 while (head
!= (tail
= inbuf
->tail
)) {
954 gig_dbg(DEBUG_INTR
, "buffer state: %u -> %u", head
, tail
);
957 src
= inbuf
->data
+ head
;
958 numbytes
= tail
- head
;
959 gig_dbg(DEBUG_INTR
, "processing %u bytes", numbytes
);
961 if (cs
->mstate
== MS_LOCKED
) {
962 gigaset_dbg_buffer(DEBUG_LOCKCMD
, "received response",
964 gigaset_if_receive(inbuf
->cs
, src
, numbytes
);
966 gigaset_dbg_buffer(DEBUG_CMD
, "received response",
968 cmd_loop(src
, numbytes
, inbuf
);
972 if (head
== RBUFSIZE
)
974 gig_dbg(DEBUG_INTR
, "setting head to %u", head
);
980 /* == data output ========================================================== */
983 * called by common.c to queue an skb for sending
984 * and start transmission if necessary
986 * B Channel control structure
989 * number of bytes accepted for sending
990 * (skb->len if ok, 0 if out of buffer space)
991 * or error code (< 0, eg. -EINVAL)
993 int gigaset_isoc_send_skb(struct bc_state
*bcs
, struct sk_buff
*skb
)
998 spin_lock_irqsave(&bcs
->cs
->lock
, flags
);
999 if (!bcs
->cs
->connected
) {
1000 spin_unlock_irqrestore(&bcs
->cs
->lock
, flags
);
1004 skb_queue_tail(&bcs
->squeue
, skb
);
1005 gig_dbg(DEBUG_ISO
, "%s: skb queued, qlen=%d",
1006 __func__
, skb_queue_len(&bcs
->squeue
));
1008 /* tasklet submits URB if necessary */
1009 tasklet_schedule(&bcs
->hw
.bas
->sent_tasklet
);
1010 spin_unlock_irqrestore(&bcs
->cs
->lock
, flags
);
1012 return len
; /* ok so far */