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); 901