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