brintos

brintos / linux-shallow public Read only

0
0
Text · 16.3 KiB · d7ae42e Raw
678 lines · c
1/* $Id: capiutil.c,v 1.13.6.4 2001/09/23 22:24:33 kai Exp $2 *3 * CAPI 2.0 convert capi message to capi message struct4 *5 * From CAPI 2.0 Development Kit AVM 1995 (msg.c)6 * Rewritten for Linux 1996 by Carsten Paeth <calle@calle.de>7 *8 * This software may be used and distributed according to the terms9 * of the GNU General Public License, incorporated herein by reference.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/* from CAPI2.0 DDK AVM Berlin GmbH */26 27typedef struct {28	int typ;29	size_t off;30} _cdef;31 32#define _CBYTE	       133#define _CWORD	       234#define _CDWORD        335#define _CSTRUCT       436#define _CMSTRUCT      537#define _CEND	       638 39static _cdef cdef[] =40{41	/*00 */42	{_CEND},43	/*01 */44	{_CEND},45	/*02 */46	{_CEND},47	/*03 */48	{_CDWORD, offsetof(_cmsg, adr.adrController)},49	/*04 */50	{_CMSTRUCT, offsetof(_cmsg, AdditionalInfo)},51	/*05 */52	{_CSTRUCT, offsetof(_cmsg, B1configuration)},53	/*06 */54	{_CWORD, offsetof(_cmsg, B1protocol)},55	/*07 */56	{_CSTRUCT, offsetof(_cmsg, B2configuration)},57	/*08 */58	{_CWORD, offsetof(_cmsg, B2protocol)},59	/*09 */60	{_CSTRUCT, offsetof(_cmsg, B3configuration)},61	/*0a */62	{_CWORD, offsetof(_cmsg, B3protocol)},63	/*0b */64	{_CSTRUCT, offsetof(_cmsg, BC)},65	/*0c */66	{_CSTRUCT, offsetof(_cmsg, BChannelinformation)},67	/*0d */68	{_CMSTRUCT, offsetof(_cmsg, BProtocol)},69	/*0e */70	{_CSTRUCT, offsetof(_cmsg, CalledPartyNumber)},71	/*0f */72	{_CSTRUCT, offsetof(_cmsg, CalledPartySubaddress)},73	/*10 */74	{_CSTRUCT, offsetof(_cmsg, CallingPartyNumber)},75	/*11 */76	{_CSTRUCT, offsetof(_cmsg, CallingPartySubaddress)},77	/*12 */78	{_CDWORD, offsetof(_cmsg, CIPmask)},79	/*13 */80	{_CDWORD, offsetof(_cmsg, CIPmask2)},81	/*14 */82	{_CWORD, offsetof(_cmsg, CIPValue)},83	/*15 */84	{_CDWORD, offsetof(_cmsg, Class)},85	/*16 */86	{_CSTRUCT, offsetof(_cmsg, ConnectedNumber)},87	/*17 */88	{_CSTRUCT, offsetof(_cmsg, ConnectedSubaddress)},89	/*18 */90	{_CDWORD, offsetof(_cmsg, Data)},91	/*19 */92	{_CWORD, offsetof(_cmsg, DataHandle)},93	/*1a */94	{_CWORD, offsetof(_cmsg, DataLength)},95	/*1b */96	{_CSTRUCT, offsetof(_cmsg, FacilityConfirmationParameter)},97	/*1c */98	{_CSTRUCT, offsetof(_cmsg, Facilitydataarray)},99	/*1d */100	{_CSTRUCT, offsetof(_cmsg, FacilityIndicationParameter)},101	/*1e */102	{_CSTRUCT, offsetof(_cmsg, FacilityRequestParameter)},103	/*1f */104	{_CWORD, offsetof(_cmsg, FacilitySelector)},105	/*20 */106	{_CWORD, offsetof(_cmsg, Flags)},107	/*21 */108	{_CDWORD, offsetof(_cmsg, Function)},109	/*22 */110	{_CSTRUCT, offsetof(_cmsg, HLC)},111	/*23 */112	{_CWORD, offsetof(_cmsg, Info)},113	/*24 */114	{_CSTRUCT, offsetof(_cmsg, InfoElement)},115	/*25 */116	{_CDWORD, offsetof(_cmsg, InfoMask)},117	/*26 */118	{_CWORD, offsetof(_cmsg, InfoNumber)},119	/*27 */120	{_CSTRUCT, offsetof(_cmsg, Keypadfacility)},121	/*28 */122	{_CSTRUCT, offsetof(_cmsg, LLC)},123	/*29 */124	{_CSTRUCT, offsetof(_cmsg, ManuData)},125	/*2a */126	{_CDWORD, offsetof(_cmsg, ManuID)},127	/*2b */128	{_CSTRUCT, offsetof(_cmsg, NCPI)},129	/*2c */130	{_CWORD, offsetof(_cmsg, Reason)},131	/*2d */132	{_CWORD, offsetof(_cmsg, Reason_B3)},133	/*2e */134	{_CWORD, offsetof(_cmsg, Reject)},135	/*2f */136	{_CSTRUCT, offsetof(_cmsg, Useruserdata)}137};138 139static unsigned char *cpars[] =140{141	/* ALERT_REQ */ [0x01] = "\x03\x04\x0c\x27\x2f\x1c\x01\x01",142	/* CONNECT_REQ */ [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	/* DISCONNECT_REQ */ [0x04] = "\x03\x04\x0c\x27\x2f\x1c\x01\x01",144	/* LISTEN_REQ */ [0x05] = "\x03\x25\x12\x13\x10\x11\x01",145	/* INFO_REQ */ [0x08] = "\x03\x0e\x04\x0c\x27\x2f\x1c\x01\x01",146	/* FACILITY_REQ */ [0x09] = "\x03\x1f\x1e\x01",147	/* SELECT_B_PROTOCOL_REQ */ [0x0a] = "\x03\x0d\x06\x08\x0a\x05\x07\x09\x01\x01",148	/* CONNECT_B3_REQ */ [0x0b] = "\x03\x2b\x01",149	/* DISCONNECT_B3_REQ */ [0x0d] = "\x03\x2b\x01",150	/* DATA_B3_REQ */ [0x0f] = "\x03\x18\x1a\x19\x20\x01",151	/* RESET_B3_REQ */ [0x10] = "\x03\x2b\x01",152	/* ALERT_CONF */ [0x13] = "\x03\x23\x01",153	/* CONNECT_CONF */ [0x14] = "\x03\x23\x01",154	/* DISCONNECT_CONF */ [0x16] = "\x03\x23\x01",155	/* LISTEN_CONF */ [0x17] = "\x03\x23\x01",156	/* MANUFACTURER_REQ */ [0x18] = "\x03\x2a\x15\x21\x29\x01",157	/* INFO_CONF */ [0x1a] = "\x03\x23\x01",158	/* FACILITY_CONF */ [0x1b] = "\x03\x23\x1f\x1b\x01",159	/* SELECT_B_PROTOCOL_CONF */ [0x1c] = "\x03\x23\x01",160	/* CONNECT_B3_CONF */ [0x1d] = "\x03\x23\x01",161	/* DISCONNECT_B3_CONF */ [0x1f] = "\x03\x23\x01",162	/* DATA_B3_CONF */ [0x21] = "\x03\x19\x23\x01",163	/* RESET_B3_CONF */ [0x22] = "\x03\x23\x01",164	/* CONNECT_IND */ [0x26] = "\x03\x14\x0e\x10\x0f\x11\x0b\x28\x22\x04\x0c\x27\x2f\x1c\x01\x01",165	/* CONNECT_ACTIVE_IND */ [0x27] = "\x03\x16\x17\x28\x01",166	/* DISCONNECT_IND */ [0x28] = "\x03\x2c\x01",167	/* MANUFACTURER_CONF */ [0x2a] = "\x03\x2a\x15\x21\x29\x01",168	/* INFO_IND */ [0x2c] = "\x03\x26\x24\x01",169	/* FACILITY_IND */ [0x2d] = "\x03\x1f\x1d\x01",170	/* CONNECT_B3_IND */ [0x2f] = "\x03\x2b\x01",171	/* CONNECT_B3_ACTIVE_IND */ [0x30] = "\x03\x2b\x01",172	/* DISCONNECT_B3_IND */ [0x31] = "\x03\x2d\x2b\x01",173	/* DATA_B3_IND */ [0x33] = "\x03\x18\x1a\x19\x20\x01",174	/* RESET_B3_IND */ [0x34] = "\x03\x2b\x01",175	/* CONNECT_B3_T90_ACTIVE_IND */ [0x35] = "\x03\x2b\x01",176	/* CONNECT_RESP */ [0x38] = "\x03\x2e\x0d\x06\x08\x0a\x05\x07\x09\x01\x16\x17\x28\x04\x0c\x27\x2f\x1c\x01\x01",177	/* CONNECT_ACTIVE_RESP */ [0x39] = "\x03\x01",178	/* DISCONNECT_RESP */ [0x3a] = "\x03\x01",179	/* MANUFACTURER_IND */ [0x3c] = "\x03\x2a\x15\x21\x29\x01",180	/* INFO_RESP */ [0x3e] = "\x03\x01",181	/* FACILITY_RESP */ [0x3f] = "\x03\x1f\x01",182	/* CONNECT_B3_RESP */ [0x41] = "\x03\x2e\x2b\x01",183	/* CONNECT_B3_ACTIVE_RESP */ [0x42] = "\x03\x01",184	/* DISCONNECT_B3_RESP */ [0x43] = "\x03\x01",185	/* DATA_B3_RESP */ [0x45] = "\x03\x19\x01",186	/* RESET_B3_RESP */ [0x46] = "\x03\x01",187	/* CONNECT_B3_T90_ACTIVE_RESP */ [0x47] = "\x03\x01",188	/* MANUFACTURER_RESP */ [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 * capi_cmd2par() - find parameter string for CAPI 2.0 command/subcommand219 * @cmd:	command number220 * @subcmd:	subcommand number221 *222 * Return value: static string, NULL if command/subcommand unknown223 */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		/* $$$$$ assert (cmsg->p); */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 * capi_cmd2str() - convert CAPI 2.0 command/subcommand number to name307 * @cmd:	command number308 * @subcmd:	subcommand number309 *310 * Return value: static string311 */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_TRACE327 328/*-------------------------------------------------------*/329 330static char *pnames[] =331{332	/*00 */ NULL,333	/*01 */ NULL,334	/*02 */ NULL,335	/*03 */ "Controller/PLCI/NCCI",336	/*04 */ "AdditionalInfo",337	/*05 */ "B1configuration",338	/*06 */ "B1protocol",339	/*07 */ "B2configuration",340	/*08 */ "B2protocol",341	/*09 */ "B3configuration",342	/*0a */ "B3protocol",343	/*0b */ "BC",344	/*0c */ "BChannelinformation",345	/*0d */ "BProtocol",346	/*0e */ "CalledPartyNumber",347	/*0f */ "CalledPartySubaddress",348	/*10 */ "CallingPartyNumber",349	/*11 */ "CallingPartySubaddress",350	/*12 */ "CIPmask",351	/*13 */ "CIPmask2",352	/*14 */ "CIPValue",353	/*15 */ "Class",354	/*16 */ "ConnectedNumber",355	/*17 */ "ConnectedSubaddress",356	/*18 */ "Data32",357	/*19 */ "DataHandle",358	/*1a */ "DataLength",359	/*1b */ "FacilityConfirmationParameter",360	/*1c */ "Facilitydataarray",361	/*1d */ "FacilityIndicationParameter",362	/*1e */ "FacilityRequestParameter",363	/*1f */ "FacilitySelector",364	/*20 */ "Flags",365	/*21 */ "Function",366	/*22 */ "HLC",367	/*23 */ "Info",368	/*24 */ "InfoElement",369	/*25 */ "InfoMask",370	/*26 */ "InfoNumber",371	/*27 */ "Keypadfacility",372	/*28 */ "LLC",373	/*29 */ "ManuData",374	/*2a */ "ManuID",375	/*2b */ "NCPI",376	/*2c */ "Reason",377	/*2d */ "Reason_B3",378	/*2e */ "Reject",379	/*2f */ "Useruserdata"380};381 382#include <linux/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		/* truncated, need bigger buffer */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			else440				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;	/* invalid command/subcommand */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			else499				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			else504				cmsg->l += 3 + *(u16 *) (cmsg->m + cmsg->l + 1);505 506			break;507 508		case _CMSTRUCT:509/*----- Metastruktur 0 -----*/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	} else541		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 * cdebbuf_free() - free CAPI debug buffer559 * @cdb:	buffer to free560 */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 * capi_message2str() - format CAPI 2.0 message for printing576 * @msg:	CAPI 2.0 message577 *578 * Allocates a CAPI debug buffer and fills it with a printable representation579 * of the CAPI 2.0 message in @msg.580 * Return value: allocated debug buffer, NULL on error581 * The returned buffer should be freed by a call to cdebbuf_free() after use.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	else595		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 /* !CONFIG_CAPI_TRACE */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#endif678