capi.c 12.8 KB
Newer Older
Linus Torvalds's avatar
Linus Torvalds committed
1 2 3 4 5
/*
 * CAPI encoder/decoder for
 * Portugal Telecom CAPI 2.0
 *
 * Copyright (C) 1996 Universidade de Lisboa
6
 *
Linus Torvalds's avatar
Linus Torvalds committed
7 8
 * Written by Pedro Roque Marques (roque@di.fc.ul.pt)
 *
9
 * This software may be used and distributed according to the terms of
Linus Torvalds's avatar
Linus Torvalds committed
10 11 12 13 14 15 16 17
 * the GNU General Public License, incorporated herein by reference.
 *
 * Not compatible with the AVM Gmbh. CAPI 2.0
 *
 */

/*
 *        Documentation:
18
 *        - "Common ISDN API - Perfil Português - Versão 2.1",
Linus Torvalds's avatar
Linus Torvalds committed
19
 *           Telecom Portugal, Fev 1992.
20
 *        - "Common ISDN API - Especificação de protocolos para
Linus Torvalds's avatar
Linus Torvalds committed
21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53
 *           acesso aos canais B", Inesc, Jan 1994.
 */

/*
 *        TODO: better decoding of Information Elements
 *              for debug purposes mainly
 *              encode our number in CallerPN and ConnectedPN
 */

#include <linux/string.h>
#include <linux/kernel.h>

#include <linux/types.h>
#include <linux/slab.h>
#include <linux/mm.h>

#include <linux/skbuff.h>

#include <asm/io.h>
#include <asm/string.h>

#include <linux/isdnif.h>

#include "pcbit.h"
#include "edss1.h"
#include "capi.h"


/*
 *  Encoding of CAPI messages
 *
 */

54
int capi_conn_req(const char *calledPN, struct sk_buff **skb, int proto)
Linus Torvalds's avatar
Linus Torvalds committed
55
{
56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74
	ushort len;

	/*
	 * length
	 *   AppInfoMask - 2
	 *   BC0         - 3
	 *   BC1         - 1
	 *   Chan        - 2
	 *   Keypad      - 1
	 *   CPN         - 1
	 *   CPSA        - 1
	 *   CalledPN    - 2 + strlen
	 *   CalledPSA   - 1
	 *   rest...     - 4
	 *   ----------------
	 *   Total        18 + strlen
	 */

	len = 18 + strlen(calledPN);
Linus Torvalds's avatar
Linus Torvalds committed
75 76 77 78 79

	if (proto == ISDN_PROTO_L2_TRANS)
		len++;

	if ((*skb = dev_alloc_skb(len)) == NULL) {
80 81

		printk(KERN_WARNING "capi_conn_req: alloc_skb failed\n");
Linus Torvalds's avatar
Linus Torvalds committed
82 83 84
		return -1;
	}

85 86
	/* InfoElmMask */
	*((ushort *)skb_put(*skb, 2)) = AppInfoMask;
Linus Torvalds's avatar
Linus Torvalds committed
87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103

	if (proto == ISDN_PROTO_L2_TRANS)
	{
		/* Bearer Capability - Mandatory*/
		*(skb_put(*skb, 1)) = 3;        /* BC0.Length		*/
		*(skb_put(*skb, 1)) = 0x80;     /* Speech		*/
		*(skb_put(*skb, 1)) = 0x10;     /* Circuit Mode		*/
		*(skb_put(*skb, 1)) = 0x23;     /* A-law		*/
	}
	else
	{
		/* Bearer Capability - Mandatory*/
		*(skb_put(*skb, 1)) = 2;        /* BC0.Length		*/
		*(skb_put(*skb, 1)) = 0x88;     /* Digital Information	*/
		*(skb_put(*skb, 1)) = 0x90;     /* BC0.Octect4		*/
	}

104 105
	/* Bearer Capability - Optional*/
	*(skb_put(*skb, 1)) = 0;        /* BC1.Length = 0                    */
Linus Torvalds's avatar
Linus Torvalds committed
106

107 108
	*(skb_put(*skb, 1)) = 1;        /* ChannelID.Length = 1              */
	*(skb_put(*skb, 1)) = 0x83;     /* Basic Interface - Any Channel     */
Linus Torvalds's avatar
Linus Torvalds committed
109

110
	*(skb_put(*skb, 1)) = 0;        /* Keypad.Length = 0                 */
Linus Torvalds's avatar
Linus Torvalds committed
111 112


113 114
	*(skb_put(*skb, 1)) = 0;        /* CallingPN.Length = 0              */
	*(skb_put(*skb, 1)) = 0;        /* CallingPSA.Length = 0             */
Linus Torvalds's avatar
Linus Torvalds committed
115

116 117 118 119
	/* Called Party Number */
	*(skb_put(*skb, 1)) = strlen(calledPN) + 1;
	*(skb_put(*skb, 1)) = 0x81;
	memcpy(skb_put(*skb, strlen(calledPN)), calledPN, strlen(calledPN));
Linus Torvalds's avatar
Linus Torvalds committed
120

121
	/* '#' */
Linus Torvalds's avatar
Linus Torvalds committed
122

123
	*(skb_put(*skb, 1)) = 0;       /* CalledPSA.Length = 0     */
Linus Torvalds's avatar
Linus Torvalds committed
124

125 126 127 128 129 130 131
	/* LLC.Length  = 0; */
	/* HLC0.Length = 0; */
	/* HLC1.Length = 0; */
	/* UTUS.Length = 0; */
	memset(skb_put(*skb, 4), 0, 4);

	return len;
Linus Torvalds's avatar
Linus Torvalds committed
132 133
}

