linux/drivers/staging/i4l/act2000/capi.c
<<
>>
Prefs
   1/* $Id: capi.c,v 1.9.6.2 2001/09/23 22:24:32 kai Exp $
   2 *
   3 * ISDN lowlevel-module for the IBM ISDN-S0 Active 2000.
   4 * CAPI encoder/decoder
   5 *
   6 * Author       Fritz Elfert
   7 * Copyright    by Fritz Elfert      <fritz@isdn4linux.de>
   8 *
   9 * This software may be used and distributed according to the terms
  10 * of the GNU General Public License, incorporated herein by reference.
  11 *
  12 * Thanks to Friedemann Baitinger and IBM Germany
  13 *
  14 */
  15
  16#include "act2000.h"
  17#include "capi.h"
  18
  19static actcapi_msgdsc valid_msg[] = {
  20        {{ 0x86, 0x02}, "DATA_B3_IND"},       /* DATA_B3_IND/CONF must be first because of speed!!! */
  21        {{ 0x86, 0x01}, "DATA_B3_CONF"},
  22        {{ 0x02, 0x01}, "CONNECT_CONF"},
  23        {{ 0x02, 0x02}, "CONNECT_IND"},
  24        {{ 0x09, 0x01}, "CONNECT_INFO_CONF"},
  25        {{ 0x03, 0x02}, "CONNECT_ACTIVE_IND"},
  26        {{ 0x04, 0x01}, "DISCONNECT_CONF"},
  27        {{ 0x04, 0x02}, "DISCONNECT_IND"},
  28        {{ 0x05, 0x01}, "LISTEN_CONF"},
  29        {{ 0x06, 0x01}, "GET_PARAMS_CONF"},
  30        {{ 0x07, 0x01}, "INFO_CONF"},
  31        {{ 0x07, 0x02}, "INFO_IND"},
  32        {{ 0x08, 0x01}, "DATA_CONF"},
  33        {{ 0x08, 0x02}, "DATA_IND"},
  34        {{ 0x40, 0x01}, "SELECT_B2_PROTOCOL_CONF"},
  35        {{ 0x80, 0x01}, "SELECT_B3_PROTOCOL_CONF"},
  36        {{ 0x81, 0x01}, "LISTEN_B3_CONF"},
  37        {{ 0x82, 0x01}, "CONNECT_B3_CONF"},
  38        {{ 0x82, 0x02}, "CONNECT_B3_IND"},
  39        {{ 0x83, 0x02}, "CONNECT_B3_ACTIVE_IND"},
  40        {{ 0x84, 0x01}, "DISCONNECT_B3_CONF"},
  41        {{ 0x84, 0x02}, "DISCONNECT_B3_IND"},
  42        {{ 0x85, 0x01}, "GET_B3_PARAMS_CONF"},
  43        {{ 0x01, 0x01}, "RESET_B3_CONF"},
  44        {{ 0x01, 0x02}, "RESET_B3_IND"},
  45        /* {{ 0x87, 0x02, "HANDSET_IND"}, not implemented */
  46        {{ 0xff, 0x01}, "MANUFACTURER_CONF"},
  47        {{ 0xff, 0x02}, "MANUFACTURER_IND"},
  48#ifdef DEBUG_MSG
  49        /* Requests */
  50        {{ 0x01, 0x00}, "RESET_B3_REQ"},
  51        {{ 0x02, 0x00}, "CONNECT_REQ"},
  52        {{ 0x04, 0x00}, "DISCONNECT_REQ"},
  53        {{ 0x05, 0x00}, "LISTEN_REQ"},
  54        {{ 0x06, 0x00}, "GET_PARAMS_REQ"},
  55        {{ 0x07, 0x00}, "INFO_REQ"},
  56        {{ 0x08, 0x00}, "DATA_REQ"},
  57        {{ 0x09, 0x00}, "CONNECT_INFO_REQ"},
  58        {{ 0x40, 0x00}, "SELECT_B2_PROTOCOL_REQ"},
  59        {{ 0x80, 0x00}, "SELECT_B3_PROTOCOL_REQ"},
  60        {{ 0x81, 0x00}, "LISTEN_B3_REQ"},
  61        {{ 0x82, 0x00}, "CONNECT_B3_REQ"},
  62        {{ 0x84, 0x00}, "DISCONNECT_B3_REQ"},
  63        {{ 0x85, 0x00}, "GET_B3_PARAMS_REQ"},
  64        {{ 0x86, 0x00}, "DATA_B3_REQ"},
  65        {{ 0xff, 0x00}, "MANUFACTURER_REQ"},
  66        /* Responses */
  67        {{ 0x01, 0x03}, "RESET_B3_RESP"},
  68        {{ 0x02, 0x03}, "CONNECT_RESP"},
  69        {{ 0x03, 0x03}, "CONNECT_ACTIVE_RESP"},
  70        {{ 0x04, 0x03}, "DISCONNECT_RESP"},
  71        {{ 0x07, 0x03}, "INFO_RESP"},
  72        {{ 0x08, 0x03}, "DATA_RESP"},
  73        {{ 0x82, 0x03}, "CONNECT_B3_RESP"},
  74        {{ 0x83, 0x03}, "CONNECT_B3_ACTIVE_RESP"},
  75        {{ 0x84, 0x03}, "DISCONNECT_B3_RESP"},
  76        {{ 0x86, 0x03}, "DATA_B3_RESP"},
  77        {{ 0xff, 0x03}, "MANUFACTURER_RESP"},
  78#endif
  79        {{ 0x00, 0x00}, NULL},
  80};
  81#define num_valid_imsg 27 /* MANUFACTURER_IND */
  82
  83/*
  84 * Check for a valid incoming CAPI message.
  85 * Return:
  86 *   0 = Invalid message
  87 *   1 = Valid message, no B-Channel-data
  88 *   2 = Valid message, B-Channel-data
  89 */
  90int
  91actcapi_chkhdr(act2000_card *card, actcapi_msghdr *hdr)
  92{
  93        int i;
  94
  95        if (hdr->applicationID != 1)
  96                return 0;
  97        if (hdr->len < 9)
  98                return 0;
  99        for (i = 0; i < num_valid_imsg; i++)
 100                if ((hdr->cmd.cmd == valid_msg[i].cmd.cmd) &&
 101                    (hdr->cmd.subcmd == valid_msg[i].cmd.subcmd)) {
 102                        return (i ? 1 : 2);
 103                }
 104        return 0;
 105}
 106
 107#define ACTCAPI_MKHDR(l, c, s) {                                \
 108                skb = alloc_skb(l + 8, GFP_ATOMIC);             \
 109                if (skb) {                                      \
 110                        m = (actcapi_msg *)skb_put(skb, l + 8); \
 111                        m->hdr.len = l + 8;                     \
 112                        m->hdr.applicationID = 1;               \
 113                        m->hdr.cmd.cmd = c;                     \
 114                        m->hdr.cmd.subcmd = s;                  \
 115                        m->hdr.msgnum = actcapi_nextsmsg(card); \
 116                } else {                                        \
 117                        m = NULL;                               \
 118                }                                               \
 119        }
 120
 121#define ACTCAPI_CHKSKB if (!skb) {                                      \
 122                printk(KERN_WARNING "actcapi: alloc_skb failed\n");     \
 123                return;                                                 \
 124        }
 125
 126#define ACTCAPI_QUEUE_TX {                              \
 127                actcapi_debug_msg(skb, 1);              \
 128                skb_queue_tail(&card->sndq, skb);       \
 129                act2000_schedule_tx(card);              \
 130        }
 131
 132int
 133actcapi_listen_req(act2000_card *card)
 134{
 135        __u16 eazmask = 0;
 136        int i;
 137        actcapi_msg *m;
 138        struct sk_buff *skb;
 139
 140        for (i = 0; i < ACT2000_BCH; i++)
 141                eazmask |= card->bch[i].eazmask;
 142        ACTCAPI_MKHDR(9, 0x05, 0x00);
 143        if (!skb) {
 144                printk(KERN_WARNING "actcapi: alloc_skb failed\n");
 145                return -ENOMEM;
 146        }
 147        m->msg.listen_req.controller = 0;
 148        m->msg.listen_req.infomask = 0x3f; /* All information */
 149        m->msg.listen_req.eazmask = eazmask;
 150        m->msg.listen_req.simask = (eazmask) ? 0x86 : 0; /* All SI's  */
 151        ACTCAPI_QUEUE_TX;
 152        return 0;
 153}
 154
 155int
 156actcapi_connect_req(act2000_card *card, act2000_chan *chan, char *phone,
 157                    char eaz, int si1, int si2)
 158{
 159        actcapi_msg *m;
 160        struct sk_buff *skb;
 161
 162        ACTCAPI_MKHDR((11 + strlen(phone)), 0x02, 0x00);
 163        if (!skb) {
 164                printk(KERN_WARNING "actcapi: alloc_skb failed\n");
 165                chan->fsm_state = ACT2000_STATE_NULL;
 166                return -ENOMEM;
 167        }
 168        m->msg.connect_req.controller = 0;
 169        m->msg.connect_req.bchan = 0x83;
 170        m->msg.connect_req.infomask = 0x3f;
 171        m->msg.connect_req.si1 = si1;
 172        m->msg.connect_req.si2 = si2;
 173        m->msg.connect_req.eaz = eaz ? eaz : '0';
 174        m->msg.connect_req.addr.len = strlen(phone) + 1;
 175        m->msg.connect_req.addr.tnp = 0x81;
 176        memcpy(m->msg.connect_req.addr.num, phone, strlen(phone));
 177        chan->callref = m->hdr.msgnum;
 178        ACTCAPI_QUEUE_TX;
 179        return 0;
 180}
 181
 182static void
 183actcapi_connect_b3_req(act2000_card *card, act2000_chan *chan)
 184{
 185        actcapi_msg *m;
 186        struct sk_buff *skb;
 187
 188        ACTCAPI_MKHDR(17, 0x82, 0x00);
 189        ACTCAPI_CHKSKB;
 190        m->msg.connect_b3_req.plci = chan->plci;
 191        memset(&m->msg.connect_b3_req.ncpi, 0,
 192               sizeof(m->msg.connect_b3_req.ncpi));
 193        m->msg.connect_b3_req.ncpi.len = 13;
 194        m->msg.connect_b3_req.ncpi.modulo = 8;
 195        ACTCAPI_QUEUE_TX;
 196}
 197
 198/*
 199 * Set net type (1TR6) or (EDSS1)
 200 */
 201int
 202actcapi_manufacturer_req_net(act2000_card *card)
 203{
 204        actcapi_msg *m;
 205        struct sk_buff *skb;
 206
 207        ACTCAPI_MKHDR(5, 0xff, 0x00);
 208        if (!skb) {
 209                printk(KERN_WARNING "actcapi: alloc_skb failed\n");
 210                return -ENOMEM;
 211        }
 212        m->msg.manufacturer_req_net.manuf_msg = 0x11;
 213        m->msg.manufacturer_req_net.controller = 1;
 214        m->msg.manufacturer_req_net.nettype = (card->ptype == ISDN_PTYPE_EURO) ? 1 : 0;
 215        ACTCAPI_QUEUE_TX;
 216        printk(KERN_INFO "act2000 %s: D-channel protocol now %s\n",
 217               card->interface.id, (card->ptype == ISDN_PTYPE_EURO) ? "euro" : "1tr6");
 218        card->interface.features &=
 219                ~(ISDN_FEATURE_P_UNKNOWN | ISDN_FEATURE_P_EURO | ISDN_FEATURE_P_1TR6);
 220        card->interface.features |=
 221                ((card->ptype == ISDN_PTYPE_EURO) ? ISDN_FEATURE_P_EURO : ISDN_FEATURE_P_1TR6);
 222        return 0;
 223}
 224
 225/*
 226 * Switch V.42 on or off
 227 */
 228#if 0
 229int
 230actcapi_manufacturer_req_v42(act2000_card *card, ulong arg)
 231{
 232        actcapi_msg *m;
 233        struct sk_buff *skb;
 234
 235        ACTCAPI_MKHDR(8, 0xff, 0x00);
 236        if (!skb) {
 237
 238                printk(KERN_WARNING "actcapi: alloc_skb failed\n");
 239                return -ENOMEM;
 240        }
 241        m->msg.manufacturer_req_v42.manuf_msg = 0x10;
 242        m->msg.manufacturer_req_v42.controller = 0;
 243        m->msg.manufacturer_req_v42.v42control = (arg ? 1 : 0);
 244        ACTCAPI_QUEUE_TX;
 245        return 0;
 246}
 247#endif  /*  0  */
 248
 249/*
 250 * Set error-handler
 251 */
 252int
 253actcapi_manufacturer_req_errh(act2000_card *card)
 254{
 255        actcapi_msg *m;
 256        struct sk_buff *skb;
 257
 258        ACTCAPI_MKHDR(4, 0xff, 0x00);
 259        if (!skb) {
 260
 261                printk(KERN_WARNING "actcapi: alloc_skb failed\n");
 262                return -ENOMEM;
 263        }
 264        m->msg.manufacturer_req_err.manuf_msg = 0x03;
 265        m->msg.manufacturer_req_err.controller = 0;
 266        ACTCAPI_QUEUE_TX;
 267        return 0;
 268}
 269
 270/*
 271 * Set MSN-Mapping.
 272 */
 273int
 274actcapi_manufacturer_req_msn(act2000_card *card)
 275{
 276        msn_entry *p = card->msn_list;
 277        actcapi_msg *m;
 278        struct sk_buff *skb;
 279        int len;
 280
 281        while (p) {
 282                int i;
 283
 284                len = strlen(p->msn);
 285                for (i = 0; i < 2; i++) {
 286                        ACTCAPI_MKHDR(6 + len, 0xff, 0x00);
 287                        if (!skb) {
 288                                printk(KERN_WARNING "actcapi: alloc_skb failed\n");
 289                                return -ENOMEM;
 290                        }
 291                        m->msg.manufacturer_req_msn.manuf_msg = 0x13 + i;
 292                        m->msg.manufacturer_req_msn.controller = 0;
 293                        m->msg.manufacturer_req_msn.msnmap.eaz = p->eaz;
 294                        m->msg.manufacturer_req_msn.msnmap.len = len;
 295                        memcpy(m->msg.manufacturer_req_msn.msnmap.msn, p->msn, len);
 296                        ACTCAPI_QUEUE_TX;
 297                }
 298                p = p->next;
 299        }
 300        return 0;
 301}
 302
 303void
 304actcapi_select_b2_protocol_req(act2000_card *card, act2000_chan *chan)
 305{
 306        actcapi_msg *m;
 307        struct sk_buff *skb;
 308
 309        ACTCAPI_MKHDR(10, 0x40, 0x00);
 310        ACTCAPI_CHKSKB;
 311        m->msg.select_b2_protocol_req.plci = chan->plci;
 312        memset(&m->msg.select_b2_protocol_req.dlpd, 0,
 313               sizeof(m->msg.select_b2_protocol_req.dlpd));
 314        m->msg.select_b2_protocol_req.dlpd.len = 6;
 315        switch (chan->l2prot) {
 316        case ISDN_PROTO_L2_TRANS:
 317                m->msg.select_b2_protocol_req.protocol = 0x03;
 318                m->msg.select_b2_protocol_req.dlpd.dlen = 4000;
 319                break;
 320        case ISDN_PROTO_L2_HDLC:
 321                m->msg.select_b2_protocol_req.protocol = 0x02;
 322                m->msg.select_b2_protocol_req.dlpd.dlen = 4000;
 323                break;
 324        case ISDN_PROTO_L2_X75I:
 325        case ISDN_PROTO_L2_X75UI:
 326        case ISDN_PROTO_L2_X75BUI:
 327                m->msg.select_b2_protocol_req.protocol = 0x01;
 328                m->msg.select_b2_protocol_req.dlpd.dlen = 4000;
 329                m->msg.select_b2_protocol_req.dlpd.laa = 3;
 330                m->msg.select_b2_protocol_req.dlpd.lab = 1;
 331                m->msg.select_b2_protocol_req.dlpd.win = 7;
 332                m->msg.select_b2_protocol_req.dlpd.modulo = 8;
 333                break;
 334        }
 335        ACTCAPI_QUEUE_TX;
 336}
 337
 338static void
 339actcapi_select_b3_protocol_req(act2000_card *card, act2000_chan *chan)
 340{
 341        actcapi_msg *m;
 342        struct sk_buff *skb;
 343
 344        ACTCAPI_MKHDR(17, 0x80, 0x00);
 345        ACTCAPI_CHKSKB;
 346        m->msg.select_b3_protocol_req.plci = chan->plci;
 347        memset(&m->msg.select_b3_protocol_req.ncpd, 0,
 348               sizeof(m->msg.select_b3_protocol_req.ncpd));
 349        switch (chan->l3prot) {
 350        case ISDN_PROTO_L3_TRANS:
 351                m->msg.select_b3_protocol_req.protocol = 0x04;
 352                m->msg.select_b3_protocol_req.ncpd.len = 13;
 353                m->msg.select_b3_protocol_req.ncpd.modulo = 8;
 354                break;
 355        }
 356        ACTCAPI_QUEUE_TX;
 357}
 358
 359static void
 360actcapi_listen_b3_req(act2000_card *card, act2000_chan *chan)
 361{
 362        actcapi_msg *m;
 363        struct sk_buff *skb;
 364
 365        ACTCAPI_MKHDR(2, 0x81, 0x00);
 366        ACTCAPI_CHKSKB;
 367        m->msg.listen_b3_req.plci = chan->plci;
 368        ACTCAPI_QUEUE_TX;
 369}
 370
 371static void
 372actcapi_disconnect_req(act2000_card *card, act2000_chan *chan)
 373{
 374        actcapi_msg *m;
 375        struct sk_buff *skb;
 376
 377        ACTCAPI_MKHDR(3, 0x04, 0x00);
 378        ACTCAPI_CHKSKB;
 379        m->msg.disconnect_req.plci = chan->plci;
 380        m->msg.disconnect_req.cause = 0;
 381        ACTCAPI_QUEUE_TX;
 382}
 383
 384void
 385actcapi_disconnect_b3_req(act2000_card *card, act2000_chan *chan)
 386{
 387        actcapi_msg *m;
 388        struct sk_buff *skb;
 389
 390        ACTCAPI_MKHDR(17, 0x84, 0x00);
 391        ACTCAPI_CHKSKB;
 392        m->msg.disconnect_b3_req.ncci = chan->ncci;
 393        memset(&m->msg.disconnect_b3_req.ncpi, 0,
 394               sizeof(m->msg.disconnect_b3_req.ncpi));
 395        m->msg.disconnect_b3_req.ncpi.len = 13;
 396        m->msg.disconnect_b3_req.ncpi.modulo = 8;
 397        chan->fsm_state = ACT2000_STATE_BHWAIT;
 398        ACTCAPI_QUEUE_TX;
 399}
 400
 401void
 402actcapi_connect_resp(act2000_card *card, act2000_chan *chan, __u8 cause)
 403{
 404        actcapi_msg *m;
 405        struct sk_buff *skb;
 406
 407        ACTCAPI_MKHDR(3, 0x02, 0x03);
 408        ACTCAPI_CHKSKB;
 409        m->msg.connect_resp.plci = chan->plci;
 410        m->msg.connect_resp.rejectcause = cause;
 411        if (cause) {
 412                chan->fsm_state = ACT2000_STATE_NULL;
 413                chan->plci = 0x8000;
 414        } else
 415                chan->fsm_state = ACT2000_STATE_IWAIT;
 416        ACTCAPI_QUEUE_TX;
 417}
 418
 419static void
 420actcapi_connect_active_resp(act2000_card *card, act2000_chan *chan)
 421{
 422        actcapi_msg *m;
 423        struct sk_buff *skb;
 424
 425        ACTCAPI_MKHDR(2, 0x03, 0x03);
 426        ACTCAPI_CHKSKB;
 427        m->msg.connect_resp.plci = chan->plci;
 428        if (chan->fsm_state == ACT2000_STATE_IWAIT)
 429                chan->fsm_state = ACT2000_STATE_IBWAIT;
 430        ACTCAPI_QUEUE_TX;
 431}
 432
 433static void
 434actcapi_connect_b3_resp(act2000_card *card, act2000_chan *chan, __u8 rejectcause)
 435{
 436        actcapi_msg *m;
 437        struct sk_buff *skb;
 438
 439        ACTCAPI_MKHDR((rejectcause ? 3 : 17), 0x82, 0x03);
 440        ACTCAPI_CHKSKB;
 441        m->msg.connect_b3_resp.ncci = chan->ncci;
 442        m->msg.connect_b3_resp.rejectcause = rejectcause;
 443        if (!rejectcause) {
 444                memset(&m->msg.connect_b3_resp.ncpi, 0,
 445                       sizeof(m->msg.connect_b3_resp.ncpi));
 446                m->msg.connect_b3_resp.ncpi.len = 13;
 447                m->msg.connect_b3_resp.ncpi.modulo = 8;
 448                chan->fsm_state = ACT2000_STATE_BWAIT;
 449        }
 450        ACTCAPI_QUEUE_TX;
 451}
 452
 453static void
 454actcapi_connect_b3_active_resp(act2000_card *card, act2000_chan *chan)
 455{
 456        actcapi_msg *m;
 457        struct sk_buff *skb;
 458
 459        ACTCAPI_MKHDR(2, 0x83, 0x03);
 460        ACTCAPI_CHKSKB;
 461        m->msg.connect_b3_active_resp.ncci = chan->ncci;
 462        chan->fsm_state = ACT2000_STATE_ACTIVE;
 463        ACTCAPI_QUEUE_TX;
 464}
 465
 466static void
 467actcapi_info_resp(act2000_card *card, act2000_chan *chan)
 468{
 469        actcapi_msg *m;
 470        struct sk_buff *skb;
 471
 472        ACTCAPI_MKHDR(2, 0x07, 0x03);
 473        ACTCAPI_CHKSKB;
 474        m->msg.info_resp.plci = chan->plci;
 475        ACTCAPI_QUEUE_TX;
 476}
 477
 478static void
 479actcapi_disconnect_b3_resp(act2000_card *card, act2000_chan *chan)
 480{
 481        actcapi_msg *m;
 482        struct sk_buff *skb;
 483
 484        ACTCAPI_MKHDR(2, 0x84, 0x03);
 485        ACTCAPI_CHKSKB;
 486        m->msg.disconnect_b3_resp.ncci = chan->ncci;
 487        chan->ncci = 0x8000;
 488        chan->queued = 0;
 489        ACTCAPI_QUEUE_TX;
 490}
 491
 492static void
 493actcapi_disconnect_resp(act2000_card *card, act2000_chan *chan)
 494{
 495        actcapi_msg *m;
 496        struct sk_buff *skb;
 497
 498        ACTCAPI_MKHDR(2, 0x04, 0x03);
 499        ACTCAPI_CHKSKB;
 500        m->msg.disconnect_resp.plci = chan->plci;
 501        chan->plci = 0x8000;
 502        ACTCAPI_QUEUE_TX;
 503}
 504
 505static int
 506new_plci(act2000_card *card, __u16 plci)
 507{
 508        int i;
 509        for (i = 0; i < ACT2000_BCH; i++)
 510                if (card->bch[i].plci == 0x8000) {
 511                        card->bch[i].plci = plci;
 512                        return i;
 513                }
 514        return -1;
 515}
 516
 517static int
 518find_plci(act2000_card *card, __u16 plci)
 519{
 520        int i;
 521        for (i = 0; i < ACT2000_BCH; i++)
 522                if (card->bch[i].plci == plci)
 523                        return i;
 524        return -1;
 525}
 526
 527static int
 528find_ncci(act2000_card *card, __u16 ncci)
 529{
 530        int i;
 531        for (i = 0; i < ACT2000_BCH; i++)
 532                if (card->bch[i].ncci == ncci)
 533                        return i;
 534        return -1;
 535}
 536
 537static int
 538find_dialing(act2000_card *card, __u16 callref)
 539{
 540        int i;
 541        for (i = 0; i < ACT2000_BCH; i++)
 542                if ((card->bch[i].callref == callref) &&
 543                    (card->bch[i].fsm_state == ACT2000_STATE_OCALL))
 544                        return i;
 545        return -1;
 546}
 547
 548static int
 549actcapi_data_b3_ind(act2000_card *card, struct sk_buff *skb) {
 550        __u16 plci;
 551        __u16 ncci;
 552        __u8  blocknr;
 553        int chan;
 554        actcapi_msg *msg = (actcapi_msg *)skb->data;
 555
 556        EVAL_NCCI(msg->msg.data_b3_ind.fakencci, plci, ncci);
 557        chan = find_ncci(card, ncci);
 558        if (chan < 0)
 559                return 0;
 560        if (card->bch[chan].fsm_state != ACT2000_STATE_ACTIVE)
 561                return 0;
 562        if (card->bch[chan].plci != plci)
 563                return 0;
 564        blocknr = msg->msg.data_b3_ind.blocknr;
 565        skb_pull(skb, 19);
 566        card->interface.rcvcallb_skb(card->myid, chan, skb);
 567        if (!(skb = alloc_skb(11, GFP_ATOMIC))) {
 568                printk(KERN_WARNING "actcapi: alloc_skb failed\n");
 569                return 1;
 570        }
 571        msg = (actcapi_msg *)skb_put(skb, 11);
 572        msg->hdr.len = 11;
 573        msg->hdr.applicationID = 1;
 574        msg->hdr.cmd.cmd = 0x86;
 575        msg->hdr.cmd.subcmd = 0x03;
 576        msg->hdr.msgnum = actcapi_nextsmsg(card);
 577        msg->msg.data_b3_resp.ncci = ncci;
 578        msg->msg.data_b3_resp.blocknr = blocknr;
 579        ACTCAPI_QUEUE_TX;
 580        return 1;
 581}
 582
 583/*
 584 * Walk over ackq, unlink DATA_B3_REQ from it, if
 585 * ncci and blocknr are matching.
 586 * Decrement queued-bytes counter.
 587 */
 588static int
 589handle_ack(act2000_card *card, act2000_chan *chan, __u8 blocknr) {
 590        unsigned long flags;
 591        struct sk_buff *skb;
 592        struct sk_buff *tmp;
 593        struct actcapi_msg *m;
 594        int ret = 0;
 595
 596        spin_lock_irqsave(&card->lock, flags);
 597        skb = skb_peek(&card->ackq);
 598        spin_unlock_irqrestore(&card->lock, flags);
 599        if (!skb) {
 600                printk(KERN_WARNING "act2000: handle_ack nothing found!\n");
 601                return 0;
 602        }
 603        tmp = skb;
 604        while (1) {
 605                m = (actcapi_msg *)tmp->data;
 606                if ((((m->msg.data_b3_req.fakencci >> 8) & 0xff) == chan->ncci) &&
 607                    (m->msg.data_b3_req.blocknr == blocknr)) {
 608                        /* found corresponding DATA_B3_REQ */
 609                        skb_unlink(tmp, &card->ackq);
 610                        chan->queued -= m->msg.data_b3_req.datalen;
 611                        if (m->msg.data_b3_req.flags)
 612                                ret = m->msg.data_b3_req.datalen;
 613                        dev_kfree_skb(tmp);
 614                        if (chan->queued < 0)
 615                                chan->queued = 0;
 616                        return ret;
 617                }
 618                spin_lock_irqsave(&card->lock, flags);
 619                tmp = skb_peek((struct sk_buff_head *)tmp);
 620                spin_unlock_irqrestore(&card->lock, flags);
 621                if ((tmp == skb) || !tmp) {
 622                        /* reached end of queue */
 623                        printk(KERN_WARNING "act2000: handle_ack nothing found!\n");
 624                        return 0;
 625                }
 626        }
 627}
 628
 629void
 630actcapi_dispatch(struct work_struct *work)
 631{
 632        struct act2000_card *card =
 633                container_of(work, struct act2000_card, rcv_tq);
 634        struct sk_buff *skb;
 635        actcapi_msg *msg;
 636        __u16 ccmd;
 637        int chan;
 638        int len;
 639        act2000_chan *ctmp;
 640        isdn_ctrl cmd;
 641        char tmp[170];
 642
 643        while ((skb = skb_dequeue(&card->rcvq))) {
 644                actcapi_debug_msg(skb, 0);
 645                msg = (actcapi_msg *)skb->data;
 646                ccmd = ((msg->hdr.cmd.cmd << 8) | msg->hdr.cmd.subcmd);
 647                switch (ccmd) {
 648                case 0x8602:
 649                        /* DATA_B3_IND */
 650                        if (actcapi_data_b3_ind(card, skb))
 651                                return;
 652                        break;
 653                case 0x8601:
 654                        /* DATA_B3_CONF */
 655                        chan = find_ncci(card, msg->msg.data_b3_conf.ncci);
 656                        if ((chan >= 0) && (card->bch[chan].fsm_state == ACT2000_STATE_ACTIVE)) {
 657                                if (msg->msg.data_b3_conf.info != 0)
 658                                        printk(KERN_WARNING "act2000: DATA_B3_CONF: %04x\n",
 659                                               msg->msg.data_b3_conf.info);
 660                                len = handle_ack(card, &card->bch[chan],
 661                                                 msg->msg.data_b3_conf.blocknr);
 662                                if (len) {
 663                                        cmd.driver = card->myid;
 664                                        cmd.command = ISDN_STAT_BSENT;
 665                                        cmd.arg = chan;
 666                                        cmd.parm.length = len;
 667                                        card->interface.statcallb(&cmd);
 668                                }
 669                        }
 670                        break;
 671                case 0x0201:
 672                        /* CONNECT_CONF */
 673                        chan = find_dialing(card, msg->hdr.msgnum);
 674                        if (chan >= 0) {
 675                                if (msg->msg.connect_conf.info) {
 676                                        card->bch[chan].fsm_state = ACT2000_STATE_NULL;
 677                                        cmd.driver = card->myid;
 678                                        cmd.command = ISDN_STAT_DHUP;
 679                                        cmd.arg = chan;
 680                                        card->interface.statcallb(&cmd);
 681                                } else {
 682                                        card->bch[chan].fsm_state = ACT2000_STATE_OWAIT;
 683                                        card->bch[chan].plci = msg->msg.connect_conf.plci;
 684                                }
 685                        }
 686                        break;
 687                case 0x0202:
 688                        /* CONNECT_IND */
 689                        chan = new_plci(card, msg->msg.connect_ind.plci);
 690                        if (chan < 0) {
 691                                ctmp = (act2000_chan *)tmp;
 692                                ctmp->plci = msg->msg.connect_ind.plci;
 693                                actcapi_connect_resp(card, ctmp, 0x11); /* All Card-Cannels busy */
 694                        } else {
 695                                card->bch[chan].fsm_state = ACT2000_STATE_ICALL;
 696                                cmd.driver = card->myid;
 697                                cmd.command = ISDN_STAT_ICALL;
 698                                cmd.arg = chan;
 699                                cmd.parm.setup.si1 = msg->msg.connect_ind.si1;
 700                                cmd.parm.setup.si2 = msg->msg.connect_ind.si2;
 701                                if (card->ptype == ISDN_PTYPE_EURO)
 702                                        strcpy(cmd.parm.setup.eazmsn,
 703                                               act2000_find_eaz(card, msg->msg.connect_ind.eaz));
 704                                else {
 705                                        cmd.parm.setup.eazmsn[0] = msg->msg.connect_ind.eaz;
 706                                        cmd.parm.setup.eazmsn[1] = 0;
 707                                }
 708                                memset(cmd.parm.setup.phone, 0, sizeof(cmd.parm.setup.phone));
 709                                memcpy(cmd.parm.setup.phone, msg->msg.connect_ind.addr.num,
 710                                       msg->msg.connect_ind.addr.len - 1);
 711                                cmd.parm.setup.plan = msg->msg.connect_ind.addr.tnp;
 712                                cmd.parm.setup.screen = 0;
 713                                if (card->interface.statcallb(&cmd) == 2)
 714                                        actcapi_connect_resp(card, &card->bch[chan], 0x15); /* Reject Call */
 715                        }
 716                        break;
 717                case 0x0302:
 718                        /* CONNECT_ACTIVE_IND */
 719                        chan = find_plci(card, msg->msg.connect_active_ind.plci);
 720                        if (chan >= 0)
 721                                switch (card->bch[chan].fsm_state) {
 722                                case ACT2000_STATE_IWAIT:
 723                                        actcapi_connect_active_resp(card, &card->bch[chan]);
 724                                        break;
 725                                case ACT2000_STATE_OWAIT:
 726                                        actcapi_connect_active_resp(card, &card->bch[chan]);
 727                                        actcapi_select_b2_protocol_req(card, &card->bch[chan]);
 728                                        break;
 729                                }
 730                        break;
 731                case 0x8202:
 732                        /* CONNECT_B3_IND */
 733                        chan = find_plci(card, msg->msg.connect_b3_ind.plci);
 734                        if ((chan >= 0) && (card->bch[chan].fsm_state == ACT2000_STATE_IBWAIT)) {
 735                                card->bch[chan].ncci = msg->msg.connect_b3_ind.ncci;
 736                                actcapi_connect_b3_resp(card, &card->bch[chan], 0);
 737                        } else {
 738                                ctmp = (act2000_chan *)tmp;
 739                                ctmp->ncci = msg->msg.connect_b3_ind.ncci;
 740                                actcapi_connect_b3_resp(card, ctmp, 0x11); /* All Card-Cannels busy */
 741                        }
 742                        break;
 743                case 0x8302:
 744                        /* CONNECT_B3_ACTIVE_IND */
 745                        chan = find_ncci(card, msg->msg.connect_b3_active_ind.ncci);
 746                        if ((chan >= 0) && (card->bch[chan].fsm_state == ACT2000_STATE_BWAIT)) {
 747                                actcapi_connect_b3_active_resp(card, &card->bch[chan]);
 748                                cmd.driver = card->myid;
 749                                cmd.command = ISDN_STAT_BCONN;
 750                                cmd.arg = chan;
 751                                card->interface.statcallb(&cmd);
 752                        }
 753                        break;
 754                case 0x8402:
 755                        /* DISCONNECT_B3_IND */
 756                        chan = find_ncci(card, msg->msg.disconnect_b3_ind.ncci);
 757                        if (chan >= 0) {
 758                                ctmp = &card->bch[chan];
 759                                actcapi_disconnect_b3_resp(card, ctmp);
 760                                switch (ctmp->fsm_state) {
 761                                case ACT2000_STATE_ACTIVE:
 762                                        ctmp->fsm_state = ACT2000_STATE_DHWAIT2;
 763                                        cmd.driver = card->myid;
 764                                        cmd.command = ISDN_STAT_BHUP;
 765                                        cmd.arg = chan;
 766                                        card->interface.statcallb(&cmd);
 767                                        break;
 768                                case ACT2000_STATE_BHWAIT2:
 769                                        actcapi_disconnect_req(card, ctmp);
 770                                        ctmp->fsm_state = ACT2000_STATE_DHWAIT;
 771                                        cmd.driver = card->myid;
 772                                        cmd.command = ISDN_STAT_BHUP;
 773                                        cmd.arg = chan;
 774                                        card->interface.statcallb(&cmd);
 775                                        break;
 776                                }
 777                        }
 778                        break;
 779                case 0x0402:
 780                        /* DISCONNECT_IND */
 781                        chan = find_plci(card, msg->msg.disconnect_ind.plci);
 782                        if (chan >= 0) {
 783                                ctmp = &card->bch[chan];
 784                                actcapi_disconnect_resp(card, ctmp);
 785                                ctmp->fsm_state = ACT2000_STATE_NULL;
 786                                cmd.driver = card->myid;
 787                                cmd.command = ISDN_STAT_DHUP;
 788                                cmd.arg = chan;
 789                                card->interface.statcallb(&cmd);
 790                        } else {
 791                                ctmp = (act2000_chan *)tmp;
 792                                ctmp->plci = msg->msg.disconnect_ind.plci;
 793                                actcapi_disconnect_resp(card, ctmp);
 794                        }
 795                        break;
 796                case 0x4001:
 797                        /* SELECT_B2_PROTOCOL_CONF */
 798                        chan = find_plci(card, msg->msg.select_b2_protocol_conf.plci);
 799                        if (chan >= 0)
 800                                switch (card->bch[chan].fsm_state) {
 801                                case ACT2000_STATE_ICALL:
 802                                case ACT2000_STATE_OWAIT:
 803                                        ctmp = &card->bch[chan];
 804                                        if (msg->msg.select_b2_protocol_conf.info == 0)
 805                                                actcapi_select_b3_protocol_req(card, ctmp);
 806                                        else {
 807                                                ctmp->fsm_state = ACT2000_STATE_NULL;
 808                                                cmd.driver = card->myid;
 809                                                cmd.command = ISDN_STAT_DHUP;
 810                                                cmd.arg = chan;
 811                                                card->interface.statcallb(&cmd);
 812                                        }
 813                                        break;
 814                                }
 815                        break;
 816                case 0x8001:
 817                        /* SELECT_B3_PROTOCOL_CONF */
 818                        chan = find_plci(card, msg->msg.select_b3_protocol_conf.plci);
 819                        if (chan >= 0)
 820                                switch (card->bch[chan].fsm_state) {
 821                                case ACT2000_STATE_ICALL:
 822                                case ACT2000_STATE_OWAIT:
 823                                        ctmp = &card->bch[chan];
 824                                        if (msg->msg.select_b3_protocol_conf.info == 0)
 825                                                actcapi_listen_b3_req(card, ctmp);
 826                                        else {
 827                                                ctmp->fsm_state = ACT2000_STATE_NULL;
 828                                                cmd.driver = card->myid;
 829                                                cmd.command = ISDN_STAT_DHUP;
 830                                                cmd.arg = chan;
 831                                                card->interface.statcallb(&cmd);
 832                                        }
 833                                }
 834                        break;
 835                case 0x8101:
 836                        /* LISTEN_B3_CONF */
 837                        chan = find_plci(card, msg->msg.listen_b3_conf.plci);
 838                        if (chan >= 0)
 839                                switch (card->bch[chan].fsm_state) {
 840                                case ACT2000_STATE_ICALL:
 841                                        ctmp = &card->bch[chan];
 842                                        if (msg->msg.listen_b3_conf.info == 0)
 843                                                actcapi_connect_resp(card, ctmp, 0);
 844                                        else {
 845                                                ctmp->fsm_state = ACT2000_STATE_NULL;
 846                                                cmd.driver = card->myid;
 847                                                cmd.command = ISDN_STAT_DHUP;
 848                                                cmd.arg = chan;
 849                                                card->interface.statcallb(&cmd);
 850                                        }
 851                                        break;
 852                                case ACT2000_STATE_OWAIT:
 853                                        ctmp = &card->bch[chan];
 854                                        if (msg->msg.listen_b3_conf.info == 0) {
 855                                                actcapi_connect_b3_req(card, ctmp);
 856                                                ctmp->fsm_state = ACT2000_STATE_OBWAIT;
 857                                                cmd.driver = card->myid;
 858                                                cmd.command = ISDN_STAT_DCONN;
 859                                                cmd.arg = chan;
 860                                                card->interface.statcallb(&cmd);
 861                                        } else {
 862                                                ctmp->fsm_state = ACT2000_STATE_NULL;
 863                                                cmd.driver = card->myid;
 864                                                cmd.command = ISDN_STAT_DHUP;
 865                                                cmd.arg = chan;
 866                                                card->interface.statcallb(&cmd);
 867                                        }
 868                                        break;
 869                                }
 870                        break;
 871                case 0x8201:
 872                        /* CONNECT_B3_CONF */
 873                        chan = find_plci(card, msg->msg.connect_b3_conf.plci);
 874                        if ((chan >= 0) && (card->bch[chan].fsm_state == ACT2000_STATE_OBWAIT)) {
 875                                ctmp = &card->bch[chan];
 876                                if (msg->msg.connect_b3_conf.info) {
 877                                        ctmp->fsm_state = ACT2000_STATE_NULL;
 878                                        cmd.driver = card->myid;
 879                                        cmd.command = ISDN_STAT_DHUP;
 880                                        cmd.arg = chan;
 881                                        card->interface.statcallb(&cmd);
 882                                } else {
 883                                        ctmp->ncci = msg->msg.connect_b3_conf.ncci;
 884                                        ctmp->fsm_state = ACT2000_STATE_BWAIT;
 885                                }
 886                        }
 887                        break;
 888                case 0x8401:
 889                        /* DISCONNECT_B3_CONF */
 890                        chan = find_ncci(card, msg->msg.disconnect_b3_conf.ncci);
 891                        if ((chan >= 0) && (card->bch[chan].fsm_state == ACT2000_STATE_BHWAIT))
 892                                card->bch[chan].fsm_state = ACT2000_STATE_BHWAIT2;
 893                        break;
 894                case 0x0702:
 895                        /* INFO_IND */
 896                        chan = find_plci(card, msg->msg.info_ind.plci);
 897                        if (chan >= 0)
 898                                /* TODO: Eval Charging info / cause */
 899                                actcapi_info_resp(card, &card->bch[chan]);
 900                        break;
 901                case 0x0401:
 902                        /* LISTEN_CONF */
 903                case 0x0501:
 904                        /* LISTEN_CONF */
 905                case 0xff01:
 906                        /* MANUFACTURER_CONF */
 907                        break;
 908                case 0xff02:
 909                        /* MANUFACTURER_IND */
 910                        if (msg->msg.manuf_msg == 3) {
 911                                memset(tmp, 0, sizeof(tmp));
 912                                strncpy(tmp,
 913                                        &msg->msg.manufacturer_ind_err.errstring,
 914                                        msg->hdr.len - 16);
 915                                if (msg->msg.manufacturer_ind_err.errcode)
 916                                        printk(KERN_WARNING "act2000: %s\n", tmp);
 917                                else {
 918                                        printk(KERN_DEBUG "act2000: %s\n", tmp);
 919                                        if ((!strncmp(tmp, "INFO: Trace buffer con", 22)) ||
 920                                            (!strncmp(tmp, "INFO: Compile Date/Tim", 22))) {
 921                                                card->flags |= ACT2000_FLAGS_RUNNING;
 922                                                cmd.command = ISDN_STAT_RUN;
 923                                                cmd.driver = card->myid;
 924                                                cmd.arg = 0;
 925                                                actcapi_manufacturer_req_net(card);
 926                                                actcapi_manufacturer_req_msn(card);
 927                                                actcapi_listen_req(card);
 928                                                card->interface.statcallb(&cmd);
 929                                        }
 930                                }
 931                        }
 932                        break;
 933                default:
 934                        printk(KERN_WARNING "act2000: UNHANDLED Message %04x\n", ccmd);
 935                        break;
 936                }
 937                dev_kfree_skb(skb);
 938        }
 939}
 940
 941#ifdef DEBUG_MSG
 942static void
 943actcapi_debug_caddr(actcapi_addr *addr)
 944{
 945        char tmp[30];
 946
 947        printk(KERN_DEBUG " Alen  = %d\n", addr->len);
 948        if (addr->len > 0)
 949                printk(KERN_DEBUG " Atnp  = 0x%02x\n", addr->tnp);
 950        if (addr->len > 1) {
 951                memset(tmp, 0, 30);
 952                memcpy(tmp, addr->num, addr->len - 1);
 953                printk(KERN_DEBUG " Anum  = '%s'\n", tmp);
 954        }
 955}
 956
 957static void
 958actcapi_debug_ncpi(actcapi_ncpi *ncpi)
 959{
 960        printk(KERN_DEBUG " ncpi.len = %d\n", ncpi->len);
 961        if (ncpi->len >= 2)
 962                printk(KERN_DEBUG " ncpi.lic = 0x%04x\n", ncpi->lic);
 963        if (ncpi->len >= 4)
 964                printk(KERN_DEBUG " ncpi.hic = 0x%04x\n", ncpi->hic);
 965        if (ncpi->len >= 6)
 966                printk(KERN_DEBUG " ncpi.ltc = 0x%04x\n", ncpi->ltc);
 967        if (ncpi->len >= 8)
 968                printk(KERN_DEBUG " ncpi.htc = 0x%04x\n", ncpi->htc);
 969        if (ncpi->len >= 10)
 970                printk(KERN_DEBUG " ncpi.loc = 0x%04x\n", ncpi->loc);
 971        if (ncpi->len >= 12)
 972                printk(KERN_DEBUG " ncpi.hoc = 0x%04x\n", ncpi->hoc);
 973        if (ncpi->len >= 13)
 974                printk(KERN_DEBUG " ncpi.mod = %d\n", ncpi->modulo);
 975}
 976
 977static void
 978actcapi_debug_dlpd(actcapi_dlpd *dlpd)
 979{
 980        printk(KERN_DEBUG " dlpd.len = %d\n", dlpd->len);
 981        if (dlpd->len >= 2)
 982                printk(KERN_DEBUG " dlpd.dlen   = 0x%04x\n", dlpd->dlen);
 983        if (dlpd->len >= 3)
 984                printk(KERN_DEBUG " dlpd.laa    = 0x%02x\n", dlpd->laa);
 985        if (dlpd->len >= 4)
 986                printk(KERN_DEBUG " dlpd.lab    = 0x%02x\n", dlpd->lab);
 987        if (dlpd->len >= 5)
 988                printk(KERN_DEBUG " dlpd.modulo = %d\n", dlpd->modulo);
 989        if (dlpd->len >= 6)
 990                printk(KERN_DEBUG " dlpd.win    = %d\n", dlpd->win);
 991}
 992
 993#ifdef DEBUG_DUMP_SKB
 994static void dump_skb(struct sk_buff *skb)
 995{
 996        char tmp[80];
 997        char *p = skb->data;
 998        char *t = tmp;
 999        int i;
1000
1001        for (i = 0; i < skb->len; i++) {
1002                t += sprintf(t, "%02x ", *p++ & 0xff);
1003                if ((i & 0x0f) == 8) {
1004                        printk(KERN_DEBUG "dump: %s\n", tmp);
1005                        t = tmp;
1006                }
1007        }
1008        if (i & 0x07)
1009                printk(KERN_DEBUG "dump: %s\n", tmp);
1010}
1011#endif
1012
1013void
1014actcapi_debug_msg(struct sk_buff *skb, int direction)
1015{
1016        actcapi_msg *msg = (actcapi_msg *)skb->data;
1017        char *descr;
1018        int i;
1019        char tmp[170];
1020
1021#ifndef DEBUG_DATA_MSG
1022        if (msg->hdr.cmd.cmd == 0x86)
1023                return;
1024#endif
1025        descr = "INVALID";
1026#ifdef DEBUG_DUMP_SKB
1027        dump_skb(skb);
1028#endif
1029        for (i = 0; i < ARRAY_SIZE(valid_msg); i++)
1030                if ((msg->hdr.cmd.cmd == valid_msg[i].cmd.cmd) &&
1031                    (msg->hdr.cmd.subcmd == valid_msg[i].cmd.subcmd)) {
1032                        descr = valid_msg[i].description;
1033                        break;
1034                }
1035        printk(KERN_DEBUG "%s %s msg\n", direction ? "Outgoing" : "Incoming", descr);
1036        printk(KERN_DEBUG " ApplID = %d\n", msg->hdr.applicationID);
1037        printk(KERN_DEBUG " Len    = %d\n", msg->hdr.len);
1038        printk(KERN_DEBUG " MsgNum = 0x%04x\n", msg->hdr.msgnum);
1039        printk(KERN_DEBUG " Cmd    = 0x%02x\n", msg->hdr.cmd.cmd);
1040        printk(KERN_DEBUG " SubCmd = 0x%02x\n", msg->hdr.cmd.subcmd);
1041        switch (i) {
1042        case 0:
1043                /* DATA B3 IND */
1044                printk(KERN_DEBUG " BLOCK = 0x%02x\n",
1045                       msg->msg.data_b3_ind.blocknr);
1046                break;
1047        case 2:
1048                /* CONNECT CONF */
1049                printk(KERN_DEBUG " PLCI = 0x%04x\n",
1050                       msg->msg.connect_conf.plci);
1051                printk(KERN_DEBUG " Info = 0x%04x\n",
1052                       msg->msg.connect_conf.info);
1053                break;
1054        case 3:
1055                /* CONNECT IND */
1056                printk(KERN_DEBUG " PLCI = 0x%04x\n",
1057                       msg->msg.connect_ind.plci);
1058                printk(KERN_DEBUG " Contr = %d\n",
1059                       msg->msg.connect_ind.controller);
1060                printk(KERN_DEBUG " SI1   = %d\n",
1061                       msg->msg.connect_ind.si1);
1062                printk(KERN_DEBUG " SI2   = %d\n",
1063                       msg->msg.connect_ind.si2);
1064                printk(KERN_DEBUG " EAZ   = '%c'\n",
1065                       msg->msg.connect_ind.eaz);
1066                actcapi_debug_caddr(&msg->msg.connect_ind.addr);
1067                break;
1068        case 5:
1069                /* CONNECT ACTIVE IND */
1070                printk(KERN_DEBUG " PLCI = 0x%04x\n",
1071                       msg->msg.connect_active_ind.plci);
1072                actcapi_debug_caddr(&msg->msg.connect_active_ind.addr);
1073                break;
1074        case 8:
1075                /* LISTEN CONF */
1076                printk(KERN_DEBUG " Contr = %d\n",
1077                       msg->msg.listen_conf.controller);
1078                printk(KERN_DEBUG " Info = 0x%04x\n",
1079                       msg->msg.listen_conf.info);
1080                break;
1081        case 11:
1082                /* INFO IND */
1083                printk(KERN_DEBUG " PLCI = 0x%04x\n",
1084                       msg->msg.info_ind.plci);
1085                printk(KERN_DEBUG " Imsk = 0x%04x\n",
1086                       msg->msg.info_ind.nr.mask);
1087                if (msg->hdr.len > 12) {
1088                        int l = msg->hdr.len - 12;
1089                        int j;
1090                        char *p = tmp;
1091                        for (j = 0; j < l; j++)
1092                                p += sprintf(p, "%02x ", msg->msg.info_ind.el.display[j]);
1093                        printk(KERN_DEBUG " D = '%s'\n", tmp);
1094                }
1095                break;
1096        case 14:
1097                /* SELECT B2 PROTOCOL CONF */
1098                printk(KERN_DEBUG " PLCI = 0x%04x\n",
1099                       msg->msg.select_b2_protocol_conf.plci);
1100                printk(KERN_DEBUG " Info = 0x%04x\n",
1101                       msg->msg.select_b2_protocol_conf.info);
1102                break;
1103        case 15:
1104                /* SELECT B3 PROTOCOL CONF */
1105                printk(KERN_DEBUG " PLCI = 0x%04x\n",
1106                       msg->msg.select_b3_protocol_conf.plci);
1107                printk(KERN_DEBUG " Info = 0x%04x\n",
1108                       msg->msg.select_b3_protocol_conf.info);
1109                break;
1110        case 16:
1111                /* LISTEN B3 CONF */
1112                printk(KERN_DEBUG " PLCI = 0x%04x\n",
1113                       msg->msg.listen_b3_conf.plci);
1114                printk(KERN_DEBUG " Info = 0x%04x\n",
1115                       msg->msg.listen_b3_conf.info);
1116                break;
1117        case 18:
1118                /* CONNECT B3 IND */
1119                printk(KERN_DEBUG " NCCI = 0x%04x\n",
1120                       msg->msg.connect_b3_ind.ncci);
1121                printk(KERN_DEBUG " PLCI = 0x%04x\n",
1122                       msg->msg.connect_b3_ind.plci);
1123                actcapi_debug_ncpi(&msg->msg.connect_b3_ind.ncpi);
1124                break;
1125        case 19:
1126                /* CONNECT B3 ACTIVE IND */
1127                printk(KERN_DEBUG " NCCI = 0x%04x\n",
1128                       msg->msg.connect_b3_active_ind.ncci);
1129                actcapi_debug_ncpi(&msg->msg.connect_b3_active_ind.ncpi);
1130                break;
1131        case 26:
1132                /* MANUFACTURER IND */
1133                printk(KERN_DEBUG " Mmsg = 0x%02x\n",
1134                       msg->msg.manufacturer_ind_err.manuf_msg);
1135                switch (msg->msg.manufacturer_ind_err.manuf_msg) {
1136                case 3:
1137                        printk(KERN_DEBUG " Contr = %d\n",
1138                               msg->msg.manufacturer_ind_err.controller);
1139                        printk(KERN_DEBUG " Code = 0x%08x\n",
1140                               msg->msg.manufacturer_ind_err.errcode);
1141                        memset(tmp, 0, sizeof(tmp));
1142                        strncpy(tmp, &msg->msg.manufacturer_ind_err.errstring,
1143                                msg->hdr.len - 16);
1144                        printk(KERN_DEBUG " Emsg = '%s'\n", tmp);
1145                        break;
1146                }
1147                break;
1148        case 30:
1149                /* LISTEN REQ */
1150                printk(KERN_DEBUG " Imsk = 0x%08x\n",
1151                       msg->msg.listen_req.infomask);
1152                printk(KERN_DEBUG " Emsk = 0x%04x\n",
1153                       msg->msg.listen_req.eazmask);
1154                printk(KERN_DEBUG " Smsk = 0x%04x\n",
1155                       msg->msg.listen_req.simask);
1156                break;
1157        case 35:
1158                /* SELECT_B2_PROTOCOL_REQ */
1159                printk(KERN_DEBUG " PLCI  = 0x%04x\n",
1160                       msg->msg.select_b2_protocol_req.plci);
1161                printk(KERN_DEBUG " prot  = 0x%02x\n",
1162                       msg->msg.select_b2_protocol_req.protocol);
1163                if (msg->hdr.len >= 11)
1164                        printk(KERN_DEBUG "No dlpd\n");
1165                else
1166                        actcapi_debug_dlpd(&msg->msg.select_b2_protocol_req.dlpd);
1167                break;
1168        case 44:
1169                /* CONNECT RESP */
1170                printk(KERN_DEBUG " PLCI  = 0x%04x\n",
1171                       msg->msg.connect_resp.plci);
1172                printk(KERN_DEBUG " CAUSE = 0x%02x\n",
1173                       msg->msg.connect_resp.rejectcause);
1174                break;
1175        case 45:
1176                /* CONNECT ACTIVE RESP */
1177                printk(KERN_DEBUG " PLCI  = 0x%04x\n",
1178                       msg->msg.connect_active_resp.plci);
1179                break;
1180        }
1181}
1182#endif
1183