1/*	$NetBSD: i4b_capi_msgs.c,v 1.5.4.4 2005/03/04 16:53:44 skrll Exp $	*/
2
3/*
4 * Copyright (c) 2001-2003 Cubical Solutions Ltd. 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 * capi/capi_msgs.c	The CAPI i4b message handlers.
28 *
29 * $FreeBSD: src/sys/i4b/capi/capi_msgs.c,v 1.2 2001/10/21 08:51:54 hm Exp $
30 */
31
32#include <sys/cdefs.h>
33__KERNEL_RCSID(0, "$NetBSD: i4b_capi_msgs.c,v 1.5.4.4 2005/03/04 16:53:44 skrll Exp $");
34
35#include <sys/param.h>
36#include <sys/kernel.h>
37#include <sys/systm.h>
38#include <sys/mbuf.h>
39#include <sys/socket.h>
40#include <sys/callout.h>
41#include <net/if.h>
42
43#include <netisdn/i4b_debug.h>
44#include <netisdn/i4b_ioctl.h>
45#include <netisdn/i4b_cause.h>
46#include <netisdn/i4b_l3l4.h>
47#include <netisdn/i4b_mbuf.h>
48#include <netisdn/i4b_global.h>
49#include <netisdn/i4b_l4.h>
50#include <netisdn/i4b_capi.h>
51#include <netisdn/i4b_capi_msgs.h>
52
53/*
54//  Administrative messages:
55//  ------------------------
56*/
57
58void capi_listen_req(capi_softc_t *sc, u_int32_t CIP)
59{
60    struct mbuf *m = i4b_Dgetmbuf(8 + 18);
61    u_int8_t *msg;
62    u_int16_t msgid;
63
64    if (!m) {
65	printf("capi%d: can't get mbuf for listen_req\n", sc->sc_unit);
66	return;
67    }
68
69    msgid = sc->sc_msgid++;
70
71    msg = capimsg_setu16(mtod(m, u_int8_t*), m->m_len);
72    msg = capimsg_setu16(msg, I4BCAPI_APPLID);
73    msg = capimsg_setu16(msg, CAPI_LISTEN_REQ);
74    msg = capimsg_setu16(msg, msgid);
75
76    msg = capimsg_setu32(msg, sc->sc_unit + 1); /* Controller */
77    msg = capimsg_setu32(msg, 0); /* Info mask */
78    msg = capimsg_setu32(msg, CIP);
79    msg = capimsg_setu32(msg, 0);
80    msg = capimsg_setu8(msg, 0);
81    msg = capimsg_setu8(msg, 0);
82
83    sc->send(sc, m);
84}
85
86void capi_listen_conf(capi_softc_t *sc, struct mbuf *m_in)
87{
88    struct isdn_l3_driver *l3drv;
89    u_int8_t *msg = mtod(m_in, u_int8_t*);
90    u_int16_t Info;
91
92    capimsg_getu16(msg + 12, &Info);
93
94    if (Info == 0) {
95	/* We are now listening. */
96
97	sc->sc_state = C_UP;
98	l3drv = isdn_find_l3_by_isdnif(sc->capi_isdnif);
99	l3drv->dl_est = DL_UP;
100
101	i4b_l4_l12stat(l3drv, 1, 1);
102	i4b_l4_l12stat(l3drv, 2, 1);
103
104    } else {
105	/* XXX sc->sc_state = C_DOWN ? XXX */
106	printf("capi%d: can't listen, info=%04x\n", sc->sc_unit, Info);
107    }
108}
109
110void capi_info_ind(capi_softc_t *sc, struct mbuf *m_in)
111{
112    struct mbuf *m = i4b_Dgetmbuf(8 + 4);
113    u_int8_t *msg = mtod(m_in, u_int8_t*);
114    u_int16_t applid, msgid;
115    u_int32_t PLCI;
116
117    if (!m) {
118	printf("capi%d: can't get mbuf for info_resp\n", sc->sc_unit);
119	return;
120    }
121
122    msg = capimsg_getu16(msg + 2, &applid);
123    msg = capimsg_getu16(msg + 2, &msgid);
124    msg = capimsg_getu32(msg, &PLCI);
125
126    /* i4b_l4_info_ind() */
127
128    msg = capimsg_setu16(mtod(m, u_int8_t*), m->m_len);
129    msg = capimsg_setu16(msg, applid);
130    msg = capimsg_setu16(msg, CAPI_INFO_RESP);
131    msg = capimsg_setu16(msg, msgid);
132
133    msg = capimsg_setu32(msg, PLCI);
134
135    sc->send(sc, m);
136}
137
138void capi_alert_req(capi_softc_t *sc, call_desc_t *cd)
139{
140    struct mbuf *m = i4b_Dgetmbuf(8 + 5);
141    u_int8_t *msg;
142    u_int16_t msgid;
143    u_int32_t PLCI;
144
145    if (!m) {
146	printf("capi%d: can't get mbuf for alert_req\n", sc->sc_unit);
147	return;
148    }
149
150    msgid = sc->sc_bchan[cd->channelid].msgid = sc->sc_msgid++;
151    PLCI = (sc->sc_bchan[cd->channelid].ncci & CAPI_PLCI_MASK);
152
153    msg = capimsg_setu16(mtod(m, u_int8_t*), m->m_len);
154    msg = capimsg_setu16(msg, I4BCAPI_APPLID);
155    msg = capimsg_setu16(msg, CAPI_ALERT_REQ);
156    msg = capimsg_setu16(msg, msgid);
157
158    msg = capimsg_setu32(msg, PLCI);
159    msg = capimsg_setu8(msg, 0);
160
161    sc->send(sc, m);
162}
163
164void capi_alert_conf(capi_softc_t *sc, struct mbuf *m_in)
165{
166    u_int8_t *msg = mtod(m_in, u_int8_t*);
167    u_int16_t Info;
168
169    msg = capimsg_getu16(msg + 12, &Info);
170
171    if (Info) {
172	printf("capi%d: can't alert, info=%04x\n", sc->sc_unit, Info);
173    }
174}
175
176/*
177//  Outgoing call setup:
178//  --------------------
179//
180//             CAPI_CONNECT_REQ -->
181//                              <-- CAPI_CONNECT_CONF
182//                       (notify Layer 4)
183//                              <-- CAPI_CONNECT_ACTIVE_IND
184//     CAPI_CONNECT_ACTIVE_RESP -->
185//          CAPI_CONNECT_B3_REQ -->
186//                              <-- CAPI_CONNECT_B3_CONF
187//                              <-- CAPI_CONNECT_B3_ACTIVE_IND
188//  CAPI_CONNECT_B3_ACTIVE_RESP -->
189//                       (notify Layer 4)
190*/
191
192void capi_connect_req(capi_softc_t *sc, call_desc_t *cd)
193{
194    struct isdn_l3_driver *l3drv;
195    struct mbuf *m;
196    u_int8_t *msg;
197    u_int16_t msgid;
198    int slen = strlen(cd->src_telno);
199    int dlen = strlen(cd->dst_telno);
200
201    m = i4b_Dgetmbuf(8 + 27 + slen + dlen);
202    if (!m) {
203	printf("capi%d: can't get mbuf for connect_req\n", sc->sc_unit);
204	return;
205    }
206
207    l3drv = isdn_find_l3_by_isdnif(sc->capi_isdnif);
208
209    cd->crflag = CRF_ORIG;
210
211    sc->sc_bchan[cd->channelid].cdid = cd->cdid;
212    sc->sc_bchan[cd->channelid].bprot = cd->bprot;
213    sc->sc_bchan[cd->channelid].state = B_CONNECT_CONF;
214    msgid = sc->sc_bchan[cd->channelid].msgid = sc->sc_msgid++;
215    l3drv->bch_state[cd->channelid] = BCH_ST_RSVD;
216
217    msg = capimsg_setu16(mtod(m, u_int8_t*), m->m_len);
218    msg = capimsg_setu16(msg, I4BCAPI_APPLID);
219    msg = capimsg_setu16(msg, CAPI_CONNECT_REQ);
220    msg = capimsg_setu16(msg, msgid);
221
222    msg = capimsg_setu32(msg, sc->sc_unit + 1); /* Controller */
223
224    switch (cd->bprot) {
225    case BPROT_NONE:
226	msg = capimsg_setu16(msg, 0x0010); /* Telephony */
227	break;
228
229    case BPROT_RHDLC:
230	msg = capimsg_setu16(msg, 0x0002); /* Unrestricted digital */
231	break;
232
233    default:
234	msg = capimsg_setu16(msg, 0x0002); /* Unrestricted digital */
235    }
236
237    msg = capimsg_setu8(msg, 1 + dlen);
238    msg = capimsg_setu8(msg, 0x80);
239    strncpy(msg, cd->dst_telno, dlen);
240
241    msg = capimsg_setu8(msg + dlen, 2 + slen);
242    msg = capimsg_setu8(msg, 0x00);
243    msg = capimsg_setu8(msg, 0x80); /* Presentation and screening indicator */
244    strncpy(msg, cd->src_telno, slen);
245
246    msg = capimsg_setu8(msg + slen, 0); /* Called & */
247    msg = capimsg_setu8(msg, 0); /* Calling party subaddress */
248
249    msg = capimsg_setu8(msg, 15); /* B protocol */
250    if (cd->bprot == BPROT_NONE)
251	msg = capimsg_setu16(msg, 1); /* B1 protocol = transparent */
252    else
253	msg = capimsg_setu16(msg, 0); /* B1 protocol = HDLC */
254    msg = capimsg_setu16(msg, 1); /* B2 protocol = transparent */
255    msg = capimsg_setu16(msg, 0); /* B3 protocol = transparent */
256    msg = capimsg_setu8(msg, 0); /* B1 parameters */
257    msg = capimsg_setu8(msg, 0); /* B2 parameters */
258    msg = capimsg_setu8(msg, 0); /* B3 parameters */
259
260    msg = capimsg_setu8(msg, 0); /* Bearer Capability */
261    msg = capimsg_setu8(msg, 0); /* Low Layer Compatibility */
262    msg = capimsg_setu8(msg, 0); /* High Layer Compatibility */
263    msg = capimsg_setu8(msg, 0); /* Additional Info */
264
265    sc->send(sc, m);
266}
267
268void capi_connect_conf(capi_softc_t *sc, struct mbuf *m_in)
269{
270    u_int8_t *msg = mtod(m_in, u_int8_t*);
271    call_desc_t *cd;
272    u_int16_t msgid;
273    u_int32_t PLCI;
274    u_int16_t Info;
275    int bch;
276
277    msg = capimsg_getu16(msg + 6, &msgid);
278    msg = capimsg_getu32(msg, &PLCI);
279    msg = capimsg_getu16(msg, &Info);
280
281    for (bch = 0; bch < sc->sc_nbch; bch++)
282	if ((sc->sc_bchan[bch].state == B_CONNECT_CONF) &&
283	    (sc->sc_bchan[bch].msgid == msgid))
284	    break;
285
286    if ((bch == sc->sc_nbch) ||
287	(cd = cd_by_cdid(sc->sc_bchan[bch].cdid)) == NULL) {
288	printf("capi%d: can't find channel for connect_conf PLCI %x\n",
289	       sc->sc_unit, PLCI);
290	return;
291    }
292
293    if (Info == 0) {
294	sc->sc_bchan[bch].state = B_CONNECT_ACTIVE_IND;
295	sc->sc_bchan[bch].ncci = PLCI;
296
297	i4b_l4_proceeding_ind(cd);
298
299    } else {
300	struct isdn_l3_driver *l3drv;
301
302	l3drv = isdn_find_l3_by_isdnif(sc->capi_isdnif);
303	SET_CAUSE_TV(cd->cause_out, CAUSET_I4B, CAUSE_I4B_L1ERROR);
304	i4b_l4_disconnect_ind(cd);
305	freecd_by_cd(cd);
306
307	sc->sc_bchan[bch].state = B_FREE;
308
309	l3drv->bch_state[bch] = BCH_ST_FREE;
310
311	printf("capi%d: can't connect out, info=%04x\n", sc->sc_unit, Info);
312    }
313}
314
315void capi_connect_active_ind(capi_softc_t *sc, struct mbuf *m_in)
316{
317    struct mbuf *m = i4b_Dgetmbuf(8 + 4);
318    u_int8_t *msg = mtod(m_in, u_int8_t*);
319    call_desc_t *cd;
320    u_int16_t applid, msgid;
321    u_int32_t PLCI;
322    int bch;
323
324    if (!m) {
325	printf("capi%d: can't get mbuf for active_ind\n", sc->sc_unit);
326	return;
327    }
328
329    msg = capimsg_getu16(msg + 2, &applid);
330    msg = capimsg_getu16(msg + 2, &msgid);
331    msg = capimsg_getu32(msg, &PLCI);
332
333    for (bch = 0; bch < sc->sc_nbch; bch++)
334	if ((sc->sc_bchan[bch].state == B_CONNECT_ACTIVE_IND) &&
335	    (sc->sc_bchan[bch].ncci == PLCI))
336	    break;
337
338    if ((bch == sc->sc_nbch) ||
339	(cd = cd_by_cdid(sc->sc_bchan[bch].cdid)) == NULL) {
340	printf("capi%d: can't find channel for active_resp, PLCI %x\n",
341	       sc->sc_unit, PLCI);
342	return;
343    }
344
345    msg = capimsg_setu16(mtod(m, u_int8_t*), m->m_len);
346    msg = capimsg_setu16(msg, applid);
347    msg = capimsg_setu16(msg, CAPI_CONNECT_ACTIVE_RESP);
348    msg = capimsg_setu16(msg, msgid);
349
350    msg = capimsg_setu32(msg, PLCI);
351
352    sc->send(sc, m);
353
354    if (cd->crflag == CRF_ORIG) {
355	capi_connect_b3_req(sc, cd);
356
357    } else {
358	sc->sc_bchan[bch].state = B_CONNECT_B3_IND;
359    }
360}
361
362void capi_connect_b3_req(capi_softc_t *sc, call_desc_t *cd)
363{
364    struct mbuf *m = i4b_Dgetmbuf(8 + 5);
365    u_int8_t *msg;
366    u_int16_t msgid;
367    u_int32_t PLCI;
368
369    if (!m) {
370	printf("capi%d: can't get mbuf for connect_b3_req\n", sc->sc_unit);
371	return;
372    }
373
374    sc->sc_bchan[cd->channelid].state = B_CONNECT_B3_CONF;
375    msgid = sc->sc_bchan[cd->channelid].msgid = sc->sc_msgid++;
376    PLCI = (sc->sc_bchan[cd->channelid].ncci & CAPI_PLCI_MASK);
377
378    msg = capimsg_setu16(mtod(m, u_int8_t*), m->m_len);
379    msg = capimsg_setu16(msg, I4BCAPI_APPLID);
380    msg = capimsg_setu16(msg, CAPI_CONNECT_B3_REQ);
381    msg = capimsg_setu16(msg, msgid);
382
383    msg = capimsg_setu32(msg, PLCI);
384    msg = capimsg_setu8(msg, 0); /* NCPI */
385
386    sc->send(sc, m);
387}
388
389void capi_connect_b3_conf(capi_softc_t *sc, struct mbuf *m_in)
390{
391    u_int8_t *msg = mtod(m_in, u_int8_t*);
392    call_desc_t *cd;
393    u_int16_t msgid;
394    u_int32_t NCCI;
395    u_int16_t Info;
396    int bch;
397
398    msg = capimsg_getu16(msg + 6, &msgid);
399    msg = capimsg_getu32(msg, &NCCI);
400    msg = capimsg_getu16(msg, &Info);
401
402    for (bch = 0; bch < sc->sc_nbch; bch++)
403	if ((sc->sc_bchan[bch].state == B_CONNECT_B3_CONF) &&
404	    (sc->sc_bchan[bch].ncci == (NCCI & CAPI_PLCI_MASK)))
405	    break;
406
407    if ((bch == sc->sc_nbch) ||
408	(cd = cd_by_cdid(sc->sc_bchan[bch].cdid)) == NULL) {
409	printf("capi%d: can't find channel for connect_b3_conf NCCI %x\n",
410	       sc->sc_unit, NCCI);
411	return;
412    }
413
414    if (Info == 0) {
415	sc->sc_bchan[bch].ncci = NCCI;
416	sc->sc_bchan[bch].state = B_CONNECT_B3_ACTIVE_IND;
417
418    } else {
419	struct isdn_l3_driver *l3drv;
420
421	l3drv = isdn_find_l3_by_isdnif(sc->capi_isdnif);
422
423	SET_CAUSE_TV(cd->cause_in, CAUSET_I4B, CAUSE_I4B_OOO); /* XXX */
424	i4b_l4_disconnect_ind(cd);
425	freecd_by_cd(cd);
426
427	l3drv->bch_state[bch] = BCH_ST_RSVD;
428
429	printf("capi%d: can't connect_b3 out, info=%04x\n", sc->sc_unit, Info);
430
431	capi_disconnect_req(sc, cd);
432    }
433}
434
435void capi_connect_b3_active_ind(capi_softc_t *sc, struct mbuf *m_in)
436{
437    struct mbuf *m = i4b_Dgetmbuf(8 + 4);
438    u_int8_t *msg = mtod(m_in, u_int8_t*);
439    call_desc_t *cd;
440    u_int16_t applid, msgid;
441    u_int32_t NCCI;
442    int bch;
443
444    if (!m) {
445	printf("capi%d: can't get mbuf for b3_active_ind\n", sc->sc_unit);
446	return;
447    }
448
449    msg = capimsg_getu16(msg + 2, &applid);
450    msg = capimsg_getu16(msg + 2, &msgid);
451    msg = capimsg_getu32(msg, &NCCI);
452
453    for (bch = 0; bch < sc->sc_nbch; bch++)
454	if ((sc->sc_bchan[bch].state == B_CONNECT_B3_ACTIVE_IND) &&
455	    (sc->sc_bchan[bch].ncci == NCCI))
456	    break;
457
458    if ((bch == sc->sc_nbch) ||
459	(cd = cd_by_cdid(sc->sc_bchan[bch].cdid)) == NULL) {
460	printf("capi%d: can't find channel for b3_active_resp NCCI %x\n",
461	       sc->sc_unit, NCCI);
462	return;
463    }
464
465    msg = capimsg_setu16(mtod(m, u_int8_t*), m->m_len);
466    msg = capimsg_setu16(msg, I4BCAPI_APPLID);
467    msg = capimsg_setu16(msg, CAPI_CONNECT_B3_ACTIVE_RESP);
468    msg = capimsg_setu16(msg, msgid);
469
470    msg = capimsg_setu32(msg, NCCI);
471
472    sc->send(sc, m);
473
474    sc->sc_bchan[bch].state = B_CONNECTED;
475
476    i4b_l4_connect_active_ind(cd);
477}
478
479/*
480//  Incoming call setup:
481//  --------------------
482//
483//                              <-- CAPI_CONNECT_IND
484//                       (consult Layer 4)
485//            CAPI_CONNECT_RESP -->
486//                              <-- CAPI_CONNECT_ACTIVE_IND
487//     CAPI_CONNECT_ACTIVE_RESP -->
488//                              <-- CAPI_CONNECT_B3_IND
489//         CAPI_CONNECT_B3_RESP -->
490//                              <-- CAPI_CONNECT_B3_ACTIVE_IND
491//  CAPI_CONNECT_B3_ACTIVE_RESP -->
492//                       (notify Layer 4)
493*/
494
495void capi_connect_ind(capi_softc_t *sc, struct mbuf *m_in)
496{
497    u_int8_t *msg = mtod(m_in, u_int8_t*);
498    call_desc_t *cd;
499    u_int16_t applid, msgid;
500    u_int32_t PLCI;
501    u_int16_t CIP;
502    u_int8_t x, y, z;
503    int bch;
504
505    if ((cd = reserve_cd()) == NULL) {
506	printf("capi%d: can't get cd for connect_ind\n", sc->sc_unit);
507	return;
508    }
509
510    cd->isdnif = sc->capi_isdnif;
511    cd->channelexcl = 0;
512    cd->l3drv = isdn_find_l3_by_isdnif(sc->capi_isdnif);
513
514    for (bch = 0; bch < sc->sc_nbch; bch++)
515	if (sc->sc_bchan[bch].state == B_FREE)
516	    break;
517
518    sc->sc_bchan[bch].state = B_CONNECT_IND;
519    cd->channelid = bch; /* XXX CHAN_ANY XXX */
520
521    cd->crflag = CRF_DEST;
522    cd->cr = get_rand_cr(sc->sc_unit);
523    cd->scr_ind = SCR_NONE;
524    cd->prs_ind = PRS_NONE;
525    cd->bprot = BPROT_NONE;
526    cd->ilt = NULL;
527    cd->display[0] = '\0';
528    cd->datetime[0] = '\0';
529
530    msg = capimsg_getu16(msg + 2, &applid);
531    msg = capimsg_getu16(msg + 2, &msgid);
532    msg = capimsg_getu32(msg, &PLCI);
533    msg = capimsg_getu16(msg, &CIP);
534
535    cd->event = (int) msgid; /* XXX overload */
536    cd->Q931state = (int) PLCI; /* XXX overload */
537
538    switch (CIP) {
539    case 0x0010:
540    case 0x0001: cd->bprot = BPROT_NONE; break;
541    case 0x0002: cd->bprot = BPROT_RHDLC; break;
542    default:
543#if 0
544	NDBGL4(L4_CAPIDBG, "capi%d: unknown CIP = %d", sc->sc_unit, CIP);
545#endif
546	cd->bprot = BPROT_NONE;
547    }
548
549    msg = capimsg_getu8(msg, &x); /* Called party struct len */
550    if (x) {
551	msg = capimsg_getu8(msg, &y); /* Numbering plan */
552	z = x - 1;
553	if (z >= TELNO_MAX) z = (TELNO_MAX-1);
554	strncpy(cd->dst_telno, msg, z);
555	msg += x;
556	x = z;
557    }
558    cd->dst_telno[x] = '\0';
559
560    msg = capimsg_getu8(msg, &x); /* Calling party struct len */
561    if (x) {
562	msg = capimsg_getu8(msg, &y); /* Numbering plan */
563	msg = capimsg_getu8(msg, &y); /* Screening/Presentation */
564	if ((y & 0x80) == 0) { /* screening used */
565	    cd->scr_ind = (y & 3) + SCR_USR_NOSC;
566	    cd->prs_ind = ((y >> 5) & 3) + PRS_ALLOWED;
567	}
568	z = x - 2;
569	if (z >= TELNO_MAX) z = (TELNO_MAX-1);
570	strncpy(cd->src_telno, msg, z);
571	msg += x;
572	x = z;
573    }
574    cd->src_telno[x] = '\0';
575
576    i4b_l4_connect_ind(cd);
577}
578
579void capi_connect_resp(capi_softc_t *sc, call_desc_t *cd)
580{
581    struct isdn_l3_driver *l3drv;
582    struct mbuf *m;
583    u_int8_t *msg;
584    u_int16_t msgid;
585    u_int32_t PLCI;
586    int dlen = strlen(cd->dst_telno);
587
588    m = i4b_Dgetmbuf(8 + 21 + dlen);
589    if (!m) {
590	printf("capi%d: can't get mbuf for connect_resp\n", sc->sc_unit);
591	return;
592    }
593
594    l3drv = isdn_find_l3_by_isdnif(sc->capi_isdnif);
595
596    msgid = (u_int16_t) cd->event;
597    PLCI = (u_int32_t) cd->Q931state;
598
599    msg = capimsg_setu16(mtod(m, u_int8_t*), m->m_len);
600    msg = capimsg_setu16(msg, I4BCAPI_APPLID);
601    msg = capimsg_setu16(msg, CAPI_CONNECT_RESP);
602    msg = capimsg_setu16(msg, msgid);
603
604    msg = capimsg_setu32(msg, PLCI);
605
606    switch (cd->response) {
607    case SETUP_RESP_ACCEPT:
608	sc->sc_bchan[cd->channelid].cdid = cd->cdid;
609	sc->sc_bchan[cd->channelid].ncci = PLCI;
610	sc->sc_bchan[cd->channelid].state = B_CONNECT_ACTIVE_IND;
611	l3drv->bch_state[cd->channelid] = BCH_ST_USED;
612	msg = capimsg_setu16(msg, 0); /* Accept the call */
613	break;
614
615    case SETUP_RESP_REJECT:
616	sc->sc_bchan[cd->channelid].state = B_FREE;
617	l3drv->bch_state[cd->channelid] = BCH_ST_FREE;
618	msg = capimsg_setu16(msg, 2); /* Reject, normal call clearing */
619	break;
620
621    case SETUP_RESP_DNTCRE:
622	sc->sc_bchan[cd->channelid].state = B_FREE;
623	l3drv->bch_state[cd->channelid] = BCH_ST_FREE;
624	if (sc->sc_nbch == 30) {
625	    /* With PRI, we can't really ignore calls  -- normal clearing */
626	    msg = capimsg_setu16(msg, (0x3480|CAUSE_Q850_NCCLR));
627	} else {
628	    msg = capimsg_setu16(msg, 1); /* Ignore */
629	}
630	break;
631
632    default:
633	sc->sc_bchan[cd->channelid].state = B_FREE;
634	l3drv->bch_state[cd->channelid] = BCH_ST_FREE;
635	msg = capimsg_setu16(msg, (0x3480|CAUSE_Q850_CALLREJ));
636    }
637
638    msg = capimsg_setu8(msg, 15); /* B protocol */
639    if (cd->bprot == BPROT_NONE)
640	msg = capimsg_setu16(msg, 1); /* B1 protocol = transparent */
641    else
642	msg = capimsg_setu16(msg, 0); /* B1 protocol = HDLC */
643    msg = capimsg_setu16(msg, 1); /* B2 protocol = transparent */
644    msg = capimsg_setu16(msg, 0); /* B3 protocol = transparent */
645    msg = capimsg_setu8(msg, 0); /* B1 parameters */
646    msg = capimsg_setu8(msg, 0); /* B2 parameters */
647    msg = capimsg_setu8(msg, 0); /* B3 parameters */
648
649    msg = capimsg_setu8(msg, 1 + dlen);
650    msg = capimsg_setu8(msg, 0x80); /* Numbering plan */
651    strncpy(msg, cd->dst_telno, dlen);
652    msg = capimsg_setu8(msg + dlen, 0); /* Connected subaddress */
653    msg = capimsg_setu8(msg, 0); /* Low Layer Compatibility */
654    msg = capimsg_setu8(msg, 0); /* Additional Info */
655
656    sc->send(sc, m);
657}
658
659void capi_connect_b3_ind(capi_softc_t *sc, struct mbuf *m_in)
660{
661    struct mbuf *m = i4b_Dgetmbuf(8 + 7);
662    u_int8_t *msg = mtod(m_in, u_int8_t*);
663    u_int16_t applid, msgid;
664    u_int32_t NCCI;
665    int bch;
666
667    if (!m) {
668	printf("capi%d: can't get mbuf for connect_b3_resp\n", sc->sc_unit);
669	return;
670    }
671
672    msg = capimsg_getu16(msg + 2, &applid);
673    msg = capimsg_getu16(msg + 2, &msgid);
674    msg = capimsg_getu32(msg, &NCCI);
675
676    for (bch = 0; bch < sc->sc_nbch; bch++)
677	if ((sc->sc_bchan[bch].state == B_CONNECT_B3_IND) &&
678	    (sc->sc_bchan[bch].ncci == (NCCI & CAPI_PLCI_MASK)))
679	    break;
680
681    msg = capimsg_setu16(mtod(m, u_int8_t*), m->m_len);
682    msg = capimsg_setu16(msg, applid);
683    msg = capimsg_setu16(msg, CAPI_CONNECT_B3_RESP);
684    msg = capimsg_setu16(msg, msgid);
685
686    msg = capimsg_setu32(msg, NCCI);
687
688    if (bch == sc->sc_nbch) {
689	printf("capi%d: can't get cd for connect_b3_resp NCCI %x\n",
690	       sc->sc_unit, NCCI);
691	msg = capimsg_setu16(msg, 8); /* Reject, destination OOO */
692
693    } else {
694	sc->sc_bchan[bch].ncci = NCCI;
695	sc->sc_bchan[bch].state = B_CONNECT_B3_ACTIVE_IND;
696	msg = capimsg_setu16(msg, 0); /* Accept */
697    }
698
699    msg = capimsg_setu8(msg, 0); /* NCPI */
700
701    sc->send(sc, m);
702}
703
704/*
705//  Data transfer:
706//  --------------
707*/
708
709void capi_data_b3_req(capi_softc_t *sc, int chan, struct mbuf *m_b3)
710{
711    struct mbuf *m = i4b_Dgetmbuf(8 + 14);
712    u_int8_t *msg;
713    u_int16_t msgid;
714
715    if (!m) {
716	printf("capi%d: can't get mbuf for data_b3_req\n", sc->sc_unit);
717	return;
718    }
719
720    msgid = sc->sc_bchan[chan].msgid = sc->sc_msgid++;
721    sc->sc_bchan[chan].busy = 1;
722
723    msg = capimsg_setu16(mtod(m, u_int8_t*), m->m_len);
724    msg = capimsg_setu16(msg, I4BCAPI_APPLID);
725    msg = capimsg_setu16(msg, CAPI_DATA_B3_REQ);
726    msg = capimsg_setu16(msg, msgid);
727
728    msg = capimsg_setu32(msg, sc->sc_bchan[chan].ncci);
729    msg = capimsg_setu32(msg, (u_int32_t) m_b3->m_data); /* Pointer */
730    msg = capimsg_setu16(msg, m_b3->m_len);
731    msg = capimsg_setu16(msg, chan);
732    msg = capimsg_setu16(msg, 0); /* Flags */
733
734    m->m_next = m_b3;
735
736    sc->send(sc, m);
737}
738
739void capi_data_b3_conf(capi_softc_t *sc, struct mbuf *m_in)
740{
741    u_int8_t *msg = mtod(m_in, u_int8_t*);
742    u_int32_t NCCI;
743    u_int16_t handle;
744    u_int16_t Info;
745
746    msg = capimsg_getu32(msg + 8, &NCCI);
747    msg = capimsg_getu16(msg, &handle);
748    msg = capimsg_getu16(msg, &Info);
749
750    if (Info == 0) {
751	sc->sc_bchan[handle].busy = 0;
752	capi_start_tx(sc, handle);
753
754    } else {
755	printf("capi%d: data_b3_conf NCCI %x handle %x info=%04x\n",
756	       sc->sc_unit, NCCI, handle, Info);
757    }
758}
759
760void capi_data_b3_ind(capi_softc_t *sc, struct mbuf *m_in)
761{
762    struct mbuf *m = i4b_Dgetmbuf(8 + 6);
763    u_int8_t *msg = mtod(m_in, u_int8_t*);
764    u_int16_t applid, msgid;
765    u_int32_t NCCI;
766    u_int16_t handle;
767    int bch;
768
769    if (!m) {
770	printf("capi%d: can't get mbuf for data_b3_resp\n", sc->sc_unit);
771	return;
772    }
773
774    msg = capimsg_getu16(msg + 2, &applid);
775    msg = capimsg_getu16(msg + 2, &msgid);
776    msg = capimsg_getu32(msg, &NCCI);
777    msg = capimsg_getu16(msg + 6, &handle);
778
779    for (bch = 0; bch < sc->sc_nbch; bch++)
780	if ((sc->sc_bchan[bch].state == B_CONNECTED) &&
781	    (sc->sc_bchan[bch].ncci == NCCI))
782	    break;
783
784    if (bch == sc->sc_nbch) {
785	printf("capi%d: can't find channel for data_b3_ind NCCI %x\n",
786	       sc->sc_unit, NCCI);
787
788    } else {
789	if (sc->sc_bchan[bch].bprot == BPROT_RHDLC) {
790	    /* HDLC drivers use rx_mbuf */
791
792	    sc->sc_bchan[bch].in_mbuf = m_in->m_next;
793	    sc->sc_bchan[bch].rxcount += m_in->m_next->m_len;
794	    m_in->m_next = NULL; /* driver frees */
795
796	    (*sc->sc_bchan[bch].l4_driver->bch_rx_data_ready)(
797		sc->sc_bchan[bch].l4_driver_softc);
798
799	} else {
800	    /* Telephony drivers use rx_queue */
801
802	    if (!IF_QFULL(&sc->sc_bchan[bch].rx_queue)) {
803		IF_ENQUEUE(&sc->sc_bchan[bch].rx_queue, m_in->m_next);
804		sc->sc_bchan[bch].rxcount += m_in->m_next->m_len;
805		m_in->m_next = NULL; /* driver frees */
806	    }
807
808	    (*sc->sc_bchan[bch].l4_driver->bch_rx_data_ready)(
809		sc->sc_bchan[bch].l4_driver_softc);
810	}
811    }
812
813    msg = capimsg_setu16(mtod(m, u_int8_t*), m->m_len);
814    msg = capimsg_setu16(msg, I4BCAPI_APPLID);
815    msg = capimsg_setu16(msg, CAPI_DATA_B3_RESP);
816    msg = capimsg_setu16(msg, msgid);
817
818    msg = capimsg_setu32(msg, NCCI);
819    msg = capimsg_setu16(msg, handle);
820
821    sc->send(sc, m);
822}
823
824/*
825//  Connection teardown:
826//  --------------------
827*/
828
829void capi_disconnect_req(capi_softc_t *sc, call_desc_t *cd)
830{
831    struct isdn_l3_driver *l3drv;
832    struct mbuf *m = i4b_Dgetmbuf(8 + 5);
833    u_int8_t *msg;
834    u_int16_t msgid;
835    u_int32_t PLCI;
836
837    if (!m) {
838	printf("capi%d: can't get mbuf for disconnect_req\n", sc->sc_unit);
839	return;
840    }
841
842    l3drv = isdn_find_l3_by_isdnif(sc->capi_isdnif);
843
844    sc->sc_bchan[cd->channelid].state = B_DISCONNECT_CONF;
845    l3drv->bch_state[cd->channelid] = BCH_ST_RSVD;
846    msgid = sc->sc_bchan[cd->channelid].msgid = sc->sc_msgid++;
847    PLCI = (sc->sc_bchan[cd->channelid].ncci & CAPI_PLCI_MASK);
848
849    msg = capimsg_setu16(mtod(m, u_int8_t*), m->m_len);
850    msg = capimsg_setu16(msg, I4BCAPI_APPLID);
851    msg = capimsg_setu16(msg, CAPI_DISCONNECT_REQ);
852    msg = capimsg_setu16(msg, msgid);
853
854    msg = capimsg_setu32(msg, PLCI);
855    msg = capimsg_setu8(msg, 0); /* Additional Info */
856
857    sc->send(sc, m);
858}
859
860void capi_disconnect_conf(capi_softc_t *sc, struct mbuf *m_in)
861{
862    struct isdn_l3_driver *l3drv;
863    u_int8_t *msg = mtod(m_in, u_int8_t*);
864    call_desc_t *cd;
865    u_int32_t PLCI;
866    int bch;
867
868    msg = capimsg_getu32(msg + 8, &PLCI);
869
870    for (bch = 0; bch < sc->sc_nbch; bch++)
871	if ((sc->sc_bchan[bch].state == B_DISCONNECT_CONF) &&
872	    ((sc->sc_bchan[bch].ncci & CAPI_PLCI_MASK) == PLCI))
873	    break;
874
875    if (bch == sc->sc_nbch) {
876	printf("capi%d: can't find channel for disconnect_conf PLCI %x\n",
877	       sc->sc_unit, PLCI);
878	return;
879    }
880
881    cd = cd_by_cdid(sc->sc_bchan[bch].cdid);
882    if (!cd) {
883	printf("capi%d: can't find cd for disconnect_conf PLCI %x\n",
884	       sc->sc_unit, PLCI);
885    } else {
886	i4b_l4_disconnect_ind(cd);
887	freecd_by_cd(cd);
888    }
889
890    l3drv = isdn_find_l3_by_isdnif(sc->capi_isdnif);
891
892    sc->sc_bchan[bch].state = B_FREE;
893    l3drv->bch_state[bch] = BCH_ST_FREE;
894}
895
896void capi_disconnect_b3_ind(capi_softc_t *sc, struct mbuf *m_in)
897{
898    struct mbuf *m = i4b_Dgetmbuf(8 + 4);
899    u_int8_t *msg = mtod(m_in, u_int8_t*);
900    u_int16_t applid, msgid;
901    u_int32_t NCCI;
902
903    if (!m) {
904	printf("capi%d: can't get mbuf for disconnect_b3_resp\n", sc->sc_unit);
905	return;
906    }
907
908    msg = capimsg_getu16(msg + 2, &applid);
909    msg = capimsg_getu16(msg + 2, &msgid);
910    msg = capimsg_getu32(msg, &NCCI);
911
912    /* XXX update bchan state? XXX */
913
914    msg = capimsg_setu16(mtod(m, u_int8_t*), m->m_len);
915    msg = capimsg_setu16(msg, applid);
916    msg = capimsg_setu16(msg, CAPI_DISCONNECT_B3_RESP);
917    msg = capimsg_setu16(msg, msgid);
918
919    msg = capimsg_setu32(msg, NCCI);
920
921    sc->send(sc, m);
922}
923
924void capi_disconnect_ind(capi_softc_t *sc, struct mbuf *m_in)
925{
926    struct isdn_l3_driver *l3drv;
927    struct mbuf *m = i4b_Dgetmbuf(8 + 4);
928    u_int8_t *msg = mtod(m_in, u_int8_t*);
929    call_desc_t *cd;
930    u_int16_t applid, msgid;
931    u_int32_t PLCI;
932    u_int16_t Reason;
933    int bch;
934
935    if (!m) {
936	printf("capi%d: can't get mbuf for disconnect_resp\n", sc->sc_unit);
937	return;
938    }
939
940    msg = capimsg_getu16(msg + 2, &applid);
941    msg = capimsg_getu16(msg + 2, &msgid);
942    msg = capimsg_getu32(msg, &PLCI);
943    msg = capimsg_getu16(msg, &Reason);
944
945    for (bch = 0; bch < sc->sc_nbch; bch++)
946	if ((sc->sc_bchan[bch].state != B_FREE) &&
947	    ((sc->sc_bchan[bch].ncci & CAPI_PLCI_MASK) == PLCI))
948	    break;
949
950    if (bch < sc->sc_nbch) {
951	/* We may not have a bchan assigned if call was ignored. */
952
953	cd = cd_by_cdid(sc->sc_bchan[bch].cdid);
954	sc->sc_bchan[bch].state = B_DISCONNECT_IND;
955    } else
956	cd = NULL;
957
958    if (cd) {
959	if ((Reason & 0xff00) == 0x3400) {
960	    SET_CAUSE_TV(cd->cause_in, CAUSET_Q850, (Reason & 0x7f));
961	} else {
962	    SET_CAUSE_TV(cd->cause_in, CAUSET_I4B, CAUSE_I4B_NORMAL);
963	}
964
965	i4b_l4_disconnect_ind(cd);
966	freecd_by_cd(cd);
967
968	sc->sc_bchan[bch].state = B_FREE;
969	l3drv = isdn_find_l3_by_isdnif(sc->capi_isdnif);
970	l3drv->bch_state[bch] = BCH_ST_FREE;
971    }
972
973    msg = capimsg_setu16(mtod(m, u_int8_t*), m->m_len);
974    msg = capimsg_setu16(msg, applid);
975    msg = capimsg_setu16(msg, CAPI_DISCONNECT_RESP);
976    msg = capimsg_setu16(msg, msgid);
977
978    msg = capimsg_setu32(msg, PLCI);
979
980    sc->send(sc, m);
981}
982