1 /*****************************************************************************/
3 * auerisdn_b.c -- Auerswald PBX/System Telephone ISDN B-channel interface.
5 * Copyright (C) 2002 Wolfgang Mües (wolfgang@iksw-muees.de)
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.
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.
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.
21 /*****************************************************************************/
23 #include <linux/isdnif.h> /* ISDN constants */
24 #include <linux/netdevice.h> /* skb functions */
26 #undef DEBUG /* include debug macros until it's done */
27 #include <linux/usb.h> /* standard usb header */
32 /*-------------------------------------------------------------------*/
33 /* ISDN B channel support defines */
34 #define AUISDN_BC_1MS 8 /* Bytes per channel and ms */
35 #define AUISDN_BC_INC 4 /* change INT OUT size increment */
36 #define AUISDN_BCDATATHRESHOLD 48 /* for unsymmetric 2-B-channels */
37 #define AUISDN_TOGGLETIME 6 /* Timeout for unsymmetric serve */
39 /*-------------------------------------------------------------------*/
42 #define dump( desc, adr, len) \
45 printk (KERN_DEBUG); \
47 for (u = 0; u < len; u++) \
48 printk (" %02X", adr[u] & 0xFF); \
52 #define dump( desc, adr, len)
55 /*-------------------------------------------------------------------*/
57 /* Callback to L2 for HISAX */
58 /* This callback can be called from 3 sources:
59 a) from hisax context (answer from a l2l1 function)
60 b) from interrupt context (a B channel paket arrived, a B channel paket was sent)
61 c) from kernel daemon context (probe/disconnecting)
63 void auerisdn_b_l1l2(struct auerisdnbc *bc, int pr, void *arg)
65 struct auerhisax *ahp;
69 ahp = bc->cp->isdn.ahp;
71 ahp->hisax_b_if[bc->channel].ifc.l1l2(&ahp->
76 dbg("auerisdn_b_l1l2 called without ahp");
77 if (pr == (PH_DATA | INDICATION)) {
78 skb = (struct sk_buff *) arg;
80 skb_pull(skb, skb->len);
81 dev_kfree_skb_any(skb);
87 /* fill the INT OUT data buffer with new data */
88 /* Transfer buffer size to fill is in urbp->transfer_buffer_length */
89 static void auerisdn_bintbo_newdata(struct auerisdn *ip)
92 struct urb *urbp = ip->intbo_urbp;
93 struct auerisdnbc *bc = &ip->bc[0]; /* start with B-channel 0 */
101 /* FIXME: this algorithm is fixed to 2 B-channels */
102 /* Which B channel should we serve? */
103 if (ip->bc[1].mode != L1_MODE_NULL) {
104 /* B channel 1 is used */
105 if (bc->mode != L1_MODE_NULL) {
106 /* both B-channels are used */
107 if (ip->intbo_toggletimer) {
108 /* simply toggling */
109 ip->intbo_toggletimer--;
110 i = ip->intbo_index ^ 1; /* serve both channels equal */
112 /* search the B channel with the most demand of data */
113 i = bc->txfree - ip->bc[1].txfree;
114 if (i < -AUISDN_BCDATATHRESHOLD)
115 i = 1; /* B channel 1 needs more data */
116 else if (i > AUISDN_BCDATATHRESHOLD)
117 i = 0; /* B channel 0 needs more data */
119 i = ip->intbo_index ^ 1; /* serve both channels equal */
120 if (i == ip->intbo_index)
121 ip->intbo_toggletimer =
130 dbg("INTBO: Fill B%d with %d Bytes, %d Bytes free",
131 bc->channel + 1, urbp->transfer_buffer_length - AUH_SIZE,
134 /* Fill the buffer with data */
135 ucp = ip->intbo_bufp;
136 *ucp++ = AUH_B1CHANNEL + bc->channel; /* First byte is channel nr. */
137 buf_size = urbp->transfer_buffer_length - AUH_SIZE;
139 while (len < buf_size) {
140 spin_lock_irqsave(&bc->txskb_lock, flags);
141 if ((skb = bc->txskb)) {
142 /* dump ("raw tx data:", skb->data, skb->len); */
143 if (bc->mode == L1_MODE_TRANS) {
144 bytes_sent = buf_size - len;
145 if (skb->len < bytes_sent)
146 bytes_sent = skb->len;
147 { /* swap tx bytes */
148 register unsigned char *src =
151 for (count = 0; count < bytes_sent;
158 bc->lastbyte = skb->data[bytes_sent - 1];
161 isdnhdlc_encode(&bc->outp_hdlc_state,
164 ucp, buf_size - len);
165 /* dump ("hdlc data:", ucp, bs); */
169 skb_pull(skb, bytes_sent);
174 spin_unlock_irqrestore(&bc->txskb_lock,
176 auerisdn_b_l1l2(bc, PH_DATA | CONFIRM,
177 (void *) skb->truesize);
178 dev_kfree_skb_any(skb);
182 if (bc->mode == L1_MODE_TRANS) {
183 memset(ucp, bc->lastbyte, buf_size - len);
184 ucp += buf_size - len;
186 /* dbg ("fill = 0xFF"); */
190 isdnhdlc_encode(&bc->outp_hdlc_state,
191 NULL, 0, &bytes_sent,
192 ucp, buf_size - len);
193 /* dbg ("fill = 0x%02X", (int)*ucp); */
198 spin_unlock_irqrestore(&bc->txskb_lock, flags);
200 /* dbg ("%d Bytes to TX buffer", len); */
204 /* INT OUT completion handler */
205 static void auerisdn_bintbo_complete(struct urb *urbp)
207 struct auerisdn *ip = urbp->context;
209 /* unlink completion? */
210 if ((urbp->status == -ENOENT) || (urbp->status == -ECONNRESET)) {
211 /* should we restart with another size? */
212 if (ip->intbo_state == INTBOS_CHANGE) {
213 dbg("state => RESTART");
214 ip->intbo_state = INTBOS_RESTART;
216 /* set up variables for later restart */
217 dbg("INTBO stopped");
218 ip->intbo_state = INTBOS_IDLE;
220 /* nothing more to do */
224 /* other state != 0? */
226 warn("auerisdn_bintbo_complete: status = %d",
231 /* Should we fill in new data? */
232 if (ip->intbo_state == INTBOS_CHANGE) {
233 dbg("state == INTBOS_CHANGE, no new data");
237 /* fill in new data */
238 auerisdn_bintbo_newdata(ip);
241 /* set up the INT OUT URB the first time */
242 /* Don't start the URB */
243 static void auerisdn_bintbo_setup(struct auerisdn *ip, unsigned int len)
245 ip->intbo_state = INTBOS_IDLE;
246 FILL_INT_URB(ip->intbo_urbp, ip->usbdev,
247 usb_sndintpipe(ip->usbdev, ip->intbo_endp),
248 ip->intbo_bufp, len, auerisdn_bintbo_complete, ip,
250 ip->intbo_urbp->transfer_flags |= USB_ASYNC_UNLINK;
251 ip->intbo_urbp->status = 0;
254 /* restart the INT OUT endpoint */
255 static void auerisdn_bintbo_restart(struct auerisdn *ip)
257 struct urb *urbp = ip->intbo_urbp;
260 /* dbg ("auerisdn_intbo_restart"); */
263 auerisdn_bintbo_setup(ip, ip->paketsize + AUH_SIZE);
265 /* Fill in new data */
266 auerisdn_bintbo_newdata(ip);
268 /* restart the urb */
269 ip->intbo_state = INTBOS_RUNNING;
270 status = usb_submit_urb(urbp);
272 err("can't submit INT OUT urb, status = %d", status);
273 urbp->status = status;
274 urbp->complete(urbp);
278 /* change the size of the INT OUT endpoint */
279 static void auerisdn_bchange(struct auerisdn *ip, unsigned int paketsize)
282 dbg("txfree[0] = %d, txfree[1] = %d, old size = %d, new size = %d",
283 ip->bc[0].txfree, ip->bc[1].txfree, ip->paketsize, paketsize);
284 ip->paketsize = paketsize;
286 if (paketsize == 0) {
287 /* stop the INT OUT endpoint */
288 dbg("stop unlinking INT out urb");
289 ip->intbo_state = INTBOS_IDLE;
290 usb_unlink_urb(ip->intbo_urbp);
293 if (ip->intbo_state != INTBOS_IDLE) {
294 /* dbg ("unlinking INT out urb"); */
295 ip->intbo_state = INTBOS_CHANGE;
296 usb_unlink_urb(ip->intbo_urbp);
298 /* dbg ("restart immediately"); */
299 auerisdn_bintbo_restart(ip);
303 /* serve the outgoing B channel interrupt */
304 /* Called from the INT IN completion handler */
305 static void auerisdn_bserv(struct auerisdn *ip)
307 struct auerisdnbc *bc;
309 unsigned int paketsize;
311 /* should we start the INT OUT endpoint again? */
312 if (ip->intbo_state == INTBOS_RESTART) {
313 /* dbg ("Restart INT OUT from INT IN"); */
314 auerisdn_bintbo_restart(ip);
317 /* no new calculation if change already in progress */
318 if (ip->intbo_state == INTBOS_CHANGE)
321 /* calculation of transfer parameters for INT OUT endpoint */
323 for (u = 0; u < AUISDN_BCHANNELS; u++) {
325 if (bc->mode != L1_MODE_NULL) { /* B channel is active */
326 unsigned int bpp = AUISDN_BC_1MS * ip->outInterval;
327 if (bc->txfree < bpp) { /* buffer is full, throttle */
328 bc->txsize = bpp - AUISDN_BC_INC;
329 paketsize += bpp - AUISDN_BC_INC;
330 } else if (bc->txfree < bpp * 2) {
331 paketsize += bc->txsize; /* schmidt-trigger, continue */
332 } else if (bc->txfree < bpp * 4) { /* we are in synch */
335 } else if (bc->txfree > bc->ofsize / 2) {/* we have to fill the buffer */
336 bc->txsize = bpp + AUISDN_BC_INC;
337 paketsize += bpp + AUISDN_BC_INC;
339 paketsize += bc->txsize; /* schmidt-trigger, continue */
344 /* check if we have to change the paket size */
345 if (paketsize != ip->paketsize)
346 auerisdn_bchange(ip, paketsize);
349 /* Send activation/deactivation state to L2 */
350 static void auerisdn_bconf(struct auerisdnbc *bc)
355 if (bc->mode == L1_MODE_NULL) {
356 auerisdn_b_l1l2(bc, PH_DEACTIVATE | INDICATION, NULL);
357 /* recycle old txskb */
358 spin_lock_irqsave(&bc->txskb_lock, flags);
361 spin_unlock_irqrestore(&bc->txskb_lock, flags);
363 skb_pull(skb, skb->len);
364 auerisdn_b_l1l2(bc, PH_DATA | CONFIRM,
365 (void *) skb->truesize);
366 dev_kfree_skb_any(skb);
369 auerisdn_b_l1l2(bc, PH_ACTIVATE | INDICATION, NULL);
373 /* B channel setup completion handler */
374 static void auerisdn_bmode_complete(struct urb *urb)
376 struct auerswald *cp;
377 struct auerbuf *bp = (struct auerbuf *) urb->context;
378 struct auerisdnbc *bc;
381 dbg("auerisdn_bmode_complete called");
382 cp = ((struct auerswald *) ((char *) (bp->list) -
384 long) (&((struct auerswald *) 0)->
387 /* select the B-channel */
388 channel = le16_to_cpu(bp->dr->wIndex);
389 channel -= AUH_B1CHANNEL;
392 if (channel >= AUISDN_BCHANNELS)
394 bc = &cp->isdn.bc[channel];
396 /* Check for success */
398 err("complete with non-zero status: %d", urb->status);
400 bc->mode = *bp->bufp;
402 /* Signal current mode to L2 */
405 /* reuse the buffer */
406 rel:auerbuf_releasebuf(bp);
408 /* Wake up all processes waiting for a buffer */
409 wake_up(&cp->bufferwait);
412 /* Setup a B channel transfer mode */
413 static void auerisdn_bmode(struct auerisdnbc *bc, unsigned int mode)
415 struct auerswald *cp = bc->cp;
419 /* don't allow activation on disconnect */
420 if (cp->disconnecting) {
423 /* Else check if something changed */
424 } else if (bc->mode != mode) {
425 if ((mode != L1_MODE_NULL) && (mode != L1_MODE_TRANS)) {
426 /* init RX hdlc decoder */
428 isdnhdlc_rcv_init(&bc->inp_hdlc_state, 0);
429 /* init TX hdlc decoder */
431 isdnhdlc_out_init(&bc->outp_hdlc_state, 0, 0);
434 if (mode == L1_MODE_NULL)
436 if ((bc->mode == L1_MODE_NULL) || (mode == L1_MODE_NULL)) {
437 /* Activation or deactivation required */
439 /* get a buffer for the command */
440 bp = auerbuf_getbuf(&cp->bufctl);
441 /* if no buffer available: can't change the mode */
443 err("auerisdn_bmode: no data buffer available");
447 /* fill the control message */
448 bp->dr->bRequestType = AUT_WREQ;
449 bp->dr->bRequest = AUV_CHANNELCTL;
450 if (mode != L1_MODE_NULL)
451 bp->dr->wValue = cpu_to_le16(1);
453 bp->dr->wValue = cpu_to_le16(0);
455 cpu_to_le16(AUH_B1CHANNEL + bc->channel);
456 bp->dr->wLength = cpu_to_le16(0);
458 FILL_CONTROL_URB(bp->urbp, cp->usbdev,
459 usb_sndctrlpipe(cp->usbdev, 0),
460 (unsigned char *) bp->dr,
463 auerisdn_bmode_complete, bp);
465 /* submit the control msg */
467 auerchain_submit_urb(&cp->controlchain,
470 bp->urbp->status = ret;
471 auerisdn_bmode_complete(bp->urbp);
476 /* new mode is set */
479 /* send confirmation to L2 */
483 /* B-channel transfer function L2->L1 */
484 void auerisdn_b_l2l1(struct hisax_if *ifc, int pr, void *arg,
485 unsigned int channel)
487 struct auerhisax *ahp;
488 struct auerisdnbc *bc;
489 struct auerswald *cp;
495 ahp = (struct auerhisax *) ifc->priv;
498 if (cp && !cp->disconnecting) {
499 /* normal execution */
500 bc = &cp->isdn.bc[channel];
502 case PH_ACTIVATE | REQUEST: /* activation request */
503 mode = (int) arg; /* one of the L1_MODE constants */
504 dbg("B%d, PH_ACTIVATE_REQUEST Mode = %d",
505 bc->channel + 1, mode);
506 auerisdn_bmode(bc, mode);
508 case PH_DEACTIVATE | REQUEST: /* deactivation request */
509 dbg("B%d, PH_DEACTIVATE_REQUEST", bc->channel + 1);
510 auerisdn_bmode(bc, L1_MODE_NULL);
512 case PH_DATA | REQUEST: /* Transmit data request */
513 skb = (struct sk_buff *) arg;
514 spin_lock_irqsave(&bc->txskb_lock, flags);
516 err("Overflow in B channel TX");
517 skb_pull(skb, skb->len);
518 dev_kfree_skb_any(skb);
520 if (cp->disconnecting
521 || (bc->mode == L1_MODE_NULL)) {
522 skb_pull(skb, skb->len);
523 spin_unlock_irqrestore(&bc->
530 dev_kfree_skb_any(skb);
535 spin_unlock_irqrestore(&bc->txskb_lock, flags);
538 warn("pr %#x\n", pr);
542 /* hisax interface is down */
544 case PH_ACTIVATE | REQUEST: /* activation request */
545 dbg("B channel: PH_ACTIVATE | REQUEST with interface down");
546 /* don't answer this request! Endless... */
548 case PH_DEACTIVATE | REQUEST: /* deactivation request */
549 dbg("B channel: PH_DEACTIVATE | REQUEST with interface down");
550 ifc->l1l2(ifc, PH_DEACTIVATE | INDICATION, NULL);
552 case PH_DATA | REQUEST: /* Transmit data request */
553 dbg("B channel: PH_DATA | REQUEST with interface down");
554 skb = (struct sk_buff *) arg;
555 /* free data buffer */
557 skb_pull(skb, skb->len);
558 dev_kfree_skb_any(skb);
560 /* send confirmation back to layer 2 */
561 ifc->l1l2(ifc, PH_DATA | CONFIRM, NULL);
564 warn("pr %#x\n", pr);
570 /* Completion handler for B channel input endpoint */
571 void auerisdn_intbi_complete(struct urb *urb)
573 unsigned int bytecount;
576 unsigned int syncbit;
577 unsigned int syncdata;
578 struct auerisdnbc *bc;
582 struct auerswald *cp = (struct auerswald *) urb->context;
583 /* do not respond to an error condition */
584 if (urb->status != 0) {
585 dbg("nonzero URB status = %d", urb->status);
588 if (cp->disconnecting)
591 /* Parse and extract the header information */
592 bytecount = urb->actual_length;
593 ucp = cp->isdn.intbi_bufp;
595 return; /* no data */
596 channel = *ucp & AUH_TYPEMASK;
597 syncbit = *ucp & AUH_SYNC;
600 channel -= AUH_B1CHANNEL;
602 return; /* unknown data channel, no B1,B2 */
603 if (channel >= AUISDN_BCHANNELS)
604 return; /* unknown data channel, no B1,B2 */
605 bc = &cp->isdn.bc[channel];
608 /* Calculate amount of bytes which are free in tx device buffer */
609 bc->txfree = ((255 - *ucp++) * bc->ofsize) / 256;
610 /* dbg ("%d Bytes free in TX buffer", bc->txfree); */
613 /* Next Byte: TX sync information */
618 dbg("Sync data = %d", syncdata);
621 /* The rest of the paket is plain data */
624 /* dump ("RX Data is:", ucp, bytecount); */
626 /* Send B channel data to upper layers */
627 while (bytecount > 0) {
628 if (bc->mode == L1_MODE_NULL) {
629 /* skip the data. Nobody needs them */
632 } else if (bc->mode == L1_MODE_TRANS) {
633 { /* swap rx bytes */
634 register unsigned char *dest = bc->rxbuf;
636 for (; bytecount; bytecount--)
638 isdnhdlc_bit_rev_tab[*ucp++];
642 status = isdnhdlc_decode(&bc->inp_hdlc_state, ucp,
644 bc->rxbuf, AUISDN_RXSIZE);
649 /* Good frame received */
650 if (!(skb = dev_alloc_skb(status))) {
651 warn("receive out of memory");
654 memcpy(skb_put(skb, status), bc->rxbuf, status);
655 /* dump ("HDLC Paket", bc->rxbuf, status); */
656 auerisdn_b_l1l2(bc, PH_DATA | INDICATION, skb);
657 /* these errors may actually happen at the start of a connection! */
658 } else if (status == -HDLC_CRC_ERROR) {
660 } else if (status == -HDLC_FRAMING_ERROR) {
661 dbg("framing error");
662 } else if (status == -HDLC_LENGTH_ERROR) {
667 int_tx: /* serve the outgoing B channel */
668 auerisdn_bserv(&cp->isdn);
671 /* Stop the B channel activity. The device is disconnecting */
672 /* This function is called after cp->disconnecting is true */
673 unsigned int auerisdn_b_disconnect(struct auerswald *cp)
676 struct auerisdnbc *bc;
677 unsigned int result = 0;
679 /* Close the B channels */
680 for (u = 0; u < AUISDN_BCHANNELS; u++) {
681 bc = &cp->isdn.bc[u];
682 if (bc->mode != L1_MODE_NULL) { /* B channel is active */
683 auerisdn_bmode(bc, L1_MODE_NULL);
687 /* return 1 if there is B channel traffic */