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