linux/drivers/isdn/capi/capiutil.c
<<
>>
Prefs
   1/* $Id: capiutil.c,v 1.13.6.4 2001/09/23 22:24:33 kai Exp $
   2 *
   3 * CAPI 2.0 convert capi message to capi message struct
   4 *
   5 * From CAPI 2.0 Development Kit AVM 1995 (msg.c)
   6 * Rewritten for Linux 1996 by Carsten Paeth <calle@calle.de>
   7 *
   8 * This software may be used and distributed according to the terms
   9 * of the GNU General Public License, incorporated herein by reference.
  10 *
  11 */
  12
  13#include <linux/module.h>
  14#include <linux/string.h>
  15#include <linux/ctype.h>
  16#include <linux/stddef.h>
  17#include <linux/kernel.h>
  18#include <linux/mm.h>
  19#include <linux/init.h>
  20#include <linux/isdn/capiutil.h>
  21#include <linux/slab.h>
  22
  23/* from CAPI2.0 DDK AVM Berlin GmbH */
  24
  25typedef struct {
  26        int typ;
  27        size_t off;
  28} _cdef;
  29
  30#define _CBYTE         1
  31#define _CWORD         2
  32#define _CDWORD        3
  33#define _CSTRUCT       4
  34#define _CMSTRUCT      5
  35#define _CEND          6
  36
  37static _cdef cdef[] =
  38{
  39        /*00 */
  40        {_CEND},
  41        /*01 */
  42        {_CEND},
  43        /*02 */
  44        {_CEND},
  45        /*03 */
  46        {_CDWORD, offsetof(_cmsg, adr.adrController)},
  47        /*04 */
  48        {_CMSTRUCT, offsetof(_cmsg, AdditionalInfo)},
  49        /*05 */
  50        {_CSTRUCT, offsetof(_cmsg, B1configuration)},
  51        /*06 */
  52        {_CWORD, offsetof(_cmsg, B1protocol)},
  53        /*07 */
  54        {_CSTRUCT, offsetof(_cmsg, B2configuration)},
  55        /*08 */
  56        {_CWORD, offsetof(_cmsg, B2protocol)},
  57        /*09 */
  58        {_CSTRUCT, offsetof(_cmsg, B3configuration)},
  59        /*0a */
  60        {_CWORD, offsetof(_cmsg, B3protocol)},
  61        /*0b */
  62        {_CSTRUCT, offsetof(_cmsg, BC)},
  63        /*0c */
  64        {_CSTRUCT, offsetof(_cmsg, BChannelinformation)},
  65        /*0d */
  66        {_CMSTRUCT, offsetof(_cmsg, BProtocol)},
  67        /*0e */
  68        {_CSTRUCT, offsetof(_cmsg, CalledPartyNumber)},
  69        /*0f */
  70        {_CSTRUCT, offsetof(_cmsg, CalledPartySubaddress)},
  71        /*10 */
  72        {_CSTRUCT, offsetof(_cmsg, CallingPartyNumber)},
  73        /*11 */
  74        {_CSTRUCT, offsetof(_cmsg, CallingPartySubaddress)},
  75        /*12 */
  76        {_CDWORD, offsetof(_cmsg, CIPmask)},
  77        /*13 */
  78        {_CDWORD, offsetof(_cmsg, CIPmask2)},
  79        /*14 */
  80        {_CWORD, offsetof(_cmsg, CIPValue)},
  81        /*15 */
  82        {_CDWORD, offsetof(_cmsg, Class)},
  83        /*16 */
  84        {_CSTRUCT, offsetof(_cmsg, ConnectedNumber)},
  85        /*17 */
  86        {_CSTRUCT, offsetof(_cmsg, ConnectedSubaddress)},
  87        /*18 */
  88        {_CDWORD, offsetof(_cmsg, Data)},
  89        /*19 */
  90        {_CWORD, offsetof(_cmsg, DataHandle)},
  91        /*1a */
  92        {_CWORD, offsetof(_cmsg, DataLength)},
  93        /*1b */
  94        {_CSTRUCT, offsetof(_cmsg, FacilityConfirmationParameter)},
  95        /*1c */
  96        {_CSTRUCT, offsetof(_cmsg, Facilitydataarray)},
  97        /*1d */
  98        {_CSTRUCT, offsetof(_cmsg, FacilityIndicationParameter)},
  99        /*1e */
 100        {_CSTRUCT, offsetof(_cmsg, FacilityRequestParameter)},
 101        /*1f */
 102        {_CWORD, offsetof(_cmsg, FacilitySelector)},
 103        /*20 */
 104        {_CWORD, offsetof(_cmsg, Flags)},
 105        /*21 */
 106        {_CDWORD, offsetof(_cmsg, Function)},
 107        /*22 */
 108        {_CSTRUCT, offsetof(_cmsg, HLC)},
 109        /*23 */
 110        {_CWORD, offsetof(_cmsg, Info)},
 111        /*24 */
 112        {_CSTRUCT, offsetof(_cmsg, InfoElement)},
 113        /*25 */
 114        {_CDWORD, offsetof(_cmsg, InfoMask)},
 115        /*26 */
 116        {_CWORD, offsetof(_cmsg, InfoNumber)},
 117        /*27 */
 118        {_CSTRUCT, offsetof(_cmsg, Keypadfacility)},
 119        /*28 */
 120        {_CSTRUCT, offsetof(_cmsg, LLC)},
 121        /*29 */
 122        {_CSTRUCT, offsetof(_cmsg, ManuData)},
 123        /*2a */
 124        {_CDWORD, offsetof(_cmsg, ManuID)},
 125        /*2b */
 126        {_CSTRUCT, offsetof(_cmsg, NCPI)},
 127        /*2c */
 128        {_CWORD, offsetof(_cmsg, Reason)},
 129        /*2d */
 130        {_CWORD, offsetof(_cmsg, Reason_B3)},
 131        /*2e */
 132        {_CWORD, offsetof(_cmsg, Reject)},
 133        /*2f */
 134        {_CSTRUCT, offsetof(_cmsg, Useruserdata)}
 135};
 136
 137static unsigned char *cpars[] =
 138{
 139        /* ALERT_REQ */ [0x01] = "\x03\x04\x0c\x27\x2f\x1c\x01\x01",
 140        /* CONNECT_REQ */ [0x02] = "\x03\x14\x0e\x10\x0f\x11\x0d\x06\x08\x0a\x05\x07\x09\x01\x0b\x28\x22\x04\x0c\x27\x2f\x1c\x01\x01",
 141        /* DISCONNECT_REQ */ [0x04] = "\x03\x04\x0c\x27\x2f\x1c\x01\x01",
 142        /* LISTEN_REQ */ [0x05] = "\x03\x25\x12\x13\x10\x11\x01",
 143        /* INFO_REQ */ [0x08] = "\x03\x0e\x04\x0c\x27\x2f\x1c\x01\x01",
 144        /* FACILITY_REQ */ [0x09] = "\x03\x1f\x1e\x01",
 145        /* SELECT_B_PROTOCOL_REQ */ [0x0a] = "\x03\x0d\x06\x08\x0a\x05\x07\x09\x01\x01",
 146        /* CONNECT_B3_REQ */ [0x0b] = "\x03\x2b\x01",
 147        /* DISCONNECT_B3_REQ */ [0x0d] = "\x03\x2b\x01",
 148        /* DATA_B3_REQ */ [0x0f] = "\x03\x18\x1a\x19\x20\x01",
 149        /* RESET_B3_REQ */ [0x10] = "\x03\x2b\x01",
 150        /* ALERT_CONF */ [0x13] = "\x03\x23\x01",
 151        /* CONNECT_CONF */ [0x14] = "\x03\x23\x01",
 152        /* DISCONNECT_CONF */ [0x16] = "\x03\x23\x01",
 153        /* LISTEN_CONF */ [0x17] = "\x03\x23\x01",
 154        /* MANUFACTURER_REQ */ [0x18] = "\x03\x2a\x15\x21\x29\x01",
 155        /* INFO_CONF */ [0x1a] = "\x03\x23\x01",
 156        /* FACILITY_CONF */ [0x1b] = "\x03\x23\x1f\x1b\x01",
 157        /* SELECT_B_PROTOCOL_CONF */ [0x1c] = "\x03\x23\x01",
 158        /* CONNECT_B3_CONF */ [0x1d] = "\x03\x23\x01",
 159        /* DISCONNECT_B3_CONF */ [0x1f] = "\x03\x23\x01",
 160        /* DATA_B3_CONF */ [0x21] = "\x03\x19\x23\x01",
 161        /* RESET_B3_CONF */ [0x22] = "\x03\x23\x01",
 162        /* CONNECT_IND */ [0x26] = "\x03\x14\x0e\x10\x0f\x11\x0b\x28\x22\x04\x0c\x27\x2f\x1c\x01\x01",
 163        /* CONNECT_ACTIVE_IND */ [0x27] = "\x03\x16\x17\x28\x01",
 164        /* DISCONNECT_IND */ [0x28] = "\x03\x2c\x01",
 165        /* MANUFACTURER_CONF */ [0x2a] = "\x03\x2a\x15\x21\x29\x01",
 166        /* INFO_IND */ [0x2c] = "\x03\x26\x24\x01",
 167        /* FACILITY_IND */ [0x2d] = "\x03\x1f\x1d\x01",
 168        /* CONNECT_B3_IND */ [0x2f] = "\x03\x2b\x01",
 169        /* CONNECT_B3_ACTIVE_IND */ [0x30] = "\x03\x2b\x01",
 170        /* DISCONNECT_B3_IND */ [0x31] = "\x03\x2d\x2b\x01",
 171        /* DATA_B3_IND */ [0x33] = "\x03\x18\x1a\x19\x20\x01",
 172        /* RESET_B3_IND */ [0x34] = "\x03\x2b\x01",
 173        /* CONNECT_B3_T90_ACTIVE_IND */ [0x35] = "\x03\x2b\x01",
 174        /* CONNECT_RESP */ [0x38] = "\x03\x2e\x0d\x06\x08\x0a\x05\x07\x09\x01\x16\x17\x28\x04\x0c\x27\x2f\x1c\x01\x01",
 175        /* CONNECT_ACTIVE_RESP */ [0x39] = "\x03\x01",
 176        /* DISCONNECT_RESP */ [0x3a] = "\x03\x01",
 177        /* MANUFACTURER_IND */ [0x3c] = "\x03\x2a\x15\x21\x29\x01",
 178        /* INFO_RESP */ [0x3e] = "\x03\x01",
 179        /* FACILITY_RESP */ [0x3f] = "\x03\x1f\x01",
 180        /* CONNECT_B3_RESP */ [0x41] = "\x03\x2e\x2b\x01",
 181        /* CONNECT_B3_ACTIVE_RESP */ [0x42] = "\x03\x01",
 182        /* DISCONNECT_B3_RESP */ [0x43] = "\x03\x01",
 183        /* DATA_B3_RESP */ [0x45] = "\x03\x19\x01",
 184        /* RESET_B3_RESP */ [0x46] = "\x03\x01",
 185        /* CONNECT_B3_T90_ACTIVE_RESP */ [0x47] = "\x03\x01",
 186        /* MANUFACTURER_RESP */ [0x4e] = "\x03\x2a\x15\x21\x29\x01",
 187};
 188
 189/*-------------------------------------------------------*/
 190
 191#define byteTLcpy(x, y)         *(u8 *)(x) = *(u8 *)(y);
 192#define wordTLcpy(x, y)         *(u16 *)(x) = *(u16 *)(y);
 193#define dwordTLcpy(x, y)        memcpy(x, y, 4);
 194#define structTLcpy(x, y, l)    memcpy(x, y, l)
 195#define structTLcpyovl(x, y, l) memmove(x, y, l)
 196
 197#define byteTRcpy(x, y)         *(u8 *)(y) = *(u8 *)(x);
 198#define wordTRcpy(x, y)         *(u16 *)(y) = *(u16 *)(x);
 199#define dwordTRcpy(x, y)        memcpy(y, x, 4);
 200#define structTRcpy(x, y, l)    memcpy(y, x, l)
 201#define structTRcpyovl(x, y, l) memmove(y, x, l)
 202
 203/*-------------------------------------------------------*/
 204static unsigned command_2_index(u8 c, u8 sc)
 205{
 206        if (c & 0x80)
 207                c = 0x9 + (c & 0x0f);
 208        else if (c == 0x41)
 209                c = 0x9 + 0x1;
 210        if (c > 0x18)
 211                c = 0x00;
 212        return (sc & 3) * (0x9 + 0x9) + c;
 213}
 214
 215/**
 216 * capi_cmd2par() - find parameter string for CAPI 2.0 command/subcommand
 217 * @cmd:        command number
 218 * @subcmd:     subcommand number
 219 *
 220 * Return value: static string, NULL if command/subcommand unknown
 221 */
 222
 223static unsigned char *capi_cmd2par(u8 cmd, u8 subcmd)
 224{
 225        return cpars[command_2_index(cmd, subcmd)];
 226}
 227
 228/*-------------------------------------------------------*/
 229#define TYP (cdef[cmsg->par[cmsg->p]].typ)
 230#define OFF (((u8 *)cmsg) + cdef[cmsg->par[cmsg->p]].off)
 231
 232static void jumpcstruct(_cmsg *cmsg)
 233{
 234        unsigned layer;
 235        for (cmsg->p++, layer = 1; layer;) {
 236                /* $$$$$ assert (cmsg->p); */
 237                cmsg->p++;
 238                switch (TYP) {
 239                case _CMSTRUCT:
 240                        layer++;
 241                        break;
 242                case _CEND:
 243                        layer--;
 244                        break;
 245                }
 246        }
 247}
 248/*-------------------------------------------------------*/
 249static void pars_2_message(_cmsg *cmsg)
 250{
 251
 252        for (; TYP != _CEND; cmsg->p++) {
 253                switch (TYP) {
 254                case _CBYTE:
 255                        byteTLcpy(cmsg->m + cmsg->l, OFF);
 256                        cmsg->l++;
 257                        break;
 258                case _CWORD:
 259                        wordTLcpy(cmsg->m + cmsg->l, OFF);
 260                        cmsg->l += 2;
 261                        break;
 262                case _CDWORD:
 263                        dwordTLcpy(cmsg->m + cmsg->l, OFF);
 264                        cmsg->l += 4;
 265                        break;
 266                case _CSTRUCT:
 267                        if (*(u8 **) OFF == NULL) {
 268                                *(cmsg->m + cmsg->l) = '\0';
 269                                cmsg->l++;
 270                        } else if (**(_cstruct *) OFF != 0xff) {
 271                                structTLcpy(cmsg->m + cmsg->l, *(_cstruct *) OFF, 1 + **(_cstruct *) OFF);
 272                                cmsg->l += 1 + **(_cstruct *) OFF;
 273                        } else {
 274                                _cstruct s = *(_cstruct *) OFF;
 275                                structTLcpy(cmsg->m + cmsg->l, s, 3 + *(u16 *) (s + 1));
 276                                cmsg->l += 3 + *(u16 *) (s + 1);
 277                        }
 278                        break;
 279                case _CMSTRUCT:
 280/*----- Metastruktur 0 -----*/
 281                        if (*(_cmstruct *) OFF == CAPI_DEFAULT) {
 282                                *(cmsg->m + cmsg->l) = '\0';
 283                                cmsg->l++;
 284                                jumpcstruct(cmsg);
 285                        }
 286/*----- Metastruktur wird composed -----*/
 287                        else {
 288                                unsigned _l = cmsg->l;
 289                                unsigned _ls;
 290                                cmsg->l++;
 291                                cmsg->p++;
 292                                pars_2_message(cmsg);
 293                                _ls = cmsg->l - _l - 1;
 294                                if (_ls < 255)
 295                                        (cmsg->m + _l)[0] = (u8) _ls;
 296                                else {
 297                                        structTLcpyovl(cmsg->m + _l + 3, cmsg->m + _l + 1, _ls);
 298                                        (cmsg->m + _l)[0] = 0xff;
 299                                        wordTLcpy(cmsg->m + _l + 1, &_ls);
 300                                }
 301                        }
 302                        break;
 303                }
 304        }
 305}
 306
 307/**
 308 * capi_cmsg2message() - assemble CAPI 2.0 message from _cmsg structure
 309 * @cmsg:       _cmsg structure
 310 * @msg:        buffer for assembled message
 311 *
 312 * Return value: 0 for success
 313 */
 314
 315unsigned capi_cmsg2message(_cmsg *cmsg, u8 *msg)
 316{
 317        cmsg->m = msg;
 318        cmsg->l = 8;
 319        cmsg->p = 0;
 320        cmsg->par = capi_cmd2par(cmsg->Command, cmsg->Subcommand);
 321        if (!cmsg->par)
 322                return 1;       /* invalid command/subcommand */
 323
 324        pars_2_message(cmsg);
 325
 326        wordTLcpy(msg + 0, &cmsg->l);
 327        byteTLcpy(cmsg->m + 4, &cmsg->Command);
 328        byteTLcpy(cmsg->m + 5, &cmsg->Subcommand);
 329        wordTLcpy(cmsg->m + 2, &cmsg->ApplId);
 330        wordTLcpy(cmsg->m + 6, &cmsg->Messagenumber);
 331
 332        return 0;
 333}
 334
 335/*-------------------------------------------------------*/
 336static void message_2_pars(_cmsg *cmsg)
 337{
 338        for (; TYP != _CEND; cmsg->p++) {
 339
 340                switch (TYP) {
 341                case _CBYTE:
 342                        byteTRcpy(cmsg->m + cmsg->l, OFF);
 343                        cmsg->l++;
 344                        break;
 345                case _CWORD:
 346                        wordTRcpy(cmsg->m + cmsg->l, OFF);
 347                        cmsg->l += 2;
 348                        break;
 349                case _CDWORD:
 350                        dwordTRcpy(cmsg->m + cmsg->l, OFF);
 351                        cmsg->l += 4;
 352                        break;
 353                case _CSTRUCT:
 354                        *(u8 **) OFF = cmsg->m + cmsg->l;
 355
 356                        if (cmsg->m[cmsg->l] != 0xff)
 357                                cmsg->l += 1 + cmsg->m[cmsg->l];
 358                        else
 359                                cmsg->l += 3 + *(u16 *) (cmsg->m + cmsg->l + 1);
 360                        break;
 361                case _CMSTRUCT:
 362/*----- Metastruktur 0 -----*/
 363                        if (cmsg->m[cmsg->l] == '\0') {
 364                                *(_cmstruct *) OFF = CAPI_DEFAULT;
 365                                cmsg->l++;
 366                                jumpcstruct(cmsg);
 367                        } else {
 368                                unsigned _l = cmsg->l;
 369                                *(_cmstruct *) OFF = CAPI_COMPOSE;
 370                                cmsg->l = (cmsg->m + _l)[0] == 255 ? cmsg->l + 3 : cmsg->l + 1;
 371                                cmsg->p++;
 372                                message_2_pars(cmsg);
 373                        }
 374                        break;
 375                }
 376        }
 377}
 378
 379/**
 380 * capi_message2cmsg() - disassemble CAPI 2.0 message into _cmsg structure
 381 * @cmsg:       _cmsg structure
 382 * @msg:        buffer for assembled message
 383 *
 384 * Return value: 0 for success
 385 */
 386
 387unsigned capi_message2cmsg(_cmsg *cmsg, u8 *msg)
 388{
 389        memset(cmsg, 0, sizeof(_cmsg));
 390        cmsg->m = msg;
 391        cmsg->l = 8;
 392        cmsg->p = 0;
 393        byteTRcpy(cmsg->m + 4, &cmsg->Command);
 394        byteTRcpy(cmsg->m + 5, &cmsg->Subcommand);
 395        cmsg->par = capi_cmd2par(cmsg->Command, cmsg->Subcommand);
 396        if (!cmsg->par)
 397                return 1;       /* invalid command/subcommand */
 398
 399        message_2_pars(cmsg);
 400
 401        wordTRcpy(msg + 0, &cmsg->l);
 402        wordTRcpy(cmsg->m + 2, &cmsg->ApplId);
 403        wordTRcpy(cmsg->m + 6, &cmsg->Messagenumber);
 404
 405        return 0;
 406}
 407
 408/**
 409 * capi_cmsg_header() - initialize header part of _cmsg structure
 410 * @cmsg:       _cmsg structure
 411 * @_ApplId:    ApplID field value
 412 * @_Command:   Command field value
 413 * @_Subcommand:        Subcommand field value
 414 * @_Messagenumber:     Message Number field value
 415 * @_Controller:        Controller/PLCI/NCCI field value
 416 *
 417 * Return value: 0 for success
 418 */
 419
 420unsigned capi_cmsg_header(_cmsg *cmsg, u16 _ApplId,
 421                          u8 _Command, u8 _Subcommand,
 422                          u16 _Messagenumber, u32 _Controller)
 423{
 424        memset(cmsg, 0, sizeof(_cmsg));
 425        cmsg->ApplId = _ApplId;
 426        cmsg->Command = _Command;
 427        cmsg->Subcommand = _Subcommand;
 428        cmsg->Messagenumber = _Messagenumber;
 429        cmsg->adr.adrController = _Controller;
 430        return 0;
 431}
 432
 433/*-------------------------------------------------------*/
 434
 435static char *mnames[] =
 436{
 437        [0x01] = "ALERT_REQ",
 438        [0x02] = "CONNECT_REQ",
 439        [0x04] = "DISCONNECT_REQ",
 440        [0x05] = "LISTEN_REQ",
 441        [0x08] = "INFO_REQ",
 442        [0x09] = "FACILITY_REQ",
 443        [0x0a] = "SELECT_B_PROTOCOL_REQ",
 444        [0x0b] = "CONNECT_B3_REQ",
 445        [0x0d] = "DISCONNECT_B3_REQ",
 446        [0x0f] = "DATA_B3_REQ",
 447        [0x10] = "RESET_B3_REQ",
 448        [0x13] = "ALERT_CONF",
 449        [0x14] = "CONNECT_CONF",
 450        [0x16] = "DISCONNECT_CONF",
 451        [0x17] = "LISTEN_CONF",
 452        [0x18] = "MANUFACTURER_REQ",
 453        [0x1a] = "INFO_CONF",
 454        [0x1b] = "FACILITY_CONF",
 455        [0x1c] = "SELECT_B_PROTOCOL_CONF",
 456        [0x1d] = "CONNECT_B3_CONF",
 457        [0x1f] = "DISCONNECT_B3_CONF",
 458        [0x21] = "DATA_B3_CONF",
 459        [0x22] = "RESET_B3_CONF",
 460        [0x26] = "CONNECT_IND",
 461        [0x27] = "CONNECT_ACTIVE_IND",
 462        [0x28] = "DISCONNECT_IND",
 463        [0x2a] = "MANUFACTURER_CONF",
 464        [0x2c] = "INFO_IND",
 465        [0x2d] = "FACILITY_IND",
 466        [0x2f] = "CONNECT_B3_IND",
 467        [0x30] = "CONNECT_B3_ACTIVE_IND",
 468        [0x31] = "DISCONNECT_B3_IND",
 469        [0x33] = "DATA_B3_IND",
 470        [0x34] = "RESET_B3_IND",
 471        [0x35] = "CONNECT_B3_T90_ACTIVE_IND",
 472        [0x38] = "CONNECT_RESP",
 473        [0x39] = "CONNECT_ACTIVE_RESP",
 474        [0x3a] = "DISCONNECT_RESP",
 475        [0x3c] = "MANUFACTURER_IND",
 476        [0x3e] = "INFO_RESP",
 477        [0x3f] = "FACILITY_RESP",
 478        [0x41] = "CONNECT_B3_RESP",
 479        [0x42] = "CONNECT_B3_ACTIVE_RESP",
 480        [0x43] = "DISCONNECT_B3_RESP",
 481        [0x45] = "DATA_B3_RESP",
 482        [0x46] = "RESET_B3_RESP",
 483        [0x47] = "CONNECT_B3_T90_ACTIVE_RESP",
 484        [0x4e] = "MANUFACTURER_RESP"
 485};
 486
 487/**
 488 * capi_cmd2str() - convert CAPI 2.0 command/subcommand number to name
 489 * @cmd:        command number
 490 * @subcmd:     subcommand number
 491 *
 492 * Return value: static string
 493 */
 494
 495char *capi_cmd2str(u8 cmd, u8 subcmd)
 496{
 497        char *result;
 498
 499        result = mnames[command_2_index(cmd, subcmd)];
 500        if (result == NULL)
 501                result = "INVALID_COMMAND";
 502        return result;
 503}
 504
 505
 506/*-------------------------------------------------------*/
 507
 508#ifdef CONFIG_CAPI_TRACE
 509
 510/*-------------------------------------------------------*/
 511
 512static char *pnames[] =
 513{
 514        /*00 */ NULL,
 515        /*01 */ NULL,
 516        /*02 */ NULL,
 517        /*03 */ "Controller/PLCI/NCCI",
 518        /*04 */ "AdditionalInfo",
 519        /*05 */ "B1configuration",
 520        /*06 */ "B1protocol",
 521        /*07 */ "B2configuration",
 522        /*08 */ "B2protocol",
 523        /*09 */ "B3configuration",
 524        /*0a */ "B3protocol",
 525        /*0b */ "BC",
 526        /*0c */ "BChannelinformation",
 527        /*0d */ "BProtocol",
 528        /*0e */ "CalledPartyNumber",
 529        /*0f */ "CalledPartySubaddress",
 530        /*10 */ "CallingPartyNumber",
 531        /*11 */ "CallingPartySubaddress",
 532        /*12 */ "CIPmask",
 533        /*13 */ "CIPmask2",
 534        /*14 */ "CIPValue",
 535        /*15 */ "Class",
 536        /*16 */ "ConnectedNumber",
 537        /*17 */ "ConnectedSubaddress",
 538        /*18 */ "Data32",
 539        /*19 */ "DataHandle",
 540        /*1a */ "DataLength",
 541        /*1b */ "FacilityConfirmationParameter",
 542        /*1c */ "Facilitydataarray",
 543        /*1d */ "FacilityIndicationParameter",
 544        /*1e */ "FacilityRequestParameter",
 545        /*1f */ "FacilitySelector",
 546        /*20 */ "Flags",
 547        /*21 */ "Function",
 548        /*22 */ "HLC",
 549        /*23 */ "Info",
 550        /*24 */ "InfoElement",
 551        /*25 */ "InfoMask",
 552        /*26 */ "InfoNumber",
 553        /*27 */ "Keypadfacility",
 554        /*28 */ "LLC",
 555        /*29 */ "ManuData",
 556        /*2a */ "ManuID",
 557        /*2b */ "NCPI",
 558        /*2c */ "Reason",
 559        /*2d */ "Reason_B3",
 560        /*2e */ "Reject",
 561        /*2f */ "Useruserdata"
 562};
 563
 564
 565
 566#include <stdarg.h>
 567
 568/*-------------------------------------------------------*/
 569static _cdebbuf *bufprint(_cdebbuf *cdb, char *fmt, ...)
 570{
 571        va_list f;
 572        size_t n, r;
 573
 574        if (!cdb)
 575                return NULL;
 576        va_start(f, fmt);
 577        r = cdb->size - cdb->pos;
 578        n = vsnprintf(cdb->p, r, fmt, f);
 579        va_end(f);
 580        if (n >= r) {
 581                /* truncated, need bigger buffer */
 582                size_t ns = 2 * cdb->size;
 583                u_char *nb;
 584
 585                while ((ns - cdb->pos) <= n)
 586                        ns *= 2;
 587                nb = kmalloc(ns, GFP_ATOMIC);
 588                if (!nb) {
 589                        cdebbuf_free(cdb);
 590                        return NULL;
 591                }
 592                memcpy(nb, cdb->buf, cdb->pos);
 593                kfree(cdb->buf);
 594                nb[cdb->pos] = 0;
 595                cdb->buf = nb;
 596                cdb->p = cdb->buf + cdb->pos;
 597                cdb->size = ns;
 598                va_start(f, fmt);
 599                r = cdb->size - cdb->pos;
 600                n = vsnprintf(cdb->p, r, fmt, f);
 601                va_end(f);
 602        }
 603        cdb->p += n;
 604        cdb->pos += n;
 605        return cdb;
 606}
 607
 608static _cdebbuf *printstructlen(_cdebbuf *cdb, u8 *m, unsigned len)
 609{
 610        unsigned hex = 0;
 611
 612        if (!cdb)
 613                return NULL;
 614        for (; len; len--, m++)
 615                if (isalnum(*m) || *m == ' ') {
 616                        if (hex)
 617                                cdb = bufprint(cdb, ">");
 618                        cdb = bufprint(cdb, "%c", *m);
 619                        hex = 0;
 620                } else {
 621                        if (!hex)
 622                                cdb = bufprint(cdb, "<%02x", *m);
 623                        else
 624                                cdb = bufprint(cdb, " %02x", *m);
 625                        hex = 1;
 626                }
 627        if (hex)
 628                cdb = bufprint(cdb, ">");
 629        return cdb;
 630}
 631
 632static _cdebbuf *printstruct(_cdebbuf *cdb, u8 *m)
 633{
 634        unsigned len;
 635
 636        if (m[0] != 0xff) {
 637                len = m[0];
 638                m += 1;
 639        } else {
 640                len = ((u16 *) (m + 1))[0];
 641                m += 3;
 642        }
 643        cdb = printstructlen(cdb, m, len);
 644        return cdb;
 645}
 646
 647/*-------------------------------------------------------*/
 648#define NAME (pnames[cmsg->par[cmsg->p]])
 649
 650static _cdebbuf *protocol_message_2_pars(_cdebbuf *cdb, _cmsg *cmsg, int level)
 651{
 652        if (!cmsg->par)
 653                return NULL;    /* invalid command/subcommand */
 654
 655        for (; TYP != _CEND; cmsg->p++) {
 656                int slen = 29 + 3 - level;
 657                int i;
 658
 659                if (!cdb)
 660                        return NULL;
 661                cdb = bufprint(cdb, "  ");
 662                for (i = 0; i < level - 1; i++)
 663                        cdb = bufprint(cdb, " ");
 664
 665                switch (TYP) {
 666                case _CBYTE:
 667                        cdb = bufprint(cdb, "%-*s = 0x%x\n", slen, NAME, *(u8 *) (cmsg->m + cmsg->l));
 668                        cmsg->l++;
 669                        break;
 670                case _CWORD:
 671                        cdb = bufprint(cdb, "%-*s = 0x%x\n", slen, NAME, *(u16 *) (cmsg->m + cmsg->l));
 672                        cmsg->l += 2;
 673                        break;
 674                case _CDWORD:
 675                        cdb = bufprint(cdb, "%-*s = 0x%lx\n", slen, NAME, *(u32 *) (cmsg->m + cmsg->l));
 676                        cmsg->l += 4;
 677                        break;
 678                case _CSTRUCT:
 679                        cdb = bufprint(cdb, "%-*s = ", slen, NAME);
 680                        if (cmsg->m[cmsg->l] == '\0')
 681                                cdb = bufprint(cdb, "default");
 682                        else
 683                                cdb = printstruct(cdb, cmsg->m + cmsg->l);
 684                        cdb = bufprint(cdb, "\n");
 685                        if (cmsg->m[cmsg->l] != 0xff)
 686                                cmsg->l += 1 + cmsg->m[cmsg->l];
 687                        else
 688                                cmsg->l += 3 + *(u16 *) (cmsg->m + cmsg->l + 1);
 689
 690                        break;
 691
 692                case _CMSTRUCT:
 693/*----- Metastruktur 0 -----*/
 694                        if (cmsg->m[cmsg->l] == '\0') {
 695                                cdb = bufprint(cdb, "%-*s = default\n", slen, NAME);
 696                                cmsg->l++;
 697                                jumpcstruct(cmsg);
 698                        } else {
 699                                char *name = NAME;
 700                                unsigned _l = cmsg->l;
 701                                cdb = bufprint(cdb, "%-*s\n", slen, name);
 702                                cmsg->l = (cmsg->m + _l)[0] == 255 ? cmsg->l + 3 : cmsg->l + 1;
 703                                cmsg->p++;
 704                                cdb = protocol_message_2_pars(cdb, cmsg, level + 1);
 705                        }
 706                        break;
 707                }
 708        }
 709        return cdb;
 710}
 711/*-------------------------------------------------------*/
 712
 713static _cdebbuf *g_debbuf;
 714static u_long g_debbuf_lock;
 715static _cmsg *g_cmsg;
 716
 717static _cdebbuf *cdebbuf_alloc(void)
 718{
 719        _cdebbuf *cdb;
 720
 721        if (likely(!test_and_set_bit(1, &g_debbuf_lock))) {
 722                cdb = g_debbuf;
 723                goto init;
 724        } else
 725                cdb = kmalloc(sizeof(_cdebbuf), GFP_ATOMIC);
 726        if (!cdb)
 727                return NULL;
 728        cdb->buf = kmalloc(CDEBUG_SIZE, GFP_ATOMIC);
 729        if (!cdb->buf) {
 730                kfree(cdb);
 731                return NULL;
 732        }
 733        cdb->size = CDEBUG_SIZE;
 734init:
 735        cdb->buf[0] = 0;
 736        cdb->p = cdb->buf;
 737        cdb->pos = 0;
 738        return cdb;
 739}
 740
 741/**
 742 * cdebbuf_free() - free CAPI debug buffer
 743 * @cdb:        buffer to free
 744 */
 745
 746void cdebbuf_free(_cdebbuf *cdb)
 747{
 748        if (likely(cdb == g_debbuf)) {
 749                test_and_clear_bit(1, &g_debbuf_lock);
 750                return;
 751        }
 752        if (likely(cdb))
 753                kfree(cdb->buf);
 754        kfree(cdb);
 755}
 756
 757
 758/**
 759 * capi_message2str() - format CAPI 2.0 message for printing
 760 * @msg:        CAPI 2.0 message
 761 *
 762 * Allocates a CAPI debug buffer and fills it with a printable representation
 763 * of the CAPI 2.0 message in @msg.
 764 * Return value: allocated debug buffer, NULL on error
 765 * The returned buffer should be freed by a call to cdebbuf_free() after use.
 766 */
 767
 768_cdebbuf *capi_message2str(u8 *msg)
 769{
 770        _cdebbuf *cdb;
 771        _cmsg   *cmsg;
 772
 773        cdb = cdebbuf_alloc();
 774        if (unlikely(!cdb))
 775                return NULL;
 776        if (likely(cdb == g_debbuf))
 777                cmsg = g_cmsg;
 778        else
 779                cmsg = kmalloc(sizeof(_cmsg), GFP_ATOMIC);
 780        if (unlikely(!cmsg)) {
 781                cdebbuf_free(cdb);
 782                return NULL;
 783        }
 784        cmsg->m = msg;
 785        cmsg->l = 8;
 786        cmsg->p = 0;
 787        byteTRcpy(cmsg->m + 4, &cmsg->Command);
 788        byteTRcpy(cmsg->m + 5, &cmsg->Subcommand);
 789        cmsg->par = capi_cmd2par(cmsg->Command, cmsg->Subcommand);
 790
 791        cdb = bufprint(cdb, "%-26s ID=%03d #0x%04x LEN=%04d\n",
 792                       capi_cmd2str(cmsg->Command, cmsg->Subcommand),
 793                       ((unsigned short *) msg)[1],
 794                       ((unsigned short *) msg)[3],
 795                       ((unsigned short *) msg)[0]);
 796
 797        cdb = protocol_message_2_pars(cdb, cmsg, 1);
 798        if (unlikely(cmsg != g_cmsg))
 799                kfree(cmsg);
 800        return cdb;
 801}
 802
 803/**
 804 * capi_cmsg2str() - format _cmsg structure for printing
 805 * @cmsg:       _cmsg structure
 806 *
 807 * Allocates a CAPI debug buffer and fills it with a printable representation
 808 * of the CAPI 2.0 message stored in @cmsg by a previous call to
 809 * capi_cmsg2message() or capi_message2cmsg().
 810 * Return value: allocated debug buffer, NULL on error
 811 * The returned buffer should be freed by a call to cdebbuf_free() after use.
 812 */
 813
 814_cdebbuf *capi_cmsg2str(_cmsg *cmsg)
 815{
 816        _cdebbuf *cdb;
 817
 818        if (!cmsg->m)
 819                return NULL;    /* no message */
 820        cdb = cdebbuf_alloc();
 821        if (!cdb)
 822                return NULL;
 823        cmsg->l = 8;
 824        cmsg->p = 0;
 825        cdb = bufprint(cdb, "%s ID=%03d #0x%04x LEN=%04d\n",
 826                       capi_cmd2str(cmsg->Command, cmsg->Subcommand),
 827                       ((u16 *) cmsg->m)[1],
 828                       ((u16 *) cmsg->m)[3],
 829                       ((u16 *) cmsg->m)[0]);
 830        cdb = protocol_message_2_pars(cdb, cmsg, 1);
 831        return cdb;
 832}
 833
 834int __init cdebug_init(void)
 835{
 836        g_cmsg = kmalloc(sizeof(_cmsg), GFP_KERNEL);
 837        if (!g_cmsg)
 838                return -ENOMEM;
 839        g_debbuf = kmalloc(sizeof(_cdebbuf), GFP_KERNEL);
 840        if (!g_debbuf) {
 841                kfree(g_cmsg);
 842                return -ENOMEM;
 843        }
 844        g_debbuf->buf = kmalloc(CDEBUG_GSIZE, GFP_KERNEL);
 845        if (!g_debbuf->buf) {
 846                kfree(g_cmsg);
 847                kfree(g_debbuf);
 848                return -ENOMEM;
 849        }
 850        g_debbuf->size = CDEBUG_GSIZE;
 851        g_debbuf->buf[0] = 0;
 852        g_debbuf->p = g_debbuf->buf;
 853        g_debbuf->pos = 0;
 854        return 0;
 855}
 856
 857void __exit cdebug_exit(void)
 858{
 859        if (g_debbuf)
 860                kfree(g_debbuf->buf);
 861        kfree(g_debbuf);
 862        kfree(g_cmsg);
 863}
 864
 865#else /* !CONFIG_CAPI_TRACE */
 866
 867static _cdebbuf g_debbuf = {"CONFIG_CAPI_TRACE not enabled", NULL, 0, 0};
 868
 869_cdebbuf *capi_message2str(u8 *msg)
 870{
 871        return &g_debbuf;
 872}
 873
 874_cdebbuf *capi_cmsg2str(_cmsg *cmsg)
 875{
 876        return &g_debbuf;
 877}
 878
 879void cdebbuf_free(_cdebbuf *cdb)
 880{
 881}
 882
 883int __init cdebug_init(void)
 884{
 885        return 0;
 886}
 887
 888void __exit cdebug_exit(void)
 889{
 890}
 891
 892#endif
 893
 894EXPORT_SYMBOL(cdebbuf_free);
 895EXPORT_SYMBOL(capi_cmsg2message);
 896EXPORT_SYMBOL(capi_message2cmsg);
 897EXPORT_SYMBOL(capi_cmsg_header);
 898EXPORT_SYMBOL(capi_cmd2str);
 899EXPORT_SYMBOL(capi_cmsg2str);
 900EXPORT_SYMBOL(capi_message2str);
 901