PageRenderTime 131ms CodeModel.GetById 36ms app.highlight 86ms RepoModel.GetById 1ms app.codeStats 0ms

/drivers/isdn/capi/capidrv.c

https://bitbucket.org/ndreys/linux-sunxi
C | 2326 lines | 1941 code | 269 blank | 116 comment | 319 complexity | 729868874d8c6dd64f8cba6561afb982 MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.0, AGPL-1.0

Large files files are truncated, but you can click here to view the full file

   1/* $Id: capidrv.c,v 1.1.2.2 2004/01/12 23:17:24 keil Exp $
   2 *
   3 * ISDN4Linux Driver, using capi20 interface (kernelcapi)
   4 *
   5 * Copyright 1997 by Carsten Paeth <calle@calle.de>
   6 *
   7 * This software may be used and distributed according to the terms
   8 * of the GNU General Public License, incorporated herein by reference.
   9 *
  10 */
  11
  12#include <linux/module.h>
  13#include <linux/errno.h>
  14#include <linux/kernel.h>
  15#include <linux/major.h>
  16#include <linux/slab.h>
  17#include <linux/fcntl.h>
  18#include <linux/fs.h>
  19#include <linux/signal.h>
  20#include <linux/mm.h>
  21#include <linux/timer.h>
  22#include <linux/wait.h>
  23#include <linux/skbuff.h>
  24#include <linux/isdn.h>
  25#include <linux/isdnif.h>
  26#include <linux/proc_fs.h>
  27#include <linux/seq_file.h>
  28#include <linux/capi.h>
  29#include <linux/kernelcapi.h>
  30#include <linux/ctype.h>
  31#include <linux/init.h>
  32#include <linux/moduleparam.h>
  33
  34#include <linux/isdn/capiutil.h>
  35#include <linux/isdn/capicmd.h>
  36#include "capidrv.h"
  37
  38static int debugmode = 0;
  39
  40MODULE_DESCRIPTION("CAPI4Linux: Interface to ISDN4Linux");
  41MODULE_AUTHOR("Carsten Paeth");
  42MODULE_LICENSE("GPL");
  43module_param(debugmode, uint, S_IRUGO|S_IWUSR);
  44
  45/* -------- type definitions ----------------------------------------- */
  46
  47
  48struct capidrv_contr {
  49
  50	struct capidrv_contr *next;
  51	struct module *owner;
  52	u32 contrnr;
  53	char name[20];
  54
  55	/*
  56	 * for isdn4linux
  57	 */
  58	isdn_if interface;
  59	int myid;
  60
  61	/*
  62	 * LISTEN state
  63	 */
  64	int state;
  65	u32 cipmask;
  66	u32 cipmask2;
  67        struct timer_list listentimer;
  68
  69	/*
  70	 * ID of capi message sent
  71	 */
  72	u16 msgid;
  73
  74	/*
  75	 * B-Channels
  76	 */
  77	int nbchan;
  78	struct capidrv_bchan {
  79		struct capidrv_contr *contr;
  80		u8 msn[ISDN_MSNLEN];
  81		int l2;
  82		int l3;
  83		u8 num[ISDN_MSNLEN];
  84		u8 mynum[ISDN_MSNLEN];
  85		int si1;
  86		int si2;
  87		int incoming;
  88		int disconnecting;
  89		struct capidrv_plci {
  90			struct capidrv_plci *next;
  91			u32 plci;
  92			u32 ncci;	/* ncci for CONNECT_ACTIVE_IND */
  93			u16 msgid;	/* to identfy CONNECT_CONF */
  94			int chan;
  95			int state;
  96			int leasedline;
  97			struct capidrv_ncci {
  98				struct capidrv_ncci *next;
  99				struct capidrv_plci *plcip;
 100				u32 ncci;
 101				u16 msgid;	/* to identfy CONNECT_B3_CONF */
 102				int chan;
 103				int state;
 104				int oldstate;
 105				/* */
 106				u16 datahandle;
 107				struct ncci_datahandle_queue {
 108				    struct ncci_datahandle_queue *next;
 109				    u16                         datahandle;
 110				    int                           len;
 111				} *ackqueue;
 112			} *ncci_list;
 113		} *plcip;
 114		struct capidrv_ncci *nccip;
 115	} *bchans;
 116
 117	struct capidrv_plci *plci_list;
 118
 119	/* for q931 data */
 120	u8  q931_buf[4096];
 121	u8 *q931_read;
 122	u8 *q931_write;
 123	u8 *q931_end;
 124};
 125
 126
 127struct capidrv_data {
 128	struct capi20_appl ap;
 129	int ncontr;
 130	struct capidrv_contr *contr_list;
 131};
 132
 133typedef struct capidrv_plci capidrv_plci;
 134typedef struct capidrv_ncci capidrv_ncci;
 135typedef struct capidrv_contr capidrv_contr;
 136typedef struct capidrv_data capidrv_data;
 137typedef struct capidrv_bchan capidrv_bchan;
 138
 139/* -------- data definitions ----------------------------------------- */
 140
 141static capidrv_data global;
 142static DEFINE_SPINLOCK(global_lock);
 143
 144static void handle_dtrace_data(capidrv_contr *card,
 145	int send, int level2, u8 *data, u16 len);
 146
 147/* -------- convert functions ---------------------------------------- */
 148
 149static inline u32 b1prot(int l2, int l3)
 150{
 151	switch (l2) {
 152	case ISDN_PROTO_L2_X75I:
 153	case ISDN_PROTO_L2_X75UI:
 154	case ISDN_PROTO_L2_X75BUI:
 155		return 0;
 156	case ISDN_PROTO_L2_HDLC:
 157	default:
 158		return 0;
 159	case ISDN_PROTO_L2_TRANS:
 160		return 1;
 161        case ISDN_PROTO_L2_V11096:
 162        case ISDN_PROTO_L2_V11019:
 163        case ISDN_PROTO_L2_V11038:
 164		return 2;
 165        case ISDN_PROTO_L2_FAX:
 166		return 4;
 167	case ISDN_PROTO_L2_MODEM:
 168		return 8;
 169	}
 170}
 171
 172static inline u32 b2prot(int l2, int l3)
 173{
 174	switch (l2) {
 175	case ISDN_PROTO_L2_X75I:
 176	case ISDN_PROTO_L2_X75UI:
 177	case ISDN_PROTO_L2_X75BUI:
 178	default:
 179		return 0;
 180	case ISDN_PROTO_L2_HDLC:
 181	case ISDN_PROTO_L2_TRANS:
 182        case ISDN_PROTO_L2_V11096:
 183        case ISDN_PROTO_L2_V11019:
 184        case ISDN_PROTO_L2_V11038:
 185	case ISDN_PROTO_L2_MODEM:
 186		return 1;
 187        case ISDN_PROTO_L2_FAX:
 188		return 4;
 189	}
 190}
 191
 192static inline u32 b3prot(int l2, int l3)
 193{
 194	switch (l2) {
 195	case ISDN_PROTO_L2_X75I:
 196	case ISDN_PROTO_L2_X75UI:
 197	case ISDN_PROTO_L2_X75BUI:
 198	case ISDN_PROTO_L2_HDLC:
 199	case ISDN_PROTO_L2_TRANS:
 200        case ISDN_PROTO_L2_V11096:
 201        case ISDN_PROTO_L2_V11019:
 202        case ISDN_PROTO_L2_V11038:
 203	case ISDN_PROTO_L2_MODEM:
 204	default:
 205		return 0;
 206        case ISDN_PROTO_L2_FAX:
 207		return 4;
 208	}
 209}
 210
 211static _cstruct b1config_async_v110(u16 rate)
 212{
 213	/* CAPI-Spec "B1 Configuration" */
 214	static unsigned char buf[9];
 215	buf[0] = 8; /* len */
 216	/* maximum bitrate */
 217	buf[1] = rate & 0xff; buf[2] = (rate >> 8) & 0xff;
 218	buf[3] = 8; buf[4] = 0; /* 8 bits per character */
 219	buf[5] = 0; buf[6] = 0; /* parity none */
 220	buf[7] = 0; buf[8] = 0; /* 1 stop bit */
 221	return buf;
 222}
 223
 224static _cstruct b1config(int l2, int l3)
 225{
 226	switch (l2) {
 227	case ISDN_PROTO_L2_X75I:
 228	case ISDN_PROTO_L2_X75UI:
 229	case ISDN_PROTO_L2_X75BUI:
 230	case ISDN_PROTO_L2_HDLC:
 231	case ISDN_PROTO_L2_TRANS:
 232	default:
 233		return NULL;
 234        case ISDN_PROTO_L2_V11096:
 235	    return b1config_async_v110(9600);
 236        case ISDN_PROTO_L2_V11019:
 237	    return b1config_async_v110(19200);
 238        case ISDN_PROTO_L2_V11038:
 239	    return b1config_async_v110(38400);
 240	}
 241}
 242
 243static inline u16 si2cip(u8 si1, u8 si2)
 244{
 245	static const u8 cip[17][5] =
 246	{
 247	/*  0  1  2  3  4  */
 248		{0, 0, 0, 0, 0},	/*0 */
 249		{16, 16, 4, 26, 16},	/*1 */
 250		{17, 17, 17, 4, 4},	/*2 */
 251		{2, 2, 2, 2, 2},	/*3 */
 252		{18, 18, 18, 18, 18},	/*4 */
 253		{2, 2, 2, 2, 2},	/*5 */
 254		{0, 0, 0, 0, 0},	/*6 */
 255		{2, 2, 2, 2, 2},	/*7 */
 256		{2, 2, 2, 2, 2},	/*8 */
 257		{21, 21, 21, 21, 21},	/*9 */
 258		{19, 19, 19, 19, 19},	/*10 */
 259		{0, 0, 0, 0, 0},	/*11 */
 260		{0, 0, 0, 0, 0},	/*12 */
 261		{0, 0, 0, 0, 0},	/*13 */
 262		{0, 0, 0, 0, 0},	/*14 */
 263		{22, 22, 22, 22, 22},	/*15 */
 264		{27, 27, 27, 28, 27}	/*16 */
 265	};
 266	if (si1 > 16)
 267		si1 = 0;
 268	if (si2 > 4)
 269		si2 = 0;
 270
 271	return (u16) cip[si1][si2];
 272}
 273
 274static inline u8 cip2si1(u16 cipval)
 275{
 276	static const u8 si[32] =
 277	{7, 1, 7, 7, 1, 1, 7, 7,	/*0-7 */
 278	 7, 1, 0, 0, 0, 0, 0, 0,	/*8-15 */
 279	 1, 2, 4, 10, 9, 9, 15, 7,	/*16-23 */
 280	 7, 7, 1, 16, 16, 0, 0, 0};	/*24-31 */
 281
 282	if (cipval > 31)
 283		cipval = 0;	/* .... */
 284	return si[cipval];
 285}
 286
 287static inline u8 cip2si2(u16 cipval)
 288{
 289	static const u8 si[32] =
 290	{0, 0, 0, 0, 2, 3, 0, 0,	/*0-7 */
 291	 0, 3, 0, 0, 0, 0, 0, 0,	/*8-15 */
 292	 1, 2, 0, 0, 9, 0, 0, 0,	/*16-23 */
 293	 0, 0, 3, 2, 3, 0, 0, 0};	/*24-31 */
 294
 295	if (cipval > 31)
 296		cipval = 0;	/* .... */
 297	return si[cipval];
 298}
 299
 300
 301/* -------- controller management ------------------------------------- */
 302
 303static inline capidrv_contr *findcontrbydriverid(int driverid)
 304{
 305    	unsigned long flags;
 306	capidrv_contr *p;
 307
 308	spin_lock_irqsave(&global_lock, flags);
 309	for (p = global.contr_list; p; p = p->next)
 310		if (p->myid == driverid)
 311			break;
 312	spin_unlock_irqrestore(&global_lock, flags);
 313	return p;
 314}
 315
 316static capidrv_contr *findcontrbynumber(u32 contr)
 317{
 318	unsigned long flags;
 319	capidrv_contr *p = global.contr_list;
 320
 321	spin_lock_irqsave(&global_lock, flags);
 322	for (p = global.contr_list; p; p = p->next)
 323		if (p->contrnr == contr)
 324			break;
 325	spin_unlock_irqrestore(&global_lock, flags);
 326	return p;
 327}
 328
 329
 330/* -------- plci management ------------------------------------------ */
 331
 332static capidrv_plci *new_plci(capidrv_contr * card, int chan)
 333{
 334	capidrv_plci *plcip;
 335
 336	plcip = kzalloc(sizeof(capidrv_plci), GFP_ATOMIC);
 337
 338	if (plcip == NULL)
 339		return NULL;
 340
 341	plcip->state = ST_PLCI_NONE;
 342	plcip->plci = 0;
 343	plcip->msgid = 0;
 344	plcip->chan = chan;
 345	plcip->next = card->plci_list;
 346	card->plci_list = plcip;
 347	card->bchans[chan].plcip = plcip;
 348
 349	return plcip;
 350}
 351
 352static capidrv_plci *find_plci_by_plci(capidrv_contr * card, u32 plci)
 353{
 354	capidrv_plci *p;
 355	for (p = card->plci_list; p; p = p->next)
 356		if (p->plci == plci)
 357			return p;
 358	return NULL;
 359}
 360
 361static capidrv_plci *find_plci_by_msgid(capidrv_contr * card, u16 msgid)
 362{
 363	capidrv_plci *p;
 364	for (p = card->plci_list; p; p = p->next)
 365		if (p->msgid == msgid)
 366			return p;
 367	return NULL;
 368}
 369
 370static capidrv_plci *find_plci_by_ncci(capidrv_contr * card, u32 ncci)
 371{
 372	capidrv_plci *p;
 373	for (p = card->plci_list; p; p = p->next)
 374		if (p->plci == (ncci & 0xffff))
 375			return p;
 376	return NULL;
 377}
 378
 379static void free_plci(capidrv_contr * card, capidrv_plci * plcip)
 380{
 381	capidrv_plci **pp;
 382
 383	for (pp = &card->plci_list; *pp; pp = &(*pp)->next) {
 384		if (*pp == plcip) {
 385			*pp = (*pp)->next;
 386			card->bchans[plcip->chan].plcip = NULL;
 387			card->bchans[plcip->chan].disconnecting = 0;
 388			card->bchans[plcip->chan].incoming = 0;
 389			kfree(plcip);
 390			return;
 391		}
 392	}
 393	printk(KERN_ERR "capidrv-%d: free_plci %p (0x%x) not found, Huh?\n",
 394	       card->contrnr, plcip, plcip->plci);
 395}
 396
 397/* -------- ncci management ------------------------------------------ */
 398
 399static inline capidrv_ncci *new_ncci(capidrv_contr * card,
 400				     capidrv_plci * plcip,
 401				     u32 ncci)
 402{
 403	capidrv_ncci *nccip;
 404
 405	nccip = kzalloc(sizeof(capidrv_ncci), GFP_ATOMIC);
 406
 407	if (nccip == NULL)
 408		return NULL;
 409
 410	nccip->ncci = ncci;
 411	nccip->state = ST_NCCI_NONE;
 412	nccip->plcip = plcip;
 413	nccip->chan = plcip->chan;
 414	nccip->datahandle = 0;
 415
 416	nccip->next = plcip->ncci_list;
 417	plcip->ncci_list = nccip;
 418
 419	card->bchans[plcip->chan].nccip = nccip;
 420
 421	return nccip;
 422}
 423
 424static inline capidrv_ncci *find_ncci(capidrv_contr * card, u32 ncci)
 425{
 426	capidrv_plci *plcip;
 427	capidrv_ncci *p;
 428
 429	if ((plcip = find_plci_by_ncci(card, ncci)) == NULL)
 430		return NULL;
 431
 432	for (p = plcip->ncci_list; p; p = p->next)
 433		if (p->ncci == ncci)
 434			return p;
 435	return NULL;
 436}
 437
 438static inline capidrv_ncci *find_ncci_by_msgid(capidrv_contr * card,
 439					       u32 ncci, u16 msgid)
 440{
 441	capidrv_plci *plcip;
 442	capidrv_ncci *p;
 443
 444	if ((plcip = find_plci_by_ncci(card, ncci)) == NULL)
 445		return NULL;
 446
 447	for (p = plcip->ncci_list; p; p = p->next)
 448		if (p->msgid == msgid)
 449			return p;
 450	return NULL;
 451}
 452
 453static void free_ncci(capidrv_contr * card, struct capidrv_ncci *nccip)
 454{
 455	struct capidrv_ncci **pp;
 456
 457	for (pp = &(nccip->plcip->ncci_list); *pp; pp = &(*pp)->next) {
 458		if (*pp == nccip) {
 459			*pp = (*pp)->next;
 460			break;
 461		}
 462	}
 463	card->bchans[nccip->chan].nccip = NULL;
 464	kfree(nccip);
 465}
 466
 467static int capidrv_add_ack(struct capidrv_ncci *nccip,
 468		           u16 datahandle, int len)
 469{
 470	struct ncci_datahandle_queue *n, **pp;
 471
 472	n = (struct ncci_datahandle_queue *)
 473		kmalloc(sizeof(struct ncci_datahandle_queue), GFP_ATOMIC);
 474	if (!n) {
 475	   printk(KERN_ERR "capidrv: kmalloc ncci_datahandle failed\n");
 476	   return -1;
 477	}
 478	n->next = NULL;
 479	n->datahandle = datahandle;
 480	n->len = len;
 481	for (pp = &nccip->ackqueue; *pp; pp = &(*pp)->next) ;
 482	*pp = n;
 483	return 0;
 484}
 485
 486static int capidrv_del_ack(struct capidrv_ncci *nccip, u16 datahandle)
 487{
 488	struct ncci_datahandle_queue **pp, *p;
 489	int len;
 490
 491	for (pp = &nccip->ackqueue; *pp; pp = &(*pp)->next) {
 492 		if ((*pp)->datahandle == datahandle) {
 493			p = *pp;
 494			len = p->len;
 495			*pp = (*pp)->next;
 496		        kfree(p);
 497			return len;
 498		}
 499	}
 500	return -1;
 501}
 502
 503/* -------- convert and send capi message ---------------------------- */
 504
 505static void send_message(capidrv_contr * card, _cmsg * cmsg)
 506{
 507	struct sk_buff *skb;
 508	size_t len;
 509
 510	capi_cmsg2message(cmsg, cmsg->buf);
 511	len = CAPIMSG_LEN(cmsg->buf);
 512	skb = alloc_skb(len, GFP_ATOMIC);
 513	if (!skb) {
 514		printk(KERN_ERR "capidrv::send_message: can't allocate mem\n");
 515		return;
 516	}
 517	memcpy(skb_put(skb, len), cmsg->buf, len);
 518	if (capi20_put_message(&global.ap, skb) != CAPI_NOERROR)
 519		kfree_skb(skb);
 520}
 521
 522/* -------- state machine -------------------------------------------- */
 523
 524struct listenstatechange {
 525	int actstate;
 526	int nextstate;
 527	int event;
 528};
 529
 530static struct listenstatechange listentable[] =
 531{
 532  {ST_LISTEN_NONE, ST_LISTEN_WAIT_CONF, EV_LISTEN_REQ},
 533  {ST_LISTEN_ACTIVE, ST_LISTEN_ACTIVE_WAIT_CONF, EV_LISTEN_REQ},
 534  {ST_LISTEN_WAIT_CONF, ST_LISTEN_NONE, EV_LISTEN_CONF_ERROR},
 535  {ST_LISTEN_ACTIVE_WAIT_CONF, ST_LISTEN_ACTIVE, EV_LISTEN_CONF_ERROR},
 536  {ST_LISTEN_WAIT_CONF, ST_LISTEN_NONE, EV_LISTEN_CONF_EMPTY},
 537  {ST_LISTEN_ACTIVE_WAIT_CONF, ST_LISTEN_NONE, EV_LISTEN_CONF_EMPTY},
 538  {ST_LISTEN_WAIT_CONF, ST_LISTEN_ACTIVE, EV_LISTEN_CONF_OK},
 539  {ST_LISTEN_ACTIVE_WAIT_CONF, ST_LISTEN_ACTIVE, EV_LISTEN_CONF_OK},
 540  {},
 541};
 542
 543static void listen_change_state(capidrv_contr * card, int event)
 544{
 545	struct listenstatechange *p = listentable;
 546	while (p->event) {
 547		if (card->state == p->actstate && p->event == event) {
 548			if (debugmode)
 549				printk(KERN_DEBUG "capidrv-%d: listen_change_state %d -> %d\n",
 550				       card->contrnr, card->state, p->nextstate);
 551			card->state = p->nextstate;
 552			return;
 553		}
 554		p++;
 555	}
 556	printk(KERN_ERR "capidrv-%d: listen_change_state state=%d event=%d ????\n",
 557	       card->contrnr, card->state, event);
 558
 559}
 560
 561/* ------------------------------------------------------------------ */
 562
 563static void p0(capidrv_contr * card, capidrv_plci * plci)
 564{
 565	isdn_ctrl cmd;
 566
 567	card->bchans[plci->chan].contr = NULL;
 568	cmd.command = ISDN_STAT_DHUP;
 569	cmd.driver = card->myid;
 570	cmd.arg = plci->chan;
 571	card->interface.statcallb(&cmd);
 572	free_plci(card, plci);
 573}
 574
 575/* ------------------------------------------------------------------ */
 576
 577struct plcistatechange {
 578	int actstate;
 579	int nextstate;
 580	int event;
 581	void (*changefunc) (capidrv_contr * card, capidrv_plci * plci);
 582};
 583
 584static struct plcistatechange plcitable[] =
 585{
 586  /* P-0 */
 587  {ST_PLCI_NONE, ST_PLCI_OUTGOING, EV_PLCI_CONNECT_REQ, NULL},
 588  {ST_PLCI_NONE, ST_PLCI_ALLOCATED, EV_PLCI_FACILITY_IND_UP, NULL},
 589  {ST_PLCI_NONE, ST_PLCI_INCOMING, EV_PLCI_CONNECT_IND, NULL},
 590  {ST_PLCI_NONE, ST_PLCI_RESUMEING, EV_PLCI_RESUME_REQ, NULL},
 591  /* P-0.1 */
 592  {ST_PLCI_OUTGOING, ST_PLCI_NONE, EV_PLCI_CONNECT_CONF_ERROR, p0},
 593  {ST_PLCI_OUTGOING, ST_PLCI_ALLOCATED, EV_PLCI_CONNECT_CONF_OK, NULL},
 594  /* P-1 */
 595  {ST_PLCI_ALLOCATED, ST_PLCI_ACTIVE, EV_PLCI_CONNECT_ACTIVE_IND, NULL},
 596  {ST_PLCI_ALLOCATED, ST_PLCI_DISCONNECTING, EV_PLCI_DISCONNECT_REQ, NULL},
 597  {ST_PLCI_ALLOCATED, ST_PLCI_DISCONNECTING, EV_PLCI_FACILITY_IND_DOWN, NULL},
 598  {ST_PLCI_ALLOCATED, ST_PLCI_DISCONNECTED, EV_PLCI_DISCONNECT_IND, NULL},
 599  /* P-ACT */
 600  {ST_PLCI_ACTIVE, ST_PLCI_DISCONNECTING, EV_PLCI_DISCONNECT_REQ, NULL},
 601  {ST_PLCI_ACTIVE, ST_PLCI_DISCONNECTING, EV_PLCI_FACILITY_IND_DOWN, NULL},
 602  {ST_PLCI_ACTIVE, ST_PLCI_DISCONNECTED, EV_PLCI_DISCONNECT_IND, NULL},
 603  {ST_PLCI_ACTIVE, ST_PLCI_HELD, EV_PLCI_HOLD_IND, NULL},
 604  {ST_PLCI_ACTIVE, ST_PLCI_DISCONNECTING, EV_PLCI_SUSPEND_IND, NULL},
 605  /* P-2 */
 606  {ST_PLCI_INCOMING, ST_PLCI_DISCONNECTING, EV_PLCI_CONNECT_REJECT, NULL},
 607  {ST_PLCI_INCOMING, ST_PLCI_FACILITY_IND, EV_PLCI_FACILITY_IND_UP, NULL},
 608  {ST_PLCI_INCOMING, ST_PLCI_ACCEPTING, EV_PLCI_CONNECT_RESP, NULL},
 609  {ST_PLCI_INCOMING, ST_PLCI_DISCONNECTING, EV_PLCI_DISCONNECT_REQ, NULL},
 610  {ST_PLCI_INCOMING, ST_PLCI_DISCONNECTING, EV_PLCI_FACILITY_IND_DOWN, NULL},
 611  {ST_PLCI_INCOMING, ST_PLCI_DISCONNECTED, EV_PLCI_DISCONNECT_IND, NULL},
 612  {ST_PLCI_INCOMING, ST_PLCI_DISCONNECTING, EV_PLCI_CD_IND, NULL},
 613  /* P-3 */
 614  {ST_PLCI_FACILITY_IND, ST_PLCI_DISCONNECTING, EV_PLCI_CONNECT_REJECT, NULL},
 615  {ST_PLCI_FACILITY_IND, ST_PLCI_ACCEPTING, EV_PLCI_CONNECT_ACTIVE_IND, NULL},
 616  {ST_PLCI_FACILITY_IND, ST_PLCI_DISCONNECTING, EV_PLCI_DISCONNECT_REQ, NULL},
 617  {ST_PLCI_FACILITY_IND, ST_PLCI_DISCONNECTING, EV_PLCI_FACILITY_IND_DOWN, NULL},
 618  {ST_PLCI_FACILITY_IND, ST_PLCI_DISCONNECTED, EV_PLCI_DISCONNECT_IND, NULL},
 619  /* P-4 */
 620  {ST_PLCI_ACCEPTING, ST_PLCI_ACTIVE, EV_PLCI_CONNECT_ACTIVE_IND, NULL},
 621  {ST_PLCI_ACCEPTING, ST_PLCI_DISCONNECTING, EV_PLCI_DISCONNECT_REQ, NULL},
 622  {ST_PLCI_ACCEPTING, ST_PLCI_DISCONNECTING, EV_PLCI_FACILITY_IND_DOWN, NULL},
 623  {ST_PLCI_ACCEPTING, ST_PLCI_DISCONNECTED, EV_PLCI_DISCONNECT_IND, NULL},
 624  /* P-5 */
 625  {ST_PLCI_DISCONNECTING, ST_PLCI_DISCONNECTED, EV_PLCI_DISCONNECT_IND, NULL},
 626  /* P-6 */
 627  {ST_PLCI_DISCONNECTED, ST_PLCI_NONE, EV_PLCI_DISCONNECT_RESP, p0},
 628  /* P-0.Res */
 629  {ST_PLCI_RESUMEING, ST_PLCI_NONE, EV_PLCI_RESUME_CONF_ERROR, p0},
 630  {ST_PLCI_RESUMEING, ST_PLCI_RESUME, EV_PLCI_RESUME_CONF_OK, NULL},
 631  /* P-RES */
 632  {ST_PLCI_RESUME, ST_PLCI_ACTIVE, EV_PLCI_RESUME_IND, NULL},
 633  /* P-HELD */
 634  {ST_PLCI_HELD, ST_PLCI_ACTIVE, EV_PLCI_RETRIEVE_IND, NULL},
 635  {},
 636};
 637
 638static void plci_change_state(capidrv_contr * card, capidrv_plci * plci, int event)
 639{
 640	struct plcistatechange *p = plcitable;
 641	while (p->event) {
 642		if (plci->state == p->actstate && p->event == event) {
 643			if (debugmode)
 644				printk(KERN_DEBUG "capidrv-%d: plci_change_state:0x%x %d -> %d\n",
 645				  card->contrnr, plci->plci, plci->state, p->nextstate);
 646			plci->state = p->nextstate;
 647			if (p->changefunc)
 648				p->changefunc(card, plci);
 649			return;
 650		}
 651		p++;
 652	}
 653	printk(KERN_ERR "capidrv-%d: plci_change_state:0x%x state=%d event=%d ????\n",
 654	       card->contrnr, plci->plci, plci->state, event);
 655}
 656
 657/* ------------------------------------------------------------------ */
 658
 659static _cmsg cmsg;
 660
 661static void n0(capidrv_contr * card, capidrv_ncci * ncci)
 662{
 663	isdn_ctrl cmd;
 664
 665	capi_fill_DISCONNECT_REQ(&cmsg,
 666				 global.ap.applid,
 667				 card->msgid++,
 668				 ncci->plcip->plci,
 669				 NULL,	/* BChannelinformation */
 670				 NULL,	/* Keypadfacility */
 671				 NULL,	/* Useruserdata */   /* $$$$ */
 672				 NULL	/* Facilitydataarray */
 673	);
 674	plci_change_state(card, ncci->plcip, EV_PLCI_DISCONNECT_REQ);
 675	send_message(card, &cmsg);
 676
 677	cmd.command = ISDN_STAT_BHUP;
 678	cmd.driver = card->myid;
 679	cmd.arg = ncci->chan;
 680	card->interface.statcallb(&cmd);
 681	free_ncci(card, ncci);
 682}
 683
 684/* ------------------------------------------------------------------ */
 685
 686struct nccistatechange {
 687	int actstate;
 688	int nextstate;
 689	int event;
 690	void (*changefunc) (capidrv_contr * card, capidrv_ncci * ncci);
 691};
 692
 693static struct nccistatechange nccitable[] =
 694{
 695  /* N-0 */
 696  {ST_NCCI_NONE, ST_NCCI_OUTGOING, EV_NCCI_CONNECT_B3_REQ, NULL},
 697  {ST_NCCI_NONE, ST_NCCI_INCOMING, EV_NCCI_CONNECT_B3_IND, NULL},
 698  /* N-0.1 */
 699  {ST_NCCI_OUTGOING, ST_NCCI_ALLOCATED, EV_NCCI_CONNECT_B3_CONF_OK, NULL},
 700  {ST_NCCI_OUTGOING, ST_NCCI_NONE, EV_NCCI_CONNECT_B3_CONF_ERROR, n0},
 701  /* N-1 */
 702  {ST_NCCI_INCOMING, ST_NCCI_DISCONNECTING, EV_NCCI_CONNECT_B3_REJECT, NULL},
 703  {ST_NCCI_INCOMING, ST_NCCI_ALLOCATED, EV_NCCI_CONNECT_B3_RESP, NULL},
 704  {ST_NCCI_INCOMING, ST_NCCI_DISCONNECTED, EV_NCCI_DISCONNECT_B3_IND, NULL},
 705  {ST_NCCI_INCOMING, ST_NCCI_DISCONNECTING, EV_NCCI_DISCONNECT_B3_REQ, NULL},
 706  /* N-2 */
 707  {ST_NCCI_ALLOCATED, ST_NCCI_ACTIVE, EV_NCCI_CONNECT_B3_ACTIVE_IND, NULL},
 708  {ST_NCCI_ALLOCATED, ST_NCCI_DISCONNECTED, EV_NCCI_DISCONNECT_B3_IND, NULL},
 709  {ST_NCCI_ALLOCATED, ST_NCCI_DISCONNECTING, EV_NCCI_DISCONNECT_B3_REQ, NULL},
 710  /* N-ACT */
 711  {ST_NCCI_ACTIVE, ST_NCCI_ACTIVE, EV_NCCI_RESET_B3_IND, NULL},
 712  {ST_NCCI_ACTIVE, ST_NCCI_RESETING, EV_NCCI_RESET_B3_REQ, NULL},
 713  {ST_NCCI_ACTIVE, ST_NCCI_DISCONNECTED, EV_NCCI_DISCONNECT_B3_IND, NULL},
 714  {ST_NCCI_ACTIVE, ST_NCCI_DISCONNECTING, EV_NCCI_DISCONNECT_B3_REQ, NULL},
 715  /* N-3 */
 716  {ST_NCCI_RESETING, ST_NCCI_ACTIVE, EV_NCCI_RESET_B3_IND, NULL},
 717  {ST_NCCI_RESETING, ST_NCCI_DISCONNECTED, EV_NCCI_DISCONNECT_B3_IND, NULL},
 718  {ST_NCCI_RESETING, ST_NCCI_DISCONNECTING, EV_NCCI_DISCONNECT_B3_REQ, NULL},
 719  /* N-4 */
 720  {ST_NCCI_DISCONNECTING, ST_NCCI_DISCONNECTED, EV_NCCI_DISCONNECT_B3_IND, NULL},
 721  {ST_NCCI_DISCONNECTING, ST_NCCI_PREVIOUS, EV_NCCI_DISCONNECT_B3_CONF_ERROR,NULL},
 722  /* N-5 */
 723  {ST_NCCI_DISCONNECTED, ST_NCCI_NONE, EV_NCCI_DISCONNECT_B3_RESP, n0},
 724  {},
 725};
 726
 727static void ncci_change_state(capidrv_contr * card, capidrv_ncci * ncci, int event)
 728{
 729	struct nccistatechange *p = nccitable;
 730	while (p->event) {
 731		if (ncci->state == p->actstate && p->event == event) {
 732			if (debugmode)
 733				printk(KERN_DEBUG "capidrv-%d: ncci_change_state:0x%x %d -> %d\n",
 734				  card->contrnr, ncci->ncci, ncci->state, p->nextstate);
 735			if (p->nextstate == ST_NCCI_PREVIOUS) {
 736				ncci->state = ncci->oldstate;
 737				ncci->oldstate = p->actstate;
 738			} else {
 739				ncci->oldstate = p->actstate;
 740				ncci->state = p->nextstate;
 741			}
 742			if (p->changefunc)
 743				p->changefunc(card, ncci);
 744			return;
 745		}
 746		p++;
 747	}
 748	printk(KERN_ERR "capidrv-%d: ncci_change_state:0x%x state=%d event=%d ????\n",
 749	       card->contrnr, ncci->ncci, ncci->state, event);
 750}
 751
 752/* ------------------------------------------------------------------- */
 753
 754static inline int new_bchan(capidrv_contr * card)
 755{
 756	int i;
 757	for (i = 0; i < card->nbchan; i++) {
 758		if (card->bchans[i].plcip == NULL) {
 759			card->bchans[i].disconnecting = 0;
 760			return i;
 761		}
 762	}
 763	return -1;
 764}
 765
 766/* ------------------------------------------------------------------- */
 767
 768static void handle_controller(_cmsg * cmsg)
 769{
 770	capidrv_contr *card = findcontrbynumber(cmsg->adr.adrController & 0x7f);
 771
 772	if (!card) {
 773		printk(KERN_ERR "capidrv: %s from unknown controller 0x%x\n",
 774		       capi_cmd2str(cmsg->Command, cmsg->Subcommand),
 775		       cmsg->adr.adrController & 0x7f);
 776		return;
 777	}
 778	switch (CAPICMD(cmsg->Command, cmsg->Subcommand)) {
 779
 780	case CAPI_LISTEN_CONF:	/* Controller */
 781		if (debugmode)
 782			printk(KERN_DEBUG "capidrv-%d: listenconf Info=0x%4x (%s) cipmask=0x%x\n",
 783			       card->contrnr, cmsg->Info, capi_info2str(cmsg->Info), card->cipmask);
 784		if (cmsg->Info) {
 785			listen_change_state(card, EV_LISTEN_CONF_ERROR);
 786		} else if (card->cipmask == 0) {
 787			listen_change_state(card, EV_LISTEN_CONF_EMPTY);
 788		} else {
 789			listen_change_state(card, EV_LISTEN_CONF_OK);
 790		}
 791		break;
 792
 793	case CAPI_MANUFACTURER_IND:	/* Controller */
 794		if (   cmsg->ManuID == 0x214D5641
 795		    && cmsg->Class == 0
 796		    && cmsg->Function == 1) {
 797		   u8  *data = cmsg->ManuData+3;
 798		   u16  len = cmsg->ManuData[0];
 799		   u16 layer;
 800		   int direction;
 801		   if (len == 255) {
 802		      len = (cmsg->ManuData[1] | (cmsg->ManuData[2] << 8));
 803		      data += 2;
 804		   }
 805		   len -= 2;
 806		   layer = ((*(data-1)) << 8) | *(data-2);
 807		   if (layer & 0x300)
 808			direction = (layer & 0x200) ? 0 : 1;
 809		   else direction = (layer & 0x800) ? 0 : 1;
 810		   if (layer & 0x0C00) {
 811		   	if ((layer & 0xff) == 0x80) {
 812		           handle_dtrace_data(card, direction, 1, data, len);
 813		           break;
 814		   	}
 815		   } else if ((layer & 0xff) < 0x80) {
 816		      handle_dtrace_data(card, direction, 0, data, len);
 817		      break;
 818		   }
 819	           printk(KERN_INFO "capidrv-%d: %s from controller 0x%x layer 0x%x, ignored\n",
 820                        card->contrnr, 
 821			capi_cmd2str(cmsg->Command, cmsg->Subcommand),
 822			cmsg->adr.adrController, layer);
 823                   break;
 824		}
 825		goto ignored;
 826	case CAPI_MANUFACTURER_CONF:	/* Controller */
 827		if (cmsg->ManuID == 0x214D5641) {
 828		   char *s = NULL;
 829		   switch (cmsg->Class) {
 830		      case 0: break;
 831		      case 1: s = "unknown class"; break;
 832		      case 2: s = "unknown function"; break;
 833		      default: s = "unknown error"; break;
 834		   }
 835		   if (s)
 836	           printk(KERN_INFO "capidrv-%d: %s from controller 0x%x function %d: %s\n",
 837			card->contrnr,
 838			capi_cmd2str(cmsg->Command, cmsg->Subcommand),
 839			cmsg->adr.adrController,
 840			cmsg->Function, s);
 841		   break;
 842		}
 843		goto ignored;
 844	case CAPI_FACILITY_IND:	/* Controller/plci/ncci */
 845		goto ignored;
 846	case CAPI_FACILITY_CONF:	/* Controller/plci/ncci */
 847		goto ignored;
 848	case CAPI_INFO_IND:	/* Controller/plci */
 849		goto ignored;
 850	case CAPI_INFO_CONF:	/* Controller/plci */
 851		goto ignored;
 852
 853	default:
 854		printk(KERN_ERR "capidrv-%d: got %s from controller 0x%x ???",
 855		       card->contrnr,
 856		       capi_cmd2str(cmsg->Command, cmsg->Subcommand),
 857		       cmsg->adr.adrController);
 858	}
 859	return;
 860
 861      ignored:
 862	printk(KERN_INFO "capidrv-%d: %s from controller 0x%x ignored\n",
 863	       card->contrnr,
 864	       capi_cmd2str(cmsg->Command, cmsg->Subcommand),
 865	       cmsg->adr.adrController);
 866}
 867
 868static void handle_incoming_call(capidrv_contr * card, _cmsg * cmsg)
 869{
 870	capidrv_plci *plcip;
 871	capidrv_bchan *bchan;
 872	isdn_ctrl cmd;
 873	int chan;
 874
 875	if ((chan = new_bchan(card)) == -1) {
 876		printk(KERN_ERR "capidrv-%d: incoming call on not existing bchan ?\n", card->contrnr);
 877		return;
 878	}
 879	bchan = &card->bchans[chan];
 880	if ((plcip = new_plci(card, chan)) == NULL) {
 881		printk(KERN_ERR "capidrv-%d: incoming call: no memory, sorry.\n", card->contrnr);
 882		return;
 883	}
 884	bchan->incoming = 1;
 885	plcip->plci = cmsg->adr.adrPLCI;
 886	plci_change_state(card, plcip, EV_PLCI_CONNECT_IND);
 887
 888	cmd.command = ISDN_STAT_ICALL;
 889	cmd.driver = card->myid;
 890	cmd.arg = chan;
 891	memset(&cmd.parm.setup, 0, sizeof(cmd.parm.setup));
 892	strncpy(cmd.parm.setup.phone,
 893	        cmsg->CallingPartyNumber + 3,
 894		cmsg->CallingPartyNumber[0] - 2);
 895	strncpy(cmd.parm.setup.eazmsn,
 896	        cmsg->CalledPartyNumber + 2,
 897		cmsg->CalledPartyNumber[0] - 1);
 898	cmd.parm.setup.si1 = cip2si1(cmsg->CIPValue);
 899	cmd.parm.setup.si2 = cip2si2(cmsg->CIPValue);
 900	cmd.parm.setup.plan = cmsg->CallingPartyNumber[1];
 901	cmd.parm.setup.screen = cmsg->CallingPartyNumber[2];
 902
 903	printk(KERN_INFO "capidrv-%d: incoming call %s,%d,%d,%s\n", 
 904			card->contrnr,
 905			cmd.parm.setup.phone,
 906			cmd.parm.setup.si1,
 907			cmd.parm.setup.si2,
 908			cmd.parm.setup.eazmsn);
 909
 910	if (cmd.parm.setup.si1 == 1 && cmd.parm.setup.si2 != 0) {
 911		printk(KERN_INFO "capidrv-%d: patching si2=%d to 0 for VBOX\n", 
 912			card->contrnr,
 913			cmd.parm.setup.si2);
 914		cmd.parm.setup.si2 = 0;
 915	}
 916
 917	switch (card->interface.statcallb(&cmd)) {
 918	case 0:
 919	case 3:
 920		/* No device matching this call.
 921		 * and isdn_common.c has send a HANGUP command
 922		 * which is ignored in state ST_PLCI_INCOMING,
 923		 * so we send RESP to ignore the call
 924		 */
 925		capi_cmsg_answer(cmsg);
 926		cmsg->Reject = 1;	/* ignore */
 927		plci_change_state(card, plcip, EV_PLCI_CONNECT_REJECT);
 928		send_message(card, cmsg);
 929		printk(KERN_INFO "capidrv-%d: incoming call %s,%d,%d,%s ignored\n",
 930			card->contrnr,
 931			cmd.parm.setup.phone,
 932			cmd.parm.setup.si1,
 933			cmd.parm.setup.si2,
 934			cmd.parm.setup.eazmsn);
 935		break;
 936	case 1:
 937		/* At least one device matching this call (RING on ttyI)
 938		 * HL-driver may send ALERTING on the D-channel in this
 939		 * case.
 940		 * really means: RING on ttyI or a net interface
 941		 * accepted this call already.
 942		 *
 943		 * If the call was accepted, state has already changed,
 944		 * and CONNECT_RESP already sent.
 945		 */
 946		if (plcip->state == ST_PLCI_INCOMING) {
 947			printk(KERN_INFO "capidrv-%d: incoming call %s,%d,%d,%s tty alerting\n",
 948				card->contrnr,
 949				cmd.parm.setup.phone,
 950				cmd.parm.setup.si1,
 951				cmd.parm.setup.si2,
 952				cmd.parm.setup.eazmsn);
 953			capi_fill_ALERT_REQ(cmsg,
 954					    global.ap.applid,
 955					    card->msgid++,
 956					    plcip->plci,	/* adr */
 957					    NULL,/* BChannelinformation */
 958					    NULL,/* Keypadfacility */
 959					    NULL,/* Useruserdata */
 960					    NULL /* Facilitydataarray */
 961			);
 962			plcip->msgid = cmsg->Messagenumber;
 963			send_message(card, cmsg);
 964		} else {
 965			printk(KERN_INFO "capidrv-%d: incoming call %s,%d,%d,%s on netdev\n",
 966				card->contrnr,
 967				cmd.parm.setup.phone,
 968				cmd.parm.setup.si1,
 969				cmd.parm.setup.si2,
 970				cmd.parm.setup.eazmsn);
 971		}
 972		break;
 973
 974	case 2:		/* Call will be rejected. */
 975		capi_cmsg_answer(cmsg);
 976		cmsg->Reject = 2;	/* reject call, normal call clearing */
 977		plci_change_state(card, plcip, EV_PLCI_CONNECT_REJECT);
 978		send_message(card, cmsg);
 979		break;
 980
 981	default:
 982		/* An error happened. (Invalid parameters for example.) */
 983		capi_cmsg_answer(cmsg);
 984		cmsg->Reject = 8;	/* reject call,
 985					   destination out of order */
 986		plci_change_state(card, plcip, EV_PLCI_CONNECT_REJECT);
 987		send_message(card, cmsg);
 988		break;
 989	}
 990	return;
 991}
 992
 993static void handle_plci(_cmsg * cmsg)
 994{
 995	capidrv_contr *card = findcontrbynumber(cmsg->adr.adrController & 0x7f);
 996	capidrv_plci *plcip;
 997	isdn_ctrl cmd;
 998	_cdebbuf *cdb;
 999
1000	if (!card) {
1001		printk(KERN_ERR "capidrv: %s from unknown controller 0x%x\n",
1002		       capi_cmd2str(cmsg->Command, cmsg->Subcommand),
1003		       cmsg->adr.adrController & 0x7f);
1004		return;
1005	}
1006	switch (CAPICMD(cmsg->Command, cmsg->Subcommand)) {
1007
1008	case CAPI_DISCONNECT_IND:	/* plci */
1009		if (cmsg->Reason) {
1010			printk(KERN_INFO "capidrv-%d: %s reason 0x%x (%s) for plci 0x%x\n",
1011			   card->contrnr,
1012			   capi_cmd2str(cmsg->Command, cmsg->Subcommand),
1013			       cmsg->Reason, capi_info2str(cmsg->Reason), cmsg->adr.adrPLCI);
1014		}
1015		if (!(plcip = find_plci_by_plci(card, cmsg->adr.adrPLCI))) {
1016			capi_cmsg_answer(cmsg);
1017			send_message(card, cmsg);
1018			goto notfound;
1019		}
1020		card->bchans[plcip->chan].disconnecting = 1;
1021		plci_change_state(card, plcip, EV_PLCI_DISCONNECT_IND);
1022		capi_cmsg_answer(cmsg);
1023		plci_change_state(card, plcip, EV_PLCI_DISCONNECT_RESP);
1024		send_message(card, cmsg);
1025		break;
1026
1027	case CAPI_DISCONNECT_CONF:	/* plci */
1028		if (cmsg->Info) {
1029			printk(KERN_INFO "capidrv-%d: %s info 0x%x (%s) for plci 0x%x\n",
1030			   card->contrnr,
1031			   capi_cmd2str(cmsg->Command, cmsg->Subcommand),
1032			       cmsg->Info, capi_info2str(cmsg->Info), 
1033			       cmsg->adr.adrPLCI);
1034		}
1035		if (!(plcip = find_plci_by_plci(card, cmsg->adr.adrPLCI)))
1036			goto notfound;
1037
1038		card->bchans[plcip->chan].disconnecting = 1;
1039		break;
1040
1041	case CAPI_ALERT_CONF:	/* plci */
1042		if (cmsg->Info) {
1043			printk(KERN_INFO "capidrv-%d: %s info 0x%x (%s) for plci 0x%x\n",
1044			   card->contrnr,
1045			   capi_cmd2str(cmsg->Command, cmsg->Subcommand),
1046			       cmsg->Info, capi_info2str(cmsg->Info), 
1047			       cmsg->adr.adrPLCI);
1048		}
1049		break;
1050
1051	case CAPI_CONNECT_IND:	/* plci */
1052		handle_incoming_call(card, cmsg);
1053		break;
1054
1055	case CAPI_CONNECT_CONF:	/* plci */
1056		if (cmsg->Info) {
1057			printk(KERN_INFO "capidrv-%d: %s info 0x%x (%s) for plci 0x%x\n",
1058			   card->contrnr,
1059			   capi_cmd2str(cmsg->Command, cmsg->Subcommand),
1060			       cmsg->Info, capi_info2str(cmsg->Info), 
1061			       cmsg->adr.adrPLCI);
1062		}
1063		if (!(plcip = find_plci_by_msgid(card, cmsg->Messagenumber)))
1064			goto notfound;
1065
1066		plcip->plci = cmsg->adr.adrPLCI;
1067		if (cmsg->Info) {
1068			plci_change_state(card, plcip, EV_PLCI_CONNECT_CONF_ERROR);
1069		} else {
1070			plci_change_state(card, plcip, EV_PLCI_CONNECT_CONF_OK);
1071		}
1072		break;
1073
1074	case CAPI_CONNECT_ACTIVE_IND:	/* plci */
1075
1076		if (!(plcip = find_plci_by_plci(card, cmsg->adr.adrPLCI)))
1077			goto notfound;
1078
1079		if (card->bchans[plcip->chan].incoming) {
1080			capi_cmsg_answer(cmsg);
1081			plci_change_state(card, plcip, EV_PLCI_CONNECT_ACTIVE_IND);
1082			send_message(card, cmsg);
1083		} else {
1084			capidrv_ncci *nccip;
1085			capi_cmsg_answer(cmsg);
1086			send_message(card, cmsg);
1087
1088			nccip = new_ncci(card, plcip, cmsg->adr.adrPLCI);
1089
1090			if (!nccip) {
1091				printk(KERN_ERR "capidrv-%d: no mem for ncci, sorry\n", card->contrnr);
1092				break;	/* $$$$ */
1093			}
1094			capi_fill_CONNECT_B3_REQ(cmsg,
1095						 global.ap.applid,
1096						 card->msgid++,
1097						 plcip->plci,	/* adr */
1098						 NULL	/* NCPI */
1099			);
1100			nccip->msgid = cmsg->Messagenumber;
1101			plci_change_state(card, plcip,
1102					  EV_PLCI_CONNECT_ACTIVE_IND);
1103			ncci_change_state(card, nccip, EV_NCCI_CONNECT_B3_REQ);
1104			send_message(card, cmsg);
1105			cmd.command = ISDN_STAT_DCONN;
1106			cmd.driver = card->myid;
1107			cmd.arg = plcip->chan;
1108			card->interface.statcallb(&cmd);
1109		}
1110		break;
1111
1112	case CAPI_INFO_IND:	/* Controller/plci */
1113
1114		if (!(plcip = find_plci_by_plci(card, cmsg->adr.adrPLCI)))
1115			goto notfound;
1116
1117		if (cmsg->InfoNumber == 0x4000) {
1118			if (cmsg->InfoElement[0] == 4) {
1119				cmd.command = ISDN_STAT_CINF;
1120				cmd.driver = card->myid;
1121				cmd.arg = plcip->chan;
1122				sprintf(cmd.parm.num, "%lu",
1123					(unsigned long)
1124					((u32) cmsg->InfoElement[1]
1125				  | ((u32) (cmsg->InfoElement[2]) << 8)
1126				 | ((u32) (cmsg->InfoElement[3]) << 16)
1127					 | ((u32) (cmsg->InfoElement[4]) << 24)));
1128				card->interface.statcallb(&cmd);
1129				break;
1130			}
1131		}
1132		cdb = capi_cmsg2str(cmsg);
1133		if (cdb) {
1134			printk(KERN_WARNING "capidrv-%d: %s\n",
1135				card->contrnr, cdb->buf);
1136			cdebbuf_free(cdb);
1137		} else
1138			printk(KERN_WARNING "capidrv-%d: CAPI_INFO_IND InfoNumber %x not handled\n",
1139				card->contrnr, cmsg->InfoNumber);
1140
1141		break;
1142
1143	case CAPI_CONNECT_ACTIVE_CONF:		/* plci */
1144		goto ignored;
1145	case CAPI_SELECT_B_PROTOCOL_CONF:	/* plci */
1146		goto ignored;
1147	case CAPI_FACILITY_IND:	/* Controller/plci/ncci */
1148		goto ignored;
1149	case CAPI_FACILITY_CONF:	/* Controller/plci/ncci */
1150		goto ignored;
1151
1152	case CAPI_INFO_CONF:	/* Controller/plci */
1153		goto ignored;
1154
1155	default:
1156		printk(KERN_ERR "capidrv-%d: got %s for plci 0x%x ???",
1157		       card->contrnr,
1158		       capi_cmd2str(cmsg->Command, cmsg->Subcommand),
1159		       cmsg->adr.adrPLCI);
1160	}
1161	return;
1162      ignored:
1163	printk(KERN_INFO "capidrv-%d: %s for plci 0x%x ignored\n",
1164	       card->contrnr,
1165	       capi_cmd2str(cmsg->Command, cmsg->Subcommand),
1166	       cmsg->adr.adrPLCI);
1167	return;
1168      notfound:
1169	printk(KERN_ERR "capidrv-%d: %s: plci 0x%x not found\n",
1170	       card->contrnr,
1171	       capi_cmd2str(cmsg->Command, cmsg->Subcommand),
1172	       cmsg->adr.adrPLCI);
1173	return;
1174}
1175
1176static void handle_ncci(_cmsg * cmsg)
1177{
1178	capidrv_contr *card = findcontrbynumber(cmsg->adr.adrController & 0x7f);
1179	capidrv_plci *plcip;
1180	capidrv_ncci *nccip;
1181	isdn_ctrl cmd;
1182	int len;
1183
1184	if (!card) {
1185		printk(KERN_ERR "capidrv: %s from unknown controller 0x%x\n",
1186		       capi_cmd2str(cmsg->Command, cmsg->Subcommand),
1187		       cmsg->adr.adrController & 0x7f);
1188		return;
1189	}
1190	switch (CAPICMD(cmsg->Command, cmsg->Subcommand)) {
1191
1192	case CAPI_CONNECT_B3_ACTIVE_IND:	/* ncci */
1193		if (!(nccip = find_ncci(card, cmsg->adr.adrNCCI)))
1194			goto notfound;
1195
1196		capi_cmsg_answer(cmsg);
1197		ncci_change_state(card, nccip, EV_NCCI_CONNECT_B3_ACTIVE_IND);
1198		send_message(card, cmsg);
1199
1200		cmd.command = ISDN_STAT_BCONN;
1201		cmd.driver = card->myid;
1202		cmd.arg = nccip->chan;
1203		card->interface.statcallb(&cmd);
1204
1205		printk(KERN_INFO "capidrv-%d: chan %d up with ncci 0x%x\n",
1206		       card->contrnr, nccip->chan, nccip->ncci);
1207		break;
1208
1209	case CAPI_CONNECT_B3_ACTIVE_CONF:	/* ncci */
1210		goto ignored;
1211
1212	case CAPI_CONNECT_B3_IND:	/* ncci */
1213
1214		plcip = find_plci_by_ncci(card, cmsg->adr.adrNCCI);
1215		if (plcip) {
1216			nccip = new_ncci(card, plcip, cmsg->adr.adrNCCI);
1217			if (nccip) {
1218				ncci_change_state(card, nccip, EV_NCCI_CONNECT_B3_IND);
1219				capi_fill_CONNECT_B3_RESP(cmsg,
1220							  global.ap.applid,
1221							  card->msgid++,
1222							  nccip->ncci,	/* adr */
1223							  0,	/* Reject */
1224							  NULL	/* NCPI */
1225				);
1226				ncci_change_state(card, nccip, EV_NCCI_CONNECT_B3_RESP);
1227				send_message(card, cmsg);
1228				break;
1229			}
1230			printk(KERN_ERR "capidrv-%d: no mem for ncci, sorry\n",							card->contrnr);
1231		} else {
1232			printk(KERN_ERR "capidrv-%d: %s: plci for ncci 0x%x not found\n",
1233			   card->contrnr,
1234			   capi_cmd2str(cmsg->Command, cmsg->Subcommand),
1235			       cmsg->adr.adrNCCI);
1236		}
1237		capi_fill_CONNECT_B3_RESP(cmsg,
1238					  global.ap.applid,
1239					  card->msgid++,
1240					  cmsg->adr.adrNCCI,
1241					  2,	/* Reject */
1242					  NULL	/* NCPI */
1243		);
1244		send_message(card, cmsg);
1245		break;
1246
1247	case CAPI_CONNECT_B3_CONF:	/* ncci */
1248
1249		if (!(nccip = find_ncci_by_msgid(card,
1250						 cmsg->adr.adrNCCI,
1251						 cmsg->Messagenumber)))
1252			goto notfound;
1253
1254		nccip->ncci = cmsg->adr.adrNCCI;
1255		if (cmsg->Info) {
1256			printk(KERN_INFO "capidrv-%d: %s info 0x%x (%s) for ncci 0x%x\n",
1257			   card->contrnr,
1258			   capi_cmd2str(cmsg->Command, cmsg->Subcommand),
1259			       cmsg->Info, capi_info2str(cmsg->Info), 
1260			       cmsg->adr.adrNCCI);
1261		}
1262
1263		if (cmsg->Info)
1264			ncci_change_state(card, nccip, EV_NCCI_CONNECT_B3_CONF_ERROR);
1265		else
1266			ncci_change_state(card, nccip, EV_NCCI_CONNECT_B3_CONF_OK);
1267		break;
1268
1269	case CAPI_CONNECT_B3_T90_ACTIVE_IND:	/* ncci */
1270		capi_cmsg_answer(cmsg);
1271		send_message(card, cmsg);
1272		break;
1273
1274	case CAPI_DATA_B3_IND:	/* ncci */
1275		/* handled in handle_data() */
1276		goto ignored;
1277
1278	case CAPI_DATA_B3_CONF:	/* ncci */
1279		if (cmsg->Info) {
1280			printk(KERN_WARNING "CAPI_DATA_B3_CONF: Info %x - %s\n",
1281				cmsg->Info, capi_info2str(cmsg->Info));
1282		}
1283		if (!(nccip = find_ncci(card, cmsg->adr.adrNCCI)))
1284			goto notfound;
1285
1286		len = capidrv_del_ack(nccip, cmsg->DataHandle);
1287		if (len < 0)
1288			break;
1289	        cmd.command = ISDN_STAT_BSENT;
1290	        cmd.driver = card->myid;
1291	        cmd.arg = nccip->chan;
1292		cmd.parm.length = len;
1293	        card->interface.statcallb(&cmd);
1294		break;
1295
1296	case CAPI_DISCONNECT_B3_IND:	/* ncci */
1297		if (!(nccip = find_ncci(card, cmsg->adr.adrNCCI)))
1298			goto notfound;
1299
1300		card->bchans[nccip->chan].disconnecting = 1;
1301		ncci_change_state(card, nccip, EV_NCCI_DISCONNECT_B3_IND);
1302		capi_cmsg_answer(cmsg);
1303		ncci_change_state(card, nccip, EV_NCCI_DISCONNECT_B3_RESP);
1304		send_message(card, cmsg);
1305		break;
1306
1307	case CAPI_DISCONNECT_B3_CONF:	/* ncci */
1308		if (!(nccip = find_ncci(card, cmsg->adr.adrNCCI)))
1309			goto notfound;
1310		if (cmsg->Info) {
1311			printk(KERN_INFO "capidrv-%d: %s info 0x%x (%s) for ncci 0x%x\n",
1312			   card->contrnr,
1313			   capi_cmd2str(cmsg->Command, cmsg->Subcommand),
1314			       cmsg->Info, capi_info2str(cmsg->Info), 
1315			       cmsg->adr.adrNCCI);
1316			ncci_change_state(card, nccip, EV_NCCI_DISCONNECT_B3_CONF_ERROR);
1317		}
1318		break;
1319
1320	case CAPI_RESET_B3_IND:	/* ncci */
1321		if (!(nccip = find_ncci(card, cmsg->adr.adrNCCI)))
1322			goto notfound;
1323		ncci_change_state(card, nccip, EV_NCCI_RESET_B3_IND);
1324		capi_cmsg_answer(cmsg);
1325		send_message(card, cmsg);
1326		break;
1327
1328	case CAPI_RESET_B3_CONF:	/* ncci */
1329		goto ignored;	/* $$$$ */
1330
1331	case CAPI_FACILITY_IND:	/* Controller/plci/ncci */
1332		goto ignored;
1333	case CAPI_FACILITY_CONF:	/* Controller/plci/ncci */
1334		goto ignored;
1335
1336	default:
1337		printk(KERN_ERR "capidrv-%d: got %s for ncci 0x%x ???",
1338		       card->contrnr,
1339		       capi_cmd2str(cmsg->Command, cmsg->Subcommand),
1340		       cmsg->adr.adrNCCI);
1341	}
1342	return;
1343      ignored:
1344	printk(KERN_INFO "capidrv-%d: %s for ncci 0x%x ignored\n",
1345	       card->contrnr,
1346	       capi_cmd2str(cmsg->Command, cmsg->Subcommand),
1347	       cmsg->adr.adrNCCI);
1348	return;
1349      notfound:
1350	printk(KERN_ERR "capidrv-%d: %s: ncci 0x%x not found\n",
1351	       card->contrnr,
1352	       capi_cmd2str(cmsg->Command, cmsg->Subcommand),
1353	       cmsg->adr.adrNCCI);
1354}
1355
1356
1357static void handle_data(_cmsg * cmsg, struct sk_buff *skb)
1358{
1359	capidrv_contr *card = findcontrbynumber(cmsg->adr.adrController & 0x7f);
1360	capidrv_ncci *nccip;
1361
1362	if (!card) {
1363		printk(KERN_ERR "capidrv: %s from unknown controller 0x%x\n",
1364		       capi_cmd2str(cmsg->Command, cmsg->Subcommand),
1365		       cmsg->adr.adrController & 0x7f);
1366		kfree_skb(skb);
1367		return;
1368	}
1369	if (!(nccip = find_ncci(card, cmsg->adr.adrNCCI))) {
1370		printk(KERN_ERR "capidrv-%d: %s: ncci 0x%x not found\n",
1371		       card->contrnr,
1372		       capi_cmd2str(cmsg->Command, cmsg->Subcommand),
1373		       cmsg->adr.adrNCCI);
1374		kfree_skb(skb);
1375		return;
1376	}
1377	(void) skb_pull(skb, CAPIMSG_LEN(skb->data));
1378	card->interface.rcvcallb_skb(card->myid, nccip->chan, skb);
1379	capi_cmsg_answer(cmsg);
1380	send_message(card, cmsg);
1381}
1382
1383static _cmsg s_cmsg;
1384
1385static void capidrv_recv_message(struct capi20_appl *ap, struct sk_buff *skb)
1386{
1387	capi_message2cmsg(&s_cmsg, skb->data);
1388	if (debugmode > 3) {
1389		_cdebbuf *cdb = capi_cmsg2str(&s_cmsg);
1390
1391		if (cdb) {
1392			printk(KERN_DEBUG "%s: applid=%d %s\n", __func__,
1393				ap->applid, cdb->buf);
1394			cdebbuf_free(cdb);
1395		} else
1396			printk(KERN_DEBUG "%s: applid=%d %s not traced\n",
1397				__func__, ap->applid,
1398				capi_cmd2str(s_cmsg.Command, s_cmsg.Subcommand));
1399	}
1400	if (s_cmsg.Command == CAPI_DATA_B3
1401	    && s_cmsg.Subcommand == CAPI_IND) {
1402		handle_data(&s_cmsg, skb);
1403		return;
1404	}
1405	if ((s_cmsg.adr.adrController & 0xffffff00) == 0)
1406		handle_controller(&s_cmsg);
1407	else if ((s_cmsg.adr.adrPLCI & 0xffff0000) == 0)
1408		handle_plci(&s_cmsg);
1409	else
1410		handle_ncci(&s_cmsg);
1411	/*
1412	 * data of skb used in s_cmsg,
1413	 * free data when s_cmsg is not used again
1414	 * thanks to Lars Heete <hel@admin.de>
1415	 */
1416	kfree_skb(skb);
1417}
1418
1419/* ------------------------------------------------------------------- */
1420
1421#define PUTBYTE_TO_STATUS(card, byte) \
1422	do { \
1423		*(card)->q931_write++ = (byte); \
1424        	if ((card)->q931_write > (card)->q931_end) \
1425	  		(card)->q931_write = (card)->q931_buf; \
1426	} while (0)
1427
1428static void handle_dtrace_data(capidrv_contr *card,
1429			     int send, int level2, u8 *data, u16 len)
1430{
1431    	u8 *p, *end;
1432    	isdn_ctrl cmd;
1433
1434    	if (!len) {
1435		printk(KERN_DEBUG "capidrv-%d: avmb1_q931_data: len == %d\n",
1436				card->contrnr, len);
1437		return;
1438	}
1439
1440	if (level2) {
1441		PUTBYTE_TO_STATUS(card, 'D');
1442		PUTBYTE_TO_STATUS(card, '2');
1443        	PUTBYTE_TO_STATUS(card, send ? '>' : '<');
1444        	PUTBYTE_TO_STATUS(card, ':');
1445	} else {
1446        	PUTBYTE_TO_STATUS(card, 'D');
1447        	PUTBYTE_TO_STATUS(card, '3');
1448        	PUTBYTE_TO_STATUS(card, send ? '>' : '<');
1449        	PUTBYTE_TO_STATUS(card, ':');
1450    	}
1451
1452	for (p = data, end = data+len; p < end; p++) {
1453		PUTBYTE_TO_STATUS(card, ' ');
1454		PUTBYTE_TO_STATUS(card, hex_asc_hi(*p));
1455		PUTBYTE_TO_STATUS(card, hex_asc_lo(*p));
1456	}
1457	PUTBYTE_TO_STATUS(card, '\n');
1458
1459	cmd.command = ISDN_STAT_STAVAIL;
1460	cmd.driver = card->myid;
1461	cmd.arg = len*3+5;
1462	card->interface.statcallb(&cmd);
1463}
1464
1465/* ------------------------------------------------------------------- */
1466
1467static _cmsg cmdcmsg;
1468
1469static int capidrv_ioctl(isdn_ctrl * c, capidrv_contr * card)
1470{
1471	switch (c->arg) {
1472	case 1:
1473		debugmode = (int)(*((unsigned int *)c->parm.num));
1474		printk(KERN_DEBUG "capidrv-%d: debugmode=%d\n",
1475				card->contrnr, debugmode);
1476		return 0;
1477	default:
1478		printk(KERN_DEBUG "capidrv-%d: capidrv_ioctl(%ld) called ??\n",
1479				card->contrnr, c->arg);
1480		return -EINVAL;
1481	}
1482	return -EINVAL;
1483}
1484
1485/*
1486 * Handle leased lines (CAPI-Bundling)
1487 */
1488
1489struct internal_bchannelinfo {
1490   unsigned short channelalloc;
1491   unsigned short operation;
1492   unsigned char  cmask[31];
1493};
1494
1495static int decodeFVteln(char *teln, unsigned long *bmaskp, int *activep)
1496{
1497	unsigned long bmask = 0;
1498	int active = !0;
1499	char *s;
1500	int i;
1501
1502	if (strncmp(teln, "FV:", 3) != 0)
1503		return 1;
1504	s = teln + 3;
1505	while (*s && *s == ' ') s++;
1506	if (!*s) return -2;
1507	if (*s == 'p' || *s == 'P') {
1508		active = 0;
1509		s++;
1510	}
1511	if (*s == 'a' || *s == 'A') {
1512		active = !0;
1513		s++;
1514	}
1515	while (*s) {
1516		int digit1 = 0;
1517		int digit2 = 0;
1518		char *endp;
1519
1520		digit1 = simple_strtoul(s, &endp, 10);
1521		if (s == endp)
1522			return -3;
1523		s = endp;
1524
1525		if (digit1 <= 0 || digit1 > 30) return -4;
1526		if (*s == 0 || *s == ',' || *s == ' ') {
1527			bmask |= (1 << digit1);
1528			digit1 = 0;
1529			if (*s) s++;
1530			continue;
1531		}
1532		if (*s != '-') return -5;
1533		s++;
1534
1535		digit2 = simple_strtoul(s, &endp, 10);
1536		if (s == endp)
1537			return -3;
1538		s = endp;
1539
1540		if (digit2 <= 0 || digit2 > 30) return -4;
1541		if (*s == 0 || *s == ',' || *s == ' ') {
1542			if (digit1 > digit2)
1543				for (i = digit2; i <= digit1 ; i++)
1544					bmask |= (1 << i);
1545			else 
1546				for (i = digit1; i <= digit2 ; i++)
1547					bmask |= (1 << i);
1548			digit1 = digit2 = 0;
1549			if (*s) s++;
1550			continue;
1551		}
1552		return -6;
1553	}
1554	if (activep) *activep = active;
1555	if (bmaskp) *bmaskp = bmask;
1556	return 0;
1557}
1558
1559static int FVteln2capi20(char *teln, u8 AdditionalInfo[1+2+2+31])
1560{
1561	unsigned long bmask;
1562	int active;
1563	int rc, i;
1564   
1565	rc = decodeFVteln(teln, &bmask, &active);
1566	if (rc) return rc;
1567	/* Length */
1568	AdditionalInfo[0] = 2+2+31;
1569        /* Channel: 3 => use channel allocation */
1570        AdditionalInfo[1] = 3; AdditionalInfo[2] = 0;
1571	/* Operation: 0 => DTE mode, 1 => DCE mode */
1572        if (active) {
1573   		AdditionalInfo[3] = 0; AdditionalInfo[4] = 0;
1574   	} else {
1575   		AdditionalInfo[3] = 1; AdditionalInfo[4] = 0;
1576	}
1577	/* Channel mask array */
1578	AdditionalInfo[5] = 0; /* no D-Channel */
1579	for (i=1; i <= 30; i++)
1580		AdditionalInfo[5+i] = (bmask & (1 << i)) ? 0xff : 0;
1581	return 0;
1582}
1583
1584static int capidrv_command(isdn_ctrl * c, capidrv_contr * card)
1585{
1586	isdn_ctrl cmd;
1587	struct capidrv_bchan *bchan;
1588	struct capidrv_plci *plcip;
1589	u8 AdditionalInfo[1+2+2+31];
1590        int rc, isleasedline = 0;
1591
1592	if (c->command == ISDN_CMD_IOCTL)
1593		return capidrv_ioctl(c, card);
1594
1595	switch (c->command) {
1596	case ISDN_CMD_DIAL:{
1597			u8 calling[ISDN_MSNLEN + 3];
1598			u8 called[ISDN_MSNLEN + 2];
1599
1600			if (debugmode)
1601				printk(KERN_DEBUG "capidrv-%d: ISDN_CMD_DIAL(ch=%ld,\"%s,%d,%d,%s\")\n",
1602					card->contrnr,
1603					c->arg,
1604				        c->parm.setup.phone,
1605				        c->parm.setup.si1,
1606				        c->parm.setup.si2,
1607				        c->parm.setup.eazmsn);
1608
1609			bchan = &card->bchans[c->arg % card->nbchan];
1610
1611			if (bchan->plcip) {
1612				printk(KERN_ERR "capidrv-%d: dail ch=%ld,\"%s,%d,%d,%s\" in use (plci=0x%x)\n",
1613					card->contrnr,
1614			        	c->arg, 
1615				        c->parm.setup.phone,
1616				        c->parm.setup.si1,
1617				        c->parm.setup.si2,
1618				        c->parm.setup.eazmsn,
1619				        bchan->plcip->plci);
1620				return 0;
1621			}
1622			bchan->si1 = c->parm.setup.si1;
1623			bchan->si2 = c->parm.setup.si2;
1624
1625			strncpy(bchan->num, c->parm.setup.phone, sizeof(bchan->num));
1626			strncpy(bchan->mynum, c->parm.setup.eazmsn, sizeof(bchan->mynum));
1627                        rc = FVteln2capi20(bchan->num, AdditionalInfo);
1628			isleasedline = (rc == 0);
1629			if (rc < 0)
1630				printk(KERN_ERR "capidrv-%d: WARNING: invalid leased linedefinition \"%s\"\n", card->contrnr, bchan->num);
1631
1632			if (isleasedline) {
1633				calling[0] = 0;
1634				called[0] = 0;
1635			        if (debugmode)
1636					printk(KERN_DEBUG "capidrv-%d: connecting leased line\n", card->contrnr);
1637			} else {
1638		        	calling[0] = strlen(bchan->mynum) + 2;
1639		        	calling[1] = 0;
1640		     		calling[2] = 0x80;
1641			   	strncpy(calling + 3, bchan->mynum, ISDN_MSNLEN);
1642				called[0] = strlen(bchan->num) + 1;
1643				called[1] = 0x80;
1644				strncpy(called + 2, bchan->num, ISDN_MSNLEN);
1645			}
1646
1647			capi_fill_CONNECT_REQ(&cmdcmsg,
1648					      global.ap.applid,
1649					      card->msgid++,
1650					      card->contrnr,	/* adr */
1651					  si2cip(bchan->si1, bchan->si2),	/* cipvalue */
1652					      called,	/* CalledPartyNumber */
1653					      calling,	/* CallingPartyNumber */
1654					      NULL,	/* CalledPartySubaddress */
1655					      NULL,	/* CallingPartySubaddress */
1656					    b1prot(bchan->l2, bchan->l3),	/* B1protocol */
1657					    b2prot(bchan->l2, bchan->l3),	/* B2protocol */
1658					    b3prot(bchan->l2, bchan->l3),	/* B3protocol */
1659					    b1config(bchan->l2, bchan->l3),	/* B1configuration */
1660					      NULL,	/* B2configuration */
1661					      NULL,	/* B3configuration */
1662					      NULL,	/* BC */
1663					      NULL,	/* LLC */
1664					      NULL,	/* HLC */
1665					      /* BChannelinformation */
1666					      isleasedline ? AdditionalInfo : NULL,
1667					      NULL,	/* Keypadfacility */
1668					      NULL,	/* Useruserdata */
1669					      NULL	/* Facilitydataarray */
1670			    );
1671			if ((plcip = new_plci(card, (c->arg % card->nbchan))) == NULL) {
1672				cmd.command = ISDN_STAT_DHUP;
1673				cmd.driver = card->myid;
1674				cmd.arg = (c->arg % card->nbchan);
1675				card->interface.statcallb(&cmd);
1676				return -1;
1677			}
1678			plcip->msgid = cmdcmsg.Messagenumber;
1679			plcip->leasedline = isleasedline;
1680			plci_change_state(card, plcip, EV_PLCI_CONNECT_REQ);
1681			send_message(card, &cmdcmsg);
1682			return 0;
1683		}
1684
1685	case ISDN_CMD_ACCEPTD:
1686
1687		bchan = &card->bchans[c->arg % card->nbchan];
1688		if (debugmode)
1689			printk(KERN_DEBUG "capidrv-%d: ISDN_CMD_ACCEPTD(ch=%ld) l2=%d l3=%d\n",
1690			       card->contrnr,
1691			       c->arg, bchan->l2, bchan->l3);
1692
1693		capi_fill_CONNECT_RESP(&cmdcmsg,
1694				       global.ap.applid,
1695				       card->msgid++,
1696				       bchan->plcip->plci,	/* adr */
1697				       0,	/* Reject */
1698				       b1prot(bchan->l2, bchan->l3),	/* B1protocol */
1699				       b2prot(bchan->l2, bchan->l3),	/* B2protocol */
1700				       b3prot(bchan->l2, bchan->l3),	/* B3protocol */
1701				       b1config(bchan->l2, bchan->l3),	/* B1configuration */
1702				       NULL,	/* B2configuration */
1703				       NULL,	/* B3configuration */
1704				       NULL,	/* ConnectedNumber */
1705				       NULL,	/* ConnectedSubaddress */
1706				       NULL,	/* LLC */
1707				       NULL,	/* BChannelinformation */
1708				       NULL,	/* Keypadfacility */
1709				       NULL,	/* Useruserdata */
1710				       NULL	/* Facilitydataarray */
1711		);
1712		capi_cmsg2message(&cmdcmsg, cmdcmsg.buf);
1713		plci_change_state(card, bchan->plcip, EV_PLCI_CONNECT_RESP);
1714		send_message(card, &cmdcmsg);
1715		return 0;
1716
1717	case ISDN_CMD_ACCEPTB:
1718		if (debugmode)
1719			printk(KERN_DEBUG "capidrv-%d: ISDN_CMD_ACCEPTB(ch=%ld)\n",
1720			       card->contrnr,
1721			       c->arg);
1722		return -ENOSYS;
1723
1724	case ISDN_CMD_HANGUP:
1725		if (debugmode)
1726			printk(KERN_DEBUG "capidrv-%d: ISDN_CMD_HANGUP(ch=%ld)\n",
1727			       card->contrnr,
1728			       c->arg);
1729		bchan = &card->bchans[c->arg % card->nbchan];
1730
1731		if (bchan->disconnecting) {
1732			if (debugmode)
1733				printk(KERN_DEBUG "capidrv-%d: chan %ld already disconnecting ...\n",
1734				       card->contrnr,
1735				       c->arg);
1736			return 0;
1737		}
1738		if (bchan->nccip) {
1739			bchan->disconnecting = 1;
1740			capi_fill_DISCONNECT_B3_REQ(&cmdcmsg,
1741						    global.ap.applid,
1742						    card->msgid++,
1743						    bchan->nccip->ncci,
1744						    NULL	/* NCPI */
1745			);
1746			ncci_change_state(card, bchan->nccip, EV_NCCI_DISCONNECT_B3_REQ);
1747			send_message(card, &cmdcmsg);
1748			return 0;
1749		} else if (bchan->plcip) {
1750			if (bchan->plcip->state == ST_PLCI_INCOMING) {
1751				/*
1752				 * just ignore, we a called from
1753				 * isdn_status_callback(),
1754				 * which will return 0 or 2, this is handled
1755				 * by the CONNECT_IND handler
1756				 */
1757				bchan->disconnecting = 1;
1758				return 0;
1759			} else if (bchan->plcip->plci) {
1760				bchan->disconnecting = 1;
1761				capi_fill_DISCONNECT_REQ(&cmdcmsg,
1762							 global.ap.applid,
1763							 card->msgid++,
1764						      bchan->plcip->plci,
1765							 NULL,	/* BChannelinformation */
1766							 NULL,	/* Keypadfacility */
1767							 NULL,	/* Useruserdata */
1768							 NULL	/* Facilitydataarray */
1769				);
1770				plci_change_state(card, bchan->plcip, EV_PLCI_DISCONNECT_REQ);
1771				send_message(card, &cmdcmsg);
1772				return 0;
1773			} else {
1774				printk(KERN_ERR "capidrv-%d: chan %ld disconnect request while waiting for CONNECT_CONF\n",
1775				       card->contrnr,
1776				       c->arg);
1777				return -EINVAL;
1778			}
1779		}
1780		printk(KERN_ERR "capidrv-%d: chan %ld disconnect request on free channel\n",
1781				       card->contrnr,
1782				       c->arg);
1783		return -EINVAL;
1784/* ready */
1785
1786	case ISDN_CMD_SETL2:
1787		if (debugmode)
1788			printk(KERN_DEBUG "capidrv-%d: set L2 on chan %ld to %ld\n",
1789			       card->contrnr,
1790			       (c->arg & 0xff), (c->arg >> 8));
1791		bchan = &card->bchans[(c->arg & 0xff) % card->nbchan];
1792		bchan->l2 = (c->arg >> 8);
1793		return 0;
1794
1795	case ISDN_CMD_SETL3:
1796		if (debugmode)
1797			printk(KERN_DEBUG "capidrv-%d: set L3 on chan %ld to %ld\n",
1798			       card->contrnr,
1799			       (c->arg & 0xff), (c->arg >> 8));
1800		bchan = &card->bchans[(c->arg & 0xff) % card->nbchan];
1801		bchan->l3 = (c->arg >> 8);
1802		return 0;
1803
1804	case ISDN_CMD_SETEAZ:
1805		if (debugmode)
1806			printk(KERN_DEBUG "capidrv-%d: set EAZ \"%s\" on chan %ld\n",
1807			       card->contrnr,
1808			       c->parm.num, c->arg);
1809		bchan = &card->bchans[c->arg % card->nbchan];
1810		strncpy(bchan->msn, c->parm.num, ISDN_MSNLEN);
1811		return 0;
1812
1813	case ISDN_CMD_CLREAZ:
1814		if (deb

Large files files are truncated, but you can click here to view the full file