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