1 /* $MirOS: src/sys/netisdn/i4b_l4.c,v 1.2 2005/03/06 21:28:27 tg Exp $ */
2 
3 /*
4  * Copyright (c) 1997, 2000 Hellmuth Michaelis. All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25  * SUCH DAMAGE.
26  *
27  *---------------------------------------------------------------------------
28  *
29  *	i4b_l4.c - kernel interface to userland
30  *
31  *---------------------------------------------------------------------------*/
32 
33 #include <sys/cdefs.h>
34 
35 #include "isdn.h"
36 #include "irip.h"
37 
38 #if NISDN > 0
39 
40 #include <sys/param.h>
41 #include <sys/kernel.h>
42 #include <sys/systm.h>
43 #include <sys/conf.h>
44 #include <sys/mbuf.h>
45 #include <sys/proc.h>
46 #include <sys/fcntl.h>
47 #include <sys/socket.h>
48 #include <net/if.h>
49 
50 #include <sys/timeout.h>
51 
52 #ifdef __FreeBSD__
53 #include <machine/i4b_debug.h>
54 #include <machine/i4b_ioctl.h>
55 #include <machine/i4b_cause.h>
56 #else
57 #include <netisdn/i4b_debug.h>
58 #include <netisdn/i4b_ioctl.h>
59 #include <netisdn/i4b_cause.h>
60 #endif
61 
62 #include <netisdn/i4b_global.h>
63 #include <netisdn/i4b_l3l4.h>
64 #include <netisdn/i4b_mbuf.h>
65 #include <netisdn/i4b_l2.h>
66 #include <netisdn/i4b_l3.h>
67 #include <netisdn/i4b_l4.h>
68 
69 unsigned int i4b_l4_debug = L4_DEBUG_DEFAULT;
70 
71 /*
72  * ISDNs, in userland sometimes called "controllers", but one controller
73  * may have multiple BRIs, for example daic QUAD cards attach four BRIs.
74  * An ISDN may also be a PRI (30 B channels).
75  */
76 static SLIST_HEAD(, isdn_l3_driver) isdnif_list = SLIST_HEAD_INITIALIZER(isdnif_list);
77 static int next_isdnif = 0;
78 
79 /*
80  * Attach a new L3 driver instance and return its ISDN identifier
81  */
82 struct isdn_l3_driver *
isdn_attach_isdnif(const char * devname,const char * cardname,void * l1_token,const struct isdn_l3_driver_functions * l3driver,int nbch)83 isdn_attach_isdnif(const char *devname, const char *cardname,
84     void *l1_token, const struct isdn_l3_driver_functions *l3driver, int nbch)
85 {
86 	int s = splnet();
87 	int i, l, isdnif = next_isdnif++;
88 	struct isdn_l3_driver *new_ctrl;
89 
90 	new_ctrl = malloc(sizeof(*new_ctrl), M_DEVBUF, 0);
91 	memset(new_ctrl, 0, sizeof *new_ctrl);
92 	SLIST_INSERT_HEAD(&isdnif_list, new_ctrl, l3drvq);
93 	l = strlen(devname);
94 	new_ctrl->devname = malloc(l + 1, M_DEVBUF, 0);
95 	strlcpy(new_ctrl->devname, devname, l + 1);
96 	l = strlen(cardname);
97 	new_ctrl->card_name = malloc(l + 1, M_DEVBUF, 0);
98 	strlcpy(new_ctrl->card_name, cardname, l + 1);
99 
100 	new_ctrl->l3driver = l3driver;
101 	new_ctrl->l1_token = l1_token;
102 	new_ctrl->isdnif = isdnif;
103 	new_ctrl->tei = -1;
104 	new_ctrl->dl_est = DL_DOWN;
105 	new_ctrl->nbch = nbch;
106 
107 	new_ctrl->bch_state = malloc(nbch * sizeof(int), M_DEVBUF, 0);
108 	for (i = 0; i < nbch; i++)
109 		new_ctrl->bch_state[i] = BCH_ST_FREE;
110 
111 	splx(s);
112 
113 	return new_ctrl;
114 }
115 
116 /*
117  * Detach a L3 driver instance
118  */
119 int
isdn_detach_isdnif(struct isdn_l3_driver * l3drv)120 isdn_detach_isdnif(struct isdn_l3_driver *l3drv)
121 {
122 	struct isdn_l3_driver *sc;
123 	int s = splnet();
124 	int isdnif = l3drv->isdnif;
125 	int max;
126 
127 	i4b_l4_contr_ev_ind(isdnif, 0);
128 	SLIST_REMOVE(&isdnif_list, l3drv, isdn_l3_driver, l3drvq);
129 
130 	max = -1;
131 	SLIST_FOREACH(sc, &isdnif_list, l3drvq)
132 		if (sc->isdnif > max)
133 			max = sc->isdnif;
134 	next_isdnif = max+1;
135 
136 	free_all_cd_of_isdnif(isdnif);
137 
138 	splx(s);
139 
140 	free(l3drv, M_DEVBUF);
141 	printf("ISDN %d detached\n", isdnif);
142 	return 1;
143 }
144 
145 struct isdn_l3_driver *
isdn_find_l3_by_isdnif(int isdnif)146 isdn_find_l3_by_isdnif(int isdnif)
147 {
148 	struct isdn_l3_driver *sc;
149 
150 	SLIST_FOREACH(sc, &isdnif_list, l3drvq)
151 		if (sc->isdnif == isdnif)
152 			return sc;
153 	return NULL;
154 }
155 
isdn_count_isdnif(int * misdnif)156 int isdn_count_isdnif(int *misdnif)
157 {
158 	struct isdn_l3_driver *sc;
159 	int count = 0;
160 	int max_isdnif = -1;
161 
162 	SLIST_FOREACH(sc, &isdnif_list, l3drvq) {
163 		count++;
164 		if (sc->isdnif > max_isdnif)
165 			max_isdnif = sc->isdnif;
166 	}
167 
168 	if (misdnif)
169 		*misdnif = max_isdnif;
170 
171 	return count;
172 }
173 
174 void *
isdn_find_softc_by_isdnif(int isdnif)175 isdn_find_softc_by_isdnif(int isdnif)
176 {
177 	struct isdn_l3_driver *sc = isdn_find_l3_by_isdnif(isdnif);
178 	if (sc == NULL)
179 		return NULL;
180 	/*
181 	 * XXX - hack: do not return a softc for active cards.
182 	 *       all callers of this expecting l2_softc* results
183 	 *       should be fixed!
184 	 */
185 	if (sc->l3driver->N_DOWNLOAD)
186 		return NULL;
187 	return sc->l1_token;
188 }
189 
190 /*---------------------------------------------------------------------------*
191  *      daemon is attached
192  *---------------------------------------------------------------------------*/
193 void
i4b_l4_daemon_attached(void)194 i4b_l4_daemon_attached(void)
195 {
196 	struct isdn_l3_driver *d;
197 
198 	int x = splnet();
199 	SLIST_FOREACH(d, &isdnif_list, l3drvq)
200 	{
201 		d->l3driver->N_MGMT_COMMAND(d, CMR_DOPEN, 0);
202 	}
203 	splx(x);
204 }
205 
206 /*---------------------------------------------------------------------------*
207  *      daemon is detached
208  *---------------------------------------------------------------------------*/
209 void
i4b_l4_daemon_detached(void)210 i4b_l4_daemon_detached(void)
211 {
212 	struct isdn_l3_driver *d;
213 
214 	int x = splnet();
215 	SLIST_FOREACH(d, &isdnif_list, l3drvq)
216 	{
217 		d->l3driver->N_MGMT_COMMAND(d, CMR_DCLOSE, 0);
218 	}
219 	splx(x);
220 }
221 
222 /*
223  * B-channel layer 4 drivers and their registry.
224  * (Application drivers connecting to a B-channel)
225  */
226 static int i4b_link_bchandrvr(call_desc_t *cd);
227 static void i4b_unlink_bchandrvr(call_desc_t *cd);
228 static void i4b_l4_setup_timeout(call_desc_t *cd);
229 static void i4b_idle_check_fix_unit(call_desc_t *cd);
230 static void i4b_idle_check_var_unit(call_desc_t *cd);
231 static void i4b_l4_setup_timeout_fix_unit(call_desc_t *cd);
232 static void i4b_l4_setup_timeout_var_unit(call_desc_t *cd);
233 static time_t i4b_get_idletime(call_desc_t *cd);
234 
235 static int next_l4_driver_id = 0;
236 
237 struct l4_driver_desc {
238 	SLIST_ENTRY(l4_driver_desc) l4drvq;
239 	char name[L4DRIVER_NAME_SIZ];
240 	int driver_id;
241 	const struct isdn_l4_driver_functions *driver;
242 	int units;
243 };
244 static SLIST_HEAD(, l4_driver_desc) l4_driver_registry
245     = SLIST_HEAD_INITIALIZER(l4_driver_registry);
246 
isdn_l4_driver_attach(const char * name,int units,const struct isdn_l4_driver_functions * driver)247 int isdn_l4_driver_attach(const char *name, int units, const struct isdn_l4_driver_functions *driver)
248 {
249 	struct l4_driver_desc * new_driver;
250 
251 	new_driver = malloc(sizeof(struct l4_driver_desc), M_DEVBUF, 0);
252 	memset(new_driver, 0, sizeof(struct l4_driver_desc));
253 	strncpy(new_driver->name, name, L4DRIVER_NAME_SIZ);
254 	new_driver->name[L4DRIVER_NAME_SIZ-1] = 0;
255 	new_driver->driver_id =	next_l4_driver_id++;
256 	new_driver->driver = driver;
257 	new_driver->units = units;
258 	SLIST_INSERT_HEAD(&l4_driver_registry, new_driver, l4drvq);
259 	return new_driver->driver_id;
260 }
261 
isdn_l4_driver_detatch(const char * name)262 int isdn_l4_driver_detatch(const char *name)
263 {
264 	/* XXX - not yet implemented */
265 	return 0;
266 }
267 
isdn_l4_find_driver(const char * name,int unit)268 const struct isdn_l4_driver_functions *isdn_l4_find_driver(const char *name, int unit)
269 {
270 	struct l4_driver_desc * d;
271 	SLIST_FOREACH(d, &l4_driver_registry, l4drvq)
272 		if (strcmp(d->name, name) == 0) {
273 			return d->driver;
274 		}
275 	return NULL;
276 }
277 
isdn_l4_find_driverid(const char * name)278 int isdn_l4_find_driverid(const char *name)
279 {
280 	struct l4_driver_desc * d;
281 	SLIST_FOREACH(d, &l4_driver_registry, l4drvq)
282 		if (strcmp(d->name, name) == 0) {
283 			return d->driver_id;
284 		}
285 	return -1;
286 }
287 
isdn_l4_get_driver(int driver_id,int unit)288 const struct isdn_l4_driver_functions *isdn_l4_get_driver(int driver_id, int unit)
289 {
290 	struct l4_driver_desc * d;
291 	SLIST_FOREACH(d, &l4_driver_registry, l4drvq)
292 		if (d->driver_id == driver_id) {
293 			return d->driver;
294 		}
295 	return NULL;
296 }
297 
298 /*---------------------------------------------------------------------------*
299  *	send MSG_PDEACT_IND message to userland
300  *---------------------------------------------------------------------------*/
301 void
i4b_l4_pdeact(struct isdn_l3_driver * d,int numactive)302 i4b_l4_pdeact(struct isdn_l3_driver *d, int numactive)
303 {
304 	struct mbuf *m;
305 	int i;
306 	call_desc_t *cd;
307 
308 	for(i=0; i < num_call_desc; i++)
309 	{
310 		if(call_desc[i].cdid != CDID_UNUSED && call_desc[i].l3drv == d)
311 		{
312 			cd = &call_desc[i];
313 
314 			if(cd->timeout_active)
315 			{
316 				STOP_TIMER(cd->idle_timeout_handle, i4b_idle_check, cd);
317 			}
318 
319 			if (cd->l4_driver != NULL && cd->l4_driver_softc != NULL)
320 			{
321 				(*cd->l4_driver->line_disconnected)(cd->l4_driver_softc, (void *)cd);
322 				i4b_unlink_bchandrvr(cd);
323 			}
324 
325 			if ((cd->channelid >= 0)
326 			     && (cd->channelid < d->nbch));
327 				d->bch_state[cd->channelid] = BCH_ST_FREE;
328 
329 			cd->cdid = CDID_UNUSED;
330 		}
331 	}
332 
333 	if((m = i4b_Dgetmbuf(sizeof(msg_pdeact_ind_t))) != NULL)
334 	{
335 		msg_pdeact_ind_t *md = (msg_pdeact_ind_t *)m->m_data;
336 
337 		md->header.type = MSG_PDEACT_IND;
338 		md->header.cdid = -1;
339 
340 		md->controller = d->isdnif;
341 		md->numactive = numactive;
342 
343 		i4bputqueue_hipri(m);		/* URGENT !!! */
344 	}
345 }
346 
347 /*---------------------------------------------------------------------------*
348  *	send MSG_L12STAT_IND message to userland
349  *---------------------------------------------------------------------------*/
350 void
i4b_l4_l12stat(struct isdn_l3_driver * d,int layer,int state)351 i4b_l4_l12stat(struct isdn_l3_driver *d, int layer, int state)
352 {
353 	struct mbuf *m;
354 
355 	if((m = i4b_Dgetmbuf(sizeof(msg_l12stat_ind_t))) != NULL)
356 	{
357 		msg_l12stat_ind_t *md = (msg_l12stat_ind_t *)m->m_data;
358 
359 		md->header.type = MSG_L12STAT_IND;
360 		md->header.cdid = -1;
361 
362 		md->controller = d->isdnif;
363 		md->layer = layer;
364 		md->state = state;
365 
366 		i4bputqueue(m);
367 	}
368 }
369 
370 /*---------------------------------------------------------------------------*
371  *	send MSG_TEIASG_IND message to userland
372  *---------------------------------------------------------------------------*/
373 void
i4b_l4_teiasg(struct isdn_l3_driver * d,int tei)374 i4b_l4_teiasg(struct isdn_l3_driver *d, int tei)
375 {
376 	struct mbuf *m;
377 
378 	if((m = i4b_Dgetmbuf(sizeof(msg_teiasg_ind_t))) != NULL)
379 	{
380 		msg_teiasg_ind_t *md = (msg_teiasg_ind_t *)m->m_data;
381 
382 		md->header.type = MSG_TEIASG_IND;
383 		md->header.cdid = -1;
384 
385 		md->controller = d->isdnif;
386 		md->tei = d->tei;
387 
388 		i4bputqueue(m);
389 	}
390 }
391 
392 /*---------------------------------------------------------------------------*
393  *	send MSG_DIALOUT_IND message to userland
394  *---------------------------------------------------------------------------*/
395 void
i4b_l4_dialout(int driver,int driver_unit)396 i4b_l4_dialout(int driver, int driver_unit)
397 {
398 	struct mbuf *m;
399 
400 	if((m = i4b_Dgetmbuf(sizeof(msg_dialout_ind_t))) != NULL)
401 	{
402 		msg_dialout_ind_t *md = (msg_dialout_ind_t *)m->m_data;
403 
404 		md->header.type = MSG_DIALOUT_IND;
405 		md->header.cdid = -1;
406 
407 		md->driver = driver;
408 		md->driver_unit = driver_unit;
409 
410 		i4bputqueue(m);
411 	}
412 }
413 
414 /*---------------------------------------------------------------------------*
415  *	send MSG_DIALOUTNUMBER_IND message to userland
416  *---------------------------------------------------------------------------*/
417 void
i4b_l4_dialoutnumber(int driver,int driver_unit,int cmdlen,char * cmd)418 i4b_l4_dialoutnumber(int driver, int driver_unit, int cmdlen, char *cmd)
419 {
420 	struct mbuf *m;
421 
422 	if((m = i4b_Dgetmbuf(sizeof(msg_dialoutnumber_ind_t))) != NULL)
423 	{
424 		msg_dialoutnumber_ind_t *md = (msg_dialoutnumber_ind_t *)m->m_data;
425 
426 		md->header.type = MSG_DIALOUTNUMBER_IND;
427 		md->header.cdid = -1;
428 
429 		md->driver = driver;
430 		md->driver_unit = driver_unit;
431 
432 		if(cmdlen > TELNO_MAX)
433 			cmdlen = TELNO_MAX;
434 
435 		md->cmdlen = cmdlen;
436 		memcpy(md->cmd, cmd, cmdlen);
437 		i4bputqueue(m);
438 	}
439 }
440 
441 /*---------------------------------------------------------------------------*
442  *	send MSG_NEGOTIATION_COMPL message to userland
443  *---------------------------------------------------------------------------*/
444 void
i4b_l4_negcomplete(call_desc_t * cd)445 i4b_l4_negcomplete(call_desc_t *cd)
446 {
447 	struct mbuf *m;
448 
449 	if((m = i4b_Dgetmbuf(sizeof(msg_negcomplete_ind_t))) != NULL)
450 	{
451 		msg_negcomplete_ind_t *md = (msg_negcomplete_ind_t *)m->m_data;
452 
453 		md->header.type = MSG_NEGCOMP_IND;
454 		md->header.cdid = cd->cdid;
455 
456 		i4bputqueue(m);
457 	}
458 }
459 
460 /*---------------------------------------------------------------------------*
461  *	send MSG_IFSTATE_CHANGED_IND message to userland
462  *---------------------------------------------------------------------------*/
463 void
i4b_l4_ifstate_changed(call_desc_t * cd,int new_state)464 i4b_l4_ifstate_changed(call_desc_t *cd, int new_state)
465 {
466 	struct mbuf *m;
467 
468 	if((m = i4b_Dgetmbuf(sizeof(msg_ifstatechg_ind_t))) != NULL)
469 	{
470 		msg_ifstatechg_ind_t *md = (msg_ifstatechg_ind_t *)m->m_data;
471 
472 		md->header.type = MSG_IFSTATE_CHANGED_IND;
473 		md->header.cdid = cd->cdid;
474 		md->state = new_state;
475 
476 		i4bputqueue(m);
477 	}
478 }
479 
480 /*---------------------------------------------------------------------------*
481  *	send MSG_DRVRDISC_REQ message to userland
482  *---------------------------------------------------------------------------*/
483 void
i4b_l4_drvrdisc(int cdid)484 i4b_l4_drvrdisc(int cdid)
485 {
486 	struct mbuf *m;
487 
488 	if((m = i4b_Dgetmbuf(sizeof(msg_drvrdisc_req_t))) != NULL)
489 	{
490 		msg_drvrdisc_req_t *md = (msg_drvrdisc_req_t *)m->m_data;
491 
492 		md->header.type = MSG_DRVRDISC_REQ;
493 		md->header.cdid = cdid;
494 
495 		i4bputqueue(m);
496 	}
497 }
498 
499 /*---------------------------------------------------------------------------*
500  *	send MSG_ACCT_IND message to userland
501  *---------------------------------------------------------------------------*/
502 void
i4b_l4_accounting(int cdid,int accttype,int ioutbytes,int iinbytes,int ro,int ri,int outbytes,int inbytes)503 i4b_l4_accounting(int cdid, int accttype, int ioutbytes,
504 		int iinbytes, int ro, int ri, int outbytes, int inbytes)
505 {
506 	struct mbuf *m;
507 
508 	if((m = i4b_Dgetmbuf(sizeof(msg_accounting_ind_t))) != NULL)
509 	{
510 		msg_accounting_ind_t *md = (msg_accounting_ind_t *)m->m_data;
511 
512 		md->header.type = MSG_ACCT_IND;
513 		md->header.cdid = cdid;
514 
515 		md->accttype = accttype;
516 		md->ioutbytes = ioutbytes;
517 		md->iinbytes = iinbytes;
518 		md->outbps = ro;
519 		md->inbps = ri;
520 		md->outbytes = outbytes;
521 		md->inbytes = inbytes;
522 
523 		i4bputqueue(m);
524 	}
525 }
526 
527 /*---------------------------------------------------------------------------*
528  *	send MSG_CONNECT_IND message to userland
529  *---------------------------------------------------------------------------*/
530 void
i4b_l4_connect_ind(call_desc_t * cd)531 i4b_l4_connect_ind(call_desc_t *cd)
532 {
533 	struct mbuf *m;
534 
535 	if((m = i4b_Dgetmbuf(sizeof(msg_connect_ind_t))) != NULL)
536 	{
537 		msg_connect_ind_t *mp = (msg_connect_ind_t *)m->m_data;
538 
539 		mp->header.type = MSG_CONNECT_IND;
540 		mp->header.cdid = cd->cdid;
541 
542 		mp->controller = cd->isdnif;
543 		mp->channel = cd->channelid;
544 		mp->bprot = cd->bprot;
545 
546 		cd->dir = DIR_INCOMING;
547 
548 		if(strlen(cd->dst_telno) > 0)
549 			strlcpy(mp->dst_telno, cd->dst_telno, sizeof mp->dst_telno);
550 		else
551 			strlcpy(mp->dst_telno, TELNO_EMPTY, sizeof mp->dst_telno);
552 
553 		if(strlen(cd->src_telno) > 0)
554 			strlcpy(mp->src_telno, cd->src_telno, sizeof mp->src_telno);
555 		else
556 			strlcpy(mp->src_telno, TELNO_EMPTY, sizeof mp->src_telno);
557 		mp->type_plan = cd->type_plan;
558 		memcpy(mp->src_subaddr, cd->src_subaddr, sizeof(mp->src_subaddr));
559 		memcpy(mp->dest_subaddr, cd->dest_subaddr, sizeof(mp->dest_subaddr));
560 
561 		strlcpy(mp->display, cd->display, sizeof mp->src_telno);
562 
563 		mp->scr_ind = cd->scr_ind;
564 		mp->prs_ind = cd->prs_ind;
565 
566 		T400_start(cd);
567 
568 		i4bputqueue(m);
569 	}
570 }
571 
572 /*---------------------------------------------------------------------------*
573  *	send MSG_CONNECT_ACTIVE_IND message to userland
574  *---------------------------------------------------------------------------*/
575 void
i4b_l4_connect_active_ind(call_desc_t * cd)576 i4b_l4_connect_active_ind(call_desc_t *cd)
577 {
578 	int s;
579 	struct mbuf *m;
580 
581 	s = splnet();
582 
583 	cd->last_active_time = cd->connect_time = SECOND;
584 
585 	NDBGL4(L4_TIMO, "last_active/connect_time=%ld", (long)cd->connect_time);
586 
587 	i4b_link_bchandrvr(cd);
588 
589 	update_controller_leds(cd->l3drv);
590 
591 	(*cd->l4_driver->line_connected)(cd->l4_driver_softc, cd);
592 
593 	i4b_l4_setup_timeout(cd);
594 
595 	splx(s);
596 
597 	if((m = i4b_Dgetmbuf(sizeof(msg_connect_active_ind_t))) != NULL)
598 	{
599 		msg_connect_active_ind_t *mp = (msg_connect_active_ind_t *)m->m_data;
600 
601 		mp->header.type = MSG_CONNECT_ACTIVE_IND;
602 		mp->header.cdid = cd->cdid;
603 		mp->controller = cd->isdnif;
604 		mp->channel = cd->channelid;
605 		if(cd->datetime[0] != '\0')
606 			strlcpy(mp->datetime, cd->datetime, sizeof mp->datetime);
607 		else
608 			mp->datetime[0] = '\0';
609 		i4bputqueue(m);
610 	}
611 }
612 
613 /*---------------------------------------------------------------------------*
614  *	send MSG_DISCONNECT_IND message to userland
615  *---------------------------------------------------------------------------*/
616 void
i4b_l4_disconnect_ind(call_desc_t * cd)617 i4b_l4_disconnect_ind(call_desc_t *cd)
618 {
619 	struct isdn_l3_driver *d;
620 	struct mbuf *m;
621 
622 	if(cd->timeout_active)
623 		STOP_TIMER(cd->idle_timeout_handle, i4b_idle_check, cd);
624 
625 	if (cd->l4_driver != NULL && cd->l4_driver_softc != NULL)
626 	{
627 		(*cd->l4_driver->line_disconnected)(cd->l4_driver_softc, (void *)cd);
628 		i4b_unlink_bchandrvr(cd);
629 	}
630 
631 	d = cd->l3drv;
632 
633 	if((cd->channelid >= 0) && (cd->channelid < d->nbch))
634 	{
635 		d->bch_state[cd->channelid] = BCH_ST_FREE;
636 		/*
637 		 * XXX: don't call l2 function for active cards.
638 		 */
639 		if (d->l3driver->N_DOWNLOAD == NULL)
640 			i4b_l2_channel_set_state(d, cd->channelid, BCH_ST_FREE);
641 	}
642 	else
643 	{
644 		/* no error, might be hunting call for callback */
645 		NDBGL4(L4_MSG, "invalid channel %d for ISDN!", cd->channelid);
646 	}
647 	update_controller_leds(d);
648 
649 	if((m = i4b_Dgetmbuf(sizeof(msg_disconnect_ind_t))) != NULL)
650 	{
651 		msg_disconnect_ind_t *mp = (msg_disconnect_ind_t *)m->m_data;
652 
653 		mp->header.type = MSG_DISCONNECT_IND;
654 		mp->header.cdid = cd->cdid;
655 		mp->cause = cd->cause_in;
656 
657 		i4bputqueue(m);
658 	}
659 }
660 
661 /*---------------------------------------------------------------------------*
662  *	send MSG_IDLE_TIMEOUT_IND message to userland
663  *---------------------------------------------------------------------------*/
664 void
i4b_l4_idle_timeout_ind(call_desc_t * cd)665 i4b_l4_idle_timeout_ind(call_desc_t *cd)
666 {
667 	struct mbuf *m;
668 
669 	if((m = i4b_Dgetmbuf(sizeof(msg_idle_timeout_ind_t))) != NULL)
670 	{
671 		msg_idle_timeout_ind_t *mp = (msg_idle_timeout_ind_t *)m->m_data;
672 
673 		mp->header.type = MSG_IDLE_TIMEOUT_IND;
674 		mp->header.cdid = cd->cdid;
675 
676 		i4bputqueue(m);
677 	}
678 }
679 
680 /*---------------------------------------------------------------------------*
681  *	send MSG_CHARGING_IND message to userland
682  *---------------------------------------------------------------------------*/
683 void
i4b_l4_charging_ind(call_desc_t * cd)684 i4b_l4_charging_ind(call_desc_t *cd)
685 {
686 	struct mbuf *m;
687 
688 	if((m = i4b_Dgetmbuf(sizeof(msg_charging_ind_t))) != NULL)
689 	{
690 		msg_charging_ind_t *mp = (msg_charging_ind_t *)m->m_data;
691 
692 		mp->header.type = MSG_CHARGING_IND;
693 		mp->header.cdid = cd->cdid;
694 		mp->units_type = cd->units_type;
695 
696 /*XXX*/		if(mp->units_type == CHARGE_CALC)
697 			mp->units = cd->cunits;
698 		else
699 			mp->units = cd->units;
700 
701 		i4bputqueue(m);
702 	}
703 }
704 
705 /*---------------------------------------------------------------------------*
706  *	send MSG_STATUS_IND message to userland
707  *---------------------------------------------------------------------------*/
708 void
i4b_l4_status_ind(call_desc_t * cd)709 i4b_l4_status_ind(call_desc_t *cd)
710 {
711 }
712 
713 /*---------------------------------------------------------------------------*
714  *	send MSG_ALERT_IND message to userland
715  *---------------------------------------------------------------------------*/
716 void
i4b_l4_alert_ind(call_desc_t * cd)717 i4b_l4_alert_ind(call_desc_t *cd)
718 {
719 	struct mbuf *m;
720 
721 	if((m = i4b_Dgetmbuf(sizeof(msg_alert_ind_t))) != NULL)
722 	{
723 		msg_alert_ind_t *mp = (msg_alert_ind_t *)m->m_data;
724 
725 		mp->header.type = MSG_ALERT_IND;
726 		mp->header.cdid = cd->cdid;
727 
728 		i4bputqueue(m);
729 	}
730 }
731 
732 /*---------------------------------------------------------------------------*
733  *	send MSG_INFO_IND message to userland
734  *---------------------------------------------------------------------------*/
735 void
i4b_l4_info_ind(call_desc_t * cd)736 i4b_l4_info_ind(call_desc_t *cd)
737 {
738 }
739 
740 /*---------------------------------------------------------------------------*
741  *	send MSG_INFO_IND message to userland
742  *---------------------------------------------------------------------------*/
743 void
i4b_l4_proceeding_ind(call_desc_t * cd)744 i4b_l4_proceeding_ind(call_desc_t *cd)
745 {
746 	struct mbuf *m;
747 
748 	if((m = i4b_Dgetmbuf(sizeof(msg_proceeding_ind_t))) != NULL)
749 	{
750 		msg_proceeding_ind_t *mp = (msg_proceeding_ind_t *)m->m_data;
751 
752 		mp->header.type = MSG_PROCEEDING_IND;
753 		mp->header.cdid = cd->cdid;
754 		mp->controller = cd->isdnif;
755 		mp->channel = cd->channelid;
756 		i4bputqueue(m);
757 	}
758 }
759 
760 /*---------------------------------------------------------------------------*
761  *    send MSG_PACKET_IND message to userland
762  *---------------------------------------------------------------------------*/
763 void
i4b_l4_packet_ind(int driver,int driver_unit,int dir,struct mbuf * pkt)764 i4b_l4_packet_ind(int driver, int driver_unit, int dir, struct mbuf *pkt)
765 {
766 	struct mbuf *m;
767 	int len = pkt->m_pkthdr.len;
768 	unsigned char *ip = pkt->m_data;
769 
770 	if((m = i4b_Dgetmbuf(sizeof(msg_packet_ind_t))) != NULL)
771 	{
772 		msg_packet_ind_t *mp = (msg_packet_ind_t *)m->m_data;
773 
774 		mp->header.type = MSG_PACKET_IND;
775 		mp->header.cdid = -1;
776 		mp->driver = driver;
777 		mp->driver_unit = driver_unit;
778 		mp->direction = dir;
779 		memcpy(mp->pktdata, ip,
780 			len <MAX_PACKET_LOG ? len : MAX_PACKET_LOG);
781 		i4bputqueue(m);
782 	}
783 }
784 
785 /*---------------------------------------------------------------------------*
786  *    send MSG_CONTR_EV_IND message to userland
787  *---------------------------------------------------------------------------*/
788 void
i4b_l4_contr_ev_ind(int controller,int attach)789 i4b_l4_contr_ev_ind(int controller, int attach)
790 {
791 	struct mbuf *m;
792 
793 	if((m = i4b_Dgetmbuf(sizeof(msg_ctrl_ev_ind_t))) != NULL)
794 	{
795 		msg_ctrl_ev_ind_t *ev = (msg_ctrl_ev_ind_t *)m->m_data;
796 
797 		ev->header.type = MSG_CONTR_EV_IND;
798 		ev->header.cdid = -1;
799 		ev->controller = controller;
800 		ev->event = attach;
801 		i4bputqueue(m);
802 	}
803 }
804 
805 /*---------------------------------------------------------------------------*
806  *	link a driver(unit) to a B-channel(controller,unit,channel)
807  *---------------------------------------------------------------------------*/
808 static int
i4b_link_bchandrvr(call_desc_t * cd)809 i4b_link_bchandrvr(call_desc_t *cd)
810 {
811 	struct isdn_l3_driver *d = cd->l3drv;
812 
813 	if (d == NULL || d->l3driver == NULL || d->l3driver->get_linktab == NULL)
814 	{
815 			cd->ilt = NULL;
816 			return 1;
817 	}
818 
819 	cd->ilt = d->l3driver->get_linktab(d->l1_token,
820 	    cd->channelid);
821 
822 	cd->l4_driver = isdn_l4_get_driver(cd->bchan_driver_index, cd->bchan_driver_unit);
823 	if (cd->l4_driver != NULL)
824 		cd->l4_driver_softc = cd->l4_driver->get_softc(cd->bchan_driver_unit);
825 	else
826 		cd->l4_driver_softc = NULL;
827 
828 	if(cd->l4_driver == NULL || cd->l4_driver_softc == NULL || cd->ilt == NULL)
829 		return(-1);
830 
831 	if (d->l3driver->set_l4_driver != NULL)
832 	{
833 		d->l3driver->set_l4_driver(d->l1_token,
834 		    cd->channelid, cd->l4_driver, cd->l4_driver_softc);
835 	}
836 
837 	cd->l4_driver->set_linktab(cd->l4_driver_softc, cd->ilt);
838 
839 	/* activate B channel */
840 
841 	(*cd->ilt->bchannel_driver->bch_config)(cd->ilt->l1token, cd->ilt->channel, cd->bprot, 1);
842 
843 	return(0);
844 }
845 
846 /*---------------------------------------------------------------------------*
847  *	unlink a driver(unit) from a B-channel(controller,unit,channel)
848  *---------------------------------------------------------------------------*/
849 static void
i4b_unlink_bchandrvr(call_desc_t * cd)850 i4b_unlink_bchandrvr(call_desc_t *cd)
851 {
852 	struct isdn_l3_driver *d = cd->l3drv;
853 
854 	/*
855 	 * XXX - what's this *cd manipulation for? Shouldn't we
856 	 * close the bchannel driver first and then just set ilt to NULL
857 	 * in *cd?
858 	 */
859 	if (d == NULL || d->l3driver == NULL || d->l3driver->get_linktab == NULL)
860 	{
861 		cd->ilt = NULL;
862 		return;
863 	}
864 	else
865 	{
866 		cd->ilt = d->l3driver->get_linktab(
867 		    d->l1_token, cd->channelid);
868 	}
869 
870 	/* deactivate B channel */
871 
872 	(*cd->ilt->bchannel_driver->bch_config)(cd->ilt->l1token, cd->ilt->channel, cd->bprot, 0);
873 }
874 
875 /*---------------------------------------------------------------------------
876 
877 	How shorthold mode works for OUTGOING connections
878 	=================================================
879 
880 	|<---- unchecked-window ------->|<-checkwindow->|<-safetywindow>|
881 
882 idletime_state:      IST_NONCHK             IST_CHECK       IST_SAFE
883 
884 	|				|		|		|
885   time>>+-------------------------------+---------------+---------------+-...
886 	|				|		|		|
887 	|				|<--idle_time-->|<--earlyhup--->|
888 	|<-----------------------unitlen------------------------------->|
889 
890 
891 	  unitlen - specifies the time a charging unit lasts
892 	idle_time - specifies the thime the line must be idle at the
893 		    end of the unit to be elected for hangup
894 	 earlyhup - is the beginning of a timing safety zone before the
895 		    next charging unit starts
896 
897 	The algorithm works as follows: lets assume the unitlen is 100
898 	secons, idle_time is 40 seconds and earlyhup is 10 seconds.
899 	The line then must be idle 50 seconds after the begin of the
900 	current unit and it must then be quiet for 40 seconds. if it
901 	has been quiet for this 40 seconds, the line is closed 10
902 	seconds before the next charging unit starts. In case there was
903 	any traffic within the idle_time, the line is not closed.
904 	It does not matter whether there was any traffic between second
905 	0 and second 50 or not.
906 
907 
908 	How shorthold mode works for INCOMING connections
909 	=================================================
910 
911 	it is just possible to specify a maximum idle time for incoming
912 	connections, after this time of no activity on the line the line
913 	is closed.
914 
915 ---------------------------------------------------------------------------*/
916 
917 static time_t
i4b_get_idletime(call_desc_t * cd)918 i4b_get_idletime(call_desc_t *cd)
919 {
920 	if (cd->l4_driver->get_idletime)
921 		return cd->l4_driver->get_idletime(cd->l4_driver_softc);
922 	return cd->last_active_time;
923 }
924 
925 /*---------------------------------------------------------------------------*
926  *	B channel idle check timeout setup
927  *---------------------------------------------------------------------------*/
928 static void
i4b_l4_setup_timeout(call_desc_t * cd)929 i4b_l4_setup_timeout(call_desc_t *cd)
930 {
931 	NDBGL4(L4_TIMO, "%ld: direction %d, shorthold algorithm %d",
932 		(long)SECOND, cd->dir, cd->shorthold_data.shorthold_algorithm);
933 
934 	cd->timeout_active = 0;
935 	cd->idletime_state = IST_IDLE;
936 
937 	if((cd->dir == DIR_INCOMING) && (cd->max_idle_time > 0))
938 	{
939 		/* incoming call: simple max idletime check */
940 
941 		START_TIMER(cd->idle_timeout_handle, i4b_idle_check, cd, hz/2);
942 		cd->timeout_active = 1;
943 		NDBGL4(L4_TIMO, "%ld: incoming-call, setup max_idle_time to %ld", (long)SECOND, (long)cd->max_idle_time);
944 	}
945 	else if((cd->dir == DIR_OUTGOING) && (cd->shorthold_data.idle_time > 0))
946 	{
947 		switch( cd->shorthold_data.shorthold_algorithm )
948 		{
949 			default:	/* fall into the old fix algorithm */
950 			case SHA_FIXU:
951 				i4b_l4_setup_timeout_fix_unit( cd );
952 				break;
953 
954 			case SHA_VARU:
955 				i4b_l4_setup_timeout_var_unit( cd );
956 				break;
957 		}
958 	}
959 	else
960 	{
961 		NDBGL4(L4_TIMO, "no idle_timeout configured");
962 	}
963 }
964 
965 /*---------------------------------------------------------------------------*
966  *	fixed unit algorithm B channel idle check timeout setup
967  *---------------------------------------------------------------------------*/
968 static void
i4b_l4_setup_timeout_fix_unit(call_desc_t * cd)969 i4b_l4_setup_timeout_fix_unit(call_desc_t *cd)
970 {
971 	/* outgoing call */
972 
973 	if((cd->shorthold_data.idle_time > 0) && (cd->shorthold_data.unitlen_time == 0))
974 	{
975 		/* outgoing call: simple max idletime check */
976 
977 		START_TIMER(cd->idle_timeout_handle, i4b_idle_check, cd, hz/2);
978 		cd->timeout_active = 1;
979 		NDBGL4(L4_TIMO, "%ld: outgoing-call, setup idle_time to %ld",
980 			(long)SECOND, (long)cd->shorthold_data.idle_time);
981 	}
982 	else if((cd->shorthold_data.unitlen_time > 0) && (cd->shorthold_data.unitlen_time > (cd->shorthold_data.idle_time + cd->shorthold_data.earlyhup_time)))
983 	{
984 		/* outgoing call: full shorthold mode check */
985 
986 		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)));
987 		cd->timeout_active = 1;
988 		cd->idletime_state = IST_NONCHK;
989 		NDBGL4(L4_TIMO, "%ld: outgoing-call, start %ld sec nocheck window",
990 			(long)SECOND, (long)(cd->shorthold_data.unitlen_time - (cd->shorthold_data.idle_time + cd->shorthold_data.earlyhup_time)));
991 
992 		if(cd->aocd_flag == 0)
993 		{
994 			cd->units_type = CHARGE_CALC;
995 			cd->cunits++;
996 			i4b_l4_charging_ind(cd);
997 		}
998 	}
999 	else
1000 	{
1001 		/* parms somehow got wrong .. */
1002 
1003 		NDBGL4(L4_ERR, "%ld: ERROR: idletime[%ld]+earlyhup[%ld] > unitlength[%ld]!",
1004 			(long)SECOND, (long)cd->shorthold_data.idle_time, (long)cd->shorthold_data.earlyhup_time, (long)cd->shorthold_data.unitlen_time);
1005 	}
1006 }
1007 
1008 /*---------------------------------------------------------------------------*
1009  *	variable unit algorithm B channel idle check timeout setup
1010  *---------------------------------------------------------------------------*/
1011 static void
i4b_l4_setup_timeout_var_unit(call_desc_t * cd)1012 i4b_l4_setup_timeout_var_unit(call_desc_t *cd)
1013 {
1014 	/* outgoing call: variable unit idletime check */
1015 
1016 	/*
1017 	 * start checking for an idle connect one second before the end of the unit.
1018 	 * The one second takes into account of rounding due to the driver only
1019 	 * using the seconds and not the uSeconds of the current time
1020 	 */
1021 	cd->idletime_state = IST_CHECK;	/* move directly to the checking state */
1022 
1023 	START_TIMER(cd->idle_timeout_handle, i4b_idle_check, cd, hz * (cd->shorthold_data.unitlen_time - 1) );
1024 	cd->timeout_active = 1;
1025 	NDBGL4(L4_TIMO, "%ld: outgoing-call, var idle time - setup to %ld",
1026 		(long)SECOND, (long)cd->shorthold_data.unitlen_time);
1027 }
1028 
1029 
1030 /*---------------------------------------------------------------------------*
1031  *	B channel idle check timeout function
1032  *---------------------------------------------------------------------------*/
1033 void
i4b_idle_check(call_desc_t * cd)1034 i4b_idle_check(call_desc_t *cd)
1035 {
1036 	int s;
1037 
1038 	if(cd->cdid == CDID_UNUSED)
1039 		return;
1040 
1041 	s = splnet();
1042 
1043 	/* failsafe */
1044 
1045 	if(cd->timeout_active == 0)
1046 	{
1047 		NDBGL4(L4_ERR, "ERROR: timeout_active == 0 !!!");
1048 	}
1049 	else
1050 	{
1051 		cd->timeout_active = 0;
1052 	}
1053 
1054 	/* incoming connections, simple idletime check */
1055 
1056 	if(cd->dir == DIR_INCOMING)
1057 	{
1058 		if((i4b_get_idletime(cd) + cd->max_idle_time) <= SECOND)
1059 		{
1060 			struct isdn_l3_driver *d = cd->l3drv;
1061 			NDBGL4(L4_TIMO, "%ld: incoming-call, line idle timeout, disconnecting!", (long)SECOND);
1062 			d->l3driver->N_DISCONNECT_REQUEST(cd,
1063 					(CAUSET_I4B << 8) | CAUSE_I4B_NORMAL);
1064 			i4b_l4_idle_timeout_ind(cd);
1065 		}
1066 		else
1067 		{
1068 			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);
1069 
1070 			START_TIMER(cd->idle_timeout_handle, i4b_idle_check, cd, hz/2);
1071 			cd->timeout_active = 1;
1072 		}
1073 	}
1074 
1075 	/* outgoing connections */
1076 
1077 	else if(cd->dir == DIR_OUTGOING)
1078 	{
1079 		switch( cd->shorthold_data.shorthold_algorithm )
1080 		{
1081 			case SHA_FIXU:
1082 				i4b_idle_check_fix_unit( cd );
1083 				break;
1084 			case SHA_VARU:
1085 				i4b_idle_check_var_unit( cd );
1086 				break;
1087 			default:
1088 				NDBGL4(L4_TIMO, "%ld: bad value for shorthold_algorithm of %d",
1089 					(long)SECOND, cd->shorthold_data.shorthold_algorithm);
1090 				i4b_idle_check_fix_unit( cd );
1091 				break;
1092 		}
1093 	}
1094 	splx(s);
1095 }
1096 
1097 /*---------------------------------------------------------------------------*
1098  *	fixed unit algorithm B channel idle check timeout function
1099  *---------------------------------------------------------------------------*/
1100 static void
i4b_idle_check_fix_unit(call_desc_t * cd)1101 i4b_idle_check_fix_unit(call_desc_t *cd)
1102 {
1103 	struct isdn_l3_driver *d = cd->l3drv;
1104 
1105 	/* simple idletime calculation */
1106 
1107 	if((cd->shorthold_data.idle_time > 0) && (cd->shorthold_data.unitlen_time == 0))
1108 	{
1109 		if((i4b_get_idletime(cd) + cd->shorthold_data.idle_time) <= SECOND)
1110 		{
1111 			NDBGL4(L4_TIMO, "%ld: outgoing-call-st, idle timeout, disconnecting!", (long)SECOND);
1112 			d->l3driver->N_DISCONNECT_REQUEST(cd, (CAUSET_I4B << 8) | CAUSE_I4B_NORMAL);
1113 			i4b_l4_idle_timeout_ind(cd);
1114 		}
1115 		else
1116 		{
1117 			NDBGL4(L4_TIMO, "%ld: outgoing-call-st, activity, last_active=%ld, max_idle=%ld",
1118 					(long)SECOND, (long)i4b_get_idletime(cd), (long)cd->shorthold_data.idle_time);
1119 			START_TIMER(cd->idle_timeout_handle, i4b_idle_check, cd, hz/2);
1120 			cd->timeout_active = 1;
1121 		}
1122 	}
1123 
1124 	/* full shorthold mode calculation */
1125 
1126 	else if((cd->shorthold_data.unitlen_time > 0)
1127 	         && (cd->shorthold_data.unitlen_time > (cd->shorthold_data.idle_time + cd->shorthold_data.earlyhup_time)))
1128 	{
1129 		switch(cd->idletime_state)
1130 		{
1131 
1132 		case IST_NONCHK:	/* end of non-check time */
1133 
1134 			START_TIMER(cd->idle_timeout_handle, i4b_idle_check, cd, hz*(cd->shorthold_data.idle_time));
1135 			cd->idletimechk_start = SECOND;
1136 			cd->idletime_state = IST_CHECK;
1137 			cd->timeout_active = 1;
1138 			NDBGL4(L4_TIMO, "%ld: outgoing-call, idletime check window reached!", (long)SECOND);
1139 			break;
1140 
1141 		case IST_CHECK:		/* end of idletime chk */
1142 			if((i4b_get_idletime(cd) > cd->idletimechk_start) &&
1143 			   (i4b_get_idletime(cd) <= SECOND))
1144 			{	/* activity detected */
1145 				START_TIMER(cd->idle_timeout_handle, i4b_idle_check, cd, hz*(cd->shorthold_data.earlyhup_time));
1146 				cd->timeout_active = 1;
1147 				cd->idletime_state = IST_SAFE;
1148 				NDBGL4(L4_TIMO, "%ld: outgoing-call, activity at %ld, wait earlyhup-end", (long)SECOND, (long)i4b_get_idletime(cd));
1149 			}
1150 			else
1151 			{	/* no activity, hangup */
1152 				NDBGL4(L4_TIMO, "%ld: outgoing-call, idle timeout, last activity at %ld", (long)SECOND, (long)i4b_get_idletime(cd));
1153 				d->l3driver->N_DISCONNECT_REQUEST(cd, (CAUSET_I4B << 8) | CAUSE_I4B_NORMAL);
1154 				i4b_l4_idle_timeout_ind(cd);
1155 				cd->idletime_state = IST_IDLE;
1156 			}
1157 			break;
1158 
1159 		case IST_SAFE:	/* end of earlyhup time */
1160 
1161 			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)));
1162 			cd->timeout_active = 1;
1163 			cd->idletime_state = IST_NONCHK;
1164 
1165 			if(cd->aocd_flag == 0)
1166 			{
1167 				cd->units_type = CHARGE_CALC;
1168 				cd->cunits++;
1169 				i4b_l4_charging_ind(cd);
1170 			}
1171 
1172 			NDBGL4(L4_TIMO, "%ld: outgoing-call, earlyhup end, wait for idletime start", (long)SECOND);
1173 			break;
1174 
1175 		default:
1176 			NDBGL4(L4_ERR, "outgoing-call: invalid idletime_state value!");
1177 			cd->idletime_state = IST_IDLE;
1178 			break;
1179 		}
1180 	}
1181 }
1182 
1183 /*---------------------------------------------------------------------------*
1184  *	variable unit algorithm B channel idle check timeout function
1185  *---------------------------------------------------------------------------*/
1186 static void
i4b_idle_check_var_unit(call_desc_t * cd)1187 i4b_idle_check_var_unit(call_desc_t *cd)
1188 {
1189 	switch(cd->idletime_state)
1190 	{
1191 
1192 	/* see if there has been any activity within the last idle_time seconds */
1193 	case IST_CHECK:
1194 		if( i4b_get_idletime(cd) > (SECOND - cd->shorthold_data.idle_time))
1195 		{	/* activity detected */
1196 #if defined(__FreeBSD_version) && __FreeBSD_version >= 300001
1197 			cd->idle_timeout_handle =
1198 #endif
1199 			/* check again in one second */
1200 			START_TIMER(cd->idle_timeout_handle, i4b_idle_check, cd, hz);
1201 			cd->timeout_active = 1;
1202 			cd->idletime_state = IST_CHECK;
1203 			NDBGL4(L4_TIMO, "%ld: outgoing-call, var idle timeout - activity at %ld, continuing", (long)SECOND, (long)i4b_get_idletime(cd));
1204 		}
1205 		else
1206 		{	/* no activity, hangup */
1207 			struct isdn_l3_driver *d = cd->l3drv;
1208 			NDBGL4(L4_TIMO, "%ld: outgoing-call, var idle timeout - last activity at %ld", (long)SECOND, (long)i4b_get_idletime(cd));
1209 			d->l3driver->N_DISCONNECT_REQUEST(cd, (CAUSET_I4B << 8) | CAUSE_I4B_NORMAL);
1210 			i4b_l4_idle_timeout_ind(cd);
1211 			cd->idletime_state = IST_IDLE;
1212 		}
1213 		break;
1214 
1215 	default:
1216 		NDBGL4(L4_ERR, "outgoing-call: var idle timeout invalid idletime_state value!");
1217 		cd->idletime_state = IST_IDLE;
1218 		break;
1219 	}
1220 }
1221 
1222 #endif /* NISDN > 0 */
1223