Expand PMF_FN_* macros.
[netbsd-mini2440.git] / sys / netisdn / i4b_l4.c
blob338818ea69eecc96992c99ccaf957ef4b7f34570
1 /*
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
6 * are met:
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
23 * SUCH DAMAGE.
25 *---------------------------------------------------------------------------
27 * i4b_l4.c - kernel interface to userland
28 * -----------------------------------------
30 * $Id: i4b_l4.c,v 1.32 2006/11/16 01:33:49 christos Exp $
32 * $FreeBSD$
34 * last edit-date: [Fri Jan 5 11:33:47 2001]
36 *---------------------------------------------------------------------------*/
38 #include <sys/cdefs.h>
39 __KERNEL_RCSID(0, "$NetBSD: i4b_l4.c,v 1.31 2006/10/16 12:23:00 pooka Exp $");
41 #include "isdn.h"
42 #include "irip.h"
44 #if NISDN > 0
46 #include <sys/param.h>
47 #include <sys/kernel.h>
48 #include <sys/systm.h>
49 #include <sys/conf.h>
50 #include <sys/mbuf.h>
51 #include <sys/proc.h>
52 #include <sys/fcntl.h>
53 #include <sys/socket.h>
54 #include <net/if.h>
56 #if defined(__NetBSD__) && __NetBSD_Version__ >= 104230000
57 #include <sys/callout.h>
58 #endif
60 #ifdef __FreeBSD__
61 #include <machine/i4b_debug.h>
62 #include <machine/i4b_ioctl.h>
63 #include <machine/i4b_cause.h>
64 #else
65 #include <netisdn/i4b_debug.h>
66 #include <netisdn/i4b_ioctl.h>
67 #include <netisdn/i4b_cause.h>
68 #endif
70 #include <netisdn/i4b_global.h>
71 #include <netisdn/i4b_l3l4.h>
72 #include <netisdn/i4b_mbuf.h>
73 #include <netisdn/i4b_l2.h>
74 #include <netisdn/i4b_l3.h>
75 #include <netisdn/i4b_l4.h>
77 unsigned int i4b_l4_debug = L4_DEBUG_DEFAULT;
80 * ISDNs, in userland sometimes called "controllers", but one controller
81 * may have multiple BRIs, for example daic QUAD cards attach four BRIs.
82 * An ISDN may also be a PRI (30 B channels).
84 static SLIST_HEAD(, isdn_l3_driver) isdnif_list = SLIST_HEAD_INITIALIZER(isdnif_list);
85 static int next_isdnif = 0;
88 * Attach a new L3 driver instance and return its ISDN identifier
90 struct isdn_l3_driver *
91 isdn_attach_isdnif(const char *devname, const char *cardname,
92 void *l1_token, const struct isdn_l3_driver_functions *l3driver, int nbch)
94 int s = splnet();
95 int i, l, isdnif = next_isdnif++;
96 struct isdn_l3_driver *new_ctrl;
98 new_ctrl = malloc(sizeof(*new_ctrl), M_DEVBUF, M_WAITOK|M_ZERO);
99 SLIST_INSERT_HEAD(&isdnif_list, new_ctrl, l3drvq);
100 l = strlen(devname);
101 new_ctrl->devname = malloc(l + 1, M_DEVBUF, M_WAITOK);
102 strlcpy(new_ctrl->devname, devname, l + 1);
103 l = strlen(cardname);
104 new_ctrl->card_name = malloc(l + 1, M_DEVBUF, M_WAITOK);
105 strlcpy(new_ctrl->card_name, cardname, l + 1);
107 new_ctrl->l3driver = l3driver;
108 new_ctrl->l1_token = l1_token;
109 new_ctrl->isdnif = isdnif;
110 new_ctrl->tei = -1;
111 new_ctrl->dl_est = DL_DOWN;
112 new_ctrl->nbch = nbch;
114 new_ctrl->bch_state = malloc(nbch * sizeof(int), M_DEVBUF, M_WAITOK);
115 for (i = 0; i < nbch; i++)
116 new_ctrl->bch_state[i] = BCH_ST_FREE;
118 splx(s);
120 return new_ctrl;
124 * Detach a L3 driver instance
127 isdn_detach_isdnif(struct isdn_l3_driver *l3drv)
129 struct isdn_l3_driver *sc;
130 int s = splnet();
131 int isdnif = l3drv->isdnif;
132 int maxidx;
134 i4b_l4_contr_ev_ind(isdnif, 0);
135 SLIST_REMOVE(&isdnif_list, l3drv, isdn_l3_driver, l3drvq);
137 maxidx = -1;
138 SLIST_FOREACH(sc, &isdnif_list, l3drvq)
139 if (sc->isdnif > maxidx)
140 maxidx = sc->isdnif;
141 next_isdnif = maxidx+1;
143 free_all_cd_of_isdnif(isdnif);
145 splx(s);
147 free(l3drv, M_DEVBUF);
148 printf("ISDN %d detached\n", isdnif);
149 return 1;
152 struct isdn_l3_driver *
153 isdn_find_l3_by_isdnif(int isdnif)
155 struct isdn_l3_driver *sc;
157 SLIST_FOREACH(sc, &isdnif_list, l3drvq)
158 if (sc->isdnif == isdnif)
159 return sc;
160 return NULL;
163 int isdn_count_isdnif(int *misdnif)
165 struct isdn_l3_driver *sc;
166 int count = 0;
167 int max_isdnif = -1;
169 SLIST_FOREACH(sc, &isdnif_list, l3drvq) {
170 count++;
171 if (sc->isdnif > max_isdnif)
172 max_isdnif = sc->isdnif;
175 if (misdnif)
176 *misdnif = max_isdnif;
178 return count;
181 void *
182 isdn_find_softc_by_isdnif(int isdnif)
184 struct isdn_l3_driver *sc = isdn_find_l3_by_isdnif(isdnif);
185 if (sc == NULL)
186 return NULL;
188 * XXX - hack: do not return a softc for active cards.
189 * all callers of this expecting l2_softc* results
190 * should be fixed!
192 if (sc->l3driver->N_DOWNLOAD)
193 return NULL;
194 return sc->l1_token;
197 /*---------------------------------------------------------------------------*
198 * daemon is attached
199 *---------------------------------------------------------------------------*/
200 void
201 i4b_l4_daemon_attached(void)
203 struct isdn_l3_driver *d;
205 int x = splnet();
206 SLIST_FOREACH(d, &isdnif_list, l3drvq)
208 d->l3driver->N_MGMT_COMMAND(d, CMR_DOPEN, 0);
210 splx(x);
213 /*---------------------------------------------------------------------------*
214 * daemon is detached
215 *---------------------------------------------------------------------------*/
216 void
217 i4b_l4_daemon_detached(void)
219 struct isdn_l3_driver *d;
221 int x = splnet();
222 SLIST_FOREACH(d, &isdnif_list, l3drvq)
224 d->l3driver->N_MGMT_COMMAND(d, CMR_DCLOSE, 0);
226 splx(x);
230 * B-channel layer 4 drivers and their registry.
231 * (Application drivers connecting to a B-channel)
233 static int i4b_link_bchandrvr(call_desc_t *cd);
234 static void i4b_unlink_bchandrvr(call_desc_t *cd);
235 static void i4b_l4_setup_timeout(call_desc_t *cd);
236 static void i4b_idle_check_fix_unit(call_desc_t *cd);
237 static void i4b_idle_check_var_unit(call_desc_t *cd);
238 static void i4b_l4_setup_timeout_fix_unit(call_desc_t *cd);
239 static void i4b_l4_setup_timeout_var_unit(call_desc_t *cd);
240 static time_t i4b_get_idletime(call_desc_t *cd);
242 static int next_l4_driver_id = 0;
244 struct l4_driver_desc {
245 SLIST_ENTRY(l4_driver_desc) l4drvq;
246 char name[L4DRIVER_NAME_SIZ];
247 int driver_id;
248 const struct isdn_l4_driver_functions *driver;
249 int units;
251 static SLIST_HEAD(, l4_driver_desc) l4_driver_registry
252 = SLIST_HEAD_INITIALIZER(l4_driver_registry);
254 int isdn_l4_driver_attach(const char *name, int units, const struct isdn_l4_driver_functions *driver)
256 struct l4_driver_desc * new_driver;
258 new_driver = malloc(sizeof(struct l4_driver_desc), M_DEVBUF,
259 M_WAITOK|M_ZERO);
260 strncpy(new_driver->name, name, L4DRIVER_NAME_SIZ);
261 new_driver->name[L4DRIVER_NAME_SIZ-1] = 0;
262 new_driver->driver_id = next_l4_driver_id++;
263 new_driver->driver = driver;
264 new_driver->units = units;
265 SLIST_INSERT_HEAD(&l4_driver_registry, new_driver, l4drvq);
266 return new_driver->driver_id;
269 int isdn_l4_driver_detatch(const char *name)
271 /* XXX - not yet implemented */
272 (void)name;
273 return 0;
276 const struct isdn_l4_driver_functions *isdn_l4_find_driver(const char *name, int unit)
278 struct l4_driver_desc * d;
279 SLIST_FOREACH(d, &l4_driver_registry, l4drvq)
280 if (strcmp(d->name, name) == 0) {
281 return d->driver;
283 return NULL;
286 int isdn_l4_find_driverid(const char *name)
288 struct l4_driver_desc * d;
289 SLIST_FOREACH(d, &l4_driver_registry, l4drvq)
290 if (strcmp(d->name, name) == 0) {
291 return d->driver_id;
293 return -1;
296 const struct isdn_l4_driver_functions *isdn_l4_get_driver(int driver_id, int unit)
298 struct l4_driver_desc * d;
299 SLIST_FOREACH(d, &l4_driver_registry, l4drvq)
300 if (d->driver_id == driver_id) {
301 return d->driver;
303 return NULL;
306 /*---------------------------------------------------------------------------*
307 * send MSG_PDEACT_IND message to userland
308 *---------------------------------------------------------------------------*/
309 void
310 i4b_l4_pdeact(struct isdn_l3_driver *d, int numactive)
312 struct mbuf *m;
313 int i;
314 call_desc_t *cd;
316 for(i=0; i < num_call_desc; i++)
318 if(call_desc[i].cdid != CDID_UNUSED && call_desc[i].l3drv == d)
320 cd = &call_desc[i];
322 if(cd->timeout_active)
324 STOP_TIMER(cd->idle_timeout_handle, i4b_idle_check, cd);
327 if (cd->l4_driver != NULL && cd->l4_driver_softc != NULL)
329 (*cd->l4_driver->line_disconnected)(cd->l4_driver_softc, (void *)cd);
330 i4b_unlink_bchandrvr(cd);
333 if ((cd->channelid >= 0)
334 && (cd->channelid < d->nbch))
335 d->bch_state[cd->channelid] = BCH_ST_FREE;
337 cd->cdid = CDID_UNUSED;
341 if((m = i4b_Dgetmbuf(sizeof(msg_pdeact_ind_t))) != NULL)
343 msg_pdeact_ind_t *md = (msg_pdeact_ind_t *)m->m_data;
345 md->header.type = MSG_PDEACT_IND;
346 md->header.cdid = -1;
348 md->controller = d->isdnif;
349 md->numactive = numactive;
351 i4bputqueue_hipri(m); /* URGENT !!! */
355 /*---------------------------------------------------------------------------*
356 * send MSG_L12STAT_IND message to userland
357 *---------------------------------------------------------------------------*/
358 void
359 i4b_l4_l12stat(struct isdn_l3_driver *d, int layer, int state)
361 struct mbuf *m;
363 if((m = i4b_Dgetmbuf(sizeof(msg_l12stat_ind_t))) != NULL)
365 msg_l12stat_ind_t *md = (msg_l12stat_ind_t *)m->m_data;
367 md->header.type = MSG_L12STAT_IND;
368 md->header.cdid = -1;
370 md->controller = d->isdnif;
371 md->layer = layer;
372 md->state = state;
374 i4bputqueue(m);
378 /*---------------------------------------------------------------------------*
379 * send MSG_TEIASG_IND message to userland
380 *---------------------------------------------------------------------------*/
381 void
382 i4b_l4_teiasg(struct isdn_l3_driver *d, int tei)
384 struct mbuf *m;
386 if((m = i4b_Dgetmbuf(sizeof(msg_teiasg_ind_t))) != NULL)
388 msg_teiasg_ind_t *md = (msg_teiasg_ind_t *)m->m_data;
390 md->header.type = MSG_TEIASG_IND;
391 md->header.cdid = -1;
393 md->controller = d->isdnif;
394 md->tei = d->tei;
396 i4bputqueue(m);
400 /*---------------------------------------------------------------------------*
401 * send MSG_DIALOUT_IND message to userland
402 *---------------------------------------------------------------------------*/
403 void
404 i4b_l4_dialout(int driver, int driver_unit)
406 struct mbuf *m;
408 if((m = i4b_Dgetmbuf(sizeof(msg_dialout_ind_t))) != NULL)
410 msg_dialout_ind_t *md = (msg_dialout_ind_t *)m->m_data;
412 md->header.type = MSG_DIALOUT_IND;
413 md->header.cdid = -1;
415 md->driver = driver;
416 md->driver_unit = driver_unit;
418 i4bputqueue(m);
422 /*---------------------------------------------------------------------------*
423 * send MSG_DIALOUTNUMBER_IND message to userland
424 *---------------------------------------------------------------------------*/
425 void
426 i4b_l4_dialoutnumber(int driver, int driver_unit, int cmdlen, char *cmd)
428 struct mbuf *m;
430 if((m = i4b_Dgetmbuf(sizeof(msg_dialoutnumber_ind_t))) != NULL)
432 msg_dialoutnumber_ind_t *md = (msg_dialoutnumber_ind_t *)m->m_data;
434 md->header.type = MSG_DIALOUTNUMBER_IND;
435 md->header.cdid = -1;
437 md->driver = driver;
438 md->driver_unit = driver_unit;
440 if(cmdlen > TELNO_MAX)
441 cmdlen = TELNO_MAX;
443 md->cmdlen = cmdlen;
444 memcpy(md->cmd, cmd, cmdlen);
445 i4bputqueue(m);
449 /*---------------------------------------------------------------------------*
450 * send MSG_NEGOTIATION_COMPL message to userland
451 *---------------------------------------------------------------------------*/
452 void
453 i4b_l4_negcomplete(call_desc_t *cd)
455 struct mbuf *m;
457 if((m = i4b_Dgetmbuf(sizeof(msg_negcomplete_ind_t))) != NULL)
459 msg_negcomplete_ind_t *md = (msg_negcomplete_ind_t *)m->m_data;
461 md->header.type = MSG_NEGCOMP_IND;
462 md->header.cdid = cd->cdid;
464 i4bputqueue(m);
468 /*---------------------------------------------------------------------------*
469 * send MSG_IFSTATE_CHANGED_IND message to userland
470 *---------------------------------------------------------------------------*/
471 void
472 i4b_l4_ifstate_changed(call_desc_t *cd, int new_state)
474 struct mbuf *m;
476 if((m = i4b_Dgetmbuf(sizeof(msg_ifstatechg_ind_t))) != NULL)
478 msg_ifstatechg_ind_t *md = (msg_ifstatechg_ind_t *)m->m_data;
480 md->header.type = MSG_IFSTATE_CHANGED_IND;
481 md->header.cdid = cd->cdid;
482 md->state = new_state;
484 i4bputqueue(m);
488 /*---------------------------------------------------------------------------*
489 * send MSG_DRVRDISC_REQ message to userland
490 *---------------------------------------------------------------------------*/
491 void
492 i4b_l4_drvrdisc(int cdid)
494 struct mbuf *m;
496 if((m = i4b_Dgetmbuf(sizeof(msg_drvrdisc_req_t))) != NULL)
498 msg_drvrdisc_req_t *md = (msg_drvrdisc_req_t *)m->m_data;
500 md->header.type = MSG_DRVRDISC_REQ;
501 md->header.cdid = cdid;
503 i4bputqueue(m);
507 /*---------------------------------------------------------------------------*
508 * send MSG_ACCT_IND message to userland
509 *---------------------------------------------------------------------------*/
510 void
511 i4b_l4_accounting(int cdid, int accttype, int ioutbytes,
512 int iinbytes, int ro, int ri, int outbytes, int inbytes)
514 struct mbuf *m;
516 if((m = i4b_Dgetmbuf(sizeof(msg_accounting_ind_t))) != NULL)
518 msg_accounting_ind_t *md = (msg_accounting_ind_t *)m->m_data;
520 md->header.type = MSG_ACCT_IND;
521 md->header.cdid = cdid;
523 md->accttype = accttype;
524 md->ioutbytes = ioutbytes;
525 md->iinbytes = iinbytes;
526 md->outbps = ro;
527 md->inbps = ri;
528 md->outbytes = outbytes;
529 md->inbytes = inbytes;
531 i4bputqueue(m);
535 /*---------------------------------------------------------------------------*
536 * send MSG_CONNECT_IND message to userland
537 *---------------------------------------------------------------------------*/
538 void
539 i4b_l4_connect_ind(call_desc_t *cd)
541 struct mbuf *m;
543 if((m = i4b_Dgetmbuf(sizeof(msg_connect_ind_t))) != NULL)
545 msg_connect_ind_t *mp = (msg_connect_ind_t *)m->m_data;
547 mp->header.type = MSG_CONNECT_IND;
548 mp->header.cdid = cd->cdid;
550 mp->controller = cd->isdnif;
551 mp->channel = cd->channelid;
552 mp->bprot = cd->bprot;
554 cd->dir = DIR_INCOMING;
556 if(strlen(cd->dst_telno) > 0)
557 strlcpy(mp->dst_telno, cd->dst_telno,
558 sizeof(mp->dst_telno));
559 else
560 strlcpy(mp->dst_telno, TELNO_EMPTY,
561 sizeof(mp->dst_telno));
563 if(strlen(cd->src_telno) > 0)
564 strlcpy(mp->src_telno, cd->src_telno,
565 sizeof(mp->src_telno));
566 else
567 strlcpy(mp->src_telno, TELNO_EMPTY,
568 sizeof(mp->src_telno));
569 mp->type_plan = cd->type_plan;
570 memcpy(mp->src_subaddr, cd->src_subaddr, sizeof(mp->src_subaddr));
571 memcpy(mp->dest_subaddr, cd->dest_subaddr, sizeof(mp->dest_subaddr));
573 strlcpy(mp->display, cd->display, sizeof(mp->src_telno));
575 mp->scr_ind = cd->scr_ind;
576 mp->prs_ind = cd->prs_ind;
578 T400_start(cd);
580 i4bputqueue(m);
584 /*---------------------------------------------------------------------------*
585 * send MSG_CONNECT_ACTIVE_IND message to userland
586 *---------------------------------------------------------------------------*/
587 void
588 i4b_l4_connect_active_ind(call_desc_t *cd)
590 int s;
591 struct mbuf *m;
593 s = splnet();
595 cd->last_active_time = cd->connect_time = SECOND;
597 NDBGL4(L4_TIMO, "last_active/connect_time=%ld", (long)cd->connect_time);
599 i4b_link_bchandrvr(cd);
601 update_controller_leds(cd->l3drv);
603 if (cd->l4_driver != NULL && cd->l4_driver_softc != NULL)
604 (*cd->l4_driver->line_connected)(cd->l4_driver_softc, cd);
606 i4b_l4_setup_timeout(cd);
608 splx(s);
610 if((m = i4b_Dgetmbuf(sizeof(msg_connect_active_ind_t))) != NULL)
612 msg_connect_active_ind_t *mp = (msg_connect_active_ind_t *)m->m_data;
614 mp->header.type = MSG_CONNECT_ACTIVE_IND;
615 mp->header.cdid = cd->cdid;
616 mp->controller = cd->isdnif;
617 mp->channel = cd->channelid;
618 if(cd->datetime[0] != '\0')
619 strlcpy(mp->datetime, cd->datetime,
620 sizeof(mp->datetime));
621 else
622 mp->datetime[0] = '\0';
623 i4bputqueue(m);
627 /*---------------------------------------------------------------------------*
628 * send MSG_DISCONNECT_IND message to userland
629 *---------------------------------------------------------------------------*/
630 void
631 i4b_l4_disconnect_ind(call_desc_t *cd)
633 struct isdn_l3_driver *d;
634 struct mbuf *m;
636 if(cd->timeout_active)
637 STOP_TIMER(cd->idle_timeout_handle, i4b_idle_check, cd);
639 if (cd->l4_driver != NULL && cd->l4_driver_softc != NULL)
641 (*cd->l4_driver->line_disconnected)(cd->l4_driver_softc, (void *)cd);
642 i4b_unlink_bchandrvr(cd);
645 d = cd->l3drv;
647 if((cd->channelid >= 0) && (cd->channelid < d->nbch))
649 d->bch_state[cd->channelid] = BCH_ST_FREE;
651 * XXX: don't call l2 function for active cards.
653 if (d->l3driver->N_DOWNLOAD == NULL)
654 i4b_l2_channel_set_state(d, cd->channelid, BCH_ST_FREE);
656 else
658 /* no error, might be hunting call for callback */
659 NDBGL4(L4_MSG, "invalid channel %d for ISDN!", cd->channelid);
661 update_controller_leds(d);
663 if((m = i4b_Dgetmbuf(sizeof(msg_disconnect_ind_t))) != NULL)
665 msg_disconnect_ind_t *mp = (msg_disconnect_ind_t *)m->m_data;
667 mp->header.type = MSG_DISCONNECT_IND;
668 mp->header.cdid = cd->cdid;
669 mp->cause = cd->cause_in;
671 i4bputqueue(m);
675 /*---------------------------------------------------------------------------*
676 * send MSG_IDLE_TIMEOUT_IND message to userland
677 *---------------------------------------------------------------------------*/
678 void
679 i4b_l4_idle_timeout_ind(call_desc_t *cd)
681 struct mbuf *m;
683 if((m = i4b_Dgetmbuf(sizeof(msg_idle_timeout_ind_t))) != NULL)
685 msg_idle_timeout_ind_t *mp = (msg_idle_timeout_ind_t *)m->m_data;
687 mp->header.type = MSG_IDLE_TIMEOUT_IND;
688 mp->header.cdid = cd->cdid;
690 i4bputqueue(m);
694 /*---------------------------------------------------------------------------*
695 * send MSG_CHARGING_IND message to userland
696 *---------------------------------------------------------------------------*/
697 void
698 i4b_l4_charging_ind(call_desc_t *cd)
700 struct mbuf *m;
702 if((m = i4b_Dgetmbuf(sizeof(msg_charging_ind_t))) != NULL)
704 msg_charging_ind_t *mp = (msg_charging_ind_t *)m->m_data;
706 mp->header.type = MSG_CHARGING_IND;
707 mp->header.cdid = cd->cdid;
708 mp->units_type = cd->units_type;
710 /*XXX*/ if(mp->units_type == CHARGE_CALC)
711 mp->units = cd->cunits;
712 else
713 mp->units = cd->units;
715 i4bputqueue(m);
719 /*---------------------------------------------------------------------------*
720 * send MSG_STATUS_IND message to userland
721 *---------------------------------------------------------------------------*/
722 void
723 i4b_l4_status_ind(call_desc_t *cd)
727 /*---------------------------------------------------------------------------*
728 * send MSG_ALERT_IND message to userland
729 *---------------------------------------------------------------------------*/
730 void
731 i4b_l4_alert_ind(call_desc_t *cd)
733 struct mbuf *m;
735 if((m = i4b_Dgetmbuf(sizeof(msg_alert_ind_t))) != NULL)
737 msg_alert_ind_t *mp = (msg_alert_ind_t *)m->m_data;
739 mp->header.type = MSG_ALERT_IND;
740 mp->header.cdid = cd->cdid;
742 i4bputqueue(m);
746 /*---------------------------------------------------------------------------*
747 * send MSG_INFO_IND message to userland
748 *---------------------------------------------------------------------------*/
749 void
750 i4b_l4_info_ind(call_desc_t *cd)
754 /*---------------------------------------------------------------------------*
755 * send MSG_INFO_IND message to userland
756 *---------------------------------------------------------------------------*/
757 void
758 i4b_l4_proceeding_ind(call_desc_t *cd)
760 struct mbuf *m;
762 if((m = i4b_Dgetmbuf(sizeof(msg_proceeding_ind_t))) != NULL)
764 msg_proceeding_ind_t *mp = (msg_proceeding_ind_t *)m->m_data;
766 mp->header.type = MSG_PROCEEDING_IND;
767 mp->header.cdid = cd->cdid;
768 mp->controller = cd->isdnif;
769 mp->channel = cd->channelid;
770 i4bputqueue(m);
774 /*---------------------------------------------------------------------------*
775 * send MSG_PACKET_IND message to userland
776 *---------------------------------------------------------------------------*/
777 void
778 i4b_l4_packet_ind(int driver, int driver_unit, int dir, struct mbuf *pkt)
780 struct mbuf *m;
781 int len = pkt->m_pkthdr.len;
782 unsigned char *ip = pkt->m_data;
784 if((m = i4b_Dgetmbuf(sizeof(msg_packet_ind_t))) != NULL)
786 msg_packet_ind_t *mp = (msg_packet_ind_t *)m->m_data;
788 mp->header.type = MSG_PACKET_IND;
789 mp->header.cdid = -1;
790 mp->driver = driver;
791 mp->driver_unit = driver_unit;
792 mp->direction = dir;
793 memcpy(mp->pktdata, ip,
794 len <MAX_PACKET_LOG ? len : MAX_PACKET_LOG);
795 i4bputqueue(m);
799 /*---------------------------------------------------------------------------*
800 * send MSG_CONTR_EV_IND message to userland
801 *---------------------------------------------------------------------------*/
802 void
803 i4b_l4_contr_ev_ind(int controller, int attach)
805 struct mbuf *m;
807 if((m = i4b_Dgetmbuf(sizeof(msg_ctrl_ev_ind_t))) != NULL)
809 msg_ctrl_ev_ind_t *ev = (msg_ctrl_ev_ind_t *)m->m_data;
811 ev->header.type = MSG_CONTR_EV_IND;
812 ev->header.cdid = -1;
813 ev->controller = controller;
814 ev->event = attach;
815 i4bputqueue(m);
819 /*---------------------------------------------------------------------------*
820 * link a driver(unit) to a B-channel(controller,unit,channel)
821 *---------------------------------------------------------------------------*/
822 static int
823 i4b_link_bchandrvr(call_desc_t *cd)
825 struct isdn_l3_driver *d = cd->l3drv;
827 if (d == NULL || d->l3driver == NULL || d->l3driver->get_linktab == NULL)
829 cd->ilt = NULL;
830 return 1;
833 cd->ilt = d->l3driver->get_linktab(d->l1_token,
834 cd->channelid);
836 cd->l4_driver = isdn_l4_get_driver(cd->bchan_driver_index, cd->bchan_driver_unit);
837 if (cd->l4_driver != NULL)
838 cd->l4_driver_softc = cd->l4_driver->get_softc(cd->bchan_driver_unit);
839 else
840 cd->l4_driver_softc = NULL;
842 if(cd->l4_driver == NULL || cd->l4_driver_softc == NULL || cd->ilt == NULL)
843 return(-1);
845 if (d->l3driver->set_l4_driver != NULL)
847 d->l3driver->set_l4_driver(d->l1_token,
848 cd->channelid, cd->l4_driver, cd->l4_driver_softc);
851 cd->l4_driver->set_linktab(cd->l4_driver_softc, cd->ilt);
853 /* activate B channel */
855 (*cd->ilt->bchannel_driver->bch_config)(cd->ilt->l1token, cd->ilt->channel, cd->bprot, 1);
857 return(0);
860 /*---------------------------------------------------------------------------*
861 * unlink a driver(unit) from a B-channel(controller,unit,channel)
862 *---------------------------------------------------------------------------*/
863 static void
864 i4b_unlink_bchandrvr(call_desc_t *cd)
866 struct isdn_l3_driver *d = cd->l3drv;
869 * XXX - what's this *cd manipulation for? Shouldn't we
870 * close the bchannel driver first and then just set ilt to NULL
871 * in *cd?
873 if (d == NULL || d->l3driver == NULL || d->l3driver->get_linktab == NULL)
875 cd->ilt = NULL;
876 return;
878 else
880 cd->ilt = d->l3driver->get_linktab(
881 d->l1_token, cd->channelid);
884 /* deactivate B channel */
886 (*cd->ilt->bchannel_driver->bch_config)(cd->ilt->l1token, cd->ilt->channel, cd->bprot, 0);
889 /*---------------------------------------------------------------------------
891 How shorthold mode works for OUTGOING connections
892 =================================================
894 |<---- unchecked-window ------->|<-checkwindow->|<-safetywindow>|
896 idletime_state: IST_NONCHK IST_CHECK IST_SAFE
898 | | | |
899 time>>+-------------------------------+---------------+---------------+-...
900 | | | |
901 | |<--idle_time-->|<--earlyhup--->|
902 |<-----------------------unitlen------------------------------->|
905 unitlen - specifies the time a charging unit lasts
906 idle_time - specifies the thime the line must be idle at the
907 end of the unit to be elected for hangup
908 earlyhup - is the beginning of a timing safety zone before the
909 next charging unit starts
911 The algorithm works as follows: lets assume the unitlen is 100
912 secons, idle_time is 40 seconds and earlyhup is 10 seconds.
913 The line then must be idle 50 seconds after the begin of the
914 current unit and it must then be quiet for 40 seconds. if it
915 has been quiet for this 40 seconds, the line is closed 10
916 seconds before the next charging unit starts. In case there was
917 any traffic within the idle_time, the line is not closed.
918 It does not matter whether there was any traffic between second
919 0 and second 50 or not.
922 How shorthold mode works for INCOMING connections
923 =================================================
925 it is just possible to specify a maximum idle time for incoming
926 connections, after this time of no activity on the line the line
927 is closed.
929 ---------------------------------------------------------------------------*/
931 static time_t
932 i4b_get_idletime(call_desc_t *cd)
934 if (cd->l4_driver != NULL && cd->l4_driver_softc != NULL
935 && cd->l4_driver->get_idletime)
936 return cd->l4_driver->get_idletime(cd->l4_driver_softc);
937 return cd->last_active_time;
940 /*---------------------------------------------------------------------------*
941 * B channel idle check timeout setup
942 *---------------------------------------------------------------------------*/
943 static void
944 i4b_l4_setup_timeout(call_desc_t *cd)
946 NDBGL4(L4_TIMO, "%ld: direction %d, shorthold algorithm %d",
947 (long)SECOND, cd->dir, cd->shorthold_data.shorthold_algorithm);
949 cd->timeout_active = 0;
950 cd->idletime_state = IST_IDLE;
952 if((cd->dir == DIR_INCOMING) && (cd->max_idle_time > 0))
954 /* incoming call: simple max idletime check */
956 START_TIMER(cd->idle_timeout_handle, i4b_idle_check, cd, hz/2);
957 cd->timeout_active = 1;
958 NDBGL4(L4_TIMO, "%ld: incoming-call, setup max_idle_time to %ld", (long)SECOND, (long)cd->max_idle_time);
960 else if((cd->dir == DIR_OUTGOING) && (cd->shorthold_data.idle_time > 0))
962 switch( cd->shorthold_data.shorthold_algorithm )
964 default: /* fall into the old fix algorithm */
965 case SHA_FIXU:
966 i4b_l4_setup_timeout_fix_unit( cd );
967 break;
969 case SHA_VARU:
970 i4b_l4_setup_timeout_var_unit( cd );
971 break;
974 else
976 NDBGL4(L4_TIMO, "no idle_timeout configured");
980 /*---------------------------------------------------------------------------*
981 * fixed unit algorithm B channel idle check timeout setup
982 *---------------------------------------------------------------------------*/
983 static void
984 i4b_l4_setup_timeout_fix_unit(call_desc_t *cd)
986 /* outgoing call */
988 if((cd->shorthold_data.idle_time > 0) && (cd->shorthold_data.unitlen_time == 0))
990 /* outgoing call: simple max idletime check */
992 START_TIMER(cd->idle_timeout_handle, i4b_idle_check, cd, hz/2);
993 cd->timeout_active = 1;
994 NDBGL4(L4_TIMO, "%ld: outgoing-call, setup idle_time to %ld",
995 (long)SECOND, (long)cd->shorthold_data.idle_time);
997 else if((cd->shorthold_data.unitlen_time > 0) && (cd->shorthold_data.unitlen_time > (cd->shorthold_data.idle_time + cd->shorthold_data.earlyhup_time)))
999 /* outgoing call: full shorthold mode check */
1001 START_TIMER(cd->idle_timeout_handle, i4b_idle_check, cd, hz*(cd->shorthold_data.unitlen_time - (cd->shorthold_data.idle_time + cd->shorthold_data.earlyhup_time)));
1002 cd->timeout_active = 1;
1003 cd->idletime_state = IST_NONCHK;
1004 NDBGL4(L4_TIMO, "%ld: outgoing-call, start %ld sec nocheck window",
1005 (long)SECOND, (long)(cd->shorthold_data.unitlen_time - (cd->shorthold_data.idle_time + cd->shorthold_data.earlyhup_time)));
1007 if(cd->aocd_flag == 0)
1009 cd->units_type = CHARGE_CALC;
1010 cd->cunits++;
1011 i4b_l4_charging_ind(cd);
1014 else
1016 /* parms somehow got wrong .. */
1018 NDBGL4(L4_ERR, "%ld: ERROR: idletime[%ld]+earlyhup[%ld] > unitlength[%ld]!",
1019 (long)SECOND, (long)cd->shorthold_data.idle_time, (long)cd->shorthold_data.earlyhup_time, (long)cd->shorthold_data.unitlen_time);
1023 /*---------------------------------------------------------------------------*
1024 * variable unit algorithm B channel idle check timeout setup
1025 *---------------------------------------------------------------------------*/
1026 static void
1027 i4b_l4_setup_timeout_var_unit(call_desc_t *cd)
1029 /* outgoing call: variable unit idletime check */
1032 * start checking for an idle connect one second before the end of the unit.
1033 * The one second takes into account of rounding due to the driver only
1034 * using the seconds and not the uSeconds of the current time
1036 cd->idletime_state = IST_CHECK; /* move directly to the checking state */
1038 START_TIMER(cd->idle_timeout_handle, i4b_idle_check, cd, hz * (cd->shorthold_data.unitlen_time - 1) );
1039 cd->timeout_active = 1;
1040 NDBGL4(L4_TIMO, "%ld: outgoing-call, var idle time - setup to %ld",
1041 (long)SECOND, (long)cd->shorthold_data.unitlen_time);
1045 /*---------------------------------------------------------------------------*
1046 * B channel idle check timeout function
1047 *---------------------------------------------------------------------------*/
1048 void
1049 i4b_idle_check(call_desc_t *cd)
1051 int s;
1053 if(cd->cdid == CDID_UNUSED)
1054 return;
1056 s = splnet();
1058 /* failsafe */
1060 if(cd->timeout_active == 0)
1062 NDBGL4(L4_ERR, "ERROR: timeout_active == 0 !!!");
1064 else
1066 cd->timeout_active = 0;
1069 /* incoming connections, simple idletime check */
1071 if(cd->dir == DIR_INCOMING)
1073 if((i4b_get_idletime(cd) + cd->max_idle_time) <= SECOND)
1075 struct isdn_l3_driver *d = cd->l3drv;
1076 NDBGL4(L4_TIMO, "%ld: incoming-call, line idle timeout, disconnecting!", (long)SECOND);
1077 d->l3driver->N_DISCONNECT_REQUEST(cd,
1078 (CAUSET_I4B << 8) | CAUSE_I4B_NORMAL);
1079 i4b_l4_idle_timeout_ind(cd);
1081 else
1083 NDBGL4(L4_TIMO, "%ld: incoming-call, activity, last_active=%ld, max_idle=%ld", (long)SECOND, (long)i4b_get_idletime(cd), (long)cd->max_idle_time);
1085 START_TIMER(cd->idle_timeout_handle, i4b_idle_check, cd, hz/2);
1086 cd->timeout_active = 1;
1090 /* outgoing connections */
1092 else if(cd->dir == DIR_OUTGOING)
1094 switch( cd->shorthold_data.shorthold_algorithm )
1096 case SHA_FIXU:
1097 i4b_idle_check_fix_unit( cd );
1098 break;
1099 case SHA_VARU:
1100 i4b_idle_check_var_unit( cd );
1101 break;
1102 default:
1103 NDBGL4(L4_TIMO, "%ld: bad value for shorthold_algorithm of %d",
1104 (long)SECOND, cd->shorthold_data.shorthold_algorithm);
1105 i4b_idle_check_fix_unit( cd );
1106 break;
1109 splx(s);
1112 /*---------------------------------------------------------------------------*
1113 * fixed unit algorithm B channel idle check timeout function
1114 *---------------------------------------------------------------------------*/
1115 static void
1116 i4b_idle_check_fix_unit(call_desc_t *cd)
1118 struct isdn_l3_driver *d = cd->l3drv;
1120 /* simple idletime calculation */
1122 if((cd->shorthold_data.idle_time > 0) && (cd->shorthold_data.unitlen_time == 0))
1124 if((i4b_get_idletime(cd) + cd->shorthold_data.idle_time) <= SECOND)
1126 NDBGL4(L4_TIMO, "%ld: outgoing-call-st, idle timeout, disconnecting!", (long)SECOND);
1127 d->l3driver->N_DISCONNECT_REQUEST(cd, (CAUSET_I4B << 8) | CAUSE_I4B_NORMAL);
1128 i4b_l4_idle_timeout_ind(cd);
1130 else
1132 NDBGL4(L4_TIMO, "%ld: outgoing-call-st, activity, last_active=%ld, max_idle=%ld",
1133 (long)SECOND, (long)i4b_get_idletime(cd), (long)cd->shorthold_data.idle_time);
1134 START_TIMER(cd->idle_timeout_handle, i4b_idle_check, cd, hz/2);
1135 cd->timeout_active = 1;
1139 /* full shorthold mode calculation */
1141 else if((cd->shorthold_data.unitlen_time > 0)
1142 && (cd->shorthold_data.unitlen_time > (cd->shorthold_data.idle_time + cd->shorthold_data.earlyhup_time)))
1144 switch(cd->idletime_state)
1147 case IST_NONCHK: /* end of non-check time */
1149 START_TIMER(cd->idle_timeout_handle, i4b_idle_check, cd, hz*(cd->shorthold_data.idle_time));
1150 cd->idletimechk_start = SECOND;
1151 cd->idletime_state = IST_CHECK;
1152 cd->timeout_active = 1;
1153 NDBGL4(L4_TIMO, "%ld: outgoing-call, idletime check window reached!", (long)SECOND);
1154 break;
1156 case IST_CHECK: /* end of idletime chk */
1157 if((i4b_get_idletime(cd) > cd->idletimechk_start) &&
1158 (i4b_get_idletime(cd) <= SECOND))
1159 { /* activity detected */
1160 START_TIMER(cd->idle_timeout_handle, i4b_idle_check, cd, hz*(cd->shorthold_data.earlyhup_time));
1161 cd->timeout_active = 1;
1162 cd->idletime_state = IST_SAFE;
1163 NDBGL4(L4_TIMO, "%ld: outgoing-call, activity at %ld, wait earlyhup-end", (long)SECOND, (long)i4b_get_idletime(cd));
1165 else
1166 { /* no activity, hangup */
1167 NDBGL4(L4_TIMO, "%ld: outgoing-call, idle timeout, last activity at %ld", (long)SECOND, (long)i4b_get_idletime(cd));
1168 d->l3driver->N_DISCONNECT_REQUEST(cd, (CAUSET_I4B << 8) | CAUSE_I4B_NORMAL);
1169 i4b_l4_idle_timeout_ind(cd);
1170 cd->idletime_state = IST_IDLE;
1172 break;
1174 case IST_SAFE: /* end of earlyhup time */
1176 START_TIMER(cd->idle_timeout_handle, i4b_idle_check, cd, hz*(cd->shorthold_data.unitlen_time - (cd->shorthold_data.idle_time+cd->shorthold_data.earlyhup_time)));
1177 cd->timeout_active = 1;
1178 cd->idletime_state = IST_NONCHK;
1180 if(cd->aocd_flag == 0)
1182 cd->units_type = CHARGE_CALC;
1183 cd->cunits++;
1184 i4b_l4_charging_ind(cd);
1187 NDBGL4(L4_TIMO, "%ld: outgoing-call, earlyhup end, wait for idletime start", (long)SECOND);
1188 break;
1190 default:
1191 NDBGL4(L4_ERR, "outgoing-call: invalid idletime_state value!");
1192 cd->idletime_state = IST_IDLE;
1193 break;
1198 /*---------------------------------------------------------------------------*
1199 * variable unit algorithm B channel idle check timeout function
1200 *---------------------------------------------------------------------------*/
1201 static void
1202 i4b_idle_check_var_unit(call_desc_t *cd)
1204 switch(cd->idletime_state)
1207 /* see if there has been any activity within the last idle_time seconds */
1208 case IST_CHECK:
1209 if( i4b_get_idletime(cd) > (SECOND - cd->shorthold_data.idle_time))
1210 { /* activity detected */
1211 #if defined(__FreeBSD_version) && __FreeBSD_version >= 300001
1212 cd->idle_timeout_handle =
1213 #endif
1214 /* check again in one second */
1215 START_TIMER(cd->idle_timeout_handle, i4b_idle_check, cd, hz);
1216 cd->timeout_active = 1;
1217 cd->idletime_state = IST_CHECK;
1218 NDBGL4(L4_TIMO, "%ld: outgoing-call, var idle timeout - activity at %ld, continuing", (long)SECOND, (long)i4b_get_idletime(cd));
1220 else
1221 { /* no activity, hangup */
1222 struct isdn_l3_driver *d = cd->l3drv;
1223 NDBGL4(L4_TIMO, "%ld: outgoing-call, var idle timeout - last activity at %ld", (long)SECOND, (long)i4b_get_idletime(cd));
1224 d->l3driver->N_DISCONNECT_REQUEST(cd, (CAUSET_I4B << 8) | CAUSE_I4B_NORMAL);
1225 i4b_l4_idle_timeout_ind(cd);
1226 cd->idletime_state = IST_IDLE;
1228 break;
1230 default:
1231 NDBGL4(L4_ERR, "outgoing-call: var idle timeout invalid idletime_state value!");
1232 cd->idletime_state = IST_IDLE;
1233 break;
1237 #endif /* NISDN > 0 */