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#include "kcapi.h"
24
25
26
27typedef struct {
28 int typ;
29 size_t off;
30} _cdef;
31
32#define _CBYTE 1
33#define _CWORD 2
34#define _CDWORD 3
35#define _CSTRUCT 4
36#define _CMSTRUCT 5
37#define _CEND 6
38
39static _cdef cdef[] =
40{
41
42 {_CEND},
43
44 {_CEND},
45
46 {_CEND},
47
48 {_CDWORD, offsetof(_cmsg, adr.adrController)},
49
50 {_CMSTRUCT, offsetof(_cmsg, AdditionalInfo)},
51
52 {_CSTRUCT, offsetof(_cmsg, B1configuration)},
53
54 {_CWORD, offsetof(_cmsg, B1protocol)},
55
56 {_CSTRUCT, offsetof(_cmsg, B2configuration)},
57
58 {_CWORD, offsetof(_cmsg, B2protocol)},
59
60 {_CSTRUCT, offsetof(_cmsg, B3configuration)},
61
62 {_CWORD, offsetof(_cmsg, B3protocol)},
63
64 {_CSTRUCT, offsetof(_cmsg, BC)},
65
66 {_CSTRUCT, offsetof(_cmsg, BChannelinformation)},
67
68 {_CMSTRUCT, offsetof(_cmsg, BProtocol)},
69
70 {_CSTRUCT, offsetof(_cmsg, CalledPartyNumber)},
71
72 {_CSTRUCT, offsetof(_cmsg, CalledPartySubaddress)},
73
74 {_CSTRUCT, offsetof(_cmsg, CallingPartyNumber)},
75
76 {_CSTRUCT, offsetof(_cmsg, CallingPartySubaddress)},
77
78 {_CDWORD, offsetof(_cmsg, CIPmask)},
79
80 {_CDWORD, offsetof(_cmsg, CIPmask2)},
81
82 {_CWORD, offsetof(_cmsg, CIPValue)},
83
84 {_CDWORD, offsetof(_cmsg, Class)},
85
86 {_CSTRUCT, offsetof(_cmsg, ConnectedNumber)},
87
88 {_CSTRUCT, offsetof(_cmsg, ConnectedSubaddress)},
89
90 {_CDWORD, offsetof(_cmsg, Data)},
91
92 {_CWORD, offsetof(_cmsg, DataHandle)},
93
94 {_CWORD, offsetof(_cmsg, DataLength)},
95
96 {_CSTRUCT, offsetof(_cmsg, FacilityConfirmationParameter)},
97
98 {_CSTRUCT, offsetof(_cmsg, Facilitydataarray)},
99
100 {_CSTRUCT, offsetof(_cmsg, FacilityIndicationParameter)},
101
102 {_CSTRUCT, offsetof(_cmsg, FacilityRequestParameter)},
103
104 {_CWORD, offsetof(_cmsg, FacilitySelector)},
105
106 {_CWORD, offsetof(_cmsg, Flags)},
107
108 {_CDWORD, offsetof(_cmsg, Function)},
109
110 {_CSTRUCT, offsetof(_cmsg, HLC)},
111
112 {_CWORD, offsetof(_cmsg, Info)},
113
114 {_CSTRUCT, offsetof(_cmsg, InfoElement)},
115
116 {_CDWORD, offsetof(_cmsg, InfoMask)},
117
118 {_CWORD, offsetof(_cmsg, InfoNumber)},
119
120 {_CSTRUCT, offsetof(_cmsg, Keypadfacility)},
121
122 {_CSTRUCT, offsetof(_cmsg, LLC)},
123
124 {_CSTRUCT, offsetof(_cmsg, ManuData)},
125
126 {_CDWORD, offsetof(_cmsg, ManuID)},
127
128 {_CSTRUCT, offsetof(_cmsg, NCPI)},
129
130 {_CWORD, offsetof(_cmsg, Reason)},
131
132 {_CWORD, offsetof(_cmsg, Reason_B3)},
133
134 {_CWORD, offsetof(_cmsg, Reject)},
135
136 {_CSTRUCT, offsetof(_cmsg, Useruserdata)}
137};
138
139static unsigned char *cpars[] =
140{
141 [0x01] = "\x03\x04\x0c\x27\x2f\x1c\x01\x01",
142 [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",
143 [0x04] = "\x03\x04\x0c\x27\x2f\x1c\x01\x01",
144 [0x05] = "\x03\x25\x12\x13\x10\x11\x01",
145 [0x08] = "\x03\x0e\x04\x0c\x27\x2f\x1c\x01\x01",
146 [0x09] = "\x03\x1f\x1e\x01",
147 [0x0a] = "\x03\x0d\x06\x08\x0a\x05\x07\x09\x01\x01",
148 [0x0b] = "\x03\x2b\x01",
149 [0x0d] = "\x03\x2b\x01",
150 [0x0f] = "\x03\x18\x1a\x19\x20\x01",
151 [0x10] = "\x03\x2b\x01",
152 [0x13] = "\x03\x23\x01",
153 [0x14] = "\x03\x23\x01",
154 [0x16] = "\x03\x23\x01",
155 [0x17] = "\x03\x23\x01",
156 [0x18] = "\x03\x2a\x15\x21\x29\x01",
157 [0x1a] = "\x03\x23\x01",
158 [0x1b] = "\x03\x23\x1f\x1b\x01",
159 [0x1c] = "\x03\x23\x01",
160 [0x1d] = "\x03\x23\x01",
161 [0x1f] = "\x03\x23\x01",
162 [0x21] = "\x03\x19\x23\x01",
163 [0x22] = "\x03\x23\x01",
164 [0x26] = "\x03\x14\x0e\x10\x0f\x11\x0b\x28\x22\x04\x0c\x27\x2f\x1c\x01\x01",
165 [0x27] = "\x03\x16\x17\x28\x01",
166 [0x28] = "\x03\x2c\x01",
167 [0x2a] = "\x03\x2a\x15\x21\x29\x01",
168 [0x2c] = "\x03\x26\x24\x01",
169 [0x2d] = "\x03\x1f\x1d\x01",
170 [0x2f] = "\x03\x2b\x01",
171 [0x30] = "\x03\x2b\x01",
172 [0x31] = "\x03\x2d\x2b\x01",
173 [0x33] = "\x03\x18\x1a\x19\x20\x01",
174 [0x34] = "\x03\x2b\x01",
175 [0x35] = "\x03\x2b\x01",
176 [0x38] = "\x03\x2e\x0d\x06\x08\x0a\x05\x07\x09\x01\x16\x17\x28\x04\x0c\x27\x2f\x1c\x01\x01",
177 [0x39] = "\x03\x01",
178 [0x3a] = "\x03\x01",
179 [0x3c] = "\x03\x2a\x15\x21\x29\x01",
180 [0x3e] = "\x03\x01",
181 [0x3f] = "\x03\x1f\x01",
182 [0x41] = "\x03\x2e\x2b\x01",
183 [0x42] = "\x03\x01",
184 [0x43] = "\x03\x01",
185 [0x45] = "\x03\x19\x01",
186 [0x46] = "\x03\x01",
187 [0x47] = "\x03\x01",
188 [0x4e] = "\x03\x2a\x15\x21\x29\x01",
189};
190
191
192
193#define byteTLcpy(x, y) *(u8 *)(x) = *(u8 *)(y);
194#define wordTLcpy(x, y) *(u16 *)(x) = *(u16 *)(y);
195#define dwordTLcpy(x, y) memcpy(x, y, 4);
196#define structTLcpy(x, y, l) memcpy(x, y, l)
197#define structTLcpyovl(x, y, l) memmove(x, y, l)
198
199#define byteTRcpy(x, y) *(u8 *)(y) = *(u8 *)(x);
200#define wordTRcpy(x, y) *(u16 *)(y) = *(u16 *)(x);
201#define dwordTRcpy(x, y) memcpy(y, x, 4);
202#define structTRcpy(x, y, l) memcpy(y, x, l)
203#define structTRcpyovl(x, y, l) memmove(y, x, l)
204
205
206static unsigned command_2_index(u8 c, u8 sc)
207{
208 if (c & 0x80)
209 c = 0x9 + (c & 0x0f);
210 else if (c == 0x41)
211 c = 0x9 + 0x1;
212 if (c > 0x18)
213 c = 0x00;
214 return (sc & 3) * (0x9 + 0x9) + c;
215}
216
217
218
219
220
221
222
223
224
225static unsigned char *capi_cmd2par(u8 cmd, u8 subcmd)
226{
227 return cpars[command_2_index(cmd, subcmd)];
228}
229
230
231#define TYP (cdef[cmsg->par[cmsg->p]].typ)
232#define OFF (((u8 *)cmsg) + cdef[cmsg->par[cmsg->p]].off)
233
234static void jumpcstruct(_cmsg *cmsg)
235{
236 unsigned layer;
237 for (cmsg->p++, layer = 1; layer;) {
238
239 cmsg->p++;
240 switch (TYP) {
241 case _CMSTRUCT:
242 layer++;
243 break;
244 case _CEND:
245 layer--;
246 break;
247 }
248 }
249}
250
251
252
253static char *mnames[] =
254{
255 [0x01] = "ALERT_REQ",
256 [0x02] = "CONNECT_REQ",
257 [0x04] = "DISCONNECT_REQ",
258 [0x05] = "LISTEN_REQ",
259 [0x08] = "INFO_REQ",
260 [0x09] = "FACILITY_REQ",
261 [0x0a] = "SELECT_B_PROTOCOL_REQ",
262 [0x0b] = "CONNECT_B3_REQ",
263 [0x0d] = "DISCONNECT_B3_REQ",
264 [0x0f] = "DATA_B3_REQ",
265 [0x10] = "RESET_B3_REQ",
266 [0x13] = "ALERT_CONF",
267 [0x14] = "CONNECT_CONF",
268 [0x16] = "DISCONNECT_CONF",
269 [0x17] = "LISTEN_CONF",
270 [0x18] = "MANUFACTURER_REQ",
271 [0x1a] = "INFO_CONF",
272 [0x1b] = "FACILITY_CONF",
273 [0x1c] = "SELECT_B_PROTOCOL_CONF",
274 [0x1d] = "CONNECT_B3_CONF",
275 [0x1f] = "DISCONNECT_B3_CONF",
276 [0x21] = "DATA_B3_CONF",
277 [0x22] = "RESET_B3_CONF",
278 [0x26] = "CONNECT_IND",
279 [0x27] = "CONNECT_ACTIVE_IND",
280 [0x28] = "DISCONNECT_IND",
281 [0x2a] = "MANUFACTURER_CONF",
282 [0x2c] = "INFO_IND",
283 [0x2d] = "FACILITY_IND",
284 [0x2f] = "CONNECT_B3_IND",
285 [0x30] = "CONNECT_B3_ACTIVE_IND",
286 [0x31] = "DISCONNECT_B3_IND",
287 [0x33] = "DATA_B3_IND",
288 [0x34] = "RESET_B3_IND",
289 [0x35] = "CONNECT_B3_T90_ACTIVE_IND",
290 [0x38] = "CONNECT_RESP",
291 [0x39] = "CONNECT_ACTIVE_RESP",
292 [0x3a] = "DISCONNECT_RESP",
293 [0x3c] = "MANUFACTURER_IND",
294 [0x3e] = "INFO_RESP",
295 [0x3f] = "FACILITY_RESP",
296 [0x41] = "CONNECT_B3_RESP",
297 [0x42] = "CONNECT_B3_ACTIVE_RESP",
298 [0x43] = "DISCONNECT_B3_RESP",
299 [0x45] = "DATA_B3_RESP",
300 [0x46] = "RESET_B3_RESP",
301 [0x47] = "CONNECT_B3_T90_ACTIVE_RESP",
302 [0x4e] = "MANUFACTURER_RESP"
303};
304
305
306
307
308
309
310
311
312
313char *capi_cmd2str(u8 cmd, u8 subcmd)
314{
315 char *result;
316
317 result = mnames[command_2_index(cmd, subcmd)];
318 if (result == NULL)
319 result = "INVALID_COMMAND";
320 return result;
321}
322
323
324
325
326#ifdef CONFIG_CAPI_TRACE
327
328
329
330static char *pnames[] =
331{
332 NULL,
333 NULL,
334 NULL,
335 "Controller/PLCI/NCCI",
336 "AdditionalInfo",
337 "B1configuration",
338 "B1protocol",
339 "B2configuration",
340 "B2protocol",
341 "B3configuration",
342 "B3protocol",
343 "BC",
344 "BChannelinformation",
345 "BProtocol",
346 "CalledPartyNumber",
347 "CalledPartySubaddress",
348 "CallingPartyNumber",
349 "CallingPartySubaddress",
350 "CIPmask",
351 "CIPmask2",
352 "CIPValue",
353 "Class",
354 "ConnectedNumber",
355 "ConnectedSubaddress",
356 "Data32",
357 "DataHandle",
358 "DataLength",
359 "FacilityConfirmationParameter",
360 "Facilitydataarray",
361 "FacilityIndicationParameter",
362 "FacilityRequestParameter",
363 "FacilitySelector",
364 "Flags",
365 "Function",
366 "HLC",
367 "Info",
368 "InfoElement",
369 "InfoMask",
370 "InfoNumber",
371 "Keypadfacility",
372 "LLC",
373 "ManuData",
374 "ManuID",
375 "NCPI",
376 "Reason",
377 "Reason_B3",
378 "Reject",
379 "Useruserdata"
380};
381
382#include <stdarg.h>
383
384
385static _cdebbuf *bufprint(_cdebbuf *cdb, char *fmt, ...)
386{
387 va_list f;
388 size_t n, r;
389
390 if (!cdb)
391 return NULL;
392 va_start(f, fmt);
393 r = cdb->size - cdb->pos;
394 n = vsnprintf(cdb->p, r, fmt, f);
395 va_end(f);
396 if (n >= r) {
397
398 size_t ns = 2 * cdb->size;
399 u_char *nb;
400
401 while ((ns - cdb->pos) <= n)
402 ns *= 2;
403 nb = kmalloc(ns, GFP_ATOMIC);
404 if (!nb) {
405 cdebbuf_free(cdb);
406 return NULL;
407 }
408 memcpy(nb, cdb->buf, cdb->pos);
409 kfree(cdb->buf);
410 nb[cdb->pos] = 0;
411 cdb->buf = nb;
412 cdb->p = cdb->buf + cdb->pos;
413 cdb->size = ns;
414 va_start(f, fmt);
415 r = cdb->size - cdb->pos;
416 n = vsnprintf(cdb->p, r, fmt, f);
417 va_end(f);
418 }
419 cdb->p += n;
420 cdb->pos += n;
421 return cdb;
422}
423
424static _cdebbuf *printstructlen(_cdebbuf *cdb, u8 *m, unsigned len)
425{
426 unsigned hex = 0;
427
428 if (!cdb)
429 return NULL;
430 for (; len; len--, m++)
431 if (isalnum(*m) || *m == ' ') {
432 if (hex)
433 cdb = bufprint(cdb, ">");
434 cdb = bufprint(cdb, "%c", *m);
435 hex = 0;
436 } else {
437 if (!hex)
438 cdb = bufprint(cdb, "<%02x", *m);
439 else
440 cdb = bufprint(cdb, " %02x", *m);
441 hex = 1;
442 }
443 if (hex)
444 cdb = bufprint(cdb, ">");
445 return cdb;
446}
447
448static _cdebbuf *printstruct(_cdebbuf *cdb, u8 *m)
449{
450 unsigned len;
451
452 if (m[0] != 0xff) {
453 len = m[0];
454 m += 1;
455 } else {
456 len = ((u16 *) (m + 1))[0];
457 m += 3;
458 }
459 cdb = printstructlen(cdb, m, len);
460 return cdb;
461}
462
463
464#define NAME (pnames[cmsg->par[cmsg->p]])
465
466static _cdebbuf *protocol_message_2_pars(_cdebbuf *cdb, _cmsg *cmsg, int level)
467{
468 if (!cmsg->par)
469 return NULL;
470
471 for (; TYP != _CEND; cmsg->p++) {
472 int slen = 29 + 3 - level;
473 int i;
474
475 if (!cdb)
476 return NULL;
477 cdb = bufprint(cdb, " ");
478 for (i = 0; i < level - 1; i++)
479 cdb = bufprint(cdb, " ");
480
481 switch (TYP) {
482 case _CBYTE:
483 cdb = bufprint(cdb, "%-*s = 0x%x\n", slen, NAME, *(u8 *) (cmsg->m + cmsg->l));
484 cmsg->l++;
485 break;
486 case _CWORD:
487 cdb = bufprint(cdb, "%-*s = 0x%x\n", slen, NAME, *(u16 *) (cmsg->m + cmsg->l));
488 cmsg->l += 2;
489 break;
490 case _CDWORD:
491 cdb = bufprint(cdb, "%-*s = 0x%lx\n", slen, NAME, *(u32 *) (cmsg->m + cmsg->l));
492 cmsg->l += 4;
493 break;
494 case _CSTRUCT:
495 cdb = bufprint(cdb, "%-*s = ", slen, NAME);
496 if (cmsg->m[cmsg->l] == '\0')
497 cdb = bufprint(cdb, "default");
498 else
499 cdb = printstruct(cdb, cmsg->m + cmsg->l);
500 cdb = bufprint(cdb, "\n");
501 if (cmsg->m[cmsg->l] != 0xff)
502 cmsg->l += 1 + cmsg->m[cmsg->l];
503 else
504 cmsg->l += 3 + *(u16 *) (cmsg->m + cmsg->l + 1);
505
506 break;
507
508 case _CMSTRUCT:
509
510 if (cmsg->m[cmsg->l] == '\0') {
511 cdb = bufprint(cdb, "%-*s = default\n", slen, NAME);
512 cmsg->l++;
513 jumpcstruct(cmsg);
514 } else {
515 char *name = NAME;
516 unsigned _l = cmsg->l;
517 cdb = bufprint(cdb, "%-*s\n", slen, name);
518 cmsg->l = (cmsg->m + _l)[0] == 255 ? cmsg->l + 3 : cmsg->l + 1;
519 cmsg->p++;
520 cdb = protocol_message_2_pars(cdb, cmsg, level + 1);
521 }
522 break;
523 }
524 }
525 return cdb;
526}
527
528
529static _cdebbuf *g_debbuf;
530static u_long g_debbuf_lock;
531static _cmsg *g_cmsg;
532
533static _cdebbuf *cdebbuf_alloc(void)
534{
535 _cdebbuf *cdb;
536
537 if (likely(!test_and_set_bit(1, &g_debbuf_lock))) {
538 cdb = g_debbuf;
539 goto init;
540 } else
541 cdb = kmalloc(sizeof(_cdebbuf), GFP_ATOMIC);
542 if (!cdb)
543 return NULL;
544 cdb->buf = kmalloc(CDEBUG_SIZE, GFP_ATOMIC);
545 if (!cdb->buf) {
546 kfree(cdb);
547 return NULL;
548 }
549 cdb->size = CDEBUG_SIZE;
550init:
551 cdb->buf[0] = 0;
552 cdb->p = cdb->buf;
553 cdb->pos = 0;
554 return cdb;
555}
556
557
558
559
560
561
562void cdebbuf_free(_cdebbuf *cdb)
563{
564 if (likely(cdb == g_debbuf)) {
565 test_and_clear_bit(1, &g_debbuf_lock);
566 return;
567 }
568 if (likely(cdb))
569 kfree(cdb->buf);
570 kfree(cdb);
571}
572
573
574
575
576
577
578
579
580
581
582
583
584_cdebbuf *capi_message2str(u8 *msg)
585{
586 _cdebbuf *cdb;
587 _cmsg *cmsg;
588
589 cdb = cdebbuf_alloc();
590 if (unlikely(!cdb))
591 return NULL;
592 if (likely(cdb == g_debbuf))
593 cmsg = g_cmsg;
594 else
595 cmsg = kmalloc(sizeof(_cmsg), GFP_ATOMIC);
596 if (unlikely(!cmsg)) {
597 cdebbuf_free(cdb);
598 return NULL;
599 }
600 cmsg->m = msg;
601 cmsg->l = 8;
602 cmsg->p = 0;
603 byteTRcpy(cmsg->m + 4, &cmsg->Command);
604 byteTRcpy(cmsg->m + 5, &cmsg->Subcommand);
605 cmsg->par = capi_cmd2par(cmsg->Command, cmsg->Subcommand);
606
607 cdb = bufprint(cdb, "%-26s ID=%03d #0x%04x LEN=%04d\n",
608 capi_cmd2str(cmsg->Command, cmsg->Subcommand),
609 ((unsigned short *) msg)[1],
610 ((unsigned short *) msg)[3],
611 ((unsigned short *) msg)[0]);
612
613 cdb = protocol_message_2_pars(cdb, cmsg, 1);
614 if (unlikely(cmsg != g_cmsg))
615 kfree(cmsg);
616 return cdb;
617}
618
619int __init cdebug_init(void)
620{
621 g_cmsg = kmalloc(sizeof(_cmsg), GFP_KERNEL);
622 if (!g_cmsg)
623 return -ENOMEM;
624 g_debbuf = kmalloc(sizeof(_cdebbuf), GFP_KERNEL);
625 if (!g_debbuf) {
626 kfree(g_cmsg);
627 return -ENOMEM;
628 }
629 g_debbuf->buf = kmalloc(CDEBUG_GSIZE, GFP_KERNEL);
630 if (!g_debbuf->buf) {
631 kfree(g_cmsg);
632 kfree(g_debbuf);
633 return -ENOMEM;
634 }
635 g_debbuf->size = CDEBUG_GSIZE;
636 g_debbuf->buf[0] = 0;
637 g_debbuf->p = g_debbuf->buf;
638 g_debbuf->pos = 0;
639 return 0;
640}
641
642void cdebug_exit(void)
643{
644 if (g_debbuf)
645 kfree(g_debbuf->buf);
646 kfree(g_debbuf);
647 kfree(g_cmsg);
648}
649
650#else
651
652static _cdebbuf g_debbuf = {"CONFIG_CAPI_TRACE not enabled", NULL, 0, 0};
653
654_cdebbuf *capi_message2str(u8 *msg)
655{
656 return &g_debbuf;
657}
658
659_cdebbuf *capi_cmsg2str(_cmsg *cmsg)
660{
661 return &g_debbuf;
662}
663
664void cdebbuf_free(_cdebbuf *cdb)
665{
666}
667
668int __init cdebug_init(void)
669{
670 return 0;
671}
672
673void cdebug_exit(void)
674{
675}
676
677#endif
678