Sync usage with man page.
[netbsd-mini2440.git] / sys / netisdn / i4b_capi_msgs.c
blobdaa35db17639a069afa8b84c0a390630f40a04a2
1 /* $NetBSD: i4b_capi_msgs.c,v 1.5.4.4 2005/03/04 16:53:44 skrll Exp $ */
3 /*
4 * Copyright (c) 2001-2003 Cubical Solutions Ltd. All rights reserved.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
27 * capi/capi_msgs.c The CAPI i4b message handlers.
29 * $FreeBSD: src/sys/i4b/capi/capi_msgs.c,v 1.2 2001/10/21 08:51:54 hm Exp $
32 #include <sys/cdefs.h>
33 __KERNEL_RCSID(0, "$NetBSD: i4b_capi_msgs.c,v 1.5.4.4 2005/03/04 16:53:44 skrll Exp $");
35 #include <sys/param.h>
36 #include <sys/kernel.h>
37 #include <sys/systm.h>
38 #include <sys/mbuf.h>
39 #include <sys/socket.h>
40 #include <sys/callout.h>
41 #include <net/if.h>
43 #include <netisdn/i4b_debug.h>
44 #include <netisdn/i4b_ioctl.h>
45 #include <netisdn/i4b_cause.h>
46 #include <netisdn/i4b_l3l4.h>
47 #include <netisdn/i4b_mbuf.h>
48 #include <netisdn/i4b_global.h>
49 #include <netisdn/i4b_l4.h>
50 #include <netisdn/i4b_capi.h>
51 #include <netisdn/i4b_capi_msgs.h>
54 // Administrative messages:
55 // ------------------------
58 void capi_listen_req(capi_softc_t *sc, u_int32_t CIP)
60 struct mbuf *m = i4b_Dgetmbuf(8 + 18);
61 u_int8_t *msg;
62 u_int16_t msgid;
64 if (!m) {
65 printf("capi%d: can't get mbuf for listen_req\n", sc->sc_unit);
66 return;
69 msgid = sc->sc_msgid++;
71 msg = capimsg_setu16(mtod(m, u_int8_t*), m->m_len);
72 msg = capimsg_setu16(msg, I4BCAPI_APPLID);
73 msg = capimsg_setu16(msg, CAPI_LISTEN_REQ);
74 msg = capimsg_setu16(msg, msgid);
76 msg = capimsg_setu32(msg, sc->sc_unit + 1); /* Controller */
77 msg = capimsg_setu32(msg, 0); /* Info mask */
78 msg = capimsg_setu32(msg, CIP);
79 msg = capimsg_setu32(msg, 0);
80 msg = capimsg_setu8(msg, 0);
81 msg = capimsg_setu8(msg, 0);
83 sc->send(sc, m);
86 void capi_listen_conf(capi_softc_t *sc, struct mbuf *m_in)
88 struct isdn_l3_driver *l3drv;
89 u_int8_t *msg = mtod(m_in, u_int8_t*);
90 u_int16_t Info;
92 capimsg_getu16(msg + 12, &Info);
94 if (Info == 0) {
95 /* We are now listening. */
97 sc->sc_state = C_UP;
98 l3drv = isdn_find_l3_by_isdnif(sc->capi_isdnif);
99 l3drv->dl_est = DL_UP;
101 i4b_l4_l12stat(l3drv, 1, 1);
102 i4b_l4_l12stat(l3drv, 2, 1);
104 } else {
105 /* XXX sc->sc_state = C_DOWN ? XXX */
106 printf("capi%d: can't listen, info=%04x\n", sc->sc_unit, Info);
110 void capi_info_ind(capi_softc_t *sc, struct mbuf *m_in)
112 struct mbuf *m = i4b_Dgetmbuf(8 + 4);
113 u_int8_t *msg = mtod(m_in, u_int8_t*);
114 u_int16_t applid, msgid;
115 u_int32_t PLCI;
117 if (!m) {
118 printf("capi%d: can't get mbuf for info_resp\n", sc->sc_unit);
119 return;
122 msg = capimsg_getu16(msg + 2, &applid);
123 msg = capimsg_getu16(msg + 2, &msgid);
124 msg = capimsg_getu32(msg, &PLCI);
126 /* i4b_l4_info_ind() */
128 msg = capimsg_setu16(mtod(m, u_int8_t*), m->m_len);
129 msg = capimsg_setu16(msg, applid);
130 msg = capimsg_setu16(msg, CAPI_INFO_RESP);
131 msg = capimsg_setu16(msg, msgid);
133 msg = capimsg_setu32(msg, PLCI);
135 sc->send(sc, m);
138 void capi_alert_req(capi_softc_t *sc, call_desc_t *cd)
140 struct mbuf *m = i4b_Dgetmbuf(8 + 5);
141 u_int8_t *msg;
142 u_int16_t msgid;
143 u_int32_t PLCI;
145 if (!m) {
146 printf("capi%d: can't get mbuf for alert_req\n", sc->sc_unit);
147 return;
150 msgid = sc->sc_bchan[cd->channelid].msgid = sc->sc_msgid++;
151 PLCI = (sc->sc_bchan[cd->channelid].ncci & CAPI_PLCI_MASK);
153 msg = capimsg_setu16(mtod(m, u_int8_t*), m->m_len);
154 msg = capimsg_setu16(msg, I4BCAPI_APPLID);
155 msg = capimsg_setu16(msg, CAPI_ALERT_REQ);
156 msg = capimsg_setu16(msg, msgid);
158 msg = capimsg_setu32(msg, PLCI);
159 msg = capimsg_setu8(msg, 0);
161 sc->send(sc, m);
164 void capi_alert_conf(capi_softc_t *sc, struct mbuf *m_in)
166 u_int8_t *msg = mtod(m_in, u_int8_t*);
167 u_int16_t Info;
169 msg = capimsg_getu16(msg + 12, &Info);
171 if (Info) {
172 printf("capi%d: can't alert, info=%04x\n", sc->sc_unit, Info);
177 // Outgoing call setup:
178 // --------------------
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)
192 void capi_connect_req(capi_softc_t *sc, call_desc_t *cd)
194 struct isdn_l3_driver *l3drv;
195 struct mbuf *m;
196 u_int8_t *msg;
197 u_int16_t msgid;
198 int slen = strlen(cd->src_telno);
199 int dlen = strlen(cd->dst_telno);
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;
207 l3drv = isdn_find_l3_by_isdnif(sc->capi_isdnif);
209 cd->crflag = CRF_ORIG;
211 sc->sc_bchan[cd->channelid].cdid = cd->cdid;
212 sc->sc_bchan[cd->channelid].bprot = cd->bprot;
213 sc->sc_bchan[cd->channelid].state = B_CONNECT_CONF;
214 msgid = sc->sc_bchan[cd->channelid].msgid = sc->sc_msgid++;
215 l3drv->bch_state[cd->channelid] = BCH_ST_RSVD;
217 msg = capimsg_setu16(mtod(m, u_int8_t*), m->m_len);
218 msg = capimsg_setu16(msg, I4BCAPI_APPLID);
219 msg = capimsg_setu16(msg, CAPI_CONNECT_REQ);
220 msg = capimsg_setu16(msg, msgid);
222 msg = capimsg_setu32(msg, sc->sc_unit + 1); /* Controller */
224 switch (cd->bprot) {
225 case BPROT_NONE:
226 msg = capimsg_setu16(msg, 0x0010); /* Telephony */
227 break;
229 case BPROT_RHDLC:
230 msg = capimsg_setu16(msg, 0x0002); /* Unrestricted digital */
231 break;
233 default:
234 msg = capimsg_setu16(msg, 0x0002); /* Unrestricted digital */
237 msg = capimsg_setu8(msg, 1 + dlen);
238 msg = capimsg_setu8(msg, 0x80);
239 strncpy(msg, cd->dst_telno, dlen);
241 msg = capimsg_setu8(msg + dlen, 2 + slen);
242 msg = capimsg_setu8(msg, 0x00);
243 msg = capimsg_setu8(msg, 0x80); /* Presentation and screening indicator */
244 strncpy(msg, cd->src_telno, slen);
246 msg = capimsg_setu8(msg + slen, 0); /* Called & */
247 msg = capimsg_setu8(msg, 0); /* Calling party subaddress */
249 msg = capimsg_setu8(msg, 15); /* B protocol */
250 if (cd->bprot == BPROT_NONE)
251 msg = capimsg_setu16(msg, 1); /* B1 protocol = transparent */
252 else
253 msg = capimsg_setu16(msg, 0); /* B1 protocol = HDLC */
254 msg = capimsg_setu16(msg, 1); /* B2 protocol = transparent */
255 msg = capimsg_setu16(msg, 0); /* B3 protocol = transparent */
256 msg = capimsg_setu8(msg, 0); /* B1 parameters */
257 msg = capimsg_setu8(msg, 0); /* B2 parameters */
258 msg = capimsg_setu8(msg, 0); /* B3 parameters */
260 msg = capimsg_setu8(msg, 0); /* Bearer Capability */
261 msg = capimsg_setu8(msg, 0); /* Low Layer Compatibility */
262 msg = capimsg_setu8(msg, 0); /* High Layer Compatibility */
263 msg = capimsg_setu8(msg, 0); /* Additional Info */
265 sc->send(sc, m);
268 void capi_connect_conf(capi_softc_t *sc, struct mbuf *m_in)
270 u_int8_t *msg = mtod(m_in, u_int8_t*);
271 call_desc_t *cd;
272 u_int16_t msgid;
273 u_int32_t PLCI;
274 u_int16_t Info;
275 int bch;
277 msg = capimsg_getu16(msg + 6, &msgid);
278 msg = capimsg_getu32(msg, &PLCI);
279 msg = capimsg_getu16(msg, &Info);
281 for (bch = 0; bch < sc->sc_nbch; bch++)
282 if ((sc->sc_bchan[bch].state == B_CONNECT_CONF) &&
283 (sc->sc_bchan[bch].msgid == msgid))
284 break;
286 if ((bch == sc->sc_nbch) ||
287 (cd = cd_by_cdid(sc->sc_bchan[bch].cdid)) == NULL) {
288 printf("capi%d: can't find channel for connect_conf PLCI %x\n",
289 sc->sc_unit, PLCI);
290 return;
293 if (Info == 0) {
294 sc->sc_bchan[bch].state = B_CONNECT_ACTIVE_IND;
295 sc->sc_bchan[bch].ncci = PLCI;
297 i4b_l4_proceeding_ind(cd);
299 } else {
300 struct isdn_l3_driver *l3drv;
302 l3drv = isdn_find_l3_by_isdnif(sc->capi_isdnif);
303 SET_CAUSE_TV(cd->cause_out, CAUSET_I4B, CAUSE_I4B_L1ERROR);
304 i4b_l4_disconnect_ind(cd);
305 freecd_by_cd(cd);
307 sc->sc_bchan[bch].state = B_FREE;
309 l3drv->bch_state[bch] = BCH_ST_FREE;
311 printf("capi%d: can't connect out, info=%04x\n", sc->sc_unit, Info);
315 void capi_connect_active_ind(capi_softc_t *sc, struct mbuf *m_in)
317 struct mbuf *m = i4b_Dgetmbuf(8 + 4);
318 u_int8_t *msg = mtod(m_in, u_int8_t*);
319 call_desc_t *cd;
320 u_int16_t applid, msgid;
321 u_int32_t PLCI;
322 int bch;
324 if (!m) {
325 printf("capi%d: can't get mbuf for active_ind\n", sc->sc_unit);
326 return;
329 msg = capimsg_getu16(msg + 2, &applid);
330 msg = capimsg_getu16(msg + 2, &msgid);
331 msg = capimsg_getu32(msg, &PLCI);
333 for (bch = 0; bch < sc->sc_nbch; bch++)
334 if ((sc->sc_bchan[bch].state == B_CONNECT_ACTIVE_IND) &&
335 (sc->sc_bchan[bch].ncci == PLCI))
336 break;
338 if ((bch == sc->sc_nbch) ||
339 (cd = cd_by_cdid(sc->sc_bchan[bch].cdid)) == NULL) {
340 printf("capi%d: can't find channel for active_resp, PLCI %x\n",
341 sc->sc_unit, PLCI);
342 return;
345 msg = capimsg_setu16(mtod(m, u_int8_t*), m->m_len);
346 msg = capimsg_setu16(msg, applid);
347 msg = capimsg_setu16(msg, CAPI_CONNECT_ACTIVE_RESP);
348 msg = capimsg_setu16(msg, msgid);
350 msg = capimsg_setu32(msg, PLCI);
352 sc->send(sc, m);
354 if (cd->crflag == CRF_ORIG) {
355 capi_connect_b3_req(sc, cd);
357 } else {
358 sc->sc_bchan[bch].state = B_CONNECT_B3_IND;
362 void capi_connect_b3_req(capi_softc_t *sc, call_desc_t *cd)
364 struct mbuf *m = i4b_Dgetmbuf(8 + 5);
365 u_int8_t *msg;
366 u_int16_t msgid;
367 u_int32_t PLCI;
369 if (!m) {
370 printf("capi%d: can't get mbuf for connect_b3_req\n", sc->sc_unit);
371 return;
374 sc->sc_bchan[cd->channelid].state = B_CONNECT_B3_CONF;
375 msgid = sc->sc_bchan[cd->channelid].msgid = sc->sc_msgid++;
376 PLCI = (sc->sc_bchan[cd->channelid].ncci & CAPI_PLCI_MASK);
378 msg = capimsg_setu16(mtod(m, u_int8_t*), m->m_len);
379 msg = capimsg_setu16(msg, I4BCAPI_APPLID);
380 msg = capimsg_setu16(msg, CAPI_CONNECT_B3_REQ);
381 msg = capimsg_setu16(msg, msgid);
383 msg = capimsg_setu32(msg, PLCI);
384 msg = capimsg_setu8(msg, 0); /* NCPI */
386 sc->send(sc, m);
389 void capi_connect_b3_conf(capi_softc_t *sc, struct mbuf *m_in)
391 u_int8_t *msg = mtod(m_in, u_int8_t*);
392 call_desc_t *cd;
393 u_int16_t msgid;
394 u_int32_t NCCI;
395 u_int16_t Info;
396 int bch;
398 msg = capimsg_getu16(msg + 6, &msgid);
399 msg = capimsg_getu32(msg, &NCCI);
400 msg = capimsg_getu16(msg, &Info);
402 for (bch = 0; bch < sc->sc_nbch; bch++)
403 if ((sc->sc_bchan[bch].state == B_CONNECT_B3_CONF) &&
404 (sc->sc_bchan[bch].ncci == (NCCI & CAPI_PLCI_MASK)))
405 break;
407 if ((bch == sc->sc_nbch) ||
408 (cd = cd_by_cdid(sc->sc_bchan[bch].cdid)) == NULL) {
409 printf("capi%d: can't find channel for connect_b3_conf NCCI %x\n",
410 sc->sc_unit, NCCI);
411 return;
414 if (Info == 0) {
415 sc->sc_bchan[bch].ncci = NCCI;
416 sc->sc_bchan[bch].state = B_CONNECT_B3_ACTIVE_IND;
418 } else {
419 struct isdn_l3_driver *l3drv;
421 l3drv = isdn_find_l3_by_isdnif(sc->capi_isdnif);
423 SET_CAUSE_TV(cd->cause_in, CAUSET_I4B, CAUSE_I4B_OOO); /* XXX */
424 i4b_l4_disconnect_ind(cd);
425 freecd_by_cd(cd);
427 l3drv->bch_state[bch] = BCH_ST_RSVD;
429 printf("capi%d: can't connect_b3 out, info=%04x\n", sc->sc_unit, Info);
431 capi_disconnect_req(sc, cd);
435 void capi_connect_b3_active_ind(capi_softc_t *sc, struct mbuf *m_in)
437 struct mbuf *m = i4b_Dgetmbuf(8 + 4);
438 u_int8_t *msg = mtod(m_in, u_int8_t*);
439 call_desc_t *cd;
440 u_int16_t applid, msgid;
441 u_int32_t NCCI;
442 int bch;
444 if (!m) {
445 printf("capi%d: can't get mbuf for b3_active_ind\n", sc->sc_unit);
446 return;
449 msg = capimsg_getu16(msg + 2, &applid);
450 msg = capimsg_getu16(msg + 2, &msgid);
451 msg = capimsg_getu32(msg, &NCCI);
453 for (bch = 0; bch < sc->sc_nbch; bch++)
454 if ((sc->sc_bchan[bch].state == B_CONNECT_B3_ACTIVE_IND) &&
455 (sc->sc_bchan[bch].ncci == NCCI))
456 break;
458 if ((bch == sc->sc_nbch) ||
459 (cd = cd_by_cdid(sc->sc_bchan[bch].cdid)) == NULL) {
460 printf("capi%d: can't find channel for b3_active_resp NCCI %x\n",
461 sc->sc_unit, NCCI);
462 return;
465 msg = capimsg_setu16(mtod(m, u_int8_t*), m->m_len);
466 msg = capimsg_setu16(msg, I4BCAPI_APPLID);
467 msg = capimsg_setu16(msg, CAPI_CONNECT_B3_ACTIVE_RESP);
468 msg = capimsg_setu16(msg, msgid);
470 msg = capimsg_setu32(msg, NCCI);
472 sc->send(sc, m);
474 sc->sc_bchan[bch].state = B_CONNECTED;
476 i4b_l4_connect_active_ind(cd);
480 // Incoming call setup:
481 // --------------------
483 // <-- CAPI_CONNECT_IND
484 // (consult Layer 4)
485 // CAPI_CONNECT_RESP -->
486 // <-- CAPI_CONNECT_ACTIVE_IND
487 // CAPI_CONNECT_ACTIVE_RESP -->
488 // <-- CAPI_CONNECT_B3_IND
489 // CAPI_CONNECT_B3_RESP -->
490 // <-- CAPI_CONNECT_B3_ACTIVE_IND
491 // CAPI_CONNECT_B3_ACTIVE_RESP -->
492 // (notify Layer 4)
495 void capi_connect_ind(capi_softc_t *sc, struct mbuf *m_in)
497 u_int8_t *msg = mtod(m_in, u_int8_t*);
498 call_desc_t *cd;
499 u_int16_t applid, msgid;
500 u_int32_t PLCI;
501 u_int16_t CIP;
502 u_int8_t x, y, z;
503 int bch;
505 if ((cd = reserve_cd()) == NULL) {
506 printf("capi%d: can't get cd for connect_ind\n", sc->sc_unit);
507 return;
510 cd->isdnif = sc->capi_isdnif;
511 cd->channelexcl = 0;
512 cd->l3drv = isdn_find_l3_by_isdnif(sc->capi_isdnif);
514 for (bch = 0; bch < sc->sc_nbch; bch++)
515 if (sc->sc_bchan[bch].state == B_FREE)
516 break;
518 sc->sc_bchan[bch].state = B_CONNECT_IND;
519 cd->channelid = bch; /* XXX CHAN_ANY XXX */
521 cd->crflag = CRF_DEST;
522 cd->cr = get_rand_cr(sc->sc_unit);
523 cd->scr_ind = SCR_NONE;
524 cd->prs_ind = PRS_NONE;
525 cd->bprot = BPROT_NONE;
526 cd->ilt = NULL;
527 cd->display[0] = '\0';
528 cd->datetime[0] = '\0';
530 msg = capimsg_getu16(msg + 2, &applid);
531 msg = capimsg_getu16(msg + 2, &msgid);
532 msg = capimsg_getu32(msg, &PLCI);
533 msg = capimsg_getu16(msg, &CIP);
535 cd->event = (int) msgid; /* XXX overload */
536 cd->Q931state = (int) PLCI; /* XXX overload */
538 switch (CIP) {
539 case 0x0010:
540 case 0x0001: cd->bprot = BPROT_NONE; break;
541 case 0x0002: cd->bprot = BPROT_RHDLC; break;
542 default:
543 #if 0
544 NDBGL4(L4_CAPIDBG, "capi%d: unknown CIP = %d", sc->sc_unit, CIP);
545 #endif
546 cd->bprot = BPROT_NONE;
549 msg = capimsg_getu8(msg, &x); /* Called party struct len */
550 if (x) {
551 msg = capimsg_getu8(msg, &y); /* Numbering plan */
552 z = x - 1;
553 if (z >= TELNO_MAX) z = (TELNO_MAX-1);
554 strncpy(cd->dst_telno, msg, z);
555 msg += x;
556 x = z;
558 cd->dst_telno[x] = '\0';
560 msg = capimsg_getu8(msg, &x); /* Calling party struct len */
561 if (x) {
562 msg = capimsg_getu8(msg, &y); /* Numbering plan */
563 msg = capimsg_getu8(msg, &y); /* Screening/Presentation */
564 if ((y & 0x80) == 0) { /* screening used */
565 cd->scr_ind = (y & 3) + SCR_USR_NOSC;
566 cd->prs_ind = ((y >> 5) & 3) + PRS_ALLOWED;
568 z = x - 2;
569 if (z >= TELNO_MAX) z = (TELNO_MAX-1);
570 strncpy(cd->src_telno, msg, z);
571 msg += x;
572 x = z;
574 cd->src_telno[x] = '\0';
576 i4b_l4_connect_ind(cd);
579 void capi_connect_resp(capi_softc_t *sc, call_desc_t *cd)
581 struct isdn_l3_driver *l3drv;
582 struct mbuf *m;
583 u_int8_t *msg;
584 u_int16_t msgid;
585 u_int32_t PLCI;
586 int dlen = strlen(cd->dst_telno);
588 m = i4b_Dgetmbuf(8 + 21 + dlen);
589 if (!m) {
590 printf("capi%d: can't get mbuf for connect_resp\n", sc->sc_unit);
591 return;
594 l3drv = isdn_find_l3_by_isdnif(sc->capi_isdnif);
596 msgid = (u_int16_t) cd->event;
597 PLCI = (u_int32_t) cd->Q931state;
599 msg = capimsg_setu16(mtod(m, u_int8_t*), m->m_len);
600 msg = capimsg_setu16(msg, I4BCAPI_APPLID);
601 msg = capimsg_setu16(msg, CAPI_CONNECT_RESP);
602 msg = capimsg_setu16(msg, msgid);
604 msg = capimsg_setu32(msg, PLCI);
606 switch (cd->response) {
607 case SETUP_RESP_ACCEPT:
608 sc->sc_bchan[cd->channelid].cdid = cd->cdid;
609 sc->sc_bchan[cd->channelid].ncci = PLCI;
610 sc->sc_bchan[cd->channelid].state = B_CONNECT_ACTIVE_IND;
611 l3drv->bch_state[cd->channelid] = BCH_ST_USED;
612 msg = capimsg_setu16(msg, 0); /* Accept the call */
613 break;
615 case SETUP_RESP_REJECT:
616 sc->sc_bchan[cd->channelid].state = B_FREE;
617 l3drv->bch_state[cd->channelid] = BCH_ST_FREE;
618 msg = capimsg_setu16(msg, 2); /* Reject, normal call clearing */
619 break;
621 case SETUP_RESP_DNTCRE:
622 sc->sc_bchan[cd->channelid].state = B_FREE;
623 l3drv->bch_state[cd->channelid] = BCH_ST_FREE;
624 if (sc->sc_nbch == 30) {
625 /* With PRI, we can't really ignore calls -- normal clearing */
626 msg = capimsg_setu16(msg, (0x3480|CAUSE_Q850_NCCLR));
627 } else {
628 msg = capimsg_setu16(msg, 1); /* Ignore */
630 break;
632 default:
633 sc->sc_bchan[cd->channelid].state = B_FREE;
634 l3drv->bch_state[cd->channelid] = BCH_ST_FREE;
635 msg = capimsg_setu16(msg, (0x3480|CAUSE_Q850_CALLREJ));
638 msg = capimsg_setu8(msg, 15); /* B protocol */
639 if (cd->bprot == BPROT_NONE)
640 msg = capimsg_setu16(msg, 1); /* B1 protocol = transparent */
641 else
642 msg = capimsg_setu16(msg, 0); /* B1 protocol = HDLC */
643 msg = capimsg_setu16(msg, 1); /* B2 protocol = transparent */
644 msg = capimsg_setu16(msg, 0); /* B3 protocol = transparent */
645 msg = capimsg_setu8(msg, 0); /* B1 parameters */
646 msg = capimsg_setu8(msg, 0); /* B2 parameters */
647 msg = capimsg_setu8(msg, 0); /* B3 parameters */
649 msg = capimsg_setu8(msg, 1 + dlen);
650 msg = capimsg_setu8(msg, 0x80); /* Numbering plan */
651 strncpy(msg, cd->dst_telno, dlen);
652 msg = capimsg_setu8(msg + dlen, 0); /* Connected subaddress */
653 msg = capimsg_setu8(msg, 0); /* Low Layer Compatibility */
654 msg = capimsg_setu8(msg, 0); /* Additional Info */
656 sc->send(sc, m);
659 void capi_connect_b3_ind(capi_softc_t *sc, struct mbuf *m_in)
661 struct mbuf *m = i4b_Dgetmbuf(8 + 7);
662 u_int8_t *msg = mtod(m_in, u_int8_t*);
663 u_int16_t applid, msgid;
664 u_int32_t NCCI;
665 int bch;
667 if (!m) {
668 printf("capi%d: can't get mbuf for connect_b3_resp\n", sc->sc_unit);
669 return;
672 msg = capimsg_getu16(msg + 2, &applid);
673 msg = capimsg_getu16(msg + 2, &msgid);
674 msg = capimsg_getu32(msg, &NCCI);
676 for (bch = 0; bch < sc->sc_nbch; bch++)
677 if ((sc->sc_bchan[bch].state == B_CONNECT_B3_IND) &&
678 (sc->sc_bchan[bch].ncci == (NCCI & CAPI_PLCI_MASK)))
679 break;
681 msg = capimsg_setu16(mtod(m, u_int8_t*), m->m_len);
682 msg = capimsg_setu16(msg, applid);
683 msg = capimsg_setu16(msg, CAPI_CONNECT_B3_RESP);
684 msg = capimsg_setu16(msg, msgid);
686 msg = capimsg_setu32(msg, NCCI);
688 if (bch == sc->sc_nbch) {
689 printf("capi%d: can't get cd for connect_b3_resp NCCI %x\n",
690 sc->sc_unit, NCCI);
691 msg = capimsg_setu16(msg, 8); /* Reject, destination OOO */
693 } else {
694 sc->sc_bchan[bch].ncci = NCCI;
695 sc->sc_bchan[bch].state = B_CONNECT_B3_ACTIVE_IND;
696 msg = capimsg_setu16(msg, 0); /* Accept */
699 msg = capimsg_setu8(msg, 0); /* NCPI */
701 sc->send(sc, m);
705 // Data transfer:
706 // --------------
709 void capi_data_b3_req(capi_softc_t *sc, int chan, struct mbuf *m_b3)
711 struct mbuf *m = i4b_Dgetmbuf(8 + 14);
712 u_int8_t *msg;
713 u_int16_t msgid;
715 if (!m) {
716 printf("capi%d: can't get mbuf for data_b3_req\n", sc->sc_unit);
717 return;
720 msgid = sc->sc_bchan[chan].msgid = sc->sc_msgid++;
721 sc->sc_bchan[chan].busy = 1;
723 msg = capimsg_setu16(mtod(m, u_int8_t*), m->m_len);
724 msg = capimsg_setu16(msg, I4BCAPI_APPLID);
725 msg = capimsg_setu16(msg, CAPI_DATA_B3_REQ);
726 msg = capimsg_setu16(msg, msgid);
728 msg = capimsg_setu32(msg, sc->sc_bchan[chan].ncci);
729 msg = capimsg_setu32(msg, (u_int32_t) m_b3->m_data); /* Pointer */
730 msg = capimsg_setu16(msg, m_b3->m_len);
731 msg = capimsg_setu16(msg, chan);
732 msg = capimsg_setu16(msg, 0); /* Flags */
734 m->m_next = m_b3;
736 sc->send(sc, m);
739 void capi_data_b3_conf(capi_softc_t *sc, struct mbuf *m_in)
741 u_int8_t *msg = mtod(m_in, u_int8_t*);
742 u_int32_t NCCI;
743 u_int16_t handle;
744 u_int16_t Info;
746 msg = capimsg_getu32(msg + 8, &NCCI);
747 msg = capimsg_getu16(msg, &handle);
748 msg = capimsg_getu16(msg, &Info);
750 if (Info == 0) {
751 sc->sc_bchan[handle].busy = 0;
752 capi_start_tx(sc, handle);
754 } else {
755 printf("capi%d: data_b3_conf NCCI %x handle %x info=%04x\n",
756 sc->sc_unit, NCCI, handle, Info);
760 void capi_data_b3_ind(capi_softc_t *sc, struct mbuf *m_in)
762 struct mbuf *m = i4b_Dgetmbuf(8 + 6);
763 u_int8_t *msg = mtod(m_in, u_int8_t*);
764 u_int16_t applid, msgid;
765 u_int32_t NCCI;
766 u_int16_t handle;
767 int bch;
769 if (!m) {
770 printf("capi%d: can't get mbuf for data_b3_resp\n", sc->sc_unit);
771 return;
774 msg = capimsg_getu16(msg + 2, &applid);
775 msg = capimsg_getu16(msg + 2, &msgid);
776 msg = capimsg_getu32(msg, &NCCI);
777 msg = capimsg_getu16(msg + 6, &handle);
779 for (bch = 0; bch < sc->sc_nbch; bch++)
780 if ((sc->sc_bchan[bch].state == B_CONNECTED) &&
781 (sc->sc_bchan[bch].ncci == NCCI))
782 break;
784 if (bch == sc->sc_nbch) {
785 printf("capi%d: can't find channel for data_b3_ind NCCI %x\n",
786 sc->sc_unit, NCCI);
788 } else {
789 if (sc->sc_bchan[bch].bprot == BPROT_RHDLC) {
790 /* HDLC drivers use rx_mbuf */
792 sc->sc_bchan[bch].in_mbuf = m_in->m_next;
793 sc->sc_bchan[bch].rxcount += m_in->m_next->m_len;
794 m_in->m_next = NULL; /* driver frees */
796 (*sc->sc_bchan[bch].l4_driver->bch_rx_data_ready)(
797 sc->sc_bchan[bch].l4_driver_softc);
799 } else {
800 /* Telephony drivers use rx_queue */
802 if (!IF_QFULL(&sc->sc_bchan[bch].rx_queue)) {
803 IF_ENQUEUE(&sc->sc_bchan[bch].rx_queue, m_in->m_next);
804 sc->sc_bchan[bch].rxcount += m_in->m_next->m_len;
805 m_in->m_next = NULL; /* driver frees */
808 (*sc->sc_bchan[bch].l4_driver->bch_rx_data_ready)(
809 sc->sc_bchan[bch].l4_driver_softc);
813 msg = capimsg_setu16(mtod(m, u_int8_t*), m->m_len);
814 msg = capimsg_setu16(msg, I4BCAPI_APPLID);
815 msg = capimsg_setu16(msg, CAPI_DATA_B3_RESP);
816 msg = capimsg_setu16(msg, msgid);
818 msg = capimsg_setu32(msg, NCCI);
819 msg = capimsg_setu16(msg, handle);
821 sc->send(sc, m);
825 // Connection teardown:
826 // --------------------
829 void capi_disconnect_req(capi_softc_t *sc, call_desc_t *cd)
831 struct isdn_l3_driver *l3drv;
832 struct mbuf *m = i4b_Dgetmbuf(8 + 5);
833 u_int8_t *msg;
834 u_int16_t msgid;
835 u_int32_t PLCI;
837 if (!m) {
838 printf("capi%d: can't get mbuf for disconnect_req\n", sc->sc_unit);
839 return;
842 l3drv = isdn_find_l3_by_isdnif(sc->capi_isdnif);
844 sc->sc_bchan[cd->channelid].state = B_DISCONNECT_CONF;
845 l3drv->bch_state[cd->channelid] = BCH_ST_RSVD;
846 msgid = sc->sc_bchan[cd->channelid].msgid = sc->sc_msgid++;
847 PLCI = (sc->sc_bchan[cd->channelid].ncci & CAPI_PLCI_MASK);
849 msg = capimsg_setu16(mtod(m, u_int8_t*), m->m_len);
850 msg = capimsg_setu16(msg, I4BCAPI_APPLID);
851 msg = capimsg_setu16(msg, CAPI_DISCONNECT_REQ);
852 msg = capimsg_setu16(msg, msgid);
854 msg = capimsg_setu32(msg, PLCI);
855 msg = capimsg_setu8(msg, 0); /* Additional Info */
857 sc->send(sc, m);
860 void capi_disconnect_conf(capi_softc_t *sc, struct mbuf *m_in)
862 struct isdn_l3_driver *l3drv;
863 u_int8_t *msg = mtod(m_in, u_int8_t*);
864 call_desc_t *cd;
865 u_int32_t PLCI;
866 int bch;
868 msg = capimsg_getu32(msg + 8, &PLCI);
870 for (bch = 0; bch < sc->sc_nbch; bch++)
871 if ((sc->sc_bchan[bch].state == B_DISCONNECT_CONF) &&
872 ((sc->sc_bchan[bch].ncci & CAPI_PLCI_MASK) == PLCI))
873 break;
875 if (bch == sc->sc_nbch) {
876 printf("capi%d: can't find channel for disconnect_conf PLCI %x\n",
877 sc->sc_unit, PLCI);
878 return;
881 cd = cd_by_cdid(sc->sc_bchan[bch].cdid);
882 if (!cd) {
883 printf("capi%d: can't find cd for disconnect_conf PLCI %x\n",
884 sc->sc_unit, PLCI);
885 } else {
886 i4b_l4_disconnect_ind(cd);
887 freecd_by_cd(cd);
890 l3drv = isdn_find_l3_by_isdnif(sc->capi_isdnif);
892 sc->sc_bchan[bch].state = B_FREE;
893 l3drv->bch_state[bch] = BCH_ST_FREE;
896 void capi_disconnect_b3_ind(capi_softc_t *sc, struct mbuf *m_in)
898 struct mbuf *m = i4b_Dgetmbuf(8 + 4);
899 u_int8_t *msg = mtod(m_in, u_int8_t*);
900 u_int16_t applid, msgid;
901 u_int32_t NCCI;
903 if (!m) {
904 printf("capi%d: can't get mbuf for disconnect_b3_resp\n", sc->sc_unit);
905 return;
908 msg = capimsg_getu16(msg + 2, &applid);
909 msg = capimsg_getu16(msg + 2, &msgid);
910 msg = capimsg_getu32(msg, &NCCI);
912 /* XXX update bchan state? XXX */
914 msg = capimsg_setu16(mtod(m, u_int8_t*), m->m_len);
915 msg = capimsg_setu16(msg, applid);
916 msg = capimsg_setu16(msg, CAPI_DISCONNECT_B3_RESP);
917 msg = capimsg_setu16(msg, msgid);
919 msg = capimsg_setu32(msg, NCCI);
921 sc->send(sc, m);
924 void capi_disconnect_ind(capi_softc_t *sc, struct mbuf *m_in)
926 struct isdn_l3_driver *l3drv;
927 struct mbuf *m = i4b_Dgetmbuf(8 + 4);
928 u_int8_t *msg = mtod(m_in, u_int8_t*);
929 call_desc_t *cd;
930 u_int16_t applid, msgid;
931 u_int32_t PLCI;
932 u_int16_t Reason;
933 int bch;
935 if (!m) {
936 printf("capi%d: can't get mbuf for disconnect_resp\n", sc->sc_unit);
937 return;
940 msg = capimsg_getu16(msg + 2, &applid);
941 msg = capimsg_getu16(msg + 2, &msgid);
942 msg = capimsg_getu32(msg, &PLCI);
943 msg = capimsg_getu16(msg, &Reason);
945 for (bch = 0; bch < sc->sc_nbch; bch++)
946 if ((sc->sc_bchan[bch].state != B_FREE) &&
947 ((sc->sc_bchan[bch].ncci & CAPI_PLCI_MASK) == PLCI))
948 break;
950 if (bch < sc->sc_nbch) {
951 /* We may not have a bchan assigned if call was ignored. */
953 cd = cd_by_cdid(sc->sc_bchan[bch].cdid);
954 sc->sc_bchan[bch].state = B_DISCONNECT_IND;
955 } else
956 cd = NULL;
958 if (cd) {
959 if ((Reason & 0xff00) == 0x3400) {
960 SET_CAUSE_TV(cd->cause_in, CAUSET_Q850, (Reason & 0x7f));
961 } else {
962 SET_CAUSE_TV(cd->cause_in, CAUSET_I4B, CAUSE_I4B_NORMAL);
965 i4b_l4_disconnect_ind(cd);
966 freecd_by_cd(cd);
968 sc->sc_bchan[bch].state = B_FREE;
969 l3drv = isdn_find_l3_by_isdnif(sc->capi_isdnif);
970 l3drv->bch_state[bch] = BCH_ST_FREE;
973 msg = capimsg_setu16(mtod(m, u_int8_t*), m->m_len);
974 msg = capimsg_setu16(msg, applid);
975 msg = capimsg_setu16(msg, CAPI_DISCONNECT_RESP);
976 msg = capimsg_setu16(msg, msgid);
978 msg = capimsg_setu32(msg, PLCI);
980 sc->send(sc, m);