1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16#include "gigaset.h"
17#include <linux/crc-ccitt.h>
18#include <linux/bitrev.h>
19
20
21
22
23
24
25static inline int muststuff(unsigned char c)
26{
27 if (c < PPP_TRANS) return 1;
28 if (c == PPP_FLAG) return 1;
29 if (c == PPP_ESCAPE) return 1;
30
31
32
33 return 0;
34}
35
36
37
38
39
40
41
42static inline int cmd_loop(unsigned char c, unsigned char *src, int numbytes,
43 struct inbuf_t *inbuf)
44{
45 struct cardstate *cs = inbuf->cs;
46 unsigned cbytes = cs->cbytes;
47 int inputstate = inbuf->inputstate;
48 int startbytes = numbytes;
49
50 for (;;) {
51 cs->respdata[cbytes] = c;
52 if (c == 10 || c == 13) {
53 gig_dbg(DEBUG_TRANSCMD, "%s: End of Command (%d Bytes)",
54 __func__, cbytes);
55 cs->cbytes = cbytes;
56 gigaset_handle_modem_response(cs);
57
58 cbytes = 0;
59
60 if (cs->dle &&
61 !(inputstate & INS_DLE_command)) {
62 inputstate &= ~INS_command;
63 break;
64 }
65 } else {
66
67 if (cbytes < MAX_RESP_SIZE - 1)
68 cbytes++;
69 else
70 dev_warn(cs->dev, "response too large\n");
71 }
72
73 if (!numbytes)
74 break;
75 c = *src++;
76 --numbytes;
77 if (c == DLE_FLAG &&
78 (cs->dle || inputstate & INS_DLE_command)) {
79 inputstate |= INS_DLE_char;
80 break;
81 }
82 }
83
84 cs->cbytes = cbytes;
85 inbuf->inputstate = inputstate;
86
87 return startbytes - numbytes;
88}
89
90
91
92
93
94static inline int lock_loop(unsigned char *src, int numbytes,
95 struct inbuf_t *inbuf)
96{
97 struct cardstate *cs = inbuf->cs;
98
99 gigaset_dbg_buffer(DEBUG_LOCKCMD, "received response",
100 numbytes, src);
101 gigaset_if_receive(cs, src, numbytes);
102
103 return numbytes;
104}
105
106
107
108
109
110
111
112
113
114static inline int hdlc_loop(unsigned char c, unsigned char *src, int numbytes,
115 struct inbuf_t *inbuf)
116{
117 struct cardstate *cs = inbuf->cs;
118 struct bc_state *bcs = inbuf->bcs;
119 int inputstate = bcs->inputstate;
120 __u16 fcs = bcs->fcs;
121 struct sk_buff *skb = bcs->skb;
122 unsigned char error;
123 struct sk_buff *compskb;
124 int startbytes = numbytes;
125 int l;
126
127 if (unlikely(inputstate & INS_byte_stuff)) {
128 inputstate &= ~INS_byte_stuff;
129 goto byte_stuff;
130 }
131 for (;;) {
132 if (unlikely(c == PPP_ESCAPE)) {
133 if (unlikely(!numbytes)) {
134 inputstate |= INS_byte_stuff;
135 break;
136 }
137 c = *src++;
138 --numbytes;
139 if (unlikely(c == DLE_FLAG &&
140 (cs->dle ||
141 inbuf->inputstate & INS_DLE_command))) {
142 inbuf->inputstate |= INS_DLE_char;
143 inputstate |= INS_byte_stuff;
144 break;
145 }
146byte_stuff:
147 c ^= PPP_TRANS;
148 if (unlikely(!muststuff(c)))
149 gig_dbg(DEBUG_HDLC, "byte stuffed: 0x%02x", c);
150 } else if (unlikely(c == PPP_FLAG)) {
151 if (unlikely(inputstate & INS_skip_frame)) {
152#ifdef CONFIG_GIGASET_DEBUG
153 if (!(inputstate & INS_have_data)) {
154 ++bcs->emptycount;
155 } else
156 gig_dbg(DEBUG_HDLC,
157 "7e----------------------------");
158#endif
159
160
161 error = 1;
162 gigaset_rcv_error(NULL, cs, bcs);
163 } else if (!(inputstate & INS_have_data)) {
164#ifdef CONFIG_GIGASET_DEBUG
165 ++bcs->emptycount;
166#endif
167 break;
168 } else {
169 gig_dbg(DEBUG_HDLC,
170 "7e----------------------------");
171
172
173 error = 0;
174
175 if (unlikely(fcs != PPP_GOODFCS)) {
176 dev_err(cs->dev,
177 "Checksum failed, %u bytes corrupted!\n",
178 skb->len);
179 compskb = NULL;
180 gigaset_rcv_error(compskb, cs, bcs);
181 error = 1;
182 } else {
183 if (likely((l = skb->len) > 2)) {
184 skb->tail -= 2;
185 skb->len -= 2;
186 } else {
187 dev_kfree_skb(skb);
188 skb = NULL;
189 inputstate |= INS_skip_frame;
190 if (l == 1) {
191 dev_err(cs->dev,
192 "invalid packet size (1)!\n");
193 error = 1;
194 gigaset_rcv_error(NULL,
195 cs, bcs);
196 }
197 }
198 if (likely(!(error ||
199 (inputstate &
200 INS_skip_frame)))) {
201 gigaset_rcv_skb(skb, cs, bcs);
202 }
203 }
204 }
205
206 if (unlikely(error))
207 if (skb)
208 dev_kfree_skb(skb);
209
210 fcs = PPP_INITFCS;
211 inputstate &= ~(INS_have_data | INS_skip_frame);
212 if (unlikely(bcs->ignore)) {
213 inputstate |= INS_skip_frame;
214 skb = NULL;
215 } else if (likely((skb = dev_alloc_skb(SBUFSIZE + HW_HDR_LEN)) != NULL)) {
216 skb_reserve(skb, HW_HDR_LEN);
217 } else {
218 dev_warn(cs->dev,
219 "could not allocate new skb\n");
220 inputstate |= INS_skip_frame;
221 }
222
223 break;
224 } else if (unlikely(muststuff(c))) {
225
226 gig_dbg(DEBUG_HDLC, "not byte stuffed: 0x%02x", c);
227 }
228
229
230
231#ifdef CONFIG_GIGASET_DEBUG
232 if (unlikely(!(inputstate & INS_have_data))) {
233 gig_dbg(DEBUG_HDLC, "7e (%d x) ================",
234 bcs->emptycount);
235 bcs->emptycount = 0;
236 }
237#endif
238
239 inputstate |= INS_have_data;
240
241 if (likely(!(inputstate & INS_skip_frame))) {
242 if (unlikely(skb->len == SBUFSIZE)) {
243 dev_warn(cs->dev, "received packet too long\n");
244 dev_kfree_skb_any(skb);
245 skb = NULL;
246 inputstate |= INS_skip_frame;
247 break;
248 }
249 *__skb_put(skb, 1) = c;
250 fcs = crc_ccitt_byte(fcs, c);
251 }
252
253 if (unlikely(!numbytes))
254 break;
255 c = *src++;
256 --numbytes;
257 if (unlikely(c == DLE_FLAG &&
258 (cs->dle ||
259 inbuf->inputstate & INS_DLE_command))) {
260 inbuf->inputstate |= INS_DLE_char;
261 break;
262 }
263 }
264 bcs->inputstate = inputstate;
265 bcs->fcs = fcs;
266 bcs->skb = skb;
267 return startbytes - numbytes;
268}
269
270
271
272
273
274
275
276
277static inline int iraw_loop(unsigned char c, unsigned char *src, int numbytes,
278 struct inbuf_t *inbuf)
279{
280 struct cardstate *cs = inbuf->cs;
281 struct bc_state *bcs = inbuf->bcs;
282 int inputstate = bcs->inputstate;
283 struct sk_buff *skb = bcs->skb;
284 int startbytes = numbytes;
285
286 for (;;) {
287
288 inputstate |= INS_have_data;
289
290 if (likely(!(inputstate & INS_skip_frame))) {
291 if (unlikely(skb->len == SBUFSIZE)) {
292
293 dev_warn(cs->dev, "received packet too long\n");
294 dev_kfree_skb_any(skb);
295 skb = NULL;
296 inputstate |= INS_skip_frame;
297 break;
298 }
299 *__skb_put(skb, 1) = bitrev8(c);
300 }
301
302 if (unlikely(!numbytes))
303 break;
304 c = *src++;
305 --numbytes;
306 if (unlikely(c == DLE_FLAG &&
307 (cs->dle ||
308 inbuf->inputstate & INS_DLE_command))) {
309 inbuf->inputstate |= INS_DLE_char;
310 break;
311 }
312 }
313
314
315 if (likely(inputstate & INS_have_data)) {
316 if (likely(!(inputstate & INS_skip_frame))) {
317 gigaset_rcv_skb(skb, cs, bcs);
318 }
319 inputstate &= ~(INS_have_data | INS_skip_frame);
320 if (unlikely(bcs->ignore)) {
321 inputstate |= INS_skip_frame;
322 skb = NULL;
323 } else if (likely((skb = dev_alloc_skb(SBUFSIZE + HW_HDR_LEN))
324 != NULL)) {
325 skb_reserve(skb, HW_HDR_LEN);
326 } else {
327 dev_warn(cs->dev, "could not allocate new skb\n");
328 inputstate |= INS_skip_frame;
329 }
330 }
331
332 bcs->inputstate = inputstate;
333 bcs->skb = skb;
334 return startbytes - numbytes;
335}
336
337
338
339
340
341
342
343
344
345
346void gigaset_m10x_input(struct inbuf_t *inbuf)
347{
348 struct cardstate *cs;
349 unsigned tail, head, numbytes;
350 unsigned char *src, c;
351 int procbytes;
352
353 head = inbuf->head;
354 tail = inbuf->tail;
355 gig_dbg(DEBUG_INTR, "buffer state: %u -> %u", head, tail);
356
357 if (head != tail) {
358 cs = inbuf->cs;
359 src = inbuf->data + head;
360 numbytes = (head > tail ? RBUFSIZE : tail) - head;
361 gig_dbg(DEBUG_INTR, "processing %u bytes", numbytes);
362
363 while (numbytes) {
364 if (cs->mstate == MS_LOCKED) {
365 procbytes = lock_loop(src, numbytes, inbuf);
366 src += procbytes;
367 numbytes -= procbytes;
368 } else {
369 c = *src++;
370 --numbytes;
371 if (c == DLE_FLAG && (cs->dle ||
372 inbuf->inputstate & INS_DLE_command)) {
373 if (!(inbuf->inputstate & INS_DLE_char)) {
374 inbuf->inputstate |= INS_DLE_char;
375 goto nextbyte;
376 }
377
378 inbuf->inputstate &= ~INS_DLE_char;
379 }
380
381 if (!(inbuf->inputstate & INS_DLE_char)) {
382
383
384 if (inbuf->inputstate & INS_command)
385 procbytes = cmd_loop(c, src, numbytes, inbuf);
386 else if (inbuf->bcs->proto2 == ISDN_PROTO_L2_HDLC)
387 procbytes = hdlc_loop(c, src, numbytes, inbuf);
388 else
389 procbytes = iraw_loop(c, src, numbytes, inbuf);
390
391 src += procbytes;
392 numbytes -= procbytes;
393 } else {
394 inbuf->inputstate &= ~INS_DLE_char;
395 switch (c) {
396 case 'X':
397 if (inbuf->inputstate & INS_command)
398 dev_warn(cs->dev,
399 "received <DLE> 'X' in command mode\n");
400 inbuf->inputstate |=
401 INS_command | INS_DLE_command;
402 break;
403 case '.':
404 if (!(inbuf->inputstate & INS_command))
405 dev_warn(cs->dev,
406 "received <DLE> '.' in hdlc mode\n");
407 inbuf->inputstate &= cs->dle ?
408 ~(INS_DLE_command|INS_command)
409 : ~INS_DLE_command;
410 break;
411
412 default:
413 dev_err(cs->dev,
414 "received 0x10 0x%02x!\n",
415 (int) c);
416
417 }
418 }
419 }
420nextbyte:
421 if (!numbytes) {
422
423 if (head > tail) {
424 head = 0;
425 src = inbuf->data;
426 numbytes = tail;
427 } else {
428 head = tail;
429 break;
430 }
431 }
432 }
433
434 gig_dbg(DEBUG_INTR, "setting head to %u", head);
435 inbuf->head = head;
436 }
437}
438EXPORT_SYMBOL_GPL(gigaset_m10x_input);
439
440
441
442
443
444
445
446
447
448
449
450
451
452static struct sk_buff *HDLC_Encode(struct sk_buff *skb, int head, int tail)
453{
454 struct sk_buff *hdlc_skb;
455 __u16 fcs;
456 unsigned char c;
457 unsigned char *cp;
458 int len;
459 unsigned int stuf_cnt;
460
461 stuf_cnt = 0;
462 fcs = PPP_INITFCS;
463 cp = skb->data;
464 len = skb->len;
465 while (len--) {
466 if (muststuff(*cp))
467 stuf_cnt++;
468 fcs = crc_ccitt_byte(fcs, *cp++);
469 }
470 fcs ^= 0xffff;
471
472
473
474
475 hdlc_skb = dev_alloc_skb(skb->len + stuf_cnt + 6 + tail + head);
476 if (!hdlc_skb) {
477 dev_kfree_skb(skb);
478 return NULL;
479 }
480 skb_reserve(hdlc_skb, head);
481
482
483 memcpy(hdlc_skb->head, skb->head, 2);
484
485
486 *(skb_put(hdlc_skb, 1)) = PPP_FLAG;
487
488
489 while (skb->len--) {
490 if (muststuff(*skb->data)) {
491 *(skb_put(hdlc_skb, 1)) = PPP_ESCAPE;
492 *(skb_put(hdlc_skb, 1)) = (*skb->data++) ^ PPP_TRANS;
493 } else
494 *(skb_put(hdlc_skb, 1)) = *skb->data++;
495 }
496
497
498 c = (fcs & 0x00ff);
499 if (muststuff(c)) {
500 *(skb_put(hdlc_skb, 1)) = PPP_ESCAPE;
501 c ^= PPP_TRANS;
502 }
503 *(skb_put(hdlc_skb, 1)) = c;
504
505 c = ((fcs >> 8) & 0x00ff);
506 if (muststuff(c)) {
507 *(skb_put(hdlc_skb, 1)) = PPP_ESCAPE;
508 c ^= PPP_TRANS;
509 }
510 *(skb_put(hdlc_skb, 1)) = c;
511
512 *(skb_put(hdlc_skb, 1)) = PPP_FLAG;
513
514 dev_kfree_skb(skb);
515 return hdlc_skb;
516}
517
518
519
520
521
522
523
524
525
526static struct sk_buff *iraw_encode(struct sk_buff *skb, int head, int tail)
527{
528 struct sk_buff *iraw_skb;
529 unsigned char c;
530 unsigned char *cp;
531 int len;
532
533
534 iraw_skb = dev_alloc_skb(2*skb->len + tail + head);
535 if (!iraw_skb) {
536 dev_kfree_skb(skb);
537 return NULL;
538 }
539 skb_reserve(iraw_skb, head);
540
541 cp = skb->data;
542 len = skb->len;
543 while (len--) {
544 c = bitrev8(*cp++);
545 if (c == DLE_FLAG)
546 *(skb_put(iraw_skb, 1)) = c;
547 *(skb_put(iraw_skb, 1)) = c;
548 }
549 dev_kfree_skb(skb);
550 return iraw_skb;
551}
552
553
554
555
556
557
558
559
560
561
562
563
564
565int gigaset_m10x_send_skb(struct bc_state *bcs, struct sk_buff *skb)
566{
567 unsigned len = skb->len;
568 unsigned long flags;
569
570 if (bcs->proto2 == ISDN_PROTO_L2_HDLC)
571 skb = HDLC_Encode(skb, HW_HDR_LEN, 0);
572 else
573 skb = iraw_encode(skb, HW_HDR_LEN, 0);
574 if (!skb) {
575 dev_err(bcs->cs->dev,
576 "unable to allocate memory for encoding!\n");
577 return -ENOMEM;
578 }
579
580 skb_queue_tail(&bcs->squeue, skb);
581 spin_lock_irqsave(&bcs->cs->lock, flags);
582 if (bcs->cs->connected)
583 tasklet_schedule(&bcs->cs->write_tasklet);
584 spin_unlock_irqrestore(&bcs->cs->lock, flags);
585
586 return len;
587}
588EXPORT_SYMBOL_GPL(gigaset_m10x_send_skb);
589