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