134
int capi_conn_resp(struct pcbit_chan *chan, struct sk_buff **skb)
Linus Torvalds's avatar
Linus Torvalds committed
135
{
136

Linus Torvalds's avatar
Linus Torvalds committed
137
	if ((*skb = dev_alloc_skb(5)) == NULL) {
138

Linus Torvalds's avatar
Linus Torvalds committed
139 140 141 142
		printk(KERN_WARNING "capi_conn_resp: alloc_skb failed\n");
		return -1;
	}

143 144 145 146
	*((ushort *)skb_put(*skb, 2)) = chan->callref;
	*(skb_put(*skb, 1)) = 0x01;  /* ACCEPT_CALL */
	*(skb_put(*skb, 1)) = 0;
	*(skb_put(*skb, 1)) = 0;
Linus Torvalds's avatar
Linus Torvalds committed
147

148
	return 5;
Linus Torvalds's avatar
Linus Torvalds committed
149 150
}

151
int capi_conn_active_req(struct pcbit_chan *chan, struct sk_buff **skb)
Linus Torvalds's avatar
Linus Torvalds committed
152
{
153 154 155 156
	/*
	 * 8 bytes
	 */

Linus Torvalds's avatar
Linus Torvalds committed
157
	if ((*skb = dev_alloc_skb(8)) == NULL) {
158

Linus Torvalds's avatar
Linus Torvalds committed
159 160 161 162
		printk(KERN_WARNING "capi_conn_active_req: alloc_skb failed\n");
		return -1;
	}

163
	*((ushort *)skb_put(*skb, 2)) = chan->callref;
Linus Torvalds's avatar
Linus Torvalds committed
164 165

#ifdef DEBUG
166
	printk(KERN_DEBUG "Call Reference: %04x\n", chan->callref);
Linus Torvalds's avatar
Linus Torvalds committed
167 168
#endif

169 170 171 172 173 174
	*(skb_put(*skb, 1)) = 0;       /*  BC.Length = 0;          */
	*(skb_put(*skb, 1)) = 0;       /*  ConnectedPN.Length = 0  */
	*(skb_put(*skb, 1)) = 0;       /*  PSA.Length              */
	*(skb_put(*skb, 1)) = 0;       /*  LLC.Length = 0;         */
	*(skb_put(*skb, 1)) = 0;       /*  HLC.Length = 0;         */
	*(skb_put(*skb, 1)) = 0;       /*  UTUS.Length = 0;        */
Linus Torvalds's avatar
Linus Torvalds committed
175 176 177 178

	return 8;
}

