HID: fix possible deadlock in hidraw_read
[cascardo/linux.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 /* process a block of data received from the device
338  */
339 void gigaset_m10x_input(struct inbuf_t *inbuf)
340 {
341         struct cardstate *cs;
342         unsigned tail, head, numbytes;
343         unsigned char *src, c;
344         int procbytes;
345
346         head = inbuf->head;
347         tail = inbuf->tail;
348         gig_dbg(DEBUG_INTR, "buffer state: %u -> %u", head, tail);
349
350         if (head != tail) {
351                 cs = inbuf->cs;
352                 src = inbuf->data + head;
353                 numbytes = (head > tail ? RBUFSIZE : tail) - head;
354                 gig_dbg(DEBUG_INTR, "processing %u bytes", numbytes);
355
356                 while (numbytes) {
357                         if (cs->mstate == MS_LOCKED) {
358                                 procbytes = lock_loop(src, numbytes, inbuf);
359                                 src += procbytes;
360                                 numbytes -= procbytes;
361                         } else {
362                                 c = *src++;
363                                 --numbytes;
364                                 if (c == DLE_FLAG && (cs->dle ||
365                                     inbuf->inputstate & INS_DLE_command)) {
366                                         if (!(inbuf->inputstate & INS_DLE_char)) {
367                                                 inbuf->inputstate |= INS_DLE_char;
368                                                 goto nextbyte;
369                                         }
370                                         /* <DLE> <DLE> => <DLE> in data stream */
371                                         inbuf->inputstate &= ~INS_DLE_char;
372                                 }
373
374                                 if (!(inbuf->inputstate & INS_DLE_char)) {
375
376                                         /* FIXME use function pointers?  */
377                                         if (inbuf->inputstate & INS_command)
378                                                 procbytes = cmd_loop(c, src, numbytes, inbuf);
379                                         else if (inbuf->bcs->proto2 == ISDN_PROTO_L2_HDLC)
380                                                 procbytes = hdlc_loop(c, src, numbytes, inbuf);
381                                         else
382                                                 procbytes = iraw_loop(c, src, numbytes, inbuf);
383
384                                         src += procbytes;
385                                         numbytes -= procbytes;
386                                 } else {  /* DLE char */
387                                         inbuf->inputstate &= ~INS_DLE_char;
388                                         switch (c) {
389                                         case 'X': /*begin of command*/
390                                                 if (inbuf->inputstate & INS_command)
391                                                         dev_warn(cs->dev,
392                                         "received <DLE> 'X' in command mode\n");
393                                                 inbuf->inputstate |=
394                                                         INS_command | INS_DLE_command;
395                                                 break;
396                                         case '.': /*end of command*/
397                                                 if (!(inbuf->inputstate & INS_command))
398                                                         dev_warn(cs->dev,
399                                         "received <DLE> '.' in hdlc mode\n");
400                                                 inbuf->inputstate &= cs->dle ?
401                                                         ~(INS_DLE_command|INS_command)
402                                                         : ~INS_DLE_command;
403                                                 break;
404                                         //case DLE_FLAG: /*DLE_FLAG in data stream*/ /* schon oben behandelt! */
405                                         default:
406                                                 dev_err(cs->dev,
407                                                       "received 0x10 0x%02x!\n",
408                                                         (int) c);
409                                                 /* FIXME: reset driver?? */
410                                         }
411                                 }
412                         }
413 nextbyte:
414                         if (!numbytes) {
415                                 /* end of buffer, check for wrap */
416                                 if (head > tail) {
417                                         head = 0;
418                                         src = inbuf->data;
419                                         numbytes = tail;
420                                 } else {
421                                         head = tail;
422                                         break;
423                                 }
424                         }
425                 }
426
427                 gig_dbg(DEBUG_INTR, "setting head to %u", head);
428                 inbuf->head = head;
429         }
430 }
431 EXPORT_SYMBOL_GPL(gigaset_m10x_input);
432
433
434 /* == data output ========================================================== */
435
436 /* Encoding of a PPP packet into an octet stuffed HDLC frame
437  * with FCS, opening and closing flags.
438  * parameters:
439  *      skb     skb containing original packet (freed upon return)
440  *      head    number of headroom bytes to allocate in result skb
441  *      tail    number of tailroom bytes to allocate in result skb
442  * Return value:
443  *      pointer to newly allocated skb containing the result frame
444  */
445 static struct sk_buff *HDLC_Encode(struct sk_buff *skb, int head, int tail)
446 {
447         struct sk_buff *hdlc_skb;
448         __u16 fcs;
449         unsigned char c;
450         unsigned char *cp;
451         int len;
452         unsigned int stuf_cnt;
453
454         stuf_cnt = 0;
455         fcs = PPP_INITFCS;
456         cp = skb->data;
457         len = skb->len;
458         while (len--) {
459                 if (muststuff(*cp))
460                         stuf_cnt++;
461                 fcs = crc_ccitt_byte(fcs, *cp++);
462         }
463         fcs ^= 0xffff;                  /* complement */
464
465         /* size of new buffer: original size + number of stuffing bytes
466          * + 2 bytes FCS + 2 stuffing bytes for FCS (if needed) + 2 flag bytes
467          */
468         hdlc_skb = dev_alloc_skb(skb->len + stuf_cnt + 6 + tail + head);
469         if (!hdlc_skb) {
470                 dev_kfree_skb(skb);
471                 return NULL;
472         }
473         skb_reserve(hdlc_skb, head);
474
475         /* Copy acknowledge request into new skb */
476         memcpy(hdlc_skb->head, skb->head, 2);
477
478         /* Add flag sequence in front of everything.. */
479         *(skb_put(hdlc_skb, 1)) = PPP_FLAG;
480
481         /* Perform byte stuffing while copying data. */
482         while (skb->len--) {
483                 if (muststuff(*skb->data)) {
484                         *(skb_put(hdlc_skb, 1)) = PPP_ESCAPE;
485                         *(skb_put(hdlc_skb, 1)) = (*skb->data++) ^ PPP_TRANS;
486                 } else
487                         *(skb_put(hdlc_skb, 1)) = *skb->data++;
488         }
489
490         /* Finally add FCS (byte stuffed) and flag sequence */
491         c = (fcs & 0x00ff);     /* least significant byte first */
492         if (muststuff(c)) {
493                 *(skb_put(hdlc_skb, 1)) = PPP_ESCAPE;
494                 c ^= PPP_TRANS;
495         }
496         *(skb_put(hdlc_skb, 1)) = c;
497
498         c = ((fcs >> 8) & 0x00ff);
499         if (muststuff(c)) {
500                 *(skb_put(hdlc_skb, 1)) = PPP_ESCAPE;
501                 c ^= PPP_TRANS;
502         }
503         *(skb_put(hdlc_skb, 1)) = c;
504
505         *(skb_put(hdlc_skb, 1)) = PPP_FLAG;
506
507         dev_kfree_skb(skb);
508         return hdlc_skb;
509 }
510
511 /* Encoding of a raw packet into an octet stuffed bit inverted frame
512  * parameters:
513  *      skb     skb containing original packet (freed upon return)
514  *      head    number of headroom bytes to allocate in result skb
515  *      tail    number of tailroom bytes to allocate in result skb
516  * Return value:
517  *      pointer to newly allocated skb containing the result frame
518  */
519 static struct sk_buff *iraw_encode(struct sk_buff *skb, int head, int tail)
520 {
521         struct sk_buff *iraw_skb;
522         unsigned char c;
523         unsigned char *cp;
524         int len;
525
526         /* worst case: every byte must be stuffed */
527         iraw_skb = dev_alloc_skb(2*skb->len + tail + head);
528         if (!iraw_skb) {
529                 dev_kfree_skb(skb);
530                 return NULL;
531         }
532         skb_reserve(iraw_skb, head);
533
534         cp = skb->data;
535         len = skb->len;
536         while (len--) {
537                 c = bitrev8(*cp++);
538                 if (c == DLE_FLAG)
539                         *(skb_put(iraw_skb, 1)) = c;
540                 *(skb_put(iraw_skb, 1)) = c;
541         }
542         dev_kfree_skb(skb);
543         return iraw_skb;
544 }
545
546 /* gigaset_send_skb
547  * called by common.c to queue an skb for sending
548  * and start transmission if necessary
549  * parameters:
550  *      B Channel control structure
551  *      skb
552  * Return value:
553  *      number of bytes accepted for sending
554  *      (skb->len if ok, 0 if out of buffer space)
555  *      or error code (< 0, eg. -EINVAL)
556  */
557 int gigaset_m10x_send_skb(struct bc_state *bcs, struct sk_buff *skb)
558 {
559         unsigned len = skb->len;
560         unsigned long flags;
561
562         if (bcs->proto2 == ISDN_PROTO_L2_HDLC)
563                 skb = HDLC_Encode(skb, HW_HDR_LEN, 0);
564         else
565                 skb = iraw_encode(skb, HW_HDR_LEN, 0);
566         if (!skb) {
567                 dev_err(bcs->cs->dev,
568                         "unable to allocate memory for encoding!\n");
569                 return -ENOMEM;
570         }
571
572         skb_queue_tail(&bcs->squeue, skb);
573         spin_lock_irqsave(&bcs->cs->lock, flags);
574         if (bcs->cs->connected)
575                 tasklet_schedule(&bcs->cs->write_tasklet);
576         spin_unlock_irqrestore(&bcs->cs->lock, flags);
577
578         return len;     /* ok so far */
579 }
580 EXPORT_SYMBOL_GPL(gigaset_m10x_send_skb);