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
494unsigned capi_cmsg2message(_cmsg * cmsg, u8 * msg)
495{
496 cmsg->m = msg;
497 cmsg->l = 8;
498 cmsg->p = 0;
499 cmsg->par = cpars[command_2_index(cmsg->Command, cmsg->Subcommand)];
500
501 pars_2_message(cmsg);
502
503 wordTLcpy(msg + 0, &cmsg->l);
504 byteTLcpy(cmsg->m + 4, &cmsg->Command);
505 byteTLcpy(cmsg->m + 5, &cmsg->Subcommand);
506 wordTLcpy(cmsg->m + 2, &cmsg->ApplId);
507 wordTLcpy(cmsg->m + 6, &cmsg->Messagenumber);
508
509 return 0;
510}
511
512
513static void message_2_pars(_cmsg * cmsg)
514{
515 for (; TYP != _CEND; cmsg->p++) {
516
517 switch (TYP) {
518 case _CBYTE:
519 byteTRcpy(cmsg->m + cmsg->l, OFF);
520 cmsg->l++;
521 break;
522 case _CWORD:
523 wordTRcpy(cmsg->m + cmsg->l, OFF);
524 cmsg->l += 2;
525 break;
526 case _CDWORD:
527 dwordTRcpy(cmsg->m + cmsg->l, OFF);
528 cmsg->l += 4;
529 break;
530 case _CSTRUCT:
531 *(u8 **) OFF = cmsg->m + cmsg->l;
532
533 if (cmsg->m[cmsg->l] != 0xff)
534 cmsg->l += 1 + cmsg->m[cmsg->l];
535 else
536 cmsg->l += 3 + *(u16 *) (cmsg->m + cmsg->l + 1);
537 break;
538 case _CMSTRUCT:
539
540 if (cmsg->m[cmsg->l] == '\0') {
541 *(_cmstruct *) OFF = CAPI_DEFAULT;
542 cmsg->l++;
543 jumpcstruct(cmsg);
544 } else {
545 unsigned _l = cmsg->l;
546 *(_cmstruct *) OFF = CAPI_COMPOSE;
547 cmsg->l = (cmsg->m + _l)[0] == 255 ? cmsg->l + 3 : cmsg->l + 1;
548 cmsg->p++;
549 message_2_pars(cmsg);
550 }
551 break;
552 }
553 }
554}
555
556
557unsigned capi_message2cmsg(_cmsg * cmsg, u8 * msg)
558{
559 memset(cmsg, 0, sizeof(_cmsg));
560 cmsg->m = msg;
561 cmsg->l = 8;
562 cmsg->p = 0;
563 byteTRcpy(cmsg->m + 4, &cmsg->Command);
564 byteTRcpy(cmsg->m + 5, &cmsg->Subcommand);
565 cmsg->par = cpars[command_2_index(cmsg->Command, cmsg->Subcommand)];
566
567 message_2_pars(cmsg);
568
569 wordTRcpy(msg + 0, &cmsg->l);
570 wordTRcpy(cmsg->m + 2, &cmsg->ApplId);
571 wordTRcpy(cmsg->m + 6, &cmsg->Messagenumber);
572
573 return 0;
574}
575
576
577unsigned capi_cmsg_header(_cmsg * cmsg, u16 _ApplId,
578 u8 _Command, u8 _Subcommand,
579 u16 _Messagenumber, u32 _Controller)
580{
581 memset(cmsg, 0, sizeof(_cmsg));
582 cmsg->ApplId = _ApplId;
583 cmsg->Command = _Command;
584 cmsg->Subcommand = _Subcommand;
585 cmsg->Messagenumber = _Messagenumber;
586 cmsg->adr.adrController = _Controller;
587 return 0;
588}
589
590
591
592static char *mnames[] =
593{
594 [0x01] = "ALERT_REQ",
595 [0x02] = "CONNECT_REQ",
596 [0x04] = "DISCONNECT_REQ",
597 [0x05] = "LISTEN_REQ",
598 [0x08] = "INFO_REQ",
599 [0x09] = "FACILITY_REQ",
600 [0x0a] = "SELECT_B_PROTOCOL_REQ",
601 [0x0b] = "CONNECT_B3_REQ",
602 [0x0d] = "DISCONNECT_B3_REQ",
603 [0x0f] = "DATA_B3_REQ",
604 [0x10] = "RESET_B3_REQ",
605 [0x13] = "ALERT_CONF",
606 [0x14] = "CONNECT_CONF",
607 [0x16] = "DISCONNECT_CONF",
608 [0x17] = "LISTEN_CONF",
609 [0x18] = "MANUFACTURER_REQ",
610 [0x1a] = "INFO_CONF",
611 [0x1b] = "FACILITY_CONF",
612 [0x1c] = "SELECT_B_PROTOCOL_CONF",
613 [0x1d] = "CONNECT_B3_CONF",
614 [0x1f] = "DISCONNECT_B3_CONF",
615 [0x21] = "DATA_B3_CONF",
616 [0x22] = "RESET_B3_CONF",
617 [0x26] = "CONNECT_IND",
618 [0x27] = "CONNECT_ACTIVE_IND",
619 [0x28] = "DISCONNECT_IND",
620 [0x2a] = "MANUFACTURER_CONF",
621 [0x2c] = "INFO_IND",
622 [0x2d] = "FACILITY_IND",
623 [0x2f] = "CONNECT_B3_IND",
624 [0x30] = "CONNECT_B3_ACTIVE_IND",
625 [0x31] = "DISCONNECT_B3_IND",
626 [0x33] = "DATA_B3_IND",
627 [0x34] = "RESET_B3_IND",
628 [0x35] = "CONNECT_B3_T90_ACTIVE_IND",
629 [0x38] = "CONNECT_RESP",
630 [0x39] = "CONNECT_ACTIVE_RESP",
631 [0x3a] = "DISCONNECT_RESP",
632 [0x3c] = "MANUFACTURER_IND",
633 [0x3e] = "INFO_RESP",
634 [0x3f] = "FACILITY_RESP",
635 [0x41] = "CONNECT_B3_RESP",
636 [0x42] = "CONNECT_B3_ACTIVE_RESP",
637 [0x43] = "DISCONNECT_B3_RESP",
638 [0x45] = "DATA_B3_RESP",
639 [0x46] = "RESET_B3_RESP",
640 [0x47] = "CONNECT_B3_T90_ACTIVE_RESP",
641 [0x4e] = "MANUFACTURER_RESP"
642};
643
644char *capi_cmd2str(u8 cmd, u8 subcmd)
645{
646 return mnames[command_2_index(cmd, subcmd)];
647}
648
649
650
651
652#ifdef CONFIG_CAPI_TRACE
653
654
655
656static char *pnames[] =
657{
658 NULL,
659 NULL,
660 NULL,
661 "Controller/PLCI/NCCI",
662 "AdditionalInfo",
663 "B1configuration",
664 "B1protocol",
665 "B2configuration",
666 "B2protocol",
667 "B3configuration",
668 "B3protocol",
669 "BC",
670 "BChannelinformation",
671 "BProtocol",
672 "CalledPartyNumber",
673 "CalledPartySubaddress",
674 "CallingPartyNumber",
675 "CallingPartySubaddress",
676 "CIPmask",
677 "CIPmask2",
678 "CIPValue",
679 "Class",
680 "ConnectedNumber",
681 "ConnectedSubaddress",
682 "Data32",
683 "DataHandle",
684 "DataLength",
685 "FacilityConfirmationParameter",
686 "Facilitydataarray",
687 "FacilityIndicationParameter",
688 "FacilityRequestParameter",
689 "FacilitySelector",
690 "Flags",
691 "Function",
692 "HLC",
693 "Info",
694 "InfoElement",
695 "InfoMask",
696 "InfoNumber",
697 "Keypadfacility",
698 "LLC",
699 "ManuData",
700 "ManuID",
701 "NCPI",
702 "Reason",
703 "Reason_B3",
704 "Reject",
705 "Useruserdata"
706};
707
708
709
710#include <stdarg.h>
711
712
713static _cdebbuf *bufprint(_cdebbuf *cdb, char *fmt,...)
714{
715 va_list f;
716 size_t n,r;
717
718 if (!cdb)
719 return NULL;
720 va_start(f, fmt);
721 r = cdb->size - cdb->pos;
722 n = vsnprintf(cdb->p, r, fmt, f);
723 va_end(f);
724 if (n >= r) {
725
726 size_t ns = 2 * cdb->size;
727 u_char *nb;
728
729 while ((ns - cdb->pos) <= n)
730 ns *= 2;
731 nb = kmalloc(ns, GFP_ATOMIC);
732 if (!nb) {
733 cdebbuf_free(cdb);
734 return NULL;
735 }
736 memcpy(nb, cdb->buf, cdb->pos);
737 kfree(cdb->buf);
738 nb[cdb->pos] = 0;
739 cdb->buf = nb;
740 cdb->p = cdb->buf + cdb->pos;
741 cdb->size = ns;
742 va_start(f, fmt);
743 r = cdb->size - cdb->pos;
744 n = vsnprintf(cdb->p, r, fmt, f);
745 va_end(f);
746 }
747 cdb->p += n;
748 cdb->pos += n;
749 return cdb;
750}
751
752static _cdebbuf *printstructlen(_cdebbuf *cdb, u8 * m, unsigned len)
753{
754 unsigned hex = 0;
755
756 if (!cdb)
757 return NULL;
758 for (; len; len--, m++)
759 if (isalnum(*m) || *m == ' ') {
760 if (hex)
761 cdb = bufprint(cdb, ">");
762 cdb = bufprint(cdb, "%c", *m);
763 hex = 0;
764 } else {
765 if (!hex)
766 cdb = bufprint(cdb, "<%02x", *m);
767 else
768 cdb = bufprint(cdb, " %02x", *m);
769 hex = 1;
770 }
771 if (hex)
772 cdb = bufprint(cdb, ">");
773 return cdb;
774}
775
776static _cdebbuf *printstruct(_cdebbuf *cdb, u8 * m)
777{
778 unsigned len;
779
780 if (m[0] != 0xff) {
781 len = m[0];
782 m += 1;
783 } else {
784 len = ((u16 *) (m + 1))[0];
785 m += 3;
786 }
787 cdb = printstructlen(cdb, m, len);
788 return cdb;
789}
790
791
792#define NAME (pnames[cmsg->par[cmsg->p]])
793
794static _cdebbuf *protocol_message_2_pars(_cdebbuf *cdb, _cmsg *cmsg, int level)
795{
796 for (; TYP != _CEND; cmsg->p++) {
797 int slen = 29 + 3 - level;
798 int i;
799
800 if (!cdb)
801 return NULL;
802 cdb = bufprint(cdb, " ");
803 for (i = 0; i < level - 1; i++)
804 cdb = bufprint(cdb, " ");
805
806 switch (TYP) {
807 case _CBYTE:
808 cdb = bufprint(cdb, "%-*s = 0x%x\n", slen, NAME, *(u8 *) (cmsg->m + cmsg->l));
809 cmsg->l++;
810 break;
811 case _CWORD:
812 cdb = bufprint(cdb, "%-*s = 0x%x\n", slen, NAME, *(u16 *) (cmsg->m + cmsg->l));
813 cmsg->l += 2;
814 break;
815 case _CDWORD:
816 cdb = bufprint(cdb, "%-*s = 0x%lx\n", slen, NAME, *(u32 *) (cmsg->m + cmsg->l));
817 cmsg->l += 4;
818 break;
819 case _CSTRUCT:
820 cdb = bufprint(cdb, "%-*s = ", slen, NAME);
821 if (cmsg->m[cmsg->l] == '\0')
822 cdb = bufprint(cdb, "default");
823 else
824 cdb = printstruct(cdb, cmsg->m + cmsg->l);
825 cdb = bufprint(cdb, "\n");
826 if (cmsg->m[cmsg->l] != 0xff)
827 cmsg->l += 1 + cmsg->m[cmsg->l];
828 else
829 cmsg->l += 3 + *(u16 *) (cmsg->m + cmsg->l + 1);
830
831 break;
832
833 case _CMSTRUCT:
834
835 if (cmsg->m[cmsg->l] == '\0') {
836 cdb = bufprint(cdb, "%-*s = default\n", slen, NAME);
837 cmsg->l++;
838 jumpcstruct(cmsg);
839 } else {
840 char *name = NAME;
841 unsigned _l = cmsg->l;
842 cdb = bufprint(cdb, "%-*s\n", slen, name);
843 cmsg->l = (cmsg->m + _l)[0] == 255 ? cmsg->l + 3 : cmsg->l + 1;
844 cmsg->p++;
845 cdb = protocol_message_2_pars(cdb, cmsg, level + 1);
846 }
847 break;
848 }
849 }
850 return cdb;
851}
852
853
854static _cdebbuf *g_debbuf;
855static u_long g_debbuf_lock;
856static _cmsg *g_cmsg;
857
858static _cdebbuf *cdebbuf_alloc(void)
859{
860 _cdebbuf *cdb;
861
862 if (likely(!test_and_set_bit(1, &g_debbuf_lock))) {
863 cdb = g_debbuf;
864 goto init;
865 } else
866 cdb = kmalloc(sizeof(_cdebbuf), GFP_ATOMIC);
867 if (!cdb)
868 return NULL;
869 cdb->buf = kmalloc(CDEBUG_SIZE, GFP_ATOMIC);
870 if (!cdb->buf) {
871 kfree(cdb);
872 return NULL;
873 }
874 cdb->size = CDEBUG_SIZE;
875init:
876 cdb->buf[0] = 0;
877 cdb->p = cdb->buf;
878 cdb->pos = 0;
879 return cdb;
880}
881
882void cdebbuf_free(_cdebbuf *cdb)
883{
884 if (likely(cdb == g_debbuf)) {
885 test_and_clear_bit(1, &g_debbuf_lock);
886 return;
887 }
888 if (likely(cdb))
889 kfree(cdb->buf);
890 kfree(cdb);
891}
892
893
894_cdebbuf *capi_message2str(u8 * msg)
895{
896 _cdebbuf *cdb;
897 _cmsg *cmsg;
898
899 cdb = cdebbuf_alloc();
900 if (unlikely(!cdb))
901 return NULL;
902 if (likely(cdb == g_debbuf))
903 cmsg = g_cmsg;
904 else
905 cmsg = kmalloc(sizeof(_cmsg), GFP_ATOMIC);
906 if (unlikely(!cmsg)) {
907 cdebbuf_free(cdb);
908 return NULL;
909 }
910 cmsg->m = msg;
911 cmsg->l = 8;
912 cmsg->p = 0;
913 byteTRcpy(cmsg->m + 4, &cmsg->Command);
914 byteTRcpy(cmsg->m + 5, &cmsg->Subcommand);
915 cmsg->par = cpars[command_2_index(cmsg->Command, cmsg->Subcommand)];
916
917 cdb = bufprint(cdb, "%-26s ID=%03d #0x%04x LEN=%04d\n",
918 mnames[command_2_index(cmsg->Command, cmsg->Subcommand)],
919 ((unsigned short *) msg)[1],
920 ((unsigned short *) msg)[3],
921 ((unsigned short *) msg)[0]);
922
923 cdb = protocol_message_2_pars(cdb, cmsg, 1);
924 if (unlikely(cmsg != g_cmsg))
925 kfree(cmsg);
926 return cdb;
927}
928
929_cdebbuf *capi_cmsg2str(_cmsg * cmsg)
930{
931 _cdebbuf *cdb;
932
933 cdb = cdebbuf_alloc();
934 if (!cdb)
935 return NULL;
936 cmsg->l = 8;
937 cmsg->p = 0;
938 cdb = bufprint(cdb, "%s ID=%03d #0x%04x LEN=%04d\n",
939 mnames[command_2_index(cmsg->Command, cmsg->Subcommand)],
940 ((u16 *) cmsg->m)[1],
941 ((u16 *) cmsg->m)[3],
942 ((u16 *) cmsg->m)[0]);
943 cdb = protocol_message_2_pars(cdb, cmsg, 1);
944 return cdb;
945}
946
947int __init cdebug_init(void)
948{
949 g_cmsg= kmalloc(sizeof(_cmsg), GFP_KERNEL);
950 if (!g_cmsg)
951 return -ENOMEM;
952 g_debbuf = kmalloc(sizeof(_cdebbuf), GFP_KERNEL);
953 if (!g_debbuf) {
954 kfree(g_cmsg);
955 return -ENOMEM;
956 }
957 g_debbuf->buf = kmalloc(CDEBUG_GSIZE, GFP_KERNEL);
958 if (!g_debbuf->buf) {
959 kfree(g_cmsg);
960 kfree(g_debbuf);
961 return -ENOMEM;;
962 }
963 g_debbuf->size = CDEBUG_GSIZE;
964 g_debbuf->buf[0] = 0;
965 g_debbuf->p = g_debbuf->buf;
966 g_debbuf->pos = 0;
967 return 0;
968}
969
970void __exit cdebug_exit(void)
971{
972 if (g_debbuf)
973 kfree(g_debbuf->buf);
974 kfree(g_debbuf);
975 kfree(g_cmsg);
976}
977
978#else
979
980static _cdebbuf g_debbuf = {"CONFIG_CAPI_TRACE not enabled", NULL, 0, 0};
981
982_cdebbuf *capi_message2str(u8 * msg)
983{
984 return &g_debbuf;
985}
986
987_cdebbuf *capi_cmsg2str(_cmsg * cmsg)
988{
989 return &g_debbuf;
990}
991
992void cdebbuf_free(_cdebbuf *cdb)
993{
994}
995
996int __init cdebug_init(void)
997{
998 return 0;
999}
1000
1001void __exit cdebug_exit(void)
1002{
1003}
1004
1005#endif
1006
1007EXPORT_SYMBOL(cdebbuf_free);
1008EXPORT_SYMBOL(capi_cmsg2message);
1009EXPORT_SYMBOL(capi_message2cmsg);
1010EXPORT_SYMBOL(capi_cmsg_header);
1011EXPORT_SYMBOL(capi_cmd2str);
1012EXPORT_SYMBOL(capi_cmsg2str);
1013EXPORT_SYMBOL(capi_message2str);
1014EXPORT_SYMBOL(capi_info2str);
1015