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