179
int capi_conn_active_resp(struct pcbit_chan *chan, struct sk_buff **skb)
Linus Torvalds's avatar
Linus Torvalds committed
180
{
181 182 183 184
	/*
	 * 2 bytes
	 */

Linus Torvalds's avatar
Linus Torvalds committed
185
	if ((*skb = dev_alloc_skb(2)) == NULL) {
186

Linus Torvalds's avatar
Linus Torvalds committed
187 188 189 190
		printk(KERN_WARNING "capi_conn_active_resp: alloc_skb failed\n");
		return -1;
	}

191
	*((ushort *)skb_put(*skb, 2)) = chan->callref;
Linus Torvalds's avatar
Linus Torvalds committed
192

193
	return 2;
Linus Torvalds's avatar
Linus Torvalds committed
194 195 196
}


197 198
int capi_select_proto_req(struct pcbit_chan *chan, struct sk_buff **skb,
			  int outgoing)
Linus Torvalds's avatar
Linus Torvalds committed
199 200
{

201 202 203
	/*
	 * 18 bytes
	 */
Linus Torvalds's avatar
Linus Torvalds committed
204 205

	if ((*skb = dev_alloc_skb(18)) == NULL) {
206

Linus Torvalds's avatar
Linus Torvalds committed
207 208 209 210
		printk(KERN_WARNING "capi_select_proto_req: alloc_skb failed\n");
		return -1;
	}

211
	*((ushort *)skb_put(*skb, 2)) = chan->callref;
Linus Torvalds's avatar
Linus Torvalds committed
212

213
	/* Layer2 protocol */
Linus Torvalds's avatar
Linus Torvalds committed
214

215 216 217 218 219 220 221
	switch (chan->proto) {
	case ISDN_PROTO_L2_X75I:
		*(skb_put(*skb, 1)) = 0x05;            /* LAPB */
		break;
	case ISDN_PROTO_L2_HDLC:
		*(skb_put(*skb, 1)) = 0x02;
		break;
Linus Torvalds's avatar
Linus Torvalds committed
222
	case ISDN_PROTO_L2_TRANS:
223
		/*
Linus Torvalds's avatar
Linus Torvalds committed
224 225 226 227
		 *	Voice (a-law)
		 */
		*(skb_put(*skb, 1)) = 0x06;
		break;
228 229 230
	default:
#ifdef DEBUG
		printk(KERN_DEBUG "Transparent\n");
Linus Torvalds's avatar
Linus Torvalds committed
231
#endif
232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259
		*(skb_put(*skb, 1)) = 0x03;
		break;
	}

	*(skb_put(*skb, 1)) = (outgoing ? 0x02 : 0x42);    /* Don't ask */
	*(skb_put(*skb, 1)) = 0x00;

	*((ushort *) skb_put(*skb, 2)) = MRU;


	*(skb_put(*skb, 1)) = 0x08;           /* Modulo */
	*(skb_put(*skb, 1)) = 0x07;           /* Max Window */

	*(skb_put(*skb, 1)) = 0x01;           /* No Layer3 Protocol */

	/*
	 * 2 - layer3 MTU       [10]
	 *   - Modulo           [12]
	 *   - Window
	 *   - layer1 proto     [14]
	 *   - bitrate
	 *   - sub-channel      [16]
	 *   - layer1dataformat [17]
	 */

	memset(skb_put(*skb, 8), 0, 8);

	return 18;
Linus Torvalds's avatar
Linus Torvalds committed
260 261 262 263 264 265 266
}


int capi_activate_transp_req(struct pcbit_chan *chan, struct sk_buff **skb)
{

	if ((*skb = dev_alloc_skb(7)) == NULL) {
267

Linus Torvalds's avatar
Linus Torvalds committed
268 269 270 271
		printk(KERN_WARNING "capi_activate_transp_req: alloc_skb failed\n");
		return -1;
	}

272
	*((ushort *)skb_put(*skb, 2)) = chan->callref;
Linus Torvalds's avatar
Linus Torvalds committed
273 274


275 276
	*(skb_put(*skb, 1)) = chan->layer2link; /* Layer2 id */
	*(skb_put(*skb, 1)) = 0x00;             /* Transmit by default */
Linus Torvalds's avatar
Linus Torvalds committed
277

278
	*((ushort *) skb_put(*skb, 2)) = MRU;
Linus Torvalds's avatar
Linus Torvalds committed
279

280 281 282
	*(skb_put(*skb, 1)) = 0x01;             /* Enables reception*/

	return 7;
Linus Torvalds's avatar
Linus Torvalds committed
283 284
}

