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