1/* $Id: isdnloop.c,v 1.11.6.7 2001/11/11 19:54:31 kai Exp $ 2 * 3 * ISDN low-level module implementing a dummy loop driver. 4 * 5 * Copyright 1997 by Fritz Elfert (fritz@isdn4linux.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/interrupt.h> 14#include <linux/slab.h> 15#include <linux/init.h> 16#include <linux/sched.h> 17#include "isdnloop.h" 18 19static char *isdnloop_id = "loop0"; 20 21MODULE_DESCRIPTION("ISDN4Linux: Pseudo Driver that simulates an ISDN card"); 22MODULE_AUTHOR("Fritz Elfert"); 23MODULE_LICENSE("GPL"); 24module_param(isdnloop_id, charp, 0); 25MODULE_PARM_DESC(isdnloop_id, "ID-String of first card"); 26 27static int isdnloop_addcard(char *); 28 29/* 30 * Free queue completely. 31 * 32 * Parameter: 33 * card = pointer to card struct 34 * channel = channel number 35 */ 36static void 37isdnloop_free_queue(isdnloop_card *card, int channel) 38{ 39 struct sk_buff_head *queue = &card->bqueue[channel]; 40 41 skb_queue_purge(queue); 42 card->sndcount[channel] = 0; 43} 44 45/* 46 * Send B-Channel data to another virtual card. 47 * This routine is called via timer-callback from isdnloop_pollbchan(). 48 * 49 * Parameter: 50 * card = pointer to card struct. 51 * ch = channel number (0-based) 52 */ 53static void 54isdnloop_bchan_send(isdnloop_card *card, int ch) 55{ 56 isdnloop_card *rcard = card->rcard[ch]; 57 int rch = card->rch[ch], len, ack; 58 struct sk_buff *skb; 59 isdn_ctrl cmd; 60 61 while (card->sndcount[ch]) { 62 skb = skb_dequeue(&card->bqueue[ch]); 63 if (skb) { 64 len = skb->len; 65 card->sndcount[ch] -= len; 66 ack = *(skb->head); /* used as scratch area */ 67 cmd.driver = card->myid; 68 cmd.arg = ch; 69 if (rcard) { 70 rcard->interface.rcvcallb_skb(rcard->myid, rch, skb); 71 } else { 72 printk(KERN_WARNING "isdnloop: no rcard, skb dropped\n"); 73 dev_kfree_skb(skb); 74 75 }; 76 cmd.command = ISDN_STAT_BSENT; 77 cmd.parm.length = len; 78 card->interface.statcallb(&cmd); 79 } else 80 card->sndcount[ch] = 0; 81 } 82} 83 84/* 85 * Send/Receive Data to/from the B-Channel. 86 * This routine is called via timer-callback. 87 * It schedules itself while any B-Channel is open. 88 * 89 * Parameter: 90 * data = pointer to card struct, set by kernel timer.data 91 */ 92static void 93isdnloop_pollbchan(unsigned long data) 94{ 95 isdnloop_card *card = (isdnloop_card *) data; 96 unsigned long flags; 97 98 if (card->flags & ISDNLOOP_FLAGS_B1ACTIVE) 99 isdnloop_bchan_send(card, 0); 100 if (card->flags & ISDNLOOP_FLAGS_B2ACTIVE) 101 isdnloop_bchan_send(card, 1); 102 if (card->flags & (ISDNLOOP_FLAGS_B1ACTIVE | ISDNLOOP_FLAGS_B2ACTIVE)) { 103 /* schedule b-channel polling again */ 104 spin_lock_irqsave(&card->isdnloop_lock, flags); 105 card->rb_timer.expires = jiffies + ISDNLOOP_TIMER_BCREAD; 106 add_timer(&card->rb_timer); 107 card->flags |= ISDNLOOP_FLAGS_RBTIMER; 108 spin_unlock_irqrestore(&card->isdnloop_lock, flags); 109 } else 110 card->flags &= ~ISDNLOOP_FLAGS_RBTIMER; 111} 112 113/* 114 * Parse ICN-type setup string and fill fields of setup-struct 115 * with parsed data. 116 * 117 * Parameter: 118 * setup = setup string, format: [caller-id],si1,si2,[called-id] 119 * cmd = pointer to struct to be filled. 120 */ 121static void 122isdnloop_parse_setup(char *setup, isdn_ctrl *cmd) 123{ 124 char *t = setup; 125 char *s = strchr(t, ','); 126 127 *s++ = '\0'; 128 strlcpy(cmd->parm.setup.phone, t, sizeof(cmd->parm.setup.phone)); 129 s = strchr(t = s, ','); 130 *s++ = '\0'; 131 if (!strlen(t)) 132 cmd->parm.setup.si1 = 0; 133 else 134 cmd->parm.setup.si1 = simple_strtoul(t, NULL, 10); 135 s = strchr(t = s, ','); 136 *s++ = '\0'; 137 if (!strlen(t)) 138 cmd->parm.setup.si2 = 0; 139 else 140 cmd->parm.setup.si2 = 141 simple_strtoul(t, NULL, 10); 142 strlcpy(cmd->parm.setup.eazmsn, s, sizeof(cmd->parm.setup.eazmsn)); 143 cmd->parm.setup.plan = 0; 144 cmd->parm.setup.screen = 0; 145} 146 147typedef struct isdnloop_stat { 148 char *statstr; 149 int command; 150 int action; 151} isdnloop_stat; 152/* *INDENT-OFF* */ 153static isdnloop_stat isdnloop_stat_table[] = { 154 {"BCON_", ISDN_STAT_BCONN, 1}, /* B-Channel connected */ 155 {"BDIS_", ISDN_STAT_BHUP, 2}, /* B-Channel disconnected */ 156 {"DCON_", ISDN_STAT_DCONN, 0}, /* D-Channel connected */ 157 {"DDIS_", ISDN_STAT_DHUP, 0}, /* D-Channel disconnected */ 158 {"DCAL_I", ISDN_STAT_ICALL, 3}, /* Incoming call dialup-line */ 159 {"DSCA_I", ISDN_STAT_ICALL, 3}, /* Incoming call 1TR6-SPV */ 160 {"FCALL", ISDN_STAT_ICALL, 4}, /* Leased line connection up */ 161 {"CIF", ISDN_STAT_CINF, 5}, /* Charge-info, 1TR6-type */ 162 {"AOC", ISDN_STAT_CINF, 6}, /* Charge-info, DSS1-type */ 163 {"CAU", ISDN_STAT_CAUSE, 7}, /* Cause code */ 164 {"TEI OK", ISDN_STAT_RUN, 0}, /* Card connected to wallplug */ 165 {"E_L1: ACT FAIL", ISDN_STAT_BHUP, 8}, /* Layer-1 activation failed */ 166 {"E_L2: DATA LIN", ISDN_STAT_BHUP, 8}, /* Layer-2 data link lost */ 167 {"E_L1: ACTIVATION FAILED", 168 ISDN_STAT_BHUP, 8}, /* Layer-1 activation failed */ 169 {NULL, 0, -1} 170}; 171/* *INDENT-ON* */ 172 173 174/* 175 * Parse Status message-strings from virtual card. 176 * Depending on status, call statcallb for sending messages to upper 177 * levels. Also set/reset B-Channel active-flags. 178 * 179 * Parameter: 180 * status = status string to parse. 181 * channel = channel where message comes from. 182 * card = card where message comes from. 183 */ 184static void 185isdnloop_parse_status(u_char *status, int channel, isdnloop_card *card) 186{ 187 isdnloop_stat *s = isdnloop_stat_table; 188 int action = -1; 189 isdn_ctrl cmd; 190 191 while (s->statstr) { 192 if (!strncmp(status, s->statstr, strlen(s->statstr))) { 193 cmd.command = s->command; 194 action = s->action; 195 break; 196 } 197 s++; 198 } 199 if (action == -1) 200 return; 201 cmd.driver = card->myid; 202 cmd.arg = channel; 203 switch (action) { 204 case 1: 205 /* BCON_x */ 206 card->flags |= (channel) ? 207 ISDNLOOP_FLAGS_B2ACTIVE : ISDNLOOP_FLAGS_B1ACTIVE; 208 break; 209 case 2: 210 /* BDIS_x */ 211 card->flags &= ~((channel) ? 212 ISDNLOOP_FLAGS_B2ACTIVE : ISDNLOOP_FLAGS_B1ACTIVE); 213 isdnloop_free_queue(card, channel); 214 break; 215 case 3: 216 /* DCAL_I and DSCA_I */ 217 isdnloop_parse_setup(status + 6, &cmd); 218 break; 219 case 4: 220 /* FCALL */ 221 sprintf(cmd.parm.setup.phone, "LEASED%d", card->myid); 222 sprintf(cmd.parm.setup.eazmsn, "%d", channel + 1); 223 cmd.parm.setup.si1 = 7; 224 cmd.parm.setup.si2 = 0; 225 cmd.parm.setup.plan = 0; 226 cmd.parm.setup.screen = 0; 227 break; 228 case 5: 229 /* CIF */ 230 strlcpy(cmd.parm.num, status + 3, sizeof(cmd.parm.num)); 231 break; 232 case 6: 233 /* AOC */ 234 snprintf(cmd.parm.num, sizeof(cmd.parm.num), "%d", 235 (int) simple_strtoul(status + 7, NULL, 16)); 236 break; 237 case 7: 238 /* CAU */ 239 status += 3; 240 if (strlen(status) == 4) 241 snprintf(cmd.parm.num, sizeof(cmd.parm.num), "%s%c%c", 242 status + 2, *status, *(status + 1)); 243 else 244 strlcpy(cmd.parm.num, status + 1, sizeof(cmd.parm.num)); 245 break; 246 case 8: 247 /* Misc Errors on L1 and L2 */ 248 card->flags &= ~ISDNLOOP_FLAGS_B1ACTIVE; 249 isdnloop_free_queue(card, 0); 250 cmd.arg = 0; 251 cmd.driver = card->myid; 252 card->interface.statcallb(&cmd); 253 cmd.command = ISDN_STAT_DHUP; 254 cmd.arg = 0; 255 cmd.driver = card->myid; 256 card->interface.statcallb(&cmd); 257 cmd.command = ISDN_STAT_BHUP; 258 card->flags &= ~ISDNLOOP_FLAGS_B2ACTIVE; 259 isdnloop_free_queue(card, 1); 260 cmd.arg = 1; 261 cmd.driver = card->myid; 262 card->interface.statcallb(&cmd); 263 cmd.command = ISDN_STAT_DHUP; 264 cmd.arg = 1; 265 cmd.driver = card->myid; 266 break; 267 } 268 card->interface.statcallb(&cmd); 269} 270 271/* 272 * Store a cwcharacter into ringbuffer for reading from /dev/isdnctrl 273 * 274 * Parameter: 275 * card = pointer to card struct. 276 * c = char to store. 277 */ 278static void 279isdnloop_putmsg(isdnloop_card *card, unsigned char c) 280{ 281 ulong flags; 282 283 spin_lock_irqsave(&card->isdnloop_lock, flags); 284 *card->msg_buf_write++ = (c == 0xff) ? '\n' : c; 285 if (card->msg_buf_write == card->msg_buf_read) { 286 if (++card->msg_buf_read > card->msg_buf_end) 287 card->msg_buf_read = card->msg_buf; 288 } 289 if (card->msg_buf_write > card->msg_buf_end) 290 card->msg_buf_write = card->msg_buf; 291 spin_unlock_irqrestore(&card->isdnloop_lock, flags); 292} 293 294/* 295 * Poll a virtual cards message queue. 296 * If there are new status-replies from the card, copy them to 297 * ringbuffer for reading on /dev/isdnctrl and call 298 * isdnloop_parse_status() for processing them. Watch for special 299 * Firmware bootmessage and parse it, to get the D-Channel protocol. 300 * If there are B-Channels open, initiate a timer-callback to 301 * isdnloop_pollbchan(). 302 * This routine is called periodically via timer interrupt. 303 * 304 * Parameter: 305 * data = pointer to card struct 306 */ 307static void 308isdnloop_polldchan(unsigned long data) 309{ 310 isdnloop_card *card = (isdnloop_card *) data; 311 struct sk_buff *skb; 312 int avail; 313 int left; 314 u_char c; 315 int ch; 316 unsigned long flags; 317 u_char *p; 318 isdn_ctrl cmd; 319 320 skb = skb_dequeue(&card->dqueue); 321 if (skb) 322 avail = skb->len; 323 else 324 avail = 0; 325 for (left = avail; left > 0; left--) { 326 c = *skb->data; 327 skb_pull(skb, 1); 328 isdnloop_putmsg(card, c); 329 card->imsg[card->iptr] = c; 330 if (card->iptr < 59) 331 card->iptr++; 332 if (!skb->len) { 333 avail++; 334 isdnloop_putmsg(card, '\n'); 335 card->imsg[card->iptr] = 0; 336 card->iptr = 0; 337 if (card->imsg[0] == '0' && card->imsg[1] >= '0' && 338 card->imsg[1] <= '2' && card->imsg[2] == ';') { 339 ch = (card->imsg[1] - '0') - 1; 340 p = &card->imsg[3]; 341 isdnloop_parse_status(p, ch, card); 342 } else { 343 p = card->imsg; 344 if (!strncmp(p, "DRV1.", 5)) { 345 printk(KERN_INFO "isdnloop: (%s) %s\n", CID, p); 346 if (!strncmp(p + 7, "TC", 2)) { 347 card->ptype = ISDN_PTYPE_1TR6; 348 card->interface.features |= ISDN_FEATURE_P_1TR6; 349 printk(KERN_INFO 350 "isdnloop: (%s) 1TR6-Protocol loaded and running\n", CID); 351 } 352 if (!strncmp(p + 7, "EC", 2)) { 353 card->ptype = ISDN_PTYPE_EURO; 354 card->interface.features |= ISDN_FEATURE_P_EURO; 355 printk(KERN_INFO 356 "isdnloop: (%s) Euro-Protocol loaded and running\n", CID); 357 } 358 continue; 359 360 } 361 } 362 } 363 } 364 if (avail) { 365 cmd.command = ISDN_STAT_STAVAIL; 366 cmd.driver = card->myid; 367 cmd.arg = avail; 368 card->interface.statcallb(&cmd); 369 } 370 if (card->flags & (ISDNLOOP_FLAGS_B1ACTIVE | ISDNLOOP_FLAGS_B2ACTIVE)) 371 if (!(card->flags & ISDNLOOP_FLAGS_RBTIMER)) { 372 /* schedule b-channel polling */ 373 card->flags |= ISDNLOOP_FLAGS_RBTIMER; 374 spin_lock_irqsave(&card->isdnloop_lock, flags); 375 del_timer(&card->rb_timer); 376 card->rb_timer.function = isdnloop_pollbchan; 377 card->rb_timer.data = (unsigned long) card; 378 card->rb_timer.expires = jiffies + ISDNLOOP_TIMER_BCREAD; 379 add_timer(&card->rb_timer); 380 spin_unlock_irqrestore(&card->isdnloop_lock, flags); 381 } 382 /* schedule again */ 383 spin_lock_irqsave(&card->isdnloop_lock, flags); 384 card->st_timer.expires = jiffies + ISDNLOOP_TIMER_DCREAD; 385 add_timer(&card->st_timer); 386 spin_unlock_irqrestore(&card->isdnloop_lock, flags); 387} 388 389/* 390 * Append a packet to the transmit buffer-queue. 391 * 392 * Parameter: 393 * channel = Number of B-channel 394 * skb = packet to send. 395 * card = pointer to card-struct 396 * Return: 397 * Number of bytes transferred, -E??? on error 398 */ 399static int 400isdnloop_sendbuf(int channel, struct sk_buff *skb, isdnloop_card *card) 401{ 402 int len = skb->len; 403 unsigned long flags; 404 struct sk_buff *nskb; 405 406 if (len > 4000) { 407 printk(KERN_WARNING 408 "isdnloop: Send packet too large\n"); 409 return -EINVAL; 410 } 411 if (len) { 412 if (!(card->flags & (channel) ? ISDNLOOP_FLAGS_B2ACTIVE : ISDNLOOP_FLAGS_B1ACTIVE)) 413 return 0; 414 if (card->sndcount[channel] > ISDNLOOP_MAX_SQUEUE) 415 return 0; 416 spin_lock_irqsave(&card->isdnloop_lock, flags); 417 nskb = dev_alloc_skb(skb->len); 418 if (nskb) { 419 skb_copy_from_linear_data(skb, 420 skb_put(nskb, len), len); 421 skb_queue_tail(&card->bqueue[channel], nskb); 422 dev_kfree_skb(skb); 423 } else 424 len = 0; 425 card->sndcount[channel] += len; 426 spin_unlock_irqrestore(&card->isdnloop_lock, flags); 427 } 428 return len; 429} 430 431/* 432 * Read the messages from the card's ringbuffer 433 * 434 * Parameter: 435 * buf = pointer to buffer. 436 * len = number of bytes to read. 437 * user = flag, 1: called from userlevel 0: called from kernel. 438 * card = pointer to card struct. 439 * Return: 440 * number of bytes actually transferred. 441 */ 442static int 443isdnloop_readstatus(u_char __user *buf, int len, isdnloop_card *card) 444{ 445 int count; 446 u_char __user *p; 447 448 for (p = buf, count = 0; count < len; p++, count++) { 449 if (card->msg_buf_read == card->msg_buf_write) 450 return count; 451 if (put_user(*card->msg_buf_read++, p)) 452 return -EFAULT; 453 if (card->msg_buf_read > card->msg_buf_end) 454 card->msg_buf_read = card->msg_buf; 455 } 456 return count; 457} 458 459/* 460 * Simulate a card's response by appending it to the cards 461 * message queue. 462 * 463 * Parameter: 464 * card = pointer to card struct. 465 * s = pointer to message-string. 466 * ch = channel: 0 = generic messages, 1 and 2 = D-channel messages. 467 * Return: 468 * 0 on success, 1 on memory squeeze. 469 */ 470static int 471isdnloop_fake(isdnloop_card *card, char *s, int ch) 472{ 473 struct sk_buff *skb; 474 int len = strlen(s) + ((ch >= 0) ? 3 : 0); 475 skb = dev_alloc_skb(len); 476 if (!skb) { 477 printk(KERN_WARNING "isdnloop: Out of memory in isdnloop_fake\n"); 478 return 1; 479 } 480 if (ch >= 0) 481 sprintf(skb_put(skb, 3), "%02d;", ch); 482 memcpy(skb_put(skb, strlen(s)), s, strlen(s)); 483 skb_queue_tail(&card->dqueue, skb); 484 return 0; 485} 486/* *INDENT-OFF* */ 487static isdnloop_stat isdnloop_cmd_table[] = { 488 {"BCON_R", 0, 1}, /* B-Channel connect */ 489 {"BCON_I", 0, 17}, /* B-Channel connect ind */ 490 {"BDIS_R", 0, 2}, /* B-Channel disconnect */ 491 {"DDIS_R", 0, 3}, /* D-Channel disconnect */ 492 {"DCON_R", 0, 16}, /* D-Channel connect */ 493 {"DSCA_R", 0, 4}, /* Dial 1TR6-SPV */ 494 {"DCAL_R", 0, 5}, /* Dial */ 495 {"EAZC", 0, 6}, /* Clear EAZ listener */ 496 {"EAZ", 0, 7}, /* Set EAZ listener */ 497 {"SEEAZ", 0, 8}, /* Get EAZ listener */ 498 {"MSN", 0, 9}, /* Set/Clear MSN listener */ 499 {"MSALL", 0, 10}, /* Set multi MSN listeners */ 500 {"SETSIL", 0, 11}, /* Set SI list */ 501 {"SEESIL", 0, 12}, /* Get SI list */ 502 {"SILC", 0, 13}, /* Clear SI list */ 503 {"LOCK", 0, -1}, /* LOCK channel */ 504 {"UNLOCK", 0, -1}, /* UNLOCK channel */ 505 {"FV2ON", 1, 14}, /* Leased mode on */ 506 {"FV2OFF", 1, 15}, /* Leased mode off */ 507 {NULL, 0, -1} 508}; 509/* *INDENT-ON* */ 510 511 512/* 513 * Simulate an error-response from a card. 514 * 515 * Parameter: 516 * card = pointer to card struct. 517 */ 518static void 519isdnloop_fake_err(isdnloop_card *card) 520{ 521 char buf[64]; 522 523 snprintf(buf, sizeof(buf), "E%s", card->omsg); 524 isdnloop_fake(card, buf, -1); 525 isdnloop_fake(card, "NAK", -1); 526} 527 528static u_char ctable_eu[] = {0x00, 0x11, 0x01, 0x12}; 529static u_char ctable_1t[] = {0x00, 0x3b, 0x01, 0x3a}; 530 531/* 532 * Assemble a simplified cause message depending on the 533 * D-channel protocol used. 534 * 535 * Parameter: 536 * card = pointer to card struct. 537 * loc = location: 0 = local, 1 = remote. 538 * cau = cause: 1 = busy, 2 = nonexistent callerid, 3 = no user responding. 539 * Return: 540 * Pointer to buffer containing the assembled message. 541 */ 542static char * 543isdnloop_unicause(isdnloop_card *card, int loc, int cau) 544{ 545 static char buf[6]; 546 547 switch (card->ptype) { 548 case ISDN_PTYPE_EURO: 549 sprintf(buf, "E%02X%02X", (loc) ? 4 : 2, ctable_eu[cau]); 550 break; 551 case ISDN_PTYPE_1TR6: 552 sprintf(buf, "%02X44", ctable_1t[cau]); 553 break; 554 default: 555 return "0000"; 556 } 557 return buf; 558} 559 560/* 561 * Release a virtual connection. Called from timer interrupt, when 562 * called party did not respond. 563 * 564 * Parameter: 565 * card = pointer to card struct. 566 * ch = channel (0-based) 567 */ 568static void 569isdnloop_atimeout(isdnloop_card *card, int ch) 570{ 571 unsigned long flags; 572 char buf[60]; 573 574 spin_lock_irqsave(&card->isdnloop_lock, flags); 575 if (card->rcard) { 576 isdnloop_fake(card->rcard[ch], "DDIS_I", card->rch[ch] + 1); 577 card->rcard[ch]->rcard[card->rch[ch]] = NULL; 578 card->rcard[ch] = NULL; 579 } 580 isdnloop_fake(card, "DDIS_I", ch + 1); 581 /* No user responding */ 582 sprintf(buf, "CAU%s", isdnloop_unicause(card, 1, 3)); 583 isdnloop_fake(card, buf, ch + 1); 584 spin_unlock_irqrestore(&card->isdnloop_lock, flags); 585} 586 587/* 588 * Wrapper for isdnloop_atimeout(). 589 */ 590static void 591isdnloop_atimeout0(unsigned long data) 592{ 593 isdnloop_card *card = (isdnloop_card *) data; 594 isdnloop_atimeout(card, 0); 595} 596 597/* 598 * Wrapper for isdnloop_atimeout(). 599 */ 600static void 601isdnloop_atimeout1(unsigned long data) 602{ 603 isdnloop_card *card = (isdnloop_card *) data; 604 isdnloop_atimeout(card, 1); 605} 606 607/* 608 * Install a watchdog for a user, not responding. 609 * 610 * Parameter: 611 * card = pointer to card struct. 612 * ch = channel to watch for. 613 */ 614static void 615isdnloop_start_ctimer(isdnloop_card *card, int ch) 616{ 617 unsigned long flags; 618 619 spin_lock_irqsave(&card->isdnloop_lock, flags); 620 init_timer(&card->c_timer[ch]); 621 card->c_timer[ch].expires = jiffies + ISDNLOOP_TIMER_ALERTWAIT; 622 if (ch) 623 card->c_timer[ch].function = isdnloop_atimeout1; 624 else 625 card->c_timer[ch].function = isdnloop_atimeout0; 626 card->c_timer[ch].data = (unsigned long) card; 627 add_timer(&card->c_timer[ch]); 628 spin_unlock_irqrestore(&card->isdnloop_lock, flags); 629} 630 631/* 632 * Kill a pending channel watchdog. 633 * 634 * Parameter: 635 * card = pointer to card struct. 636 * ch = channel (0-based). 637 */ 638static void 639isdnloop_kill_ctimer(isdnloop_card *card, int ch) 640{ 641 unsigned long flags; 642 643 spin_lock_irqsave(&card->isdnloop_lock, flags); 644 del_timer(&card->c_timer[ch]); 645 spin_unlock_irqrestore(&card->isdnloop_lock, flags); 646} 647 648static u_char si2bit[] = {0, 1, 0, 0, 0, 2, 0, 4, 0, 0}; 649static u_char bit2si[] = {1, 5, 7}; 650 651/* 652 * Try finding a listener for an outgoing call. 653 * 654 * Parameter: 655 * card = pointer to calling card. 656 * p = pointer to ICN-type setup-string. 657 * lch = channel of calling card. 658 * cmd = pointer to struct to be filled when parsing setup. 659 * Return: 660 * 0 = found match, alerting should happen. 661 * 1 = found matching number but it is busy. 662 * 2 = no matching listener. 663 * 3 = found matching number but SI does not match. 664 */ 665static int 666isdnloop_try_call(isdnloop_card *card, char *p, int lch, isdn_ctrl *cmd) 667{ 668 isdnloop_card *cc = cards; 669 unsigned long flags; 670 int ch; 671 int num_match; 672 int i; 673 char *e; 674 char nbuf[32]; 675 676 isdnloop_parse_setup(p, cmd); 677 while (cc) { 678 for (ch = 0; ch < 2; ch++) { 679 /* Exclude ourself */ 680 if ((cc == card) && (ch == lch)) 681 continue; 682 num_match = 0; 683 switch (cc->ptype) { 684 case ISDN_PTYPE_EURO: 685 for (i = 0; i < 3; i++) 686 if (!(strcmp(cc->s0num[i], cmd->parm.setup.phone))) 687 num_match = 1; 688 break; 689 case ISDN_PTYPE_1TR6: 690 e = cc->eazlist[ch]; 691 while (*e) { 692 sprintf(nbuf, "%s%c", cc->s0num[0], *e); 693 if (!(strcmp(nbuf, cmd->parm.setup.phone))) 694 num_match = 1; 695 e++; 696 } 697 } 698 if (num_match) { 699 spin_lock_irqsave(&card->isdnloop_lock, flags); 700 /* channel idle? */ 701 if (!(cc->rcard[ch])) { 702 /* Check SI */ 703 if (!(si2bit[cmd->parm.setup.si1] & cc->sil[ch])) { 704 spin_unlock_irqrestore(&card->isdnloop_lock, flags); 705 return 3; 706 } 707 /* ch is idle, si and number matches */ 708 cc->rcard[ch] = card; 709 cc->rch[ch] = lch; 710 card->rcard[lch] = cc; 711 card->rch[lch] = ch; 712 spin_unlock_irqrestore(&card->isdnloop_lock, flags); 713 return 0; 714 } else { 715 spin_unlock_irqrestore(&card->isdnloop_lock, flags); 716 /* num matches, but busy */ 717 if (ch == 1) 718 return 1; 719 } 720 } 721 } 722 cc = cc->next; 723 } 724 return 2; 725} 726 727/* 728 * Depending on D-channel protocol and caller/called, modify 729 * phone number. 730 * 731 * Parameter: 732 * card = pointer to card struct. 733 * phone = pointer phone number. 734 * caller = flag: 1 = caller, 0 = called. 735 * Return: 736 * pointer to new phone number. 737 */ 738static char * 739isdnloop_vstphone(isdnloop_card *card, char *phone, int caller) 740{ 741 int i; 742 static char nphone[30]; 743 744 if (!card) { 745 printk("BUG!!!\n"); 746 return ""; 747 } 748 switch (card->ptype) { 749 case ISDN_PTYPE_EURO: 750 if (caller) { 751 for (i = 0; i < 2; i++) 752 if (!(strcmp(card->s0num[i], phone))) 753 return phone; 754 return card->s0num[0]; 755 } 756 return phone; 757 break; 758 case ISDN_PTYPE_1TR6: 759 if (caller) { 760 sprintf(nphone, "%s%c", card->s0num[0], phone[0]); 761 return nphone; 762 } else 763 return &phone[strlen(phone) - 1]; 764 break; 765 } 766 return ""; 767} 768 769/* 770 * Parse an ICN-type command string sent to the 'card'. 771 * Perform misc. actions depending on the command. 772 * 773 * Parameter: 774 * card = pointer to card struct. 775 */ 776static void 777isdnloop_parse_cmd(isdnloop_card *card) 778{ 779 char *p = card->omsg; 780 isdn_ctrl cmd; 781 char buf[60]; 782 isdnloop_stat *s = isdnloop_cmd_table; 783 int action = -1; 784 int i; 785 int ch; 786 787 if ((card->omsg[0] != '0') && (card->omsg[2] != ';')) { 788 isdnloop_fake_err(card); 789 return; 790 } 791 ch = card->omsg[1] - '0'; 792 if ((ch < 0) || (ch > 2)) { 793 isdnloop_fake_err(card); 794 return; 795 } 796 p += 3; 797 while (s->statstr) { 798 if (!strncmp(p, s->statstr, strlen(s->statstr))) { 799 action = s->action; 800 if (s->command && (ch != 0)) { 801 isdnloop_fake_err(card); 802 return; 803 } 804 break; 805 } 806 s++; 807 } 808 if (action == -1) 809 return; 810 switch (action) { 811 case 1: 812 /* 0x;BCON_R */ 813 if (card->rcard[ch - 1]) { 814 isdnloop_fake(card->rcard[ch - 1], "BCON_I", 815 card->rch[ch - 1] + 1); 816 isdnloop_fake(card, "BCON_C", ch); 817 } 818 break; 819 case 17: 820 /* 0x;BCON_I */ 821 if (card->rcard[ch - 1]) { 822 isdnloop_fake(card->rcard[ch - 1], "BCON_C", 823 card->rch[ch - 1] + 1); 824 } 825 break; 826 case 2: 827 /* 0x;BDIS_R */ 828 isdnloop_fake(card, "BDIS_C", ch); 829 if (card->rcard[ch - 1]) { 830 isdnloop_fake(card->rcard[ch - 1], "BDIS_I", 831 card->rch[ch - 1] + 1); 832 } 833 break; 834 case 16: 835 /* 0x;DCON_R */ 836 isdnloop_kill_ctimer(card, ch - 1); 837 if (card->rcard[ch - 1]) { 838 isdnloop_kill_ctimer(card->rcard[ch - 1], card->rch[ch - 1]); 839 isdnloop_fake(card->rcard[ch - 1], "DCON_C", 840 card->rch[ch - 1] + 1); 841 isdnloop_fake(card, "DCON_C", ch); 842 } 843 break; 844 case 3: 845 /* 0x;DDIS_R */ 846 isdnloop_kill_ctimer(card, ch - 1); 847 if (card->rcard[ch - 1]) { 848 isdnloop_kill_ctimer(card->rcard[ch - 1], card->rch[ch - 1]); 849 isdnloop_fake(card->rcard[ch - 1], "DDIS_I", 850 card->rch[ch - 1] + 1); 851 card->rcard[ch - 1] = NULL; 852 } 853 isdnloop_fake(card, "DDIS_C", ch); 854 break; 855 case 4: 856 /* 0x;DSCA_Rdd,yy,zz,oo */ 857 if (card->ptype != ISDN_PTYPE_1TR6) { 858 isdnloop_fake_err(card); 859 return; 860 } 861 /* Fall through */ 862 case 5: 863 /* 0x;DCAL_Rdd,yy,zz,oo */ 864 p += 6; 865 switch (isdnloop_try_call(card, p, ch - 1, &cmd)) { 866 case 0: 867 /* Alerting */ 868 sprintf(buf, "D%s_I%s,%02d,%02d,%s", 869 (action == 4) ? "SCA" : "CAL", 870 isdnloop_vstphone(card, cmd.parm.setup.eazmsn, 1), 871 cmd.parm.setup.si1, 872 cmd.parm.setup.si2, 873 isdnloop_vstphone(card->rcard[ch - 1], 874 cmd.parm.setup.phone, 0)); 875 isdnloop_fake(card->rcard[ch - 1], buf, card->rch[ch - 1] + 1); 876 /* Fall through */ 877 case 3: 878 /* si1 does not match, don't alert but start timer */ 879 isdnloop_start_ctimer(card, ch - 1); 880 break; 881 case 1: 882 /* Remote busy */ 883 isdnloop_fake(card, "DDIS_I", ch); 884 sprintf(buf, "CAU%s", isdnloop_unicause(card, 1, 1)); 885 isdnloop_fake(card, buf, ch); 886 break; 887 case 2: 888 /* No such user */ 889 isdnloop_fake(card, "DDIS_I", ch); 890 sprintf(buf, "CAU%s", isdnloop_unicause(card, 1, 2)); 891 isdnloop_fake(card, buf, ch); 892 break; 893 } 894 break; 895 case 6: 896 /* 0x;EAZC */ 897 card->eazlist[ch - 1][0] = '\0'; 898 break; 899 case 7: 900 /* 0x;EAZ */ 901 p += 3; 902 if (strlen(p) >= sizeof(card->eazlist[0])) 903 break; 904 strcpy(card->eazlist[ch - 1], p); 905 break; 906 case 8: 907 /* 0x;SEEAZ */ 908 sprintf(buf, "EAZ-LIST: %s", card->eazlist[ch - 1]); 909 isdnloop_fake(card, buf, ch + 1); 910 break; 911 case 9: 912 /* 0x;MSN */ 913 break; 914 case 10: 915 /* 0x;MSNALL */ 916 break; 917 case 11: 918 /* 0x;SETSIL */ 919 p += 6; 920 i = 0; 921 while (strchr("0157", *p)) { 922 if (i) 923 card->sil[ch - 1] |= si2bit[*p - '0']; 924 i = (*p++ == '0'); 925 } 926 if (*p) 927 isdnloop_fake_err(card); 928 break; 929 case 12: 930 /* 0x;SEESIL */ 931 sprintf(buf, "SIN-LIST: "); 932 p = buf + 10; 933 for (i = 0; i < 3; i++) 934 if (card->sil[ch - 1] & (1 << i)) 935 p += sprintf(p, "%02d", bit2si[i]); 936 isdnloop_fake(card, buf, ch + 1); 937 break; 938 case 13: 939 /* 0x;SILC */ 940 card->sil[ch - 1] = 0; 941 break; 942 case 14: 943 /* 00;FV2ON */ 944 break; 945 case 15: 946 /* 00;FV2OFF */ 947 break; 948 } 949} 950 951/* 952 * Put command-strings into the of the 'card'. In reality, execute them 953 * right in place by calling isdnloop_parse_cmd(). Also copy every 954 * command to the read message ringbuffer, preceding it with a '>'. 955 * These mesagges can be read at /dev/isdnctrl. 956 * 957 * Parameter: 958 * buf = pointer to command buffer. 959 * len = length of buffer data. 960 * user = flag: 1 = called form userlevel, 0 called from kernel. 961 * card = pointer to card struct. 962 * Return: 963 * number of bytes transferred (currently always equals len). 964 */ 965static int 966isdnloop_writecmd(const u_char *buf, int len, int user, isdnloop_card *card) 967{ 968 int xcount = 0; 969 int ocount = 1; 970 isdn_ctrl cmd; 971 972 while (len) { 973 int count = len; 974 u_char *p; 975 u_char msg[0x100]; 976 977 if (count > 255) 978 count = 255; 979 if (user) { 980 if (copy_from_user(msg, buf, count)) 981 return -EFAULT; 982 } else 983 memcpy(msg, buf, count); 984 isdnloop_putmsg(card, '>'); 985 for (p = msg; count > 0; count--, p++) { 986 len--; 987 xcount++; 988 isdnloop_putmsg(card, *p); 989 card->omsg[card->optr] = *p; 990 if (*p == '\n') { 991 card->omsg[card->optr] = '\0'; 992 card->optr = 0; 993 isdnloop_parse_cmd(card); 994 if (len) { 995 isdnloop_putmsg(card, '>'); 996 ocount++; 997 } 998 } else { 999 if (card->optr < 59) 1000 card->optr++; 1001 } 1002 ocount++; 1003 } 1004 } 1005 cmd.command = ISDN_STAT_STAVAIL; 1006 cmd.driver = card->myid; 1007 cmd.arg = ocount; 1008 card->interface.statcallb(&cmd); 1009 return xcount; 1010} 1011 1012/* 1013 * Delete card's pending timers, send STOP to linklevel 1014 */ 1015static void 1016isdnloop_stopcard(isdnloop_card *card) 1017{ 1018 unsigned long flags; 1019 isdn_ctrl cmd; 1020 1021 spin_lock_irqsave(&card->isdnloop_lock, flags); 1022 if (card->flags & ISDNLOOP_FLAGS_RUNNING) { 1023 card->flags &= ~ISDNLOOP_FLAGS_RUNNING; 1024 del_timer(&card->st_timer); 1025 del_timer(&card->rb_timer); 1026 del_timer(&card->c_timer[0]); 1027 del_timer(&card->c_timer[1]); 1028 cmd.command = ISDN_STAT_STOP; 1029 cmd.driver = card->myid; 1030 card->interface.statcallb(&cmd); 1031 } 1032 spin_unlock_irqrestore(&card->isdnloop_lock, flags); 1033} 1034 1035/* 1036 * Stop all cards before unload. 1037 */ 1038static void 1039isdnloop_stopallcards(void) 1040{ 1041 isdnloop_card *p = cards; 1042 1043 while (p) { 1044 isdnloop_stopcard(p); 1045 p = p->next; 1046 } 1047} 1048 1049/* 1050 * Start a 'card'. Simulate card's boot message and set the phone 1051 * number(s) of the virtual 'S0-Interface'. Install D-channel 1052 * poll timer. 1053 * 1054 * Parameter: 1055 * card = pointer to card struct. 1056 * sdefp = pointer to struct holding ioctl parameters. 1057 * Return: 1058 * 0 on success, -E??? otherwise. 1059 */ 1060static int 1061isdnloop_start(isdnloop_card *card, isdnloop_sdef *sdefp) 1062{ 1063 unsigned long flags; 1064 isdnloop_sdef sdef; 1065 int i; 1066 1067 if (card->flags & ISDNLOOP_FLAGS_RUNNING) 1068 return -EBUSY; 1069 if (copy_from_user((char *) &sdef, (char *) sdefp, sizeof(sdef))) 1070 return -EFAULT; 1071 1072 for (i = 0; i < 3; i++) { 1073 if (!memchr(sdef.num[i], 0, sizeof(sdef.num[i]))) 1074 return -EINVAL; 1075 } 1076 1077 spin_lock_irqsave(&card->isdnloop_lock, flags); 1078 switch (sdef.ptype) { 1079 case ISDN_PTYPE_EURO: 1080 if (isdnloop_fake(card, "DRV1.23EC-Q.931-CAPI-CNS-BASIS-20.02.96", 1081 -1)) { 1082 spin_unlock_irqrestore(&card->isdnloop_lock, flags); 1083 return -ENOMEM; 1084 } 1085 card->sil[0] = card->sil[1] = 4; 1086 if (isdnloop_fake(card, "TEI OK", 0)) { 1087 spin_unlock_irqrestore(&card->isdnloop_lock, flags); 1088 return -ENOMEM; 1089 } 1090 for (i = 0; i < 3; i++) { 1091 strlcpy(card->s0num[i], sdef.num[i], 1092 sizeof(card->s0num[0])); 1093 } 1094 break; 1095 case ISDN_PTYPE_1TR6: 1096 if (isdnloop_fake(card, "DRV1.04TC-1TR6-CAPI-CNS-BASIS-29.11.95", 1097 -1)) { 1098 spin_unlock_irqrestore(&card->isdnloop_lock, flags); 1099 return -ENOMEM; 1100 } 1101 card->sil[0] = card->sil[1] = 4; 1102 if (isdnloop_fake(card, "TEI OK", 0)) { 1103 spin_unlock_irqrestore(&card->isdnloop_lock, flags); 1104 return -ENOMEM; 1105 } 1106 strlcpy(card->s0num[0], sdef.num[0], sizeof(card->s0num[0])); 1107 card->s0num[1][0] = '\0'; 1108 card->s0num[2][0] = '\0'; 1109 break; 1110 default: 1111 spin_unlock_irqrestore(&card->isdnloop_lock, flags); 1112 printk(KERN_WARNING "isdnloop: Illegal D-channel protocol %d\n", 1113 sdef.ptype); 1114 return -EINVAL; 1115 } 1116 init_timer(&card->st_timer); 1117 card->st_timer.expires = jiffies + ISDNLOOP_TIMER_DCREAD; 1118 card->st_timer.function = isdnloop_polldchan; 1119 card->st_timer.data = (unsigned long) card; 1120 add_timer(&card->st_timer); 1121 card->flags |= ISDNLOOP_FLAGS_RUNNING; 1122 spin_unlock_irqrestore(&card->isdnloop_lock, flags); 1123 return 0; 1124} 1125 1126/* 1127 * Main handler for commands sent by linklevel. 1128 */ 1129static int 1130isdnloop_command(isdn_ctrl *c, isdnloop_card *card) 1131{ 1132 ulong a; 1133 int i; 1134 char cbuf[80]; 1135 isdn_ctrl cmd; 1136 isdnloop_cdef cdef; 1137 1138 switch (c->command) { 1139 case ISDN_CMD_IOCTL: 1140 memcpy(&a, c->parm.num, sizeof(ulong)); 1141 switch (c->arg) { 1142 case ISDNLOOP_IOCTL_DEBUGVAR: 1143 return (ulong) card; 1144 case ISDNLOOP_IOCTL_STARTUP: 1145 if (!access_ok(VERIFY_READ, (void *) a, sizeof(isdnloop_sdef))) 1146 return -EFAULT; 1147 return isdnloop_start(card, (isdnloop_sdef *) a); 1148 break; 1149 case ISDNLOOP_IOCTL_ADDCARD: 1150 if (copy_from_user((char *)&cdef, 1151 (char *)a, 1152 sizeof(cdef))) 1153 return -EFAULT; 1154 return isdnloop_addcard(cdef.id1); 1155 break; 1156 case ISDNLOOP_IOCTL_LEASEDCFG: 1157 if (a) { 1158 if (!card->leased) { 1159 card->leased = 1; 1160 while (card->ptype == ISDN_PTYPE_UNKNOWN) 1161 schedule_timeout_interruptible(10); 1162 schedule_timeout_interruptible(10); 1163 sprintf(cbuf, "00;FV2ON\n01;EAZ1\n02;EAZ2\n"); 1164 i = isdnloop_writecmd(cbuf, strlen(cbuf), 0, card); 1165 printk(KERN_INFO 1166 "isdnloop: (%s) Leased-line mode enabled\n", 1167 CID); 1168 cmd.command = ISDN_STAT_RUN; 1169 cmd.driver = card->myid; 1170 cmd.arg = 0; 1171 card->interface.statcallb(&cmd); 1172 } 1173 } else { 1174 if (card->leased) { 1175 card->leased = 0; 1176 sprintf(cbuf, "00;FV2OFF\n"); 1177 i = isdnloop_writecmd(cbuf, strlen(cbuf), 0, card); 1178 printk(KERN_INFO 1179 "isdnloop: (%s) Leased-line mode disabled\n", 1180 CID); 1181 cmd.command = ISDN_STAT_RUN; 1182 cmd.driver = card->myid; 1183 cmd.arg = 0; 1184 card->interface.statcallb(&cmd); 1185 } 1186 } 1187 return 0; 1188 default: 1189 return -EINVAL; 1190 } 1191 break; 1192 case ISDN_CMD_DIAL: 1193 if (!(card->flags & ISDNLOOP_FLAGS_RUNNING)) 1194 return -ENODEV; 1195 if (card->leased) 1196 break; 1197 if ((c->arg & 255) < ISDNLOOP_BCH) { 1198 char *p; 1199 char dcode[4]; 1200 1201 a = c->arg; 1202 p = c->parm.setup.phone; 1203 if (*p == 's' || *p == 'S') { 1204 /* Dial for SPV */ 1205 p++; 1206 strcpy(dcode, "SCA"); 1207 } else 1208 /* Normal Dial */ 1209 strcpy(dcode, "CAL"); 1210 snprintf(cbuf, sizeof(cbuf), 1211 "%02d;D%s_R%s,%02d,%02d,%s\n", (int) (a + 1), 1212 dcode, p, c->parm.setup.si1, 1213 c->parm.setup.si2, c->parm.setup.eazmsn); 1214 i = isdnloop_writecmd(cbuf, strlen(cbuf), 0, card); 1215 } 1216 break; 1217 case ISDN_CMD_ACCEPTD: 1218 if (!(card->flags & ISDNLOOP_FLAGS_RUNNING)) 1219 return -ENODEV; 1220 if (c->arg < ISDNLOOP_BCH) { 1221 a = c->arg + 1; 1222 cbuf[0] = 0; 1223 switch (card->l2_proto[a - 1]) { 1224 case ISDN_PROTO_L2_X75I: 1225 sprintf(cbuf, "%02d;BX75\n", (int) a); 1226 break; 1227#ifdef CONFIG_ISDN_X25 1228 case ISDN_PROTO_L2_X25DTE: 1229 sprintf(cbuf, "%02d;BX2T\n", (int) a); 1230 break; 1231 case ISDN_PROTO_L2_X25DCE: 1232 sprintf(cbuf, "%02d;BX2C\n", (int) a); 1233 break; 1234#endif 1235 case ISDN_PROTO_L2_HDLC: 1236 sprintf(cbuf, "%02d;BTRA\n", (int) a); 1237 break; 1238 } 1239 if (strlen(cbuf)) 1240 i = isdnloop_writecmd(cbuf, strlen(cbuf), 0, card); 1241 sprintf(cbuf, "%02d;DCON_R\n", (int) a); 1242 i = isdnloop_writecmd(cbuf, strlen(cbuf), 0, card); 1243 } 1244 break; 1245 case ISDN_CMD_ACCEPTB: 1246 if (!(card->flags & ISDNLOOP_FLAGS_RUNNING)) 1247 return -ENODEV; 1248 if (c->arg < ISDNLOOP_BCH) { 1249 a = c->arg + 1; 1250 switch (card->l2_proto[a - 1]) { 1251 case ISDN_PROTO_L2_X75I: 1252 sprintf(cbuf, "%02d;BCON_R,BX75\n", (int) a); 1253 break; 1254#ifdef CONFIG_ISDN_X25 1255 case ISDN_PROTO_L2_X25DTE: 1256 sprintf(cbuf, "%02d;BCON_R,BX2T\n", (int) a); 1257 break; 1258 case ISDN_PROTO_L2_X25DCE: 1259 sprintf(cbuf, "%02d;BCON_R,BX2C\n", (int) a); 1260 break; 1261#endif 1262 case ISDN_PROTO_L2_HDLC: 1263 sprintf(cbuf, "%02d;BCON_R,BTRA\n", (int) a); 1264 break; 1265 default: 1266 sprintf(cbuf, "%02d;BCON_R\n", (int) a); 1267 } 1268 printk(KERN_DEBUG "isdnloop writecmd '%s'\n", cbuf); 1269 i = isdnloop_writecmd(cbuf, strlen(cbuf), 0, card); 1270 break; 1271 case ISDN_CMD_HANGUP: 1272 if (!(card->flags & ISDNLOOP_FLAGS_RUNNING)) 1273 return -ENODEV; 1274 if (c->arg < ISDNLOOP_BCH) { 1275 a = c->arg + 1; 1276 sprintf(cbuf, "%02d;BDIS_R\n%02d;DDIS_R\n", (int) a, (int) a); 1277 i = isdnloop_writecmd(cbuf, strlen(cbuf), 0, card); 1278 } 1279 break; 1280 case ISDN_CMD_SETEAZ: 1281 if (!(card->flags & ISDNLOOP_FLAGS_RUNNING)) 1282 return -ENODEV; 1283 if (card->leased) 1284 break; 1285 if (c->arg < ISDNLOOP_BCH) { 1286 a = c->arg + 1; 1287 if (card->ptype == ISDN_PTYPE_EURO) { 1288 sprintf(cbuf, "%02d;MS%s%s\n", (int) a, 1289 c->parm.num[0] ? "N" : "ALL", c->parm.num); 1290 } else 1291 sprintf(cbuf, "%02d;EAZ%s\n", (int) a, 1292 c->parm.num[0] ? c->parm.num : (u_char *) "0123456789"); 1293 i = isdnloop_writecmd(cbuf, strlen(cbuf), 0, card); 1294 } 1295 break; 1296 case ISDN_CMD_CLREAZ: 1297 if (!(card->flags & ISDNLOOP_FLAGS_RUNNING)) 1298 return -ENODEV; 1299 if (card->leased) 1300 break; 1301 if (c->arg < ISDNLOOP_BCH) { 1302 a = c->arg + 1; 1303 if (card->ptype == ISDN_PTYPE_EURO) 1304 sprintf(cbuf, "%02d;MSNC\n", (int) a); 1305 else 1306 sprintf(cbuf, "%02d;EAZC\n", (int) a); 1307 i = isdnloop_writecmd(cbuf, strlen(cbuf), 0, card); 1308 } 1309 break; 1310 case ISDN_CMD_SETL2: 1311 if (!(card->flags & ISDNLOOP_FLAGS_RUNNING)) 1312 return -ENODEV; 1313 if ((c->arg & 255) < ISDNLOOP_BCH) { 1314 a = c->arg; 1315 switch (a >> 8) { 1316 case ISDN_PROTO_L2_X75I: 1317 sprintf(cbuf, "%02d;BX75\n", (int) (a & 255) + 1); 1318 break; 1319#ifdef CONFIG_ISDN_X25 1320 case ISDN_PROTO_L2_X25DTE: 1321 sprintf(cbuf, "%02d;BX2T\n", (int) (a & 255) + 1); 1322 break; 1323 case ISDN_PROTO_L2_X25DCE: 1324 sprintf(cbuf, "%02d;BX2C\n", (int) (a & 255) + 1); 1325 break; 1326#endif 1327 case ISDN_PROTO_L2_HDLC: 1328 sprintf(cbuf, "%02d;BTRA\n", (int) (a & 255) + 1); 1329 break; 1330 case ISDN_PROTO_L2_TRANS: 1331 sprintf(cbuf, "%02d;BTRA\n", (int) (a & 255) + 1); 1332 break; 1333 default: 1334 return -EINVAL; 1335 } 1336 i = isdnloop_writecmd(cbuf, strlen(cbuf), 0, card); 1337 card->l2_proto[a & 255] = (a >> 8); 1338 } 1339 break; 1340 case ISDN_CMD_SETL3: 1341 if (!(card->flags & ISDNLOOP_FLAGS_RUNNING)) 1342 return -ENODEV; 1343 return 0; 1344 default: 1345 return -EINVAL; 1346 } 1347 } 1348 return 0; 1349} 1350 1351/* 1352 * Find card with given driverId 1353 */ 1354static inline isdnloop_card * 1355isdnloop_findcard(int driverid) 1356{ 1357 isdnloop_card *p = cards; 1358 1359 while (p) { 1360 if (p->myid == driverid) 1361 return p; 1362 p = p->next; 1363 } 1364 return (isdnloop_card *) 0; 1365} 1366 1367/* 1368 * Wrapper functions for interface to linklevel 1369 */ 1370static int 1371if_command(isdn_ctrl *c) 1372{ 1373 isdnloop_card *card = isdnloop_findcard(c->driver); 1374 1375 if (card) 1376 return isdnloop_command(c, card); 1377 printk(KERN_ERR 1378 "isdnloop: if_command called with invalid driverId!\n"); 1379 return -ENODEV; 1380} 1381 1382static int 1383if_writecmd(const u_char __user *buf, int len, int id, int channel) 1384{ 1385 isdnloop_card *card = isdnloop_findcard(id); 1386 1387 if (card) { 1388 if (!(card->flags & ISDNLOOP_FLAGS_RUNNING)) 1389 return -ENODEV; 1390 return isdnloop_writecmd(buf, len, 1, card); 1391 } 1392 printk(KERN_ERR 1393 "isdnloop: if_writecmd called with invalid driverId!\n"); 1394 return -ENODEV; 1395} 1396 1397static int 1398if_readstatus(u_char __user *buf, int len, int id, int channel) 1399{ 1400 isdnloop_card *card = isdnloop_findcard(id); 1401 1402 if (card) { 1403 if (!(card->flags & ISDNLOOP_FLAGS_RUNNING)) 1404 return -ENODEV; 1405 return isdnloop_readstatus(buf, len, card); 1406 } 1407 printk(KERN_ERR 1408 "isdnloop: if_readstatus called with invalid driverId!\n"); 1409 return -ENODEV; 1410} 1411 1412static int 1413if_sendbuf(int id, int channel, int ack, struct sk_buff *skb) 1414{ 1415 isdnloop_card *card = isdnloop_findcard(id); 1416 1417 if (card) { 1418 if (!(card->flags & ISDNLOOP_FLAGS_RUNNING)) 1419 return -ENODEV; 1420 /* ack request stored in skb scratch area */ 1421 *(skb->head) = ack; 1422 return isdnloop_sendbuf(channel, skb, card); 1423 } 1424 printk(KERN_ERR 1425 "isdnloop: if_sendbuf called with invalid driverId!\n"); 1426 return -ENODEV; 1427} 1428 1429/* 1430 * Allocate a new card-struct, initialize it 1431 * link it into cards-list and register it at linklevel. 1432 */ 1433static isdnloop_card * 1434isdnloop_initcard(char *id) 1435{ 1436 isdnloop_card *card; 1437 int i; 1438 card = kzalloc(sizeof(isdnloop_card), GFP_KERNEL); 1439 if (!card) { 1440 printk(KERN_WARNING 1441 "isdnloop: (%s) Could not allocate card-struct.\n", id); 1442 return (isdnloop_card *) 0; 1443 } 1444 card->interface.owner = THIS_MODULE; 1445 card->interface.channels = ISDNLOOP_BCH; 1446 card->interface.hl_hdrlen = 1; /* scratch area for storing ack flag*/ 1447 card->interface.maxbufsize = 4000; 1448 card->interface.command = if_command; 1449 card->interface.writebuf_skb = if_sendbuf; 1450 card->interface.writecmd = if_writecmd; 1451 card->interface.readstat = if_readstatus; 1452 card->interface.features = ISDN_FEATURE_L2_X75I | 1453#ifdef CONFIG_ISDN_X25 1454 ISDN_FEATURE_L2_X25DTE | 1455 ISDN_FEATURE_L2_X25DCE | 1456#endif 1457 ISDN_FEATURE_L2_HDLC | 1458 ISDN_FEATURE_L3_TRANS | 1459 ISDN_FEATURE_P_UNKNOWN; 1460 card->ptype = ISDN_PTYPE_UNKNOWN; 1461 strlcpy(card->interface.id, id, sizeof(card->interface.id)); 1462 card->msg_buf_write = card->msg_buf; 1463 card->msg_buf_read = card->msg_buf; 1464 card->msg_buf_end = &card->msg_buf[sizeof(card->msg_buf) - 1]; 1465 for (i = 0; i < ISDNLOOP_BCH; i++) { 1466 card->l2_proto[i] = ISDN_PROTO_L2_X75I; 1467 skb_queue_head_init(&card->bqueue[i]); 1468 } 1469 skb_queue_head_init(&card->dqueue); 1470 spin_lock_init(&card->isdnloop_lock); 1471 card->next = cards; 1472 cards = card; 1473 if (!register_isdn(&card->interface)) { 1474 cards = cards->next; 1475 printk(KERN_WARNING 1476 "isdnloop: Unable to register %s\n", id); 1477 kfree(card); 1478 return (isdnloop_card *) 0; 1479 } 1480 card->myid = card->interface.channels; 1481 return card; 1482} 1483 1484static int 1485isdnloop_addcard(char *id1) 1486{ 1487 isdnloop_card *card; 1488 card = isdnloop_initcard(id1); 1489 if (!card) { 1490 return -EIO; 1491 } 1492 printk(KERN_INFO 1493 "isdnloop: (%s) virtual card added\n", 1494 card->interface.id); 1495 return 0; 1496} 1497 1498static int __init 1499isdnloop_init(void) 1500{ 1501 if (isdnloop_id) 1502 return isdnloop_addcard(isdnloop_id); 1503 1504 return 0; 1505} 1506 1507static void __exit 1508isdnloop_exit(void) 1509{ 1510 isdn_ctrl cmd; 1511 isdnloop_card *card = cards; 1512 isdnloop_card *last; 1513 int i; 1514 1515 isdnloop_stopallcards(); 1516 while (card) { 1517 cmd.command = ISDN_STAT_UNLOAD; 1518 cmd.driver = card->myid; 1519 card->interface.statcallb(&cmd); 1520 for (i = 0; i < ISDNLOOP_BCH; i++) 1521 isdnloop_free_queue(card, i); 1522 card = card->next; 1523 } 1524 card = cards; 1525 while (card) { 1526 last = card; 1527 skb_queue_purge(&card->dqueue); 1528 card = card->next; 1529 kfree(last); 1530 } 1531 printk(KERN_NOTICE "isdnloop-ISDN-driver unloaded\n"); 1532} 1533 1534module_init(isdnloop_init); 1535module_exit(isdnloop_exit); 1536