Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/geert/linux...
[sfrench/cifs-2.6.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 encode 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
39  * (mstate != MS_LOCKED && (inputstate & INS_command))
40  * Append received bytes to the command response buffer and forward them
41  * line by line to the response handler. Exit whenever a mode/state change
42  * might have occurred.
43  * Return value:
44  *      number of processed bytes
45  */
46 static unsigned cmd_loop(unsigned numbytes, struct inbuf_t *inbuf)
47 {
48         unsigned char *src = inbuf->data + inbuf->head;
49         struct cardstate *cs = inbuf->cs;
50         unsigned cbytes = cs->cbytes;
51         unsigned procbytes = 0;
52         unsigned char c;
53
54         while (procbytes < numbytes) {
55                 c = *src++;
56                 procbytes++;
57
58                 switch (c) {
59                 case '\n':
60                         if (cbytes == 0 && cs->respdata[0] == '\r') {
61                                 /* collapse LF with preceding CR */
62                                 cs->respdata[0] = 0;
63                                 break;
64                         }
65                         /* --v-- fall through --v-- */
66                 case '\r':
67                         /* end of message line, pass to response handler */
68                         gig_dbg(DEBUG_TRANSCMD, "%s: End of Message (%d Bytes)",
69                                 __func__, cbytes);
70                         if (cbytes >= MAX_RESP_SIZE) {
71                                 dev_warn(cs->dev, "response too large (%d)\n",
72                                          cbytes);
73                                 cbytes = MAX_RESP_SIZE;
74                         }
75                         cs->cbytes = cbytes;
76                         gigaset_handle_modem_response(cs);
77                         cbytes = 0;
78
79                         /* store EOL byte for CRLF collapsing */
80                         cs->respdata[0] = c;
81
82                         /* cs->dle may have changed */
83                         if (cs->dle && !(inbuf->inputstate & INS_DLE_command))
84                                 inbuf->inputstate &= ~INS_command;
85
86                         /* return for reevaluating state */
87                         goto exit;
88
89                 case DLE_FLAG:
90                         if (inbuf->inputstate & INS_DLE_char) {
91                                 /* quoted DLE: clear quote flag */
92                                 inbuf->inputstate &= ~INS_DLE_char;
93                         } else if (cs->dle ||
94                                    (inbuf->inputstate & INS_DLE_command)) {
95                                 /* DLE escape, pass up for handling */
96                                 inbuf->inputstate |= INS_DLE_char;
97                                 goto exit;
98                         }
99                         /* quoted or not in DLE mode: treat as regular data */
100                         /* --v-- fall through --v-- */
101                 default:
102                         /* append to line buffer if possible */
103                         if (cbytes < MAX_RESP_SIZE)
104                                 cs->respdata[cbytes] = c;
105                         cbytes++;
106                 }
107         }
108 exit:
109         cs->cbytes = cbytes;
110         return procbytes;
111 }
112
113 /* process a block of received bytes in lock mode
114  * All received bytes are passed unmodified to the tty i/f.
115  * Return value:
116  *      number of processed bytes
117  */
118 static unsigned lock_loop(unsigned numbytes, struct inbuf_t *inbuf)
119 {
120         unsigned char *src = inbuf->data + inbuf->head;
121
122         gigaset_dbg_buffer(DEBUG_LOCKCMD, "received response", numbytes, src);
123         gigaset_if_receive(inbuf->cs, src, numbytes);
124         return numbytes;
125 }
126
127 /* set up next receive skb for data mode
128  */
129 static void new_rcv_skb(struct bc_state *bcs)
130 {
131         struct cardstate *cs = bcs->cs;
132         unsigned short hw_hdr_len = cs->hw_hdr_len;
133
134         if (bcs->ignore) {
135                 bcs->skb = NULL;
136                 return;
137         }
138
139         bcs->skb = dev_alloc_skb(SBUFSIZE + hw_hdr_len);
140         if (bcs->skb == NULL) {
141                 dev_warn(cs->dev, "could not allocate new skb\n");
142                 return;
143         }
144         skb_reserve(bcs->skb, hw_hdr_len);
145 }
146
147 /* process a block of received bytes in HDLC data mode
148  * (mstate != MS_LOCKED && !(inputstate & INS_command) && proto2 == L2_HDLC)
149  * Collect HDLC frames, undoing byte stuffing and watching for DLE escapes.
150  * When a frame is complete, check the FCS and pass valid frames to the LL.
151  * If DLE is encountered, return immediately to let the caller handle it.
152  * Return value:
153  *      number of processed bytes
154  */
155 static unsigned hdlc_loop(unsigned numbytes, struct inbuf_t *inbuf)
156 {
157         struct cardstate *cs = inbuf->cs;
158         struct bc_state *bcs = cs->bcs;
159         int inputstate = bcs->inputstate;
160         __u16 fcs = bcs->fcs;
161         struct sk_buff *skb = bcs->skb;
162         unsigned char *src = inbuf->data + inbuf->head;
163         unsigned procbytes = 0;
164         unsigned char c;
165
166         if (inputstate & INS_byte_stuff) {
167                 if (!numbytes)
168                         return 0;
169                 inputstate &= ~INS_byte_stuff;
170                 goto byte_stuff;
171         }
172
173         while (procbytes < numbytes) {
174                 c = *src++;
175                 procbytes++;
176                 if (c == DLE_FLAG) {
177                         if (inputstate & INS_DLE_char) {
178                                 /* quoted DLE: clear quote flag */
179                                 inputstate &= ~INS_DLE_char;
180                         } else if (cs->dle || (inputstate & INS_DLE_command)) {
181                                 /* DLE escape, pass up for handling */
182                                 inputstate |= INS_DLE_char;
183                                 break;
184                         }
185                 }
186
187                 if (c == PPP_ESCAPE) {
188                         /* byte stuffing indicator: pull in next byte */
189                         if (procbytes >= numbytes) {
190                                 /* end of buffer, save for later processing */
191                                 inputstate |= INS_byte_stuff;
192                                 break;
193                         }
194 byte_stuff:
195                         c = *src++;
196                         procbytes++;
197                         if (c == DLE_FLAG) {
198                                 if (inputstate & INS_DLE_char) {
199                                         /* quoted DLE: clear quote flag */
200                                         inputstate &= ~INS_DLE_char;
201                                 } else if (cs->dle ||
202                                            (inputstate & INS_DLE_command)) {
203                                         /* DLE escape, pass up for handling */
204                                         inputstate |=
205                                                 INS_DLE_char | INS_byte_stuff;
206                                         break;
207                                 }
208                         }
209                         c ^= PPP_TRANS;
210 #ifdef CONFIG_GIGASET_DEBUG
211                         if (!muststuff(c))
212                                 gig_dbg(DEBUG_HDLC, "byte stuffed: 0x%02x", c);
213 #endif
214                 } else if (c == PPP_FLAG) {
215                         /* end of frame: process content if any */
216                         if (inputstate & INS_have_data) {
217                                 gig_dbg(DEBUG_HDLC,
218                                         "7e----------------------------");
219
220                                 /* check and pass received frame */
221                                 if (!skb) {
222                                         /* skipped frame */
223                                         gigaset_isdn_rcv_err(bcs);
224                                 } else if (skb->len < 2) {
225                                         /* frame too short for FCS */
226                                         dev_warn(cs->dev,
227                                                  "short frame (%d)\n",
228                                                  skb->len);
229                                         gigaset_isdn_rcv_err(bcs);
230                                         dev_kfree_skb_any(skb);
231                                 } else if (fcs != PPP_GOODFCS) {
232                                         /* frame check error */
233                                         dev_err(cs->dev,
234                                 "Checksum failed, %u bytes corrupted!\n",
235                                                 skb->len);
236                                         gigaset_isdn_rcv_err(bcs);
237                                         dev_kfree_skb_any(skb);
238                                 } else {
239                                         /* good frame */
240                                         __skb_trim(skb, skb->len - 2);
241                                         gigaset_skb_rcvd(bcs, skb);
242                                 }
243
244                                 /* prepare reception of next frame */
245                                 inputstate &= ~INS_have_data;
246                                 new_rcv_skb(bcs);
247                                 skb = bcs->skb;
248                         } else {
249                                 /* empty frame (7E 7E) */
250 #ifdef CONFIG_GIGASET_DEBUG
251                                 ++bcs->emptycount;
252 #endif
253                                 if (!skb) {
254                                         /* skipped (?) */
255                                         gigaset_isdn_rcv_err(bcs);
256                                         new_rcv_skb(bcs);
257                                         skb = bcs->skb;
258                                 }
259                         }
260
261                         fcs = PPP_INITFCS;
262                         continue;
263 #ifdef CONFIG_GIGASET_DEBUG
264                 } else if (muststuff(c)) {
265                         /* Should not happen. Possible after ZDLE=1<CR><LF>. */
266                         gig_dbg(DEBUG_HDLC, "not byte stuffed: 0x%02x", c);
267 #endif
268                 }
269
270                 /* regular data byte, append to skb */
271 #ifdef CONFIG_GIGASET_DEBUG
272                 if (!(inputstate & INS_have_data)) {
273                         gig_dbg(DEBUG_HDLC, "7e (%d x) ================",
274                                 bcs->emptycount);
275                         bcs->emptycount = 0;
276                 }
277 #endif
278                 inputstate |= INS_have_data;
279                 if (skb) {
280                         if (skb->len == SBUFSIZE) {
281                                 dev_warn(cs->dev, "received packet too long\n");
282                                 dev_kfree_skb_any(skb);
283                                 /* skip remainder of packet */
284                                 bcs->skb = skb = NULL;
285                         } else {
286                                 *__skb_put(skb, 1) = c;
287                                 fcs = crc_ccitt_byte(fcs, c);
288                         }
289                 }
290         }
291
292         bcs->inputstate = inputstate;
293         bcs->fcs = fcs;
294         return procbytes;
295 }
296
297 /* process a block of received bytes in transparent data mode
298  * (mstate != MS_LOCKED && !(inputstate & INS_command) && proto2 != L2_HDLC)
299  * Invert bytes, undoing byte stuffing and watching for DLE escapes.
300  * If DLE is encountered, return immediately to let the caller handle it.
301  * Return value:
302  *      number of processed bytes
303  */
304 static unsigned iraw_loop(unsigned numbytes, struct inbuf_t *inbuf)
305 {
306         struct cardstate *cs = inbuf->cs;
307         struct bc_state *bcs = cs->bcs;
308         int inputstate = bcs->inputstate;
309         struct sk_buff *skb = bcs->skb;
310         unsigned char *src = inbuf->data + inbuf->head;
311         unsigned procbytes = 0;
312         unsigned char c;
313
314         if (!skb) {
315                 /* skip this block */
316                 new_rcv_skb(bcs);
317                 return numbytes;
318         }
319
320         while (procbytes < numbytes && skb->len < SBUFSIZE) {
321                 c = *src++;
322                 procbytes++;
323
324                 if (c == DLE_FLAG) {
325                         if (inputstate & INS_DLE_char) {
326                                 /* quoted DLE: clear quote flag */
327                                 inputstate &= ~INS_DLE_char;
328                         } else if (cs->dle || (inputstate & INS_DLE_command)) {
329                                 /* DLE escape, pass up for handling */
330                                 inputstate |= INS_DLE_char;
331                                 break;
332                         }
333                 }
334
335                 /* regular data byte: append to current skb */
336                 inputstate |= INS_have_data;
337                 *__skb_put(skb, 1) = bitrev8(c);
338         }
339
340         /* pass data up */
341         if (inputstate & INS_have_data) {
342                 gigaset_skb_rcvd(bcs, skb);
343                 inputstate &= ~INS_have_data;
344                 new_rcv_skb(bcs);
345         }
346
347         bcs->inputstate = inputstate;
348         return procbytes;
349 }
350
351 /* process DLE escapes
352  * Called whenever a DLE sequence might be encountered in the input stream.
353  * Either processes the entire DLE sequence or, if that isn't possible,
354  * notes the fact that an initial DLE has been received in the INS_DLE_char
355  * inputstate flag and resumes processing of the sequence on the next call.
356  */
357 static void handle_dle(struct inbuf_t *inbuf)
358 {
359         struct cardstate *cs = inbuf->cs;
360
361         if (cs->mstate == MS_LOCKED)
362                 return;         /* no DLE processing in lock mode */
363
364         if (!(inbuf->inputstate & INS_DLE_char)) {
365                 /* no DLE pending */
366                 if (inbuf->data[inbuf->head] == DLE_FLAG &&
367                     (cs->dle || inbuf->inputstate & INS_DLE_command)) {
368                         /* start of DLE sequence */
369                         inbuf->head++;
370                         if (inbuf->head == inbuf->tail ||
371                             inbuf->head == RBUFSIZE) {
372                                 /* end of buffer, save for later processing */
373                                 inbuf->inputstate |= INS_DLE_char;
374                                 return;
375                         }
376                 } else {
377                         /* regular data byte */
378                         return;
379                 }
380         }
381
382         /* consume pending DLE */
383         inbuf->inputstate &= ~INS_DLE_char;
384
385         switch (inbuf->data[inbuf->head]) {
386         case 'X':       /* begin of event message */
387                 if (inbuf->inputstate & INS_command)
388                         dev_notice(cs->dev,
389                                    "received <DLE>X in command mode\n");
390                 inbuf->inputstate |= INS_command | INS_DLE_command;
391                 inbuf->head++;  /* byte consumed */
392                 break;
393         case '.':       /* end of event message */
394                 if (!(inbuf->inputstate & INS_DLE_command))
395                         dev_notice(cs->dev,
396                                    "received <DLE>. without <DLE>X\n");
397                 inbuf->inputstate &= ~INS_DLE_command;
398                 /* return to data mode if in DLE mode */
399                 if (cs->dle)
400                         inbuf->inputstate &= ~INS_command;
401                 inbuf->head++;  /* byte consumed */
402                 break;
403         case DLE_FLAG:  /* DLE in data stream */
404                 /* mark as quoted */
405                 inbuf->inputstate |= INS_DLE_char;
406                 if (!(cs->dle || inbuf->inputstate & INS_DLE_command))
407                         dev_notice(cs->dev,
408                                    "received <DLE><DLE> not in DLE mode\n");
409                 break;  /* quoted byte left in buffer */
410         default:
411                 dev_notice(cs->dev, "received <DLE><%02x>\n",
412                            inbuf->data[inbuf->head]);
413                 /* quoted byte left in buffer */
414         }
415 }
416
417 /**
418  * gigaset_m10x_input() - process a block of data received from the device
419  * @inbuf:      received data and device descriptor structure.
420  *
421  * Called by hardware module {ser,usb}_gigaset with a block of received
422  * bytes. Separates the bytes received over the serial data channel into
423  * user data and command replies (locked/unlocked) according to the
424  * current state of the interface.
425  */
426 void gigaset_m10x_input(struct inbuf_t *inbuf)
427 {
428         struct cardstate *cs = inbuf->cs;
429         unsigned numbytes, procbytes;
430
431         gig_dbg(DEBUG_INTR, "buffer state: %u -> %u", inbuf->head, inbuf->tail);
432
433         while (inbuf->head != inbuf->tail) {
434                 /* check for DLE escape */
435                 handle_dle(inbuf);
436
437                 /* process a contiguous block of bytes */
438                 numbytes = (inbuf->head > inbuf->tail ?
439                             RBUFSIZE : inbuf->tail) - inbuf->head;
440                 gig_dbg(DEBUG_INTR, "processing %u bytes", numbytes);
441                 /*
442                  * numbytes may be 0 if handle_dle() ate the last byte.
443                  * This does no harm, *_loop() will just return 0 immediately.
444                  */
445
446                 if (cs->mstate == MS_LOCKED)
447                         procbytes = lock_loop(numbytes, inbuf);
448                 else if (inbuf->inputstate & INS_command)
449                         procbytes = cmd_loop(numbytes, inbuf);
450                 else if (cs->bcs->proto2 == L2_HDLC)
451                         procbytes = hdlc_loop(numbytes, inbuf);
452                 else
453                         procbytes = iraw_loop(numbytes, inbuf);
454                 inbuf->head += procbytes;
455
456                 /* check for buffer wraparound */
457                 if (inbuf->head >= RBUFSIZE)
458                         inbuf->head = 0;
459
460                 gig_dbg(DEBUG_INTR, "head set to %u", inbuf->head);
461         }
462 }
463 EXPORT_SYMBOL_GPL(gigaset_m10x_input);
464
465
466 /* == data output ========================================================== */
467
468 /*
469  * Encode a data packet into an octet stuffed HDLC frame with FCS,
470  * opening and closing flags, preserving headroom data.
471  * parameters:
472  *      skb             skb containing original packet (freed upon return)
473  * Return value:
474  *      pointer to newly allocated skb containing the result frame
475  *      and the original link layer header, NULL on error
476  */
477 static struct sk_buff *HDLC_Encode(struct sk_buff *skb)
478 {
479         struct sk_buff *hdlc_skb;
480         __u16 fcs;
481         unsigned char c;
482         unsigned char *cp;
483         int len;
484         unsigned int stuf_cnt;
485
486         stuf_cnt = 0;
487         fcs = PPP_INITFCS;
488         cp = skb->data;
489         len = skb->len;
490         while (len--) {
491                 if (muststuff(*cp))
492                         stuf_cnt++;
493                 fcs = crc_ccitt_byte(fcs, *cp++);
494         }
495         fcs ^= 0xffff;                  /* complement */
496
497         /* size of new buffer: original size + number of stuffing bytes
498          * + 2 bytes FCS + 2 stuffing bytes for FCS (if needed) + 2 flag bytes
499          * + room for link layer header
500          */
501         hdlc_skb = dev_alloc_skb(skb->len + stuf_cnt + 6 + skb->mac_len);
502         if (!hdlc_skb) {
503                 dev_kfree_skb_any(skb);
504                 return NULL;
505         }
506
507         /* Copy link layer header into new skb */
508         skb_reset_mac_header(hdlc_skb);
509         skb_reserve(hdlc_skb, skb->mac_len);
510         memcpy(skb_mac_header(hdlc_skb), skb_mac_header(skb), skb->mac_len);
511         hdlc_skb->mac_len = skb->mac_len;
512
513         /* Add flag sequence in front of everything.. */
514         *(skb_put(hdlc_skb, 1)) = PPP_FLAG;
515
516         /* Perform byte stuffing while copying data. */
517         while (skb->len--) {
518                 if (muststuff(*skb->data)) {
519                         *(skb_put(hdlc_skb, 1)) = PPP_ESCAPE;
520                         *(skb_put(hdlc_skb, 1)) = (*skb->data++) ^ PPP_TRANS;
521                 } else
522                         *(skb_put(hdlc_skb, 1)) = *skb->data++;
523         }
524
525         /* Finally add FCS (byte stuffed) and flag sequence */
526         c = (fcs & 0x00ff);     /* least significant byte first */
527         if (muststuff(c)) {
528                 *(skb_put(hdlc_skb, 1)) = PPP_ESCAPE;
529                 c ^= PPP_TRANS;
530         }
531         *(skb_put(hdlc_skb, 1)) = c;
532
533         c = ((fcs >> 8) & 0x00ff);
534         if (muststuff(c)) {
535                 *(skb_put(hdlc_skb, 1)) = PPP_ESCAPE;
536                 c ^= PPP_TRANS;
537         }
538         *(skb_put(hdlc_skb, 1)) = c;
539
540         *(skb_put(hdlc_skb, 1)) = PPP_FLAG;
541
542         dev_kfree_skb_any(skb);
543         return hdlc_skb;
544 }
545
546 /*
547  * Encode a data packet into an octet stuffed raw bit inverted frame,
548  * preserving headroom data.
549  * parameters:
550  *      skb             skb containing original packet (freed upon return)
551  * Return value:
552  *      pointer to newly allocated skb containing the result frame
553  *      and the original link layer header, NULL on error
554  */
555 static struct sk_buff *iraw_encode(struct sk_buff *skb)
556 {
557         struct sk_buff *iraw_skb;
558         unsigned char c;
559         unsigned char *cp;
560         int len;
561
562         /* size of new buffer (worst case = every byte must be stuffed):
563          * 2 * original size + room for link layer header
564          */
565         iraw_skb = dev_alloc_skb(2*skb->len + skb->mac_len);
566         if (!iraw_skb) {
567                 dev_kfree_skb_any(skb);
568                 return NULL;
569         }
570
571         /* copy link layer header into new skb */
572         skb_reset_mac_header(iraw_skb);
573         skb_reserve(iraw_skb, skb->mac_len);
574         memcpy(skb_mac_header(iraw_skb), skb_mac_header(skb), skb->mac_len);
575         iraw_skb->mac_len = skb->mac_len;
576
577         /* copy and stuff data */
578         cp = skb->data;
579         len = skb->len;
580         while (len--) {
581                 c = bitrev8(*cp++);
582                 if (c == DLE_FLAG)
583                         *(skb_put(iraw_skb, 1)) = c;
584                 *(skb_put(iraw_skb, 1)) = c;
585         }
586         dev_kfree_skb_any(skb);
587         return iraw_skb;
588 }
589
590 /**
591  * gigaset_m10x_send_skb() - queue an skb for sending
592  * @bcs:        B channel descriptor structure.
593  * @skb:        data to send.
594  *
595  * Called by LL to encode and queue an skb for sending, and start
596  * transmission if necessary.
597  * Once the payload data has been transmitted completely, gigaset_skb_sent()
598  * will be called with the skb's link layer header preserved.
599  *
600  * Return value:
601  *      number of bytes accepted for sending (skb->len) if ok,
602  *      error code < 0 (eg. -ENOMEM) on error
603  */
604 int gigaset_m10x_send_skb(struct bc_state *bcs, struct sk_buff *skb)
605 {
606         struct cardstate *cs = bcs->cs;
607         unsigned len = skb->len;
608         unsigned long flags;
609
610         if (bcs->proto2 == L2_HDLC)
611                 skb = HDLC_Encode(skb);
612         else
613                 skb = iraw_encode(skb);
614         if (!skb) {
615                 dev_err(cs->dev,
616                         "unable to allocate memory for encoding!\n");
617                 return -ENOMEM;
618         }
619
620         skb_queue_tail(&bcs->squeue, skb);
621         spin_lock_irqsave(&cs->lock, flags);
622         if (cs->connected)
623                 tasklet_schedule(&cs->write_tasklet);
624         spin_unlock_irqrestore(&cs->lock, flags);
625
626         return len;     /* ok so far */
627 }
628 EXPORT_SYMBOL_GPL(gigaset_m10x_send_skb);