1/* $NetBSD: i4b_capi_msgs.c,v 1.5.4.4 2005/03/04 16:53:44 skrll 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.4.4 2005/03/04 16:53:44 skrll 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 58void 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 86void 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 110void 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 138void 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 164void 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 192void 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 268void 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 315void 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 362void 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 389void 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 435void 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 495void 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 579void 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 659void 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 709void 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 739void 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 760void 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 829void 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 860void 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 896void 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 924void 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} 982