285
int capi_tdata_req(struct pcbit_chan *chan, struct sk_buff *skb)
Linus Torvalds's avatar
Linus Torvalds committed
286 287 288
{
	ushort data_len;

289 290 291

	/*
	 * callref      - 2
Linus Torvalds's avatar
Linus Torvalds committed
292
	 * layer2link   - 1
293
	 * wBlockLength - 2
Linus Torvalds's avatar
Linus Torvalds committed
294 295 296
	 * data         - 4
	 * sernum       - 1
	 */
297

Linus Torvalds's avatar
Linus Torvalds committed
298 299
	data_len = skb->len;

300
	if (skb_headroom(skb) < 10)
Linus Torvalds's avatar
Linus Torvalds committed
301 302 303 304
	{
		printk(KERN_CRIT "No headspace (%u) on headroom %p for capi header\n", skb_headroom(skb), skb);
	}
	else
305
	{
Linus Torvalds's avatar
Linus Torvalds committed
306 307 308 309 310 311 312 313 314 315 316 317 318 319 320
		skb_push(skb, 10);
	}

	*((u16 *) (skb->data)) = chan->callref;
	skb->data[2] = chan->layer2link;
	*((u16 *) (skb->data + 3)) = data_len;

	chan->s_refnum = (chan->s_refnum + 1) % 8;
	*((u32 *) (skb->data + 5)) = chan->s_refnum;

	skb->data[9] = 0;                           /* HDLC frame number */

	return 10;
}

321 322
int capi_tdata_resp(struct pcbit_chan *chan, struct sk_buff **skb)

Linus Torvalds's avatar
Linus Torvalds committed
323 324
{
	if ((*skb = dev_alloc_skb(4)) == NULL) {
325

Linus Torvalds's avatar
Linus Torvalds committed
326 327 328 329
		printk(KERN_WARNING "capi_tdata_resp: alloc_skb failed\n");
		return -1;
	}

330
	*((ushort *)skb_put(*skb, 2)) = chan->callref;
Linus Torvalds's avatar
Linus Torvalds committed
331

332 333
	*(skb_put(*skb, 1)) = chan->layer2link;
	*(skb_put(*skb, 1)) = chan->r_refnum;
Linus Torvalds's avatar
Linus Torvalds committed
334

335
	return (*skb)->len;
Linus Torvalds's avatar
Linus Torvalds committed
336 337 338 339 340 341
}

int capi_disc_req(ushort callref, struct sk_buff **skb, u_char cause)
{

	if ((*skb = dev_alloc_skb(6)) == NULL) {
342

Linus Torvalds's avatar
Linus Torvalds committed
343 344 345 346
		printk(KERN_WARNING "capi_disc_req: alloc_skb failed\n");
		return -1;
	}

347
	*((ushort *)skb_put(*skb, 2)) = callref;
Linus Torvalds's avatar
Linus Torvalds committed
348

349 350 351
	*(skb_put(*skb, 1)) = 2;                  /* Cause.Length = 2; */
	*(skb_put(*skb, 1)) = 0x80;
	*(skb_put(*skb, 1)) = 0x80 | cause;
Linus Torvalds's avatar
Linus Torvalds committed
352

353 354 355
	/*
	 * Change it: we should send 'Sic transit gloria Mundi' here ;-)
	 */
Linus Torvalds's avatar
Linus Torvalds committed
356

357
	*(skb_put(*skb, 1)) = 0;                   /* UTUS.Length = 0;  */
Linus Torvalds's avatar
Linus Torvalds committed
358

359
	return 6;
Linus Torvalds's avatar
Linus Torvalds committed
360 361 362 363 364
}

