root/drivers/isdn/capi/capiutil.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. command_2_index
  2. capi_cmd2par
  3. jumpcstruct
  4. pars_2_message
  5. capi_cmsg2message
  6. message_2_pars
  7. capi_message2cmsg
  8. capi_cmsg_header
  9. capi_cmd2str
  10. bufprint
  11. printstructlen
  12. printstruct
  13. protocol_message_2_pars
  14. cdebbuf_alloc
  15. cdebbuf_free
  16. capi_message2str
  17. capi_cmsg2str
  18. cdebug_init
  19. cdebug_exit
  20. capi_message2str
  21. capi_cmsg2str
  22. cdebbuf_free
  23. cdebug_init
  24. cdebug_exit

   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 
  25 typedef 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 
  37 static _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 
 137 static 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 /*-------------------------------------------------------*/
 204 static 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 
 223 static 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 
 232 static 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 /*-------------------------------------------------------*/
 249 static 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 
 315 unsigned 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 /*-------------------------------------------------------*/
 336 static 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 
 387 unsigned 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 
 420 unsigned 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 
 435 static 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 
 495 char *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 
 512 static 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 /*-------------------------------------------------------*/
 569 static _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 
 608 static _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 
 632 static _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 
 650 static _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 
 713 static _cdebbuf *g_debbuf;
 714 static u_long g_debbuf_lock;
 715 static _cmsg *g_cmsg;
 716 
 717 static _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;
 734 init:
 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 
 746 void 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 
 834 int __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 
 857 void __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 
 867 static _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 
 879 void cdebbuf_free(_cdebbuf *cdb)
 880 {
 881 }
 882 
 883 int __init cdebug_init(void)
 884 {
 885         return 0;
 886 }
 887 
 888 void __exit cdebug_exit(void)
 889 {
 890 }
 891 
 892 #endif
 893 
 894 EXPORT_SYMBOL(cdebbuf_free);
 895 EXPORT_SYMBOL(capi_cmsg2message);
 896 EXPORT_SYMBOL(capi_message2cmsg);
 897 EXPORT_SYMBOL(capi_cmsg_header);
 898 EXPORT_SYMBOL(capi_cmd2str);
 899 EXPORT_SYMBOL(capi_cmsg2str);
 900 EXPORT_SYMBOL(capi_message2str);

/* [<][>][^][v][top][bottom][index][help] */