[PATCH] isdn4linux: Siemens Gigaset drivers: logging usage
[firefly-linux-kernel-4.4.55.git] / drivers / isdn / gigaset / asyncdata.c
1 /*
2  * Common data handling layer for ser_gigaset and usb_gigaset
3  *
4  * Copyright (c) 2005 by Tilman Schmidt <tilman@imap.cc>,
5  *                       Hansjoerg Lipp <hjlipp@web.de>,
6  *                       Stefan Eilers <Eilers.Stefan@epost.de>.
7  *
8  * =====================================================================
9  *      This program is free software; you can redistribute it and/or
10  *      modify it under the terms of the GNU General Public License as
11  *      published by the Free Software Foundation; either version 2 of
12  *      the License, or (at your option) any later version.
13  * =====================================================================
14  */
15
16 #include "gigaset.h"
17 #include <linux/crc-ccitt.h>
18
19 //#define GIG_M10x_STUFF_VOICE_DATA
20
21 /* check if byte must be stuffed/escaped
22  * I'm not sure which data should be encoded.
23  * Therefore I will go the hard way and decode every value
24  * less than 0x20, the flag sequence and the control escape char.
25  */
26 static inline int muststuff(unsigned char c)
27 {
28         if (c < PPP_TRANS) return 1;
29         if (c == PPP_FLAG) return 1;
30         if (c == PPP_ESCAPE) return 1;
31         /* other possible candidates: */
32         /* 0x91: XON with parity set */
33         /* 0x93: XOFF with parity set */
34         return 0;
35 }
36
37 /* == data input =========================================================== */
38
39 /* process a block of received bytes in command mode (modem response)
40  * Return value:
41  *      number of processed bytes
42  */
43 static inline int cmd_loop(unsigned char c, unsigned char *src, int numbytes,
44                            struct inbuf_t *inbuf)
45 {
46         struct cardstate *cs = inbuf->cs;
47         unsigned cbytes      = cs->cbytes;
48         int inputstate = inbuf->inputstate;
49         int startbytes = numbytes;
50
51         for (;;) {
52                 cs->respdata[cbytes] = c;
53                 if (c == 10 || c == 13) {
54                         gig_dbg(DEBUG_TRANSCMD, "%s: End of Command (%d Bytes)",
55                                 __func__, cbytes);
56                         cs->cbytes = cbytes;
57                         gigaset_handle_modem_response(cs); /* can change
58                                                               cs->dle */
59                         cbytes = 0;
60
61                         if (cs->dle &&
62                             !(inputstate & INS_DLE_command)) {
63                                 inputstate &= ~INS_command;
64                                 break;
65                         }
66                 } else {
67                         /* advance in line buffer, checking for overflow */
68                         if (cbytes < MAX_RESP_SIZE - 1)
69                                 cbytes++;
70                         else
71                                 dev_warn(cs->dev, "response too large\n");
72                 }
73
74                 if (!numbytes)
75                         break;
76                 c = *src++;
77                 --numbytes;
78                 if (c == DLE_FLAG &&
79                     (cs->dle || inputstate & INS_DLE_command)) {
80                         inputstate |= INS_DLE_char;
81                         break;
82                 }
83         }
84
85         cs->cbytes = cbytes;
86         inbuf->inputstate = inputstate;
87
88         return startbytes - numbytes;
89 }
90
91 /* process a block of received bytes in lock mode (tty i/f)
92  * Return value:
93  *      number of processed bytes
94  */
95 static inline int lock_loop(unsigned char *src, int numbytes,
96                             struct inbuf_t *inbuf)
97 {
98         struct cardstate *cs = inbuf->cs;
99
100         gigaset_dbg_buffer(DEBUG_LOCKCMD, "received response",
101                            numbytes, src, 0);
102         gigaset_if_receive(cs, src, numbytes);
103
104         return numbytes;
105 }
106
107 /* process a block of received bytes in HDLC data mode
108  * Collect HDLC frames, undoing byte stuffing and watching for DLE escapes.
109  * When a frame is complete, check the FCS and pass valid frames to the LL.
110  * If DLE is encountered, return immediately to let the caller handle it.
111  * Return value:
112  *      number of processed bytes
113  *      numbytes (all bytes processed) on error --FIXME
114  */
115 static inline int hdlc_loop(unsigned char c, unsigned char *src, int numbytes,
116                             struct inbuf_t *inbuf)
117 {
118         struct cardstate *cs = inbuf->cs;
119         struct bc_state *bcs = inbuf->bcs;
120         int inputstate;
121         __u16 fcs;
122         struct sk_buff *skb;
123         unsigned char error;
124         struct sk_buff *compskb;
125         int startbytes = numbytes;
126         int l;
127
128         IFNULLRETVAL(bcs, numbytes);
129         inputstate = bcs->inputstate;
130         fcs = bcs->fcs;
131         skb = bcs->skb;
132         IFNULLRETVAL(skb, numbytes);
133
134         if (unlikely(inputstate & INS_byte_stuff)) {
135                 inputstate &= ~INS_byte_stuff;
136                 goto byte_stuff;
137         }
138         for (;;) {
139                 if (unlikely(c == PPP_ESCAPE)) {
140                         if (unlikely(!numbytes)) {
141                                 inputstate |= INS_byte_stuff;
142                                 break;
143                         }
144                         c = *src++;
145                         --numbytes;
146                         if (unlikely(c == DLE_FLAG &&
147                                      (cs->dle ||
148                                       inbuf->inputstate & INS_DLE_command))) {
149                                 inbuf->inputstate |= INS_DLE_char;
150                                 inputstate |= INS_byte_stuff;
151                                 break;
152                         }
153 byte_stuff:
154                         c ^= PPP_TRANS;
155 #ifdef CONFIG_GIGASET_DEBUG
156                         if (unlikely(!muststuff(c)))
157                                 gig_dbg(DEBUG_HDLC, "byte stuffed: 0x%02x", c);
158 #endif
159                 } else if (unlikely(c == PPP_FLAG)) {
160                         if (unlikely(inputstate & INS_skip_frame)) {
161                                 if (!(inputstate & INS_have_data)) { /* 7E 7E */
162 #ifdef CONFIG_GIGASET_DEBUG
163                                         ++bcs->emptycount;
164 #endif
165                                 } else
166                                         gig_dbg(DEBUG_HDLC,
167                                             "7e----------------------------");
168
169                                 /* end of frame */
170                                 error = 1;
171                                 gigaset_rcv_error(NULL, cs, bcs);
172                         } else if (!(inputstate & INS_have_data)) { /* 7E 7E */
173 #ifdef CONFIG_GIGASET_DEBUG
174                                 ++bcs->emptycount;
175 #endif
176                                 break;
177                         } else {
178                                 gig_dbg(DEBUG_HDLC,
179                                         "7e----------------------------");
180
181                                 /* end of frame */
182                                 error = 0;
183
184                                 if (unlikely(fcs != PPP_GOODFCS)) {
185                                         dev_err(cs->dev,
186                                             "Packet checksum at %lu failed, "
187                                             "packet is corrupted (%u bytes)!\n",
188                                             bcs->rcvbytes, skb->len);
189                                         compskb = NULL;
190                                         gigaset_rcv_error(compskb, cs, bcs);
191                                         error = 1;
192                                 } else {
193                                         if (likely((l = skb->len) > 2)) {
194                                                 skb->tail -= 2;
195                                                 skb->len -= 2;
196                                         } else {
197                                                 dev_kfree_skb(skb);
198                                                 skb = NULL;
199                                                 inputstate |= INS_skip_frame;
200                                                 if (l == 1) {
201                                                         dev_err(cs->dev,
202                                                   "invalid packet size (1)!\n");
203                                                         error = 1;
204                                                         gigaset_rcv_error(NULL,
205                                                                 cs, bcs);
206                                                 }
207                                         }
208                                         if (likely(!(error ||
209                                                      (inputstate &
210                                                       INS_skip_frame)))) {
211                                                 gigaset_rcv_skb(skb, cs, bcs);
212                                         }
213                                 }
214                         }
215
216                         if (unlikely(error))
217                                 if (skb)
218                                         dev_kfree_skb(skb);
219
220                         fcs = PPP_INITFCS;
221                         inputstate &= ~(INS_have_data | INS_skip_frame);
222                         if (unlikely(bcs->ignore)) {
223                                 inputstate |= INS_skip_frame;
224                                 skb = NULL;
225                         } else if (likely((skb = dev_alloc_skb(SBUFSIZE + HW_HDR_LEN)) != NULL)) {
226                                 skb_reserve(skb, HW_HDR_LEN);
227                         } else {
228                                 dev_warn(cs->dev,
229                                          "could not allocate new skb\n");
230                                 inputstate |= INS_skip_frame;
231                         }
232
233                         break;
234 #ifdef CONFIG_GIGASET_DEBUG
235                 } else if (unlikely(muststuff(c))) {
236                         /* Should not happen. Possible after ZDLE=1<CR><LF>. */
237                         gig_dbg(DEBUG_HDLC, "not byte stuffed: 0x%02x", c);
238 #endif
239                 }
240
241                 /* add character */
242
243 #ifdef CONFIG_GIGASET_DEBUG
244                 if (unlikely(!(inputstate & INS_have_data))) {
245                         gig_dbg(DEBUG_HDLC, "7e (%d x) ================",
246                                 bcs->emptycount);
247                         bcs->emptycount = 0;
248                 }
249 #endif
250
251                 inputstate |= INS_have_data;
252
253                 if (likely(!(inputstate & INS_skip_frame))) {
254                         if (unlikely(skb->len == SBUFSIZE)) {
255                                 dev_warn(cs->dev, "received packet too long\n");
256                                 dev_kfree_skb_any(skb);
257                                 skb = NULL;
258                                 inputstate |= INS_skip_frame;
259                                 break;
260                         }
261                         *gigaset_skb_put_quick(skb, 1) = c;
262                         /* *__skb_put (skb, 1) = c; */
263                         fcs = crc_ccitt_byte(fcs, c);
264                 }
265
266                 if (unlikely(!numbytes))
267                         break;
268                 c = *src++;
269                 --numbytes;
270                 if (unlikely(c == DLE_FLAG &&
271                              (cs->dle ||
272                               inbuf->inputstate & INS_DLE_command))) {
273                         inbuf->inputstate |= INS_DLE_char;
274                         break;
275                 }
276         }
277         bcs->inputstate = inputstate;
278         bcs->fcs = fcs;
279         bcs->skb = skb;
280         return startbytes - numbytes;
281 }
282
283 /* process a block of received bytes in transparent data mode
284  * Invert bytes, undoing byte stuffing and watching for DLE escapes.
285  * If DLE is encountered, return immediately to let the caller handle it.
286  * Return value:
287  *      number of processed bytes
288  *      numbytes (all bytes processed) on error --FIXME
289  */
290 static inline int iraw_loop(unsigned char c, unsigned char *src, int numbytes,
291                             struct inbuf_t *inbuf)
292 {
293         struct cardstate *cs = inbuf->cs;
294         struct bc_state *bcs = inbuf->bcs;
295         int inputstate;
296         struct sk_buff *skb;
297         int startbytes = numbytes;
298
299         IFNULLRETVAL(bcs, numbytes);
300         inputstate = bcs->inputstate;
301         skb = bcs->skb;
302         IFNULLRETVAL(skb, numbytes);
303
304         for (;;) {
305                 /* add character */
306                 inputstate |= INS_have_data;
307
308                 if (likely(!(inputstate & INS_skip_frame))) {
309                         if (unlikely(skb->len == SBUFSIZE)) {
310                                 //FIXME just pass skb up and allocate a new one
311                                 dev_warn(cs->dev, "received packet too long\n");
312                                 dev_kfree_skb_any(skb);
313                                 skb = NULL;
314                                 inputstate |= INS_skip_frame;
315                                 break;
316                         }
317                         *gigaset_skb_put_quick(skb, 1) = gigaset_invtab[c];
318                 }
319
320                 if (unlikely(!numbytes))
321                         break;
322                 c = *src++;
323                 --numbytes;
324                 if (unlikely(c == DLE_FLAG &&
325                              (cs->dle ||
326                               inbuf->inputstate & INS_DLE_command))) {
327                         inbuf->inputstate |= INS_DLE_char;
328                         break;
329                 }
330         }
331
332         /* pass data up */
333         if (likely(inputstate & INS_have_data)) {
334                 if (likely(!(inputstate & INS_skip_frame))) {
335                         gigaset_rcv_skb(skb, cs, bcs);
336                 }
337                 inputstate &= ~(INS_have_data | INS_skip_frame);
338                 if (unlikely(bcs->ignore)) {
339                         inputstate |= INS_skip_frame;
340                         skb = NULL;
341                 } else if (likely((skb = dev_alloc_skb(SBUFSIZE + HW_HDR_LEN))
342                                   != NULL)) {
343                         skb_reserve(skb, HW_HDR_LEN);
344                 } else {
345                         dev_warn(cs->dev, "could not allocate new skb\n");
346                         inputstate |= INS_skip_frame;
347                 }
348         }
349
350         bcs->inputstate = inputstate;
351         bcs->skb = skb;
352         return startbytes - numbytes;
353 }
354
355 /* process a block of data received from the device
356  */
357 void gigaset_m10x_input(struct inbuf_t *inbuf)
358 {
359         struct cardstate *cs;
360         unsigned tail, head, numbytes;
361         unsigned char *src, c;
362         int procbytes;
363
364         head = atomic_read(&inbuf->head);
365         tail = atomic_read(&inbuf->tail);
366         gig_dbg(DEBUG_INTR, "buffer state: %u -> %u", head, tail);
367
368         if (head != tail) {
369                 cs = inbuf->cs;
370                 src = inbuf->data + head;
371                 numbytes = (head > tail ? RBUFSIZE : tail) - head;
372                 gig_dbg(DEBUG_INTR, "processing %u bytes", numbytes);
373
374                 while (numbytes) {
375                         if (atomic_read(&cs->mstate) == MS_LOCKED) {
376                                 procbytes = lock_loop(src, numbytes, inbuf);
377                                 src += procbytes;
378                                 numbytes -= procbytes;
379                         } else {
380                                 c = *src++;
381                                 --numbytes;
382                                 if (c == DLE_FLAG && (cs->dle ||
383                                     inbuf->inputstate & INS_DLE_command)) {
384                                         if (!(inbuf->inputstate & INS_DLE_char)) {
385                                                 inbuf->inputstate |= INS_DLE_char;
386                                                 goto nextbyte;
387                                         }
388                                         /* <DLE> <DLE> => <DLE> in data stream */
389                                         inbuf->inputstate &= ~INS_DLE_char;
390                                 }
391
392                                 if (!(inbuf->inputstate & INS_DLE_char)) {
393
394                                         /* FIXME use function pointers?  */
395                                         if (inbuf->inputstate & INS_command)
396                                                 procbytes = cmd_loop(c, src, numbytes, inbuf);
397                                         else if (inbuf->bcs->proto2 == ISDN_PROTO_L2_HDLC)
398                                                 procbytes = hdlc_loop(c, src, numbytes, inbuf);
399                                         else
400                                                 procbytes = iraw_loop(c, src, numbytes, inbuf);
401
402                                         src += procbytes;
403                                         numbytes -= procbytes;
404                                 } else {  /* DLE char */
405                                         inbuf->inputstate &= ~INS_DLE_char;
406                                         switch (c) {
407                                         case 'X': /*begin of command*/
408 #ifdef CONFIG_GIGASET_DEBUG
409                                                 if (inbuf->inputstate & INS_command)
410                                                         dev_err(cs->dev,
411                                         "received <DLE> 'X' in command mode\n");
412 #endif
413                                                 inbuf->inputstate |=
414                                                         INS_command | INS_DLE_command;
415                                                 break;
416                                         case '.': /*end of command*/
417 #ifdef CONFIG_GIGASET_DEBUG
418                                                 if (!(inbuf->inputstate & INS_command))
419                                                         dev_err(cs->dev,
420                                         "received <DLE> '.' in hdlc mode\n");
421 #endif
422                                                 inbuf->inputstate &= cs->dle ?
423                                                         ~(INS_DLE_command|INS_command)
424                                                         : ~INS_DLE_command;
425                                                 break;
426                                         //case DLE_FLAG: /*DLE_FLAG in data stream*/ /* schon oben behandelt! */
427                                         default:
428                                                 dev_err(cs->dev,
429                                                       "received 0x10 0x%02x!\n",
430                                                         (int) c);
431                                                 /* FIXME: reset driver?? */
432                                         }
433                                 }
434                         }
435 nextbyte:
436                         if (!numbytes) {
437                                 /* end of buffer, check for wrap */
438                                 if (head > tail) {
439                                         head = 0;
440                                         src = inbuf->data;
441                                         numbytes = tail;
442                                 } else {
443                                         head = tail;
444                                         break;
445                                 }
446                         }
447                 }
448
449                 gig_dbg(DEBUG_INTR, "setting head to %u", head);
450                 atomic_set(&inbuf->head, head);
451         }
452 }
453
454
455 /* == data output ========================================================== */
456
457 /* Encoding of a PPP packet into an octet stuffed HDLC frame
458  * with FCS, opening and closing flags.
459  * parameters:
460  *      skb     skb containing original packet (freed upon return)
461  *      head    number of headroom bytes to allocate in result skb
462  *      tail    number of tailroom bytes to allocate in result skb
463  * Return value:
464  *      pointer to newly allocated skb containing the result frame
465  */
466 static struct sk_buff *HDLC_Encode(struct sk_buff *skb, int head, int tail)
467 {
468         struct sk_buff *hdlc_skb;
469         __u16 fcs;
470         unsigned char c;
471         unsigned char *cp;
472         int len;
473         unsigned int stuf_cnt;
474
475         stuf_cnt = 0;
476         fcs = PPP_INITFCS;
477         cp = skb->data;
478         len = skb->len;
479         while (len--) {
480                 if (muststuff(*cp))
481                         stuf_cnt++;
482                 fcs = crc_ccitt_byte(fcs, *cp++);
483         }
484         fcs ^= 0xffff;                  /* complement */
485
486         /* size of new buffer: original size + number of stuffing bytes
487          * + 2 bytes FCS + 2 stuffing bytes for FCS (if needed) + 2 flag bytes
488          */
489         hdlc_skb = dev_alloc_skb(skb->len + stuf_cnt + 6 + tail + head);
490         if (!hdlc_skb) {
491                 dev_kfree_skb(skb);
492                 return NULL;
493         }
494         skb_reserve(hdlc_skb, head);
495
496         /* Copy acknowledge request into new skb */
497         memcpy(hdlc_skb->head, skb->head, 2);
498
499         /* Add flag sequence in front of everything.. */
500         *(skb_put(hdlc_skb, 1)) = PPP_FLAG;
501
502         /* Perform byte stuffing while copying data. */
503         while (skb->len--) {
504                 if (muststuff(*skb->data)) {
505                         *(skb_put(hdlc_skb, 1)) = PPP_ESCAPE;
506                         *(skb_put(hdlc_skb, 1)) = (*skb->data++) ^ PPP_TRANS;
507                 } else
508                         *(skb_put(hdlc_skb, 1)) = *skb->data++;
509         }
510
511         /* Finally add FCS (byte stuffed) and flag sequence */
512         c = (fcs & 0x00ff);     /* least significant byte first */
513         if (muststuff(c)) {
514                 *(skb_put(hdlc_skb, 1)) = PPP_ESCAPE;
515                 c ^= PPP_TRANS;
516         }
517         *(skb_put(hdlc_skb, 1)) = c;
518
519         c = ((fcs >> 8) & 0x00ff);
520         if (muststuff(c)) {
521                 *(skb_put(hdlc_skb, 1)) = PPP_ESCAPE;
522                 c ^= PPP_TRANS;
523         }
524         *(skb_put(hdlc_skb, 1)) = c;
525
526         *(skb_put(hdlc_skb, 1)) = PPP_FLAG;
527
528         dev_kfree_skb(skb);
529         return hdlc_skb;
530 }
531
532 /* Encoding of a raw packet into an octet stuffed bit inverted frame
533  * parameters:
534  *      skb     skb containing original packet (freed upon return)
535  *      head    number of headroom bytes to allocate in result skb
536  *      tail    number of tailroom bytes to allocate in result skb
537  * Return value:
538  *      pointer to newly allocated skb containing the result frame
539  */
540 static struct sk_buff *iraw_encode(struct sk_buff *skb, int head, int tail)
541 {
542         struct sk_buff *iraw_skb;
543         unsigned char c;
544         unsigned char *cp;
545         int len;
546
547         /* worst case: every byte must be stuffed */
548         iraw_skb = dev_alloc_skb(2*skb->len + tail + head);
549         if (!iraw_skb) {
550                 dev_kfree_skb(skb);
551                 return NULL;
552         }
553         skb_reserve(iraw_skb, head);
554
555         cp = skb->data;
556         len = skb->len;
557         while (len--) {
558                 c = gigaset_invtab[*cp++];
559                 if (c == DLE_FLAG)
560                         *(skb_put(iraw_skb, 1)) = c;
561                 *(skb_put(iraw_skb, 1)) = c;
562         }
563         dev_kfree_skb(skb);
564         return iraw_skb;
565 }
566
567 /* gigaset_send_skb
568  * called by common.c to queue an skb for sending
569  * and start transmission if necessary
570  * parameters:
571  *      B Channel control structure
572  *      skb
573  * Return value:
574  *      number of bytes accepted for sending
575  *      (skb->len if ok, 0 if out of buffer space)
576  *      or error code (< 0, eg. -EINVAL)
577  */
578 int gigaset_m10x_send_skb(struct bc_state *bcs, struct sk_buff *skb)
579 {
580         unsigned len;
581
582         IFNULLRETVAL(bcs, -EFAULT);
583         IFNULLRETVAL(skb, -EFAULT);
584         len = skb->len;
585
586         if (bcs->proto2 == ISDN_PROTO_L2_HDLC)
587                 skb = HDLC_Encode(skb, HW_HDR_LEN, 0);
588         else
589                 skb = iraw_encode(skb, HW_HDR_LEN, 0);
590         if (!skb) {
591                 dev_err(bcs->cs->dev,
592                         "unable to allocate memory for encoding!\n");
593                 return -ENOMEM;
594         }
595
596         skb_queue_tail(&bcs->squeue, skb);
597         tasklet_schedule(&bcs->cs->write_tasklet);
598
599         return len;     /* ok so far */
600 }