int capi_disc_resp(struct pcbit_chan *chan, struct sk_buff **skb)
{
	if ((*skb = dev_alloc_skb(2)) == NULL) {
365

Linus Torvalds's avatar
Linus Torvalds committed
366 367 368 369
		printk(KERN_WARNING "capi_disc_resp: alloc_skb failed\n");
		return -1;
	}

370
	*((ushort *)skb_put(*skb, 2)) = chan->callref;
Linus Torvalds's avatar
Linus Torvalds committed
371

372
	return 2;
Linus Torvalds's avatar
Linus Torvalds committed
373 374 375 376 377 378 379 380
}


/*
 *  Decoding of CAPI messages
 *
 */

381 382 383
int capi_decode_conn_ind(struct pcbit_chan *chan,
			 struct sk_buff *skb,
			 struct callb_data *info)
Linus Torvalds's avatar
Linus Torvalds committed
384
{
385
	int CIlen, len;
Linus Torvalds's avatar
Linus Torvalds committed
386

387 388 389
	/* Call Reference [CAPI] */
	chan->callref = *((ushort *)skb->data);
	skb_pull(skb, 2);
Linus Torvalds's avatar
Linus Torvalds committed
390 391

#ifdef DEBUG
392
	printk(KERN_DEBUG "Call Reference: %04x\n", chan->callref);
Linus Torvalds's avatar
Linus Torvalds committed
393 394
#endif

395
	/* Channel Identification */
Linus Torvalds's avatar
Linus Torvalds committed
396

397 398 399 400
	/* Expect
	   Len = 1
	   Octect 3 = 0100 10CC - [ 7 Basic, 4 , 2-1 chan ]
	*/
Linus Torvalds's avatar
Linus Torvalds committed
401

402
	CIlen = skb->data[0];
Linus Torvalds's avatar
Linus Torvalds committed
403
#ifdef DEBUG
404
	if (CIlen == 1) {
Linus Torvalds's avatar
Linus Torvalds committed
405

406 407 408 409
		if (((skb->data[1]) & 0xFC) == 0x48)
			printk(KERN_DEBUG "decode_conn_ind: chan ok\n");
		printk(KERN_DEBUG "phyChan = %d\n", skb->data[1] & 0x03);
	}
Linus Torvalds's avatar
Linus Torvalds committed
410 411 412
	else
		printk(KERN_DEBUG "conn_ind: CIlen = %d\n", CIlen);
#endif
413
	skb_pull(skb, CIlen + 1);
Linus Torvalds's avatar
Linus Torvalds committed
414

415 416
	/* Calling Party Number */
	/* An "additional service" as far as Portugal Telecom is concerned */
Linus Torvalds's avatar
Linus Torvalds committed
417

418
	len = skb->data[0];
Linus Torvalds's avatar
Linus Torvalds committed
419 420 421

	if (len > 0) {
		int count = 1;
422

Linus Torvalds's avatar
Linus Torvalds committed
423 424 425 426 427
#ifdef DEBUG
		printk(KERN_DEBUG "CPN: Octect 3 %02x\n", skb->data[1]);
#endif
		if ((skb->data[1] & 0x80) == 0)
			count = 2;
428

Linus Torvalds's avatar
Linus Torvalds committed
429 430
		if (!(info->data.setup.CallingPN = kmalloc(len - count + 1, GFP_ATOMIC)))
			return -1;
431

432 433 434
		skb_copy_from_linear_data_offset(skb, count + 1,
						 info->data.setup.CallingPN,
						 len - count);
Linus Torvalds's avatar
Linus Torvalds committed
435 436 437 438 439 440 441 442 443 444
		info->data.setup.CallingPN[len - count] = 0;

	}
	else {
		info->data.setup.CallingPN = NULL;
		printk(KERN_DEBUG "NULL CallingPN\n");
	}

	skb_pull(skb, len + 1);

445 446
	/* Calling Party Subaddress */
	skb_pull(skb, skb->data[0] + 1);
Linus Torvalds's avatar
Linus Torvalds committed
447

448
	/* Called Party Number */
Linus Torvalds's avatar
Linus Torvalds committed
449

450
	len = skb->data[0];
Linus Torvalds's avatar
Linus Torvalds committed
451 452 453

	if (len > 0) {
		int count = 1;
454

Linus Torvalds's avatar
Linus Torvalds committed
455 456
		if ((skb->data[1] & 0x80) == 0)
			count = 2;
457

Linus Torvalds's avatar
Linus Torvalds committed
458 459
		if (!(info->data.setup.CalledPN = kmalloc(len - count + 1, GFP_ATOMIC)))
			return -1;
460

461 462 463
		skb_copy_from_linear_data_offset(skb, count + 1,
						 info->data.setup.CalledPN,
						 len - count);
Linus Torvalds's avatar
Linus Torvalds committed
464 465 466 467 468 469 470 471 472 473
		info->data.setup.CalledPN[len - count] = 0;

	}
	else {
		info->data.setup.CalledPN = NULL;
		printk(KERN_DEBUG "NULL CalledPN\n");
	}

	skb_pull(skb, len + 1);

474 475
	/* Called Party Subaddress */
	skb_pull(skb, skb->data[0] + 1);
Linus Torvalds's avatar
Linus Torvalds committed
476

477 478
	/* LLC */
	skb_pull(skb, skb->data[0] + 1);
Linus Torvalds's avatar
Linus Torvalds committed
479

480 481
	/* HLC */
	skb_pull(skb, skb->data[0] + 1);
Linus Torvalds's avatar
Linus Torvalds committed
482

483 484
	/* U2U */
	skb_pull(skb, skb->data[0] + 1);
Linus Torvalds's avatar
Linus Torvalds committed
485

486
	return 0;
Linus Torvalds's avatar
Linus Torvalds committed
487 488 489 490 491 492
}

