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