linux/drivers/isdn/hisax/l3dss1.c
<<
>>
Prefs
   1/* $Id: l3dss1.c,v 2.32.2.3 2004/01/13 14:31:25 keil Exp $
   2 *
   3 * EURO/DSS1 D-channel protocol
   4 *
   5 * German 1TR6 D-channel protocol
   6 *
   7 * Author       Karsten Keil
   8 *              based on the teles driver from Jan den Ouden
   9 * Copyright    by Karsten Keil      <keil@isdn4linux.de>
  10 * 
  11 * This software may be used and distributed according to the terms
  12 * of the GNU General Public License, incorporated herein by reference.
  13 *
  14 * For changes and modifications please read
  15 * Documentation/isdn/HiSax.cert
  16 *
  17 * Thanks to    Jan den Ouden
  18 *              Fritz Elfert
  19 *
  20 */
  21
  22#include "hisax.h"
  23#include "isdnl3.h"
  24#include "l3dss1.h"
  25#include <linux/ctype.h>
  26
  27extern char *HiSax_getrev(const char *revision);
  28static const char *dss1_revision = "$Revision: 2.32.2.3 $";
  29
  30#define EXT_BEARER_CAPS 1
  31
  32#define MsgHead(ptr, cref, mty) \
  33        *ptr++ = 0x8; \
  34        if (cref == -1) { \
  35                *ptr++ = 0x0; \
  36        } else { \
  37                *ptr++ = 0x1; \
  38                *ptr++ = cref^0x80; \
  39        } \
  40        *ptr++ = mty
  41
  42
  43/**********************************************/
  44/* get a new invoke id for remote operations. */
  45/* Only a return value != 0 is valid          */
  46/**********************************************/
  47static unsigned char new_invoke_id(struct PStack *p)
  48{
  49        unsigned char retval;
  50        int i;
  51  
  52        i = 32; /* maximum search depth */
  53
  54        retval = p->prot.dss1.last_invoke_id + 1; /* try new id */
  55        while ((i) && (p->prot.dss1.invoke_used[retval >> 3] == 0xFF)) {
  56                p->prot.dss1.last_invoke_id = (retval & 0xF8) + 8;
  57                i--;
  58        }  
  59        if (i) {
  60                while (p->prot.dss1.invoke_used[retval >> 3] & (1 << (retval & 7)))
  61                retval++; 
  62        } else
  63                retval = 0;
  64        p->prot.dss1.last_invoke_id = retval;
  65        p->prot.dss1.invoke_used[retval >> 3] |= (1 << (retval & 7));
  66        return(retval);  
  67} /* new_invoke_id */
  68
  69/*************************/
  70/* free a used invoke id */
  71/*************************/
  72static void free_invoke_id(struct PStack *p, unsigned char id)
  73{
  74
  75  if (!id) return; /* 0 = invalid value */
  76
  77  p->prot.dss1.invoke_used[id >> 3] &= ~(1 << (id & 7));
  78} /* free_invoke_id */  
  79
  80
  81/**********************************************************/
  82/* create a new l3 process and fill in dss1 specific data */
  83/**********************************************************/
  84static struct l3_process
  85*dss1_new_l3_process(struct PStack *st, int cr)
  86{  struct l3_process *proc;
  87
  88   if (!(proc = new_l3_process(st, cr))) 
  89     return(NULL);
  90
  91   proc->prot.dss1.invoke_id = 0;
  92   proc->prot.dss1.remote_operation = 0;
  93   proc->prot.dss1.uus1_data[0] = '\0';
  94   
  95   return(proc);
  96} /* dss1_new_l3_process */
  97
  98/************************************************/
  99/* free a l3 process and all dss1 specific data */
 100/************************************************/ 
 101static void
 102dss1_release_l3_process(struct l3_process *p)
 103{
 104   free_invoke_id(p->st,p->prot.dss1.invoke_id);
 105   release_l3_process(p);
 106} /* dss1_release_l3_process */
 107 
 108/********************************************************/
 109/* search a process with invoke id id and dummy callref */
 110/********************************************************/
 111static struct l3_process *
 112l3dss1_search_dummy_proc(struct PStack *st, int id)
 113{ struct l3_process *pc = st->l3.proc; /* start of processes */
 114
 115  if (!id) return(NULL);
 116
 117  while (pc)
 118   { if ((pc->callref == -1) && (pc->prot.dss1.invoke_id == id))
 119       return(pc);
 120     pc = pc->next;
 121   } 
 122  return(NULL);
 123} /* l3dss1_search_dummy_proc */
 124
 125/*******************************************************************/
 126/* called when a facility message with a dummy callref is received */
 127/* and a return result is delivered. id specifies the invoke id.   */
 128/*******************************************************************/ 
 129static void 
 130l3dss1_dummy_return_result(struct PStack *st, int id, u_char *p, u_char nlen)
 131{ isdn_ctrl ic;
 132  struct IsdnCardState *cs;
 133  struct l3_process *pc = NULL; 
 134
 135  if ((pc = l3dss1_search_dummy_proc(st, id)))
 136   { L3DelTimer(&pc->timer); /* remove timer */
 137
 138     cs = pc->st->l1.hardware;
 139     ic.driver = cs->myid;
 140     ic.command = ISDN_STAT_PROT;
 141     ic.arg = DSS1_STAT_INVOKE_RES;
 142     ic.parm.dss1_io.hl_id = pc->prot.dss1.invoke_id;
 143     ic.parm.dss1_io.ll_id = pc->prot.dss1.ll_id;
 144     ic.parm.dss1_io.proc = pc->prot.dss1.proc;
 145     ic.parm.dss1_io.timeout= 0;
 146     ic.parm.dss1_io.datalen = nlen;
 147     ic.parm.dss1_io.data = p;
 148     free_invoke_id(pc->st, pc->prot.dss1.invoke_id);
 149     pc->prot.dss1.invoke_id = 0; /* reset id */
 150
 151     cs->iif.statcallb(&ic);
 152     dss1_release_l3_process(pc); 
 153   }
 154  else
 155   l3_debug(st, "dummy return result id=0x%x result len=%d",id,nlen);
 156} /* l3dss1_dummy_return_result */
 157
 158/*******************************************************************/
 159/* called when a facility message with a dummy callref is received */
 160/* and a return error is delivered. id specifies the invoke id.    */
 161/*******************************************************************/ 
 162static void 
 163l3dss1_dummy_error_return(struct PStack *st, int id, ulong error)
 164{ isdn_ctrl ic;
 165  struct IsdnCardState *cs;
 166  struct l3_process *pc = NULL; 
 167
 168  if ((pc = l3dss1_search_dummy_proc(st, id)))
 169   { L3DelTimer(&pc->timer); /* remove timer */
 170
 171     cs = pc->st->l1.hardware;
 172     ic.driver = cs->myid;
 173     ic.command = ISDN_STAT_PROT;
 174     ic.arg = DSS1_STAT_INVOKE_ERR;
 175     ic.parm.dss1_io.hl_id = pc->prot.dss1.invoke_id;
 176     ic.parm.dss1_io.ll_id = pc->prot.dss1.ll_id;
 177     ic.parm.dss1_io.proc = pc->prot.dss1.proc;
 178     ic.parm.dss1_io.timeout= error;
 179     ic.parm.dss1_io.datalen = 0;
 180     ic.parm.dss1_io.data = NULL;
 181     free_invoke_id(pc->st, pc->prot.dss1.invoke_id);
 182     pc->prot.dss1.invoke_id = 0; /* reset id */
 183
 184     cs->iif.statcallb(&ic);
 185     dss1_release_l3_process(pc); 
 186   }
 187  else
 188   l3_debug(st, "dummy return error id=0x%x error=0x%lx",id,error);
 189} /* l3dss1_error_return */
 190
 191/*******************************************************************/
 192/* called when a facility message with a dummy callref is received */
 193/* and a invoke is delivered. id specifies the invoke id.          */
 194/*******************************************************************/ 
 195static void 
 196l3dss1_dummy_invoke(struct PStack *st, int cr, int id, 
 197                    int ident, u_char *p, u_char nlen)
 198{ isdn_ctrl ic;
 199  struct IsdnCardState *cs;
 200  
 201  l3_debug(st, "dummy invoke %s id=0x%x ident=0x%x datalen=%d",
 202               (cr == -1) ? "local" : "broadcast",id,ident,nlen);
 203  if (cr >= -1) return; /* ignore local data */
 204
 205  cs = st->l1.hardware;
 206  ic.driver = cs->myid;
 207  ic.command = ISDN_STAT_PROT;
 208  ic.arg = DSS1_STAT_INVOKE_BRD;
 209  ic.parm.dss1_io.hl_id = id;
 210  ic.parm.dss1_io.ll_id = 0;
 211  ic.parm.dss1_io.proc = ident;
 212  ic.parm.dss1_io.timeout= 0;
 213  ic.parm.dss1_io.datalen = nlen;
 214  ic.parm.dss1_io.data = p;
 215
 216  cs->iif.statcallb(&ic);
 217} /* l3dss1_dummy_invoke */
 218
 219static void
 220l3dss1_parse_facility(struct PStack *st, struct l3_process *pc,
 221                      int cr, u_char * p)
 222{
 223        int qd_len = 0;
 224        unsigned char nlen = 0, ilen, cp_tag;
 225        int ident, id;
 226        ulong err_ret;
 227
 228        if (pc) 
 229                st = pc->st; /* valid Stack */
 230        else
 231                if ((!st) || (cr >= 0)) return; /* neither pc nor st specified */
 232
 233        p++;
 234        qd_len = *p++;
 235        if (qd_len == 0) {
 236                l3_debug(st, "qd_len == 0");
 237                return;
 238        }
 239        if ((*p & 0x1F) != 0x11) {      /* Service discriminator, supplementary service */
 240                l3_debug(st, "supplementary service != 0x11");
 241                return;
 242        }
 243        while (qd_len > 0 && !(*p & 0x80)) {    /* extension ? */
 244                p++;
 245                qd_len--;
 246        }
 247        if (qd_len < 2) {
 248                l3_debug(st, "qd_len < 2");
 249                return;
 250        }
 251        p++;
 252        qd_len--;
 253        if ((*p & 0xE0) != 0xA0) {      /* class and form */
 254                l3_debug(st, "class and form != 0xA0");
 255                return;
 256        }
 257       
 258        cp_tag = *p & 0x1F; /* remember tag value */
 259
 260        p++;
 261        qd_len--;
 262        if (qd_len < 1) 
 263          { l3_debug(st, "qd_len < 1");
 264            return;
 265          }
 266        if (*p & 0x80) 
 267          { /* length format indefinite or limited */
 268            nlen = *p++ & 0x7F; /* number of len bytes or indefinite */
 269            if ((qd_len-- < ((!nlen) ? 3 : (1 + nlen))) ||
 270                (nlen > 1))   
 271             { l3_debug(st, "length format error or not implemented");
 272               return;
 273             }
 274            if (nlen == 1)
 275             { nlen = *p++; /* complete length */
 276               qd_len--;
 277             } 
 278            else
 279             { qd_len -= 2; /* trailing null bytes */
 280               if ((*(p+qd_len)) || (*(p+qd_len+1)))
 281                { l3_debug(st,"length format indefinite error");
 282                  return;
 283                }
 284               nlen = qd_len;
 285             }
 286          }
 287        else
 288          { nlen = *p++;
 289            qd_len--;
 290          } 
 291        if (qd_len < nlen) 
 292          { l3_debug(st, "qd_len < nlen");
 293            return;
 294          }
 295        qd_len -= nlen;
 296
 297        if (nlen < 2) 
 298          { l3_debug(st, "nlen < 2");
 299            return;
 300          }
 301        if (*p != 0x02) 
 302          {  /* invoke identifier tag */
 303             l3_debug(st, "invoke identifier tag !=0x02");
 304             return;
 305          }
 306        p++;
 307        nlen--;
 308        if (*p & 0x80) 
 309          { /* length format */
 310            l3_debug(st, "invoke id length format 2");
 311            return;
 312          }
 313        ilen = *p++;
 314        nlen--;
 315        if (ilen > nlen || ilen == 0) 
 316          { l3_debug(st, "ilen > nlen || ilen == 0");
 317            return;
 318          }
 319        nlen -= ilen;
 320        id = 0;
 321        while (ilen > 0) 
 322          { id = (id << 8) | (*p++ & 0xFF);     /* invoke identifier */
 323            ilen--;
 324          }
 325
 326        switch (cp_tag) {       /* component tag */
 327                case 1: /* invoke */
 328                                if (nlen < 2) {
 329                                        l3_debug(st, "nlen < 2 22");
 330                                        return;
 331                                }
 332                                if (*p != 0x02) {       /* operation value */
 333                                        l3_debug(st, "operation value !=0x02");
 334                                        return;
 335                                }
 336                                p++;
 337                                nlen--;
 338                                ilen = *p++;
 339                                nlen--;
 340                                if (ilen > nlen || ilen == 0) {
 341                                        l3_debug(st, "ilen > nlen || ilen == 0 22");
 342                                        return;
 343                                }
 344                                nlen -= ilen;
 345                                ident = 0;
 346                                while (ilen > 0) {
 347                                        ident = (ident << 8) | (*p++ & 0xFF);
 348                                        ilen--;
 349                                }
 350
 351                                if (!pc) 
 352                                 { l3dss1_dummy_invoke(st, cr, id, ident, p, nlen);
 353                                   return;
 354                                 } 
 355#ifdef HISAX_DE_AOC
 356                        {
 357
 358#define FOO1(s,a,b) \
 359            while(nlen > 1) {           \
 360                    int ilen = p[1];    \
 361                    if(nlen < ilen+2) { \
 362                            l3_debug(st, "FOO1  nlen < ilen+2"); \
 363                            return;             \
 364                    }                   \
 365                    nlen -= ilen+2;             \
 366                    if((*p & 0xFF) == (a)) {    \
 367                            int nlen = ilen;    \
 368                            p += 2;             \
 369                            b;          \
 370                    } else {            \
 371                            p += ilen+2;        \
 372                    }                   \
 373            }
 374
 375                                switch (ident) {
 376                                        case 0x22:      /* during */
 377                                                FOO1("1A", 0x30, FOO1("1C", 0xA1, FOO1("1D", 0x30, FOO1("1E", 0x02, ( {
 378                                                               ident = 0;
 379                                                        nlen = (nlen)?nlen:0; /* Make gcc happy */
 380                                                        while (ilen > 0) {
 381                                                                                                                     ident = (ident << 8) | *p++;
 382                                                                  ilen--;
 383                                                                        }
 384                                                                                                                     if (ident > pc->para.chargeinfo) {
 385                                                                                                                     pc->para.chargeinfo = ident;
 386                                                                                                                     st->l3.l3l4(st, CC_CHARGE | INDICATION, pc);
 387                                                                        }
 388                                                                                                                     if (st->l3.debug & L3_DEB_CHARGE) {
 389                                                                                                                     if (*(p + 2) == 0) {
 390                                                                                                                     l3_debug(st, "charging info during %d", pc->para.chargeinfo);
 391                                                                        }
 392                                                                   else {
 393                                                                                                                     l3_debug(st, "charging info final %d", pc->para.chargeinfo);
 394                                                                        }
 395                                                                        }
 396                                                                        }
 397                                                                    )))))
 398                                                        break;
 399                                        case 0x24:      /* final */
 400                                                FOO1("2A", 0x30, FOO1("2B", 0x30, FOO1("2C", 0xA1, FOO1("2D", 0x30, FOO1("2E", 0x02, ( {
 401                                                               ident = 0;
 402                                                        nlen = (nlen)?nlen:0; /* Make gcc happy */
 403                                                        while (ilen > 0) {
 404                                                                                                                                      ident = (ident << 8) | *p++;
 405                                                                  ilen--;
 406                                                                        }
 407                                                                                                                                      if (ident > pc->para.chargeinfo) {
 408                                                                                                                                      pc->para.chargeinfo = ident;
 409                                                                                                                                      st->l3.l3l4(st, CC_CHARGE | INDICATION, pc);
 410                                                                        }
 411                                                                                                                                      if (st->l3.debug & L3_DEB_CHARGE) {
 412                                                                                                                                      l3_debug(st, "charging info final %d", pc->para.chargeinfo);
 413                                                                        }
 414                                                                        }
 415                                                                   ))))))
 416                                                        break;
 417                                        default:
 418                                                       l3_debug(st, "invoke break invalid ident %02x",ident);
 419                                                break;
 420                                }
 421#undef FOO1
 422
 423                        }
 424#else  /* not HISAX_DE_AOC */
 425                        l3_debug(st, "invoke break");
 426#endif /* not HISAX_DE_AOC */
 427                        break;
 428                case 2: /* return result */
 429                         /* if no process available handle separately */ 
 430                        if (!pc)
 431                         { if (cr == -1) 
 432                             l3dss1_dummy_return_result(st, id, p, nlen);
 433                           return; 
 434                         }   
 435                        if ((pc->prot.dss1.invoke_id) && (pc->prot.dss1.invoke_id == id))
 436                          { /* Diversion successful */
 437                            free_invoke_id(st,pc->prot.dss1.invoke_id);
 438                            pc->prot.dss1.remote_result = 0; /* success */     
 439                            pc->prot.dss1.invoke_id = 0;
 440                            pc->redir_result = pc->prot.dss1.remote_result; 
 441                            st->l3.l3l4(st, CC_REDIR | INDICATION, pc);                                  } /* Diversion successful */
 442                        else
 443                          l3_debug(st,"return error unknown identifier");
 444                        break;
 445                case 3: /* return error */
 446                            err_ret = 0;
 447                            if (nlen < 2) 
 448                              { l3_debug(st, "return error nlen < 2");
 449                                return;
 450                              }
 451                            if (*p != 0x02) 
 452                              { /* result tag */
 453                                l3_debug(st, "invoke error tag !=0x02");
 454                                return;
 455                              }
 456                            p++;
 457                            nlen--;
 458                            if (*p > 4) 
 459                              { /* length format */
 460                                l3_debug(st, "invoke return errlen > 4 ");
 461                                return;
 462                              }
 463                            ilen = *p++;
 464                            nlen--;
 465                            if (ilen > nlen || ilen == 0) 
 466                              { l3_debug(st, "error return ilen > nlen || ilen == 0");
 467                                return;
 468                               }
 469                            nlen -= ilen;
 470                            while (ilen > 0) 
 471                             { err_ret = (err_ret << 8) | (*p++ & 0xFF);        /* error value */
 472                               ilen--;
 473                             }
 474                         /* if no process available handle separately */ 
 475                        if (!pc)
 476                         { if (cr == -1)
 477                             l3dss1_dummy_error_return(st, id, err_ret);
 478                           return; 
 479                         }   
 480                        if ((pc->prot.dss1.invoke_id) && (pc->prot.dss1.invoke_id == id))
 481                          { /* Deflection error */
 482                            free_invoke_id(st,pc->prot.dss1.invoke_id);
 483                            pc->prot.dss1.remote_result = err_ret; /* result */
 484                            pc->prot.dss1.invoke_id = 0; 
 485                            pc->redir_result = pc->prot.dss1.remote_result; 
 486                            st->l3.l3l4(st, CC_REDIR | INDICATION, pc);  
 487                          } /* Deflection error */
 488                        else
 489                          l3_debug(st,"return result unknown identifier");
 490                        break;
 491                default:
 492                        l3_debug(st, "facility default break tag=0x%02x",cp_tag);
 493                        break;
 494        }
 495}
 496
 497static void
 498l3dss1_message(struct l3_process *pc, u_char mt)
 499{
 500        struct sk_buff *skb;
 501        u_char *p;
 502
 503        if (!(skb = l3_alloc_skb(4)))
 504                return;
 505        p = skb_put(skb, 4);
 506        MsgHead(p, pc->callref, mt);
 507        l3_msg(pc->st, DL_DATA | REQUEST, skb);
 508}
 509
 510static void
 511l3dss1_message_cause(struct l3_process *pc, u_char mt, u_char cause)
 512{
 513        struct sk_buff *skb;
 514        u_char tmp[16];
 515        u_char *p = tmp;
 516        int l;
 517
 518        MsgHead(p, pc->callref, mt);
 519        *p++ = IE_CAUSE;
 520        *p++ = 0x2;
 521        *p++ = 0x80;
 522        *p++ = cause | 0x80;
 523
 524        l = p - tmp;
 525        if (!(skb = l3_alloc_skb(l)))
 526                return;
 527        memcpy(skb_put(skb, l), tmp, l);
 528        l3_msg(pc->st, DL_DATA | REQUEST, skb);
 529}
 530
 531static void
 532l3dss1_status_send(struct l3_process *pc, u_char pr, void *arg)
 533{
 534        u_char tmp[16];
 535        u_char *p = tmp;
 536        int l;
 537        struct sk_buff *skb;
 538
 539        MsgHead(p, pc->callref, MT_STATUS);
 540
 541        *p++ = IE_CAUSE;
 542        *p++ = 0x2;
 543        *p++ = 0x80;
 544        *p++ = pc->para.cause | 0x80;
 545
 546        *p++ = IE_CALL_STATE;
 547        *p++ = 0x1;
 548        *p++ = pc->state & 0x3f;
 549
 550        l = p - tmp;
 551        if (!(skb = l3_alloc_skb(l)))
 552                return;
 553        memcpy(skb_put(skb, l), tmp, l);
 554        l3_msg(pc->st, DL_DATA | REQUEST, skb);
 555}
 556
 557static void
 558l3dss1_msg_without_setup(struct l3_process *pc, u_char pr, void *arg)
 559{
 560        /* This routine is called if here was no SETUP made (checks in dss1up and in
 561         * l3dss1_setup) and a RELEASE_COMPLETE have to be sent with an error code
 562         * MT_STATUS_ENQUIRE in the NULL state is handled too
 563         */
 564        u_char tmp[16];
 565        u_char *p = tmp;
 566        int l;
 567        struct sk_buff *skb;
 568
 569        switch (pc->para.cause) {
 570                case 81:        /* invalid callreference */
 571                case 88:        /* incomp destination */
 572                case 96:        /* mandory IE missing */
 573                case 100:       /* invalid IE contents */
 574                case 101:       /* incompatible Callstate */
 575                        MsgHead(p, pc->callref, MT_RELEASE_COMPLETE);
 576                        *p++ = IE_CAUSE;
 577                        *p++ = 0x2;
 578                        *p++ = 0x80;
 579                        *p++ = pc->para.cause | 0x80;
 580                        break;
 581                default:
 582                        printk(KERN_ERR "HiSax l3dss1_msg_without_setup wrong cause %d\n",
 583                                pc->para.cause);
 584                        return;
 585        }
 586        l = p - tmp;
 587        if (!(skb = l3_alloc_skb(l)))
 588                return;
 589        memcpy(skb_put(skb, l), tmp, l);
 590        l3_msg(pc->st, DL_DATA | REQUEST, skb);
 591        dss1_release_l3_process(pc);
 592}
 593
 594static int ie_ALERTING[] = {IE_BEARER, IE_CHANNEL_ID | IE_MANDATORY_1,
 595                IE_FACILITY, IE_PROGRESS, IE_DISPLAY, IE_SIGNAL, IE_HLC,
 596                IE_USER_USER, -1};
 597static int ie_CALL_PROCEEDING[] = {IE_BEARER, IE_CHANNEL_ID | IE_MANDATORY_1,
 598                IE_FACILITY, IE_PROGRESS, IE_DISPLAY, IE_HLC, -1};
 599static int ie_CONNECT[] = {IE_BEARER, IE_CHANNEL_ID | IE_MANDATORY_1, 
 600                IE_FACILITY, IE_PROGRESS, IE_DISPLAY, IE_DATE, IE_SIGNAL,
 601                IE_CONNECT_PN, IE_CONNECT_SUB, IE_LLC, IE_HLC, IE_USER_USER, -1};
 602static int ie_CONNECT_ACKNOWLEDGE[] = {IE_CHANNEL_ID, IE_DISPLAY, IE_SIGNAL, -1};
 603static int ie_DISCONNECT[] = {IE_CAUSE | IE_MANDATORY, IE_FACILITY,
 604                IE_PROGRESS, IE_DISPLAY, IE_SIGNAL, IE_USER_USER, -1};
 605static int ie_INFORMATION[] = {IE_COMPLETE, IE_DISPLAY, IE_KEYPAD, IE_SIGNAL,
 606                IE_CALLED_PN, -1};
 607static int ie_NOTIFY[] = {IE_BEARER, IE_NOTIFY | IE_MANDATORY, IE_DISPLAY, -1};
 608static int ie_PROGRESS[] = {IE_BEARER, IE_CAUSE, IE_FACILITY, IE_PROGRESS |
 609                IE_MANDATORY, IE_DISPLAY, IE_HLC, IE_USER_USER, -1};
 610static int ie_RELEASE[] = {IE_CAUSE | IE_MANDATORY_1, IE_FACILITY, IE_DISPLAY,
 611                IE_SIGNAL, IE_USER_USER, -1};
 612/* a RELEASE_COMPLETE with errors don't require special actions 
 613static int ie_RELEASE_COMPLETE[] = {IE_CAUSE | IE_MANDATORY_1, IE_DISPLAY, IE_SIGNAL, IE_USER_USER, -1};
 614*/
 615static int ie_RESUME_ACKNOWLEDGE[] = {IE_CHANNEL_ID| IE_MANDATORY, IE_FACILITY,
 616                IE_DISPLAY, -1};
 617static int ie_RESUME_REJECT[] = {IE_CAUSE | IE_MANDATORY, IE_DISPLAY, -1};
 618static int ie_SETUP[] = {IE_COMPLETE, IE_BEARER  | IE_MANDATORY,
 619                IE_CHANNEL_ID| IE_MANDATORY, IE_FACILITY, IE_PROGRESS,
 620                IE_NET_FAC, IE_DISPLAY, IE_KEYPAD, IE_SIGNAL, IE_CALLING_PN,
 621                IE_CALLING_SUB, IE_CALLED_PN, IE_CALLED_SUB, IE_REDIR_NR,
 622                IE_LLC, IE_HLC, IE_USER_USER, -1};
 623static int ie_SETUP_ACKNOWLEDGE[] = {IE_CHANNEL_ID | IE_MANDATORY, IE_FACILITY,
 624                IE_PROGRESS, IE_DISPLAY, IE_SIGNAL, -1};
 625static int ie_STATUS[] = {IE_CAUSE | IE_MANDATORY, IE_CALL_STATE |
 626                IE_MANDATORY, IE_DISPLAY, -1};
 627static int ie_STATUS_ENQUIRY[] = {IE_DISPLAY, -1};
 628static int ie_SUSPEND_ACKNOWLEDGE[] = {IE_DISPLAY, IE_FACILITY, -1};
 629static int ie_SUSPEND_REJECT[] = {IE_CAUSE | IE_MANDATORY, IE_DISPLAY, -1};
 630/* not used 
 631 * static int ie_CONGESTION_CONTROL[] = {IE_CONGESTION | IE_MANDATORY,
 632 *              IE_CAUSE | IE_MANDATORY, IE_DISPLAY, -1};
 633 * static int ie_USER_INFORMATION[] = {IE_MORE_DATA, IE_USER_USER | IE_MANDATORY, -1};
 634 * static int ie_RESTART[] = {IE_CHANNEL_ID, IE_DISPLAY, IE_RESTART_IND |
 635 *              IE_MANDATORY, -1};
 636 */
 637static int ie_FACILITY[] = {IE_FACILITY | IE_MANDATORY, IE_DISPLAY, -1};
 638static int comp_required[] = {1,2,3,5,6,7,9,10,11,14,15,-1};
 639static int l3_valid_states[] = {0,1,2,3,4,6,7,8,9,10,11,12,15,17,19,25,-1};
 640
 641struct ie_len {
 642        int ie;
 643        int len;
 644};
 645
 646static
 647struct ie_len max_ie_len[] = {
 648        {IE_SEGMENT, 4},
 649        {IE_BEARER, 12},
 650        {IE_CAUSE, 32},
 651        {IE_CALL_ID, 10},
 652        {IE_CALL_STATE, 3},
 653        {IE_CHANNEL_ID, 34},
 654        {IE_FACILITY, 255},
 655        {IE_PROGRESS, 4},
 656        {IE_NET_FAC, 255},
 657        {IE_NOTIFY, 3},
 658        {IE_DISPLAY, 82},
 659        {IE_DATE, 8},
 660        {IE_KEYPAD, 34},
 661        {IE_SIGNAL, 3},
 662        {IE_INFORATE, 6},
 663        {IE_E2E_TDELAY, 11},
 664        {IE_TDELAY_SEL, 5},
 665        {IE_PACK_BINPARA, 3},
 666        {IE_PACK_WINSIZE, 4},
 667        {IE_PACK_SIZE, 4},
 668        {IE_CUG, 7},
 669        {IE_REV_CHARGE, 3},
 670        {IE_CALLING_PN, 24},
 671        {IE_CALLING_SUB, 23},
 672        {IE_CALLED_PN, 24},
 673        {IE_CALLED_SUB, 23},
 674        {IE_REDIR_NR, 255},
 675        {IE_TRANS_SEL, 255},
 676        {IE_RESTART_IND, 3},
 677        {IE_LLC, 18},
 678        {IE_HLC, 5},
 679        {IE_USER_USER, 131},
 680        {-1,0},
 681};
 682
 683static int
 684getmax_ie_len(u_char ie) {
 685        int i = 0;
 686        while (max_ie_len[i].ie != -1) {
 687                if (max_ie_len[i].ie == ie)
 688                        return(max_ie_len[i].len);
 689                i++;
 690        }
 691        return(255);
 692}
 693
 694static int
 695ie_in_set(struct l3_process *pc, u_char ie, int *checklist) {
 696        int ret = 1;
 697
 698        while (*checklist != -1) {
 699                if ((*checklist & 0xff) == ie) {
 700                        if (ie & 0x80)
 701                                return(-ret);
 702                        else
 703                                return(ret);
 704                }
 705                ret++;
 706                checklist++;
 707        }
 708        return(0);
 709}
 710
 711static int
 712check_infoelements(struct l3_process *pc, struct sk_buff *skb, int *checklist)
 713{
 714        int *cl = checklist;
 715        u_char mt;
 716        u_char *p, ie;
 717        int l, newpos, oldpos;
 718        int err_seq = 0, err_len = 0, err_compr = 0, err_ureg = 0;
 719        u_char codeset = 0;
 720        u_char old_codeset = 0;
 721        u_char codelock = 1;
 722        
 723        p = skb->data;
 724        /* skip cr */
 725        p++;
 726        l = (*p++) & 0xf;
 727        p += l;
 728        mt = *p++;
 729        oldpos = 0;
 730        while ((p - skb->data) < skb->len) {
 731                if ((*p & 0xf0) == 0x90) { /* shift codeset */
 732                        old_codeset = codeset;
 733                        codeset = *p & 7;
 734                        if (*p & 0x08)
 735                                codelock = 0;
 736                        else
 737                                codelock = 1;
 738                        if (pc->debug & L3_DEB_CHECK)
 739                                l3_debug(pc->st, "check IE shift%scodeset %d->%d",
 740                                        codelock ? " locking ": " ", old_codeset, codeset);
 741                        p++;
 742                        continue;
 743                }
 744                if (!codeset) { /* only codeset 0 */
 745                        if ((newpos = ie_in_set(pc, *p, cl))) {
 746                                if (newpos > 0) {
 747                                        if (newpos < oldpos)
 748                                                err_seq++;
 749                                        else
 750                                                oldpos = newpos;
 751                                }
 752                        } else {
 753                                if (ie_in_set(pc, *p, comp_required))
 754                                        err_compr++;
 755                                else
 756                                        err_ureg++;
 757                        }
 758                }
 759                ie = *p++;
 760                if (ie & 0x80) {
 761                        l = 1;
 762                } else {
 763                        l = *p++;
 764                        p += l;
 765                        l += 2;
 766                }
 767                if (!codeset && (l > getmax_ie_len(ie)))
 768                        err_len++;
 769                if (!codelock) {
 770                        if (pc->debug & L3_DEB_CHECK)
 771                                l3_debug(pc->st, "check IE shift back codeset %d->%d",
 772                                        codeset, old_codeset);
 773                        codeset = old_codeset;
 774                        codelock = 1;
 775                }
 776        }
 777        if (err_compr | err_ureg | err_len | err_seq) {
 778                if (pc->debug & L3_DEB_CHECK)
 779                        l3_debug(pc->st, "check IE MT(%x) %d/%d/%d/%d",
 780                                mt, err_compr, err_ureg, err_len, err_seq);
 781                if (err_compr)
 782                        return(ERR_IE_COMPREHENSION);
 783                if (err_ureg)
 784                        return(ERR_IE_UNRECOGNIZED);
 785                if (err_len)
 786                        return(ERR_IE_LENGTH);
 787                if (err_seq)
 788                        return(ERR_IE_SEQUENCE);
 789        } 
 790        return(0);
 791}
 792
 793/* verify if a message type exists and contain no IE error */
 794static int
 795l3dss1_check_messagetype_validity(struct l3_process *pc, int mt, void *arg)
 796{
 797        switch (mt) {
 798                case MT_ALERTING:
 799                case MT_CALL_PROCEEDING:
 800                case MT_CONNECT:
 801                case MT_CONNECT_ACKNOWLEDGE:
 802                case MT_DISCONNECT:
 803                case MT_INFORMATION:
 804                case MT_FACILITY:
 805                case MT_NOTIFY:
 806                case MT_PROGRESS:
 807                case MT_RELEASE:
 808                case MT_RELEASE_COMPLETE:
 809                case MT_SETUP:
 810                case MT_SETUP_ACKNOWLEDGE:
 811                case MT_RESUME_ACKNOWLEDGE:
 812                case MT_RESUME_REJECT:
 813                case MT_SUSPEND_ACKNOWLEDGE:
 814                case MT_SUSPEND_REJECT:
 815                case MT_USER_INFORMATION:
 816                case MT_RESTART:
 817                case MT_RESTART_ACKNOWLEDGE:
 818                case MT_CONGESTION_CONTROL:
 819                case MT_STATUS:
 820                case MT_STATUS_ENQUIRY:
 821                        if (pc->debug & L3_DEB_CHECK)
 822                                l3_debug(pc->st, "l3dss1_check_messagetype_validity mt(%x) OK", mt);
 823                        break;
 824                case MT_RESUME: /* RESUME only in user->net */
 825                case MT_SUSPEND: /* SUSPEND only in user->net */
 826                default:
 827                        if (pc->debug & (L3_DEB_CHECK | L3_DEB_WARN))
 828                                l3_debug(pc->st, "l3dss1_check_messagetype_validity mt(%x) fail", mt);
 829                        pc->para.cause = 97;
 830                        l3dss1_status_send(pc, 0, NULL);
 831                        return(1);
 832        }
 833        return(0);
 834}
 835
 836static void
 837l3dss1_std_ie_err(struct l3_process *pc, int ret) {
 838
 839        if (pc->debug & L3_DEB_CHECK)
 840                l3_debug(pc->st, "check_infoelements ret %d", ret);
 841        switch(ret) {
 842                case 0: 
 843                        break;
 844                case ERR_IE_COMPREHENSION:
 845                        pc->para.cause = 96;
 846                        l3dss1_status_send(pc, 0, NULL);
 847                        break;
 848                case ERR_IE_UNRECOGNIZED:
 849                        pc->para.cause = 99;
 850                        l3dss1_status_send(pc, 0, NULL);
 851                        break;
 852                case ERR_IE_LENGTH:
 853                        pc->para.cause = 100;
 854                        l3dss1_status_send(pc, 0, NULL);
 855                        break;
 856                case ERR_IE_SEQUENCE:
 857                default:
 858                        break;
 859        }
 860}
 861
 862static int
 863l3dss1_get_channel_id(struct l3_process *pc, struct sk_buff *skb) {
 864        u_char *p;
 865
 866        p = skb->data;
 867        if ((p = findie(p, skb->len, IE_CHANNEL_ID, 0))) {
 868                p++;
 869                if (*p != 1) { /* len for BRI = 1 */
 870                        if (pc->debug & L3_DEB_WARN)
 871                                l3_debug(pc->st, "wrong chid len %d", *p);
 872                        return (-2);
 873                }
 874                p++;
 875                if (*p & 0x60) { /* only base rate interface */
 876                        if (pc->debug & L3_DEB_WARN)
 877                                l3_debug(pc->st, "wrong chid %x", *p);
 878                        return (-3);
 879                }
 880                return(*p & 0x3);
 881        } else
 882                return(-1);
 883}
 884
 885static int
 886l3dss1_get_cause(struct l3_process *pc, struct sk_buff *skb) {
 887        u_char l, i=0;
 888        u_char *p;
 889
 890        p = skb->data;
 891        pc->para.cause = 31;
 892        pc->para.loc = 0;
 893        if ((p = findie(p, skb->len, IE_CAUSE, 0))) {
 894                p++;
 895                l = *p++;
 896                if (l>30)
 897                        return(1);
 898                if (l) {
 899                        pc->para.loc = *p++;
 900                        l--;
 901                } else {
 902                        return(2);
 903                }
 904                if (l && !(pc->para.loc & 0x80)) {
 905                        l--;
 906                        p++; /* skip recommendation */
 907                }
 908                if (l) {
 909                        pc->para.cause = *p++;
 910                        l--;
 911                        if (!(pc->para.cause & 0x80))
 912                                return(3);
 913                } else
 914                        return(4);
 915                while (l && (i<6)) {
 916                        pc->para.diag[i++] = *p++;
 917                        l--;
 918                }
 919        } else
 920                return(-1);
 921        return(0);
 922}
 923
 924static void
 925l3dss1_msg_with_uus(struct l3_process *pc, u_char cmd)
 926{
 927        struct sk_buff *skb;
 928        u_char tmp[16+40];
 929        u_char *p = tmp;
 930        int l;
 931
 932        MsgHead(p, pc->callref, cmd);
 933
 934        if (pc->prot.dss1.uus1_data[0])
 935         { *p++ = IE_USER_USER; /* UUS info element */
 936           *p++ = strlen(pc->prot.dss1.uus1_data) + 1;
 937           *p++ = 0x04; /* IA5 chars */
 938           strcpy(p,pc->prot.dss1.uus1_data);
 939           p += strlen(pc->prot.dss1.uus1_data);
 940           pc->prot.dss1.uus1_data[0] = '\0';   
 941         } 
 942
 943        l = p - tmp;
 944        if (!(skb = l3_alloc_skb(l)))
 945                return;
 946        memcpy(skb_put(skb, l), tmp, l);
 947        l3_msg(pc->st, DL_DATA | REQUEST, skb);
 948} /* l3dss1_msg_with_uus */
 949
 950static void
 951l3dss1_release_req(struct l3_process *pc, u_char pr, void *arg)
 952{
 953        StopAllL3Timer(pc);
 954        newl3state(pc, 19);
 955        if (!pc->prot.dss1.uus1_data[0]) 
 956                l3dss1_message(pc, MT_RELEASE);
 957        else
 958                l3dss1_msg_with_uus(pc, MT_RELEASE);
 959        L3AddTimer(&pc->timer, T308, CC_T308_1);
 960}
 961
 962static void
 963l3dss1_release_cmpl(struct l3_process *pc, u_char pr, void *arg)
 964{
 965        struct sk_buff *skb = arg;
 966        int ret;
 967
 968        if ((ret = l3dss1_get_cause(pc, skb))>0) {
 969                if (pc->debug & L3_DEB_WARN)
 970                        l3_debug(pc->st, "RELCMPL get_cause ret(%d)",ret);
 971        } else if (ret < 0)
 972                pc->para.cause = NO_CAUSE;
 973        StopAllL3Timer(pc);
 974        newl3state(pc, 0);
 975        pc->st->l3.l3l4(pc->st, CC_RELEASE | CONFIRM, pc);
 976        dss1_release_l3_process(pc);
 977}
 978
 979#ifdef EXT_BEARER_CAPS
 980
 981static u_char *
 982EncodeASyncParams(u_char * p, u_char si2)
 983{                               // 7c 06 88  90 21 42 00 bb
 984
 985        p[0] = 0;
 986        p[1] = 0x40;            // Intermediate rate: 16 kbit/s jj 2000.02.19
 987        p[2] = 0x80;
 988        if (si2 & 32)           // 7 data bits
 989
 990                p[2] += 16;
 991        else                    // 8 data bits
 992
 993                p[2] += 24;
 994
 995        if (si2 & 16)           // 2 stop bits
 996
 997                p[2] += 96;
 998        else                    // 1 stop bit
 999
1000                p[2] += 32;
1001
1002        if (si2 & 8)            // even parity
1003
1004                p[2] += 2;
1005        else                    // no parity
1006
1007                p[2] += 3;
1008
1009        switch (si2 & 0x07) {
1010                case 0:
1011                        p[0] = 66;      // 1200 bit/s
1012
1013                        break;
1014                case 1:
1015                        p[0] = 88;      // 1200/75 bit/s
1016
1017                        break;
1018                case 2:
1019                        p[0] = 87;      // 75/1200 bit/s
1020
1021                        break;
1022                case 3:
1023                        p[0] = 67;      // 2400 bit/s
1024
1025                        break;
1026                case 4:
1027                        p[0] = 69;      // 4800 bit/s
1028
1029                        break;
1030                case 5:
1031                        p[0] = 72;      // 9600 bit/s
1032
1033                        break;
1034                case 6:
1035                        p[0] = 73;      // 14400 bit/s
1036
1037                        break;
1038                case 7:
1039                        p[0] = 75;      // 19200 bit/s
1040
1041                        break;
1042        }
1043        return p + 3;
1044}
1045
1046static  u_char
1047EncodeSyncParams(u_char si2, u_char ai)
1048{
1049
1050        switch (si2) {
1051                case 0:
1052                        return ai + 2;  // 1200 bit/s
1053
1054                case 1:
1055                        return ai + 24;         // 1200/75 bit/s
1056
1057                case 2:
1058                        return ai + 23;         // 75/1200 bit/s
1059
1060                case 3:
1061                        return ai + 3;  // 2400 bit/s
1062
1063                case 4:
1064                        return ai + 5;  // 4800 bit/s
1065
1066                case 5:
1067                        return ai + 8;  // 9600 bit/s
1068
1069                case 6:
1070                        return ai + 9;  // 14400 bit/s
1071
1072                case 7:
1073                        return ai + 11;         // 19200 bit/s
1074
1075                case 8:
1076                        return ai + 14;         // 48000 bit/s
1077
1078                case 9:
1079                        return ai + 15;         // 56000 bit/s
1080
1081                case 15:
1082                        return ai + 40;         // negotiate bit/s
1083
1084                default:
1085                        break;
1086        }
1087        return ai;
1088}
1089
1090
1091static u_char
1092DecodeASyncParams(u_char si2, u_char * p)
1093{
1094        u_char info;
1095
1096        switch (p[5]) {
1097                case 66:        // 1200 bit/s
1098
1099                        break;  // si2 don't change
1100
1101                case 88:        // 1200/75 bit/s
1102
1103                        si2 += 1;
1104                        break;
1105                case 87:        // 75/1200 bit/s
1106
1107                        si2 += 2;
1108                        break;
1109                case 67:        // 2400 bit/s
1110
1111                        si2 += 3;
1112                        break;
1113                case 69:        // 4800 bit/s
1114
1115                        si2 += 4;
1116                        break;
1117                case 72:        // 9600 bit/s
1118
1119                        si2 += 5;
1120                        break;
1121                case 73:        // 14400 bit/s
1122
1123                        si2 += 6;
1124                        break;
1125                case 75:        // 19200 bit/s
1126
1127                        si2 += 7;
1128                        break;
1129        }
1130
1131        info = p[7] & 0x7f;
1132        if ((info & 16) && (!(info & 8)))       // 7 data bits
1133
1134                si2 += 32;      // else 8 data bits
1135
1136        if ((info & 96) == 96)  // 2 stop bits
1137
1138                si2 += 16;      // else 1 stop bit
1139
1140        if ((info & 2) && (!(info & 1)))        // even parity
1141
1142                si2 += 8;       // else no parity
1143
1144        return si2;
1145}
1146
1147
1148static u_char
1149DecodeSyncParams(u_char si2, u_char info)
1150{
1151        info &= 0x7f;
1152        switch (info) {
1153                case 40:        // bit/s negotiation failed  ai := 165 not 175!
1154
1155                        return si2 + 15;
1156                case 15:        // 56000 bit/s failed, ai := 0 not 169 !
1157
1158                        return si2 + 9;
1159                case 14:        // 48000 bit/s
1160
1161                        return si2 + 8;
1162                case 11:        // 19200 bit/s
1163
1164                        return si2 + 7;
1165                case 9: // 14400 bit/s
1166
1167                        return si2 + 6;
1168                case 8: // 9600  bit/s
1169
1170                        return si2 + 5;
1171                case 5: // 4800  bit/s
1172
1173                        return si2 + 4;
1174                case 3: // 2400  bit/s
1175
1176                        return si2 + 3;
1177                case 23:        // 75/1200 bit/s
1178
1179                        return si2 + 2;
1180                case 24:        // 1200/75 bit/s
1181
1182                        return si2 + 1;
1183                default:        // 1200 bit/s
1184
1185                        return si2;
1186        }
1187}
1188
1189static u_char
1190DecodeSI2(struct sk_buff *skb)
1191{
1192        u_char *p;              //, *pend=skb->data + skb->len;
1193
1194        if ((p = findie(skb->data, skb->len, 0x7c, 0))) {
1195                switch (p[4] & 0x0f) {
1196                        case 0x01:
1197                                if (p[1] == 0x04)       // sync. Bitratenadaption
1198
1199                                        return DecodeSyncParams(160, p[5]);     // V.110/X.30
1200
1201                                else if (p[1] == 0x06)  // async. Bitratenadaption
1202
1203                                        return DecodeASyncParams(192, p);       // V.110/X.30
1204
1205                                break;
1206                        case 0x08:      // if (p[5] == 0x02) // sync. Bitratenadaption
1207                                if (p[1] > 3) 
1208                                        return DecodeSyncParams(176, p[5]);     // V.120
1209                                break;
1210                }
1211        }
1212        return 0;
1213}
1214
1215#endif
1216
1217
1218static void
1219l3dss1_setup_req(struct l3_process *pc, u_char pr,
1220                 void *arg)
1221{
1222        struct sk_buff *skb;
1223        u_char tmp[128];
1224        u_char *p = tmp;
1225        u_char channel = 0;
1226
1227        u_char send_keypad;
1228        u_char screen = 0x80;
1229        u_char *teln;
1230        u_char *msn;
1231        u_char *sub;
1232        u_char *sp;
1233        int l;
1234
1235        MsgHead(p, pc->callref, MT_SETUP);
1236
1237        teln = pc->para.setup.phone;
1238#ifndef CONFIG_HISAX_NO_KEYPAD
1239        send_keypad = (strchr(teln,'*') || strchr(teln,'#')) ? 1 : 0; 
1240#else
1241        send_keypad = 0;
1242#endif
1243#ifndef CONFIG_HISAX_NO_SENDCOMPLETE
1244        if (!send_keypad)
1245                *p++ = 0xa1;            /* complete indicator */
1246#endif
1247        /*
1248         * Set Bearer Capability, Map info from 1TR6-convention to EDSS1
1249         */
1250        switch (pc->para.setup.si1) {
1251        case 1:                   /* Telephony                                */
1252                *p++ = IE_BEARER;
1253                *p++ = 0x3;       /* Length                                   */
1254                *p++ = 0x90;      /* Coding Std. CCITT, 3.1 kHz audio         */
1255                *p++ = 0x90;      /* Circuit-Mode 64kbps                      */
1256                *p++ = 0xa3;      /* A-Law Audio                              */
1257                break;
1258        case 5:                   /* Datatransmission 64k, BTX                */
1259        case 7:                   /* Datatransmission 64k                     */
1260        default:
1261                *p++ = IE_BEARER;
1262                *p++ = 0x2;       /* Length                                   */
1263                *p++ = 0x88;      /* Coding Std. CCITT, unrestr. dig. Inform. */
1264                *p++ = 0x90;      /* Circuit-Mode 64kbps                      */
1265                break;
1266        }
1267
1268        if (send_keypad) {
1269                *p++ = IE_KEYPAD;
1270                *p++ = strlen(teln);
1271                while (*teln)
1272                        *p++ = (*teln++) & 0x7F;
1273        }
1274          
1275        /*
1276         * What about info2? Mapping to High-Layer-Compatibility?
1277         */
1278        if ((*teln) && (!send_keypad)) {
1279                /* parse number for special things */
1280                if (!isdigit(*teln)) {
1281                        switch (0x5f & *teln) {
1282                                case 'C':
1283                                        channel = 0x08;
1284                                case 'P':
1285                                        channel |= 0x80;
1286                                        teln++;
1287                                        if (*teln == '1')
1288                                                channel |= 0x01;
1289                                        else
1290                                                channel |= 0x02;
1291                                        break;
1292                                case 'R':
1293                                        screen = 0xA0;
1294                                        break;
1295                                case 'D':
1296                                        screen = 0x80;
1297                                        break;
1298                                
1299                                default:
1300                                        if (pc->debug & L3_DEB_WARN)
1301                                                l3_debug(pc->st, "Wrong MSN Code");
1302                                        break;
1303                        }
1304                        teln++;
1305                }
1306        }
1307        if (channel) {
1308                *p++ = IE_CHANNEL_ID;
1309                *p++ = 1;
1310                *p++ = channel;
1311        }
1312        msn = pc->para.setup.eazmsn;
1313        sub = NULL;
1314        sp = msn;
1315        while (*sp) {
1316                if ('.' == *sp) {
1317                        sub = sp;
1318                        *sp = 0;
1319                } else
1320                        sp++;
1321        }
1322        if (*msn) {
1323                *p++ = IE_CALLING_PN;
1324                *p++ = strlen(msn) + (screen ? 2 : 1);
1325                /* Classify as AnyPref. */
1326                if (screen) {
1327                        *p++ = 0x01;    /* Ext = '0'B, Type = '000'B, Plan = '0001'B. */
1328                        *p++ = screen;
1329                } else
1330                        *p++ = 0x81;    /* Ext = '1'B, Type = '000'B, Plan = '0001'B. */
1331                while (*msn)
1332                        *p++ = *msn++ & 0x7f;
1333        }
1334        if (sub) {
1335                *sub++ = '.';
1336                *p++ = IE_CALLING_SUB;
1337                *p++ = strlen(sub) + 2;
1338                *p++ = 0x80;    /* NSAP coded */
1339                *p++ = 0x50;    /* local IDI format */
1340                while (*sub)
1341                        *p++ = *sub++ & 0x7f;
1342        }
1343        sub = NULL;
1344        sp = teln;
1345        while (*sp) {
1346                if ('.' == *sp) {
1347                        sub = sp;
1348                        *sp = 0;
1349                } else
1350                        sp++;
1351        }
1352        
1353        if (!send_keypad) {      
1354                *p++ = IE_CALLED_PN;
1355                *p++ = strlen(teln) + 1;
1356                /* Classify as AnyPref. */
1357                *p++ = 0x81;            /* Ext = '1'B, Type = '000'B, Plan = '0001'B. */
1358                while (*teln)
1359                        *p++ = *teln++ & 0x7f;
1360                
1361                if (sub) {
1362                        *sub++ = '.';
1363                        *p++ = IE_CALLED_SUB;
1364                        *p++ = strlen(sub) + 2;
1365                        *p++ = 0x80;    /* NSAP coded */
1366                        *p++ = 0x50;    /* local IDI format */
1367                        while (*sub)
1368                                *p++ = *sub++ & 0x7f;
1369                }
1370        }
1371#ifdef EXT_BEARER_CAPS
1372        if ((pc->para.setup.si2 >= 160) && (pc->para.setup.si2 <= 175)) {       // sync. Bitratenadaption, V.110/X.30
1373
1374                *p++ = IE_LLC;
1375                *p++ = 0x04;
1376                *p++ = 0x88;
1377                *p++ = 0x90;
1378                *p++ = 0x21;
1379                *p++ = EncodeSyncParams(pc->para.setup.si2 - 160, 0x80);
1380        } else if ((pc->para.setup.si2 >= 176) && (pc->para.setup.si2 <= 191)) {        // sync. Bitratenadaption, V.120
1381
1382                *p++ = IE_LLC;
1383                *p++ = 0x05;
1384                *p++ = 0x88;
1385                *p++ = 0x90;
1386                *p++ = 0x28;
1387                *p++ = EncodeSyncParams(pc->para.setup.si2 - 176, 0);
1388                *p++ = 0x82;
1389        } else if (pc->para.setup.si2 >= 192) {         // async. Bitratenadaption, V.110/X.30
1390
1391                *p++ = IE_LLC;
1392                *p++ = 0x06;
1393                *p++ = 0x88;
1394                *p++ = 0x90;
1395                *p++ = 0x21;
1396                p = EncodeASyncParams(p, pc->para.setup.si2 - 192);
1397#ifndef CONFIG_HISAX_NO_LLC
1398        } else {
1399          switch (pc->para.setup.si1) {
1400                case 1:                 /* Telephony                                */
1401                        *p++ = IE_LLC;
1402                        *p++ = 0x3;     /* Length                                   */
1403                        *p++ = 0x90;    /* Coding Std. CCITT, 3.1 kHz audio         */
1404                        *p++ = 0x90;    /* Circuit-Mode 64kbps                      */
1405                        *p++ = 0xa3;    /* A-Law Audio                              */
1406                        break;
1407                case 5:                 /* Datatransmission 64k, BTX                */
1408                case 7:                 /* Datatransmission 64k                     */
1409                default:
1410                        *p++ = IE_LLC;
1411                        *p++ = 0x2;     /* Length                                   */
1412                        *p++ = 0x88;    /* Coding Std. CCITT, unrestr. dig. Inform. */
1413                        *p++ = 0x90;    /* Circuit-Mode 64kbps                      */
1414                        break;
1415          }
1416#endif
1417        }
1418#endif
1419        l = p - tmp;
1420        if (!(skb = l3_alloc_skb(l)))
1421                return;
1422        memcpy(skb_put(skb, l), tmp, l);
1423        L3DelTimer(&pc->timer);
1424        L3AddTimer(&pc->timer, T303, CC_T303);
1425        newl3state(pc, 1);
1426        l3_msg(pc->st, DL_DATA | REQUEST, skb);
1427}
1428
1429static void
1430l3dss1_call_proc(struct l3_process *pc, u_char pr, void *arg)
1431{
1432        struct sk_buff *skb = arg;
1433        int id, ret;
1434
1435        if ((id = l3dss1_get_channel_id(pc, skb)) >= 0) {
1436                if ((0 == id) || ((3 == id) && (0x10 == pc->para.moderate))) {
1437                        if (pc->debug & L3_DEB_WARN)
1438                                l3_debug(pc->st, "setup answer with wrong chid %x", id);
1439                        pc->para.cause = 100;
1440                        l3dss1_status_send(pc, pr, NULL);
1441                        return;
1442                }
1443                pc->para.bchannel = id;
1444        } else if (1 == pc->state) {
1445                if (pc->debug & L3_DEB_WARN)
1446                        l3_debug(pc->st, "setup answer wrong chid (ret %d)", id);
1447                if (id == -1)
1448                        pc->para.cause = 96;
1449                else
1450                        pc->para.cause = 100;
1451                l3dss1_status_send(pc, pr, NULL);
1452                return;
1453        }
1454        /* Now we are on none mandatory IEs */
1455        ret = check_infoelements(pc, skb, ie_CALL_PROCEEDING);
1456        if (ERR_IE_COMPREHENSION == ret) {
1457                l3dss1_std_ie_err(pc, ret);
1458                return;
1459        }
1460        L3DelTimer(&pc->timer);
1461        newl3state(pc, 3);
1462        L3AddTimer(&pc->timer, T310, CC_T310);
1463        if (ret) /* STATUS for none mandatory IE errors after actions are taken */
1464                l3dss1_std_ie_err(pc, ret);
1465        pc->st->l3.l3l4(pc->st, CC_PROCEEDING | INDICATION, pc);
1466}
1467
1468static void
1469l3dss1_setup_ack(struct l3_process *pc, u_char pr, void *arg)
1470{
1471        struct sk_buff *skb = arg;
1472        int id, ret;
1473
1474        if ((id = l3dss1_get_channel_id(pc, skb)) >= 0) {
1475                if ((0 == id) || ((3 == id) && (0x10 == pc->para.moderate))) {
1476                        if (pc->debug & L3_DEB_WARN)
1477                                l3_debug(pc->st, "setup answer with wrong chid %x", id);
1478                        pc->para.cause = 100;
1479                        l3dss1_status_send(pc, pr, NULL);
1480                        return;
1481                }
1482                pc->para.bchannel = id;
1483        } else {
1484                if (pc->debug & L3_DEB_WARN)
1485                        l3_debug(pc->st, "setup answer wrong chid (ret %d)", id);
1486                if (id == -1)
1487                        pc->para.cause = 96;
1488                else
1489                        pc->para.cause = 100;
1490                l3dss1_status_send(pc, pr, NULL);
1491                return;
1492        }
1493        /* Now we are on none mandatory IEs */
1494        ret = check_infoelements(pc, skb, ie_SETUP_ACKNOWLEDGE);
1495        if (ERR_IE_COMPREHENSION == ret) {
1496                l3dss1_std_ie_err(pc, ret);
1497                return;
1498        }
1499        L3DelTimer(&pc->timer);
1500        newl3state(pc, 2);
1501        L3AddTimer(&pc->timer, T304, CC_T304);
1502        if (ret) /* STATUS for none mandatory IE errors after actions are taken */
1503                l3dss1_std_ie_err(pc, ret);
1504        pc->st->l3.l3l4(pc->st, CC_MORE_INFO | INDICATION, pc);
1505}
1506
1507static void
1508l3dss1_disconnect(struct l3_process *pc, u_char pr, void *arg)
1509{
1510        struct sk_buff *skb = arg;
1511        u_char *p;
1512        int ret;
1513        u_char cause = 0;
1514
1515        StopAllL3Timer(pc);
1516        if ((ret = l3dss1_get_cause(pc, skb))) {
1517                if (pc->debug & L3_DEB_WARN)
1518                        l3_debug(pc->st, "DISC get_cause ret(%d)", ret);
1519                if (ret < 0)
1520                        cause = 96;
1521                else if (ret > 0)
1522                        cause = 100;
1523        } 
1524        if ((p = findie(skb->data, skb->len, IE_FACILITY, 0)))
1525                l3dss1_parse_facility(pc->st, pc, pc->callref, p);
1526        ret = check_infoelements(pc, skb, ie_DISCONNECT);
1527        if (ERR_IE_COMPREHENSION == ret)
1528                cause = 96;
1529        else if ((!cause) && (ERR_IE_UNRECOGNIZED == ret))
1530                cause = 99;
1531        ret = pc->state;
1532        newl3state(pc, 12);
1533        if (cause)
1534                newl3state(pc, 19);
1535        if (11 != ret)
1536                pc->st->l3.l3l4(pc->st, CC_DISCONNECT | INDICATION, pc);
1537        else if (!cause)
1538                   l3dss1_release_req(pc, pr, NULL);
1539        if (cause) {
1540                l3dss1_message_cause(pc, MT_RELEASE, cause);
1541                L3AddTimer(&pc->timer, T308, CC_T308_1);
1542        }
1543}
1544
1545static void
1546l3dss1_connect(struct l3_process *pc, u_char pr, void *arg)
1547{
1548        struct sk_buff *skb = arg;
1549        int ret;
1550
1551        ret = check_infoelements(pc, skb, ie_CONNECT);
1552        if (ERR_IE_COMPREHENSION == ret) {
1553                l3dss1_std_ie_err(pc, ret);
1554                return;
1555        }
1556        L3DelTimer(&pc->timer); /* T310 */
1557        newl3state(pc, 10);
1558        pc->para.chargeinfo = 0;
1559        /* here should inserted COLP handling KKe */
1560        if (ret)
1561                l3dss1_std_ie_err(pc, ret);
1562        pc->st->l3.l3l4(pc->st, CC_SETUP | CONFIRM, pc);
1563}
1564
1565static void
1566l3dss1_alerting(struct l3_process *pc, u_char pr, void *arg)
1567{
1568        struct sk_buff *skb = arg;
1569        int ret;
1570
1571        ret = check_infoelements(pc, skb, ie_ALERTING);
1572        if (ERR_IE_COMPREHENSION == ret) {
1573                l3dss1_std_ie_err(pc, ret);
1574                return;
1575        }
1576        L3DelTimer(&pc->timer); /* T304 */
1577        newl3state(pc, 4);
1578        if (ret)
1579                l3dss1_std_ie_err(pc, ret);
1580        pc->st->l3.l3l4(pc->st, CC_ALERTING | INDICATION, pc);
1581}
1582
1583static void
1584l3dss1_setup(struct l3_process *pc, u_char pr, void *arg)
1585{
1586        u_char *p;
1587        int bcfound = 0;
1588        char tmp[80];
1589        struct sk_buff *skb = arg;
1590        int id;
1591        int err = 0;
1592
1593        /*
1594         * Bearer Capabilities
1595         */
1596        p = skb->data;
1597        /* only the first occurence 'll be detected ! */
1598        if ((p = findie(p, skb->len, 0x04, 0))) {
1599                if ((p[1] < 2) || (p[1] > 11))
1600                        err = 1;
1601                else {
1602                        pc->para.setup.si2 = 0;
1603                        switch (p[2] & 0x7f) {
1604                                case 0x00: /* Speech */
1605                                case 0x10: /* 3.1 Khz audio */
1606                                        pc->para.setup.si1 = 1;
1607                                        break;
1608                                case 0x08: /* Unrestricted digital information */
1609                                        pc->para.setup.si1 = 7;
1610/* JIM, 05.11.97 I wanna set service indicator 2 */
1611#ifdef EXT_BEARER_CAPS
1612                                        pc->para.setup.si2 = DecodeSI2(skb);
1613#endif
1614                                        break;
1615                                case 0x09: /* Restricted digital information */
1616                                        pc->para.setup.si1 = 2;
1617                                        break;
1618                                case 0x11:
1619                                        /* Unrestr. digital information  with 
1620                                         * tones/announcements ( or 7 kHz audio
1621                                         */
1622                                        pc->para.setup.si1 = 3;
1623                                        break;
1624                                case 0x18: /* Video */
1625                                        pc->para.setup.si1 = 4;
1626                                        break;
1627                                default:
1628                                        err = 2;
1629                                        break;
1630                        }
1631                        switch (p[3] & 0x7f) {
1632                                case 0x40: /* packed mode */
1633                                        pc->para.setup.si1 = 8;
1634                                        break;
1635                                case 0x10: /* 64 kbit */
1636                                case 0x11: /* 2*64 kbit */
1637                                case 0x13: /* 384 kbit */
1638                                case 0x15: /* 1536 kbit */
1639                                case 0x17: /* 1920 kbit */
1640                                        pc->para.moderate = p[3] & 0x7f;
1641                                        break;
1642                                default:
1643                                        err = 3;
1644                                        break;
1645                        }
1646                }
1647                if (pc->debug & L3_DEB_SI)
1648                        l3_debug(pc->st, "SI=%d, AI=%d",
1649                                pc->para.setup.si1, pc->para.setup.si2);
1650                if (err) {
1651                        if (pc->debug & L3_DEB_WARN)
1652                                l3_debug(pc->st, "setup with wrong bearer(l=%d:%x,%x)",
1653                                        p[1], p[2], p[3]);
1654                        pc->para.cause = 100;
1655                        l3dss1_msg_without_setup(pc, pr, NULL);
1656                        return;
1657                }
1658        } else {
1659                if (pc->debug & L3_DEB_WARN)
1660                        l3_debug(pc->st, "setup without bearer capabilities");
1661                /* ETS 300-104 1.3.3 */
1662                pc->para.cause = 96;
1663                l3dss1_msg_without_setup(pc, pr, NULL);
1664                return;
1665        }
1666        /*
1667         * Channel Identification
1668         */
1669        if ((id = l3dss1_get_channel_id(pc, skb)) >= 0) {
1670                if ((pc->para.bchannel = id)) {
1671                        if ((3 == id) && (0x10 == pc->para.moderate)) {
1672                                if (pc->debug & L3_DEB_WARN)
1673                                        l3_debug(pc->st, "setup with wrong chid %x",
1674                                                id);
1675                                pc->para.cause = 100;
1676                                l3dss1_msg_without_setup(pc, pr, NULL);
1677                                return;
1678                        }
1679                        bcfound++;
1680                } else 
1681                   { if (pc->debug & L3_DEB_WARN)
1682                         l3_debug(pc->st, "setup without bchannel, call waiting");
1683                     bcfound++;
1684                   } 
1685        } else {
1686                if (pc->debug & L3_DEB_WARN)
1687                        l3_debug(pc->st, "setup with wrong chid ret %d", id);
1688                if (id == -1)
1689                        pc->para.cause = 96;
1690                else
1691                        pc->para.cause = 100;
1692                l3dss1_msg_without_setup(pc, pr, NULL);
1693                return;
1694        }
1695        /* Now we are on none mandatory IEs */
1696        err = check_infoelements(pc, skb, ie_SETUP);
1697        if (ERR_IE_COMPREHENSION == err) {
1698                pc->para.cause = 96;
1699                l3dss1_msg_without_setup(pc, pr, NULL);
1700                return;
1701        }
1702        p = skb->data;
1703        if ((p = findie(p, skb->len, 0x70, 0)))
1704                iecpy(pc->para.setup.eazmsn, p, 1);
1705        else
1706                pc->para.setup.eazmsn[0] = 0;
1707
1708        p = skb->data;
1709        if ((p = findie(p, skb->len, 0x71, 0))) {
1710                /* Called party subaddress */
1711                if ((p[1] >= 2) && (p[2] == 0x80) && (p[3] == 0x50)) {
1712                        tmp[0] = '.';
1713                        iecpy(&tmp[1], p, 2);
1714                        strcat(pc->para.setup.eazmsn, tmp);
1715                } else if (pc->debug & L3_DEB_WARN)
1716                        l3_debug(pc->st, "wrong called subaddress");
1717        }
1718        p = skb->data;
1719        if ((p = findie(p, skb->len, 0x6c, 0))) {
1720                pc->para.setup.plan = p[2];
1721                if (p[2] & 0x80) {
1722                        iecpy(pc->para.setup.phone, p, 1);
1723                        pc->para.setup.screen = 0;
1724                } else {
1725                        iecpy(pc->para.setup.phone, p, 2);
1726                        pc->para.setup.screen = p[3];
1727                }
1728        } else {
1729                pc->para.setup.phone[0] = 0;
1730                pc->para.setup.plan = 0;
1731                pc->para.setup.screen = 0;
1732        }
1733        p = skb->data;
1734        if ((p = findie(p, skb->len, 0x6d, 0))) {
1735                /* Calling party subaddress */
1736                if ((p[1] >= 2) && (p[2] == 0x80) && (p[3] == 0x50)) {
1737                        tmp[0] = '.';
1738                        iecpy(&tmp[1], p, 2);
1739                        strcat(pc->para.setup.phone, tmp);
1740                } else if (pc->debug & L3_DEB_WARN)
1741                        l3_debug(pc->st, "wrong calling subaddress");
1742        }
1743        newl3state(pc, 6);
1744        if (err) /* STATUS for none mandatory IE errors after actions are taken */
1745                l3dss1_std_ie_err(pc, err);
1746        pc->st->l3.l3l4(pc->st, CC_SETUP | INDICATION, pc);
1747}
1748
1749static void
1750l3dss1_reset(struct l3_process *pc, u_char pr, void *arg)
1751{
1752        dss1_release_l3_process(pc);
1753}
1754
1755static void
1756l3dss1_disconnect_req(struct l3_process *pc, u_char pr, void *arg)
1757{
1758        struct sk_buff *skb;
1759        u_char tmp[16+40];
1760        u_char *p = tmp;
1761        int l;
1762        u_char cause = 16;
1763
1764        if (pc->para.cause != NO_CAUSE)
1765                cause = pc->para.cause;
1766
1767        StopAllL3Timer(pc);
1768
1769        MsgHead(p, pc->callref, MT_DISCONNECT);
1770
1771        *p++ = IE_CAUSE;
1772        *p++ = 0x2;
1773        *p++ = 0x80;
1774        *p++ = cause | 0x80;
1775
1776        if (pc->prot.dss1.uus1_data[0])
1777         { *p++ = IE_USER_USER; /* UUS info element */
1778           *p++ = strlen(pc->prot.dss1.uus1_data) + 1;
1779           *p++ = 0x04; /* IA5 chars */
1780           strcpy(p,pc->prot.dss1.uus1_data);
1781           p += strlen(pc->prot.dss1.uus1_data);
1782           pc->prot.dss1.uus1_data[0] = '\0';   
1783         } 
1784
1785        l = p - tmp;
1786        if (!(skb = l3_alloc_skb(l)))
1787                return;
1788        memcpy(skb_put(skb, l), tmp, l);
1789        newl3state(pc, 11);
1790        l3_msg(pc->st, DL_DATA | REQUEST, skb);
1791        L3AddTimer(&pc->timer, T305, CC_T305);
1792}
1793
1794static void
1795l3dss1_setup_rsp(struct l3_process *pc, u_char pr,
1796                 void *arg)
1797{
1798        if (!pc->para.bchannel) 
1799         { if (pc->debug & L3_DEB_WARN)
1800               l3_debug(pc->st, "D-chan connect for waiting call");
1801           l3dss1_disconnect_req(pc, pr, arg);
1802           return;
1803         }
1804        newl3state(pc, 8);
1805        l3dss1_message(pc, MT_CONNECT);
1806        L3DelTimer(&pc->timer);
1807        L3AddTimer(&pc->timer, T313, CC_T313);
1808}
1809
1810static void
1811l3dss1_connect_ack(struct l3_process *pc, u_char pr, void *arg)
1812{
1813        struct sk_buff *skb = arg;
1814        int ret;
1815
1816        ret = check_infoelements(pc, skb, ie_CONNECT_ACKNOWLEDGE);
1817        if (ERR_IE_COMPREHENSION == ret) {
1818                l3dss1_std_ie_err(pc, ret);
1819                return;
1820        }
1821        newl3state(pc, 10);
1822        L3DelTimer(&pc->timer);
1823        if (ret)
1824                l3dss1_std_ie_err(pc, ret);
1825        pc->st->l3.l3l4(pc->st, CC_SETUP_COMPL | INDICATION, pc);
1826}
1827
1828static void
1829l3dss1_reject_req(struct l3_process *pc, u_char pr, void *arg)
1830{
1831        struct sk_buff *skb;
1832        u_char tmp[16];
1833        u_char *p = tmp;
1834        int l;
1835        u_char cause = 21;
1836
1837        if (pc->para.cause != NO_CAUSE)
1838                cause = pc->para.cause;
1839
1840        MsgHead(p, pc->callref, MT_RELEASE_COMPLETE);
1841
1842        *p++ = IE_CAUSE;
1843        *p++ = 0x2;
1844        *p++ = 0x80;
1845        *p++ = cause | 0x80;
1846
1847        l = p - tmp;
1848        if (!(skb = l3_alloc_skb(l)))
1849                return;
1850        memcpy(skb_put(skb, l), tmp, l);
1851        l3_msg(pc->st, DL_DATA | REQUEST, skb);
1852        pc->st->l3.l3l4(pc->st, CC_RELEASE | INDICATION, pc);
1853        newl3state(pc, 0);
1854        dss1_release_l3_process(pc);
1855}
1856
1857static void
1858l3dss1_release(struct l3_process *pc, u_char pr, void *arg)
1859{
1860        struct sk_buff *skb = arg;
1861        u_char *p;
1862        int ret, cause=0;
1863
1864        StopAllL3Timer(pc);
1865        if ((ret = l3dss1_get_cause(pc, skb))>0) {
1866                if (pc->debug & L3_DEB_WARN)
1867                        l3_debug(pc->st, "REL get_cause ret(%d)", ret);
1868        } else if (ret<0)
1869                pc->para.cause = NO_CAUSE;
1870        if ((p = findie(skb->data, skb->len, IE_FACILITY, 0))) {
1871                l3dss1_parse_facility(pc->st, pc, pc->callref, p);
1872        }
1873        if ((ret<0) && (pc->state != 11))
1874                cause = 96;
1875        else if (ret>0)
1876                cause = 100;
1877        ret = check_infoelements(pc, skb, ie_RELEASE);
1878        if (ERR_IE_COMPREHENSION == ret)
1879                cause = 96;
1880        else if ((ERR_IE_UNRECOGNIZED == ret) && (!cause))
1881                cause = 99;  
1882        if (cause)
1883                l3dss1_message_cause(pc, MT_RELEASE_COMPLETE, cause);
1884        else
1885                l3dss1_message(pc, MT_RELEASE_COMPLETE);
1886        pc->st->l3.l3l4(pc->st, CC_RELEASE | INDICATION, pc);
1887        newl3state(pc, 0);
1888        dss1_release_l3_process(pc);
1889}
1890
1891static void
1892l3dss1_alert_req(struct l3_process *pc, u_char pr,
1893                 void *arg)
1894{
1895        newl3state(pc, 7);
1896        if (!pc->prot.dss1.uus1_data[0]) 
1897                l3dss1_message(pc, MT_ALERTING);
1898        else
1899                l3dss1_msg_with_uus(pc, MT_ALERTING); 
1900}
1901
1902static void
1903l3dss1_proceed_req(struct l3_process *pc, u_char pr,
1904                   void *arg)
1905{
1906        newl3state(pc, 9);
1907        l3dss1_message(pc, MT_CALL_PROCEEDING);
1908        pc->st->l3.l3l4(pc->st, CC_PROCEED_SEND | INDICATION, pc); 
1909}
1910
1911static void
1912l3dss1_setup_ack_req(struct l3_process *pc, u_char pr,
1913                   void *arg)
1914{
1915        newl3state(pc, 25);
1916        L3DelTimer(&pc->timer);
1917        L3AddTimer(&pc->timer, T302, CC_T302);
1918        l3dss1_message(pc, MT_SETUP_ACKNOWLEDGE);
1919}
1920
1921/********************************************/
1922/* deliver a incoming display message to HL */
1923/********************************************/
1924static void
1925l3dss1_deliver_display(struct l3_process *pc, int pr, u_char *infp)
1926{       u_char len;
1927        isdn_ctrl ic; 
1928        struct IsdnCardState *cs;
1929        char *p; 
1930
1931        if (*infp++ != IE_DISPLAY) return;
1932        if ((len = *infp++) > 80) return; /* total length <= 82 */
1933        if (!pc->chan) return;
1934
1935        p = ic.parm.display; 
1936        while (len--)
1937          *p++ = *infp++;
1938        *p = '\0';
1939        ic.command = ISDN_STAT_DISPLAY;
1940        cs = pc->st->l1.hardware;
1941        ic.driver = cs->myid;
1942        ic.arg = pc->chan->chan; 
1943        cs->iif.statcallb(&ic);
1944} /* l3dss1_deliver_display */
1945
1946
1947static void
1948l3dss1_progress(struct l3_process *pc, u_char pr, void *arg)
1949{
1950        struct sk_buff *skb = arg;
1951        int err = 0;
1952        u_char *p;
1953
1954        if ((p = findie(skb->data, skb->len, IE_PROGRESS, 0))) {
1955                if (p[1] != 2) {
1956                        err = 1;
1957                        pc->para.cause = 100;
1958                } else if (!(p[2] & 0x70)) {
1959                        switch (p[2]) {
1960                                case 0x80:
1961                                case 0x81:
1962                                case 0x82:
1963                                case 0x84:
1964                                case 0x85:
1965                                case 0x87:
1966                                case 0x8a:
1967                                        switch (p[3]) {
1968                                                case 0x81:
1969                                                case 0x82:
1970                                                case 0x83:
1971                                                case 0x84:
1972                                                case 0x88:
1973                                                        break;
1974                                                default:
1975                                                        err = 2;
1976                                                        pc->para.cause = 100;
1977                                                        break;
1978                                        }
1979                                        break;
1980                                default:
1981                                        err = 3;
1982                                        pc->para.cause = 100;
1983                                        break;
1984                        }
1985                }
1986        } else {
1987                pc->para.cause = 96;
1988                err = 4;
1989        }
1990        if (err) {      
1991                if (pc->debug & L3_DEB_WARN)
1992                        l3_debug(pc->st, "progress error %d", err);
1993                l3dss1_status_send(pc, pr, NULL);
1994                return;
1995        }
1996        /* Now we are on none mandatory IEs */
1997        err = check_infoelements(pc, skb, ie_PROGRESS);
1998        if (err)
1999                l3dss1_std_ie_err(pc, err);
2000        if (ERR_IE_COMPREHENSION != err)
2001                pc->st->l3.l3l4(pc->st, CC_PROGRESS | INDICATION, pc);
2002}
2003
2004static void
2005l3dss1_notify(struct l3_process *pc, u_char pr, void *arg)
2006{
2007        struct sk_buff *skb = arg;
2008        int err = 0;
2009        u_char *p;
2010
2011        if ((p = findie(skb->data, skb->len, IE_NOTIFY, 0))) {
2012                if (p[1] != 1) {
2013                        err = 1;
2014                        pc->para.cause = 100;
2015                } else {
2016                        switch (p[2]) {
2017                                case 0x80:
2018                                case 0x81:
2019                                case 0x82:
2020                                        break;
2021                                default:
2022                                        pc->para.cause = 100;
2023                                        err = 2;
2024                                        break;
2025                        }
2026                }
2027        } else {
2028                pc->para.cause = 96;
2029                err = 3;
2030        }
2031        if (err) {      
2032                if (pc->debug & L3_DEB_WARN)
2033                        l3_debug(pc->st, "notify error %d", err);
2034                l3dss1_status_send(pc, pr, NULL);
2035                return;
2036        }
2037        /* Now we are on none mandatory IEs */
2038        err = check_infoelements(pc, skb, ie_NOTIFY);
2039        if (err)
2040                l3dss1_std_ie_err(pc, err);
2041        if (ERR_IE_COMPREHENSION != err)
2042                pc->st->l3.l3l4(pc->st, CC_NOTIFY | INDICATION, pc);
2043}
2044
2045static void
2046l3dss1_status_enq(struct l3_process *pc, u_char pr, void *arg)
2047{
2048        int ret;
2049        struct sk_buff *skb = arg;
2050
2051        ret = check_infoelements(pc, skb, ie_STATUS_ENQUIRY);
2052        l3dss1_std_ie_err(pc, ret);
2053        pc->para.cause = 30; /* response to STATUS_ENQUIRY */
2054        l3dss1_status_send(pc, pr, NULL);
2055}
2056
2057static void
2058l3dss1_information(struct l3_process *pc, u_char pr, void *arg)
2059{
2060        int ret;
2061        struct sk_buff *skb = arg;
2062        u_char *p;
2063        char tmp[32];
2064
2065        ret = check_infoelements(pc, skb, ie_INFORMATION);
2066        if (ret)
2067                l3dss1_std_ie_err(pc, ret);
2068        if (pc->state == 25) { /* overlap receiving */
2069                L3DelTimer(&pc->timer);
2070                p = skb->data;
2071                if ((p = findie(p, skb->len, 0x70, 0))) {
2072                        iecpy(tmp, p, 1);
2073                        strcat(pc->para.setup.eazmsn, tmp);
2074                        pc->st->l3.l3l4(pc->st, CC_MORE_INFO | INDICATION, pc);
2075                }
2076                L3AddTimer(&pc->timer, T302, CC_T302);
2077        }
2078}
2079
2080/******************************/
2081/* handle deflection requests */
2082/******************************/
2083static void l3dss1_redir_req(struct l3_process *pc, u_char pr, void *arg)
2084{
2085        struct sk_buff *skb;
2086        u_char tmp[128];
2087        u_char *p = tmp;
2088        u_char *subp;
2089        u_char len_phone = 0;
2090        u_char len_sub = 0;
2091        int l; 
2092
2093
2094        strcpy(pc->prot.dss1.uus1_data,pc->chan->setup.eazmsn); /* copy uus element if available */
2095        if (!pc->chan->setup.phone[0])
2096          { pc->para.cause = -1;
2097            l3dss1_disconnect_req(pc,pr,arg); /* disconnect immediately */
2098            return;
2099          } /* only uus */
2100 
2101        if (pc->prot.dss1.invoke_id) 
2102          free_invoke_id(pc->st,pc->prot.dss1.invoke_id);
2103 
2104        if (!(pc->prot.dss1.invoke_id = new_invoke_id(pc->st))) 
2105          return;
2106
2107        MsgHead(p, pc->callref, MT_FACILITY);
2108
2109        for (subp = pc->chan->setup.phone; (*subp) && (*subp != '.'); subp++) len_phone++; /* len of phone number */
2110        if (*subp++ == '.') len_sub = strlen(subp) + 2; /* length including info subaddress element */ 
2111
2112        *p++ = 0x1c;   /* Facility info element */
2113        *p++ = len_phone + len_sub + 2 + 2 + 8 + 3 + 3; /* length of element */
2114        *p++ = 0x91;  /* remote operations protocol */
2115        *p++ = 0xa1;  /* invoke component */
2116          
2117        *p++ = len_phone + len_sub + 2 + 2 + 8 + 3; /* length of data */
2118        *p++ = 0x02;  /* invoke id tag, integer */
2119        *p++ = 0x01;  /* length */
2120        *p++ = pc->prot.dss1.invoke_id;  /* invoke id */ 
2121        *p++ = 0x02;  /* operation value tag, integer */
2122        *p++ = 0x01;  /* length */
2123        *p++ = 0x0D;  /* Call Deflect */
2124          
2125        *p++ = 0x30;  /* sequence phone number */
2126        *p++ = len_phone + 2 + 2 + 3 + len_sub; /* length */
2127          
2128        *p++ = 0x30;  /* Deflected to UserNumber */
2129        *p++ = len_phone+2+len_sub; /* length */
2130        *p++ = 0x80; /* NumberDigits */
2131        *p++ = len_phone; /* length */
2132        for (l = 0; l < len_phone; l++)
2133         *p++ = pc->chan->setup.phone[l];
2134
2135        if (len_sub)
2136          { *p++ = 0x04; /* called party subaddress */
2137            *p++ = len_sub - 2;
2138            while (*subp) *p++ = *subp++;
2139          }
2140
2141        *p++ = 0x01; /* screening identifier */
2142        *p++ = 0x01;
2143        *p++ = pc->chan->setup.screen;
2144
2145        l = p - tmp;
2146        if (!(skb = l3_alloc_skb(l))) return;
2147        memcpy(skb_put(skb, l), tmp, l);
2148
2149        l3_msg(pc->st, DL_DATA | REQUEST, skb);
2150} /* l3dss1_redir_req */
2151
2152/********************************************/
2153/* handle deflection request in early state */
2154/********************************************/
2155static void l3dss1_redir_req_early(struct l3_process *pc, u_char pr, void *arg)
2156{
2157  l3dss1_proceed_req(pc,pr,arg);
2158  l3dss1_redir_req(pc,pr,arg);
2159} /* l3dss1_redir_req_early */
2160
2161/***********************************************/
2162/* handle special commands for this protocol.  */
2163/* Examples are call independant services like */
2164/* remote operations with dummy  callref.      */
2165/***********************************************/
2166static int l3dss1_cmd_global(struct PStack *st, isdn_ctrl *ic)
2167{ u_char id;
2168  u_char temp[265];
2169  u_char *p = temp;
2170  int i, l, proc_len; 
2171  struct sk_buff *skb;
2172  struct l3_process *pc = NULL;
2173
2174  switch (ic->arg)
2175   { case DSS1_CMD_INVOKE:
2176       if (ic->parm.dss1_io.datalen < 0) return(-2); /* invalid parameter */ 
2177
2178       for (proc_len = 1, i = ic->parm.dss1_io.proc >> 8; i; i++) 
2179         i = i >> 8; /* add one byte */    
2180       l = ic->parm.dss1_io.datalen + proc_len + 8; /* length excluding ie header */
2181       if (l > 255) 
2182         return(-2); /* too long */
2183
2184       if (!(id = new_invoke_id(st))) 
2185         return(0); /* first get a invoke id -> return if no available */
2186       
2187       i = -1; 
2188       MsgHead(p, i, MT_FACILITY); /* build message head */
2189       *p++ = 0x1C; /* Facility IE */
2190       *p++ = l; /* length of ie */
2191       *p++ = 0x91; /* remote operations */
2192       *p++ = 0xA1; /* invoke */
2193       *p++ = l - 3; /* length of invoke */
2194       *p++ = 0x02; /* invoke id tag */
2195       *p++ = 0x01; /* length is 1 */
2196       *p++ = id; /* invoke id */
2197       *p++ = 0x02; /* operation */
2198       *p++ = proc_len; /* length of operation */
2199       
2200       for (i = proc_len; i; i--)
2201         *p++ = (ic->parm.dss1_io.proc >> (i-1)) & 0xFF;
2202       memcpy(p, ic->parm.dss1_io.data, ic->parm.dss1_io.datalen); /* copy data */
2203       l = (p - temp) + ic->parm.dss1_io.datalen; /* total length */         
2204
2205       if (ic->parm.dss1_io.timeout > 0)
2206        if (!(pc = dss1_new_l3_process(st, -1)))
2207          { free_invoke_id(st, id);
2208            return(-2);
2209          } 
2210       pc->prot.dss1.ll_id = ic->parm.dss1_io.ll_id; /* remember id */ 
2211       pc->prot.dss1.proc = ic->parm.dss1_io.proc; /* and procedure */
2212
2213       if (!(skb = l3_alloc_skb(l))) 
2214         { free_invoke_id(st, id);
2215           if (pc) dss1_release_l3_process(pc);
2216           return(-2);
2217         }
2218       memcpy(skb_put(skb, l), temp, l);
2219       
2220       if (pc)
2221        { pc->prot.dss1.invoke_id = id; /* remember id */
2222          L3AddTimer(&pc->timer, ic->parm.dss1_io.timeout, CC_TDSS1_IO | REQUEST);
2223        }
2224       
2225       l3_msg(st, DL_DATA | REQUEST, skb);
2226       ic->parm.dss1_io.hl_id = id; /* return id */
2227       return(0);
2228
2229     case DSS1_CMD_INVOKE_ABORT:
2230       if ((pc = l3dss1_search_dummy_proc(st, ic->parm.dss1_io.hl_id)))
2231        { L3DelTimer(&pc->timer); /* remove timer */
2232          dss1_release_l3_process(pc);
2233          return(0); 
2234        } 
2235       else
2236        { l3_debug(st, "l3dss1_cmd_global abort unknown id");
2237          return(-2);
2238        } 
2239       break;
2240    
2241     default: 
2242       l3_debug(st, "l3dss1_cmd_global unknown cmd 0x%lx", ic->arg);
2243       return(-1);  
2244   } /* switch ic-> arg */
2245  return(-1);
2246} /* l3dss1_cmd_global */
2247
2248static void 
2249l3dss1_io_timer(struct l3_process *pc)
2250{ isdn_ctrl ic;
2251  struct IsdnCardState *cs = pc->st->l1.hardware;
2252
2253  L3DelTimer(&pc->timer); /* remove timer */
2254
2255  ic.driver = cs->myid;
2256  ic.command = ISDN_STAT_PROT;
2257  ic.arg = DSS1_STAT_INVOKE_ERR;
2258  ic.parm.dss1_io.hl_id = pc->prot.dss1.invoke_id;
2259  ic.parm.dss1_io.ll_id = pc->prot.dss1.ll_id;
2260  ic.parm.dss1_io.proc = pc->prot.dss1.proc;
2261  ic.parm.dss1_io.timeout= -1;
2262  ic.parm.dss1_io.datalen = 0;
2263  ic.parm.dss1_io.data = NULL;
2264  free_invoke_id(pc->st, pc->prot.dss1.invoke_id);
2265  pc->prot.dss1.invoke_id = 0; /* reset id */
2266
2267  cs->iif.statcallb(&ic);
2268
2269  dss1_release_l3_process(pc); 
2270} /* l3dss1_io_timer */
2271
2272static void
2273l3dss1_release_ind(struct l3_process *pc, u_char pr, void *arg)
2274{
2275        u_char *p;
2276        struct sk_buff *skb = arg;
2277        int callState = 0;
2278        p = skb->data;
2279
2280        if ((p = findie(p, skb->len, IE_CALL_STATE, 0))) {
2281                p++;
2282                if (1 == *p++)
2283                        callState = *p;
2284        }
2285        if (callState == 0) {
2286                /* ETS 300-104 7.6.1, 8.6.1, 10.6.1... and 16.1
2287                 * set down layer 3 without sending any message
2288                 */
2289                pc->st->l3.l3l4(pc->st, CC_RELEASE | INDICATION, pc);
2290                newl3state(pc, 0);
2291                dss1_release_l3_process(pc);
2292        } else {
2293                pc->st->l3.l3l4(pc->st, CC_IGNORE | INDICATION, pc);
2294        }
2295}
2296
2297static void
2298l3dss1_dummy(struct l3_process *pc, u_char pr, void *arg)
2299{
2300}
2301
2302static void
2303l3dss1_t302(struct l3_process *pc, u_char pr, void *arg)
2304{
2305        L3DelTimer(&pc->timer);
2306        pc->para.loc = 0;
2307        pc->para.cause = 28; /* invalid number */
2308        l3dss1_disconnect_req(pc, pr, NULL);
2309        pc->st->l3.l3l4(pc->st, CC_SETUP_ERR, pc);
2310}
2311
2312static void
2313l3dss1_t303(struct l3_process *pc, u_char pr, void *arg)
2314{
2315        if (pc->N303 > 0) {
2316                pc->N303--;
2317                L3DelTimer(&pc->timer);
2318                l3dss1_setup_req(pc, pr, arg);
2319        } else {
2320                L3DelTimer(&pc->timer);
2321                l3dss1_message_cause(pc, MT_RELEASE_COMPLETE, 102);
2322                pc->st->l3.l3l4(pc->st, CC_NOSETUP_RSP, pc);
2323                dss1_release_l3_process(pc);
2324        }
2325}
2326
2327static void
2328l3dss1_t304(struct l3_process *pc, u_char pr, void *arg)
2329{
2330        L3DelTimer(&pc->timer);
2331        pc->para.loc = 0;
2332        pc->para.cause = 102;
2333        l3dss1_disconnect_req(pc, pr, NULL);
2334        pc->st->l3.l3l4(pc->st, CC_SETUP_ERR, pc);
2335
2336}
2337
2338static void
2339l3dss1_t305(struct l3_process *pc, u_char pr, void *arg)
2340{
2341        u_char tmp[16];
2342        u_char *p = tmp;
2343        int l;
2344        struct sk_buff *skb;
2345        u_char cause = 16;
2346
2347        L3DelTimer(&pc->timer);
2348        if (pc->para.cause != NO_CAUSE)
2349                cause = pc->para.cause;
2350
2351        MsgHead(p, pc->callref, MT_RELEASE);
2352
2353        *p++ = IE_CAUSE;
2354        *p++ = 0x2;
2355        *p++ = 0x80;
2356        *p++ = cause | 0x80;
2357
2358        l = p - tmp;
2359        if (!(skb = l3_alloc_skb(l)))
2360                return;
2361        memcpy(skb_put(skb, l), tmp, l);
2362        newl3state(pc, 19);
2363        l3_msg(pc->st, DL_DATA | REQUEST, skb);
2364        L3AddTimer(&pc->timer, T308, CC_T308_1);
2365}
2366
2367static void
2368l3dss1_t310(struct l3_process *pc, u_char pr, void *arg)
2369{
2370        L3DelTimer(&pc->timer);
2371        pc->para.loc = 0;
2372        pc->para.cause = 102;
2373        l3dss1_disconnect_req(pc, pr, NULL);
2374        pc->st->l3.l3l4(pc->st, CC_SETUP_ERR, pc);
2375}
2376
2377static void
2378l3dss1_t313(struct l3_process *pc, u_char pr, void *arg)
2379{
2380        L3DelTimer(&pc->timer);
2381        pc->para.loc = 0;
2382        pc->para.cause = 102;
2383        l3dss1_disconnect_req(pc, pr, NULL);
2384        pc->st->l3.l3l4(pc->st, CC_CONNECT_ERR, pc);
2385}
2386
2387static void
2388l3dss1_t308_1(struct l3_process *pc, u_char pr, void *arg)
2389{
2390        newl3state(pc, 19);
2391        L3DelTimer(&pc->timer);
2392        l3dss1_message(pc, MT_RELEASE);
2393        L3AddTimer(&pc->timer, T308, CC_T308_2);
2394}
2395
2396static void
2397l3dss1_t308_2(struct l3_process *pc, u_char pr, void *arg)
2398{
2399        L3DelTimer(&pc->timer);
2400        pc->st->l3.l3l4(pc->st, CC_RELEASE_ERR, pc);
2401        dss1_release_l3_process(pc);
2402}
2403
2404static void
2405l3dss1_t318(struct l3_process *pc, u_char pr, void *arg)
2406{
2407        L3DelTimer(&pc->timer);
2408        pc->para.cause = 102;   /* Timer expiry */
2409        pc->para.loc = 0;       /* local */
2410        pc->st->l3.l3l4(pc->st, CC_RESUME_ERR, pc);
2411        newl3state(pc, 19);
2412        l3dss1_message(pc, MT_RELEASE);
2413        L3AddTimer(&pc->timer, T308, CC_T308_1);
2414}
2415
2416static void
2417l3dss1_t319(struct l3_process *pc, u_char pr, void *arg)
2418{
2419        L3DelTimer(&pc->timer);
2420        pc->para.cause = 102;   /* Timer expiry */
2421        pc->para.loc = 0;       /* local */
2422        pc->st->l3.l3l4(pc->st, CC_SUSPEND_ERR, pc);
2423        newl3state(pc, 10);
2424}
2425
2426static void
2427l3dss1_restart(struct l3_process *pc, u_char pr, void *arg)
2428{
2429        L3DelTimer(&pc->timer);
2430        pc->st->l3.l3l4(pc->st, CC_RELEASE | INDICATION, pc);
2431        dss1_release_l3_process(pc);
2432}
2433
2434static void
2435l3dss1_status(struct l3_process *pc, u_char pr, void *arg)
2436{
2437        u_char *p;
2438        struct sk_buff *skb = arg;
2439        int ret; 
2440        u_char cause = 0, callState = 0;
2441        
2442        if ((ret = l3dss1_get_cause(pc, skb))) {
2443                if (pc->debug & L3_DEB_WARN)
2444                        l3_debug(pc->st, "STATUS get_cause ret(%d)",ret);
2445                if (ret < 0)
2446                        cause = 96;
2447                else if (ret > 0)
2448                        cause = 100;
2449        }
2450        if ((p = findie(skb->data, skb->len, IE_CALL_STATE, 0))) {
2451                p++;
2452                if (1 == *p++) {
2453                        callState = *p;
2454                        if (!ie_in_set(pc, *p, l3_valid_states))
2455                                cause = 100;
2456                } else
2457                        cause = 100;
2458        } else
2459                cause = 96;
2460        if (!cause) { /*  no error before */
2461                ret = check_infoelements(pc, skb, ie_STATUS);
2462                if (ERR_IE_COMPREHENSION == ret)
2463                        cause = 96;
2464                else if (ERR_IE_UNRECOGNIZED == ret)
2465                        cause = 99;
2466        }
2467        if (cause) {
2468                u_char tmp;
2469                
2470                if (pc->debug & L3_DEB_WARN)
2471                        l3_debug(pc->st, "STATUS error(%d/%d)",ret,cause);
2472                tmp = pc->para.cause;
2473                pc->para.cause = cause;
2474                l3dss1_status_send(pc, 0, NULL);
2475                if (cause == 99)
2476                        pc->para.cause = tmp;
2477                else
2478                        return;
2479        }
2480        cause = pc->para.cause;
2481        if (((cause & 0x7f) == 111) && (callState == 0)) {
2482                /* ETS 300-104 7.6.1, 8.6.1, 10.6.1...
2483                 * if received MT_STATUS with cause == 111 and call
2484                 * state == 0, then we must set down layer 3
2485                 */
2486                pc->st->l3.l3l4(pc->st, CC_RELEASE | INDICATION, pc);
2487                newl3state(pc, 0);
2488                dss1_release_l3_process(pc);
2489        }
2490}
2491
2492static void
2493l3dss1_facility(struct l3_process *pc, u_char pr, void *arg)
2494{
2495        struct sk_buff *skb = arg;
2496        int ret;
2497        
2498        ret = check_infoelements(pc, skb, ie_FACILITY);
2499        l3dss1_std_ie_err(pc, ret);
2500          {
2501                u_char *p;
2502                if ((p = findie(skb->data, skb->len, IE_FACILITY, 0)))
2503                        l3dss1_parse_facility(pc->st, pc, pc->callref, p);
2504        }
2505}
2506
2507static void
2508l3dss1_suspend_req(struct l3_process *pc, u_char pr, void *arg)
2509{
2510        struct sk_buff *skb;
2511        u_char tmp[32];
2512        u_char *p = tmp;
2513        u_char i, l;
2514        u_char *msg = pc->chan->setup.phone;
2515
2516        MsgHead(p, pc->callref, MT_SUSPEND);
2517        l = *msg++;
2518        if (l && (l <= 10)) {   /* Max length 10 octets */
2519                *p++ = IE_CALL_ID;
2520                *p++ = l;
2521                for (i = 0; i < l; i++)
2522                        *p++ = *msg++;
2523        } else if (l) {
2524                l3_debug(pc->st, "SUS wrong CALL_ID len %d", l);
2525                return;
2526        }
2527        l = p - tmp;
2528        if (!(skb = l3_alloc_skb(l)))
2529                return;
2530        memcpy(skb_put(skb, l), tmp, l);
2531        l3_msg(pc->st, DL_DATA | REQUEST, skb);
2532        newl3state(pc, 15);
2533        L3AddTimer(&pc->timer, T319, CC_T319);
2534}
2535
2536static void
2537l3dss1_suspend_ack(struct l3_process *pc, u_char pr, void *arg)
2538{
2539        struct sk_buff *skb = arg;
2540        int ret;
2541
2542        L3DelTimer(&pc->timer);
2543        newl3state(pc, 0);
2544        pc->para.cause = NO_CAUSE;
2545        pc->st->l3.l3l4(pc->st, CC_SUSPEND | CONFIRM, pc);
2546        /* We don't handle suspend_ack for IE errors now */
2547        if ((ret = check_infoelements(pc, skb, ie_SUSPEND_ACKNOWLEDGE)))
2548                if (pc->debug & L3_DEB_WARN)
2549                        l3_debug(pc->st, "SUSPACK check ie(%d)",ret);
2550        dss1_release_l3_process(pc);
2551}
2552
2553static void
2554l3dss1_suspend_rej(struct l3_process *pc, u_char pr, void *arg)
2555{
2556        struct sk_buff *skb = arg;
2557        int ret;
2558
2559        if ((ret = l3dss1_get_cause(pc, skb))) {
2560                if (pc->debug & L3_DEB_WARN)
2561                        l3_debug(pc->st, "SUSP_REJ get_cause ret(%d)",ret);
2562                if (ret < 0) 
2563                        pc->para.cause = 96;
2564                else
2565                        pc->para.cause = 100;
2566                l3dss1_status_send(pc, pr, NULL);
2567                return;
2568        }
2569        ret = check_infoelements(pc, skb, ie_SUSPEND_REJECT);
2570        if (ERR_IE_COMPREHENSION == ret) {
2571                l3dss1_std_ie_err(pc, ret);
2572                return;
2573        }
2574        L3DelTimer(&pc->timer);
2575        pc->st->l3.l3l4(pc->st, CC_SUSPEND_ERR, pc);
2576        newl3state(pc, 10);
2577        if (ret) /* STATUS for none mandatory IE errors after actions are taken */
2578                l3dss1_std_ie_err(pc, ret);
2579}
2580
2581static void
2582l3dss1_resume_req(struct l3_process *pc, u_char pr, void *arg)
2583{
2584        struct sk_buff *skb;
2585        u_char tmp[32];
2586        u_char *p = tmp;
2587        u_char i, l;
2588        u_char *msg = pc->para.setup.phone;
2589
2590        MsgHead(p, pc->callref, MT_RESUME);
2591
2592        l = *msg++;
2593        if (l && (l <= 10)) {   /* Max length 10 octets */
2594                *p++ = IE_CALL_ID;
2595                *p++ = l;
2596                for (i = 0; i < l; i++)
2597                        *p++ = *msg++;
2598        } else if (l) {
2599                l3_debug(pc->st, "RES wrong CALL_ID len %d", l);
2600                return;
2601        }
2602        l = p - tmp;
2603        if (!(skb = l3_alloc_skb(l)))
2604                return;
2605        memcpy(skb_put(skb, l), tmp, l);
2606        l3_msg(pc->st, DL_DATA | REQUEST, skb);
2607        newl3state(pc, 17);
2608        L3AddTimer(&pc->timer, T318, CC_T318);
2609}
2610
2611static void
2612l3dss1_resume_ack(struct l3_process *pc, u_char pr, void *arg)
2613{
2614        struct sk_buff *skb = arg;
2615        int id, ret;
2616
2617        if ((id = l3dss1_get_channel_id(pc, skb)) > 0) {
2618                if ((0 == id) || ((3 == id) && (0x10 == pc->para.moderate))) {
2619                        if (pc->debug & L3_DEB_WARN)
2620                                l3_debug(pc->st, "resume ack with wrong chid %x", id);
2621                        pc->para.cause = 100;
2622                        l3dss1_status_send(pc, pr, NULL);
2623                        return;
2624                }
2625                pc->para.bchannel = id;
2626        } else if (1 == pc->state) {
2627                if (pc->debug & L3_DEB_WARN)
2628                        l3_debug(pc->st, "resume ack without chid (ret %d)", id);
2629                pc->para.cause = 96;
2630                l3dss1_status_send(pc, pr, NULL);
2631                return;
2632        }
2633        ret = check_infoelements(pc, skb, ie_RESUME_ACKNOWLEDGE);
2634        if (ERR_IE_COMPREHENSION == ret) {
2635                l3dss1_std_ie_err(pc, ret);
2636                return;
2637        }
2638        L3DelTimer(&pc->timer);
2639        pc->st->l3.l3l4(pc->st, CC_RESUME | CONFIRM, pc);
2640        newl3state(pc, 10);
2641        if (ret) /* STATUS for none mandatory IE errors after actions are taken */
2642                l3dss1_std_ie_err(pc, ret);
2643}
2644
2645static void
2646l3dss1_resume_rej(struct l3_process *pc, u_char pr, void *arg)
2647{
2648        struct sk_buff *skb = arg;
2649        int ret;
2650
2651        if ((ret = l3dss1_get_cause(pc, skb))) {
2652                if (pc->debug & L3_DEB_WARN)
2653                        l3_debug(pc->st, "RES_REJ get_cause ret(%d)",ret);
2654                if (ret < 0) 
2655                        pc->para.cause = 96;
2656                else
2657                        pc->para.cause = 100;
2658                l3dss1_status_send(pc, pr, NULL);
2659                return;
2660        }
2661        ret = check_infoelements(pc, skb, ie_RESUME_REJECT);
2662        if (ERR_IE_COMPREHENSION == ret) {
2663                l3dss1_std_ie_err(pc, ret);
2664                return;
2665        }
2666        L3DelTimer(&pc->timer);
2667        pc->st->l3.l3l4(pc->st, CC_RESUME_ERR, pc);
2668        newl3state(pc, 0);
2669        if (ret) /* STATUS for none mandatory IE errors after actions are taken */
2670                l3dss1_std_ie_err(pc, ret);
2671        dss1_release_l3_process(pc);
2672}
2673
2674static void
2675l3dss1_global_restart(struct l3_process *pc, u_char pr, void *arg)
2676{
2677        u_char tmp[32];
2678        u_char *p;
2679        u_char ri, ch = 0, chan = 0;
2680        int l;
2681        struct sk_buff *skb = arg;
2682        struct l3_process *up;
2683
2684        newl3state(pc, 2);
2685        L3DelTimer(&pc->timer);
2686        p = skb->data;
2687        if ((p = findie(p, skb->len, IE_RESTART_IND, 0))) {
2688                ri = p[2];
2689                l3_debug(pc->st, "Restart %x", ri);
2690        } else {
2691                l3_debug(pc->st, "Restart without restart IE");
2692                ri = 0x86;
2693        }
2694        p = skb->data;
2695        if ((p = findie(p, skb->len, IE_CHANNEL_ID, 0))) {
2696                chan = p[2] & 3;
2697                ch = p[2];
2698                if (pc->st->l3.debug)
2699                        l3_debug(pc->st, "Restart for channel %d", chan);
2700        }
2701        newl3state(pc, 2);
2702        up = pc->st->l3.proc;
2703        while (up) {
2704                if ((ri & 7) == 7)
2705                        up->st->lli.l4l3(up->st, CC_RESTART | REQUEST, up);
2706                else if (up->para.bchannel == chan)
2707                        up->st->lli.l4l3(up->st, CC_RESTART | REQUEST, up);
2708                up = up->next;
2709        }
2710        p = tmp;
2711        MsgHead(p, pc->callref, MT_RESTART_ACKNOWLEDGE);
2712        if (chan) {
2713                *p++ = IE_CHANNEL_ID;
2714                *p++ = 1;
2715                *p++ = ch | 0x80;
2716        }
2717        *p++ = 0x79;            /* RESTART Ind */
2718        *p++ = 1;
2719        *p++ = ri;
2720        l = p - tmp;
2721        if (!(skb = l3_alloc_skb(l)))
2722                return;
2723        memcpy(skb_put(skb, l), tmp, l);
2724        newl3state(pc, 0);
2725        l3_msg(pc->st, DL_DATA | REQUEST, skb);
2726}
2727
2728static void
2729l3dss1_dl_reset(struct l3_process *pc, u_char pr, void *arg)
2730{
2731        pc->para.cause = 0x29;          /* Temporary failure */
2732        pc->para.loc = 0;
2733        l3dss1_disconnect_req(pc, pr, NULL);
2734        pc->st->l3.l3l4(pc->st, CC_SETUP_ERR, pc);
2735}
2736
2737static void
2738l3dss1_dl_release(struct l3_process *pc, u_char pr, void *arg)
2739{
2740        newl3state(pc, 0);
2741        pc->para.cause = 0x1b;          /* Destination out of order */
2742        pc->para.loc = 0;
2743        pc->st->l3.l3l4(pc->st, CC_RELEASE | INDICATION, pc);
2744        release_l3_process(pc);
2745}
2746
2747static void
2748l3dss1_dl_reestablish(struct l3_process *pc, u_char pr, void *arg)
2749{
2750        L3DelTimer(&pc->timer);
2751        L3AddTimer(&pc->timer, T309, CC_T309);
2752        l3_msg(pc->st, DL_ESTABLISH | REQUEST, NULL);
2753}
2754 
2755static void
2756l3dss1_dl_reest_status(struct l3_process *pc, u_char pr, void *arg)
2757{
2758        L3DelTimer(&pc->timer);
2759 
2760        pc->para.cause = 0x1F; /* normal, unspecified */
2761        l3dss1_status_send(pc, 0, NULL);
2762}
2763
2764/* *INDENT-OFF* */
2765static struct stateentry downstatelist[] =
2766{
2767        {SBIT(0),
2768         CC_SETUP | REQUEST, l3dss1_setup_req},
2769        {SBIT(0),
2770         CC_RESUME | REQUEST, l3dss1_resume_req},
2771        {SBIT(1) | SBIT(2) | SBIT(3) | SBIT(4) | SBIT(6) | SBIT(7) | SBIT(8) | SBIT(9) | SBIT(10) | SBIT(25),
2772         CC_DISCONNECT | REQUEST, l3dss1_disconnect_req},
2773        {SBIT(12),
2774         CC_RELEASE | REQUEST, l3dss1_release_req},
2775        {ALL_STATES,
2776         CC_RESTART | REQUEST, l3dss1_restart},
2777        {SBIT(6) | SBIT(25),
2778         CC_IGNORE | REQUEST, l3dss1_reset},
2779        {SBIT(6) | SBIT(25),
2780         CC_REJECT | REQUEST, l3dss1_reject_req},
2781        {SBIT(6) | SBIT(25),
2782         CC_PROCEED_SEND | REQUEST, l3dss1_proceed_req},
2783        {SBIT(6),
2784         CC_MORE_INFO | REQUEST, l3dss1_setup_ack_req},
2785        {SBIT(25),
2786         CC_MORE_INFO | REQUEST, l3dss1_dummy},
2787        {SBIT(6) | SBIT(9) | SBIT(25),
2788         CC_ALERTING | REQUEST, l3dss1_alert_req},
2789        {SBIT(6) | SBIT(7) | SBIT(9) | SBIT(25),
2790         CC_SETUP | RESPONSE, l3dss1_setup_rsp},
2791        {SBIT(10),
2792         CC_SUSPEND | REQUEST, l3dss1_suspend_req},
2793        {SBIT(7) | SBIT(9) | SBIT(25),
2794         CC_REDIR | REQUEST, l3dss1_redir_req},
2795        {SBIT(6),
2796         CC_REDIR | REQUEST, l3dss1_redir_req_early},
2797        {SBIT(9) | SBIT(25),
2798         CC_DISCONNECT | REQUEST, l3dss1_disconnect_req},
2799        {SBIT(25),
2800         CC_T302, l3dss1_t302},
2801        {SBIT(1),
2802         CC_T303, l3dss1_t303},
2803        {SBIT(2),
2804         CC_T304, l3dss1_t304},
2805        {SBIT(3),
2806         CC_T310, l3dss1_t310},
2807        {SBIT(8),
2808         CC_T313, l3dss1_t313},
2809        {SBIT(11),
2810         CC_T305, l3dss1_t305},
2811        {SBIT(15),
2812         CC_T319, l3dss1_t319},
2813        {SBIT(17),
2814         CC_T318, l3dss1_t318},
2815        {SBIT(19),
2816         CC_T308_1, l3dss1_t308_1},
2817        {SBIT(19),
2818         CC_T308_2, l3dss1_t308_2},
2819        {SBIT(10),
2820         CC_T309, l3dss1_dl_release},
2821};
2822
2823static struct stateentry datastatelist[] =
2824{
2825        {ALL_STATES,
2826         MT_STATUS_ENQUIRY, l3dss1_status_enq},
2827        {ALL_STATES,
2828         MT_FACILITY, l3dss1_facility},
2829        {SBIT(19),
2830         MT_STATUS, l3dss1_release_ind},
2831        {ALL_STATES,
2832         MT_STATUS, l3dss1_status},
2833        {SBIT(0),
2834         MT_SETUP, l3dss1_setup},
2835        {SBIT(6) | SBIT(7) | SBIT(8) | SBIT(9) | SBIT(10) | SBIT(11) | SBIT(12) |
2836         SBIT(15) | SBIT(17) | SBIT(19) | SBIT(25),
2837         MT_SETUP, l3dss1_dummy},
2838        {SBIT(1) | SBIT(2),
2839         MT_CALL_PROCEEDING, l3dss1_call_proc},
2840        {SBIT(1),
2841         MT_SETUP_ACKNOWLEDGE, l3dss1_setup_ack},
2842        {SBIT(2) | SBIT(3),
2843         MT_ALERTING, l3dss1_alerting},
2844        {SBIT(2) | SBIT(3),
2845         MT_PROGRESS, l3dss1_progress},
2846        {SBIT(2) | SBIT(3) | SBIT(4) | SBIT(7) | SBIT(8) | SBIT(9) | SBIT(10) |
2847         SBIT(11) | SBIT(12) | SBIT(15) | SBIT(17) | SBIT(19) | SBIT(25),
2848         MT_INFORMATION, l3dss1_information},
2849        {SBIT(10) | SBIT(11) | SBIT(15),
2850         MT_NOTIFY, l3dss1_notify},
2851        {SBIT(0) | SBIT(1) | SBIT(2) | SBIT(3) | SBIT(4) | SBIT(7) | SBIT(8) | SBIT(10) |
2852         SBIT(11) | SBIT(12) | SBIT(15) | SBIT(17) | SBIT(19) | SBIT(25),
2853         MT_RELEASE_COMPLETE, l3dss1_release_cmpl},
2854        {SBIT(1) | SBIT(2) | SBIT(3) | SBIT(4) | SBIT(7) | SBIT(8) | SBIT(9) | SBIT(10) | SBIT(11) | SBIT(12) | SBIT(15) | SBIT(17) | SBIT(25),
2855         MT_RELEASE, l3dss1_release},
2856        {SBIT(19),  MT_RELEASE, l3dss1_release_ind},
2857        {SBIT(1) | SBIT(2) | SBIT(3) | SBIT(4) | SBIT(7) | SBIT(8) | SBIT(9) | SBIT(10) | SBIT(11) | SBIT(15) | SBIT(17) | SBIT(25),
2858         MT_DISCONNECT, l3dss1_disconnect},
2859        {SBIT(19),
2860         MT_DISCONNECT, l3dss1_dummy},
2861        {SBIT(1) | SBIT(2) | SBIT(3) | SBIT(4),
2862         MT_CONNECT, l3dss1_connect},
2863        {SBIT(8),
2864         MT_CONNECT_ACKNOWLEDGE, l3dss1_connect_ack},
2865        {SBIT(15),
2866         MT_SUSPEND_ACKNOWLEDGE, l3dss1_suspend_ack},
2867        {SBIT(15),
2868         MT_SUSPEND_REJECT, l3dss1_suspend_rej},
2869        {SBIT(17),
2870         MT_RESUME_ACKNOWLEDGE, l3dss1_resume_ack},
2871        {SBIT(17),
2872         MT_RESUME_REJECT, l3dss1_resume_rej},
2873};
2874
2875static struct stateentry globalmes_list[] =
2876{
2877        {ALL_STATES,
2878         MT_STATUS, l3dss1_status},
2879        {SBIT(0),
2880         MT_RESTART, l3dss1_global_restart},
2881/*      {SBIT(1),
2882         MT_RESTART_ACKNOWLEDGE, l3dss1_restart_ack},
2883*/
2884};
2885
2886static struct stateentry manstatelist[] =
2887{
2888        {SBIT(2),
2889         DL_ESTABLISH | INDICATION, l3dss1_dl_reset},
2890        {SBIT(10),
2891         DL_ESTABLISH | CONFIRM, l3dss1_dl_reest_status},
2892        {SBIT(10),
2893         DL_RELEASE | INDICATION, l3dss1_dl_reestablish},
2894        {ALL_STATES,
2895         DL_RELEASE | INDICATION, l3dss1_dl_release},
2896};
2897
2898/* *INDENT-ON* */
2899
2900
2901static void
2902global_handler(struct PStack *st, int mt, struct sk_buff *skb)
2903{
2904        u_char tmp[16];
2905        u_char *p = tmp;
2906        int l;
2907        int i;
2908        struct l3_process *proc = st->l3.global;
2909
2910        proc->callref = skb->data[2]; /* cr flag */
2911        for (i = 0; i < ARRAY_SIZE(globalmes_list); i++)
2912                if ((mt == globalmes_list[i].primitive) &&
2913                    ((1 << proc->state) & globalmes_list[i].state))
2914                        break;
2915        if (i == ARRAY_SIZE(globalmes_list)) {
2916                if (st->l3.debug & L3_DEB_STATE) {
2917                        l3_debug(st, "dss1 global state %d mt %x unhandled",
2918                                proc->state, mt);
2919                }
2920                MsgHead(p, proc->callref, MT_STATUS);
2921                *p++ = IE_CAUSE;
2922                *p++ = 0x2;
2923                *p++ = 0x80;
2924                *p++ = 81 |0x80;        /* invalid cr */
2925                *p++ = 0x14;            /* CallState */
2926                *p++ = 0x1;
2927                *p++ = proc->state & 0x3f;
2928                l = p - tmp;
2929                if (!(skb = l3_alloc_skb(l)))
2930                        return;
2931                memcpy(skb_put(skb, l), tmp, l);
2932                l3_msg(proc->st, DL_DATA | REQUEST, skb);
2933        } else {
2934                if (st->l3.debug & L3_DEB_STATE) {
2935                        l3_debug(st, "dss1 global %d mt %x",
2936                                proc->state, mt);
2937                }
2938                globalmes_list[i].rout(proc, mt, skb);
2939        }
2940}
2941
2942static void
2943dss1up(struct PStack *st, int pr, void *arg)
2944{
2945        int i, mt, cr, cause, callState;
2946        char *ptr;
2947        u_char *p;
2948        struct sk_buff *skb = arg;
2949        struct l3_process *proc;
2950
2951        switch (pr) {
2952                case (DL_DATA | INDICATION):
2953                case (DL_UNIT_DATA | INDICATION):
2954                        break;
2955                case (DL_ESTABLISH | CONFIRM):
2956                case (DL_ESTABLISH | INDICATION):
2957                case (DL_RELEASE | INDICATION):
2958                case (DL_RELEASE | CONFIRM):
2959                        l3_msg(st, pr, arg);
2960                        return;
2961                        break;
2962                default:
2963                        printk(KERN_ERR "HiSax dss1up unknown pr=%04x\n", pr);
2964                        return;
2965        }
2966        if (skb->len < 3) {
2967                l3_debug(st, "dss1up frame too short(%d)", skb->len);
2968                dev_kfree_skb(skb);
2969                return;
2970        }
2971
2972        if (skb->data[0] != PROTO_DIS_EURO) {
2973                if (st->l3.debug & L3_DEB_PROTERR) {
2974                        l3_debug(st, "dss1up%sunexpected discriminator %x message len %d",
2975                                 (pr == (DL_DATA | INDICATION)) ? " " : "(broadcast) ",
2976                                 skb->data[0], skb->len);
2977                }
2978                dev_kfree_skb(skb);
2979                return;
2980        }
2981        cr = getcallref(skb->data);
2982        if (skb->len < ((skb->data[1] & 0x0f) + 3)) {
2983                l3_debug(st, "dss1up frame too short(%d)", skb->len);
2984                dev_kfree_skb(skb);
2985                return;
2986        }
2987        mt = skb->data[skb->data[1] + 2];
2988        if (st->l3.debug & L3_DEB_STATE)
2989                l3_debug(st, "dss1up cr %d", cr);
2990        if (cr == -2) {  /* wrong Callref */
2991                if (st->l3.debug & L3_DEB_WARN)
2992                        l3_debug(st, "dss1up wrong Callref");
2993                dev_kfree_skb(skb);
2994                return;
2995        } else if (cr == -1) {  /* Dummy Callref */
2996                if (mt == MT_FACILITY)
2997                        if ((p = findie(skb->data, skb->len, IE_FACILITY, 0))) {
2998                                l3dss1_parse_facility(st, NULL, 
2999                                        (pr == (DL_DATA | INDICATION)) ? -1 : -2, p); 
3000                                dev_kfree_skb(skb);
3001                                return;  
3002                        }
3003                if (st->l3.debug & L3_DEB_WARN)
3004                        l3_debug(st, "dss1up dummy Callref (no facility msg or ie)");
3005                dev_kfree_skb(skb);
3006                return;
3007        } else if ((((skb->data[1] & 0x0f) == 1) && (0==(cr & 0x7f))) ||
3008                (((skb->data[1] & 0x0f) == 2) && (0==(cr & 0x7fff)))) { /* Global CallRef */
3009                if (st->l3.debug & L3_DEB_STATE)
3010                        l3_debug(st, "dss1up Global CallRef");
3011                global_handler(st, mt, skb);
3012                dev_kfree_skb(skb);
3013                return;
3014        } else if (!(proc = getl3proc(st, cr))) {
3015                /* No transaction process exist, that means no call with
3016                 * this callreference is active
3017                 */
3018                if (mt == MT_SETUP) {
3019                        /* Setup creates a new transaction process */
3020                        if (skb->data[2] & 0x80) {
3021                                /* Setup with wrong CREF flag */
3022                                if (st->l3.debug & L3_DEB_STATE)
3023                                        l3_debug(st, "dss1up wrong CRef flag");
3024                                dev_kfree_skb(skb);
3025                                return;
3026                        }
3027                        if (!(proc = dss1_new_l3_process(st, cr))) {
3028                                /* May be to answer with RELEASE_COMPLETE and
3029                                 * CAUSE 0x2f "Resource unavailable", but this
3030                                 * need a new_l3_process too ... arghh
3031                                 */
3032                                dev_kfree_skb(skb);
3033                                return;
3034                        }
3035                } else if (mt == MT_STATUS) {
3036                        cause = 0;
3037                        if ((ptr = findie(skb->data, skb->len, IE_CAUSE, 0)) != NULL) {
3038                                ptr++;
3039                                if (*ptr++ == 2)
3040                                        ptr++;
3041                                cause = *ptr & 0x7f;
3042                        }
3043                        callState = 0;
3044                        if ((ptr = findie(skb->data, skb->len, IE_CALL_STATE, 0)) != NULL) {
3045                                ptr++;
3046                                if (*ptr++ == 2)
3047                                        ptr++;
3048                                callState = *ptr;
3049                        }
3050                        /* ETS 300-104 part 2.4.1
3051                         * if setup has not been made and a message type
3052                         * MT_STATUS is received with call state == 0,
3053                         * we must send nothing
3054                         */
3055                        if (callState != 0) {
3056                                /* ETS 300-104 part 2.4.2
3057                                 * if setup has not been made and a message type
3058                                 * MT_STATUS is received with call state != 0,
3059                                 * we must send MT_RELEASE_COMPLETE cause 101
3060                                 */
3061                                if ((proc = dss1_new_l3_process(st, cr))) {
3062                                        proc->para.cause = 101;
3063                                        l3dss1_msg_without_setup(proc, 0, NULL);
3064                                }
3065                        }
3066                        dev_kfree_skb(skb);
3067                        return;
3068                } else if (mt == MT_RELEASE_COMPLETE) {
3069                        dev_kfree_skb(skb);
3070                        return;
3071                } else {
3072                        /* ETS 300-104 part 2
3073                         * if setup has not been made and a message type
3074                         * (except MT_SETUP and RELEASE_COMPLETE) is received,
3075                         * we must send MT_RELEASE_COMPLETE cause 81 */
3076                        dev_kfree_skb(skb);
3077                        if ((proc = dss1_new_l3_process(st, cr))) {
3078                                proc->para.cause = 81;
3079                                l3dss1_msg_without_setup(proc, 0, NULL);
3080                        }
3081                        return;
3082                }
3083        }
3084        if (l3dss1_check_messagetype_validity(proc, mt, skb)) {
3085                dev_kfree_skb(skb);
3086                return;
3087        }
3088        if ((p = findie(skb->data, skb->len, IE_DISPLAY, 0)) != NULL) 
3089          l3dss1_deliver_display(proc, pr, p); /* Display IE included */
3090        for (i = 0; i < ARRAY_SIZE(datastatelist); i++)
3091                if ((mt == datastatelist[i].primitive) &&
3092                    ((1 << proc->state) & datastatelist[i].state))
3093                        break;
3094        if (i == ARRAY_SIZE(datastatelist)) {
3095                if (st->l3.debug & L3_DEB_STATE) {
3096                        l3_debug(st, "dss1up%sstate %d mt %#x unhandled",
3097                                (pr == (DL_DATA | INDICATION)) ? " " : "(broadcast) ",
3098                                proc->state, mt);
3099                }
3100                if ((MT_RELEASE_COMPLETE != mt) && (MT_RELEASE != mt)) {
3101                        proc->para.cause = 101;
3102                        l3dss1_status_send(proc, pr, skb);
3103                }
3104        } else {
3105                if (st->l3.debug & L3_DEB_STATE) {
3106                        l3_debug(st, "dss1up%sstate %d mt %x",
3107                                (pr == (DL_DATA | INDICATION)) ? " " : "(broadcast) ",
3108                                proc->state, mt);
3109                }
3110                datastatelist[i].rout(proc, pr, skb);
3111        }
3112        dev_kfree_skb(skb);
3113        return;
3114}
3115
3116static void
3117dss1down(struct PStack *st, int pr, void *arg)
3118{
3119        int i, cr;
3120        struct l3_process *proc;
3121        struct Channel *chan;
3122
3123        if ((DL_ESTABLISH | REQUEST) == pr) {
3124                l3_msg(st, pr, NULL);
3125                return;
3126        } else if (((CC_SETUP | REQUEST) == pr) || ((CC_RESUME | REQUEST) == pr)) {
3127                chan = arg;
3128                cr = newcallref();
3129                cr |= 0x80;
3130                if ((proc = dss1_new_l3_process(st, cr))) {
3131                        proc->chan = chan;
3132                        chan->proc = proc;
3133                        memcpy(&proc->para.setup, &chan->setup, sizeof(setup_parm));
3134                        proc->callref = cr;
3135                }
3136        } else {
3137                proc = arg;
3138        }
3139        if (!proc) {
3140                printk(KERN_ERR "HiSax dss1down without proc pr=%04x\n", pr);
3141                return;
3142        }
3143
3144        if ( pr == (CC_TDSS1_IO | REQUEST)) {
3145                l3dss1_io_timer(proc); /* timer expires */ 
3146                return;
3147        }  
3148
3149        for (i = 0; i < ARRAY_SIZE(downstatelist); i++)
3150                if ((pr == downstatelist[i].primitive) &&
3151                    ((1 << proc->state) & downstatelist[i].state))
3152                        break;
3153        if (i == ARRAY_SIZE(downstatelist)) {
3154                if (st->l3.debug & L3_DEB_STATE) {
3155                        l3_debug(st, "dss1down state %d prim %#x unhandled",
3156                                proc->state, pr);
3157                }
3158        } else {
3159                if (st->l3.debug & L3_DEB_STATE) {
3160                        l3_debug(st, "dss1down state %d prim %#x",
3161                                proc->state, pr);
3162                }
3163                downstatelist[i].rout(proc, pr, arg);
3164        }
3165}
3166
3167static void
3168dss1man(struct PStack *st, int pr, void *arg)
3169{
3170        int i;
3171        struct l3_process *proc = arg;
3172 
3173        if (!proc) {
3174                printk(KERN_ERR "HiSax dss1man without proc pr=%04x\n", pr);
3175                return;
3176        }
3177        for (i = 0; i < ARRAY_SIZE(manstatelist); i++)
3178                if ((pr == manstatelist[i].primitive) &&
3179                    ((1 << proc->state) & manstatelist[i].state))
3180                        break;
3181        if (i == ARRAY_SIZE(manstatelist)) {
3182                if (st->l3.debug & L3_DEB_STATE) {
3183                        l3_debug(st, "cr %d dss1man state %d prim %#x unhandled",
3184                                proc->callref & 0x7f, proc->state, pr);
3185                }
3186        } else {
3187                if (st->l3.debug & L3_DEB_STATE) {
3188                        l3_debug(st, "cr %d dss1man state %d prim %#x",
3189                                proc->callref & 0x7f, proc->state, pr);
3190                }
3191                manstatelist[i].rout(proc, pr, arg);
3192        }
3193}
3194 
3195void
3196setstack_dss1(struct PStack *st)
3197{
3198        char tmp[64];
3199        int i;
3200
3201        st->lli.l4l3 = dss1down;
3202        st->lli.l4l3_proto = l3dss1_cmd_global;
3203        st->l2.l2l3 = dss1up;
3204        st->l3.l3ml3 = dss1man;
3205        st->l3.N303 = 1;
3206        st->prot.dss1.last_invoke_id = 0;
3207        st->prot.dss1.invoke_used[0] = 1; /* Bit 0 must always be set to 1 */
3208        i = 1;
3209        while (i < 32) 
3210                st->prot.dss1.invoke_used[i++] = 0;   
3211
3212        if (!(st->l3.global = kmalloc(sizeof(struct l3_process), GFP_ATOMIC))) {
3213                printk(KERN_ERR "HiSax can't get memory for dss1 global CR\n");
3214        } else {
3215                st->l3.global->state = 0;
3216                st->l3.global->callref = 0;
3217                st->l3.global->next = NULL;
3218                st->l3.global->debug = L3_DEB_WARN;
3219                st->l3.global->st = st;
3220                st->l3.global->N303 = 1;
3221                st->l3.global->prot.dss1.invoke_id = 0; 
3222
3223                L3InitTimer(st->l3.global, &st->l3.global->timer);
3224        }
3225        strcpy(tmp, dss1_revision);
3226        printk(KERN_INFO "HiSax: DSS1 Rev. %s\n", HiSax_getrev(tmp));
3227}
3228