/*
 *  returns errcode
 */

493 494
int capi_decode_conn_conf(struct pcbit_chan *chan, struct sk_buff *skb,
			  int *complete)
Linus Torvalds's avatar
Linus Torvalds committed
495
{
496 497 498 499 500 501 502
	int errcode;

	chan->callref = *((ushort *)skb->data);     /* Update CallReference */
	skb_pull(skb, 2);

	errcode = *((ushort *) skb->data);   /* read errcode */
	skb_pull(skb, 2);
Linus Torvalds's avatar
Linus Torvalds committed
503

504 505
	*complete = *(skb->data);
	skb_pull(skb, 1);
Linus Torvalds's avatar
Linus Torvalds committed
506

507 508 509 510 511 512 513
	/* FIX ME */
	/* This is actually a firmware bug */
	if (!*complete)
	{
		printk(KERN_DEBUG "complete=%02x\n", *complete);
		*complete = 1;
	}
Linus Torvalds's avatar
Linus Torvalds committed
514 515


516 517
	/* Optional Bearer Capability */
	skb_pull(skb, *(skb->data) + 1);
Linus Torvalds's avatar
Linus Torvalds committed
518

519 520
	/* Channel Identification */
	skb_pull(skb, *(skb->data) + 1);
Linus Torvalds's avatar
Linus Torvalds committed
521

522 523
	/* High Layer Compatibility follows */
	skb_pull(skb, *(skb->data) + 1);
Linus Torvalds's avatar
Linus Torvalds committed
524

525
	return errcode;
Linus Torvalds's avatar
Linus Torvalds committed
526 527
}

528
int capi_decode_conn_actv_ind(struct pcbit_chan *chan, struct sk_buff *skb)
Linus Torvalds's avatar
Linus Torvalds committed
529
{
530
	ushort len;
Linus Torvalds's avatar
Linus Torvalds committed
531
#ifdef DEBUG
532
	char str[32];
Linus Torvalds's avatar
Linus Torvalds committed
533 534
#endif

535 536
	/* Yet Another Bearer Capability */
	skb_pull(skb, *(skb->data) + 1);
Linus Torvalds's avatar
Linus Torvalds committed
537

538 539 540

	/* Connected Party Number */
	len = *(skb->data);
Linus Torvalds's avatar
Linus Torvalds committed
541 542 543

#ifdef DEBUG
	if (len > 1 && len < 31) {
544
		skb_copy_from_linear_data_offset(skb, 2, str, len - 1);
Linus Torvalds's avatar
Linus Torvalds committed
545 546 547 548 549 550 551
		str[len] = 0;
		printk(KERN_DEBUG "Connected Party Number: %s\n", str);
	}
	else
		printk(KERN_DEBUG "actv_ind CPN len = %d\n", len);
#endif

552
	skb_pull(skb, len + 1);
Linus Torvalds's avatar
Linus Torvalds committed
553

554 555
	/* Connected Subaddress */
	skb_pull(skb, *(skb->data) + 1);
Linus Torvalds's avatar
Linus Torvalds committed
556

557 558
	/* Low Layer Capability */
	skb_pull(skb, *(skb->data) + 1);
Linus Torvalds's avatar
Linus Torvalds committed
559

560 561
	/* High Layer Capability */
	skb_pull(skb, *(skb->data) + 1);
Linus Torvalds's avatar
Linus Torvalds committed
562

563
	return 0;
Linus Torvalds's avatar
Linus Torvalds committed
564 565
}

