1 /* $NetBSD: i4b_capi_msgs.c,v 1.5 2003/10/28 17:02:54 pooka Exp $ */
2
3 /*
4 * Copyright (c) 2001-2003 Cubical Solutions Ltd. All rights reserved.
5 *
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.
14 *
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.
26 *
27 * capi/capi_msgs.c The CAPI i4b message handlers.
28 *
29 * $FreeBSD: src/sys/i4b/capi/capi_msgs.c,v 1.2 2001/10/21 08:51:54 hm Exp $
30 */
31
32 #include <sys/cdefs.h>
33 __KERNEL_RCSID(0, "$NetBSD: i4b_capi_msgs.c,v 1.5 2003/10/28 17:02:54 pooka Exp $");
34
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>
42
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>
52
53 /*
54 // Administrative messages:
55 // ------------------------
56 */
57
58 void capi_listen_req(capi_softc_t *sc, u_int32_t CIP)
59 {
60 struct mbuf *m = i4b_Dgetmbuf(8 + 18);
61 u_int8_t *msg;
62 u_int16_t msgid;
63
64 if (!m) {
65 printf("capi%d: can't get mbuf for listen_req\n", sc->sc_unit);
66 return;
67 }
68
69 msgid = sc->sc_msgid++;
70
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);
75
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);
82
83 sc->send(sc, m);
84 }
85
86 void capi_listen_conf(capi_softc_t *sc, struct mbuf *m_in)
87 {
88 struct isdn_l3_driver *l3drv;
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 l3drv = isdn_find_l3_by_isdnif(sc->capi_isdnif);
99 l3drv->dl_est = DL_UP;
100
101 i4b_l4_l12stat(l3drv, 1, 1);
102 i4b_l4_l12stat(l3drv, 2, 1);
103
104 } else {
105 /* XXX sc->sc_state = C_DOWN ? XXX */
106 printf("capi%d: can't listen, info=%04x\n", sc->sc_unit, Info);
107 }
108 }
109
110 void capi_info_ind(capi_softc_t *sc, struct mbuf *m_in)
111 {
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;
116
117 if (!m) {
118 printf("capi%d: can't get mbuf for info_resp\n", sc->sc_unit);
119 return;
120 }
121
122 msg = capimsg_getu16(msg + 2, &applid);
123 msg = capimsg_getu16(msg + 2, &msgid);
124 msg = capimsg_getu32(msg, &PLCI);
125
126 /* i4b_l4_info_ind() */
127
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);
132
133 msg = capimsg_setu32(msg, PLCI);
134
135 sc->send(sc, m);
136 }
137
138 void capi_alert_req(capi_softc_t *sc, call_desc_t *cd)
139 {
140 struct mbuf *m = i4b_Dgetmbuf(8 + 5);
141 u_int8_t *msg;
142 u_int16_t msgid;
143 u_int32_t PLCI;
144
145 if (!m) {
146 printf("capi%d: can't get mbuf for alert_req\n", sc->sc_unit);
147 return;
148 }
149
150 msgid = sc->sc_bchan[cd->channelid].msgid = sc->sc_msgid++;
151 PLCI = (sc->sc_bchan[cd->channelid].ncci & CAPI_PLCI_MASK);
152
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);
157
158 msg = capimsg_setu32(msg, PLCI);
159 msg = capimsg_setu8(msg, 0);
160
161 sc->send(sc, m);
162 }
163
164 void 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 capi_connect_req(capi_softc_t *sc, call_desc_t *cd)
193 {
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);
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 l3drv = isdn_find_l3_by_isdnif(sc->capi_isdnif);
208
209 cd->crflag = CRF_ORIG;
210
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;
216
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);
221
222 msg = capimsg_setu32(msg, sc->sc_unit + 1); /* Controller */
223
224 switch (cd->bprot) {
225 case BPROT_NONE:
226 msg = capimsg_setu16(msg, 0x0010); /* Telephony */
227 break;
228
229 case BPROT_RHDLC:
230 msg = capimsg_setu16(msg, 0x0002); /* Unrestricted digital */
231 break;
232
233 default:
234 msg = capimsg_setu16(msg, 0x0002); /* Unrestricted digital */
235 }
236
237 msg = capimsg_setu8(msg, 1 + dlen);
238 msg = capimsg_setu8(msg, 0x80);
239 strncpy(msg, cd->dst_telno, dlen);
240
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);
245
246 msg = capimsg_setu8(msg + slen, 0); /* Called & */
247 msg = capimsg_setu8(msg, 0); /* Calling party subaddress */
248
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 */
259
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 */
264
265 sc->send(sc, m);
266 }
267
268 void capi_connect_conf(capi_softc_t *sc, struct mbuf *m_in)
269 {
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;
276
277 msg = capimsg_getu16(msg + 6, &msgid);
278 msg = capimsg_getu32(msg, &PLCI);
279 msg = capimsg_getu16(msg, &Info);
280
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;
285
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;
291 }
292
293 if (Info == 0) {
294 sc->sc_bchan[bch].state = B_CONNECT_ACTIVE_IND;
295 sc->sc_bchan[bch].ncci = PLCI;
296
297 i4b_l4_proceeding_ind(cd);
298
299 } else {
300 struct isdn_l3_driver *l3drv;
301
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);
306
307 sc->sc_bchan[bch].state = B_FREE;
308
309 l3drv->bch_state[bch] = BCH_ST_FREE;
310
311 printf("capi%d: can't connect out, info=%04x\n", sc->sc_unit, Info);
312 }
313 }
314
315 void capi_connect_active_ind(capi_softc_t *sc, struct mbuf *m_in)
316 {
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;
323
324 if (!m) {
325 printf("capi%d: can't get mbuf for active_ind\n", sc->sc_unit);
326 return;
327 }
328
329 msg = capimsg_getu16(msg + 2, &applid);
330 msg = capimsg_getu16(msg + 2, &msgid);
331 msg = capimsg_getu32(msg, &PLCI);
332
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;
337
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;
343 }
344
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);
349
350 msg = capimsg_setu32(msg, PLCI);
351
352 sc->send(sc, m);
353
354 if (cd->crflag == CRF_ORIG) {
355 capi_connect_b3_req(sc, cd);
356
357 } else {
358 sc->sc_bchan[bch].state = B_CONNECT_B3_IND;
359 }
360 }
361
362 void capi_connect_b3_req(capi_softc_t *sc, call_desc_t *cd)
363 {
364 struct mbuf *m = i4b_Dgetmbuf(8 + 5);
365 u_int8_t *msg;
366 u_int16_t msgid;
367 u_int32_t PLCI;
368
369 if (!m) {
370 printf("capi%d: can't get mbuf for connect_b3_req\n", sc->sc_unit);
371 return;
372 }
373
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);
377
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);
382
383 msg = capimsg_setu32(msg, PLCI);
384 msg = capimsg_setu8(msg, 0); /* NCPI */
385
386 sc->send(sc, m);
387 }
388
389 void capi_connect_b3_conf(capi_softc_t *sc, struct mbuf *m_in)
390 {
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;
397
398 msg = capimsg_getu16(msg + 6, &msgid);
399 msg = capimsg_getu32(msg, &NCCI);
400 msg = capimsg_getu16(msg, &Info);
401
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;
406
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;
412 }
413
414 if (Info == 0) {
415 sc->sc_bchan[bch].ncci = NCCI;
416 sc->sc_bchan[bch].state = B_CONNECT_B3_ACTIVE_IND;
417
418 } else {
419 struct isdn_l3_driver *l3drv;
420
421 l3drv = isdn_find_l3_by_isdnif(sc->capi_isdnif);
422
423 SET_CAUSE_TV(cd->cause_in, CAUSET_I4B, CAUSE_I4B_OOO); /* XXX */
424 i4b_l4_disconnect_ind(cd);
425 freecd_by_cd(cd);
426
427 l3drv->bch_state[bch] = BCH_ST_RSVD;
428
429 printf("capi%d: can't connect_b3 out, info=%04x\n", sc->sc_unit, Info);
430
431 capi_disconnect_req(sc, cd);
432 }
433 }
434
435 void capi_connect_b3_active_ind(capi_softc_t *sc, struct mbuf *m_in)
436 {
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;
443
444 if (!m) {
445 printf("capi%d: can't get mbuf for b3_active_ind\n", sc->sc_unit);
446 return;
447 }
448
449 msg = capimsg_getu16(msg + 2, &applid);
450 msg = capimsg_getu16(msg + 2, &msgid);
451 msg = capimsg_getu32(msg, &NCCI);
452
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;
457
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;
463 }
464
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);
469
470 msg = capimsg_setu32(msg, NCCI);
471
472 sc->send(sc, m);
473
474 sc->sc_bchan[bch].state = B_CONNECTED;
475
476 i4b_l4_connect_active_ind(cd);
477 }
478
479 /*
480 // Incoming call setup:
481 // --------------------
482 //
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)
493 */
494
495 void capi_connect_ind(capi_softc_t *sc, struct mbuf *m_in)
496 {
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;
504
505 if ((cd = reserve_cd()) == NULL) {
506 printf("capi%d: can't get cd for connect_ind\n", sc->sc_unit);
507 return;
508 }
509
510 cd->isdnif = sc->capi_isdnif;
511 cd->channelexcl = 0;
512 cd->l3drv = isdn_find_l3_by_isdnif(sc->capi_isdnif);
513
514 for (bch = 0; bch < sc->sc_nbch; bch++)
515 if (sc->sc_bchan[bch].state == B_FREE)
516 break;
517
518 sc->sc_bchan[bch].state = B_CONNECT_IND;
519 cd->channelid = bch; /* XXX CHAN_ANY XXX */
520
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';
529
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);
534
535 cd->event = (int) msgid; /* XXX overload */
536 cd->Q931state = (int) PLCI; /* XXX overload */
537
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;
547 }
548
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;
557 }
558 cd->dst_telno[x] = '\0';
559
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;
567 }
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;
573 }
574 cd->src_telno[x] = '\0';
575
576 i4b_l4_connect_ind(cd);
577 }
578
579 void capi_connect_resp(capi_softc_t *sc, call_desc_t *cd)
580 {
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);
587
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;
592 }
593
594 l3drv = isdn_find_l3_by_isdnif(sc->capi_isdnif);
595
596 msgid = (u_int16_t) cd->event;
597 PLCI = (u_int32_t) cd->Q931state;
598
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);
603
604 msg = capimsg_setu32(msg, PLCI);
605
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;
614
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;
620
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 */
629 }
630 break;
631
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));
636 }
637
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 */
648
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 */
655
656 sc->send(sc, m);
657 }
658
659 void capi_connect_b3_ind(capi_softc_t *sc, struct mbuf *m_in)
660 {
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;
666
667 if (!m) {
668 printf("capi%d: can't get mbuf for connect_b3_resp\n", sc->sc_unit);
669 return;
670 }
671
672 msg = capimsg_getu16(msg + 2, &applid);
673 msg = capimsg_getu16(msg + 2, &msgid);
674 msg = capimsg_getu32(msg, &NCCI);
675
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;
680
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);
685
686 msg = capimsg_setu32(msg, NCCI);
687
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 */
692
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 */
697 }
698
699 msg = capimsg_setu8(msg, 0); /* NCPI */
700
701 sc->send(sc, m);
702 }
703
704 /*
705 // Data transfer:
706 // --------------
707 */
708
709 void capi_data_b3_req(capi_softc_t *sc, int chan, struct mbuf *m_b3)
710 {
711 struct mbuf *m = i4b_Dgetmbuf(8 + 14);
712 u_int8_t *msg;
713 u_int16_t msgid;
714
715 if (!m) {
716 printf("capi%d: can't get mbuf for data_b3_req\n", sc->sc_unit);
717 return;
718 }
719
720 msgid = sc->sc_bchan[chan].msgid = sc->sc_msgid++;
721 sc->sc_bchan[chan].busy = 1;
722
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);
727
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 */
733
734 m->m_next = m_b3;
735
736 sc->send(sc, m);
737 }
738
739 void capi_data_b3_conf(capi_softc_t *sc, struct mbuf *m_in)
740 {
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;
745
746 msg = capimsg_getu32(msg + 8, &NCCI);
747 msg = capimsg_getu16(msg, &handle);
748 msg = capimsg_getu16(msg, &Info);
749
750 if (Info == 0) {
751 sc->sc_bchan[handle].busy = 0;
752 capi_start_tx(sc, handle);
753
754 } else {
755 printf("capi%d: data_b3_conf NCCI %x handle %x info=%04x\n",
756 sc->sc_unit, NCCI, handle, Info);
757 }
758 }
759
760 void capi_data_b3_ind(capi_softc_t *sc, struct mbuf *m_in)
761 {
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;
768
769 if (!m) {
770 printf("capi%d: can't get mbuf for data_b3_resp\n", sc->sc_unit);
771 return;
772 }
773
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);
778
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;
783
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);
787
788 } else {
789 if (sc->sc_bchan[bch].bprot == BPROT_RHDLC) {
790 /* HDLC drivers use rx_mbuf */
791
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 */
795
796 (*sc->sc_bchan[bch].l4_driver->bch_rx_data_ready)(
797 sc->sc_bchan[bch].l4_driver_softc);
798
799 } else {
800 /* Telephony drivers use rx_queue */
801
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 */
806 }
807
808 (*sc->sc_bchan[bch].l4_driver->bch_rx_data_ready)(
809 sc->sc_bchan[bch].l4_driver_softc);
810 }
811 }
812
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);
817
818 msg = capimsg_setu32(msg, NCCI);
819 msg = capimsg_setu16(msg, handle);
820
821 sc->send(sc, m);
822 }
823
824 /*
825 // Connection teardown:
826 // --------------------
827 */
828
829 void capi_disconnect_req(capi_softc_t *sc, call_desc_t *cd)
830 {
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;
836
837 if (!m) {
838 printf("capi%d: can't get mbuf for disconnect_req\n", sc->sc_unit);
839 return;
840 }
841
842 l3drv = isdn_find_l3_by_isdnif(sc->capi_isdnif);
843
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);
848
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);
853
854 msg = capimsg_setu32(msg, PLCI);
855 msg = capimsg_setu8(msg, 0); /* Additional Info */
856
857 sc->send(sc, m);
858 }
859
860 void capi_disconnect_conf(capi_softc_t *sc, struct mbuf *m_in)
861 {
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;
867
868 msg = capimsg_getu32(msg + 8, &PLCI);
869
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;
874
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;
879 }
880
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);
888 }
889
890 l3drv = isdn_find_l3_by_isdnif(sc->capi_isdnif);
891
892 sc->sc_bchan[bch].state = B_FREE;
893 l3drv->bch_state[bch] = BCH_ST_FREE;
894 }
895
896 void capi_disconnect_b3_ind(capi_softc_t *sc, struct mbuf *m_in)
897 {
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;
902
903 if (!m) {
904 printf("capi%d: can't get mbuf for disconnect_b3_resp\n", sc->sc_unit);
905 return;
906 }
907
908 msg = capimsg_getu16(msg + 2, &applid);
909 msg = capimsg_getu16(msg + 2, &msgid);
910 msg = capimsg_getu32(msg, &NCCI);
911
912 /* XXX update bchan state? XXX */
913
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);
918
919 msg = capimsg_setu32(msg, NCCI);
920
921 sc->send(sc, m);
922 }
923
924 void capi_disconnect_ind(capi_softc_t *sc, struct mbuf *m_in)
925 {
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;
934
935 if (!m) {
936 printf("capi%d: can't get mbuf for disconnect_resp\n", sc->sc_unit);
937 return;
938 }
939
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);
944
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;
949
950 if (bch < sc->sc_nbch) {
951 /* We may not have a bchan assigned if call was ignored. */
952
953 cd = cd_by_cdid(sc->sc_bchan[bch].cdid);
954 sc->sc_bchan[bch].state = B_DISCONNECT_IND;
955 } else
956 cd = NULL;
957
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);
963 }
964
965 i4b_l4_disconnect_ind(cd);
966 freecd_by_cd(cd);
967
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;
971 }
972
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);
977
978 msg = capimsg_setu32(msg, PLCI);
979
980 sc->send(sc, m);
981 }
Cache object: c42269787e795416d0adbc9f3c0ba4ec
|