linux/drivers/isdn/hisax/tei.c
<<
>>
Prefs
   1/* $Id: tei.c,v 2.20.2.3 2004/01/13 14:31:26 keil Exp $
   2 *
   3 * Author       Karsten Keil
   4 *              based on the teles driver from Jan den Ouden
   5 * Copyright    by Karsten Keil      <keil@isdn4linux.de>
   6 * 
   7 * This software may be used and distributed according to the terms
   8 * of the GNU General Public License, incorporated herein by reference.
   9 *
  10 * For changes and modifications please read
  11 * Documentation/isdn/HiSax.cert
  12 *
  13 * Thanks to    Jan den Ouden
  14 *              Fritz Elfert
  15 *
  16 */
  17
  18#include "hisax.h"
  19#include "isdnl2.h"
  20#include <linux/init.h>
  21#include <linux/random.h>
  22
  23const char *tei_revision = "$Revision: 2.20.2.3 $";
  24
  25#define ID_REQUEST      1
  26#define ID_ASSIGNED     2
  27#define ID_DENIED       3
  28#define ID_CHK_REQ      4
  29#define ID_CHK_RES      5
  30#define ID_REMOVE       6
  31#define ID_VERIFY       7
  32
  33#define TEI_ENTITY_ID   0xf
  34
  35static struct Fsm teifsm;
  36
  37void tei_handler(struct PStack *st, u_char pr, struct sk_buff *skb);
  38
  39enum {
  40        ST_TEI_NOP,
  41        ST_TEI_IDREQ,
  42        ST_TEI_IDVERIFY,
  43};
  44
  45#define TEI_STATE_COUNT (ST_TEI_IDVERIFY+1)
  46
  47static char *strTeiState[] =
  48{
  49        "ST_TEI_NOP",
  50        "ST_TEI_IDREQ",
  51        "ST_TEI_IDVERIFY",
  52};
  53
  54enum {
  55        EV_IDREQ,
  56        EV_ASSIGN,
  57        EV_DENIED,
  58        EV_CHKREQ,
  59        EV_REMOVE,
  60        EV_VERIFY,
  61        EV_T202,
  62};
  63
  64#define TEI_EVENT_COUNT (EV_T202+1)
  65
  66static char *strTeiEvent[] =
  67{
  68        "EV_IDREQ",
  69        "EV_ASSIGN",
  70        "EV_DENIED",
  71        "EV_CHKREQ",
  72        "EV_REMOVE",
  73        "EV_VERIFY",
  74        "EV_T202",
  75};
  76
  77static unsigned int
  78random_ri(void)
  79{
  80        unsigned int x;
  81
  82        get_random_bytes(&x, sizeof(x));
  83        return (x & 0xffff);
  84}
  85
  86static struct PStack *
  87findtei(struct PStack *st, int tei)
  88{
  89        struct PStack *ptr = *(st->l1.stlistp);
  90
  91        if (tei == 127)
  92                return (NULL);
  93
  94        while (ptr)
  95                if (ptr->l2.tei == tei)
  96                        return (ptr);
  97                else
  98                        ptr = ptr->next;
  99        return (NULL);
 100}
 101
 102static void
 103put_tei_msg(struct PStack *st, u_char m_id, unsigned int ri, u_char tei)
 104{
 105        struct sk_buff *skb;
 106        u_char *bp;
 107
 108        if (!(skb = alloc_skb(8, GFP_ATOMIC))) {
 109                printk(KERN_WARNING "HiSax: No skb for TEI manager\n");
 110                return;
 111        }
 112        bp = skb_put(skb, 3);
 113        bp[0] = (TEI_SAPI << 2);
 114        bp[1] = (GROUP_TEI << 1) | 0x1;
 115        bp[2] = UI;
 116        bp = skb_put(skb, 5);
 117        bp[0] = TEI_ENTITY_ID;
 118        bp[1] = ri >> 8;
 119        bp[2] = ri & 0xff;
 120        bp[3] = m_id;
 121        bp[4] = (tei << 1) | 1;
 122        st->l2.l2l1(st, PH_DATA | REQUEST, skb);
 123}
 124
 125static void
 126tei_id_request(struct FsmInst *fi, int event, void *arg)
 127{
 128        struct PStack *st = fi->userdata;
 129
 130        if (st->l2.tei != -1) {
 131                st->ma.tei_m.printdebug(&st->ma.tei_m,
 132                        "assign request for allready asigned tei %d",
 133                        st->l2.tei);
 134                return;
 135        }
 136        st->ma.ri = random_ri();
 137        if (st->ma.debug)
 138                st->ma.tei_m.printdebug(&st->ma.tei_m,
 139                        "assign request ri %d", st->ma.ri);
 140        put_tei_msg(st, ID_REQUEST, st->ma.ri, 127);
 141        FsmChangeState(&st->ma.tei_m, ST_TEI_IDREQ);
 142        FsmAddTimer(&st->ma.t202, st->ma.T202, EV_T202, NULL, 1);
 143        st->ma.N202 = 3;
 144}
 145
 146static void
 147tei_id_assign(struct FsmInst *fi, int event, void *arg)
 148{
 149        struct PStack *ost, *st = fi->userdata;
 150        struct sk_buff *skb = arg;
 151        struct IsdnCardState *cs;
 152        int ri, tei;
 153
 154        ri = ((unsigned int) skb->data[1] << 8) + skb->data[2];
 155        tei = skb->data[4] >> 1;
 156        if (st->ma.debug)
 157                st->ma.tei_m.printdebug(&st->ma.tei_m,
 158                        "identity assign ri %d tei %d", ri, tei);
 159        if ((ost = findtei(st, tei))) { /* same tei is in use */
 160                if (ri != ost->ma.ri) {
 161                        st->ma.tei_m.printdebug(&st->ma.tei_m,
 162                                "possible duplicate assignment tei %d", tei);
 163                        ost->l2.l2tei(ost, MDL_ERROR | RESPONSE, NULL);
 164                }
 165        } else if (ri == st->ma.ri) {
 166                FsmDelTimer(&st->ma.t202, 1);
 167                FsmChangeState(&st->ma.tei_m, ST_TEI_NOP);
 168                st->l3.l3l2(st, MDL_ASSIGN | REQUEST, (void *) (long) tei);
 169                cs = (struct IsdnCardState *) st->l1.hardware;
 170                cs->cardmsg(cs, MDL_ASSIGN | REQUEST, NULL);
 171        }
 172}
 173
 174static void
 175tei_id_test_dup(struct FsmInst *fi, int event, void *arg)
 176{
 177        struct PStack *ost, *st = fi->userdata;
 178        struct sk_buff *skb = arg;
 179        int tei, ri;
 180
 181        ri = ((unsigned int) skb->data[1] << 8) + skb->data[2];
 182        tei = skb->data[4] >> 1;
 183        if (st->ma.debug)
 184                st->ma.tei_m.printdebug(&st->ma.tei_m,
 185                        "foreign identity assign ri %d tei %d", ri, tei);
 186        if ((ost = findtei(st, tei))) { /* same tei is in use */
 187                if (ri != ost->ma.ri) { /* and it wasn't our request */
 188                        st->ma.tei_m.printdebug(&st->ma.tei_m,
 189                                "possible duplicate assignment tei %d", tei);
 190                        FsmEvent(&ost->ma.tei_m, EV_VERIFY, NULL);
 191                }
 192        } 
 193}
 194
 195static void
 196tei_id_denied(struct FsmInst *fi, int event, void *arg)
 197{
 198        struct PStack *st = fi->userdata;
 199        struct sk_buff *skb = arg;
 200        int ri, tei;
 201
 202        ri = ((unsigned int) skb->data[1] << 8) + skb->data[2];
 203        tei = skb->data[4] >> 1;
 204        if (st->ma.debug)
 205                st->ma.tei_m.printdebug(&st->ma.tei_m,
 206                        "identity denied ri %d tei %d", ri, tei);
 207}
 208
 209static void
 210tei_id_chk_req(struct FsmInst *fi, int event, void *arg)
 211{
 212        struct PStack *st = fi->userdata;
 213        struct sk_buff *skb = arg;
 214        int tei;
 215
 216        tei = skb->data[4] >> 1;
 217        if (st->ma.debug)
 218                st->ma.tei_m.printdebug(&st->ma.tei_m,
 219                        "identity check req tei %d", tei);
 220        if ((st->l2.tei != -1) && ((tei == GROUP_TEI) || (tei == st->l2.tei))) {
 221                FsmDelTimer(&st->ma.t202, 4);
 222                FsmChangeState(&st->ma.tei_m, ST_TEI_NOP);
 223                put_tei_msg(st, ID_CHK_RES, random_ri(), st->l2.tei);
 224        }
 225}
 226
 227static void
 228tei_id_remove(struct FsmInst *fi, int event, void *arg)
 229{
 230        struct PStack *st = fi->userdata;
 231        struct sk_buff *skb = arg;
 232        struct IsdnCardState *cs;
 233        int tei;
 234
 235        tei = skb->data[4] >> 1;
 236        if (st->ma.debug)
 237                st->ma.tei_m.printdebug(&st->ma.tei_m,
 238                        "identity remove tei %d", tei);
 239        if ((st->l2.tei != -1) && ((tei == GROUP_TEI) || (tei == st->l2.tei))) {
 240                FsmDelTimer(&st->ma.t202, 5);
 241                FsmChangeState(&st->ma.tei_m, ST_TEI_NOP);
 242                st->l3.l3l2(st, MDL_REMOVE | REQUEST, NULL);
 243                cs = (struct IsdnCardState *) st->l1.hardware;
 244                cs->cardmsg(cs, MDL_REMOVE | REQUEST, NULL);
 245        }
 246}
 247
 248static void
 249tei_id_verify(struct FsmInst *fi, int event, void *arg)
 250{
 251        struct PStack *st = fi->userdata;
 252
 253        if (st->ma.debug)
 254                st->ma.tei_m.printdebug(&st->ma.tei_m,
 255                        "id verify request for tei %d", st->l2.tei);
 256        put_tei_msg(st, ID_VERIFY, 0, st->l2.tei);
 257        FsmChangeState(&st->ma.tei_m, ST_TEI_IDVERIFY);
 258        FsmAddTimer(&st->ma.t202, st->ma.T202, EV_T202, NULL, 2);
 259        st->ma.N202 = 2;
 260}
 261
 262static void
 263tei_id_req_tout(struct FsmInst *fi, int event, void *arg)
 264{
 265        struct PStack *st = fi->userdata;
 266        struct IsdnCardState *cs;
 267
 268        if (--st->ma.N202) {
 269                st->ma.ri = random_ri();
 270                if (st->ma.debug)
 271                        st->ma.tei_m.printdebug(&st->ma.tei_m,
 272                                "assign req(%d) ri %d", 4 - st->ma.N202,
 273                                st->ma.ri);
 274                put_tei_msg(st, ID_REQUEST, st->ma.ri, 127);
 275                FsmAddTimer(&st->ma.t202, st->ma.T202, EV_T202, NULL, 3);
 276        } else {
 277                st->ma.tei_m.printdebug(&st->ma.tei_m, "assign req failed");
 278                st->l3.l3l2(st, MDL_ERROR | RESPONSE, NULL);
 279                cs = (struct IsdnCardState *) st->l1.hardware;
 280                cs->cardmsg(cs, MDL_REMOVE | REQUEST, NULL);
 281                FsmChangeState(fi, ST_TEI_NOP);
 282        }
 283}
 284
 285static void
 286tei_id_ver_tout(struct FsmInst *fi, int event, void *arg)
 287{
 288        struct PStack *st = fi->userdata;
 289        struct IsdnCardState *cs;
 290
 291        if (--st->ma.N202) {
 292                if (st->ma.debug)
 293                        st->ma.tei_m.printdebug(&st->ma.tei_m,
 294                                "id verify req(%d) for tei %d",
 295                                3 - st->ma.N202, st->l2.tei);
 296                put_tei_msg(st, ID_VERIFY, 0, st->l2.tei);
 297                FsmAddTimer(&st->ma.t202, st->ma.T202, EV_T202, NULL, 4);
 298        } else {
 299                st->ma.tei_m.printdebug(&st->ma.tei_m,
 300                        "verify req for tei %d failed", st->l2.tei);
 301                st->l3.l3l2(st, MDL_REMOVE | REQUEST, NULL);
 302                cs = (struct IsdnCardState *) st->l1.hardware;
 303                cs->cardmsg(cs, MDL_REMOVE | REQUEST, NULL);
 304                FsmChangeState(fi, ST_TEI_NOP);
 305        }
 306}
 307
 308static void
 309tei_l1l2(struct PStack *st, int pr, void *arg)
 310{
 311        struct sk_buff *skb = arg;
 312        int mt;
 313
 314        if (test_bit(FLG_FIXED_TEI, &st->l2.flag)) {
 315                dev_kfree_skb(skb);
 316                return;
 317        }
 318
 319        if (pr == (PH_DATA | INDICATION)) {
 320                if (skb->len < 3) {
 321                        st->ma.tei_m.printdebug(&st->ma.tei_m,
 322                                "short mgr frame %ld/3", skb->len);
 323                } else if ((skb->data[0] != ((TEI_SAPI << 2) | 2)) ||
 324                           (skb->data[1] != ((GROUP_TEI << 1) | 1))) {
 325                        st->ma.tei_m.printdebug(&st->ma.tei_m,
 326                                "wrong mgr sapi/tei %x/%x",
 327                                skb->data[0], skb->data[1]);
 328                } else if ((skb->data[2] & 0xef) != UI) {
 329                        st->ma.tei_m.printdebug(&st->ma.tei_m,
 330                                "mgr frame is not ui %x", skb->data[2]);
 331                } else {
 332                        skb_pull(skb, 3);
 333                        if (skb->len < 5) {
 334                                st->ma.tei_m.printdebug(&st->ma.tei_m,
 335                                        "short mgr frame %ld/5", skb->len);
 336                        } else if (skb->data[0] != TEI_ENTITY_ID) {
 337                                /* wrong management entity identifier, ignore */
 338                                st->ma.tei_m.printdebug(&st->ma.tei_m,
 339                                        "tei handler wrong entity id %x",
 340                                        skb->data[0]);
 341                        } else {
 342                                mt = skb->data[3];
 343                                if (mt == ID_ASSIGNED)
 344                                        FsmEvent(&st->ma.tei_m, EV_ASSIGN, skb);
 345                                else if (mt == ID_DENIED)
 346                                        FsmEvent(&st->ma.tei_m, EV_DENIED, skb);
 347                                else if (mt == ID_CHK_REQ)
 348                                        FsmEvent(&st->ma.tei_m, EV_CHKREQ, skb);
 349                                else if (mt == ID_REMOVE)
 350                                        FsmEvent(&st->ma.tei_m, EV_REMOVE, skb);
 351                                else {
 352                                        st->ma.tei_m.printdebug(&st->ma.tei_m,
 353                                                "tei handler wrong mt %x\n", mt);
 354                                }
 355                        }
 356                }
 357        } else {
 358                st->ma.tei_m.printdebug(&st->ma.tei_m,
 359                        "tei handler wrong pr %x\n", pr);
 360        }
 361        dev_kfree_skb(skb);
 362}
 363
 364static void
 365tei_l2tei(struct PStack *st, int pr, void *arg)
 366{
 367        struct IsdnCardState *cs;
 368
 369        if (test_bit(FLG_FIXED_TEI, &st->l2.flag)) {
 370                if (pr == (MDL_ASSIGN | INDICATION)) {
 371                        if (st->ma.debug)
 372                                st->ma.tei_m.printdebug(&st->ma.tei_m,
 373                                        "fixed assign tei %d", st->l2.tei);
 374                        st->l3.l3l2(st, MDL_ASSIGN | REQUEST, (void *) (long) st->l2.tei);
 375                        cs = (struct IsdnCardState *) st->l1.hardware;
 376                        cs->cardmsg(cs, MDL_ASSIGN | REQUEST, NULL);
 377                }
 378                return;
 379        }
 380        switch (pr) {
 381                case (MDL_ASSIGN | INDICATION):
 382                        FsmEvent(&st->ma.tei_m, EV_IDREQ, arg);
 383                        break;
 384                case (MDL_ERROR | REQUEST):
 385                        FsmEvent(&st->ma.tei_m, EV_VERIFY, arg);
 386                        break;
 387                default:
 388                        break;
 389        }
 390}
 391
 392static void
 393tei_debug(struct FsmInst *fi, char *fmt, ...)
 394{
 395        va_list args;
 396        struct PStack *st = fi->userdata;
 397
 398        va_start(args, fmt);
 399        VHiSax_putstatus(st->l1.hardware, "tei ", fmt, args);
 400        va_end(args);
 401}
 402
 403void
 404setstack_tei(struct PStack *st)
 405{
 406        st->l2.l2tei = tei_l2tei;
 407        st->ma.T202 = 2000;     /* T202  2000 milliseconds */
 408        st->l1.l1tei = tei_l1l2;
 409        st->ma.debug = 1;
 410        st->ma.tei_m.fsm = &teifsm;
 411        st->ma.tei_m.state = ST_TEI_NOP;
 412        st->ma.tei_m.debug = 1;
 413        st->ma.tei_m.userdata = st;
 414        st->ma.tei_m.userint = 0;
 415        st->ma.tei_m.printdebug = tei_debug;
 416        FsmInitTimer(&st->ma.tei_m, &st->ma.t202);
 417}
 418
 419void
 420init_tei(struct IsdnCardState *cs, int protocol)
 421{
 422}
 423
 424void
 425release_tei(struct IsdnCardState *cs)
 426{
 427        struct PStack *st = cs->stlist;
 428
 429        while (st) {
 430                FsmDelTimer(&st->ma.t202, 1);
 431                st = st->next;
 432        }
 433}
 434
 435static struct FsmNode TeiFnList[] __initdata =
 436{
 437        {ST_TEI_NOP, EV_IDREQ, tei_id_request},
 438        {ST_TEI_NOP, EV_ASSIGN, tei_id_test_dup},
 439        {ST_TEI_NOP, EV_VERIFY, tei_id_verify},
 440        {ST_TEI_NOP, EV_REMOVE, tei_id_remove},
 441        {ST_TEI_NOP, EV_CHKREQ, tei_id_chk_req},
 442        {ST_TEI_IDREQ, EV_T202, tei_id_req_tout},
 443        {ST_TEI_IDREQ, EV_ASSIGN, tei_id_assign},
 444        {ST_TEI_IDREQ, EV_DENIED, tei_id_denied},
 445        {ST_TEI_IDVERIFY, EV_T202, tei_id_ver_tout},
 446        {ST_TEI_IDVERIFY, EV_REMOVE, tei_id_remove},
 447        {ST_TEI_IDVERIFY, EV_CHKREQ, tei_id_chk_req},
 448};
 449
 450int __init
 451TeiNew(void)
 452{
 453        teifsm.state_count = TEI_STATE_COUNT;
 454        teifsm.event_count = TEI_EVENT_COUNT;
 455        teifsm.strEvent = strTeiEvent;
 456        teifsm.strState = strTeiState;
 457        return FsmNew(&teifsm, TeiFnList, ARRAY_SIZE(TeiFnList));
 458}
 459
 460void
 461TeiFree(void)
 462{
 463        FsmFree(&teifsm);
 464}
 465