--- include/linux/isdn.h.vorrudi Fri Jan 7 20:06:14 2000 +++ include/linux/isdn.h Fri Jan 7 21:25:39 2000 @@ -296,6 +296,7 @@ #define ISDN_MINOR_CTRLMAX (64 + (ISDN_MAX_CHANNELS-1)) #define ISDN_MINOR_PPP 128 #define ISDN_MINOR_PPPMAX (128 + (ISDN_MAX_CHANNELS-1)) +#define ISDN_MINOR_CTI 254 /* fuer /dev/isdncti */ #define ISDN_MINOR_STATUS 255 #undef CONFIG_ISDN_WITH_ABC_CALLB @@ -859,6 +860,14 @@ char msn2eaz[10][ISDN_MSNLEN]; /* Mapping-Table MSN->EAZ */ } driver; +/* CTI-data */ +struct isdn_cti +{ + struct sk_buff_head blockliste; + struct wait_queue *cti_waitq; + int o; /* offene Dateien */ +}; + /* Main driver-data */ typedef struct isdn_devt { unsigned short flags; /* Bitmapped Flags: */ @@ -872,6 +881,7 @@ int global_flags; infostruct *infochain; /* List of open info-devs. */ struct wait_queue *info_waitq; /* Wait-Queue for isdninfo */ + struct isdn_cti cti; /* for CTI */ struct timer_list timer; /* Misc.-function Timer */ int chanmap[ISDN_MAX_CHANNELS];/* Map minor->device-channel */ int drvmap[ISDN_MAX_CHANNELS]; /* Map minor->driver-index */ --- drivers/isdn/isdn_common.c.vorrudi Wed Jan 5 11:55:44 2000 +++ drivers/isdn/isdn_common.c Mon Jan 10 20:19:49 2000 @@ -386,7 +386,8 @@ #include "isdn_cards.h" /* Debugflags */ -#undef ISDN_DEBUG_STATCALLB +/* #undef ISDN_DEBUG_STATCALLB */ +#define ISDN_DEBUG_STATCALLB 1 isdn_dev *dev = (isdn_dev *) 0; @@ -410,6 +411,13 @@ isdn_divert_if *divert_if = NULL; /* interface to diversion module */ #endif CONFIG_ISDN_DIVERSION +/* cti-funktions */ +static void init_cti(struct isdn_cti *d); +static int open_cti(struct isdn_cti *d,struct file *filep); +static int close_cti(struct isdn_cti *d,struct file *filep); +static void cti_event(struct isdn_cti *d,char *what,struct setup_parm *parm); +static int read_cti(struct isdn_cti *d,struct file *file, char *buf, size_t count, loff_t * off); +static unsigned int poll_cti(struct isdn_cti *d,struct file *file, poll_table * wait); static int isdn_writebuf_stub(int, int, const u_char *, int, int); @@ -801,11 +809,12 @@ dev->drv[di]->flags &= ~DRV_FLAG_RUNNING; break; case ISDN_STAT_ICALL: - if (i < 0) - return -1; #ifdef ISDN_DEBUG_STATCALLB - printk(KERN_DEBUG "ICALL (net): %d %ld %s\n", di, c->arg, c->parm.num); + printk(KERN_DEBUG "isdn_status_callback: ICALL (net): di=%d i=%d arg=%ld %s\n", di, i, c->arg, c->parm.num); #endif + cti_event(&(dev->cti),"ICALL",&(c->parm.setup)); + if (i < 0) + return -1; if (dev->global_flags & ISDN_GLOBAL_STOPPED) { cmd.driver = di; cmd.arg = c->arg; @@ -868,16 +877,16 @@ break; } #ifdef ISDN_DEBUG_STATCALLB - printk(KERN_DEBUG "ICALL: ret=%d\n", retval); + printk(KERN_DEBUG "isdn_status_callback: ICALL: ret=%d\n", retval); #endif return retval; break; case ISDN_STAT_CINF: - if (i < 0) - return -1; #ifdef ISDN_DEBUG_STATCALLB - printk(KERN_DEBUG "CINF: %ld %s\n", c->arg, c->parm.num); + printk(KERN_DEBUG "isdn_status_callback: CINF: i=%d arg=%ld %s\n",i, c->arg, c->parm.num); #endif + if (i < 0) + return -1; if (dev->global_flags & ISDN_GLOBAL_STOPPED) return 0; if (strcmp(c->parm.num, "0")) @@ -886,7 +895,7 @@ break; case ISDN_STAT_CAUSE: #ifdef ISDN_DEBUG_STATCALLB - printk(KERN_DEBUG "CAUSE: %ld %s\n", c->arg, c->parm.num); + printk(KERN_DEBUG "isdn_status_callback: CAUSE: %ld %s\n", c->arg, c->parm.num); #endif printk(KERN_INFO "isdn: %s,ch%ld cause: %s\n", dev->drvid[di], c->arg, c->parm.num); @@ -898,7 +907,7 @@ break; case ISDN_STAT_DISPLAY: #ifdef ISDN_DEBUG_STATCALLB - printk(KERN_DEBUG "DISPLAY: %ld %s\n", c->arg, c->parm.display); + printk(KERN_DEBUG "isdn_status_callback: DISPLAY: %ld %s\n", c->arg, c->parm.display); #endif isdn_tty_stat_callback(i, c); #ifdef CONFIG_ISDN_DIVERSION @@ -907,11 +916,11 @@ #endif CONFIG_ISDN_DIVERSION break; case ISDN_STAT_DCONN: - if (i < 0) - return -1; #ifdef ISDN_DEBUG_STATCALLB - printk(KERN_DEBUG "DCONN: %ld\n", c->arg); + printk(KERN_DEBUG "isdn_status_callback: DCONN: i=%d arg=%ld\n",i, c->arg); #endif + if (i < 0) + return -1; if (dev->global_flags & ISDN_GLOBAL_STOPPED) return 0; /* Find any net-device, waiting for D-channel setup */ @@ -928,11 +937,11 @@ } break; case ISDN_STAT_DHUP: - if (i < 0) - return -1; #ifdef ISDN_DEBUG_STATCALLB - printk(KERN_DEBUG "DHUP: %ld\n", c->arg); + printk(KERN_DEBUG "isdn_status_callback: DHUP: i=%d arg=%ld\n",i, c->arg); #endif + if (i < 0) + return -1; if (dev->global_flags & ISDN_GLOBAL_STOPPED) return 0; dev->drv[di]->online &= ~(1 << (c->arg)); @@ -950,11 +959,11 @@ break; break; case ISDN_STAT_BCONN: - if (i < 0) - return -1; #ifdef ISDN_DEBUG_STATCALLB - printk(KERN_DEBUG "BCONN: %ld\n", c->arg); + printk(KERN_DEBUG "isdn_status_callback: BCONN: i=%d arg=%ld\n",i, c->arg); #endif + if (i < 0) + return -1; /* Signal B-channel-connect to network-devices */ if (dev->global_flags & ISDN_GLOBAL_STOPPED) return 0; @@ -967,11 +976,11 @@ break; break; case ISDN_STAT_BHUP: - if (i < 0) - return -1; #ifdef ISDN_DEBUG_STATCALLB - printk(KERN_DEBUG "BHUP: %ld\n", c->arg); + printk(KERN_DEBUG "isdn_status_callback: BHUP: i=%d arg=%ld\n",i, c->arg); #endif + if (i < 0) + return -1; if (dev->global_flags & ISDN_GLOBAL_STOPPED) return 0; dev->drv[di]->online &= ~(1 << (c->arg)); @@ -989,7 +998,7 @@ if (i < 0) return -1; #ifdef ISDN_DEBUG_STATCALLB - printk(KERN_DEBUG "NODCH: %ld\n", c->arg); + printk(KERN_DEBUG "isdn_status_callback: NODCH: i=%d arg=%ld\n",i, c->arg); #endif if (dev->global_flags & ISDN_GLOBAL_STOPPED) return 0; @@ -1315,6 +1324,9 @@ } return 0; } + if(minor == ISDN_MINOR_CTI) { + return read_cti(&(dev->cti),file,buf,count,off); + } if (!dev->drivers) return -ENODEV; if (minor < ISDN_MINOR_CTRL) { @@ -1436,6 +1448,9 @@ } return mask; } + if(minor == ISDN_MINOR_CTI) { + return poll_cti(&(dev->cti),file,wait); + } if (minor >= ISDN_MINOR_CTRL && minor <= ISDN_MINOR_CTRLMAX) { if (drvidx < 0) { /* driver deregistered while file open */ @@ -1925,6 +1940,9 @@ } else return -ENOMEM; } + if(minor == ISDN_MINOR_CTI) { + return open_cti(&(dev->cti),filep); + } if (!dev->channels) return -ENODEV; if (minor < ISDN_MINOR_CTRL) { @@ -1982,6 +2000,9 @@ printk(KERN_WARNING "isdn: No private data while closing isdnctrl\n"); return 0; } + if (minor == ISDN_MINOR_CTI) { + return close_cti(&(dev->cti),filep); + } isdn_MOD_DEC_USE_COUNT(); if (minor < ISDN_MINOR_CTRL) return 0; @@ -2434,6 +2455,121 @@ return 1; } +static void init_cti(struct isdn_cti *d) +{ + skb_queue_head_init(&(d->blockliste)); + d->cti_waitq = (struct wait_queue *)0; + d->o = 0; +} + +static int open_cti(struct isdn_cti *d,struct file *filep) +{ + d->o++; + MOD_INC_USE_COUNT; + return 0; +} + +static int close_cti(struct isdn_cti *d,struct file *filep) +{ + d->o--; + MOD_DEC_USE_COUNT; + if(d->o <= 0) + { + isdn_free_queue(&(d->blockliste)); + } + return 0; +} + +static void cti_event(struct isdn_cti *d,char *what,struct setup_parm *parm) +{ + struct sk_buff *skb; + int l,len; + + if(d->o <= 0) return; /* nobody is interested */ + skb=dev_alloc_skb(128); + if(!skb) + { + printk(KERN_WARNING "cti_event: No buffer available\n"); + return; + } + len=l=strlen(what); + memcpy(skb_put(skb,l),what,l); + if(parm) + { + char info[32]; + memcpy(skb_put(skb,1)," ",1); + len++; + if(parm->phone[0]) + { + l=strlen(parm->phone); + memcpy(skb_put(skb,l),parm->phone,l); + len+=l; + memcpy(skb_put(skb,1)," ",1); + len++; + } + else + { + l=8; + memcpy(skb_put(skb,l),"unknown ",l); + len+=l; + } + l=strlen(parm->eazmsn); + memcpy(skb_put(skb,l),parm->eazmsn,l); + len+=l; + sprintf(info," %x %x %x %x\n",(int)(parm->si1),(int)(parm->si2), + (int)(parm->plan),(int)(parm->screen)); + l=strlen(info); + memcpy(skb_put(skb,l),info,l); + len++; + } + else + { + memcpy(skb_put(skb,1),"\n",1); + len++; + } + skb_queue_tail(&(d->blockliste),skb); + wake_up_interruptible(&(d->cti_waitq)); +} + +static int read_cti(struct isdn_cti *d,struct file *file, char *buf, size_t count, loff_t * off) +{ + struct sk_buff *skb; + int ret=0; + if(skb_queue_empty(&(d->blockliste))) + { + if (file->f_flags & O_NONBLOCK) + return -EAGAIN; + interruptible_sleep_on(&(d->cti_waitq)); + } + skb=skb_dequeue(&(d->blockliste)); + if(!skb) return -EINTR; + if(skb->len <= count) + { + if (copy_to_user(buf, skb->data, skb->len)) + return -EFAULT; + *off += skb->len; + ret=skb->len; + } + else + { + printk(KERN_INFO "read_cti: Buffer to short %d < %d\n",count,skb->len); + ret=0; + } + dev_kfree_skb(skb); + return ret; +} + +static unsigned int poll_cti(struct isdn_cti *d,struct file *file, poll_table * wait) +{ + unsigned int mask = 0; + poll_wait(file, &(d->cti_waitq), wait); + if(!skb_queue_empty(&(d->blockliste))) + { + mask |= POLLIN | POLLRDNORM; + } + return mask; +} + /* ***************************************************************************** * And now the modules code. @@ -2476,6 +2612,7 @@ return -EIO; } memset((char *) dev, 0, sizeof(isdn_dev)); + init_cti(&(dev->cti)); init_timer(&dev->timer); dev->timer.function = isdn_timer_funct; dev->sem = MUTEX;