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