linux/drivers/isdn/hisax/l3_1tr6.c
<<
>>
Prefs
   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