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