1
2
3
4
5
6
7
8
9
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
24
25#ifndef CONFIG_ISDN_DRV_AVMB1_VERBOSE_REASON
26char *capi_info2str(u16 reason)
27{
28 return "..";
29}
30#else
31char *capi_info2str(u16 reason)
32{
33 switch (reason) {
34
35
36 case 0x0001:
37 return "NCPI not supported by current protocol, NCPI ignored";
38 case 0x0002:
39 return "Flags not supported by current protocol, flags ignored";
40 case 0x0003:
41 return "Alert already sent by another application";
42
43
44 case 0x1001:
45 return "Too many applications";
46 case 0x1002:
47 return "Logical block size too small, must be at least 128 Bytes";
48 case 0x1003:
49 return "Buffer exceeds 64 kByte";
50 case 0x1004:
51 return "Message buffer size too small, must be at least 1024 Bytes";
52 case 0x1005:
53 return "Max. number of logical connections not supported";
54 case 0x1006:
55 return "Reserved";
56 case 0x1007:
57 return "The message could not be accepted because of an internal busy condition";
58 case 0x1008:
59 return "OS resource error (no memory ?)";
60 case 0x1009:
61 return "CAPI not installed";
62 case 0x100A:
63 return "Controller does not support external equipment";
64 case 0x100B:
65 return "Controller does only support external equipment";
66
67
68 case 0x1101:
69 return "Illegal application number";
70 case 0x1102:
71 return "Illegal command or subcommand or message length less than 12 bytes";
72 case 0x1103:
73 return "The message could not be accepted because of a queue full condition !! The error code does not imply that CAPI cannot receive messages directed to another controller, PLCI or NCCI";
74 case 0x1104:
75 return "Queue is empty";
76 case 0x1105:
77 return "Queue overflow, a message was lost !! This indicates a configuration error. The only recovery from this error is to perform a CAPI_RELEASE";
78 case 0x1106:
79 return "Unknown notification parameter";
80 case 0x1107:
81 return "The Message could not be accepted because of an internal busy condition";
82 case 0x1108:
83 return "OS Resource error (no memory ?)";
84 case 0x1109:
85 return "CAPI not installed";
86 case 0x110A:
87 return "Controller does not support external equipment";
88 case 0x110B:
89 return "Controller does only support external equipment";
90
91
92 case 0x2001:
93 return "Message not supported in current state";
94 case 0x2002:
95 return "Illegal Controller / PLCI / NCCI";
96 case 0x2003:
97 return "Out of PLCI";
98 case 0x2004:
99 return "Out of NCCI";
100 case 0x2005:
101 return "Out of LISTEN";
102 case 0x2006:
103 return "Out of FAX resources (protocol T.30)";
104 case 0x2007:
105 return "Illegal message parameter coding";
106
107
108 case 0x3001:
109 return "B1 protocol not supported";
110 case 0x3002:
111 return "B2 protocol not supported";
112 case 0x3003:
113 return "B3 protocol not supported";
114 case 0x3004:
115 return "B1 protocol parameter not supported";
116 case 0x3005:
117 return "B2 protocol parameter not supported";
118 case 0x3006:
119 return "B3 protocol parameter not supported";
120 case 0x3007:
121 return "B protocol combination not supported";
122 case 0x3008:
123 return "NCPI not supported";
124 case 0x3009:
125 return "CIP Value unknown";
126 case 0x300A:
127 return "Flags not supported (reserved bits)";
128 case 0x300B:
129 return "Facility not supported";
130 case 0x300C:
131 return "Data length not supported by current protocol";
132 case 0x300D:
133 return "Reset procedure not supported by current protocol";
134
135
136 case 0x3301:
137 return "Protocol error layer 1 (broken line or B-channel removed by signalling protocol)";
138 case 0x3302:
139 return "Protocol error layer 2";
140 case 0x3303:
141 return "Protocol error layer 3";
142 case 0x3304:
143 return "Another application got that call";
144
145 case 0x3311:
146 return "Connecting not successful (remote station is no FAX G3 machine)";
147 case 0x3312:
148 return "Connecting not successful (training error)";
149 case 0x3313:
150 return "Disconnected before transfer (remote station does not support transfer mode, e.g. resolution)";
151 case 0x3314:
152 return "Disconnected during transfer (remote abort)";
153 case 0x3315:
154 return "Disconnected during transfer (remote procedure error, e.g. unsuccessful repetition of T.30 commands)";
155 case 0x3316:
156 return "Disconnected during transfer (local tx data underrun)";
157 case 0x3317:
158 return "Disconnected during transfer (local rx data overflow)";
159 case 0x3318:
160 return "Disconnected during transfer (local abort)";
161 case 0x3319:
162 return "Illegal parameter coding (e.g. SFF coding error)";
163
164
165 case 0x3481: return "Unallocated (unassigned) number";
166 case 0x3482: return "No route to specified transit network";
167 case 0x3483: return "No route to destination";
168 case 0x3486: return "Channel unacceptable";
169 case 0x3487:
170 return "Call awarded and being delivered in an established channel";
171 case 0x3490: return "Normal call clearing";
172 case 0x3491: return "User busy";
173 case 0x3492: return "No user responding";
174 case 0x3493: return "No answer from user (user alerted)";
175 case 0x3495: return "Call rejected";
176 case 0x3496: return "Number changed";
177 case 0x349A: return "Non-selected user clearing";
178 case 0x349B: return "Destination out of order";
179 case 0x349C: return "Invalid number format";
180 case 0x349D: return "Facility rejected";
181 case 0x349E: return "Response to STATUS ENQUIRY";
182 case 0x349F: return "Normal, unspecified";
183 case 0x34A2: return "No circuit / channel available";
184 case 0x34A6: return "Network out of order";
185 case 0x34A9: return "Temporary failure";
186 case 0x34AA: return "Switching equipment congestion";
187 case 0x34AB: return "Access information discarded";
188 case 0x34AC: return "Requested circuit / channel not available";
189 case 0x34AF: return "Resources unavailable, unspecified";
190 case 0x34B1: return "Quality of service unavailable";
191 case 0x34B2: return "Requested facility not subscribed";
192 case 0x34B9: return "Bearer capability not authorized";
193 case 0x34BA: return "Bearer capability not presently available";
194 case 0x34BF: return "Service or option not available, unspecified";
195 case 0x34C1: return "Bearer capability not implemented";
196 case 0x34C2: return "Channel type not implemented";
197 case 0x34C5: return "Requested facility not implemented";
198 case 0x34C6: return "Only restricted digital information bearer capability is available";
199 case 0x34CF: return "Service or option not implemented, unspecified";
200 case 0x34D1: return "Invalid call reference value";
201 case 0x34D2: return "Identified channel does not exist";
202 case 0x34D3: return "A suspended call exists, but this call identity does not";
203 case 0x34D4: return "Call identity in use";
204 case 0x34D5: return "No call suspended";
205 case 0x34D6: return "Call having the requested call identity has been cleared";
206 case 0x34D8: return "Incompatible destination";
207 case 0x34DB: return "Invalid transit network selection";
208 case 0x34DF: return "Invalid message, unspecified";
209 case 0x34E0: return "Mandatory information element is missing";
210 case 0x34E1: return "Message type non-existent or not implemented";
211 case 0x34E2: return "Message not compatible with call state or message type non-existent or not implemented";
212 case 0x34E3: return "Information element non-existent or not implemented";
213 case 0x34E4: return "Invalid information element contents";
214 case 0x34E5: return "Message not compatible with call state";
215 case 0x34E6: return "Recovery on timer expiry";
216 case 0x34EF: return "Protocol error, unspecified";
217 case 0x34FF: return "Interworking, unspecified";
218
219 default: return "No additional information";
220 }
221}
222#endif
223
224typedef struct {
225 int typ;
226 size_t off;
227} _cdef;
228
229#define _CBYTE 1
230#define _CWORD 2
231#define _CDWORD 3
232#define _CSTRUCT 4
233#define _CMSTRUCT 5
234#define _CEND 6
235
236static _cdef cdef[] =
237{
238
239 {_CEND},
240
241 {_CEND},
242
243 {_CEND},
244
245 {_CDWORD, offsetof(_cmsg, adr.adrController)},
246
247 {_CMSTRUCT, offsetof(_cmsg, AdditionalInfo)},
248
249 {_CSTRUCT, offsetof(_cmsg, B1configuration)},
250
251 {_CWORD, offsetof(_cmsg, B1protocol)},
252
253 {_CSTRUCT, offsetof(_cmsg, B2configuration)},
254
255 {_CWORD, offsetof(_cmsg, B2protocol)},
256
257 {_CSTRUCT, offsetof(_cmsg, B3configuration)},
258
259 {_CWORD, offsetof(_cmsg, B3protocol)},
260
261 {_CSTRUCT, offsetof(_cmsg, BC)},
262
263 {_CSTRUCT, offsetof(_cmsg, BChannelinformation)},
264
265 {_CMSTRUCT, offsetof(_cmsg, BProtocol)},
266
267 {_CSTRUCT, offsetof(_cmsg, CalledPartyNumber)},
268
269 {_CSTRUCT, offsetof(_cmsg, CalledPartySubaddress)},
270
271 {_CSTRUCT, offsetof(_cmsg, CallingPartyNumber)},
272
273 {_CSTRUCT, offsetof(_cmsg, CallingPartySubaddress)},
274
275 {_CDWORD, offsetof(_cmsg, CIPmask)},
276
277 {_CDWORD, offsetof(_cmsg, CIPmask2)},
278
279 {_CWORD, offsetof(_cmsg, CIPValue)},
280
281 {_CDWORD, offsetof(_cmsg, Class)},
282
283 {_CSTRUCT, offsetof(_cmsg, ConnectedNumber)},
284
285 {_CSTRUCT, offsetof(_cmsg, ConnectedSubaddress)},
286
287 {_CDWORD, offsetof(_cmsg, Data)},
288
289 {_CWORD, offsetof(_cmsg, DataHandle)},
290
291 {_CWORD, offsetof(_cmsg, DataLength)},
292
293 {_CSTRUCT, offsetof(_cmsg, FacilityConfirmationParameter)},
294
295 {_CSTRUCT, offsetof(_cmsg, Facilitydataarray)},
296
297 {_CSTRUCT, offsetof(_cmsg, FacilityIndicationParameter)},
298
299 {_CSTRUCT, offsetof(_cmsg, FacilityRequestParameter)},
300
301 {_CWORD, offsetof(_cmsg, FacilitySelector)},
302
303 {_CWORD, offsetof(_cmsg, Flags)},
304
305 {_CDWORD, offsetof(_cmsg, Function)},
306
307 {_CSTRUCT, offsetof(_cmsg, HLC)},
308
309 {_CWORD, offsetof(_cmsg, Info)},
310
311 {_CSTRUCT, offsetof(_cmsg, InfoElement)},
312
313 {_CDWORD, offsetof(_cmsg, InfoMask)},
314
315 {_CWORD, offsetof(_cmsg, InfoNumber)},
316
317 {_CSTRUCT, offsetof(_cmsg, Keypadfacility)},
318
319 {_CSTRUCT, offsetof(_cmsg, LLC)},
320
321 {_CSTRUCT, offsetof(_cmsg, ManuData)},
322
323 {_CDWORD, offsetof(_cmsg, ManuID)},
324
325 {_CSTRUCT, offsetof(_cmsg, NCPI)},
326
327 {_CWORD, offsetof(_cmsg, Reason)},
328
329 {_CWORD, offsetof(_cmsg, Reason_B3)},
330
331 {_CWORD, offsetof(_cmsg, Reject)},
332
333 {_CSTRUCT, offsetof(_cmsg, Useruserdata)}
334};
335
336static unsigned char *cpars[] =
337{
338 [0x01] = "\x03\x04\x0c\x27\x2f\x1c\x01\x01",
339 [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",
340 [0x04] = "\x03\x04\x0c\x27\x2f\x1c\x01\x01",
341 [0x05] = "\x03\x25\x12\x13\x10\x11\x01",
342 [0x08] = "\x03\x0e\x04\x0c\x27\x2f\x1c\x01\x01",
343 [0x09] = "\x03\x1f\x1e\x01",
344 [0x0a] = "\x03\x0d\x06\x08\x0a\x05\x07\x09\x01\x01",
345 [0x0b] = "\x03\x2b\x01",
346 [0x0d] = "\x03\x2b\x01",
347 [0x0f] = "\x03\x18\x1a\x19\x20\x01",
348 [0x10] = "\x03\x2b\x01",
349 [0x13] = "\x03\x23\x01",
350 [0x14] = "\x03\x23\x01",
351 [0x16] = "\x03\x23\x01",
352 [0x17] = "\x03\x23\x01",
353 [0x18] = "\x03\x2a\x15\x21\x29\x01",
354 [0x1a] = "\x03\x23\x01",
355 [0x1b] = "\x03\x23\x1f\x1b\x01",
356 [0x1c] = "\x03\x23\x01",
357 [0x1d] = "\x03\x23\x01",
358 [0x1f] = "\x03\x23\x01",
359 [0x21] = "\x03\x19\x23\x01",
360 [0x22] = "\x03\x23\x01",
361 [0x26] = "\x03\x14\x0e\x10\x0f\x11\x0b\x28\x22\x04\x0c\x27\x2f\x1c\x01\x01",
362 [0x27] = "\x03\x16\x17\x28\x01",
363 [0x28] = "\x03\x2c\x01",
364 [0x2a] = "\x03\x2a\x15\x21\x29\x01",
365 [0x2c] = "\x03\x26\x24\x01",
366 [0x2d] = "\x03\x1f\x1d\x01",
367 [0x2f] = "\x03\x2b\x01",
368 [0x30] = "\x03\x2b\x01",
369 [0x31] = "\x03\x2d\x2b\x01",
370 [0x33] = "\x03\x18\x1a\x19\x20\x01",
371 [0x34] = "\x03\x2b\x01",
372 [0x35] = "\x03\x2b\x01",
373 [0x38] = "\x03\x2e\x0d\x06\x08\x0a\x05\x07\x09\x01\x16\x17\x28\x04\x0c\x27\x2f\x1c\x01\x01",
374 [0x39] = "\x03\x01",
375 [0x3a] = "\x03\x01",
376 [0x3c] = "\x03\x2a\x15\x21\x29\x01",
377 [0x3e] = "\x03\x01",
378 [0x3f] = "\x03\x1f\x01",
379 [0x41] = "\x03\x2e\x2b\x01",
380 [0x42] = "\x03\x01",
381 [0x43] = "\x03\x01",
382 [0x45] = "\x03\x19\x01",
383 [0x46] = "\x03\x01",
384 [0x47] = "\x03\x01",
385 [0x4e] = "\x03\x2a\x15\x21\x29\x01",
386};
387
388
389
390#define byteTLcpy(x, y) *(u8 *)(x) = *(u8 *)(y);
391#define wordTLcpy(x, y) *(u16 *)(x) = *(u16 *)(y);
392#define dwordTLcpy(x, y) memcpy(x, y, 4);
393#define structTLcpy(x, y, l) memcpy(x, y, l)
394#define structTLcpyovl(x, y, l) memmove(x, y, l)
395
396#define byteTRcpy(x, y) *(u8 *)(y) = *(u8 *)(x);
397#define wordTRcpy(x, y) *(u16 *)(y) = *(u16 *)(x);
398#define dwordTRcpy(x, y) memcpy(y, x, 4);
399#define structTRcpy(x, y, l) memcpy(y, x, l)
400#define structTRcpyovl(x, y, l) memmove(y, x, l)
401
402
403static unsigned command_2_index(unsigned c, unsigned sc)
404{
405 if (c & 0x80)
406 c = 0x9 + (c & 0x0f);
407 else if (c <= 0x0f);
408 else if (c == 0x41)
409 c = 0x9 + 0x1;
410 else if (c == 0xff)
411 c = 0x00;
412 return (sc & 3) * (0x9 + 0x9) + c;
413}
414
415
416#define TYP (cdef[cmsg->par[cmsg->p]].typ)
417#define OFF (((u8 *)cmsg) + cdef[cmsg->par[cmsg->p]].off)
418
419static void jumpcstruct(_cmsg *cmsg)
420{
421 unsigned layer;
422 for (cmsg->p++, layer = 1; layer;) {
423
424 cmsg->p++;
425 switch (TYP) {
426 case _CMSTRUCT:
427 layer++;
428 break;
429 case _CEND:
430 layer--;
431 break;
432 }
433 }
434}
435
436static void pars_2_message(_cmsg *cmsg)
437{
438
439 for (; TYP != _CEND; cmsg->p++) {
440 switch (TYP) {
441 case _CBYTE:
442 byteTLcpy(cmsg->m + cmsg->l, OFF);
443 cmsg->l++;
444 break;
445 case _CWORD:
446 wordTLcpy(cmsg->m + cmsg->l, OFF);
447 cmsg->l += 2;
448 break;
449 case _CDWORD:
450 dwordTLcpy(cmsg->m + cmsg->l, OFF);
451 cmsg->l += 4;
452 break;
453 case _CSTRUCT:
454 if (*(u8 **) OFF == NULL) {
455 *(cmsg->m + cmsg->l) = '\0';
456 cmsg->l++;
457 } else if (**(_cstruct *) OFF != 0xff) {
458 structTLcpy(cmsg->m + cmsg->l, *(_cstruct *) OFF, 1 + **(_cstruct *) OFF);
459 cmsg->l += 1 + **(_cstruct *) OFF;
460 } else {
461 _cstruct s = *(_cstruct *) OFF;
462 structTLcpy(cmsg->m + cmsg->l, s, 3 + *(u16 *) (s + 1));
463 cmsg->l += 3 + *(u16 *) (s + 1);
464 }
465 break;
466 case _CMSTRUCT:
467
468 if (*(_cmstruct *) OFF == CAPI_DEFAULT) {
469 *(cmsg->m + cmsg->l) = '\0';
470 cmsg->l++;
471 jumpcstruct(cmsg);
472 }
473
474 else {
475 unsigned _l = cmsg->l;
476 unsigned _ls;
477 cmsg->l++;
478 cmsg->p++;
479 pars_2_message(cmsg);
480 _ls = cmsg->l - _l - 1;
481 if (_ls < 255)
482 (cmsg->m + _l)[0] = (u8) _ls;
483 else {
484 structTLcpyovl(cmsg->m + _l + 3, cmsg->m + _l + 1, _ls);
485 (cmsg->m + _l)[0] = 0xff;
486 wordTLcpy(cmsg->m + _l + 1, &_ls);
487 }
488 }
489 break;
490 }
491 }
492}
493
494
495
496
497
498
499
500
501
502unsigned capi_cmsg2message(_cmsg *cmsg, u8 *msg)
503{
504 cmsg->m = msg;
505 cmsg->l = 8;
506 cmsg->p = 0;
507 cmsg->par = cpars[command_2_index(cmsg->Command, cmsg->Subcommand)];
508
509 pars_2_message(cmsg);
510
511 wordTLcpy(msg + 0, &cmsg->l);
512 byteTLcpy(cmsg->m + 4, &cmsg->Command);
513 byteTLcpy(cmsg->m + 5, &cmsg->Subcommand);
514 wordTLcpy(cmsg->m + 2, &cmsg->ApplId);
515 wordTLcpy(cmsg->m + 6, &cmsg->Messagenumber);
516
517 return 0;
518}
519
520
521static void message_2_pars(_cmsg *cmsg)
522{
523 for (; TYP != _CEND; cmsg->p++) {
524
525 switch (TYP) {
526 case _CBYTE:
527 byteTRcpy(cmsg->m + cmsg->l, OFF);
528 cmsg->l++;
529 break;
530 case _CWORD:
531 wordTRcpy(cmsg->m + cmsg->l, OFF);
532 cmsg->l += 2;
533 break;
534 case _CDWORD:
535 dwordTRcpy(cmsg->m + cmsg->l, OFF);
536 cmsg->l += 4;
537 break;
538 case _CSTRUCT:
539 *(u8 **) OFF = cmsg->m + cmsg->l;
540
541 if (cmsg->m[cmsg->l] != 0xff)
542 cmsg->l += 1 + cmsg->m[cmsg->l];
543 else
544 cmsg->l += 3 + *(u16 *) (cmsg->m + cmsg->l + 1);
545 break;
546 case _CMSTRUCT:
547
548 if (cmsg->m[cmsg->l] == '\0') {
549 *(_cmstruct *) OFF = CAPI_DEFAULT;
550 cmsg->l++;
551 jumpcstruct(cmsg);
552 } else {
553 unsigned _l = cmsg->l;
554 *(_cmstruct *) OFF = CAPI_COMPOSE;
555 cmsg->l = (cmsg->m + _l)[0] == 255 ? cmsg->l + 3 : cmsg->l + 1;
556 cmsg->p++;
557 message_2_pars(cmsg);
558 }
559 break;
560 }
561 }
562}
563
564
565
566
567
568
569
570
571
572unsigned capi_message2cmsg(_cmsg *cmsg, u8 *msg)
573{
574 memset(cmsg, 0, sizeof(_cmsg));
575 cmsg->m = msg;
576 cmsg->l = 8;
577 cmsg->p = 0;
578 byteTRcpy(cmsg->m + 4, &cmsg->Command);
579 byteTRcpy(cmsg->m + 5, &cmsg->Subcommand);
580 cmsg->par = cpars[command_2_index(cmsg->Command, cmsg->Subcommand)];
581
582 message_2_pars(cmsg);
583
584 wordTRcpy(msg + 0, &cmsg->l);
585 wordTRcpy(cmsg->m + 2, &cmsg->ApplId);
586 wordTRcpy(cmsg->m + 6, &cmsg->Messagenumber);
587
588 return 0;
589}
590
591
592
593
594
595
596
597
598
599
600
601
602
603unsigned capi_cmsg_header(_cmsg *cmsg, u16 _ApplId,
604 u8 _Command, u8 _Subcommand,
605 u16 _Messagenumber, u32 _Controller)
606{
607 memset(cmsg, 0, sizeof(_cmsg));
608 cmsg->ApplId = _ApplId;
609 cmsg->Command = _Command;
610 cmsg->Subcommand = _Subcommand;
611 cmsg->Messagenumber = _Messagenumber;
612 cmsg->adr.adrController = _Controller;
613 return 0;
614}
615
616
617
618static char *mnames[] =
619{
620 [0x01] = "ALERT_REQ",
621 [0x02] = "CONNECT_REQ",
622 [0x04] = "DISCONNECT_REQ",
623 [0x05] = "LISTEN_REQ",
624 [0x08] = "INFO_REQ",
625 [0x09] = "FACILITY_REQ",
626 [0x0a] = "SELECT_B_PROTOCOL_REQ",
627 [0x0b] = "CONNECT_B3_REQ",
628 [0x0d] = "DISCONNECT_B3_REQ",
629 [0x0f] = "DATA_B3_REQ",
630 [0x10] = "RESET_B3_REQ",
631 [0x13] = "ALERT_CONF",
632 [0x14] = "CONNECT_CONF",
633 [0x16] = "DISCONNECT_CONF",
634 [0x17] = "LISTEN_CONF",
635 [0x18] = "MANUFACTURER_REQ",
636 [0x1a] = "INFO_CONF",
637 [0x1b] = "FACILITY_CONF",
638 [0x1c] = "SELECT_B_PROTOCOL_CONF",
639 [0x1d] = "CONNECT_B3_CONF",
640 [0x1f] = "DISCONNECT_B3_CONF",
641 [0x21] = "DATA_B3_CONF",
642 [0x22] = "RESET_B3_CONF",
643 [0x26] = "CONNECT_IND",
644 [0x27] = "CONNECT_ACTIVE_IND",
645 [0x28] = "DISCONNECT_IND",
646 [0x2a] = "MANUFACTURER_CONF",
647 [0x2c] = "INFO_IND",
648 [0x2d] = "FACILITY_IND",
649 [0x2f] = "CONNECT_B3_IND",
650 [0x30] = "CONNECT_B3_ACTIVE_IND",
651 [0x31] = "DISCONNECT_B3_IND",
652 [0x33] = "DATA_B3_IND",
653 [0x34] = "RESET_B3_IND",
654 [0x35] = "CONNECT_B3_T90_ACTIVE_IND",
655 [0x38] = "CONNECT_RESP",
656 [0x39] = "CONNECT_ACTIVE_RESP",
657 [0x3a] = "DISCONNECT_RESP",
658 [0x3c] = "MANUFACTURER_IND",
659 [0x3e] = "INFO_RESP",
660 [0x3f] = "FACILITY_RESP",
661 [0x41] = "CONNECT_B3_RESP",
662 [0x42] = "CONNECT_B3_ACTIVE_RESP",
663 [0x43] = "DISCONNECT_B3_RESP",
664 [0x45] = "DATA_B3_RESP",
665 [0x46] = "RESET_B3_RESP",
666 [0x47] = "CONNECT_B3_T90_ACTIVE_RESP",
667 [0x4e] = "MANUFACTURER_RESP"
668};
669
670
671
672
673
674
675
676
677
678char *capi_cmd2str(u8 cmd, u8 subcmd)
679{
680 return mnames[command_2_index(cmd, subcmd)];
681}
682
683
684
685
686#ifdef CONFIG_CAPI_TRACE
687
688
689
690static char *pnames[] =
691{
692 NULL,
693 NULL,
694 NULL,
695 "Controller/PLCI/NCCI",
696 "AdditionalInfo",
697 "B1configuration",
698 "B1protocol",
699 "B2configuration",
700 "B2protocol",
701 "B3configuration",
702 "B3protocol",
703 "BC",
704 "BChannelinformation",
705 "BProtocol",
706 "CalledPartyNumber",
707 "CalledPartySubaddress",
708 "CallingPartyNumber",
709 "CallingPartySubaddress",
710 "CIPmask",
711 "CIPmask2",
712 "CIPValue",
713 "Class",
714 "ConnectedNumber",
715 "ConnectedSubaddress",
716 "Data32",
717 "DataHandle",
718 "DataLength",
719 "FacilityConfirmationParameter",
720 "Facilitydataarray",
721 "FacilityIndicationParameter",
722 "FacilityRequestParameter",
723 "FacilitySelector",
724 "Flags",
725 "Function",
726 "HLC",
727 "Info",
728 "InfoElement",
729 "InfoMask",
730 "InfoNumber",
731 "Keypadfacility",
732 "LLC",
733 "ManuData",
734 "ManuID",
735 "NCPI",
736 "Reason",
737 "Reason_B3",
738 "Reject",
739 "Useruserdata"
740};
741
742
743
744#include <stdarg.h>
745
746
747static _cdebbuf *bufprint(_cdebbuf *cdb, char *fmt, ...)
748{
749 va_list f;
750 size_t n, r;
751
752 if (!cdb)
753 return NULL;
754 va_start(f, fmt);
755 r = cdb->size - cdb->pos;
756 n = vsnprintf(cdb->p, r, fmt, f);
757 va_end(f);
758 if (n >= r) {
759
760 size_t ns = 2 * cdb->size;
761 u_char *nb;
762
763 while ((ns - cdb->pos) <= n)
764 ns *= 2;
765 nb = kmalloc(ns, GFP_ATOMIC);
766 if (!nb) {
767 cdebbuf_free(cdb);
768 return NULL;
769 }
770 memcpy(nb, cdb->buf, cdb->pos);
771 kfree(cdb->buf);
772 nb[cdb->pos] = 0;
773 cdb->buf = nb;
774 cdb->p = cdb->buf + cdb->pos;
775 cdb->size = ns;
776 va_start(f, fmt);
777 r = cdb->size - cdb->pos;
778 n = vsnprintf(cdb->p, r, fmt, f);
779 va_end(f);
780 }
781 cdb->p += n;
782 cdb->pos += n;
783 return cdb;
784}
785
786static _cdebbuf *printstructlen(_cdebbuf *cdb, u8 *m, unsigned len)
787{
788 unsigned hex = 0;
789
790 if (!cdb)
791 return NULL;
792 for (; len; len--, m++)
793 if (isalnum(*m) || *m == ' ') {
794 if (hex)
795 cdb = bufprint(cdb, ">");
796 cdb = bufprint(cdb, "%c", *m);
797 hex = 0;
798 } else {
799 if (!hex)
800 cdb = bufprint(cdb, "<%02x", *m);
801 else
802 cdb = bufprint(cdb, " %02x", *m);
803 hex = 1;
804 }
805 if (hex)
806 cdb = bufprint(cdb, ">");
807 return cdb;
808}
809
810static _cdebbuf *printstruct(_cdebbuf *cdb, u8 *m)
811{
812 unsigned len;
813
814 if (m[0] != 0xff) {
815 len = m[0];
816 m += 1;
817 } else {
818 len = ((u16 *) (m + 1))[0];
819 m += 3;
820 }
821 cdb = printstructlen(cdb, m, len);
822 return cdb;
823}
824
825
826#define NAME (pnames[cmsg->par[cmsg->p]])
827
828static _cdebbuf *protocol_message_2_pars(_cdebbuf *cdb, _cmsg *cmsg, int level)
829{
830 for (; TYP != _CEND; cmsg->p++) {
831 int slen = 29 + 3 - level;
832 int i;
833
834 if (!cdb)
835 return NULL;
836 cdb = bufprint(cdb, " ");
837 for (i = 0; i < level - 1; i++)
838 cdb = bufprint(cdb, " ");
839
840 switch (TYP) {
841 case _CBYTE:
842 cdb = bufprint(cdb, "%-*s = 0x%x\n", slen, NAME, *(u8 *) (cmsg->m + cmsg->l));
843 cmsg->l++;
844 break;
845 case _CWORD:
846 cdb = bufprint(cdb, "%-*s = 0x%x\n", slen, NAME, *(u16 *) (cmsg->m + cmsg->l));
847 cmsg->l += 2;
848 break;
849 case _CDWORD:
850 cdb = bufprint(cdb, "%-*s = 0x%lx\n", slen, NAME, *(u32 *) (cmsg->m + cmsg->l));
851 cmsg->l += 4;
852 break;
853 case _CSTRUCT:
854 cdb = bufprint(cdb, "%-*s = ", slen, NAME);
855 if (cmsg->m[cmsg->l] == '\0')
856 cdb = bufprint(cdb, "default");
857 else
858 cdb = printstruct(cdb, cmsg->m + cmsg->l);
859 cdb = bufprint(cdb, "\n");
860 if (cmsg->m[cmsg->l] != 0xff)
861 cmsg->l += 1 + cmsg->m[cmsg->l];
862 else
863 cmsg->l += 3 + *(u16 *) (cmsg->m + cmsg->l + 1);
864
865 break;
866
867 case _CMSTRUCT:
868
869 if (cmsg->m[cmsg->l] == '\0') {
870 cdb = bufprint(cdb, "%-*s = default\n", slen, NAME);
871 cmsg->l++;
872 jumpcstruct(cmsg);
873 } else {
874 char *name = NAME;
875 unsigned _l = cmsg->l;
876 cdb = bufprint(cdb, "%-*s\n", slen, name);
877 cmsg->l = (cmsg->m + _l)[0] == 255 ? cmsg->l + 3 : cmsg->l + 1;
878 cmsg->p++;
879 cdb = protocol_message_2_pars(cdb, cmsg, level + 1);
880 }
881 break;
882 }
883 }
884 return cdb;
885}
886
887
888static _cdebbuf *g_debbuf;
889static u_long g_debbuf_lock;
890static _cmsg *g_cmsg;
891
892static _cdebbuf *cdebbuf_alloc(void)
893{
894 _cdebbuf *cdb;
895
896 if (likely(!test_and_set_bit(1, &g_debbuf_lock))) {
897 cdb = g_debbuf;
898 goto init;
899 } else
900 cdb = kmalloc(sizeof(_cdebbuf), GFP_ATOMIC);
901 if (!cdb)
902 return NULL;
903 cdb->buf = kmalloc(CDEBUG_SIZE, GFP_ATOMIC);
904 if (!cdb->buf) {
905 kfree(cdb);
906 return NULL;
907 }
908 cdb->size = CDEBUG_SIZE;
909init:
910 cdb->buf[0] = 0;
911 cdb->p = cdb->buf;
912 cdb->pos = 0;
913 return cdb;
914}
915
916
917
918
919
920
921void cdebbuf_free(_cdebbuf *cdb)
922{
923 if (likely(cdb == g_debbuf)) {
924 test_and_clear_bit(1, &g_debbuf_lock);
925 return;
926 }
927 if (likely(cdb))
928 kfree(cdb->buf);
929 kfree(cdb);
930}
931
932
933
934
935
936
937
938
939
940
941
942
943_cdebbuf *capi_message2str(u8 *msg)
944{
945 _cdebbuf *cdb;
946 _cmsg *cmsg;
947
948 cdb = cdebbuf_alloc();
949 if (unlikely(!cdb))
950 return NULL;
951 if (likely(cdb == g_debbuf))
952 cmsg = g_cmsg;
953 else
954 cmsg = kmalloc(sizeof(_cmsg), GFP_ATOMIC);
955 if (unlikely(!cmsg)) {
956 cdebbuf_free(cdb);
957 return NULL;
958 }
959 cmsg->m = msg;
960 cmsg->l = 8;
961 cmsg->p = 0;
962 byteTRcpy(cmsg->m + 4, &cmsg->Command);
963 byteTRcpy(cmsg->m + 5, &cmsg->Subcommand);
964 cmsg->par = cpars[command_2_index(cmsg->Command, cmsg->Subcommand)];
965
966 cdb = bufprint(cdb, "%-26s ID=%03d #0x%04x LEN=%04d\n",
967 mnames[command_2_index(cmsg->Command, cmsg->Subcommand)],
968 ((unsigned short *) msg)[1],
969 ((unsigned short *) msg)[3],
970 ((unsigned short *) msg)[0]);
971
972 cdb = protocol_message_2_pars(cdb, cmsg, 1);
973 if (unlikely(cmsg != g_cmsg))
974 kfree(cmsg);
975 return cdb;
976}
977
978
979
980
981
982
983
984
985
986
987
988
989_cdebbuf *capi_cmsg2str(_cmsg *cmsg)
990{
991 _cdebbuf *cdb;
992
993 if (!cmsg->m)
994 return NULL;
995 cdb = cdebbuf_alloc();
996 if (!cdb)
997 return NULL;
998 cmsg->l = 8;
999 cmsg->p = 0;
1000 cdb = bufprint(cdb, "%s ID=%03d #0x%04x LEN=%04d\n",
1001 mnames[command_2_index(cmsg->Command, cmsg->Subcommand)],
1002 ((u16 *) cmsg->m)[1],
1003 ((u16 *) cmsg->m)[3],
1004 ((u16 *) cmsg->m)[0]);
1005 cdb = protocol_message_2_pars(cdb, cmsg, 1);
1006 return cdb;
1007}
1008
1009int __init cdebug_init(void)
1010{
1011 g_cmsg = kmalloc(sizeof(_cmsg), GFP_KERNEL);
1012 if (!g_cmsg)
1013 return -ENOMEM;
1014 g_debbuf = kmalloc(sizeof(_cdebbuf), GFP_KERNEL);
1015 if (!g_debbuf) {
1016 kfree(g_cmsg);
1017 return -ENOMEM;
1018 }
1019 g_debbuf->buf = kmalloc(CDEBUG_GSIZE, GFP_KERNEL);
1020 if (!g_debbuf->buf) {
1021 kfree(g_cmsg);
1022 kfree(g_debbuf);
1023 return -ENOMEM;
1024 }
1025 g_debbuf->size = CDEBUG_GSIZE;
1026 g_debbuf->buf[0] = 0;
1027 g_debbuf->p = g_debbuf->buf;
1028 g_debbuf->pos = 0;
1029 return 0;
1030}
1031
1032void __exit cdebug_exit(void)
1033{
1034 if (g_debbuf)
1035 kfree(g_debbuf->buf);
1036 kfree(g_debbuf);
1037 kfree(g_cmsg);
1038}
1039
1040#else
1041
1042static _cdebbuf g_debbuf = {"CONFIG_CAPI_TRACE not enabled", NULL, 0, 0};
1043
1044_cdebbuf *capi_message2str(u8 *msg)
1045{
1046 return &g_debbuf;
1047}
1048
1049_cdebbuf *capi_cmsg2str(_cmsg *cmsg)
1050{
1051 return &g_debbuf;
1052}
1053
1054void cdebbuf_free(_cdebbuf *cdb)
1055{
1056}
1057
1058int __init cdebug_init(void)
1059{
1060 return 0;
1061}
1062
1063void __exit cdebug_exit(void)
1064{
1065}
1066
1067#endif
1068
1069EXPORT_SYMBOL(cdebbuf_free);
1070EXPORT_SYMBOL(capi_cmsg2message);
1071EXPORT_SYMBOL(capi_message2cmsg);
1072EXPORT_SYMBOL(capi_cmsg_header);
1073EXPORT_SYMBOL(capi_cmd2str);
1074EXPORT_SYMBOL(capi_cmsg2str);
1075EXPORT_SYMBOL(capi_message2str);
1076EXPORT_SYMBOL(capi_info2str);
1077