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.5 2004/04/16 15:40:20 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: }