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