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