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