1 /* $Id: capi.c,v 1.1.2.7 2004/04/28 09:48:59 armin Exp $ 2 * 3 * CAPI 2.0 Interface for Linux 4 * 5 * Copyright 1996 by Carsten Paeth <calle@calle.de> 6 * 7 * This software may be used and distributed according to the terms 8 * of the GNU General Public License, incorporated herein by reference. 9 * 10 */ 11 12 #include <linux/config.h> 13 #include <linux/module.h> 14 #include <linux/errno.h> 15 #include <linux/kernel.h> 16 #include <linux/major.h> 17 #include <linux/sched.h> 18 #include <linux/slab.h> 19 #include <linux/fcntl.h> 20 #include <linux/fs.h> 21 #include <linux/signal.h> 22 #include <linux/mm.h> 23 #include <linux/smp_lock.h> 24 #include <linux/timer.h> 25 #include <linux/wait.h> 26 #ifdef CONFIG_ISDN_CAPI_MIDDLEWARE 27 #include <linux/tty.h> 28 #ifdef CONFIG_PPP 29 #include <linux/netdevice.h> 30 #include <linux/ppp_defs.h> 31 #include <linux/if_ppp.h> 32 #endif /* CONFIG_PPP */ 33 #endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */ 34 #include <linux/skbuff.h> 35 #include <linux/proc_fs.h> 36 #include <linux/poll.h> 37 #include <linux/capi.h> 38 #include <linux/kernelcapi.h> 39 #include <linux/init.h> 40 #include <linux/device.h> 41 #include <linux/moduleparam.h> 42 #include <linux/devfs_fs_kernel.h> 43 #include <linux/isdn/capiutil.h> 44 #include <linux/isdn/capicmd.h> 45 #if defined(CONFIG_ISDN_CAPI_CAPIFS) || defined(CONFIG_ISDN_CAPI_CAPIFS_MODULE) 46 #include "capifs.h" 47 #endif 48 49 static char *revision = "$Revision: 1.1.2.7 $"; 50 51 MODULE_DESCRIPTION("CAPI4Linux: Userspace /dev/capi20 interface"); 52 MODULE_AUTHOR("Carsten Paeth"); 53 MODULE_LICENSE("GPL"); 54 55 #undef _DEBUG_REFCOUNT /* alloc/free and open/close debug */ 56 #undef _DEBUG_TTYFUNCS /* call to tty_driver */ 57 #undef _DEBUG_DATAFLOW /* data flow */ 58 59 /* -------- driver information -------------------------------------- */ 60 61 static struct class *capi_class; 62 63 static int capi_major = 68; /* allocated */ 64 #ifdef CONFIG_ISDN_CAPI_MIDDLEWARE 65 #define CAPINC_NR_PORTS 32 66 #define CAPINC_MAX_PORTS 256 67 static int capi_ttymajor = 191; 68 static int capi_ttyminors = CAPINC_NR_PORTS; 69 #endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */ 70 71 module_param_named(major, capi_major, uint, 0); 72 #ifdef CONFIG_ISDN_CAPI_MIDDLEWARE 73 module_param_named(ttymajor, capi_ttymajor, uint, 0); 74 module_param_named(ttyminors, capi_ttyminors, uint, 0); 75 #endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */ 76 77 /* -------- defines ------------------------------------------------- */ 78 79 #define CAPINC_MAX_RECVQUEUE 10 80 #define CAPINC_MAX_SENDQUEUE 10 81 #define CAPI_MAX_BLKSIZE 2048 82 83 /* -------- data structures ----------------------------------------- */ 84 85 struct capidev; 86 struct capincci; 87 #ifdef CONFIG_ISDN_CAPI_MIDDLEWARE 88 struct capiminor; 89 90 struct capiminor { 91 struct list_head list; 92 struct capincci *nccip; 93 unsigned int minor; 94 95 struct capi20_appl *ap; 96 u32 ncci; 97 u16 datahandle; 98 u16 msgid; 99 100 struct tty_struct *tty; 101 int ttyinstop; 102 int ttyoutstop; 103 struct sk_buff *ttyskb; 104 atomic_t ttyopencount; 105 106 struct sk_buff_head inqueue; 107 int inbytes; 108 struct sk_buff_head outqueue; 109 int outbytes; 110 111 /* transmit path */ 112 struct datahandle_queue { 113 struct datahandle_queue *next; 114 u16 datahandle; 115 } *ackqueue; 116 int nack; 117 118 }; 119 #endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */ 120 121 struct capincci { 122 struct capincci *next; 123 u32 ncci; 124 struct capidev *cdev; 125 #ifdef CONFIG_ISDN_CAPI_MIDDLEWARE 126 struct capiminor *minorp; 127 #endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */ 128 }; 129 130 struct capidev { 131 struct list_head list; 132 struct capi20_appl ap; 133 u16 errcode; 134 unsigned userflags; 135 136 struct sk_buff_head recvqueue; 137 wait_queue_head_t recvwait; 138 139 struct capincci *nccis; 140 141 struct semaphore ncci_list_sem; 142 }; 143 144 /* -------- global variables ---------------------------------------- */ 145 146 static DEFINE_RWLOCK(capidev_list_lock); 147 static LIST_HEAD(capidev_list); 148 149 #ifdef CONFIG_ISDN_CAPI_MIDDLEWARE 150 static DEFINE_RWLOCK(capiminor_list_lock); 151 static LIST_HEAD(capiminor_list); 152 #endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */ 153 154 #ifdef CONFIG_ISDN_CAPI_MIDDLEWARE 155 /* -------- datahandles --------------------------------------------- */ 156 157 static int capincci_add_ack(struct capiminor *mp, u16 datahandle) 158 { 159 struct datahandle_queue *n, **pp; 160 161 n = kmalloc(sizeof(*n), GFP_ATOMIC); 162 if (!n) { 163 printk(KERN_ERR "capi: alloc datahandle failed\n"); 164 return -1; 165 } 166 n->next = NULL; 167 n->datahandle = datahandle; 168 for (pp = &mp->ackqueue; *pp; pp = &(*pp)->next) ; 169 *pp = n; 170 mp->nack++; 171 return 0; 172 } 173 174 static int capiminor_del_ack(struct capiminor *mp, u16 datahandle) 175 { 176 struct datahandle_queue **pp, *p; 177 178 for (pp = &mp->ackqueue; *pp; pp = &(*pp)->next) { 179 if ((*pp)->datahandle == datahandle) { 180 p = *pp; 181 *pp = (*pp)->next; 182 kfree(p); 183 mp->nack--; 184 return 0; 185 } 186 } 187 return -1; 188 } 189 190 static void capiminor_del_all_ack(struct capiminor *mp) 191 { 192 struct datahandle_queue **pp, *p; 193 194 pp = &mp->ackqueue; 195 while (*pp) { 196 p = *pp; 197 *pp = (*pp)->next; 198 kfree(p); 199 mp->nack--; 200 } 201 } 202 203 204 /* -------- struct capiminor ---------------------------------------- */ 205 206 static struct capiminor *capiminor_alloc(struct capi20_appl *ap, u32 ncci) 207 { 208 struct capiminor *mp, *p; 209 unsigned int minor = 0; 210 unsigned long flags; 211 212 mp = kmalloc(sizeof(*mp), GFP_ATOMIC); 213 if (!mp) { 214 printk(KERN_ERR "capi: can't alloc capiminor\n"); 215 return NULL; 216 } 217 218 memset(mp, 0, sizeof(struct capiminor)); 219 mp->ap = ap; 220 mp->ncci = ncci; 221 mp->msgid = 0; 222 atomic_set(&mp->ttyopencount,0); 223 224 skb_queue_head_init(&mp->inqueue); 225 skb_queue_head_init(&mp->outqueue); 226 227 /* Allocate the least unused minor number. 228 */ 229 write_lock_irqsave(&capiminor_list_lock, flags); 230 if (list_empty(&capiminor_list)) 231 list_add(&mp->list, &capiminor_list); 232 else { 233 list_for_each_entry(p, &capiminor_list, list) { 234 if (p->minor > minor) 235 break; 236 minor++; 237 } 238 239 if (minor < capi_ttyminors) { 240 mp->minor = minor; 241 list_add(&mp->list, p->list.prev); 242 } 243 } 244 write_unlock_irqrestore(&capiminor_list_lock, flags); 245 246 if (!(minor < capi_ttyminors)) { 247 printk(KERN_NOTICE "capi: out of minors\n"); 248 kfree(mp); 249 return NULL; 250 } 251 252 return mp; 253 } 254 255 static void capiminor_free(struct capiminor *mp) 256 { 257 unsigned long flags; 258 259 write_lock_irqsave(&capiminor_list_lock, flags); 260 list_del(&mp->list); 261 write_unlock_irqrestore(&capiminor_list_lock, flags); 262 263 if (mp->ttyskb) kfree_skb(mp->ttyskb); 264 mp->ttyskb = NULL; 265 skb_queue_purge(&mp->inqueue); 266 skb_queue_purge(&mp->outqueue); 267 capiminor_del_all_ack(mp); 268 kfree(mp); 269 } 270 271 static struct capiminor *capiminor_find(unsigned int minor) 272 { 273 struct list_head *l; 274 struct capiminor *p = NULL; 275 276 read_lock(&capiminor_list_lock); 277 list_for_each(l, &capiminor_list) { 278 p = list_entry(l, struct capiminor, list); 279 if (p->minor == minor) 280 break; 281 } 282 read_unlock(&capiminor_list_lock); 283 if (l == &capiminor_list) 284 return NULL; 285 286 return p; 287 } 288 #endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */ 289 290 /* -------- struct capincci ----------------------------------------- */ 291 292 static struct capincci *capincci_alloc(struct capidev *cdev, u32 ncci) 293 { 294 struct capincci *np, **pp; 295 #ifdef CONFIG_ISDN_CAPI_MIDDLEWARE 296 struct capiminor *mp = NULL; 297 #endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */ 298 299 np = kmalloc(sizeof(*np), GFP_ATOMIC); 300 if (!np) 301 return NULL; 302 memset(np, 0, sizeof(struct capincci)); 303 np->ncci = ncci; 304 np->cdev = cdev; 305 #ifdef CONFIG_ISDN_CAPI_MIDDLEWARE 306 mp = NULL; 307 if (cdev->userflags & CAPIFLAG_HIGHJACKING) 308 mp = np->minorp = capiminor_alloc(&cdev->ap, ncci); 309 if (mp) { 310 mp->nccip = np; 311 #ifdef _DEBUG_REFCOUNT 312 printk(KERN_DEBUG "set mp->nccip\n"); 313 #endif 314 #if defined(CONFIG_ISDN_CAPI_CAPIFS) || defined(CONFIG_ISDN_CAPI_CAPIFS_MODULE) 315 capifs_new_ncci(mp->minor, MKDEV(capi_ttymajor, mp->minor)); 316 #endif 317 } 318 #endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */ 319 for (pp=&cdev->nccis; *pp; pp = &(*pp)->next) 320 ; 321 *pp = np; 322 return np; 323 } 324 325 static void capincci_free(struct capidev *cdev, u32 ncci) 326 { 327 struct capincci *np, **pp; 328 #ifdef CONFIG_ISDN_CAPI_MIDDLEWARE 329 struct capiminor *mp; 330 #endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */ 331 332 pp=&cdev->nccis; 333 while (*pp) { 334 np = *pp; 335 if (ncci == 0xffffffff || np->ncci == ncci) { 336 *pp = (*pp)->next; 337 #ifdef CONFIG_ISDN_CAPI_MIDDLEWARE 338 if ((mp = np->minorp) != 0) { 339 #if defined(CONFIG_ISDN_CAPI_CAPIFS) || defined(CONFIG_ISDN_CAPI_CAPIFS_MODULE) 340 capifs_free_ncci(mp->minor); 341 #endif 342 if (mp->tty) { 343 mp->nccip = NULL; 344 #ifdef _DEBUG_REFCOUNT 345 printk(KERN_DEBUG "reset mp->nccip\n"); 346 #endif 347 tty_hangup(mp->tty); 348 } else { 349 capiminor_free(mp); 350 } 351 } 352 #endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */ 353 kfree(np); 354 if (*pp == 0) return; 355 } else { 356 pp = &(*pp)->next; 357 } 358 } 359 } 360 361 static struct capincci *capincci_find(struct capidev *cdev, u32 ncci) 362 { 363 struct capincci *p; 364 365 for (p=cdev->nccis; p ; p = p->next) { 366 if (p->ncci == ncci) 367 break; 368 } 369 return p; 370 } 371 372 /* -------- struct capidev ------------------------------------------ */ 373 374 static struct capidev *capidev_alloc(void) 375 { 376 struct capidev *cdev; 377 unsigned long flags; 378 379 cdev = kmalloc(sizeof(*cdev), GFP_KERNEL); 380 if (!cdev) 381 return NULL; 382 memset(cdev, 0, sizeof(struct capidev)); 383 384 init_MUTEX(&cdev->ncci_list_sem); 385 skb_queue_head_init(&cdev->recvqueue); 386 init_waitqueue_head(&cdev->recvwait); 387 write_lock_irqsave(&capidev_list_lock, flags); 388 list_add_tail(&cdev->list, &capidev_list); 389 write_unlock_irqrestore(&capidev_list_lock, flags); 390 return cdev; 391 } 392 393 static void capidev_free(struct capidev *cdev) 394 { 395 unsigned long flags; 396 397 if (cdev->ap.applid) { 398 capi20_release(&cdev->ap); 399 cdev->ap.applid = 0; 400 } 401 skb_queue_purge(&cdev->recvqueue); 402 403 down(&cdev->ncci_list_sem); 404 capincci_free(cdev, 0xffffffff); 405 up(&cdev->ncci_list_sem); 406 407 write_lock_irqsave(&capidev_list_lock, flags); 408 list_del(&cdev->list); 409 write_unlock_irqrestore(&capidev_list_lock, flags); 410 kfree(cdev); 411 } 412 413 #ifdef CONFIG_ISDN_CAPI_MIDDLEWARE 414 /* -------- handle data queue --------------------------------------- */ 415 416 static struct sk_buff * 417 gen_data_b3_resp_for(struct capiminor *mp, struct sk_buff *skb) 418 { 419 struct sk_buff *nskb; 420 nskb = alloc_skb(CAPI_DATA_B3_RESP_LEN, GFP_ATOMIC); 421 if (nskb) { 422 u16 datahandle = CAPIMSG_U16(skb->data,CAPIMSG_BASELEN+4+4+2); 423 unsigned char *s = skb_put(nskb, CAPI_DATA_B3_RESP_LEN); 424 capimsg_setu16(s, 0, CAPI_DATA_B3_RESP_LEN); 425 capimsg_setu16(s, 2, mp->ap->applid); 426 capimsg_setu8 (s, 4, CAPI_DATA_B3); 427 capimsg_setu8 (s, 5, CAPI_RESP); 428 capimsg_setu16(s, 6, mp->msgid++); 429 capimsg_setu32(s, 8, mp->ncci); 430 capimsg_setu16(s, 12, datahandle); 431 } 432 return nskb; 433 } 434 435 static int handle_recv_skb(struct capiminor *mp, struct sk_buff *skb) 436 { 437 struct sk_buff *nskb; 438 int datalen; 439 u16 errcode, datahandle; 440 struct tty_ldisc *ld; 441 442 datalen = skb->len - CAPIMSG_LEN(skb->data); 443 if (mp->tty == NULL) 444 { 445 #ifdef _DEBUG_DATAFLOW 446 printk(KERN_DEBUG "capi: currently no receiver\n"); 447 #endif 448 return -1; 449 } 450 451 ld = tty_ldisc_ref(mp->tty); 452 if (ld == NULL) 453 return -1; 454 if (ld->receive_buf == NULL) { 455 #if defined(_DEBUG_DATAFLOW) || defined(_DEBUG_TTYFUNCS) 456 printk(KERN_DEBUG "capi: ldisc has no receive_buf function\n"); 457 #endif 458 goto bad; 459 } 460 if (mp->ttyinstop) { 461 #if defined(_DEBUG_DATAFLOW) || defined(_DEBUG_TTYFUNCS) 462 printk(KERN_DEBUG "capi: recv tty throttled\n"); 463 #endif 464 goto bad; 465 } 466 if (mp->tty->receive_room < datalen) { 467 #if defined(_DEBUG_DATAFLOW) || defined(_DEBUG_TTYFUNCS) 468 printk(KERN_DEBUG "capi: no room in tty\n"); 469 #endif 470 goto bad; 471 } 472 if ((nskb = gen_data_b3_resp_for(mp, skb)) == 0) { 473 printk(KERN_ERR "capi: gen_data_b3_resp failed\n"); 474 goto bad; 475 } 476 datahandle = CAPIMSG_U16(skb->data,CAPIMSG_BASELEN+4); 477 errcode = capi20_put_message(mp->ap, nskb); 478 if (errcode != CAPI_NOERROR) { 479 printk(KERN_ERR "capi: send DATA_B3_RESP failed=%x\n", 480 errcode); 481 kfree_skb(nskb); 482 goto bad; 483 } 484 (void)skb_pull(skb, CAPIMSG_LEN(skb->data)); 485 #ifdef _DEBUG_DATAFLOW 486 printk(KERN_DEBUG "capi: DATA_B3_RESP %u len=%d => ldisc\n", 487 datahandle, skb->len); 488 #endif 489 ld->receive_buf(mp->tty, skb->data, NULL, skb->len); 490 kfree_skb(skb); 491 tty_ldisc_deref(ld); 492 return 0; 493 bad: 494 tty_ldisc_deref(ld); 495 return -1; 496 } 497 498 static void handle_minor_recv(struct capiminor *mp) 499 { 500 struct sk_buff *skb; 501 while ((skb = skb_dequeue(&mp->inqueue)) != 0) { 502 unsigned int len = skb->len; 503 mp->inbytes -= len; 504 if (handle_recv_skb(mp, skb) < 0) { 505 skb_queue_head(&mp->inqueue, skb); 506 mp->inbytes += len; 507 return; 508 } 509 } 510 } 511 512 static int handle_minor_send(struct capiminor *mp) 513 { 514 struct sk_buff *skb; 515 u16 len; 516 int count = 0; 517 u16 errcode; 518 u16 datahandle; 519 520 if (mp->tty && mp->ttyoutstop) { 521 #if defined(_DEBUG_DATAFLOW) || defined(_DEBUG_TTYFUNCS) 522 printk(KERN_DEBUG "capi: send: tty stopped\n"); 523 #endif 524 return 0; 525 } 526 527 while ((skb = skb_dequeue(&mp->outqueue)) != 0) { 528 datahandle = mp->datahandle; 529 len = (u16)skb->len; 530 skb_push(skb, CAPI_DATA_B3_REQ_LEN); 531 memset(skb->data, 0, CAPI_DATA_B3_REQ_LEN); 532 capimsg_setu16(skb->data, 0, CAPI_DATA_B3_REQ_LEN); 533 capimsg_setu16(skb->data, 2, mp->ap->applid); 534 capimsg_setu8 (skb->data, 4, CAPI_DATA_B3); 535 capimsg_setu8 (skb->data, 5, CAPI_REQ); 536 capimsg_setu16(skb->data, 6, mp->msgid++); 537 capimsg_setu32(skb->data, 8, mp->ncci); /* NCCI */ 538 capimsg_setu32(skb->data, 12, (u32) skb->data); /* Data32 */ 539 capimsg_setu16(skb->data, 16, len); /* Data length */ 540 capimsg_setu16(skb->data, 18, datahandle); 541 capimsg_setu16(skb->data, 20, 0); /* Flags */ 542 543 if (capincci_add_ack(mp, datahandle) < 0) { 544 skb_pull(skb, CAPI_DATA_B3_REQ_LEN); 545 skb_queue_head(&mp->outqueue, skb); 546 return count; 547 } 548 errcode = capi20_put_message(mp->ap, skb); 549 if (errcode == CAPI_NOERROR) { 550 mp->datahandle++; 551 count++; 552 mp->outbytes -= len; 553 #ifdef _DEBUG_DATAFLOW 554 printk(KERN_DEBUG "capi: DATA_B3_REQ %u len=%u\n", 555 datahandle, len); 556 #endif 557 continue; 558 } 559 capiminor_del_ack(mp, datahandle); 560 561 if (errcode == CAPI_SENDQUEUEFULL) { 562 skb_pull(skb, CAPI_DATA_B3_REQ_LEN); 563 skb_queue_head(&mp->outqueue, skb); 564 break; 565 } 566 567 /* ups, drop packet */ 568 printk(KERN_ERR "capi: put_message = %x\n", errcode); 569 mp->outbytes -= len; 570 kfree_skb(skb); 571 } 572 return count; 573 } 574 575 #endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */ 576 /* -------- function called by lower level -------------------------- */ 577 578 static void capi_recv_message(struct capi20_appl *ap, struct sk_buff *skb) 579 { 580 struct capidev *cdev = ap->private; 581 #ifdef CONFIG_ISDN_CAPI_MIDDLEWARE 582 struct capiminor *mp; 583 u16 datahandle; 584 #endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */ 585 struct capincci *np; 586 u32 ncci; 587 588 if (CAPIMSG_CMD(skb->data) == CAPI_CONNECT_B3_CONF) { 589 u16 info = CAPIMSG_U16(skb->data, 12); // Info field 590 if (info == 0) { 591 down(&cdev->ncci_list_sem); 592 capincci_alloc(cdev, CAPIMSG_NCCI(skb->data)); 593 up(&cdev->ncci_list_sem); 594 } 595 } 596 if (CAPIMSG_CMD(skb->data) == CAPI_CONNECT_B3_IND) { 597 down(&cdev->ncci_list_sem); 598 capincci_alloc(cdev, CAPIMSG_NCCI(skb->data)); 599 up(&cdev->ncci_list_sem); 600 } 601 if (CAPIMSG_COMMAND(skb->data) != CAPI_DATA_B3) { 602 skb_queue_tail(&cdev->recvqueue, skb); 603 wake_up_interruptible(&cdev->recvwait); 604 return; 605 } 606 ncci = CAPIMSG_CONTROL(skb->data); 607 for (np = cdev->nccis; np && np->ncci != ncci; np = np->next) 608 ; 609 if (!np) { 610 printk(KERN_ERR "BUG: capi_signal: ncci not found\n"); 611 skb_queue_tail(&cdev->recvqueue, skb); 612 wake_up_interruptible(&cdev->recvwait); 613 return; 614 } 615 #ifndef CONFIG_ISDN_CAPI_MIDDLEWARE 616 skb_queue_tail(&cdev->recvqueue, skb); 617 wake_up_interruptible(&cdev->recvwait); 618 #else /* CONFIG_ISDN_CAPI_MIDDLEWARE */ 619 mp = np->minorp; 620 if (!mp) { 621 skb_queue_tail(&cdev->recvqueue, skb); 622 wake_up_interruptible(&cdev->recvwait); 623 return; 624 } 625 626 627 if (CAPIMSG_SUBCOMMAND(skb->data) == CAPI_IND) { 628 629 datahandle = CAPIMSG_U16(skb->data, CAPIMSG_BASELEN+4+4+2); 630 #ifdef _DEBUG_DATAFLOW 631 printk(KERN_DEBUG "capi_signal: DATA_B3_IND %u len=%d\n", 632 datahandle, skb->len-CAPIMSG_LEN(skb->data)); 633 #endif 634 skb_queue_tail(&mp->inqueue, skb); 635 mp->inbytes += skb->len; 636 handle_minor_recv(mp); 637 638 } else if (CAPIMSG_SUBCOMMAND(skb->data) == CAPI_CONF) { 639 640 datahandle = CAPIMSG_U16(skb->data, CAPIMSG_BASELEN+4); 641 #ifdef _DEBUG_DATAFLOW 642 printk(KERN_DEBUG "capi_signal: DATA_B3_CONF %u 0x%x\n", 643 datahandle, 644 CAPIMSG_U16(skb->data, CAPIMSG_BASELEN+4+2)); 645 #endif 646 kfree_skb(skb); 647 (void)capiminor_del_ack(mp, datahandle); 648 if (mp->tty) 649 tty_wakeup(mp->tty); 650 (void)handle_minor_send(mp); 651 652 } else { 653 /* ups, let capi application handle it :-) */ 654 skb_queue_tail(&cdev->recvqueue, skb); 655 wake_up_interruptible(&cdev->recvwait); 656 } 657 #endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */ 658 } 659 660 /* -------- file_operations for capidev ----------------------------- */ 661 662 static ssize_t 663 capi_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) 664 { 665 struct capidev *cdev = (struct capidev *)file->private_data; 666 struct sk_buff *skb; 667 size_t copied; 668 669 if (!cdev->ap.applid) 670 return -ENODEV; 671 672 if ((skb = skb_dequeue(&cdev->recvqueue)) == 0) { 673 674 if (file->f_flags & O_NONBLOCK) 675 return -EAGAIN; 676 677 for (;;) { 678 interruptible_sleep_on(&cdev->recvwait); 679 if ((skb = skb_dequeue(&cdev->recvqueue)) != 0) 680 break; 681 if (signal_pending(current)) 682 break; 683 } 684 if (skb == 0) 685 return -ERESTARTNOHAND; 686 } 687 if (skb->len > count) { 688 skb_queue_head(&cdev->recvqueue, skb); 689 return -EMSGSIZE; 690 } 691 if (copy_to_user(buf, skb->data, skb->len)) { 692 skb_queue_head(&cdev->recvqueue, skb); 693 return -EFAULT; 694 } 695 copied = skb->len; 696 697 kfree_skb(skb); 698 699 return copied; 700 } 701 702 static ssize_t 703 capi_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) 704 { 705 struct capidev *cdev = (struct capidev *)file->private_data; 706 struct sk_buff *skb; 707 u16 mlen; 708 709 if (!cdev->ap.applid) 710 return -ENODEV; 711 712 skb = alloc_skb(count, GFP_USER); 713 if (!skb) 714 return -ENOMEM; 715 716 if (copy_from_user(skb_put(skb, count), buf, count)) { 717 kfree_skb(skb); 718 return -EFAULT; 719 } 720 mlen = CAPIMSG_LEN(skb->data); 721 if (CAPIMSG_CMD(skb->data) == CAPI_DATA_B3_REQ) { 722 if ((size_t)(mlen + CAPIMSG_DATALEN(skb->data)) != count) { 723 kfree_skb(skb); 724 return -EINVAL; 725 } 726 } else { 727 if (mlen != count) { 728 kfree_skb(skb); 729 return -EINVAL; 730 } 731 } 732 CAPIMSG_SETAPPID(skb->data, cdev->ap.applid); 733 734 if (CAPIMSG_CMD(skb->data) == CAPI_DISCONNECT_B3_RESP) { 735 down(&cdev->ncci_list_sem); 736 capincci_free(cdev, CAPIMSG_NCCI(skb->data)); 737 up(&cdev->ncci_list_sem); 738 } 739 740 cdev->errcode = capi20_put_message(&cdev->ap, skb); 741 742 if (cdev->errcode) { 743 kfree_skb(skb); 744 return -EIO; 745 } 746 return count; 747 } 748 749 static unsigned int 750 capi_poll(struct file *file, poll_table * wait) 751 { 752 struct capidev *cdev = (struct capidev *)file->private_data; 753 unsigned int mask = 0; 754 755 if (!cdev->ap.applid) 756 return POLLERR; 757 758 poll_wait(file, &(cdev->recvwait), wait); 759 mask = POLLOUT | POLLWRNORM; 760 if (!skb_queue_empty(&cdev->recvqueue)) 761 mask |= POLLIN | POLLRDNORM; 762 return mask; 763 } 764 765 static int 766 capi_ioctl(struct inode *inode, struct file *file, 767 unsigned int cmd, unsigned long arg) 768 { 769 struct capidev *cdev = file->private_data; 770 struct capi20_appl *ap = &cdev->ap; 771 capi_ioctl_struct data; 772 int retval = -EINVAL; 773 void __user *argp = (void __user *)arg; 774 775 switch (cmd) { 776 case CAPI_REGISTER: 777 { 778 if (ap->applid) 779 return -EEXIST; 780 781 if (copy_from_user(&cdev->ap.rparam, argp, 782 sizeof(struct capi_register_params))) 783 return -EFAULT; 784 785 cdev->ap.private = cdev; 786 cdev->ap.recv_message = capi_recv_message; 787 cdev->errcode = capi20_register(ap); 788 if (cdev->errcode) { 789 ap->applid = 0; 790 return -EIO; 791 } 792 } 793 return (int)ap->applid; 794 795 case CAPI_GET_VERSION: 796 { 797 if (copy_from_user(&data.contr, argp, 798 sizeof(data.contr))) 799 return -EFAULT; 800 cdev->errcode = capi20_get_version(data.contr, &data.version); 801 if (cdev->errcode) 802 return -EIO; 803 if (copy_to_user(argp, &data.version, 804 sizeof(data.version))) 805 return -EFAULT; 806 } 807 return 0; 808 809 case CAPI_GET_SERIAL: 810 { 811 if (copy_from_user(&data.contr, argp, 812 sizeof(data.contr))) 813 return -EFAULT; 814 cdev->errcode = capi20_get_serial (data.contr, data.serial); 815 if (cdev->errcode) 816 return -EIO; 817 if (copy_to_user(argp, data.serial, 818 sizeof(data.serial))) 819 return -EFAULT; 820 } 821 return 0; 822 case CAPI_GET_PROFILE: 823 { 824 if (copy_from_user(&data.contr, argp, 825 sizeof(data.contr))) 826 return -EFAULT; 827 828 if (data.contr == 0) { 829 cdev->errcode = capi20_get_profile(data.contr, &data.profile); 830 if (cdev->errcode) 831 return -EIO; 832 833 retval = copy_to_user(argp, 834 &data.profile.ncontroller, 835 sizeof(data.profile.ncontroller)); 836 837 } else { 838 cdev->errcode = capi20_get_profile(data.contr, &data.profile); 839 if (cdev->errcode) 840 return -EIO; 841 842 retval = copy_to_user(argp, &data.profile, 843 sizeof(data.profile)); 844 } 845 if (retval) 846 return -EFAULT; 847 } 848 return 0; 849 850 case CAPI_GET_MANUFACTURER: 851 { 852 if (copy_from_user(&data.contr, argp, 853 sizeof(data.contr))) 854 return -EFAULT; 855 cdev->errcode = capi20_get_manufacturer(data.contr, data.manufacturer); 856 if (cdev->errcode) 857 return -EIO; 858 859 if (copy_to_user(argp, data.manufacturer, 860 sizeof(data.manufacturer))) 861 return -EFAULT; 862 863 } 864 return 0; 865 case CAPI_GET_ERRCODE: 866 data.errcode = cdev->errcode; 867 cdev->errcode = CAPI_NOERROR; 868 if (arg) { 869 if (copy_to_user(argp, &data.errcode, 870 sizeof(data.errcode))) 871 return -EFAULT; 872 } 873 return data.errcode; 874 875 case CAPI_INSTALLED: 876 if (capi20_isinstalled() == CAPI_NOERROR) 877 return 0; 878 return -ENXIO; 879 880 case CAPI_MANUFACTURER_CMD: 881 { 882 struct capi_manufacturer_cmd mcmd; 883 if (!capable(CAP_SYS_ADMIN)) 884 return -EPERM; 885 if (copy_from_user(&mcmd, argp, sizeof(mcmd))) 886 return -EFAULT; 887 return capi20_manufacturer(mcmd.cmd, mcmd.data); 888 } 889 return 0; 890 891 case CAPI_SET_FLAGS: 892 case CAPI_CLR_FLAGS: 893 { 894 unsigned userflags; 895 if (copy_from_user(&userflags, argp, 896 sizeof(userflags))) 897 return -EFAULT; 898 if (cmd == CAPI_SET_FLAGS) 899 cdev->userflags |= userflags; 900 else 901 cdev->userflags &= ~userflags; 902 } 903 return 0; 904 905 case CAPI_GET_FLAGS: 906 if (copy_to_user(argp, &cdev->userflags, 907 sizeof(cdev->userflags))) 908 return -EFAULT; 909 return 0; 910 911 case CAPI_NCCI_OPENCOUNT: 912 { 913 struct capincci *nccip; 914 #ifdef CONFIG_ISDN_CAPI_MIDDLEWARE 915 struct capiminor *mp; 916 #endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */ 917 unsigned ncci; 918 int count = 0; 919 if (copy_from_user(&ncci, argp, sizeof(ncci))) 920 return -EFAULT; 921 922 down(&cdev->ncci_list_sem); 923 if ((nccip = capincci_find(cdev, (u32) ncci)) == 0) { 924 up(&cdev->ncci_list_sem); 925 return 0; 926 } 927 #ifdef CONFIG_ISDN_CAPI_MIDDLEWARE 928 if ((mp = nccip->minorp) != 0) { 929 count += atomic_read(&mp->ttyopencount); 930 } 931 #endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */ 932 up(&cdev->ncci_list_sem); 933 return count; 934 } 935 return 0; 936 937 #ifdef CONFIG_ISDN_CAPI_MIDDLEWARE 938 case CAPI_NCCI_GETUNIT: 939 { 940 struct capincci *nccip; 941 struct capiminor *mp; 942 unsigned ncci; 943 int unit = 0; 944 if (copy_from_user(&ncci, argp, 945 sizeof(ncci))) 946 return -EFAULT; 947 down(&cdev->ncci_list_sem); 948 nccip = capincci_find(cdev, (u32) ncci); 949 if (!nccip || (mp = nccip->minorp) == 0) { 950 up(&cdev->ncci_list_sem); 951 return -ESRCH; 952 } 953 unit = mp->minor; 954 up(&cdev->ncci_list_sem); 955 return unit; 956 } 957 return 0; 958 #endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */ 959 } 960 return -EINVAL; 961 } 962 963 static int 964 capi_open(struct inode *inode, struct file *file) 965 { 966 if (file->private_data) 967 return -EEXIST; 968 969 if ((file->private_data = capidev_alloc()) == 0) 970 return -ENOMEM; 971 972 return nonseekable_open(inode, file); 973 } 974 975 static int 976 capi_release(struct inode *inode, struct file *file) 977 { 978 struct capidev *cdev = (struct capidev *)file->private_data; 979 980 capidev_free(cdev); 981 file->private_data = NULL; 982 983 return 0; 984 } 985 986 static struct file_operations capi_fops = 987 { 988 .owner = THIS_MODULE, 989 .llseek = no_llseek, 990 .read = capi_read, 991 .write = capi_write, 992 .poll = capi_poll, 993 .ioctl = capi_ioctl, 994 .open = capi_open, 995 .release = capi_release, 996 }; 997 998 #ifdef CONFIG_ISDN_CAPI_MIDDLEWARE 999 /* -------- tty_operations for capincci ----------------------------- */ 1000 1001 static int capinc_tty_open(struct tty_struct * tty, struct file * file) 1002 { 1003 struct capiminor *mp; 1004 1005 if ((mp = capiminor_find(iminor(file->f_dentry->d_inode))) == 0) 1006 return -ENXIO; 1007 if (mp->nccip == 0) 1008 return -ENXIO; 1009 1010 tty->driver_data = (void *)mp; 1011 1012 if (atomic_read(&mp->ttyopencount) == 0) 1013 mp->tty = tty; 1014 atomic_inc(&mp->ttyopencount); 1015 #ifdef _DEBUG_REFCOUNT 1016 printk(KERN_DEBUG "capinc_tty_open ocount=%d\n", atomic_read(&mp->ttyopencount)); 1017 #endif 1018 handle_minor_recv(mp); 1019 return 0; 1020 } 1021 1022 static void capinc_tty_close(struct tty_struct * tty, struct file * file) 1023 { 1024 struct capiminor *mp; 1025 1026 mp = (struct capiminor *)tty->driver_data; 1027 if (mp) { 1028 if (atomic_dec_and_test(&mp->ttyopencount)) { 1029 #ifdef _DEBUG_REFCOUNT 1030 printk(KERN_DEBUG "capinc_tty_close lastclose\n"); 1031 #endif 1032 tty->driver_data = NULL; 1033 mp->tty = NULL; 1034 } 1035 #ifdef _DEBUG_REFCOUNT 1036 printk(KERN_DEBUG "capinc_tty_close ocount=%d\n", atomic_read(&mp->ttyopencount)); 1037 #endif 1038 if (mp->nccip == 0) 1039 capiminor_free(mp); 1040 } 1041 1042 #ifdef _DEBUG_REFCOUNT 1043 printk(KERN_DEBUG "capinc_tty_close\n"); 1044 #endif 1045 } 1046 1047 static int capinc_tty_write(struct tty_struct * tty, 1048 const unsigned char *buf, int count) 1049 { 1050 struct capiminor *mp = (struct capiminor *)tty->driver_data; 1051 struct sk_buff *skb; 1052 1053 #ifdef _DEBUG_TTYFUNCS 1054 printk(KERN_DEBUG "capinc_tty_write(count=%d)\n", count); 1055 #endif 1056 1057 if (!mp || !mp->nccip) { 1058 #ifdef _DEBUG_TTYFUNCS 1059 printk(KERN_DEBUG "capinc_tty_write: mp or mp->ncci NULL\n"); 1060 #endif 1061 return 0; 1062 } 1063 1064 skb = mp->ttyskb; 1065 if (skb) { 1066 mp->ttyskb = NULL; 1067 skb_queue_tail(&mp->outqueue, skb); 1068 mp->outbytes += skb->len; 1069 } 1070 1071 skb = alloc_skb(CAPI_DATA_B3_REQ_LEN+count, GFP_ATOMIC); 1072 if (!skb) { 1073 printk(KERN_ERR "capinc_tty_write: alloc_skb failed\n"); 1074 return -ENOMEM; 1075 } 1076 1077 skb_reserve(skb, CAPI_DATA_B3_REQ_LEN); 1078 memcpy(skb_put(skb, count), buf, count); 1079 1080 skb_queue_tail(&mp->outqueue, skb); 1081 mp->outbytes += skb->len; 1082 (void)handle_minor_send(mp); 1083 (void)handle_minor_recv(mp); 1084 return count; 1085 } 1086 1087 static void capinc_tty_put_char(struct tty_struct *tty, unsigned char ch) 1088 { 1089 struct capiminor *mp = (struct capiminor *)tty->driver_data; 1090 struct sk_buff *skb; 1091 1092 #ifdef _DEBUG_TTYFUNCS 1093 printk(KERN_DEBUG "capinc_put_char(%u)\n", ch); 1094 #endif 1095 1096 if (!mp || !mp->nccip) { 1097 #ifdef _DEBUG_TTYFUNCS 1098 printk(KERN_DEBUG "capinc_tty_put_char: mp or mp->ncci NULL\n"); 1099 #endif 1100 return; 1101 } 1102 1103 skb = mp->ttyskb; 1104 if (skb) { 1105 if (skb_tailroom(skb) > 0) { 1106 *(skb_put(skb, 1)) = ch; 1107 return; 1108 } 1109 mp->ttyskb = NULL; 1110 skb_queue_tail(&mp->outqueue, skb); 1111 mp->outbytes += skb->len; 1112 (void)handle_minor_send(mp); 1113 } 1114 skb = alloc_skb(CAPI_DATA_B3_REQ_LEN+CAPI_MAX_BLKSIZE, GFP_ATOMIC); 1115 if (skb) { 1116 skb_reserve(skb, CAPI_DATA_B3_REQ_LEN); 1117 *(skb_put(skb, 1)) = ch; 1118 mp->ttyskb = skb; 1119 } else { 1120 printk(KERN_ERR "capinc_put_char: char %u lost\n", ch); 1121 } 1122 } 1123 1124 static void capinc_tty_flush_chars(struct tty_struct *tty) 1125 { 1126 struct capiminor *mp = (struct capiminor *)tty->driver_data; 1127 struct sk_buff *skb; 1128 1129 #ifdef _DEBUG_TTYFUNCS 1130 printk(KERN_DEBUG "capinc_tty_flush_chars\n"); 1131 #endif 1132 1133 if (!mp || !mp->nccip) { 1134 #ifdef _DEBUG_TTYFUNCS 1135 printk(KERN_DEBUG "capinc_tty_flush_chars: mp or mp->ncci NULL\n"); 1136 #endif 1137 return; 1138 } 1139 1140 skb = mp->ttyskb; 1141 if (skb) { 1142 mp->ttyskb = NULL; 1143 skb_queue_tail(&mp->outqueue, skb); 1144 mp->outbytes += skb->len; 1145 (void)handle_minor_send(mp); 1146 } 1147 (void)handle_minor_recv(mp); 1148 } 1149 1150 static int capinc_tty_write_room(struct tty_struct *tty) 1151 { 1152 struct capiminor *mp = (struct capiminor *)tty->driver_data; 1153 int room; 1154 if (!mp || !mp->nccip) { 1155 #ifdef _DEBUG_TTYFUNCS 1156 printk(KERN_DEBUG "capinc_tty_write_room: mp or mp->ncci NULL\n"); 1157 #endif 1158 return 0; 1159 } 1160 room = CAPINC_MAX_SENDQUEUE-skb_queue_len(&mp->outqueue); 1161 room *= CAPI_MAX_BLKSIZE; 1162 #ifdef _DEBUG_TTYFUNCS 1163 printk(KERN_DEBUG "capinc_tty_write_room = %d\n", room); 1164 #endif 1165 return room; 1166 } 1167 1168 static int capinc_tty_chars_in_buffer(struct tty_struct *tty) 1169 { 1170 struct capiminor *mp = (struct capiminor *)tty->driver_data; 1171 if (!mp || !mp->nccip) { 1172 #ifdef _DEBUG_TTYFUNCS 1173 printk(KERN_DEBUG "capinc_tty_chars_in_buffer: mp or mp->ncci NULL\n"); 1174 #endif 1175 return 0; 1176 } 1177 #ifdef _DEBUG_TTYFUNCS 1178 printk(KERN_DEBUG "capinc_tty_chars_in_buffer = %d nack=%d sq=%d rq=%d\n", 1179 mp->outbytes, mp->nack, 1180 skb_queue_len(&mp->outqueue), 1181 skb_queue_len(&mp->inqueue)); 1182 #endif 1183 return mp->outbytes; 1184 } 1185 1186 static int capinc_tty_ioctl(struct tty_struct *tty, struct file * file, 1187 unsigned int cmd, unsigned long arg) 1188 { 1189 int error = 0; 1190 switch (cmd) { 1191 default: 1192 error = n_tty_ioctl (tty, file, cmd, arg); 1193 break; 1194 } 1195 return error; 1196 } 1197 1198 static void capinc_tty_set_termios(struct tty_struct *tty, struct termios * old) 1199 { 1200 #ifdef _DEBUG_TTYFUNCS 1201 printk(KERN_DEBUG "capinc_tty_set_termios\n"); 1202 #endif 1203 } 1204 1205 static void capinc_tty_throttle(struct tty_struct * tty) 1206 { 1207 struct capiminor *mp = (struct capiminor *)tty->driver_data; 1208 #ifdef _DEBUG_TTYFUNCS 1209 printk(KERN_DEBUG "capinc_tty_throttle\n"); 1210 #endif 1211 if (mp) 1212 mp->ttyinstop = 1; 1213 } 1214 1215 static void capinc_tty_unthrottle(struct tty_struct * tty) 1216 { 1217 struct capiminor *mp = (struct capiminor *)tty->driver_data; 1218 #ifdef _DEBUG_TTYFUNCS 1219 printk(KERN_DEBUG "capinc_tty_unthrottle\n"); 1220 #endif 1221 if (mp) { 1222 mp->ttyinstop = 0; 1223 handle_minor_recv(mp); 1224 } 1225 } 1226 1227 static void capinc_tty_stop(struct tty_struct *tty) 1228 { 1229 struct capiminor *mp = (struct capiminor *)tty->driver_data; 1230 #ifdef _DEBUG_TTYFUNCS 1231 printk(KERN_DEBUG "capinc_tty_stop\n"); 1232 #endif 1233 if (mp) { 1234 mp->ttyoutstop = 1; 1235 } 1236 } 1237 1238 static void capinc_tty_start(struct tty_struct *tty) 1239 { 1240 struct capiminor *mp = (struct capiminor *)tty->driver_data; 1241 #ifdef _DEBUG_TTYFUNCS 1242 printk(KERN_DEBUG "capinc_tty_start\n"); 1243 #endif 1244 if (mp) { 1245 mp->ttyoutstop = 0; 1246 (void)handle_minor_send(mp); 1247 } 1248 } 1249 1250 static void capinc_tty_hangup(struct tty_struct *tty) 1251 { 1252 #ifdef _DEBUG_TTYFUNCS 1253 printk(KERN_DEBUG "capinc_tty_hangup\n"); 1254 #endif 1255 } 1256 1257 static void capinc_tty_break_ctl(struct tty_struct *tty, int state) 1258 { 1259 #ifdef _DEBUG_TTYFUNCS 1260 printk(KERN_DEBUG "capinc_tty_break_ctl(%d)\n", state); 1261 #endif 1262 } 1263 1264 static void capinc_tty_flush_buffer(struct tty_struct *tty) 1265 { 1266 #ifdef _DEBUG_TTYFUNCS 1267 printk(KERN_DEBUG "capinc_tty_flush_buffer\n"); 1268 #endif 1269 } 1270 1271 static void capinc_tty_set_ldisc(struct tty_struct *tty) 1272 { 1273 #ifdef _DEBUG_TTYFUNCS 1274 printk(KERN_DEBUG "capinc_tty_set_ldisc\n"); 1275 #endif 1276 } 1277 1278 static void capinc_tty_send_xchar(struct tty_struct *tty, char ch) 1279 { 1280 #ifdef _DEBUG_TTYFUNCS 1281 printk(KERN_DEBUG "capinc_tty_send_xchar(%d)\n", ch); 1282 #endif 1283 } 1284 1285 static int capinc_tty_read_proc(char *page, char **start, off_t off, 1286 int count, int *eof, void *data) 1287 { 1288 return 0; 1289 } 1290 1291 static struct tty_driver *capinc_tty_driver; 1292 1293 static struct tty_operations capinc_ops = { 1294 .open = capinc_tty_open, 1295 .close = capinc_tty_close, 1296 .write = capinc_tty_write, 1297 .put_char = capinc_tty_put_char, 1298 .flush_chars = capinc_tty_flush_chars, 1299 .write_room = capinc_tty_write_room, 1300 .chars_in_buffer = capinc_tty_chars_in_buffer, 1301 .ioctl = capinc_tty_ioctl, 1302 .set_termios = capinc_tty_set_termios, 1303 .throttle = capinc_tty_throttle, 1304 .unthrottle = capinc_tty_unthrottle, 1305 .stop = capinc_tty_stop, 1306 .start = capinc_tty_start, 1307 .hangup = capinc_tty_hangup, 1308 .break_ctl = capinc_tty_break_ctl, 1309 .flush_buffer = capinc_tty_flush_buffer, 1310 .set_ldisc = capinc_tty_set_ldisc, 1311 .send_xchar = capinc_tty_send_xchar, 1312 .read_proc = capinc_tty_read_proc, 1313 }; 1314 1315 static int capinc_tty_init(void) 1316 { 1317 struct tty_driver *drv; 1318 1319 if (capi_ttyminors > CAPINC_MAX_PORTS) 1320 capi_ttyminors = CAPINC_MAX_PORTS; 1321 if (capi_ttyminors <= 0) 1322 capi_ttyminors = CAPINC_NR_PORTS; 1323 1324 drv = alloc_tty_driver(capi_ttyminors); 1325 if (!drv) 1326 return -ENOMEM; 1327 1328 drv->owner = THIS_MODULE; 1329 drv->driver_name = "capi_nc"; 1330 drv->devfs_name = "capi/"; 1331 drv->name = "capi"; 1332 drv->major = capi_ttymajor; 1333 drv->minor_start = 0; 1334 drv->type = TTY_DRIVER_TYPE_SERIAL; 1335 drv->subtype = SERIAL_TYPE_NORMAL; 1336 drv->init_termios = tty_std_termios; 1337 drv->init_termios.c_iflag = ICRNL; 1338 drv->init_termios.c_oflag = OPOST | ONLCR; 1339 drv->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL; 1340 drv->init_termios.c_lflag = 0; 1341 drv->flags = TTY_DRIVER_REAL_RAW|TTY_DRIVER_RESET_TERMIOS; 1342 tty_set_operations(drv, &capinc_ops); 1343 if (tty_register_driver(drv)) { 1344 put_tty_driver(drv); 1345 printk(KERN_ERR "Couldn't register capi_nc driver\n"); 1346 return -1; 1347 } 1348 capinc_tty_driver = drv; 1349 return 0; 1350 } 1351 1352 static void capinc_tty_exit(void) 1353 { 1354 struct tty_driver *drv = capinc_tty_driver; 1355 int retval; 1356 if ((retval = tty_unregister_driver(drv))) 1357 printk(KERN_ERR "capi: failed to unregister capi_nc driver (%d)\n", retval); 1358 put_tty_driver(drv); 1359 } 1360 1361 #endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */ 1362 1363 /* -------- /proc functions ----------------------------------------- */ 1364 1365 /* 1366 * /proc/capi/capi20: 1367 * minor applid nrecvctlpkt nrecvdatapkt nsendctlpkt nsenddatapkt 1368 */ 1369 static int proc_capidev_read_proc(char *page, char **start, off_t off, 1370 int count, int *eof, void *data) 1371 { 1372 struct capidev *cdev; 1373 struct list_head *l; 1374 int len = 0; 1375 1376 read_lock(&capidev_list_lock); 1377 list_for_each(l, &capidev_list) { 1378 cdev = list_entry(l, struct capidev, list); 1379 len += sprintf(page+len, "0 %d %lu %lu %lu %lu\n", 1380 cdev->ap.applid, 1381 cdev->ap.nrecvctlpkt, 1382 cdev->ap.nrecvdatapkt, 1383 cdev->ap.nsentctlpkt, 1384 cdev->ap.nsentdatapkt); 1385 if (len <= off) { 1386 off -= len; 1387 len = 0; 1388 } else { 1389 if (len-off > count) 1390 goto endloop; 1391 } 1392 } 1393 1394 endloop: 1395 read_unlock(&capidev_list_lock); 1396 if (len < count) 1397 *eof = 1; 1398 if (len > count) len = count; 1399 if (len < 0) len = 0; 1400 return len; 1401 } 1402 1403 /* 1404 * /proc/capi/capi20ncci: 1405 * applid ncci 1406 */ 1407 static int proc_capincci_read_proc(char *page, char **start, off_t off, 1408 int count, int *eof, void *data) 1409 { 1410 struct capidev *cdev; 1411 struct capincci *np; 1412 struct list_head *l; 1413 int len = 0; 1414 1415 read_lock(&capidev_list_lock); 1416 list_for_each(l, &capidev_list) { 1417 cdev = list_entry(l, struct capidev, list); 1418 for (np=cdev->nccis; np; np = np->next) { 1419 len += sprintf(page+len, "%d 0x%x\n", 1420 cdev->ap.applid, 1421 np->ncci); 1422 if (len <= off) { 1423 off -= len; 1424 len = 0; 1425 } else { 1426 if (len-off > count) 1427 goto endloop; 1428 } 1429 } 1430 } 1431 endloop: 1432 read_unlock(&capidev_list_lock); 1433 *start = page+off; 1434 if (len < count) 1435 *eof = 1; 1436 if (len>count) len = count; 1437 if (len<0) len = 0; 1438 return len; 1439 } 1440 1441 static struct procfsentries { 1442 char *name; 1443 mode_t mode; 1444 int (*read_proc)(char *page, char **start, off_t off, 1445 int count, int *eof, void *data); 1446 struct proc_dir_entry *procent; 1447 } procfsentries[] = { 1448 /* { "capi", S_IFDIR, 0 }, */ 1449 { "capi/capi20", 0 , proc_capidev_read_proc }, 1450 { "capi/capi20ncci", 0 , proc_capincci_read_proc }, 1451 }; 1452 1453 static void __init proc_init(void) 1454 { 1455 int nelem = sizeof(procfsentries)/sizeof(procfsentries[0]); 1456 int i; 1457 1458 for (i=0; i < nelem; i++) { 1459 struct procfsentries *p = procfsentries + i; 1460 p->procent = create_proc_entry(p->name, p->mode, NULL); 1461 if (p->procent) p->procent->read_proc = p->read_proc; 1462 } 1463 } 1464 1465 static void __exit proc_exit(void) 1466 { 1467 int nelem = sizeof(procfsentries)/sizeof(procfsentries[0]); 1468 int i; 1469 1470 for (i=nelem-1; i >= 0; i--) { 1471 struct procfsentries *p = procfsentries + i; 1472 if (p->procent) { 1473 remove_proc_entry(p->name, NULL); 1474 p->procent = NULL; 1475 } 1476 } 1477 } 1478 1479 /* -------- init function and module interface ---------------------- */ 1480 1481 1482 static char rev[32]; 1483 1484 static int __init capi_init(void) 1485 { 1486 char *p; 1487 char *compileinfo; 1488 int major_ret; 1489 1490 if ((p = strchr(revision, ':')) != 0 && p[1]) { 1491 strlcpy(rev, p + 2, sizeof(rev)); 1492 if ((p = strchr(rev, '$')) != 0 && p > rev) 1493 *(p-1) = 0; 1494 } else 1495 strcpy(rev, "1.0"); 1496 1497 major_ret = register_chrdev(capi_major, "capi20", &capi_fops); 1498 if (major_ret < 0) { 1499 printk(KERN_ERR "capi20: unable to get major %d\n", capi_major); 1500 return major_ret; 1501 } 1502 capi_class = class_create(THIS_MODULE, "capi"); 1503 if (IS_ERR(capi_class)) { 1504 unregister_chrdev(capi_major, "capi20"); 1505 return PTR_ERR(capi_class); 1506 } 1507 1508 class_device_create(capi_class, NULL, MKDEV(capi_major, 0), NULL, "capi"); 1509 devfs_mk_cdev(MKDEV(capi_major, 0), S_IFCHR | S_IRUSR | S_IWUSR, 1510 "isdn/capi20"); 1511 1512 #ifdef CONFIG_ISDN_CAPI_MIDDLEWARE 1513 if (capinc_tty_init() < 0) { 1514 class_device_destroy(capi_class, MKDEV(capi_major, 0)); 1515 class_destroy(capi_class); 1516 unregister_chrdev(capi_major, "capi20"); 1517 return -ENOMEM; 1518 } 1519 #endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */ 1520 1521 proc_init(); 1522 1523 #ifdef CONFIG_ISDN_CAPI_MIDDLEWARE 1524 #if defined(CONFIG_ISDN_CAPI_CAPIFS) || defined(CONFIG_ISDN_CAPI_CAPIFS_MODULE) 1525 compileinfo = " (middleware+capifs)"; 1526 #else 1527 compileinfo = " (no capifs)"; 1528 #endif 1529 #else 1530 compileinfo = " (no middleware)"; 1531 #endif 1532 printk(KERN_NOTICE "capi20: Rev %s: started up with major %d%s\n", 1533 rev, capi_major, compileinfo); 1534 1535 return 0; 1536 } 1537 1538 static void __exit capi_exit(void) 1539 { 1540 proc_exit(); 1541 1542 class_device_destroy(capi_class, MKDEV(capi_major, 0)); 1543 class_destroy(capi_class); 1544 unregister_chrdev(capi_major, "capi20"); 1545 devfs_remove("isdn/capi20"); 1546 1547 #ifdef CONFIG_ISDN_CAPI_MIDDLEWARE 1548 capinc_tty_exit(); 1549 #endif 1550 printk(KERN_NOTICE "capi: Rev %s: unloaded\n", rev); 1551 } 1552 1553 module_init(capi_init); 1554 module_exit(capi_exit); 1555