566
int capi_decode_conn_actv_conf(struct pcbit_chan *chan, struct sk_buff *skb)
Linus Torvalds's avatar
Linus Torvalds committed
567
{
568 569 570 571 572 573 574 575 576
	ushort errcode;

	errcode = *((ushort *)skb->data);
	skb_pull(skb, 2);

	/* Channel Identification
	   skb_pull(skb, skb->data[0] + 1);
	*/
	return errcode;
Linus Torvalds's avatar
Linus Torvalds committed
577 578 579 580 581
}


int capi_decode_sel_proto_conf(struct pcbit_chan *chan, struct sk_buff *skb)
{
582
	ushort errcode;
Linus Torvalds's avatar
Linus Torvalds committed
583

584 585
	chan->layer2link = *(skb->data);
	skb_pull(skb, 1);
Linus Torvalds's avatar
Linus Torvalds committed
586

587 588 589 590
	errcode = *((ushort *)skb->data);
	skb_pull(skb, 2);

	return errcode;
Linus Torvalds's avatar
Linus Torvalds committed
591 592 593 594
}

int capi_decode_actv_trans_conf(struct pcbit_chan *chan, struct sk_buff *skb)
{
595
	ushort errcode;
Linus Torvalds's avatar
Linus Torvalds committed
596

597 598
	if (chan->layer2link != *(skb->data))
		printk("capi_decode_actv_trans_conf: layer2link doesn't match\n");
Linus Torvalds's avatar
Linus Torvalds committed
599

600
	skb_pull(skb, 1);
Linus Torvalds's avatar
Linus Torvalds committed
601

602 603
	errcode = *((ushort *)skb->data);
	skb_pull(skb, 2);
Linus Torvalds's avatar
Linus Torvalds committed
604

605
	return errcode;
Linus Torvalds's avatar
Linus Torvalds committed
606 607 608 609
}

int capi_decode_disc_ind(struct pcbit_chan *chan, struct sk_buff *skb)
{
610
	ushort len;
Linus Torvalds's avatar
Linus Torvalds committed
611
#ifdef DEBUG
612
	int i;
Linus Torvalds's avatar
Linus Torvalds committed
613
#endif
614 615 616 617
	/* Cause */

	len = *(skb->data);
	skb_pull(skb, 1);
Linus Torvalds's avatar
Linus Torvalds committed
618 619 620

#ifdef DEBUG

621 622 623
	for (i = 0; i < len; i++)
		printk(KERN_DEBUG "Cause Octect %d: %02x\n", i + 3,
		       *(skb->data + i));
Linus Torvalds's avatar
Linus Torvalds committed
624 625
#endif

626
	skb_pull(skb, len);
Linus Torvalds's avatar
Linus Torvalds committed
627

628
	return 0;
Linus Torvalds's avatar
Linus Torvalds committed
629 630 631 632 633
}

#ifdef DEBUG
int capi_decode_debug_188(u_char *hdr, ushort hdrlen)
{
634 635
	char str[64];
	int len;
Linus Torvalds's avatar
Linus Torvalds committed
636

637
	len = hdr[0];
Linus Torvalds's avatar
Linus Torvalds committed
638

639 640 641 642 643 644 645
	if (len < 64 && len == hdrlen - 1) {
		memcpy(str, hdr + 1, hdrlen - 1);
		str[hdrlen - 1] = 0;
		printk("%s\n", str);
	}
	else
		printk("debug message incorrect\n");
Linus Torvalds's avatar
Linus Torvalds committed
646

647 648 649
	return 0;
}
#endif