more changes on original files
[linux-2.4.git] / drivers / usb / auerisdn.c
1 /*****************************************************************************/
2 /*
3  *      auerisdn.c  --  Auerswald PBX/System Telephone ISDN interface.
4  *
5  *      Copyright (C) 2002  Wolfgang Mües (wolfgang@iksw-muees.de)
6  *
7  *      This program is free software; you can redistribute it and/or modify
8  *      it under the terms of the GNU General Public License as published by
9  *      the Free Software Foundation; either version 2 of the License, or
10  *      (at your option) any later version.
11  *
12  *      This program is distributed in the hope that it will be useful,
13  *      but WITHOUT ANY WARRANTY; without even the implied warranty of
14  *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  *      GNU General Public License for more details.
16  *
17  *      You should have received a copy of the GNU General Public License
18  *      along with this program; if not, write to the Free Software
19  *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20  */
21  /*****************************************************************************/
22
23 #include <linux/isdnif.h>
24 #include <linux/netdevice.h>
25 #include <linux/sched.h>
26
27 #undef  DEBUG                   /* include debug macros until it's done */
28 #include <linux/usb.h>
29
30 #include "auerisdn.h"
31 #include "auermain.h"
32
33 /*-------------------------------------------------------------------*/
34 /* ISDN support defines                                              */
35 #define AUISDN_TEI      64      /* use a constant TEI */
36
37 /*-------------------------------------------------------------------*/
38 /* Debug support                                                     */
39 #ifdef DEBUG
40 #define dump( desc, adr, len) \
41 do {                    \
42         unsigned int u; \
43         printk (KERN_DEBUG); \
44         printk (desc); \
45         for (u = 0; u < len; u++) \
46                 printk (" %02X", adr[u] & 0xFF); \
47         printk ("\n"); \
48 } while (0)
49 #else
50 #define dump( desc, adr, len)
51 #endif
52
53 /*-------------------------------------------------------------------*/
54 /* Hisax Interface.                                                  */
55
56 /* The interface to hisax is long-lasting because hisax_unregister()
57    don't work well in Linux 2.4.x. So we have to hold each registered
58    hisax interface until driver removal. */
59 static struct auerhisax auerhisax_table[AUER_MAX_DEVICES];
60
61
62 /*-------------------------------------------------------------------*/
63
64 /* Callback to L2 for HISAX */
65 /* This callback can be called from 3 sources:
66    a) from hisax context (answer from a l2l1 function)
67    b) from interrupt context (a D channel paket arrived)
68    c) from kernel daemon context (probe/disconnecting)
69 */
70 static void auerisdn_d_l1l2(struct auerisdn *ip, int pr, void *arg)
71 {
72         struct sk_buff *skb;
73         struct auerhisax *ahp;
74
75         /* do the callback */
76         ahp = ip->ahp;
77         if (ahp) {
78                 ahp->hisax_d_if.ifc.l1l2(&ahp->hisax_d_if.ifc, pr, arg);
79         } else {
80                 dbg("auerisdn_d_l1l2 with ahp == NULL");
81                 if (pr == (PH_DATA | INDICATION)) {
82                         skb = (struct sk_buff *) arg;
83                         if (skb) {
84                                 skb_pull(skb, skb->len);
85                                 dev_kfree_skb_any(skb);
86                         }
87                 }
88         }
89 }
90
91
92 /* D-Channel sending completion function */
93 static void auerisdn_dcw_complete(struct urb *urb)
94 {
95         struct auerbuf *bp = (struct auerbuf *) urb->context;
96         struct auerswald *cp =
97             ((struct auerswald *) ((char *) (bp->list) -
98                                    (unsigned
99                                     long) (&((struct auerswald *) 0)->
100                                            bufctl)));
101
102         dbg("auerisdn_dcw_complete with status %d", urb->status);
103
104         /* reuse the buffer */
105         auerbuf_releasebuf(bp);
106
107         /* Wake up all processes waiting for a buffer */
108         wake_up(&cp->bufferwait);
109 }
110
111
112 /* Translate non-ETSI ISDN messages from the device */
113 static void auerisdn_translate_incoming(struct auerswald *cp,
114                                         unsigned char *msg,
115                                         unsigned int len)
116 {
117         struct auerbuf *bp;
118         int ret;
119
120         /* Translate incomming CONNECT -> CONNECT_ACK */
121         /* Format:   0   1    2     3     4        5        6    7      */
122         /*         SAPI TEI TXSEQ RXSEQ PID=08 CREFLEN=01 CREF MSG=7 ...*/
123         /* CREF.7 == 0 -> Incoming Call                                 */
124
125         /* Check for minimum length */
126         if (len < 8)
127                 return;
128
129         /* Check for a CONNECT, call originated from device */
130         if (((msg[6] & 0x80) == 0) && (msg[7] == 0x07)) {
131                 dbg("false CONNECT from device found");
132                 /* change into CONNECT_ACK */
133                 msg[7] = 0x0F;
134
135                 /* Send a CONNECT_ACK back to the device */
136
137                 /* get a new data buffer */
138                 bp = auerbuf_getbuf(&cp->bufctl);
139                 if (!bp) {
140                         warn("no auerbuf free");
141                         return;
142                 }
143
144                 /* Form a CONNECT ACK */
145                 bp->bufp[0] =
146                     cp->isdn.dchannelservice.id | AUH_DIRECT | AUH_UNSPLIT;
147                 bp->bufp[1] = 0x08;
148                 bp->bufp[2] = 0x01;
149                 bp->bufp[3] = msg[6] | 0x80;
150                 bp->bufp[4] = 0x0F;
151
152                 /* Set the transfer Parameters */
153                 bp->len = 5;
154                 bp->dr->bRequestType = AUT_WREQ;
155                 bp->dr->bRequest = AUV_WBLOCK;
156                 bp->dr->wValue = cpu_to_le16(0);
157                 bp->dr->wIndex =
158                     cpu_to_le16(cp->isdn.dchannelservice.
159                                 id | AUH_DIRECT | AUH_UNSPLIT);
160                 bp->dr->wLength = cpu_to_le16(5);
161                 FILL_CONTROL_URB(bp->urbp, cp->usbdev,
162                                  usb_sndctrlpipe(cp->usbdev, 0),
163                                  (unsigned char *) bp->dr, bp->bufp, 5,
164                                  auerisdn_dcw_complete, bp);
165                 /* up we go */
166                 ret = auerchain_submit_urb(&cp->controlchain, bp->urbp);
167                 if (ret)
168                         auerisdn_dcw_complete(bp->urbp);
169                 else
170                         dbg("auerisdn_translate: Write OK");
171         }
172         /* Check for a DISCONNECT and change to RELEASE */
173         if (msg[7] == 0x45) {
174                 dbg("DISCONNECT changed to RELEASE");
175                 msg[7] = 0x4D;
176                 return;
177         }
178 }
179
180
181 /* a D-channel paket arrived from the device */
182 static void auerisdn_dispatch_dc(struct auerscon *scp, struct auerbuf *bp)
183 {
184         struct sk_buff *skb;
185         struct auerhisax *ahp;
186         struct auerswald *cp =
187             ((struct auerswald *) ((char *) (scp) -
188                                    (unsigned
189                                     long) (&((struct auerswald *) 0)->isdn.
190                                            dchannelservice)));
191         unsigned char *sp;
192         unsigned int l2_index;
193         unsigned char c;
194         unsigned char l2_header[10];
195         unsigned long flags;
196
197         dump("D-Channel paket arrived:", bp->bufp, bp->len);
198         if (cp->disconnecting)
199                 return;
200
201         /* add a self-generated L2 message header */
202         l2_index = 0;
203         l2_header[l2_index++] = 0x02;   /* SAPI 0, C/R = 1 */
204
205         /* Parse the L3 message */
206         sp = bp->bufp + AUH_SIZE;
207
208         c = *sp++;              /* Protocol discriminator */
209         if (c != 0x08) {
210                 warn("D channel paket is not ETSI");
211                 return;
212         }
213         c = *sp++;              /* Call Reference length byte */
214         sp += c;                /* Skip Call Reference */
215
216         /* translate charge IEs */
217         /* Format of Auerswald Header:
218            0x32 len=0x0B 0xFF 0xFF 0x73 len=0x07 0x27 */
219         /* Format of IE2_UNIT:
220            0x49 len=0x04 uu1 uu2 uu3 uu4 */
221         /* Translate into: (?? Bytes)
222            0x1C Facility
223            0x?? restlen
224            0x91 Sup. Services
225            0xA1 Invoke
226            0x?? restlen
227            0x02 Invoke ID Tag
228            0x02 Invoke ID len
229            0x12 Invoke ID = 0x1234
230            0x34
231            0x02 OP Value Tag
232            0x01 Length of OPvalue
233            0x24 OpValue = AOCE
234            0x30 Universal Constructor Sequence
235            0x?? restlen
236            0x30 Universal Constructor Sequence
237            0x?? restlen
238            0xA1 Context Specific Constructor Recorded Units List
239            0x?? restlen
240            0x30 Universal Constructor Sequence
241            0x?? restlen
242            0x02 Universal Primitive Integer
243            0x?? len from IE2_UNIT
244            uu1  Recorded Units List
245            uu2
246            uu3
247            uu4
248          */
249         {
250                 unsigned char *ucp = sp;        // pointer to start of msg
251                 int l = bp->len;        // length until EOP
252                 unsigned char alen;     // length of auerswald msg
253                 l -= (int) (ucp - bp->bufp);
254                 // scan for Auerswald Header
255                 for (; l >= 9; l--, ucp++) {    // 9 = minimal length of auerswald msg
256                         if (ucp[0] != 0x32)
257                                 continue;
258                         if (ucp[2] != 0xFF)
259                                 continue;
260                         if (ucp[3] != 0xFF)
261                                 continue;
262                         if (ucp[4] != 0x73)
263                                 continue;
264                         if (ucp[6] != 0x27)
265                                 continue;
266                         // Auerswald Header found. Is it units?
267                         dbg("Auerswald msg header found");
268                         alen = ucp[1] + 2;
269                         if (ucp[7] == 0x49) {
270                                 // yes
271                                 unsigned char ul = ucp[8] + 1;  // length of charge integer
272                                 unsigned char charge[32];
273                                 // Copy charge info into new buffer
274                                 unsigned char *xp = &ucp[8];
275                                 int count;
276                                 for (count = 0; count < ul; count++)
277                                         charge[count] = *xp++;
278                                 // Erase auerswald msg
279                                 count = l - alen;
280                                 xp = ucp;
281                                 for (; count; count--, xp++)
282                                         xp[0] = xp[alen];
283                                 l -= alen;
284                                 bp->len -= alen;
285                                 // make room for new message
286                                 count = l;
287                                 xp = &ucp[l - 1];
288                                 for (; count; count--, xp--);
289                                 xp[21 + ul] = xp[0];
290                                 l += (21 + ul);
291                                 bp->len += (21 + ul);
292                                 // insert IE header
293                                 ucp[0] = 0x1C;
294                                 ucp[1] = 19 + ul;
295                                 ucp[2] = 0x91;
296                                 ucp[3] = 0xA1;
297                                 ucp[4] = 16 + ul;
298                                 ucp[5] = 0x02;
299                                 ucp[6] = 0x02;
300                                 ucp[7] = 0x12;
301                                 ucp[8] = 0x34;
302                                 ucp[9] = 0x02;
303                                 ucp[10] = 0x01;
304                                 ucp[11] = 0x24;
305                                 ucp[12] = 0x30;
306                                 ucp[13] = 7 + ul;
307                                 ucp[14] = 0x30;
308                                 ucp[15] = 5 + ul;
309                                 ucp[16] = 0xA1;
310                                 ucp[17] = 3 + ul;
311                                 ucp[18] = 0x30;
312                                 ucp[19] = 1 + ul;
313                                 ucp[20] = 0x02;
314                                 // Insert charge units
315                                 xp = &ucp[21];
316                                 for (count = 0; count < ul; count++)
317                                         *xp++ = charge[count];
318                                 dump("Rearranged message:", bp->bufp,
319                                      bp->len);
320                                 break;
321                         } else {
322                                 // we can't handle something else, erase it
323                                 int count = l - alen;
324                                 unsigned char *xp = ucp;
325                                 for (; count; count--, xp++)
326                                         xp[0] = xp[alen];
327                                 l -= alen;
328                                 bp->len -= alen;
329                                 dump("Shortened message:", bp->bufp,
330                                      bp->len);
331                         }
332                 }
333         }
334
335
336         c = *sp;                /* Message type */
337         if (c == 0x05) {
338                 /* SETUP. Use an UI frame */
339                 dbg("SETUP");
340                 l2_header[l2_index++] = 0xFF;   /* TEI 127 */
341                 l2_header[l2_index++] = 0x03;   /* UI control field */
342                 skb = dev_alloc_skb(bp->len - AUH_SIZE + l2_index);
343         } else {
344                 /* use an I frame */
345                 dbg("I Frame");
346                 l2_header[l2_index++] = (AUISDN_TEI << 1) | 0x01;       /* TEI byte */
347                 skb = dev_alloc_skb(bp->len - AUH_SIZE + l2_index + 2);
348                 if (skb) {
349                         ahp = cp->isdn.ahp;
350                         if (!ahp) {
351                                 err("ahp == NULL");
352                                 return;
353                         }
354                         spin_lock_irqsave(&ahp->seq_lock, flags);
355                         l2_header[l2_index++] = ahp->txseq;     /* transmitt sequence number */
356                         l2_header[l2_index++] = ahp->rxseq;     /* receive sequence number */
357                         ahp->txseq += 2;                        /* next paket gets next number */
358                         spin_unlock_irqrestore(&ahp->seq_lock, flags);
359                 }
360         }
361         if (!skb) {
362                 err("no memory - skipped");
363                 return;
364         }
365         sp = skb_put(skb, bp->len - AUH_SIZE + l2_index);
366         /* Add L2 header */
367         memcpy(sp, l2_header, l2_index);
368         memcpy(sp + l2_index, bp->bufp + AUH_SIZE, bp->len - AUH_SIZE);
369         /* Translate false messages */
370         auerisdn_translate_incoming(cp, sp, bp->len - AUH_SIZE + l2_index);
371         /* Send message to L2 */
372         auerisdn_d_l1l2(&cp->isdn, PH_DATA | INDICATION, skb);
373 }
374
375 /* D-channel is closed because the device is removed */
376 /* This is a no-op because ISDN close is handled different */
377 static void auerisdn_disconnect_dc(struct auerscon *scp)
378 {
379 }
380
381
382 /* confirmation helper function. */
383 static void auerisdn_d_confirmskb(struct auerswald *cp,
384                                   struct sk_buff *skb)
385 {
386         /* free the skb */
387         if (skb) {
388                 skb_pull(skb, skb->len);
389                 dev_kfree_skb_any(skb);
390         }
391
392         /* confirm the sending of data */
393         dbg("Confirm PH_DATA");
394         auerisdn_d_l1l2(&cp->isdn, PH_DATA | CONFIRM, NULL);
395 }
396
397 /* D-channel transfer function L2->L1 */
398 static void auerisdn_d_l2l1(struct hisax_if *hisax_d_if, int pr, void *arg)
399 {
400         struct auerhisax *ahp;
401         struct sk_buff *skb;
402         unsigned int len;
403         int ret;
404         struct auerbuf *bp;
405         struct auerswald *cp;
406         unsigned long flags;
407         unsigned int l2_index;
408         unsigned char c;
409         unsigned char l2_header[32];
410         unsigned char *sp;
411
412         dbg("hisax D-Channel l2l1 called");
413
414         /* Get reference to auerhisax struct */
415         cp = NULL;
416         ahp = hisax_d_if->priv;
417         if (ahp)
418                 cp = ahp->cp;
419         if (cp && !cp->disconnecting) {
420                 /* normal usage */
421                 switch (pr) {
422                 case PH_ACTIVATE | REQUEST:     /* activation request */
423                         dbg("Activation Request");
424                         cp->isdn.dc_activated = 1;
425                         /* send activation back to layer 2 */
426                         auerisdn_d_l1l2(&cp->isdn,
427                                         PH_ACTIVATE | INDICATION, NULL);
428                         break;
429                 case PH_DEACTIVATE | REQUEST:   /* deactivation request */
430                         dbg("Deactivation Request");
431                         cp->isdn.dc_activated = 0;
432                         /* send deactivation back to layer 2 */
433                         auerisdn_d_l1l2(&cp->isdn,
434                                         PH_DEACTIVATE | INDICATION, NULL);
435                         break;
436                 case PH_DATA | REQUEST: /* Transmit data request */
437                         skb = (struct sk_buff *) arg;
438                         len = skb->len;
439                         l2_index = 0;
440                         sp = skb->data;
441                         dump("Data Request:", sp, len);
442
443                         /* Parse the L2 header */
444                         if (!len)
445                                 goto phd_free;
446                         c = *sp++;      /* SAPI */
447                         l2_header[l2_index++] = c;
448                         len--;
449                         if (!len)
450                                 goto phd_free;
451                         c = *sp++;      /* TEI */
452                         l2_header[l2_index++] = c;
453                         len--;
454                         if (!len)
455                                 goto phd_free;
456                         c = *sp++;      /* Control Field, Byte 1 */
457                         len--;
458                         if (!(c & 0x01)) {
459                                 /* I FRAME */
460                                 dbg("I Frame");
461                                 if (!len)
462                                         goto phd_free;
463                                 spin_lock_irqsave(&ahp->seq_lock, flags);
464                                 ahp->rxseq = c + 2;     /* store new sequence info */
465                                 spin_unlock_irqrestore(&ahp->seq_lock,
466                                                        flags);
467                                 sp++;   /* skip Control Field, Byte 2 */
468                                 len--;
469                                 /* Check for RELEASE command */
470                                 /* and change to RELEASE_COMPLETE */
471                                 if (sp[3] == 0x4D)
472                                         sp[3] = 0x5A;
473                                 goto phd_send;
474                         }
475                         /* check the frame type */
476                         switch (c) {
477                         case 0x03:      /* UI frame */
478                                 dbg("UI Frame");
479                                 if (l2_header[0] == 0xFC) {
480                                         dbg("TEI Managment");
481                                         l2_header[0] = 0xFE;    /* set C/R bit in answer */
482                                         l2_header[l2_index++] = c;      /* Answer is UI frame */
483                                         if (!len)
484                                                 break;
485                                         c = *sp++;      /* Managment ID */
486                                         len--;
487                                         if (c != 0x0F)
488                                                 break;
489                                         l2_header[l2_index++] = c;
490                                         /* Read Reference Number */
491                                         if (!len)
492                                                 break;
493                                         l2_header[l2_index++] = *sp++;
494                                         len--;
495                                         if (!len)
496                                                 break;
497                                         l2_header[l2_index++] = *sp++;
498                                         len--;
499                                         if (!len)
500                                                 break;
501                                         c = *sp++;      /* Message Type */
502                                         len--;
503                                         switch (c) {
504                                         case 0x01:      /* Identity Request */
505                                                 dbg("Identity Request");
506                                                 l2_header[l2_index++] = 0x02;   /* Identity Assign */
507                                                 l2_header[l2_index++] =
508                                                     (AUISDN_TEI << 1) |
509                                                     0x01;
510                                                 goto phd_answer;
511                                         default:
512                                                 dbg("Unhandled TEI Managment %X", (int) c);
513                                                 break;
514                                         }
515                                         // throw away
516                                         goto phd_free;
517                                 }
518                                 /* else send UI frame out */
519                                 goto phd_send;
520                         case 0x01:      /* RR frame */
521                         case 0x05:      /* RNR frame */
522                                 dbg("RR/RNR Frame");
523                                 if (!len)
524                                         break;
525                                 c = *sp++;      /* Control Field, Byte 2 */
526                                 len--;
527                                 if (!(c & 0x01))
528                                         break;  /* P/F = 1 in commands */
529                                 if (l2_header[0] & 0x02)
530                                         break;  /* C/R = 0 from TE */
531                                 dbg("Send RR as answer");
532                                 l2_header[l2_index++] = 0x01;   /* send an RR as Answer */
533                                 spin_lock_irqsave(&ahp->seq_lock, flags);
534                                 l2_header[l2_index++] = ahp->rxseq | 0x01;
535                                 spin_unlock_irqrestore(&ahp->seq_lock,
536                                                        flags);
537                                 goto phd_answer;
538                         case 0x7F:      /* SABME */
539                                 dbg("SABME");
540                                 spin_lock_irqsave(&ahp->seq_lock, flags);
541                                 ahp->txseq = 0;
542                                 ahp->rxseq = 0;
543                                 spin_unlock_irqrestore(&ahp->seq_lock,
544                                                        flags);
545                                 l2_header[l2_index++] = 0x73;   /* UA */
546                                 goto phd_answer;
547                         case 0x53:      /* DISC */
548                                 dbg("DISC");
549                                 /* Send back a UA */
550                                 l2_header[l2_index++] = 0x73;   /* UA */
551                                 goto phd_answer;
552                         default:
553                                 dbg("Unhandled L2 Message %X", (int) c);
554                                 break;
555                         }
556                         /* all done */
557                         goto phd_free;
558
559                         /* we have to generate a local answer */
560                         /* first, confirm old message, free old skb */
561                       phd_answer:auerisdn_d_confirmskb(cp,
562                                               skb);
563
564                         /* allocate a new skbuff */
565                         skb = dev_alloc_skb(l2_index);
566                         if (!skb) {
567                                 err("no memory for new skb");
568                                 break;
569                         }
570                         dump("local answer to L2 is:", l2_header,
571                              l2_index);
572                         memcpy(skb_put(skb, l2_index), l2_header,
573                                l2_index);
574                         auerisdn_d_l1l2(&cp->isdn, PH_DATA | INDICATION,
575                                         skb);
576                         break;
577
578                         /* we have to send the L3 message out */
579                       phd_send:if (!len)
580                                 goto phd_free;  /* no message left */
581
582                         /* get a new data buffer */
583                         bp = auerbuf_getbuf(&cp->bufctl);
584                         if (!bp) {
585                                 warn("no auerbuf free");
586                                 goto phd_free;
587                         }
588                         /* protect against too big write requests */
589                         /* Should not happen */
590                         if (len > cp->maxControlLength) {
591                                 err("too long D-channel paket truncated");
592                                 len = cp->maxControlLength;
593                         }
594
595                         /* Copy the data */
596                         memcpy(bp->bufp + AUH_SIZE, sp, len);
597
598                         /* set the header byte */
599                         *(bp->bufp) =
600                             cp->isdn.dchannelservice.
601                             id | AUH_DIRECT | AUH_UNSPLIT;
602
603                         /* Set the transfer Parameters */
604                         bp->len = len + AUH_SIZE;
605                         bp->dr->bRequestType = AUT_WREQ;
606                         bp->dr->bRequest = AUV_WBLOCK;
607                         bp->dr->wValue = cpu_to_le16(0);
608                         bp->dr->wIndex =
609                             cpu_to_le16(cp->isdn.dchannelservice.
610                                         id | AUH_DIRECT | AUH_UNSPLIT);
611                         bp->dr->wLength = cpu_to_le16(len + AUH_SIZE);
612                         FILL_CONTROL_URB(bp->urbp, cp->usbdev,
613                                          usb_sndctrlpipe(cp->usbdev, 0),
614                                          (unsigned char *) bp->dr,
615                                          bp->bufp, len + AUH_SIZE,
616                                          auerisdn_dcw_complete, bp);
617                         /* up we go */
618                         ret =
619                             auerchain_submit_urb(&cp->controlchain,
620                                                  bp->urbp);
621                         if (ret)
622                                 auerisdn_dcw_complete(bp->urbp);
623                         else
624                                 dbg("auerisdn_dwrite: Write OK");
625                         /* confirm message, free skb */
626                       phd_free:auerisdn_d_confirmskb(cp,
627                                               skb);
628                         break;
629
630                 default:
631                         warn("pr %#x\n", pr);
632                         break;
633                 }
634         } else {
635                 /* hisax interface is down */
636                 switch (pr) {
637                 case PH_ACTIVATE | REQUEST:     /* activation request */
638                         dbg("D channel PH_ACTIVATE | REQUEST with interface down");
639                         /* don't answer this request! Endless... */
640                         break;
641                 case PH_DEACTIVATE | REQUEST:   /* deactivation request */
642                         dbg("D channel PH_DEACTIVATE | REQUEST with interface down");
643                         hisax_d_if->l1l2(hisax_d_if,
644                                          PH_DEACTIVATE | INDICATION, NULL);
645                         break;
646                 case PH_DATA | REQUEST: /* Transmit data request */
647                         dbg("D channel PH_DATA | REQUEST with interface down");
648                         skb = (struct sk_buff *) arg;
649                         /* free data buffer */
650                         if (skb) {
651                                 skb_pull(skb, skb->len);
652                                 dev_kfree_skb_any(skb);
653                         }
654                         /* send confirmation back to layer 2 */
655                         hisax_d_if->l1l2(hisax_d_if, PH_DATA | CONFIRM,
656                                          NULL);
657                         break;
658                 default:
659                         warn("pr %#x\n", pr);
660                         break;
661                 }
662         }
663 }
664
665
666 /* Completion function for D channel open */
667 static void auerisdn_dcopen_complete(struct urb *urbp)
668 {
669         struct auerbuf *bp = (struct auerbuf *) urbp->context;
670         struct auerswald *cp =
671             ((struct auerswald *) ((char *) (bp->list) -
672                                    (unsigned
673                                     long) (&((struct auerswald *) 0)->
674                                            bufctl)));
675         dbg("auerisdn_dcopen_complete called");
676
677         auerbuf_releasebuf(bp);
678
679         /* Wake up all processes waiting for a buffer */
680         wake_up(&cp->bufferwait);
681 }
682
683
684 /* Open the D-channel once more */
685 static void auerisdn_dcopen(unsigned long data)
686 {
687         struct auerswald *cp = (struct auerswald *) data;
688         struct auerbuf *bp;
689         int ret;
690
691         if (cp->disconnecting)
692                 return;
693         dbg("auerisdn_dcopen running");
694
695         /* get a buffer for the command */
696         bp = auerbuf_getbuf(&cp->bufctl);
697         /* if no buffer available: can't change the mode */
698         if (!bp) {
699                 err("auerisdn_dcopen: no data buffer available");
700                 return;
701         }
702
703         /* fill the control message */
704         bp->dr->bRequestType = AUT_WREQ;
705         bp->dr->bRequest = AUV_CHANNELCTL;
706         bp->dr->wValue = cpu_to_le16(1);
707         bp->dr->wIndex = cpu_to_le16(0);
708         bp->dr->wLength = cpu_to_le16(0);
709         FILL_CONTROL_URB(bp->urbp, cp->usbdev,
710                          usb_sndctrlpipe(cp->usbdev, 0),
711                          (unsigned char *) bp->dr, bp->bufp, 0,
712                          (usb_complete_t) auerisdn_dcopen_complete, bp);
713
714         /* submit the control msg */
715         ret = auerchain_submit_urb(&cp->controlchain, bp->urbp);
716         dbg("dcopen submitted");
717         if (ret) {
718                 bp->urbp->status = ret;
719                 auerisdn_dcopen_complete(bp->urbp);
720         }
721         return;
722 }
723
724
725 /* Initialize the isdn related items in struct auerswald */
726 void auerisdn_init_dev(struct auerswald *cp)
727 {
728         unsigned int u;
729         cp->isdn.dchannelservice.id = AUH_UNASSIGNED;
730         cp->isdn.dchannelservice.dispatch = auerisdn_dispatch_dc;
731         cp->isdn.dchannelservice.disconnect = auerisdn_disconnect_dc;
732         init_timer(&cp->isdn.dcopen_timer);
733         cp->isdn.dcopen_timer.data = (unsigned long) cp;
734         cp->isdn.dcopen_timer.function = auerisdn_dcopen;
735         for (u = 0; u < AUISDN_BCHANNELS; u++) {
736                 cp->isdn.bc[u].cp = cp;
737                 cp->isdn.bc[u].mode = L1_MODE_NULL;
738                 cp->isdn.bc[u].channel = u;
739                 spin_lock_init(&cp->isdn.bc[u].txskb_lock);
740         }
741 }
742
743
744 /* Connect to the HISAX interface. Returns 0 if successfull */
745 int auerisdn_probe(struct auerswald *cp)
746 {
747         struct hisax_b_if *b_if[AUISDN_BCHANNELS];
748         struct usb_endpoint_descriptor *ep;
749         struct auerhisax *ahp;
750         DECLARE_WAIT_QUEUE_HEAD(wqh);
751         unsigned int u;
752         unsigned char *ucp;
753         unsigned int first_time;
754         int ret;
755
756         /* First allocate resources, then register hisax interface */
757
758         /* Allocate RX buffers */
759         for (u = 0; u < AUISDN_BCHANNELS; u++) {
760                 if (!cp->isdn.bc[u].rxbuf) {
761                         cp->isdn.bc[u].rxbuf =
762                             (char *) kmalloc(AUISDN_RXSIZE, GFP_KERNEL);
763                         if (!cp->isdn.bc[u].rxbuf) {
764                                 err("can't allocate buffer for B channel RX data");
765                                 return -1;
766                         }
767                 }
768         }
769
770         /* Read out B-Channel output fifo size */
771         ucp = kmalloc(32, GFP_KERNEL);
772         if (!ucp) {
773                 err("Out of memory");
774                 return -3;
775         }
776         ret = usb_control_msg(cp->usbdev,                       /* pointer to device */
777                               usb_rcvctrlpipe(cp->usbdev, 0),   /* pipe to control endpoint */
778                               AUV_GETINFO,                      /* USB message request value */
779                               AUT_RREQ,                         /* USB message request type value */
780                               0,                                /* USB message value */
781                               AUDI_OUTFSIZE,                    /* USB message index value */
782                               ucp,                              /* pointer to the receive buffer */
783                               32,                               /* length of the buffer */
784                               HZ * 2);                          /* time to wait for the message to complete before timing out */
785         if (ret < 4) {
786                 kfree(ucp);
787                 err("can't read TX Fifo sizes for B1,B2");
788                 return -4;
789         }
790         for (u = 0; u < AUISDN_BCHANNELS; u++) {
791                 ret = le16_to_cpup(ucp + u * 2);
792                 cp->isdn.bc[u].ofsize = ret;
793                 cp->isdn.bc[u].txfree = ret;
794         }
795         kfree(ucp);
796         for (u = 0; u < AUISDN_BCHANNELS; u++) {
797                 dbg("B%d buffer size is %d", u, cp->isdn.bc[u].ofsize);
798         }
799
800         /* get the B channel output INT size */
801         cp->isdn.intbo_endp = AU_IRQENDPBO;
802         ep = usb_epnum_to_ep_desc(cp->usbdev, USB_DIR_OUT | AU_IRQENDPBO);
803         if (!ep) {
804                 /* Some devices have another endpoint number here ... */
805                 cp->isdn.intbo_endp = AU_IRQENDPBO_2;
806                 ep = usb_epnum_to_ep_desc(cp->usbdev,
807                                           USB_DIR_OUT | AU_IRQENDPBO_2);
808                 if (!ep) {
809                         err("can't get B channel OUT endpoint");
810                         return -5;
811                 }
812         }
813         cp->isdn.outsize = ep->wMaxPacketSize;
814         cp->isdn.outInterval = ep->bInterval;
815         cp->isdn.usbdev = cp->usbdev;
816
817         /* allocate the urb and data buffer */
818         if (!cp->isdn.intbo_urbp) {
819                 cp->isdn.intbo_urbp = usb_alloc_urb(0);
820                 if (!cp->isdn.intbo_urbp) {
821                         err("can't allocate urb for B channel output endpoint");
822                         return -6;
823                 }
824         }
825         if (!cp->isdn.intbo_bufp) {
826                 cp->isdn.intbo_bufp =
827                     (char *) kmalloc(cp->isdn.outsize, GFP_KERNEL);
828                 if (!cp->isdn.intbo_bufp) {
829                         err("can't allocate buffer for B channel output endpoint");
830                         return -7;
831                 }
832         }
833
834         /* get the B channel input INT size */
835         ep = usb_epnum_to_ep_desc(cp->usbdev, USB_DIR_IN | AU_IRQENDPBI);
836         if (!ep) {
837                 err("can't get B channel IN endpoint");
838                 return -8;
839         }
840         cp->isdn.insize = ep->wMaxPacketSize;
841
842         /* allocate the urb and data buffer */
843         if (!cp->isdn.intbi_urbp) {
844                 cp->isdn.intbi_urbp = usb_alloc_urb(0);
845                 if (!cp->isdn.intbi_urbp) {
846                         err("can't allocate urb for B channel input endpoint");
847                         return -9;
848                 }
849         }
850         if (!cp->isdn.intbi_bufp) {
851                 cp->isdn.intbi_bufp =
852                     (char *) kmalloc(cp->isdn.insize, GFP_KERNEL);
853                 if (!cp->isdn.intbi_bufp) {
854                         err("can't allocate buffer for B channel input endpoint");
855                         return -10;
856                 }
857         }
858
859         /* setup urb */
860         FILL_INT_URB(cp->isdn.intbi_urbp, cp->usbdev,
861                      usb_rcvintpipe(cp->usbdev, AU_IRQENDPBI),
862                      cp->isdn.intbi_bufp, cp->isdn.insize,
863                      auerisdn_intbi_complete, cp, ep->bInterval);
864         /* start the urb */
865         cp->isdn.intbi_urbp->status = 0;        /* needed! */
866         ret = usb_submit_urb(cp->isdn.intbi_urbp);
867         if (ret < 0) {
868                 err("activation of B channel input int failed %d", ret);
869                 usb_free_urb(cp->isdn.intbi_urbp);
870                 cp->isdn.intbi_urbp = NULL;
871                 return -11;
872         }
873
874         /* request the D-channel service now */
875         dbg("Requesting D channel now");
876         cp->isdn.dchannelservice.id = AUH_DCHANNEL;
877         if (auerswald_addservice(cp, &cp->isdn.dchannelservice)) {
878                 err("can not open D-channel");
879                 cp->isdn.dchannelservice.id = AUH_UNASSIGNED;
880                 return -2;
881         }
882
883         /* Find a free hisax interface */
884         for (u = 0; u < AUER_MAX_DEVICES; u++) {
885                 ahp = &auerhisax_table[u];
886                 if (!ahp->cp) {
887                         first_time = (u == 0);
888                         goto ahp_found;
889                 }
890         }
891         /* no free interface found */
892         return -12;
893
894         /* we found a free hisax interface */
895       ahp_found:
896         /* Wait until ipppd timeout expired. The reason behind this ugly construct:
897            If we connect to a hisax device without waiting for ipppd we are not able
898            to make a new IP connection. */
899         if (ahp->last_close) {
900                 unsigned long timeout = jiffies - ahp->last_close;
901                 if (timeout < AUISDN_IPTIMEOUT) {
902                         info("waiting for ipppd to timeout");
903                         sleep_on_timeout(&wqh, AUISDN_IPTIMEOUT - timeout);
904                 }
905         }
906
907         cp->isdn.ahp = ahp;
908         u = ahp->hisax_registered;
909         ahp->hisax_registered = 1;
910         ahp->cp = cp;
911
912         /* now do the registration */
913         if (!u) {
914                 for (u = 0; u < AUISDN_BCHANNELS; u++) {
915                         b_if[u] = &ahp->hisax_b_if[u];
916                 }
917                 if (hisax_register
918                     (&ahp->hisax_d_if, b_if, "auerswald_usb",
919                      ISDN_PTYPE_EURO)) {
920                         err("hisax registration failed");
921                         ahp->cp = NULL;
922                         cp->isdn.ahp = NULL;
923                         ahp->hisax_registered = 0;
924                         return -13;
925                 }
926                 dbg("hisax interface registered");
927         }
928
929         /* send a D channel L1 activation indication to hisax */
930         auerisdn_d_l1l2(&cp->isdn, PH_ACTIVATE | INDICATION, NULL);
931         cp->isdn.dc_activated = 1;
932
933         /* do another D channel activation for problematic devices */
934         cp->isdn.dcopen_timer.expires = jiffies + HZ;
935         dbg("add timer");
936         add_timer(&cp->isdn.dcopen_timer);
937
938         return 0;
939 }
940
941 /* The USB device was disconnected */
942 void auerisdn_disconnect(struct auerswald *cp)
943 {
944         struct auerhisax *ahp;
945         DECLARE_WAIT_QUEUE_HEAD(wqh);
946         unsigned long flags;
947         unsigned int u;
948         int ret;
949         unsigned int stop_bc;
950
951         dbg("auerisdn_disconnect called");
952
953         /* stop a running timer */
954         del_timer_sync(&cp->isdn.dcopen_timer);
955
956         /* first, stop the B channels */
957         stop_bc = auerisdn_b_disconnect(cp);
958
959         /* stop the D channels */
960         auerisdn_d_l1l2(&cp->isdn, PH_DEACTIVATE | INDICATION, NULL);
961         cp->isdn.dc_activated = 0;
962         dbg("D-Channel disconnected");
963
964         /* Wait a moment */
965         sleep_on_timeout(&wqh, HZ / 10);
966
967         /* Shut the connection to the hisax interface */
968         ahp = cp->isdn.ahp;
969         if (ahp) {
970                 dbg("closing connection to hisax interface");
971                 ahp->cp = NULL;
972                 cp->isdn.ahp = NULL;
973                 /* time of last closure */
974                 if (stop_bc)
975                         /* if we kill a running connection ... */
976                         ahp->last_close = jiffies;
977                 else
978                         ahp->last_close = 0;
979         }
980
981         /* Now free the memory */
982         if (cp->isdn.intbi_urbp) {
983                 ret = usb_unlink_urb(cp->isdn.intbi_urbp);
984                 if (ret)
985                         dbg("B in: nonzero int unlink result received: %d",
986                             ret);
987                 usb_free_urb(cp->isdn.intbi_urbp);
988                 cp->isdn.intbi_urbp = NULL;
989         }
990         kfree(cp->isdn.intbi_bufp);
991         cp->isdn.intbi_bufp = NULL;
992         
993         if (cp->isdn.intbo_urbp) {
994                 cp->isdn.intbo_urbp->transfer_flags &= ~USB_ASYNC_UNLINK;
995                 ret = usb_unlink_urb(cp->isdn.intbo_urbp);
996                 if (ret)
997                         dbg("B out: nonzero int unlink result received: %d", ret);
998                 usb_free_urb(cp->isdn.intbo_urbp);
999                 cp->isdn.intbo_urbp = NULL;
1000         }
1001         kfree(cp->isdn.intbo_bufp);
1002         cp->isdn.intbo_bufp = NULL;
1003
1004         /* Remove the rx and tx buffers */
1005         for (u = 0; u < AUISDN_BCHANNELS; u++) {
1006                 kfree(cp->isdn.bc[u].rxbuf);
1007                 cp->isdn.bc[u].rxbuf = NULL;
1008                 spin_lock_irqsave(&cp->isdn.bc[u].txskb_lock, flags);
1009                 if (cp->isdn.bc[u].txskb) {
1010                         skb_pull(cp->isdn.bc[u].txskb,
1011                                  cp->isdn.bc[u].txskb->len);
1012                         dev_kfree_skb_any(cp->isdn.bc[u].txskb);
1013                         cp->isdn.bc[u].txskb = NULL;
1014                 }
1015                 spin_unlock_irqrestore(&cp->isdn.bc[u].txskb_lock, flags);
1016         }
1017
1018         /* Remove the D-channel connection */
1019         auerswald_removeservice(cp, &cp->isdn.dchannelservice);
1020 }
1021
1022
1023 /*-------------------------------------------------------------------*/
1024 /* Environment for long-lasting hisax interface                      */
1025
1026 /* Wrapper for hisax B0 channel L2L1 */
1027 static void auerisdn_b0_l2l1_wrapper(struct hisax_if *ifc, int pr,
1028                                      void *arg)
1029 {
1030         auerisdn_b_l2l1(ifc, pr, arg, 0);
1031 }
1032
1033 /* Wrapper for hisax B1 channel L2L1 */
1034 static void auerisdn_b1_l2l1_wrapper(struct hisax_if *ifc, int pr,
1035                                      void *arg)
1036 {
1037         auerisdn_b_l2l1(ifc, pr, arg, 1);
1038 }
1039
1040 /* Init the global variables */
1041 void auerisdn_init(void)
1042 {
1043         struct auerhisax *ahp;
1044         unsigned int u;
1045
1046         memset(&auerhisax_table, 0, sizeof(auerhisax_table));
1047         for (u = 0; u < AUER_MAX_DEVICES; u++) {
1048                 ahp = &auerhisax_table[u];
1049                 spin_lock_init(&ahp->seq_lock);
1050                 ahp->hisax_d_if.ifc.priv = ahp;
1051                 ahp->hisax_d_if.ifc.l2l1 = auerisdn_d_l2l1;
1052                 ahp->hisax_b_if[0].ifc.priv = ahp;
1053                 ahp->hisax_b_if[0].ifc.l2l1 = auerisdn_b0_l2l1_wrapper;
1054                 ahp->hisax_b_if[1].ifc.priv = ahp;
1055                 ahp->hisax_b_if[1].ifc.l2l1 = auerisdn_b1_l2l1_wrapper;
1056         }
1057 }
1058
1059 /* Deinit the global variables */
1060 void auerisdn_cleanup(void)
1061 {
1062         struct auerhisax *ahp;
1063         int i;
1064
1065         /* cleanup last allocated device first */
1066         for (i = AUER_MAX_DEVICES - 1; i >= 0; i--) {
1067                 ahp = &auerhisax_table[i];
1068                 if (ahp->cp) {
1069                         err("hisax device %d open at cleanup", i);
1070                 }
1071                 if (ahp->hisax_registered) {
1072                         hisax_unregister(&ahp->hisax_d_if);
1073                         dbg("hisax interface %d freed", i);
1074                 }
1075         }
1076 }