2 * Copyright (c) 1997, 2000 Hellmuth Michaelis. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
13 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
14 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
17 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 *---------------------------------------------------------------------------
27 * i4b_l2if.c - Layer 3 interface to Layer 2
28 * -------------------------------------------
30 * $Id: i4b_l2if.c,v 1.11 2005/12/11 12:25:06 christos Exp $
34 * last edit-date: [Fri Jan 5 11:33:47 2001]
36 *---------------------------------------------------------------------------*/
38 #include <sys/cdefs.h>
39 __KERNEL_RCSID(0, "$NetBSD: i4b_l2if.c,v 1.7.6.4 2005/03/04 16:53:45 skrll Exp $");
48 #include <sys/param.h>
49 #include <sys/kernel.h>
50 #include <sys/systm.h>
52 #include <sys/socket.h>
55 #if defined(__NetBSD__) && __NetBSD_Version__ >= 104230000
56 #include <sys/callout.h>
60 #include <machine/i4b_debug.h>
61 #include <machine/i4b_ioctl.h>
62 #include <machine/i4b_cause.h>
64 #include <netisdn/i4b_debug.h>
65 #include <netisdn/i4b_ioctl.h>
66 #include <netisdn/i4b_cause.h>
69 #include <netisdn/i4b_isdnq931.h>
70 #include <netisdn/i4b_l3l4.h>
71 #include <netisdn/i4b_mbuf.h>
73 #include <netisdn/i4b_l2.h>
74 #include <netisdn/i4b_l1l2.h>
75 #include <netisdn/i4b_l3.h>
76 #include <netisdn/i4b_l3fsm.h>
77 #include <netisdn/i4b_q931.h>
79 #include <netisdn/i4b_l4.h>
81 static unsigned char make_q931_cause(cause_t cause
);
83 /*---------------------------------------------------------------------------*
84 * this converts our internal state (number) to the number specified
85 * in Q.931 and is used for reporting our state in STATUS messages.
86 *---------------------------------------------------------------------------*/
87 int i4b_status_tab
[] = {
106 /*---------------------------------------------------------------------------*
107 * return a valid q.931/q.850 cause from any of the internal causes
108 *---------------------------------------------------------------------------*/
110 make_q931_cause(cause_t cause
)
112 register unsigned char ret
;
114 switch(GET_CAUSE_TYPE(cause
))
117 ret
= GET_CAUSE_VAL(cause
);
120 ret
= cause_tab_q931
[GET_CAUSE_VAL(cause
)];
123 panic("make_q931_cause: unknown cause type!");
130 /*---------------------------------------------------------------------------*
131 * return status of data link
132 *---------------------------------------------------------------------------*/
134 i4b_get_dl_stat(call_desc_t
*cd
)
136 const struct isdn_l3_driver
* drv
= cd
->l3drv
;
140 /*---------------------------------------------------------------------------*
141 * DL ESTABLISH INDICATION from Layer 2
142 *---------------------------------------------------------------------------*/
144 i4b_dl_establish_ind(struct isdn_l3_driver
* drv
)
147 NDBGL2(L2_PRIM
, "DL-ESTABLISH-IND isdnif %d", drv
->isdnif
);
149 /* first set DL up in controller descriptor */
150 NDBGL3(L3_MSG
, "isdnif %d DL established!", drv
->isdnif
);
155 /* second, inform all (!) active call of the event */
157 for(i
=0; i
< num_call_desc
; i
++)
159 if( (call_desc
[i
].cdid
!= 0)
160 && call_desc
[i
].isdnif
== drv
->isdnif
) {
161 next_l3state(&call_desc
[i
], EV_DLESTIN
);
168 NDBGL3(L3_ERR
, "ERROR, no cdid for isdnif %d found!",
178 /*---------------------------------------------------------------------------*
179 * DL ESTABLISH CONFIRM from Layer 2
180 *---------------------------------------------------------------------------*/
182 i4b_dl_establish_cnf(struct isdn_l3_driver
* drv
)
187 NDBGL2(L2_PRIM
, "DL-ESTABLISH-CONF isdnif %d", drv
->isdnif
);
189 for(i
=0; i
< num_call_desc
; i
++)
191 if(call_desc
[i
].cdid
!= 0
192 && call_desc
[i
].isdnif
== drv
->isdnif
) {
194 next_l3state(&call_desc
[i
], EV_DLESTCF
);
201 NDBGL3(L3_ERR
, "ERROR, no cdid for isdnif %d found!",
211 /*---------------------------------------------------------------------------*
212 * DL RELEASE INDICATION from Layer 2
213 *---------------------------------------------------------------------------*/
215 i4b_dl_release_ind(struct isdn_l3_driver
* drv
)
220 NDBGL2(L2_PRIM
, "DL-RELEASE-IND isdnif %d", drv
->isdnif
);
222 /* first set controller to down */
224 drv
->dl_est
= DL_DOWN
;
228 /* second, inform all (!) active calls of the event */
230 for(i
=0; i
< num_call_desc
; i
++)
232 if(call_desc
[i
].cdid
!= 0
233 && call_desc
[i
].isdnif
== drv
->isdnif
) {
234 next_l3state(&call_desc
[i
], EV_DLRELIN
);
241 /* this is not an error since it might be a normal call end */
242 NDBGL3(L3_MSG
, "no cdid for isdnif %d found", drv
->isdnif
);
247 /*---------------------------------------------------------------------------*
248 * DL RELEASE CONFIRM from Layer 2
249 *---------------------------------------------------------------------------*/
251 i4b_dl_release_cnf(struct isdn_l3_driver
* drv
)
253 NDBGL2(L2_PRIM
, "DL-RELEASE-CONF isdnif %d", drv
->isdnif
);
255 drv
->dl_est
= DL_DOWN
;
259 /*---------------------------------------------------------------------------*
260 * i4b_dl_data_ind - process a rx'd I-frame got from layer 2
261 *---------------------------------------------------------------------------*/
263 i4b_dl_data_ind(struct isdn_l3_driver
*drv
, struct mbuf
*m
)
265 i4b_decode_q931(drv
->isdnif
, m
->m_len
, m
->m_data
);
270 /*---------------------------------------------------------------------------*
271 * dl_unit_data_ind - process a rx'd U-frame got from layer 2
272 *---------------------------------------------------------------------------*/
274 i4b_dl_unit_data_ind(struct isdn_l3_driver
*drv
, struct mbuf
*m
)
276 i4b_decode_q931(drv
->isdnif
, m
->m_len
, m
->m_data
);
281 /*---------------------------------------------------------------------------*
282 * send CONNECT message
283 *---------------------------------------------------------------------------*/
285 i4b_l3_tx_connect(call_desc_t
*cd
)
287 struct l2_softc
*l2sc
= (l2_softc_t
*)cd
->l3drv
->l1_token
;
291 NDBGL3(L3_PRIM
, "isdnif %d, cr = 0x%02x", cd
->isdnif
, cd
->cr
);
293 if((m
= i4b_Dgetmbuf(I_FRAME_HDRLEN
+ MSG_CONNECT_LEN
)) == NULL
)
294 panic("i4b_l3_tx_connect: can't allocate mbuf");
296 ptr
= m
->m_data
+ I_FRAME_HDRLEN
;
298 *ptr
++ = PD_Q931
; /* protocol discriminator */
299 *ptr
++ = 0x01; /* call reference length */
300 *ptr
++ = setup_cr(cd
, cd
->cr
); /* call reference value */
301 *ptr
++ = CONNECT
; /* message type = connect */
303 i4b_dl_data_req(l2sc
, l2sc
->drv
, m
);
306 /*---------------------------------------------------------------------------*
307 * send RELEASE COMPLETE message
308 *---------------------------------------------------------------------------*/
310 i4b_l3_tx_release_complete(call_desc_t
*cd
, int send_cause_flag
)
312 struct l2_softc
*l2sc
= (l2_softc_t
*)cd
->l3drv
->l1_token
;
315 int len
= I_FRAME_HDRLEN
+ MSG_RELEASE_COMPLETE_LEN
;
317 if(send_cause_flag
== 0)
320 NDBGL3(L3_PRIM
, "isdnif %d, cr = 0x%02x",
325 NDBGL3(L3_PRIM
, "isdnif=%d, cr=0x%02x, cause=0x%x",
326 cd
->isdnif
, cd
->cr
, cd
->cause_out
);
329 if((m
= i4b_Dgetmbuf(len
)) == NULL
)
330 panic("i4b_l3_tx_release_complete: can't allocate mbuf");
332 ptr
= m
->m_data
+ I_FRAME_HDRLEN
;
334 *ptr
++ = PD_Q931
; /* protocol discriminator */
335 *ptr
++ = 0x01; /* call reference length */
336 *ptr
++ = setup_cr(cd
, cd
->cr
); /* call reference value */
337 *ptr
++ = RELEASE_COMPLETE
; /* message type = release complete */
341 *ptr
++ = IEI_CAUSE
; /* cause ie */
343 *ptr
++ = CAUSE_STD_LOC_OUT
;
344 *ptr
++ = make_q931_cause(cd
->cause_out
);
347 i4b_dl_data_req(l2sc
, l2sc
->drv
, m
);
350 /*---------------------------------------------------------------------------*
351 * send DISCONNECT message
352 *---------------------------------------------------------------------------*/
354 i4b_l3_tx_disconnect(call_desc_t
*cd
)
356 struct l2_softc
*l2sc
= (l2_softc_t
*)cd
->l3drv
->l1_token
;
360 NDBGL3(L3_PRIM
, "isdnif %d, cr = 0x%02x", cd
->isdnif
, cd
->cr
);
362 if((m
= i4b_Dgetmbuf(I_FRAME_HDRLEN
+ MSG_DISCONNECT_LEN
)) == NULL
)
363 panic("i4b_l3_tx_disconnect: can't allocate mbuf");
365 ptr
= m
->m_data
+ I_FRAME_HDRLEN
;
367 *ptr
++ = PD_Q931
; /* protocol discriminator */
368 *ptr
++ = 0x01; /* call ref length */
369 *ptr
++ = setup_cr(cd
, cd
->cr
); /* call reference value */
370 *ptr
++ = DISCONNECT
; /* message type = disconnect */
372 *ptr
++ = IEI_CAUSE
; /* cause ie */
374 *ptr
++ = CAUSE_STD_LOC_OUT
;
375 *ptr
++ = make_q931_cause(cd
->cause_out
);
377 i4b_dl_data_req(l2sc
, l2sc
->drv
, m
);
380 /*---------------------------------------------------------------------------*
382 *---------------------------------------------------------------------------*/
384 i4b_l3_tx_setup(call_desc_t
*cd
)
386 struct l2_softc
*l2sc
= (l2_softc_t
*)cd
->l3drv
->l1_token
;
389 int slen
= strlen(cd
->src_telno
);
390 int dlen
= strlen(cd
->dst_telno
);
391 int msglen
= I_FRAME_HDRLEN
+ MSG_SETUP_LEN
+ slen
+ dlen
+
392 (cd
->bprot
== BPROT_NONE
? 1 : 0);
395 msglen
-= IEI_CALLINGPN_LEN
+2; /* whole IE not send */
398 * there is one additional octet if cd->bprot == BPROT_NONE
399 * NOTE: the selection of a bearer capability by a B L1
400 * protocol is highly questionable and a better
401 * mechanism should be used in future. (-hm)
404 NDBGL3(L3_PRIM
, "isdnif %d, cr = 0x%02x", cd
->isdnif
, cd
->cr
);
406 if((m
= i4b_Dgetmbuf(msglen
)) == NULL
)
408 panic("i4b_l3_tx_setup: can't allocate mbuf");
411 cd
->crflag
= CRF_ORIG
; /* we are the originating side */
413 ptr
= m
->m_data
+ I_FRAME_HDRLEN
;
415 *ptr
++ = PD_Q931
; /* protocol discriminator */
416 *ptr
++ = 0x01; /* call ref length */
417 *ptr
++ = setup_cr(cd
, cd
->cr
); /* call reference value */
418 *ptr
++ = SETUP
; /* message type = setup */
420 *ptr
++ = IEI_SENDCOMPL
; /* sending complete */
422 *ptr
++ = IEI_BEARERCAP
; /* bearer capability */
425 * currently i have no idea if this should be switched by
426 * the choosen B channel protocol or if there should be a
427 * separate configuration item for the bearer capability.
428 * For now, it is switched by the choosen b protocol (-hm)
433 case BPROT_NONE
: /* telephony */
434 *ptr
++ = IEI_BEARERCAP_LEN
+1;
435 *ptr
++ = IT_CAP_SPEECH
;
436 *ptr
++ = IT_RATE_64K
;
437 *ptr
++ = IT_UL1_G711A
;
440 case BPROT_RHDLC
: /* raw HDLC */
441 *ptr
++ = IEI_BEARERCAP_LEN
;
442 *ptr
++ = IT_CAP_UNR_DIG_INFO
;
443 *ptr
++ = IT_RATE_64K
;
447 *ptr
++ = IEI_BEARERCAP_LEN
;
448 *ptr
++ = IT_CAP_UNR_DIG_INFO
;
449 *ptr
++ = IT_RATE_64K
;
453 *ptr
++ = IEI_CHANNELID
; /* channel id */
454 *ptr
++ = IEI_CHANNELID_LEN
; /* channel id length */
456 switch(cd
->channelid
)
459 *ptr
++ = CHANNELID_B1
;
462 *ptr
++ = CHANNELID_B2
;
465 *ptr
++ = CHANNELID_ANY
;
470 *ptr
++ = IEI_CALLINGPN
; /* calling party no */
471 *ptr
++ = IEI_CALLINGPN_LEN
+slen
;/* calling party no length */
472 *ptr
++ = NUMBER_TYPEPLAN
; /* type of number, number plan id */
473 strncpy(ptr
, cd
->src_telno
, slen
);
477 *ptr
++ = IEI_CALLEDPN
; /* called party no */
478 *ptr
++ = IEI_CALLEDPN_LEN
+dlen
; /* called party no length */
479 *ptr
++ = NUMBER_TYPEPLAN
; /* type of number, number plan id */
480 strncpy(ptr
, cd
->dst_telno
, dlen
);
483 i4b_dl_data_req(l2sc
, l2sc
->drv
, m
);
486 /*---------------------------------------------------------------------------*
487 * send CONNECT ACKNOWLEDGE message
488 *---------------------------------------------------------------------------*/
490 i4b_l3_tx_connect_ack(call_desc_t
*cd
)
492 struct l2_softc
*l2sc
= (l2_softc_t
*)cd
->l3drv
->l1_token
;
496 NDBGL3(L3_PRIM
, "isdnif %d, cr = 0x%02x", cd
->isdnif
, cd
->cr
);
498 if((m
= i4b_Dgetmbuf(I_FRAME_HDRLEN
+ MSG_CONNECT_ACK_LEN
)) == NULL
)
499 panic("i4b_l3_tx_connect_ack: can't allocate mbuf");
501 ptr
= m
->m_data
+ I_FRAME_HDRLEN
;
503 *ptr
++ = PD_Q931
; /* protocol discriminator */
504 *ptr
++ = 0x01; /* call reference length */
505 *ptr
++ = setup_cr(cd
, cd
->cr
); /* call reference value */
506 *ptr
++ = CONNECT_ACKNOWLEDGE
; /* message type = connect ack */
508 i4b_dl_data_req(l2sc
, l2sc
->drv
, m
);
511 /*---------------------------------------------------------------------------*
512 * send STATUS message
513 *---------------------------------------------------------------------------*/
515 i4b_l3_tx_status(call_desc_t
*cd
, u_char q850cause
)
517 struct l2_softc
*l2sc
= (l2_softc_t
*)cd
->l3drv
->l1_token
;
521 NDBGL3(L3_PRIM
, "isdnif %d, cr = 0x%02x", cd
->isdnif
, cd
->cr
);
523 if((m
= i4b_Dgetmbuf(I_FRAME_HDRLEN
+ MSG_STATUS_LEN
)) == NULL
)
524 panic("i4b_l3_tx_status: can't allocate mbuf");
526 ptr
= m
->m_data
+ I_FRAME_HDRLEN
;
528 *ptr
++ = PD_Q931
; /* protocol discriminator */
529 *ptr
++ = 0x01; /* call reference length */
530 *ptr
++ = setup_cr(cd
, cd
->cr
); /* call reference value */
531 *ptr
++ = STATUS
; /* message type = connect ack */
533 *ptr
++ = IEI_CAUSE
; /* cause ie */
535 *ptr
++ = CAUSE_STD_LOC_OUT
;
536 *ptr
++ = q850cause
| EXT_LAST
;
538 *ptr
++ = IEI_CALLSTATE
; /* call state ie */
539 *ptr
++ = CALLSTATE_LEN
;
540 *ptr
++ = i4b_status_tab
[cd
->Q931state
];
542 i4b_dl_data_req(l2sc
, l2sc
->drv
, m
);
545 /*---------------------------------------------------------------------------*
546 * send RELEASE message
547 *---------------------------------------------------------------------------*/
549 i4b_l3_tx_release(call_desc_t
*cd
, int send_cause_flag
)
551 struct l2_softc
*l2sc
= (l2_softc_t
*)cd
->l3drv
->l1_token
;
554 int len
= I_FRAME_HDRLEN
+ MSG_RELEASE_LEN
;
556 NDBGL3(L3_PRIM
, "isdnif %d, cr = 0x%02x", cd
->isdnif
, cd
->cr
);
558 if(send_cause_flag
== 0)
561 if((m
= i4b_Dgetmbuf(len
)) == NULL
)
562 panic("i4b_l3_tx_release: can't allocate mbuf");
564 ptr
= m
->m_data
+ I_FRAME_HDRLEN
;
566 *ptr
++ = PD_Q931
; /* protocol discriminator */
567 *ptr
++ = 0x01; /* call reference length */
568 *ptr
++ = setup_cr(cd
, cd
->cr
); /* call reference value */
569 *ptr
++ = RELEASE
; /* message type = release complete */
573 *ptr
++ = IEI_CAUSE
; /* cause ie */
575 *ptr
++ = CAUSE_STD_LOC_OUT
;
576 *ptr
++ = make_q931_cause(cd
->cause_out
);
579 i4b_dl_data_req(l2sc
, l2sc
->drv
, m
);
582 /*---------------------------------------------------------------------------*
583 * send ALERTING message
584 *---------------------------------------------------------------------------*/
586 i4b_l3_tx_alert(call_desc_t
*cd
)
588 struct l2_softc
*l2sc
= (l2_softc_t
*)cd
->l3drv
->l1_token
;
592 if((m
= i4b_Dgetmbuf(I_FRAME_HDRLEN
+ MSG_ALERT_LEN
)) == NULL
)
593 panic("i4b_l3_tx_alert: can't allocate mbuf");
595 NDBGL3(L3_PRIM
, "isdnif %d, cr = 0x%02x", cd
->isdnif
, cd
->cr
);
597 ptr
= m
->m_data
+ I_FRAME_HDRLEN
;
599 *ptr
++ = PD_Q931
; /* protocol discriminator */
600 *ptr
++ = 0x01; /* call reference length */
601 *ptr
++ = setup_cr(cd
, cd
->cr
); /* call reference value */
602 *ptr
++ = ALERT
; /* message type = alert */
604 i4b_dl_data_req(l2sc
, l2sc
->drv
, m
);
607 #endif /* NI4BQ931 > 0 */