linux/drivers/staging/i4l/pcbit/capi.c
<<
>>
Prefs
   1/*
   2 * CAPI encoder/decoder for
   3 * Portugal Telecom CAPI 2.0
   4 *
   5 * Copyright (C) 1996 Universidade de Lisboa
   6 *
   7 * Written by Pedro Roque Marques (roque@di.fc.ul.pt)
   8 *
   9 * This software may be used and distributed according to the terms of
  10 * the GNU General Public License, incorporated herein by reference.
  11 *
  12 * Not compatible with the AVM Gmbh. CAPI 2.0
  13 *
  14 */
  15
  16/*
  17 *        Documentation:
  18 *        - "Common ISDN API - Perfil Português - Versão 2.1",
  19 *           Telecom Portugal, Fev 1992.
  20 *        - "Common ISDN API - Especificação de protocolos para
  21 *           acesso aos canais B", Inesc, Jan 1994.
  22 */
  23
  24/*
  25 *        TODO: better decoding of Information Elements
  26 *              for debug purposes mainly
  27 *              encode our number in CallerPN and ConnectedPN
  28 */
  29
  30#include <linux/kernel.h>
  31
  32#include <linux/types.h>
  33#include <linux/slab.h>
  34#include <linux/mm.h>
  35
  36#include <linux/skbuff.h>
  37
  38#include <linux/io.h>
  39#include <linux/string.h>
  40
  41#include <linux/isdnif.h>
  42
  43#include "pcbit.h"
  44#include "edss1.h"
  45#include "capi.h"
  46
  47
  48/*
  49 *  Encoding of CAPI messages
  50 *
  51 */
  52
  53int capi_conn_req(const char *calledPN, struct sk_buff **skb, int proto)
  54{
  55        ushort len;
  56
  57        /*
  58         * length
  59         *   AppInfoMask - 2
  60         *   BC0         - 3
  61         *   BC1         - 1
  62         *   Chan        - 2
  63         *   Keypad      - 1
  64         *   CPN         - 1
  65         *   CPSA        - 1
  66         *   CalledPN    - 2 + strlen
  67         *   CalledPSA   - 1
  68         *   rest...     - 4
  69         *   ----------------
  70         *   Total        18 + strlen
  71         */
  72
  73        len = 18 + strlen(calledPN);
  74
  75        if (proto == ISDN_PROTO_L2_TRANS)
  76                len++;
  77
  78        if ((*skb = dev_alloc_skb(len)) == NULL) {
  79
  80                printk(KERN_WARNING "capi_conn_req: alloc_skb failed\n");
  81                return -1;
  82        }
  83
  84        /* InfoElmMask */
  85        *((ushort *)skb_put(*skb, 2)) = AppInfoMask;
  86
  87        if (proto == ISDN_PROTO_L2_TRANS)
  88        {
  89                /* Bearer Capability - Mandatory*/
  90                *(skb_put(*skb, 1)) = 3;        /* BC0.Length           */
  91                *(skb_put(*skb, 1)) = 0x80;     /* Speech               */
  92                *(skb_put(*skb, 1)) = 0x10;     /* Circuit Mode         */
  93                *(skb_put(*skb, 1)) = 0x23;     /* A-law                */
  94        } else {
  95                /* Bearer Capability - Mandatory*/
  96                *(skb_put(*skb, 1)) = 2;        /* BC0.Length           */
  97                *(skb_put(*skb, 1)) = 0x88;     /* Digital Information  */
  98                *(skb_put(*skb, 1)) = 0x90;     /* BC0.Octect4          */
  99        }
 100
 101        /* Bearer Capability - Optional*/
 102        *(skb_put(*skb, 1)) = 0;        /* BC1.Length = 0                    */
 103
 104        *(skb_put(*skb, 1)) = 1;        /* ChannelID.Length = 1              */
 105        *(skb_put(*skb, 1)) = 0x83;     /* Basic Interface - Any Channel     */
 106
 107        *(skb_put(*skb, 1)) = 0;        /* Keypad.Length = 0                 */
 108
 109
 110        *(skb_put(*skb, 1)) = 0;        /* CallingPN.Length = 0              */
 111        *(skb_put(*skb, 1)) = 0;        /* CallingPSA.Length = 0             */
 112
 113        /* Called Party Number */
 114        *(skb_put(*skb, 1)) = strlen(calledPN) + 1;
 115        *(skb_put(*skb, 1)) = 0x81;
 116        memcpy(skb_put(*skb, strlen(calledPN)), calledPN, strlen(calledPN));
 117
 118        /* '#' */
 119
 120        *(skb_put(*skb, 1)) = 0;       /* CalledPSA.Length = 0     */
 121
 122        /* LLC.Length  = 0; */
 123        /* HLC0.Length = 0; */
 124        /* HLC1.Length = 0; */
 125        /* UTUS.Length = 0; */
 126        memset(skb_put(*skb, 4), 0, 4);
 127
 128        return len;
 129}
 130
 131int capi_conn_resp(struct pcbit_chan *chan, struct sk_buff **skb)
 132{
 133
 134        if ((*skb = dev_alloc_skb(5)) == NULL) {
 135
 136                printk(KERN_WARNING "capi_conn_resp: alloc_skb failed\n");
 137                return -1;
 138        }
 139
 140        *((ushort *)skb_put(*skb, 2)) = chan->callref;
 141        *(skb_put(*skb, 1)) = 0x01;  /* ACCEPT_CALL */
 142        *(skb_put(*skb, 1)) = 0;
 143        *(skb_put(*skb, 1)) = 0;
 144
 145        return 5;
 146}
 147
 148int capi_conn_active_req(struct pcbit_chan *chan, struct sk_buff **skb)
 149{
 150        /*
 151         * 8 bytes
 152         */
 153
 154        if ((*skb = dev_alloc_skb(8)) == NULL) {
 155
 156                printk(KERN_WARNING "capi_conn_active_req: alloc_skb failed\n");
 157                return -1;
 158        }
 159
 160        *((ushort *)skb_put(*skb, 2)) = chan->callref;
 161
 162#ifdef DEBUG
 163        printk(KERN_DEBUG "Call Reference: %04x\n", chan->callref);
 164#endif
 165
 166        *(skb_put(*skb, 1)) = 0;       /*  BC.Length = 0;          */
 167        *(skb_put(*skb, 1)) = 0;       /*  ConnectedPN.Length = 0  */
 168        *(skb_put(*skb, 1)) = 0;       /*  PSA.Length              */
 169        *(skb_put(*skb, 1)) = 0;       /*  LLC.Length = 0;         */
 170        *(skb_put(*skb, 1)) = 0;       /*  HLC.Length = 0;         */
 171        *(skb_put(*skb, 1)) = 0;       /*  UTUS.Length = 0;        */
 172
 173        return 8;
 174}
 175
 176int capi_conn_active_resp(struct pcbit_chan *chan, struct sk_buff **skb)
 177{
 178        /*
 179         * 2 bytes
 180         */
 181
 182        if ((*skb = dev_alloc_skb(2)) == NULL) {
 183
 184                printk(KERN_WARNING "capi_conn_active_resp: alloc_skb failed\n");
 185                return -1;
 186        }
 187
 188        *((ushort *)skb_put(*skb, 2)) = chan->callref;
 189
 190        return 2;
 191}
 192
 193
 194int capi_select_proto_req(struct pcbit_chan *chan, struct sk_buff **skb,
 195                          int outgoing)
 196{
 197
 198        /*
 199         * 18 bytes
 200         */
 201
 202        if ((*skb = dev_alloc_skb(18)) == NULL) {
 203
 204                printk(KERN_WARNING "capi_select_proto_req: alloc_skb failed\n");
 205                return -1;
 206        }
 207
 208        *((ushort *)skb_put(*skb, 2)) = chan->callref;
 209
 210        /* Layer2 protocol */
 211
 212        switch (chan->proto) {
 213        case ISDN_PROTO_L2_X75I:
 214                *(skb_put(*skb, 1)) = 0x05;            /* LAPB */
 215                break;
 216        case ISDN_PROTO_L2_HDLC:
 217                *(skb_put(*skb, 1)) = 0x02;
 218                break;
 219        case ISDN_PROTO_L2_TRANS:
 220                /*
 221                 *      Voice (a-law)
 222                 */
 223                *(skb_put(*skb, 1)) = 0x06;
 224                break;
 225        default:
 226#ifdef DEBUG
 227                printk(KERN_DEBUG "Transparent\n");
 228#endif
 229                *(skb_put(*skb, 1)) = 0x03;
 230                break;
 231        }
 232
 233        *(skb_put(*skb, 1)) = (outgoing ? 0x02 : 0x42);    /* Don't ask */
 234        *(skb_put(*skb, 1)) = 0x00;
 235
 236        *((ushort *) skb_put(*skb, 2)) = MRU;
 237
 238
 239        *(skb_put(*skb, 1)) = 0x08;           /* Modulo */
 240        *(skb_put(*skb, 1)) = 0x07;           /* Max Window */
 241
 242        *(skb_put(*skb, 1)) = 0x01;           /* No Layer3 Protocol */
 243
 244        /*
 245         * 2 - layer3 MTU       [10]
 246         *   - Modulo           [12]
 247         *   - Window
 248         *   - layer1 proto     [14]
 249         *   - bitrate
 250         *   - sub-channel      [16]
 251         *   - layer1dataformat [17]
 252         */
 253
 254        memset(skb_put(*skb, 8), 0, 8);
 255
 256        return 18;
 257}
 258
 259
 260int capi_activate_transp_req(struct pcbit_chan *chan, struct sk_buff **skb)
 261{
 262
 263        if ((*skb = dev_alloc_skb(7)) == NULL) {
 264
 265                printk(KERN_WARNING "capi_activate_transp_req: alloc_skb failed\n");
 266                return -1;
 267        }
 268
 269        *((ushort *)skb_put(*skb, 2)) = chan->callref;
 270
 271
 272        *(skb_put(*skb, 1)) = chan->layer2link; /* Layer2 id */
 273        *(skb_put(*skb, 1)) = 0x00;             /* Transmit by default */
 274
 275        *((ushort *) skb_put(*skb, 2)) = MRU;
 276
 277        *(skb_put(*skb, 1)) = 0x01;             /* Enables reception*/
 278
 279        return 7;
 280}
 281
 282int capi_tdata_req(struct pcbit_chan *chan, struct sk_buff *skb)
 283{
 284        ushort data_len;
 285
 286
 287        /*
 288         * callref      - 2
 289         * layer2link   - 1
 290         * wBlockLength - 2
 291         * data         - 4
 292         * sernum       - 1
 293         */
 294
 295        data_len = skb->len;
 296
 297        if (skb_headroom(skb) < 10)
 298        {
 299                printk(KERN_CRIT "No headspace (%u) on headroom %p for capi header\n", skb_headroom(skb), skb);
 300        }
 301        else
 302        {
 303                skb_push(skb, 10);
 304        }
 305
 306        *((u16 *) (skb->data)) = chan->callref;
 307        skb->data[2] = chan->layer2link;
 308        *((u16 *) (skb->data + 3)) = data_len;
 309
 310        chan->s_refnum = (chan->s_refnum + 1) % 8;
 311        *((u32 *) (skb->data + 5)) = chan->s_refnum;
 312
 313        skb->data[9] = 0;                           /* HDLC frame number */
 314
 315        return 10;
 316}
 317
 318int capi_tdata_resp(struct pcbit_chan *chan, struct sk_buff **skb)
 319
 320{
 321        if ((*skb = dev_alloc_skb(4)) == NULL) {
 322
 323                printk(KERN_WARNING "capi_tdata_resp: alloc_skb failed\n");
 324                return -1;
 325        }
 326
 327        *((ushort *)skb_put(*skb, 2)) = chan->callref;
 328
 329        *(skb_put(*skb, 1)) = chan->layer2link;
 330        *(skb_put(*skb, 1)) = chan->r_refnum;
 331
 332        return (*skb)->len;
 333}
 334
 335int capi_disc_req(ushort callref, struct sk_buff **skb, u_char cause)
 336{
 337
 338        if ((*skb = dev_alloc_skb(6)) == NULL) {
 339
 340                printk(KERN_WARNING "capi_disc_req: alloc_skb failed\n");
 341                return -1;
 342        }
 343
 344        *((ushort *)skb_put(*skb, 2)) = callref;
 345
 346        *(skb_put(*skb, 1)) = 2;                  /* Cause.Length = 2; */
 347        *(skb_put(*skb, 1)) = 0x80;
 348        *(skb_put(*skb, 1)) = 0x80 | cause;
 349
 350        /*
 351         * Change it: we should send 'Sic transit gloria Mundi' here ;-)
 352         */
 353
 354        *(skb_put(*skb, 1)) = 0;                   /* UTUS.Length = 0;  */
 355
 356        return 6;
 357}
 358
 359int capi_disc_resp(struct pcbit_chan *chan, struct sk_buff **skb)
 360{
 361        if ((*skb = dev_alloc_skb(2)) == NULL) {
 362
 363                printk(KERN_WARNING "capi_disc_resp: alloc_skb failed\n");
 364                return -1;
 365        }
 366
 367        *((ushort *)skb_put(*skb, 2)) = chan->callref;
 368
 369        return 2;
 370}
 371
 372
 373/*
 374 *  Decoding of CAPI messages
 375 *
 376 */
 377
 378int capi_decode_conn_ind(struct pcbit_chan *chan,
 379                         struct sk_buff *skb,
 380                         struct callb_data *info)
 381{
 382        int CIlen, len;
 383
 384        /* Call Reference [CAPI] */
 385        chan->callref = *((ushort *)skb->data);
 386        skb_pull(skb, 2);
 387
 388#ifdef DEBUG
 389        printk(KERN_DEBUG "Call Reference: %04x\n", chan->callref);
 390#endif
 391
 392        /* Channel Identification */
 393
 394        /* Expect
 395           Len = 1
 396           Octect 3 = 0100 10CC - [ 7 Basic, 4 , 2-1 chan ]
 397        */
 398
 399        CIlen = skb->data[0];
 400#ifdef DEBUG
 401        if (CIlen == 1) {
 402
 403                if (((skb->data[1]) & 0xFC) == 0x48)
 404                        printk(KERN_DEBUG "decode_conn_ind: chan ok\n");
 405                printk(KERN_DEBUG "phyChan = %d\n", skb->data[1] & 0x03);
 406        }
 407        else
 408                printk(KERN_DEBUG "conn_ind: CIlen = %d\n", CIlen);
 409#endif
 410        skb_pull(skb, CIlen + 1);
 411
 412        /* Calling Party Number */
 413        /* An "additional service" as far as Portugal Telecom is concerned */
 414
 415        len = skb->data[0];
 416
 417        if (len > 0) {
 418                int count = 1;
 419
 420#ifdef DEBUG
 421                printk(KERN_DEBUG "CPN: Octect 3 %02x\n", skb->data[1]);
 422#endif
 423                if ((skb->data[1] & 0x80) == 0)
 424                        count = 2;
 425
 426                if (!(info->data.setup.CallingPN = kmalloc(len - count + 1, GFP_ATOMIC)))
 427                        return -1;
 428
 429                skb_copy_from_linear_data_offset(skb, count + 1,
 430                                                 info->data.setup.CallingPN,
 431                                                 len - count);
 432                info->data.setup.CallingPN[len - count] = 0;
 433
 434        }
 435        else {
 436                info->data.setup.CallingPN = NULL;
 437                printk(KERN_DEBUG "NULL CallingPN\n");
 438        }
 439
 440        skb_pull(skb, len + 1);
 441
 442        /* Calling Party Subaddress */
 443        skb_pull(skb, skb->data[0] + 1);
 444
 445        /* Called Party Number */
 446
 447        len = skb->data[0];
 448
 449        if (len > 0) {
 450                int count = 1;
 451
 452                if ((skb->data[1] & 0x80) == 0)
 453                        count = 2;
 454
 455                if (!(info->data.setup.CalledPN = kmalloc(len - count + 1, GFP_ATOMIC)))
 456                        return -1;
 457
 458                skb_copy_from_linear_data_offset(skb, count + 1,
 459                                                 info->data.setup.CalledPN,
 460                                                 len - count);
 461                info->data.setup.CalledPN[len - count] = 0;
 462
 463        }
 464        else {
 465                info->data.setup.CalledPN = NULL;
 466                printk(KERN_DEBUG "NULL CalledPN\n");
 467        }
 468
 469        skb_pull(skb, len + 1);
 470
 471        /* Called Party Subaddress */
 472        skb_pull(skb, skb->data[0] + 1);
 473
 474        /* LLC */
 475        skb_pull(skb, skb->data[0] + 1);
 476
 477        /* HLC */
 478        skb_pull(skb, skb->data[0] + 1);
 479
 480        /* U2U */
 481        skb_pull(skb, skb->data[0] + 1);
 482
 483        return 0;
 484}
 485
 486/*
 487 *  returns errcode
 488 */
 489
 490int capi_decode_conn_conf(struct pcbit_chan *chan, struct sk_buff *skb,
 491                          int *complete)
 492{
 493        int errcode;
 494
 495        chan->callref = *((ushort *)skb->data);     /* Update CallReference */
 496        skb_pull(skb, 2);
 497
 498        errcode = *((ushort *) skb->data);   /* read errcode */
 499        skb_pull(skb, 2);
 500
 501        *complete = *(skb->data);
 502        skb_pull(skb, 1);
 503
 504        /* FIX ME */
 505        /* This is actually a firmware bug */
 506        if (!*complete)
 507        {
 508                printk(KERN_DEBUG "complete=%02x\n", *complete);
 509                *complete = 1;
 510        }
 511
 512
 513        /* Optional Bearer Capability */
 514        skb_pull(skb, *(skb->data) + 1);
 515
 516        /* Channel Identification */
 517        skb_pull(skb, *(skb->data) + 1);
 518
 519        /* High Layer Compatibility follows */
 520        skb_pull(skb, *(skb->data) + 1);
 521
 522        return errcode;
 523}
 524
 525int capi_decode_conn_actv_ind(struct pcbit_chan *chan, struct sk_buff *skb)
 526{
 527        ushort len;
 528#ifdef DEBUG
 529        char str[32];
 530#endif
 531
 532        /* Yet Another Bearer Capability */
 533        skb_pull(skb, *(skb->data) + 1);
 534
 535
 536        /* Connected Party Number */
 537        len = *(skb->data);
 538
 539#ifdef DEBUG
 540        if (len > 1 && len < 31) {
 541                skb_copy_from_linear_data_offset(skb, 2, str, len - 1);
 542                str[len] = 0;
 543                printk(KERN_DEBUG "Connected Party Number: %s\n", str);
 544        }
 545        else
 546                printk(KERN_DEBUG "actv_ind CPN len = %d\n", len);
 547#endif
 548
 549        skb_pull(skb, len + 1);
 550
 551        /* Connected Subaddress */
 552        skb_pull(skb, *(skb->data) + 1);
 553
 554        /* Low Layer Capability */
 555        skb_pull(skb, *(skb->data) + 1);
 556
 557        /* High Layer Capability */
 558        skb_pull(skb, *(skb->data) + 1);
 559
 560        return 0;
 561}
 562
 563int capi_decode_conn_actv_conf(struct pcbit_chan *chan, struct sk_buff *skb)
 564{
 565        ushort errcode;
 566
 567        errcode = *((ushort *)skb->data);
 568        skb_pull(skb, 2);
 569
 570        /* Channel Identification
 571           skb_pull(skb, skb->data[0] + 1);
 572        */
 573        return errcode;
 574}
 575
 576
 577int capi_decode_sel_proto_conf(struct pcbit_chan *chan, struct sk_buff *skb)
 578{
 579        ushort errcode;
 580
 581        chan->layer2link = *(skb->data);
 582        skb_pull(skb, 1);
 583
 584        errcode = *((ushort *)skb->data);
 585        skb_pull(skb, 2);
 586
 587        return errcode;
 588}
 589
 590int capi_decode_actv_trans_conf(struct pcbit_chan *chan, struct sk_buff *skb)
 591{
 592        ushort errcode;
 593
 594        if (chan->layer2link != *(skb->data))
 595                printk("capi_decode_actv_trans_conf: layer2link doesn't match\n");
 596
 597        skb_pull(skb, 1);
 598
 599        errcode = *((ushort *)skb->data);
 600        skb_pull(skb, 2);
 601
 602        return errcode;
 603}
 604
 605int capi_decode_disc_ind(struct pcbit_chan *chan, struct sk_buff *skb)
 606{
 607        ushort len;
 608#ifdef DEBUG
 609        int i;
 610#endif
 611        /* Cause */
 612
 613        len = *(skb->data);
 614        skb_pull(skb, 1);
 615
 616#ifdef DEBUG
 617
 618        for (i = 0; i < len; i++)
 619                printk(KERN_DEBUG "Cause Octect %d: %02x\n", i + 3,
 620                       *(skb->data + i));
 621#endif
 622
 623        skb_pull(skb, len);
 624
 625        return 0;
 626}
 627
 628#ifdef DEBUG
 629int capi_decode_debug_188(u_char *hdr, ushort hdrlen)
 630{
 631        char str[64];
 632        int len;
 633
 634        len = hdr[0];
 635
 636        if (len < 64 && len == hdrlen - 1) {
 637                memcpy(str, hdr + 1, hdrlen - 1);
 638                str[hdrlen - 1] = 0;
 639                printk("%s\n", str);
 640        }
 641        else
 642                printk("debug message incorrect\n");
 643
 644        return 0;
 645}
 646#endif
 647