Pull ticket4byte into release branch
[platform/adaptation/renesas_rcar/renesas_kernel.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.
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 #include <linux/bitrev.h>
19
20 /* check if byte must be stuffed/escaped
21  * I'm not sure which data should be encoded.
22  * Therefore I will go the hard way and decode every value
23  * less than 0x20, the flag sequence and the control escape char.
24  */
25 static 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         /* other possible candidates: */
31         /* 0x91: XON with parity set */
32         /* 0x93: XOFF with parity set */
33         return 0;
34 }
35
36 /* == data input =========================================================== */
37
38 /* process a block of received bytes in command mode (modem response)
39  * Return value:
40  *      number of processed bytes
41  */
42 static 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); /* can change
57                                                               cs->dle */
58                         cbytes = 0;
59
60                         if (cs->dle &&
61                             !(inputstate & INS_DLE_command)) {
62                                 inputstate &= ~INS_command;
63                                 break;
64                         }
65                 } else {
66                         /* advance in line buffer, checking for overflow */
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 /* process a block of received bytes in lock mode (tty i/f)
91  * Return value:
92  *      number of processed bytes
93  */
94 static 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 /* process a block of received bytes in HDLC data mode
107  * Collect HDLC frames, undoing byte stuffing and watching for DLE escapes.
108  * When a frame is complete, check the FCS and pass valid frames to the LL.
109  * If DLE is encountered, return immediately to let the caller handle it.
110  * Return value:
111  *      number of processed bytes
112  *      numbytes (all bytes processed) on error --FIXME
113  */
114 static 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                         }
146 byte_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)) { /* 7E 7E */
154                                         ++bcs->emptycount;
155                                 } else
156                                         gig_dbg(DEBUG_HDLC,
157                                             "7e----------------------------");
158 #endif
159
160                                 /* end of frame */
161                                 error = 1;
162                                 gigaset_rcv_error(NULL, cs, bcs);
163                         } else if (!(inputstate & INS_have_data)) { /* 7E 7E */
164 #ifdef CONFIG_GIGASET_DEBUG
165                                 ++bcs->emptycount;
166 #endif
167                                 break;
168                         } else {
169                                 gig_dbg(DEBUG_HDLC,
170                                         "7e----------------------------");
171
172                                 /* end of frame */
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                         /* Should not happen. Possible after ZDLE=1<CR><LF>. */
226                         gig_dbg(DEBUG_HDLC, "not byte stuffed: 0x%02x", c);
227                 }
228
229                 /* add character */
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 /* process a block of received bytes in transparent data mode
271  * Invert bytes, undoing byte stuffing and watching for DLE escapes.
272  * If DLE is encountered, return immediately to let the caller handle it.
273  * Return value:
274  *      number of processed bytes
275  *      numbytes (all bytes processed) on error --FIXME
276  */
277 static 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                 /* add character */
288                 inputstate |= INS_have_data;
289
290                 if (likely(!(inputstate & INS_skip_frame))) {
291                         if (unlikely(skb->len == SBUFSIZE)) {
292                                 //FIXME just pass skb up and allocate a new one
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         /* pass data up */
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  * gigaset_m10x_input() - process a block of data received from the device
339  * @inbuf:      received data and device descriptor structure.
340  *
341  * Called by hardware module {ser,usb}_gigaset with a block of received
342  * bytes. Separates the bytes received over the serial data channel into
343  * user data and command replies (locked/unlocked) according to the
344  * current state of the interface.
345  */
346 void 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                                         /* <DLE> <DLE> => <DLE> in data stream */
378                                         inbuf->inputstate &= ~INS_DLE_char;
379                                 }
380
381                                 if (!(inbuf->inputstate & INS_DLE_char)) {
382
383                                         /* FIXME use function pointers?  */
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 {  /* DLE char */
394                                         inbuf->inputstate &= ~INS_DLE_char;
395                                         switch (c) {
396                                         case 'X': /*begin of command*/
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 '.': /*end of command*/
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                                         //case DLE_FLAG: /*DLE_FLAG in data stream*/ /* schon oben behandelt! */
412                                         default:
413                                                 dev_err(cs->dev,
414                                                       "received 0x10 0x%02x!\n",
415                                                         (int) c);
416                                                 /* FIXME: reset driver?? */
417                                         }
418                                 }
419                         }
420 nextbyte:
421                         if (!numbytes) {
422                                 /* end of buffer, check for wrap */
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 }
438 EXPORT_SYMBOL_GPL(gigaset_m10x_input);
439
440
441 /* == data output ========================================================== */
442
443 /* Encoding of a PPP packet into an octet stuffed HDLC frame
444  * with FCS, opening and closing flags.
445  * parameters:
446  *      skb     skb containing original packet (freed upon return)
447  *      head    number of headroom bytes to allocate in result skb
448  *      tail    number of tailroom bytes to allocate in result skb
449  * Return value:
450  *      pointer to newly allocated skb containing the result frame
451  */
452 static 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;                  /* complement */
471
472         /* size of new buffer: original size + number of stuffing bytes
473          * + 2 bytes FCS + 2 stuffing bytes for FCS (if needed) + 2 flag bytes
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         /* Copy acknowledge request into new skb */
483         memcpy(hdlc_skb->head, skb->head, 2);
484
485         /* Add flag sequence in front of everything.. */
486         *(skb_put(hdlc_skb, 1)) = PPP_FLAG;
487
488         /* Perform byte stuffing while copying data. */
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         /* Finally add FCS (byte stuffed) and flag sequence */
498         c = (fcs & 0x00ff);     /* least significant byte first */
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 /* Encoding of a raw packet into an octet stuffed bit inverted frame
519  * parameters:
520  *      skb     skb containing original packet (freed upon return)
521  *      head    number of headroom bytes to allocate in result skb
522  *      tail    number of tailroom bytes to allocate in result skb
523  * Return value:
524  *      pointer to newly allocated skb containing the result frame
525  */
526 static 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         /* worst case: every byte must be stuffed */
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  * gigaset_m10x_send_skb() - queue an skb for sending
555  * @bcs:        B channel descriptor structure.
556  * @skb:        data to send.
557  *
558  * Called by i4l.c to encode and queue an skb for sending, and start
559  * transmission if necessary.
560  *
561  * Return value:
562  *      number of bytes accepted for sending (skb->len) if ok,
563  *      error code < 0 (eg. -ENOMEM) on error
564  */
565 int 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;     /* ok so far */
587 }
588 EXPORT_SYMBOL_GPL(gigaset_m10x_send_skb);