/drivers/isdn/capi/capidrv.c
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