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