1/* $Id: l3_1tr6.c,v 2.15.2.3 2004/01/13 14:31:25 keil Exp $ 2 * 3 * German 1TR6 D-channel protocol 4 * 5 * Author Karsten Keil 6 * Copyright by Karsten Keil <keil@isdn4linux.de> 7 * 8 * This software may be used and distributed according to the terms 9 * of the GNU General Public License, incorporated herein by reference. 10 * 11 * For changes and modifications please read 12 * Documentation/isdn/HiSax.cert 13 * 14 */ 15 16#include "hisax.h" 17#include "l3_1tr6.h" 18#include "isdnl3.h" 19#include <linux/ctype.h> 20 21extern char *HiSax_getrev(const char *revision); 22static const char *l3_1tr6_revision = "$Revision: 2.15.2.3 $"; 23 24#define MsgHead(ptr, cref, mty, dis) \ 25 *ptr++ = dis; \ 26 *ptr++ = 0x1; \ 27 *ptr++ = cref ^ 0x80; \ 28 *ptr++ = mty 29 30static void 31l3_1TR6_message(struct l3_process *pc, u_char mt, u_char pd) 32{ 33 struct sk_buff *skb; 34 u_char *p; 35 36 if (!(skb = l3_alloc_skb(4))) 37 return; 38 p = skb_put(skb, 4); 39 MsgHead(p, pc->callref, mt, pd); 40 l3_msg(pc->st, DL_DATA | REQUEST, skb); 41} 42 43static void 44l3_1tr6_release_req(struct l3_process *pc, u_char pr, void *arg) 45{ 46 StopAllL3Timer(pc); 47 newl3state(pc, 19); 48 l3_1TR6_message(pc, MT_N1_REL, PROTO_DIS_N1); 49 L3AddTimer(&pc->timer, T308, CC_T308_1); 50} 51 52static void 53l3_1tr6_invalid(struct l3_process *pc, u_char pr, void *arg) 54{ 55 struct sk_buff *skb = arg; 56 57 dev_kfree_skb(skb); 58 l3_1tr6_release_req(pc, 0, NULL); 59} 60 61static void 62l3_1tr6_error(struct l3_process *pc, u_char *msg, struct sk_buff *skb) 63{ 64 dev_kfree_skb(skb); 65 if (pc->st->l3.debug & L3_DEB_WARN) 66 l3_debug(pc->st, "%s", msg); 67 l3_1tr6_release_req(pc, 0, NULL); 68} 69 70static void 71l3_1tr6_setup_req(struct l3_process *pc, u_char pr, void *arg) 72{ 73 struct sk_buff *skb; 74 u_char tmp[128]; 75 u_char *p = tmp; 76 u_char *teln; 77 u_char *eaz; 78 u_char channel = 0; 79 int l; 80 81 MsgHead(p, pc->callref, MT_N1_SETUP, PROTO_DIS_N1); 82 teln = pc->para.setup.phone; 83 pc->para.spv = 0; 84 if (!isdigit(*teln)) { 85 switch (0x5f & *teln) { 86 case 'S': 87 pc->para.spv = 1; 88 break; 89 case 'C': 90 channel = 0x08; 91 case 'P': 92 channel |= 0x80; 93 teln++; 94 if (*teln == '1') 95 channel |= 0x01; 96 else 97 channel |= 0x02; 98 break; 99 default: 100 if (pc->st->l3.debug & L3_DEB_WARN) 101 l3_debug(pc->st, "Wrong MSN Code"); 102 break; 103 } 104 teln++; 105 } 106 if (channel) { 107 *p++ = 0x18; /* channel indicator */ 108 *p++ = 1; 109 *p++ = channel; 110 } 111 if (pc->para.spv) { /* SPV ? */ 112 /* NSF SPV */ 113 *p++ = WE0_netSpecFac; 114 *p++ = 4; /* Laenge */ 115 *p++ = 0; 116 *p++ = FAC_SPV; /* SPV */ 117 *p++ = pc->para.setup.si1; /* 0 for all Services */ 118 *p++ = pc->para.setup.si2; /* 0 for all Services */ 119 *p++ = WE0_netSpecFac; 120 *p++ = 4; /* Laenge */ 121 *p++ = 0; 122 *p++ = FAC_Activate; /* aktiviere SPV (default) */ 123 *p++ = pc->para.setup.si1; /* 0 for all Services */ 124 *p++ = pc->para.setup.si2; /* 0 for all Services */ 125 } 126 eaz = pc->para.setup.eazmsn; 127 if (*eaz) { 128 *p++ = WE0_origAddr; 129 *p++ = strlen(eaz) + 1; 130 /* Classify as AnyPref. */ 131 *p++ = 0x81; /* Ext = '1'B, Type = '000'B, Plan = '0001'B. */ 132 while (*eaz) 133 *p++ = *eaz++ & 0x7f; 134 } 135 *p++ = WE0_destAddr; 136 *p++ = strlen(teln) + 1; 137 /* Classify as AnyPref. */ 138 *p++ = 0x81; /* Ext = '1'B, Type = '000'B, Plan = '0001'B. */ 139 while (*teln) 140 *p++ = *teln++ & 0x7f; 141 142 *p++ = WE_Shift_F6; 143 /* Codesatz 6 fuer Service */ 144 *p++ = WE6_serviceInd; 145 *p++ = 2; /* len=2 info,info2 */ 146 *p++ = pc->para.setup.si1; 147 *p++ = pc->para.setup.si2; 148 149 l = p - tmp; 150 if (!(skb = l3_alloc_skb(l))) 151 return; 152 memcpy(skb_put(skb, l), tmp, l); 153 L3DelTimer(&pc->timer); 154 L3AddTimer(&pc->timer, T303, CC_T303); 155 newl3state(pc, 1); 156 l3_msg(pc->st, DL_DATA | REQUEST, skb); 157} 158 159static void 160l3_1tr6_setup(struct l3_process *pc, u_char pr, void *arg) 161{ 162 u_char *p; 163 int bcfound = 0; 164 struct sk_buff *skb = arg; 165 166 /* Channel Identification */ 167 p = findie(skb->data, skb->len, WE0_chanID, 0); 168 if (p) { 169 if (p[1] != 1) { 170 l3_1tr6_error(pc, "setup wrong chanID len", skb); 171 return; 172 } 173 if ((p[2] & 0xf4) != 0x80) { 174 l3_1tr6_error(pc, "setup wrong WE0_chanID", skb); 175 return; 176 } 177 if ((pc->para.bchannel = p[2] & 0x3)) 178 bcfound++; 179 } else { 180 l3_1tr6_error(pc, "missing setup chanID", skb); 181 return; 182 } 183 184 p = skb->data; 185 if ((p = findie(p, skb->len, WE6_serviceInd, 6))) { 186 pc->para.setup.si1 = p[2]; 187 pc->para.setup.si2 = p[3]; 188 } else { 189 l3_1tr6_error(pc, "missing setup SI", skb); 190 return; 191 } 192 193 p = skb->data; 194 if ((p = findie(p, skb->len, WE0_destAddr, 0))) 195 iecpy(pc->para.setup.eazmsn, p, 1); 196 else 197 pc->para.setup.eazmsn[0] = 0; 198 199 p = skb->data; 200 if ((p = findie(p, skb->len, WE0_origAddr, 0))) { 201 iecpy(pc->para.setup.phone, p, 1); 202 } else 203 pc->para.setup.phone[0] = 0; 204 205 p = skb->data; 206 pc->para.spv = 0; 207 if ((p = findie(p, skb->len, WE0_netSpecFac, 0))) { 208 if ((FAC_SPV == p[3]) || (FAC_Activate == p[3])) 209 pc->para.spv = 1; 210 } 211 dev_kfree_skb(skb); 212 213 /* Signal all services, linklevel takes care of Service-Indicator */ 214 if (bcfound) { 215 if ((pc->para.setup.si1 != 7) && (pc->st->l3.debug & L3_DEB_WARN)) { 216 l3_debug(pc->st, "non-digital call: %s -> %s", 217 pc->para.setup.phone, 218 pc->para.setup.eazmsn); 219 } 220 newl3state(pc, 6); 221 pc->st->l3.l3l4(pc->st, CC_SETUP | INDICATION, pc); 222 } else 223 release_l3_process(pc); 224} 225 226static void 227l3_1tr6_setup_ack(struct l3_process *pc, u_char pr, void *arg) 228{ 229 u_char *p; 230 struct sk_buff *skb = arg; 231 232 L3DelTimer(&pc->timer); 233 p = skb->data; 234 newl3state(pc, 2); 235 if ((p = findie(p, skb->len, WE0_chanID, 0))) { 236 if (p[1] != 1) { 237 l3_1tr6_error(pc, "setup_ack wrong chanID len", skb); 238 return; 239 } 240 if ((p[2] & 0xf4) != 0x80) { 241 l3_1tr6_error(pc, "setup_ack wrong WE0_chanID", skb); 242 return; 243 } 244 pc->para.bchannel = p[2] & 0x3; 245 } else { 246 l3_1tr6_error(pc, "missing setup_ack WE0_chanID", skb); 247 return; 248 } 249 dev_kfree_skb(skb); 250 L3AddTimer(&pc->timer, T304, CC_T304); 251 pc->st->l3.l3l4(pc->st, CC_MORE_INFO | INDICATION, pc); 252} 253 254static void 255l3_1tr6_call_sent(struct l3_process *pc, u_char pr, void *arg) 256{ 257 u_char *p; 258 struct sk_buff *skb = arg; 259 260 L3DelTimer(&pc->timer); 261 p = skb->data; 262 if ((p = findie(p, skb->len, WE0_chanID, 0))) { 263 if (p[1] != 1) { 264 l3_1tr6_error(pc, "call sent wrong chanID len", skb); 265 return; 266 } 267 if ((p[2] & 0xf4) != 0x80) { 268 l3_1tr6_error(pc, "call sent wrong WE0_chanID", skb); 269 return; 270 } 271 if ((pc->state == 2) && (pc->para.bchannel != (p[2] & 0x3))) { 272 l3_1tr6_error(pc, "call sent wrong chanID value", skb); 273 return; 274 } 275 pc->para.bchannel = p[2] & 0x3; 276 } else { 277 l3_1tr6_error(pc, "missing call sent WE0_chanID", skb); 278 return; 279 } 280 dev_kfree_skb(skb); 281 L3AddTimer(&pc->timer, T310, CC_T310); 282 newl3state(pc, 3); 283 pc->st->l3.l3l4(pc->st, CC_PROCEEDING | INDICATION, pc); 284} 285 286static void 287l3_1tr6_alert(struct l3_process *pc, u_char pr, void *arg) 288{ 289 struct sk_buff *skb = arg; 290 291 dev_kfree_skb(skb); 292 L3DelTimer(&pc->timer); /* T304 */ 293 newl3state(pc, 4); 294 pc->st->l3.l3l4(pc->st, CC_ALERTING | INDICATION, pc); 295} 296 297static void 298l3_1tr6_info(struct l3_process *pc, u_char pr, void *arg) 299{ 300 u_char *p; 301 int i, tmpcharge = 0; 302 char a_charge[8]; 303 struct sk_buff *skb = arg; 304 305 p = skb->data; 306 if ((p = findie(p, skb->len, WE6_chargingInfo, 6))) { 307 iecpy(a_charge, p, 1); 308 for (i = 0; i < strlen(a_charge); i++) { 309 tmpcharge *= 10; 310 tmpcharge += a_charge[i] & 0xf; 311 } 312 if (tmpcharge > pc->para.chargeinfo) { 313 pc->para.chargeinfo = tmpcharge; 314 pc->st->l3.l3l4(pc->st, CC_CHARGE | INDICATION, pc); 315 } 316 if (pc->st->l3.debug & L3_DEB_CHARGE) { 317 l3_debug(pc->st, "charging info %d", 318 pc->para.chargeinfo); 319 } 320 } else if (pc->st->l3.debug & L3_DEB_CHARGE) 321 l3_debug(pc->st, "charging info not found"); 322 dev_kfree_skb(skb); 323 324} 325 326static void 327l3_1tr6_info_s2(struct l3_process *pc, u_char pr, void *arg) 328{ 329 struct sk_buff *skb = arg; 330 331 dev_kfree_skb(skb); 332} 333 334static void 335l3_1tr6_connect(struct l3_process *pc, u_char pr, void *arg) 336{ 337 struct sk_buff *skb = arg; 338 339 L3DelTimer(&pc->timer); /* T310 */ 340 if (!findie(skb->data, skb->len, WE6_date, 6)) { 341 l3_1tr6_error(pc, "missing connect date", skb); 342 return; 343 } 344 newl3state(pc, 10); 345 dev_kfree_skb(skb); 346 pc->para.chargeinfo = 0; 347 pc->st->l3.l3l4(pc->st, CC_SETUP | CONFIRM, pc); 348} 349 350static void 351l3_1tr6_rel(struct l3_process *pc, u_char pr, void *arg) 352{ 353 struct sk_buff *skb = arg; 354 u_char *p; 355 356 p = skb->data; 357 if ((p = findie(p, skb->len, WE0_cause, 0))) { 358 if (p[1] > 0) { 359 pc->para.cause = p[2]; 360 if (p[1] > 1) 361 pc->para.loc = p[3]; 362 else 363 pc->para.loc = 0; 364 } else { 365 pc->para.cause = 0; 366 pc->para.loc = 0; 367 } 368 } else { 369 pc->para.cause = NO_CAUSE; 370 l3_1tr6_error(pc, "missing REL cause", skb); 371 return; 372 } 373 dev_kfree_skb(skb); 374 StopAllL3Timer(pc); 375 newl3state(pc, 0); 376 l3_1TR6_message(pc, MT_N1_REL_ACK, PROTO_DIS_N1); 377 pc->st->l3.l3l4(pc->st, CC_RELEASE | INDICATION, pc); 378 release_l3_process(pc); 379} 380 381static void 382l3_1tr6_rel_ack(struct l3_process *pc, u_char pr, void *arg) 383{ 384 struct sk_buff *skb = arg; 385 386 dev_kfree_skb(skb); 387 StopAllL3Timer(pc); 388 newl3state(pc, 0); 389 pc->para.cause = NO_CAUSE; 390 pc->st->l3.l3l4(pc->st, CC_RELEASE | CONFIRM, pc); 391 release_l3_process(pc); 392} 393 394static void 395l3_1tr6_disc(struct l3_process *pc, u_char pr, void *arg) 396{ 397 struct sk_buff *skb = arg; 398 u_char *p; 399 int i, tmpcharge = 0; 400 char a_charge[8]; 401 402 StopAllL3Timer(pc); 403 p = skb->data; 404 if ((p = findie(p, skb->len, WE6_chargingInfo, 6))) { 405 iecpy(a_charge, p, 1); 406 for (i = 0; i < strlen(a_charge); i++) { 407 tmpcharge *= 10; 408 tmpcharge += a_charge[i] & 0xf; 409 } 410 if (tmpcharge > pc->para.chargeinfo) { 411 pc->para.chargeinfo = tmpcharge; 412 pc->st->l3.l3l4(pc->st, CC_CHARGE | INDICATION, pc); 413 } 414 if (pc->st->l3.debug & L3_DEB_CHARGE) { 415 l3_debug(pc->st, "charging info %d", 416 pc->para.chargeinfo); 417 } 418 } else if (pc->st->l3.debug & L3_DEB_CHARGE) 419 l3_debug(pc->st, "charging info not found"); 420 421 422 p = skb->data; 423 if ((p = findie(p, skb->len, WE0_cause, 0))) { 424 if (p[1] > 0) { 425 pc->para.cause = p[2]; 426 if (p[1] > 1) 427 pc->para.loc = p[3]; 428 else 429 pc->para.loc = 0; 430 } else { 431 pc->para.cause = 0; 432 pc->para.loc = 0; 433 } 434 } else { 435 if (pc->st->l3.debug & L3_DEB_WARN) 436 l3_debug(pc->st, "cause not found"); 437 pc->para.cause = NO_CAUSE; 438 } 439 if (!findie(skb->data, skb->len, WE6_date, 6)) { 440 l3_1tr6_error(pc, "missing connack date", skb); 441 return; 442 } 443 dev_kfree_skb(skb); 444 newl3state(pc, 12); 445 pc->st->l3.l3l4(pc->st, CC_DISCONNECT | INDICATION, pc); 446} 447 448 449static void 450l3_1tr6_connect_ack(struct l3_process *pc, u_char pr, void *arg) 451{ 452 struct sk_buff *skb = arg; 453 454 if (!findie(skb->data, skb->len, WE6_date, 6)) { 455 l3_1tr6_error(pc, "missing connack date", skb); 456 return; 457 } 458 dev_kfree_skb(skb); 459 newl3state(pc, 10); 460 pc->para.chargeinfo = 0; 461 L3DelTimer(&pc->timer); 462 pc->st->l3.l3l4(pc->st, CC_SETUP_COMPL | INDICATION, pc); 463} 464 465static void 466l3_1tr6_alert_req(struct l3_process *pc, u_char pr, void *arg) 467{ 468 newl3state(pc, 7); 469 l3_1TR6_message(pc, MT_N1_ALERT, PROTO_DIS_N1); 470} 471 472static void 473l3_1tr6_setup_rsp(struct l3_process *pc, u_char pr, void *arg) 474{ 475 struct sk_buff *skb; 476 u_char tmp[24]; 477 u_char *p = tmp; 478 int l; 479 480 MsgHead(p, pc->callref, MT_N1_CONN, PROTO_DIS_N1); 481 if (pc->para.spv) { /* SPV ? */ 482 /* NSF SPV */ 483 *p++ = WE0_netSpecFac; 484 *p++ = 4; /* Laenge */ 485 *p++ = 0; 486 *p++ = FAC_SPV; /* SPV */ 487 *p++ = pc->para.setup.si1; 488 *p++ = pc->para.setup.si2; 489 *p++ = WE0_netSpecFac; 490 *p++ = 4; /* Laenge */ 491 *p++ = 0; 492 *p++ = FAC_Activate; /* aktiviere SPV */ 493 *p++ = pc->para.setup.si1; 494 *p++ = pc->para.setup.si2; 495 } 496 newl3state(pc, 8); 497 l = p - tmp; 498 if (!(skb = l3_alloc_skb(l))) 499 return; 500 memcpy(skb_put(skb, l), tmp, l); 501 l3_msg(pc->st, DL_DATA | REQUEST, skb); 502 L3DelTimer(&pc->timer); 503 L3AddTimer(&pc->timer, T313, CC_T313); 504} 505 506static void 507l3_1tr6_reset(struct l3_process *pc, u_char pr, void *arg) 508{ 509 release_l3_process(pc); 510} 511 512static void 513l3_1tr6_disconnect_req(struct l3_process *pc, u_char pr, void *arg) 514{ 515 struct sk_buff *skb; 516 u_char tmp[16]; 517 u_char *p = tmp; 518 int l; 519 u_char cause = 0x10; 520 u_char clen = 1; 521 522 if (pc->para.cause > 0) 523 cause = pc->para.cause; 524 /* Map DSS1 causes */ 525 switch (cause & 0x7f) { 526 case 0x10: 527 clen = 0; 528 break; 529 case 0x11: 530 cause = CAUSE_UserBusy; 531 break; 532 case 0x15: 533 cause = CAUSE_CallRejected; 534 break; 535 } 536 StopAllL3Timer(pc); 537 MsgHead(p, pc->callref, MT_N1_DISC, PROTO_DIS_N1); 538 *p++ = WE0_cause; 539 *p++ = clen; /* Laenge */ 540 if (clen) 541 *p++ = cause | 0x80; 542 newl3state(pc, 11); 543 l = p - tmp; 544 if (!(skb = l3_alloc_skb(l))) 545 return; 546 memcpy(skb_put(skb, l), tmp, l); 547 l3_msg(pc->st, DL_DATA | REQUEST, skb); 548 L3AddTimer(&pc->timer, T305, CC_T305); 549} 550 551static void 552l3_1tr6_t303(struct l3_process *pc, u_char pr, void *arg) 553{ 554 if (pc->N303 > 0) { 555 pc->N303--; 556 L3DelTimer(&pc->timer); 557 l3_1tr6_setup_req(pc, pr, arg); 558 } else { 559 L3DelTimer(&pc->timer); 560 pc->para.cause = 0; 561 l3_1tr6_disconnect_req(pc, 0, NULL); 562 } 563} 564 565static void 566l3_1tr6_t304(struct l3_process *pc, u_char pr, void *arg) 567{ 568 L3DelTimer(&pc->timer); 569 pc->para.cause = 0xE6; 570 l3_1tr6_disconnect_req(pc, pr, NULL); 571 pc->st->l3.l3l4(pc->st, CC_SETUP_ERR, pc); 572} 573 574static void 575l3_1tr6_t305(struct l3_process *pc, u_char pr, void *arg) 576{ 577 struct sk_buff *skb; 578 u_char tmp[16]; 579 u_char *p = tmp; 580 int l; 581 u_char cause = 0x90; 582 u_char clen = 1; 583 584 L3DelTimer(&pc->timer); 585 if (pc->para.cause != NO_CAUSE) 586 cause = pc->para.cause; 587 /* Map DSS1 causes */ 588 switch (cause & 0x7f) { 589 case 0x10: 590 clen = 0; 591 break; 592 case 0x15: 593 cause = CAUSE_CallRejected; 594 break; 595 } 596 MsgHead(p, pc->callref, MT_N1_REL, PROTO_DIS_N1); 597 *p++ = WE0_cause; 598 *p++ = clen; /* Laenge */ 599 if (clen) 600 *p++ = cause; 601 newl3state(pc, 19); 602 l = p - tmp; 603 if (!(skb = l3_alloc_skb(l))) 604 return; 605 memcpy(skb_put(skb, l), tmp, l); 606 l3_msg(pc->st, DL_DATA | REQUEST, skb); 607 L3AddTimer(&pc->timer, T308, CC_T308_1); 608} 609 610static void 611l3_1tr6_t310(struct l3_process *pc, u_char pr, void *arg) 612{ 613 L3DelTimer(&pc->timer); 614 pc->para.cause = 0xE6; 615 l3_1tr6_disconnect_req(pc, pr, NULL); 616 pc->st->l3.l3l4(pc->st, CC_SETUP_ERR, pc); 617} 618 619static void 620l3_1tr6_t313(struct l3_process *pc, u_char pr, void *arg) 621{ 622 L3DelTimer(&pc->timer); 623 pc->para.cause = 0xE6; 624 l3_1tr6_disconnect_req(pc, pr, NULL); 625 pc->st->l3.l3l4(pc->st, CC_CONNECT_ERR, pc); 626} 627 628static void 629l3_1tr6_t308_1(struct l3_process *pc, u_char pr, void *arg) 630{ 631 L3DelTimer(&pc->timer); 632 l3_1TR6_message(pc, MT_N1_REL, PROTO_DIS_N1); 633 L3AddTimer(&pc->timer, T308, CC_T308_2); 634 newl3state(pc, 19); 635} 636 637static void 638l3_1tr6_t308_2(struct l3_process *pc, u_char pr, void *arg) 639{ 640 L3DelTimer(&pc->timer); 641 pc->st->l3.l3l4(pc->st, CC_RELEASE_ERR, pc); 642 release_l3_process(pc); 643} 644 645static void 646l3_1tr6_dl_reset(struct l3_process *pc, u_char pr, void *arg) 647{ 648 pc->para.cause = CAUSE_LocalProcErr; 649 l3_1tr6_disconnect_req(pc, pr, NULL); 650 pc->st->l3.l3l4(pc->st, CC_SETUP_ERR, pc); 651} 652 653static void 654l3_1tr6_dl_release(struct l3_process *pc, u_char pr, void *arg) 655{ 656 newl3state(pc, 0); 657 pc->para.cause = 0x1b; /* Destination out of order */ 658 pc->para.loc = 0; 659 pc->st->l3.l3l4(pc->st, CC_RELEASE | INDICATION, pc); 660 release_l3_process(pc); 661} 662 663/* *INDENT-OFF* */ 664static struct stateentry downstl[] = 665{ 666 {SBIT(0), 667 CC_SETUP | REQUEST, l3_1tr6_setup_req}, 668 {SBIT(1) | SBIT(2) | SBIT(3) | SBIT(4) | SBIT(6) | SBIT(7) | SBIT(8) | 669 SBIT(10), 670 CC_DISCONNECT | REQUEST, l3_1tr6_disconnect_req}, 671 {SBIT(12), 672 CC_RELEASE | REQUEST, l3_1tr6_release_req}, 673 {SBIT(6), 674 CC_IGNORE | REQUEST, l3_1tr6_reset}, 675 {SBIT(6), 676 CC_REJECT | REQUEST, l3_1tr6_disconnect_req}, 677 {SBIT(6), 678 CC_ALERTING | REQUEST, l3_1tr6_alert_req}, 679 {SBIT(6) | SBIT(7), 680 CC_SETUP | RESPONSE, l3_1tr6_setup_rsp}, 681 {SBIT(1), 682 CC_T303, l3_1tr6_t303}, 683 {SBIT(2), 684 CC_T304, l3_1tr6_t304}, 685 {SBIT(3), 686 CC_T310, l3_1tr6_t310}, 687 {SBIT(8), 688 CC_T313, l3_1tr6_t313}, 689 {SBIT(11), 690 CC_T305, l3_1tr6_t305}, 691 {SBIT(19), 692 CC_T308_1, l3_1tr6_t308_1}, 693 {SBIT(19), 694 CC_T308_2, l3_1tr6_t308_2}, 695}; 696 697static struct stateentry datastln1[] = 698{ 699 {SBIT(0), 700 MT_N1_INVALID, l3_1tr6_invalid}, 701 {SBIT(0), 702 MT_N1_SETUP, l3_1tr6_setup}, 703 {SBIT(1), 704 MT_N1_SETUP_ACK, l3_1tr6_setup_ack}, 705 {SBIT(1) | SBIT(2), 706 MT_N1_CALL_SENT, l3_1tr6_call_sent}, 707 {SBIT(1) | SBIT(2) | SBIT(3) | SBIT(4) | SBIT(7) | SBIT(8) | SBIT(10), 708 MT_N1_DISC, l3_1tr6_disc}, 709 {SBIT(2) | SBIT(3) | SBIT(4), 710 MT_N1_ALERT, l3_1tr6_alert}, 711 {SBIT(2) | SBIT(3) | SBIT(4), 712 MT_N1_CONN, l3_1tr6_connect}, 713 {SBIT(2), 714 MT_N1_INFO, l3_1tr6_info_s2}, 715 {SBIT(8), 716 MT_N1_CONN_ACK, l3_1tr6_connect_ack}, 717 {SBIT(10), 718 MT_N1_INFO, l3_1tr6_info}, 719 {SBIT(0) | SBIT(1) | SBIT(2) | SBIT(3) | SBIT(4) | SBIT(7) | SBIT(8) | 720 SBIT(10) | SBIT(11) | SBIT(12) | SBIT(15) | SBIT(17), 721 MT_N1_REL, l3_1tr6_rel}, 722 {SBIT(19), 723 MT_N1_REL, l3_1tr6_rel_ack}, 724 {SBIT(0) | SBIT(1) | SBIT(2) | SBIT(3) | SBIT(4) | SBIT(7) | SBIT(8) | 725 SBIT(10) | SBIT(11) | SBIT(12) | SBIT(15) | SBIT(17), 726 MT_N1_REL_ACK, l3_1tr6_invalid}, 727 {SBIT(19), 728 MT_N1_REL_ACK, l3_1tr6_rel_ack} 729}; 730 731static struct stateentry manstatelist[] = 732{ 733 {SBIT(2), 734 DL_ESTABLISH | INDICATION, l3_1tr6_dl_reset}, 735 {ALL_STATES, 736 DL_RELEASE | INDICATION, l3_1tr6_dl_release}, 737}; 738 739/* *INDENT-ON* */ 740 741static void 742up1tr6(struct PStack *st, int pr, void *arg) 743{ 744 int i, mt, cr; 745 struct l3_process *proc; 746 struct sk_buff *skb = arg; 747 748 switch (pr) { 749 case (DL_DATA | INDICATION): 750 case (DL_UNIT_DATA | INDICATION): 751 break; 752 case (DL_ESTABLISH | CONFIRM): 753 case (DL_ESTABLISH | INDICATION): 754 case (DL_RELEASE | INDICATION): 755 case (DL_RELEASE | CONFIRM): 756 l3_msg(st, pr, arg); 757 return; 758 break; 759 } 760 if (skb->len < 4) { 761 if (st->l3.debug & L3_DEB_PROTERR) { 762 l3_debug(st, "up1tr6 len only %d", skb->len); 763 } 764 dev_kfree_skb(skb); 765 return; 766 } 767 if ((skb->data[0] & 0xfe) != PROTO_DIS_N0) { 768 if (st->l3.debug & L3_DEB_PROTERR) { 769 l3_debug(st, "up1tr6%sunexpected discriminator %x message len %d", 770 (pr == (DL_DATA | INDICATION)) ? " " : "(broadcast) ", 771 skb->data[0], skb->len); 772 } 773 dev_kfree_skb(skb); 774 return; 775 } 776 if (skb->data[1] != 1) { 777 if (st->l3.debug & L3_DEB_PROTERR) { 778 l3_debug(st, "up1tr6 CR len not 1"); 779 } 780 dev_kfree_skb(skb); 781 return; 782 } 783 cr = skb->data[2]; 784 mt = skb->data[3]; 785 if (skb->data[0] == PROTO_DIS_N0) { 786 dev_kfree_skb(skb); 787 if (st->l3.debug & L3_DEB_STATE) { 788 l3_debug(st, "up1tr6%s N0 mt %x unhandled", 789 (pr == (DL_DATA | INDICATION)) ? " " : "(broadcast) ", mt); 790 } 791 } else if (skb->data[0] == PROTO_DIS_N1) { 792 if (!(proc = getl3proc(st, cr))) { 793 if (mt == MT_N1_SETUP) { 794 if (cr < 128) { 795 if (!(proc = new_l3_process(st, cr))) { 796 if (st->l3.debug & L3_DEB_PROTERR) { 797 l3_debug(st, "up1tr6 no roc mem"); 798 } 799 dev_kfree_skb(skb); 800 return; 801 } 802 } else { 803 dev_kfree_skb(skb); 804 return; 805 } 806 } else if ((mt == MT_N1_REL) || (mt == MT_N1_REL_ACK) || 807 (mt == MT_N1_CANC_ACK) || (mt == MT_N1_CANC_REJ) || 808 (mt == MT_N1_REG_ACK) || (mt == MT_N1_REG_REJ) || 809 (mt == MT_N1_SUSP_ACK) || (mt == MT_N1_RES_REJ) || 810 (mt == MT_N1_INFO)) { 811 dev_kfree_skb(skb); 812 return; 813 } else { 814 if (!(proc = new_l3_process(st, cr))) { 815 if (st->l3.debug & L3_DEB_PROTERR) { 816 l3_debug(st, "up1tr6 no roc mem"); 817 } 818 dev_kfree_skb(skb); 819 return; 820 } 821 mt = MT_N1_INVALID; 822 } 823 } 824 for (i = 0; i < ARRAY_SIZE(datastln1); i++) 825 if ((mt == datastln1[i].primitive) && 826 ((1 << proc->state) & datastln1[i].state)) 827 break; 828 if (i == ARRAY_SIZE(datastln1)) { 829 dev_kfree_skb(skb); 830 if (st->l3.debug & L3_DEB_STATE) { 831 l3_debug(st, "up1tr6%sstate %d mt %x unhandled", 832 (pr == (DL_DATA | INDICATION)) ? " " : "(broadcast) ", 833 proc->state, mt); 834 } 835 return; 836 } else { 837 if (st->l3.debug & L3_DEB_STATE) { 838 l3_debug(st, "up1tr6%sstate %d mt %x", 839 (pr == (DL_DATA | INDICATION)) ? " " : "(broadcast) ", 840 proc->state, mt); 841 } 842 datastln1[i].rout(proc, pr, skb); 843 } 844 } 845} 846 847static void 848down1tr6(struct PStack *st, int pr, void *arg) 849{ 850 int i, cr; 851 struct l3_process *proc; 852 struct Channel *chan; 853 854 if ((DL_ESTABLISH | REQUEST) == pr) { 855 l3_msg(st, pr, NULL); 856 return; 857 } else if ((CC_SETUP | REQUEST) == pr) { 858 chan = arg; 859 cr = newcallref(); 860 cr |= 0x80; 861 if (!(proc = new_l3_process(st, cr))) { 862 return; 863 } else { 864 proc->chan = chan; 865 chan->proc = proc; 866 memcpy(&proc->para.setup, &chan->setup, sizeof(setup_parm)); 867 proc->callref = cr; 868 } 869 } else { 870 proc = arg; 871 } 872 873 for (i = 0; i < ARRAY_SIZE(downstl); i++) 874 if ((pr == downstl[i].primitive) && 875 ((1 << proc->state) & downstl[i].state)) 876 break; 877 if (i == ARRAY_SIZE(downstl)) { 878 if (st->l3.debug & L3_DEB_STATE) { 879 l3_debug(st, "down1tr6 state %d prim %d unhandled", 880 proc->state, pr); 881 } 882 } else { 883 if (st->l3.debug & L3_DEB_STATE) { 884 l3_debug(st, "down1tr6 state %d prim %d", 885 proc->state, pr); 886 } 887 downstl[i].rout(proc, pr, arg); 888 } 889} 890 891static void 892man1tr6(struct PStack *st, int pr, void *arg) 893{ 894 int i; 895 struct l3_process *proc = arg; 896 897 if (!proc) { 898 printk(KERN_ERR "HiSax man1tr6 without proc pr=%04x\n", pr); 899 return; 900 } 901 for (i = 0; i < ARRAY_SIZE(manstatelist); i++) 902 if ((pr == manstatelist[i].primitive) && 903 ((1 << proc->state) & manstatelist[i].state)) 904 break; 905 if (i == ARRAY_SIZE(manstatelist)) { 906 if (st->l3.debug & L3_DEB_STATE) { 907 l3_debug(st, "cr %d man1tr6 state %d prim %d unhandled", 908 proc->callref & 0x7f, proc->state, pr); 909 } 910 } else { 911 if (st->l3.debug & L3_DEB_STATE) { 912 l3_debug(st, "cr %d man1tr6 state %d prim %d", 913 proc->callref & 0x7f, proc->state, pr); 914 } 915 manstatelist[i].rout(proc, pr, arg); 916 } 917} 918 919void 920setstack_1tr6(struct PStack *st) 921{ 922 char tmp[64]; 923 924 st->lli.l4l3 = down1tr6; 925 st->l2.l2l3 = up1tr6; 926 st->l3.l3ml3 = man1tr6; 927 st->l3.N303 = 0; 928 929 strcpy(tmp, l3_1tr6_revision); 930 printk(KERN_INFO "HiSax: 1TR6 Rev. %s\n", HiSax_getrev(tmp)); 931} 932