diff options
Diffstat (limited to 'drivers/isdn/divert')
-rw-r--r-- | drivers/isdn/divert/divert_init.c | 75 | ||||
-rw-r--r-- | drivers/isdn/divert/divert_procfs.c | 152 | ||||
-rw-r--r-- | drivers/isdn/divert/isdn_divert.c | 1475 | ||||
-rw-r--r-- | drivers/isdn/divert/isdn_divert.h | 116 |
4 files changed, 908 insertions, 910 deletions
diff --git a/drivers/isdn/divert/divert_init.c b/drivers/isdn/divert/divert_init.c index 2f7c9fc2e89..5374c25f036 100644 --- a/drivers/isdn/divert/divert_init.c +++ b/drivers/isdn/divert/divert_init.c @@ -3,7 +3,7 @@ * Module init for DSS1 diversion services for i4l. * * Copyright 1999 by Werner Cornelius (werner@isdn4linux.de) - * + * * This software may be used and distributed according to the terms * of the GNU General Public License, incorporated herein by reference. * @@ -23,13 +23,13 @@ MODULE_LICENSE("GPL"); /* structure containing interface to hl */ /****************************************/ isdn_divert_if divert_if = - { DIVERT_IF_MAGIC, /* magic value */ - DIVERT_CMD_REG, /* register cmd */ - ll_callback, /* callback routine from ll */ - NULL, /* command still not specified */ - NULL, /* drv_to_name */ - NULL, /* name_to_drv */ - }; +{ DIVERT_IF_MAGIC, /* magic value */ + DIVERT_CMD_REG, /* register cmd */ + ll_callback, /* callback routine from ll */ + NULL, /* command still not specified */ + NULL, /* drv_to_name */ + NULL, /* name_to_drv */ +}; /*************************/ /* Module interface code */ @@ -38,17 +38,17 @@ isdn_divert_if divert_if = static int __init divert_init(void) { int i; - if (divert_dev_init()) - { printk(KERN_WARNING "dss1_divert: cannot install device, not loaded\n"); - return(-EIO); - } - if ((i = DIVERT_REG_NAME(&divert_if)) != DIVERT_NO_ERR) - { divert_dev_deinit(); - printk(KERN_WARNING "dss1_divert: error %d registering module, not loaded\n",i); - return(-EIO); - } - printk(KERN_INFO "dss1_divert module successfully installed\n"); - return(0); + if (divert_dev_init()) + { printk(KERN_WARNING "dss1_divert: cannot install device, not loaded\n"); + return (-EIO); + } + if ((i = DIVERT_REG_NAME(&divert_if)) != DIVERT_NO_ERR) + { divert_dev_deinit(); + printk(KERN_WARNING "dss1_divert: error %d registering module, not loaded\n", i); + return (-EIO); + } + printk(KERN_INFO "dss1_divert module successfully installed\n"); + return (0); } /**********************/ @@ -56,27 +56,26 @@ static int __init divert_init(void) /**********************/ static void __exit divert_exit(void) { - unsigned long flags; - int i; + unsigned long flags; + int i; - spin_lock_irqsave(&divert_lock, flags); - divert_if.cmd = DIVERT_CMD_REL; /* release */ - if ((i = DIVERT_REG_NAME(&divert_if)) != DIVERT_NO_ERR) - { printk(KERN_WARNING "dss1_divert: error %d releasing module\n",i); - spin_unlock_irqrestore(&divert_lock, flags); - return; - } - if (divert_dev_deinit()) - { printk(KERN_WARNING "dss1_divert: device busy, remove cancelled\n"); - spin_unlock_irqrestore(&divert_lock, flags); - return; - } - spin_unlock_irqrestore(&divert_lock, flags); - deleterule(-1); /* delete all rules and free mem */ - deleteprocs(); - printk(KERN_INFO "dss1_divert module successfully removed \n"); + spin_lock_irqsave(&divert_lock, flags); + divert_if.cmd = DIVERT_CMD_REL; /* release */ + if ((i = DIVERT_REG_NAME(&divert_if)) != DIVERT_NO_ERR) + { printk(KERN_WARNING "dss1_divert: error %d releasing module\n", i); + spin_unlock_irqrestore(&divert_lock, flags); + return; + } + if (divert_dev_deinit()) + { printk(KERN_WARNING "dss1_divert: device busy, remove cancelled\n"); + spin_unlock_irqrestore(&divert_lock, flags); + return; + } + spin_unlock_irqrestore(&divert_lock, flags); + deleterule(-1); /* delete all rules and free mem */ + deleteprocs(); + printk(KERN_INFO "dss1_divert module successfully removed \n"); } module_init(divert_init); module_exit(divert_exit); - diff --git a/drivers/isdn/divert/divert_procfs.c b/drivers/isdn/divert/divert_procfs.c index 9021182c4b7..fb4f1bac013 100644 --- a/drivers/isdn/divert/divert_procfs.c +++ b/drivers/isdn/divert/divert_procfs.c @@ -50,10 +50,10 @@ put_info_buffer(char *cp) if (!*cp) return; if (!(ib = kmalloc(sizeof(struct divert_info) + strlen(cp), GFP_ATOMIC))) - return; /* no memory */ + return; /* no memory */ strcpy(ib->info_start, cp); /* set output string */ ib->next = NULL; - spin_lock_irqsave( &divert_info_lock, flags ); + spin_lock_irqsave(&divert_info_lock, flags); ib->usage_cnt = if_used; if (!divert_info_head) divert_info_head = ib; /* new head */ @@ -71,7 +71,7 @@ put_info_buffer(char *cp) } else break; } /* divert_info_head->next */ - spin_unlock_irqrestore( &divert_info_lock, flags ); + spin_unlock_irqrestore(&divert_info_lock, flags); wake_up_interruptible(&(rd_queue)); } /* put_info_buffer */ @@ -81,7 +81,7 @@ put_info_buffer(char *cp) /* deflection device read routine */ /**********************************/ static ssize_t -isdn_divert_read(struct file *file, char __user *buf, size_t count, loff_t * off) +isdn_divert_read(struct file *file, char __user *buf, size_t count, loff_t *off) { struct divert_info *inf; int len; @@ -109,7 +109,7 @@ isdn_divert_read(struct file *file, char __user *buf, size_t count, loff_t * off /* deflection device write routine */ /**********************************/ static ssize_t -isdn_divert_write(struct file *file, const char __user *buf, size_t count, loff_t * off) +isdn_divert_write(struct file *file, const char __user *buf, size_t count, loff_t *off) { return (-ENODEV); } /* isdn_divert_write */ @@ -119,7 +119,7 @@ isdn_divert_write(struct file *file, const char __user *buf, size_t count, loff_ /* select routines for various kernels */ /***************************************/ static unsigned int -isdn_divert_poll(struct file *file, poll_table * wait) +isdn_divert_poll(struct file *file, poll_table *wait) { unsigned int mask = 0; @@ -139,13 +139,13 @@ isdn_divert_open(struct inode *ino, struct file *filep) { unsigned long flags; - spin_lock_irqsave( &divert_info_lock, flags ); - if_used++; + spin_lock_irqsave(&divert_info_lock, flags); + if_used++; if (divert_info_head) filep->private_data = &(divert_info_tail->next); else filep->private_data = &divert_info_head; - spin_unlock_irqrestore( &divert_info_lock, flags ); + spin_unlock_irqrestore(&divert_info_lock, flags); /* start_divert(); */ return nonseekable_open(ino, filep); } /* isdn_divert_open */ @@ -159,7 +159,7 @@ isdn_divert_close(struct inode *ino, struct file *filep) struct divert_info *inf; unsigned long flags; - spin_lock_irqsave( &divert_info_lock, flags ); + spin_lock_irqsave(&divert_info_lock, flags); if_used--; inf = *((struct divert_info **) filep->private_data); while (inf) { @@ -172,7 +172,7 @@ isdn_divert_close(struct inode *ino, struct file *filep) divert_info_head = divert_info_head->next; kfree(inf); } - spin_unlock_irqrestore( &divert_info_lock, flags ); + spin_unlock_irqrestore(&divert_info_lock, flags); return (0); } /* isdn_divert_close */ @@ -191,75 +191,75 @@ static int isdn_divert_ioctl_unlocked(struct file *file, uint cmd, ulong arg) return -EFAULT; switch (cmd) { - case IIOCGETVER: - dioctl.drv_version = DIVERT_IIOC_VERSION; /* set version */ - break; - - case IIOCGETDRV: - if ((dioctl.getid.drvid = divert_if.name_to_drv(dioctl.getid.drvnam)) < 0) - return (-EINVAL); - break; - - case IIOCGETNAM: - cp = divert_if.drv_to_name(dioctl.getid.drvid); - if (!cp) - return (-EINVAL); - if (!*cp) - return (-EINVAL); - strcpy(dioctl.getid.drvnam, cp); - break; - - case IIOCGETRULE: - if (!(rulep = getruleptr(dioctl.getsetrule.ruleidx))) - return (-EINVAL); - dioctl.getsetrule.rule = *rulep; /* copy data */ - break; - - case IIOCMODRULE: - if (!(rulep = getruleptr(dioctl.getsetrule.ruleidx))) - return (-EINVAL); - spin_lock_irqsave(&divert_lock, flags); - *rulep = dioctl.getsetrule.rule; /* copy data */ - spin_unlock_irqrestore(&divert_lock, flags); - return (0); /* no copy required */ - break; + case IIOCGETVER: + dioctl.drv_version = DIVERT_IIOC_VERSION; /* set version */ + break; - case IIOCINSRULE: - return (insertrule(dioctl.getsetrule.ruleidx, &dioctl.getsetrule.rule)); - break; + case IIOCGETDRV: + if ((dioctl.getid.drvid = divert_if.name_to_drv(dioctl.getid.drvnam)) < 0) + return (-EINVAL); + break; - case IIOCDELRULE: - return (deleterule(dioctl.getsetrule.ruleidx)); - break; + case IIOCGETNAM: + cp = divert_if.drv_to_name(dioctl.getid.drvid); + if (!cp) + return (-EINVAL); + if (!*cp) + return (-EINVAL); + strcpy(dioctl.getid.drvnam, cp); + break; - case IIOCDODFACT: - return (deflect_extern_action(dioctl.fwd_ctrl.subcmd, - dioctl.fwd_ctrl.callid, - dioctl.fwd_ctrl.to_nr)); - - case IIOCDOCFACT: - case IIOCDOCFDIS: - case IIOCDOCFINT: - if (!divert_if.drv_to_name(dioctl.cf_ctrl.drvid)) - return (-EINVAL); /* invalid driver */ - if (strnlen(dioctl.cf_ctrl.msn, sizeof(dioctl.cf_ctrl.msn)) == - sizeof(dioctl.cf_ctrl.msn)) - return -EINVAL; - if (strnlen(dioctl.cf_ctrl.fwd_nr, sizeof(dioctl.cf_ctrl.fwd_nr)) == - sizeof(dioctl.cf_ctrl.fwd_nr)) - return -EINVAL; - if ((i = cf_command(dioctl.cf_ctrl.drvid, - (cmd == IIOCDOCFACT) ? 1 : (cmd == IIOCDOCFDIS) ? 0 : 2, - dioctl.cf_ctrl.cfproc, - dioctl.cf_ctrl.msn, - dioctl.cf_ctrl.service, - dioctl.cf_ctrl.fwd_nr, - &dioctl.cf_ctrl.procid))) - return (i); - break; + case IIOCGETRULE: + if (!(rulep = getruleptr(dioctl.getsetrule.ruleidx))) + return (-EINVAL); + dioctl.getsetrule.rule = *rulep; /* copy data */ + break; - default: + case IIOCMODRULE: + if (!(rulep = getruleptr(dioctl.getsetrule.ruleidx))) return (-EINVAL); + spin_lock_irqsave(&divert_lock, flags); + *rulep = dioctl.getsetrule.rule; /* copy data */ + spin_unlock_irqrestore(&divert_lock, flags); + return (0); /* no copy required */ + break; + + case IIOCINSRULE: + return (insertrule(dioctl.getsetrule.ruleidx, &dioctl.getsetrule.rule)); + break; + + case IIOCDELRULE: + return (deleterule(dioctl.getsetrule.ruleidx)); + break; + + case IIOCDODFACT: + return (deflect_extern_action(dioctl.fwd_ctrl.subcmd, + dioctl.fwd_ctrl.callid, + dioctl.fwd_ctrl.to_nr)); + + case IIOCDOCFACT: + case IIOCDOCFDIS: + case IIOCDOCFINT: + if (!divert_if.drv_to_name(dioctl.cf_ctrl.drvid)) + return (-EINVAL); /* invalid driver */ + if (strnlen(dioctl.cf_ctrl.msn, sizeof(dioctl.cf_ctrl.msn)) == + sizeof(dioctl.cf_ctrl.msn)) + return -EINVAL; + if (strnlen(dioctl.cf_ctrl.fwd_nr, sizeof(dioctl.cf_ctrl.fwd_nr)) == + sizeof(dioctl.cf_ctrl.fwd_nr)) + return -EINVAL; + if ((i = cf_command(dioctl.cf_ctrl.drvid, + (cmd == IIOCDOCFACT) ? 1 : (cmd == IIOCDOCFDIS) ? 0 : 2, + dioctl.cf_ctrl.cfproc, + dioctl.cf_ctrl.msn, + dioctl.cf_ctrl.service, + dioctl.cf_ctrl.fwd_nr, + &dioctl.cf_ctrl.procid))) + return (i); + break; + + default: + return (-EINVAL); } /* switch cmd */ return copy_to_user((void __user *)arg, &dioctl, sizeof(dioctl)) ? -EFAULT : 0; } /* isdn_divert_ioctl */ @@ -284,7 +284,7 @@ static const struct file_operations isdn_fops = .poll = isdn_divert_poll, .unlocked_ioctl = isdn_divert_ioctl, .open = isdn_divert_open, - .release = isdn_divert_close, + .release = isdn_divert_close, }; /****************************/ diff --git a/drivers/isdn/divert/isdn_divert.c b/drivers/isdn/divert/isdn_divert.c index 48e6d220f62..e61e55f1f19 100644 --- a/drivers/isdn/divert/isdn_divert.c +++ b/drivers/isdn/divert/isdn_divert.c @@ -3,7 +3,7 @@ * DSS1 main diversion supplementary handling for i4l. * * Copyright 1999 by Werner Cornelius (werner@isdn4linux.de) - * + * * This software may be used and distributed according to the terms * of the GNU General Public License, incorporated herein by reference. * @@ -20,24 +20,24 @@ /* structure keeping calling info */ /**********************************/ struct call_struc - { isdn_ctrl ics; /* delivered setup + driver parameters */ - ulong divert_id; /* Id delivered to user */ - unsigned char akt_state; /* actual state */ - char deflect_dest[35]; /* deflection destination */ - struct timer_list timer; /* timer control structure */ - char info[90]; /* device info output */ - struct call_struc *next; /* pointer to next entry */ - struct call_struc *prev; - }; +{ isdn_ctrl ics; /* delivered setup + driver parameters */ + ulong divert_id; /* Id delivered to user */ + unsigned char akt_state; /* actual state */ + char deflect_dest[35]; /* deflection destination */ + struct timer_list timer; /* timer control structure */ + char info[90]; /* device info output */ + struct call_struc *next; /* pointer to next entry */ + struct call_struc *prev; +}; /********************************************/ /* structure keeping deflection table entry */ /********************************************/ struct deflect_struc - { struct deflect_struc *next,*prev; - divert_rule rule; /* used rule */ - }; +{ struct deflect_struc *next, *prev; + divert_rule rule; /* used rule */ +}; /*****************************************/ @@ -45,10 +45,10 @@ struct deflect_struc /*****************************************/ /* diversion/deflection processes */ static struct call_struc *divert_head = NULL; /* head of remembered entrys */ -static ulong next_id = 1; /* next info id */ +static ulong next_id = 1; /* next info id */ static struct deflect_struc *table_head = NULL; -static struct deflect_struc *table_tail = NULL; -static unsigned char extern_wait_max = 4; /* maximum wait in s for external process */ +static struct deflect_struc *table_tail = NULL; +static unsigned char extern_wait_max = 4; /* maximum wait in s for external process */ DEFINE_SPINLOCK(divert_lock); @@ -57,50 +57,50 @@ DEFINE_SPINLOCK(divert_lock); /***************************/ static void deflect_timer_expire(ulong arg) { - unsigned long flags; - struct call_struc *cs = (struct call_struc *) arg; - - spin_lock_irqsave(&divert_lock, flags); - del_timer(&cs->timer); /* delete active timer */ - spin_unlock_irqrestore(&divert_lock, flags); - - switch(cs->akt_state) - { case DEFLECT_PROCEED: - cs->ics.command = ISDN_CMD_HANGUP; /* cancel action */ - divert_if.ll_cmd(&cs->ics); - spin_lock_irqsave(&divert_lock, flags); - cs->akt_state = DEFLECT_AUTODEL; /* delete after timeout */ - cs->timer.expires = jiffies + (HZ * AUTODEL_TIME); - add_timer(&cs->timer); - spin_unlock_irqrestore(&divert_lock, flags); - break; - - case DEFLECT_ALERT: - cs->ics.command = ISDN_CMD_REDIR; /* protocol */ - strlcpy(cs->ics.parm.setup.phone, cs->deflect_dest, sizeof(cs->ics.parm.setup.phone)); - strcpy(cs->ics.parm.setup.eazmsn,"Testtext delayed"); - divert_if.ll_cmd(&cs->ics); - spin_lock_irqsave(&divert_lock, flags); - cs->akt_state = DEFLECT_AUTODEL; /* delete after timeout */ - cs->timer.expires = jiffies + (HZ * AUTODEL_TIME); - add_timer(&cs->timer); - spin_unlock_irqrestore(&divert_lock, flags); - break; - - case DEFLECT_AUTODEL: - default: - spin_lock_irqsave(&divert_lock, flags); - if (cs->prev) - cs->prev->next = cs->next; /* forward link */ - else - divert_head = cs->next; - if (cs->next) - cs->next->prev = cs->prev; /* back link */ - spin_unlock_irqrestore(&divert_lock, flags); - kfree(cs); - return; - - } /* switch */ + unsigned long flags; + struct call_struc *cs = (struct call_struc *) arg; + + spin_lock_irqsave(&divert_lock, flags); + del_timer(&cs->timer); /* delete active timer */ + spin_unlock_irqrestore(&divert_lock, flags); + + switch (cs->akt_state) + { case DEFLECT_PROCEED: + cs->ics.command = ISDN_CMD_HANGUP; /* cancel action */ + divert_if.ll_cmd(&cs->ics); + spin_lock_irqsave(&divert_lock, flags); + cs->akt_state = DEFLECT_AUTODEL; /* delete after timeout */ + cs->timer.expires = jiffies + (HZ * AUTODEL_TIME); + add_timer(&cs->timer); + spin_unlock_irqrestore(&divert_lock, flags); + break; + + case DEFLECT_ALERT: + cs->ics.command = ISDN_CMD_REDIR; /* protocol */ + strlcpy(cs->ics.parm.setup.phone, cs->deflect_dest, sizeof(cs->ics.parm.setup.phone)); + strcpy(cs->ics.parm.setup.eazmsn, "Testtext delayed"); + divert_if.ll_cmd(&cs->ics); + spin_lock_irqsave(&divert_lock, flags); + cs->akt_state = DEFLECT_AUTODEL; /* delete after timeout */ + cs->timer.expires = jiffies + (HZ * AUTODEL_TIME); + add_timer(&cs->timer); + spin_unlock_irqrestore(&divert_lock, flags); + break; + + case DEFLECT_AUTODEL: + default: + spin_lock_irqsave(&divert_lock, flags); + if (cs->prev) + cs->prev->next = cs->next; /* forward link */ + else + divert_head = cs->next; + if (cs->next) + cs->next->prev = cs->prev; /* back link */ + spin_unlock_irqrestore(&divert_lock, flags); + kfree(cs); + return; + + } /* switch */ } /* deflect_timer_func */ @@ -108,94 +108,94 @@ static void deflect_timer_expire(ulong arg) /* handle call forwarding de/activations */ /* 0 = deact, 1 = act, 2 = interrogate */ /*****************************************/ -int cf_command(int drvid, int mode, - u_char proc, char *msn, - u_char service, char *fwd_nr, ulong *procid) +int cf_command(int drvid, int mode, + u_char proc, char *msn, + u_char service, char *fwd_nr, ulong *procid) { unsigned long flags; - int retval,msnlen; - int fwd_len; - char *p,*ielenp,tmp[60]; - struct call_struc *cs; - - if (strchr(msn,'.')) return(-EINVAL); /* subaddress not allowed in msn */ - if ((proc & 0x7F) > 2) return(-EINVAL); - proc &= 3; - p = tmp; - *p++ = 0x30; /* enumeration */ - ielenp = p++; /* remember total length position */ - *p++ = 0xa; /* proc tag */ - *p++ = 1; /* length */ - *p++ = proc & 0x7F; /* procedure to de/activate/interrogate */ - *p++ = 0xa; /* service tag */ - *p++ = 1; /* length */ - *p++ = service; /* service to handle */ - - if (mode == 1) - { if (!*fwd_nr) return(-EINVAL); /* destination missing */ - if (strchr(fwd_nr,'.')) return(-EINVAL); /* subaddress not allowed */ - fwd_len = strlen(fwd_nr); - *p++ = 0x30; /* number enumeration */ - *p++ = fwd_len + 2; /* complete forward to len */ - *p++ = 0x80; /* fwd to nr */ - *p++ = fwd_len; /* length of number */ - strcpy(p,fwd_nr); /* copy number */ - p += fwd_len; /* pointer beyond fwd */ - } /* activate */ - - msnlen = strlen(msn); - *p++ = 0x80; /* msn number */ - if (msnlen > 1) - { *p++ = msnlen; /* length */ - strcpy(p,msn); - p += msnlen; - } - else *p++ = 0; - - *ielenp = p - ielenp - 1; /* set total IE length */ - - /* allocate mem for information struct */ - if (!(cs = kmalloc(sizeof(struct call_struc), GFP_ATOMIC))) - return(-ENOMEM); /* no memory */ - init_timer(&cs->timer); - cs->info[0] = '\0'; - cs->timer.function = deflect_timer_expire; - cs->timer.data = (ulong) cs; /* pointer to own structure */ - cs->ics.driver = drvid; - cs->ics.command = ISDN_CMD_PROT_IO; /* protocol specific io */ - cs->ics.arg = DSS1_CMD_INVOKE; /* invoke supplementary service */ - cs->ics.parm.dss1_io.proc = (mode == 1) ? 7: (mode == 2) ? 11:8; /* operation */ - cs->ics.parm.dss1_io.timeout = 4000; /* from ETS 300 207-1 */ - cs->ics.parm.dss1_io.datalen = p - tmp; /* total len */ - cs->ics.parm.dss1_io.data = tmp; /* start of buffer */ - - spin_lock_irqsave(&divert_lock, flags); - cs->ics.parm.dss1_io.ll_id = next_id++; /* id for callback */ - spin_unlock_irqrestore(&divert_lock, flags); - *procid = cs->ics.parm.dss1_io.ll_id; - - sprintf(cs->info,"%d 0x%lx %s%s 0 %s %02x %d%s%s\n", - (!mode ) ? DIVERT_DEACTIVATE : (mode == 1) ? DIVERT_ACTIVATE : DIVERT_REPORT, - cs->ics.parm.dss1_io.ll_id, - (mode != 2) ? "" : "0 ", - divert_if.drv_to_name(cs->ics.driver), - msn, - service & 0xFF, - proc, - (mode != 1) ? "" : " 0 ", - (mode != 1) ? "" : fwd_nr); - - retval = divert_if.ll_cmd(&cs->ics); /* execute command */ - - if (!retval) - { cs->prev = NULL; - spin_lock_irqsave(&divert_lock, flags); - cs->next = divert_head; - divert_head = cs; - spin_unlock_irqrestore(&divert_lock, flags); - } - else - kfree(cs); - return(retval); + int retval, msnlen; + int fwd_len; + char *p, *ielenp, tmp[60]; + struct call_struc *cs; + + if (strchr(msn, '.')) return (-EINVAL); /* subaddress not allowed in msn */ + if ((proc & 0x7F) > 2) return (-EINVAL); + proc &= 3; + p = tmp; + *p++ = 0x30; /* enumeration */ + ielenp = p++; /* remember total length position */ + *p++ = 0xa; /* proc tag */ + *p++ = 1; /* length */ + *p++ = proc & 0x7F; /* procedure to de/activate/interrogate */ + *p++ = 0xa; /* service tag */ + *p++ = 1; /* length */ + *p++ = service; /* service to handle */ + + if (mode == 1) + { if (!*fwd_nr) return (-EINVAL); /* destination missing */ + if (strchr(fwd_nr, '.')) return (-EINVAL); /* subaddress not allowed */ + fwd_len = strlen(fwd_nr); + *p++ = 0x30; /* number enumeration */ + *p++ = fwd_len + 2; /* complete forward to len */ + *p++ = 0x80; /* fwd to nr */ + *p++ = fwd_len; /* length of number */ + strcpy(p, fwd_nr); /* copy number */ + p += fwd_len; /* pointer beyond fwd */ + } /* activate */ + + msnlen = strlen(msn); + *p++ = 0x80; /* msn number */ + if (msnlen > 1) + { *p++ = msnlen; /* length */ + strcpy(p, msn); + p += msnlen; + } + else *p++ = 0; + + *ielenp = p - ielenp - 1; /* set total IE length */ + + /* allocate mem for information struct */ + if (!(cs = kmalloc(sizeof(struct call_struc), GFP_ATOMIC))) + return (-ENOMEM); /* no memory */ + init_timer(&cs->timer); + cs->info[0] = '\0'; + cs->timer.function = deflect_timer_expire; + cs->timer.data = (ulong) cs; /* pointer to own structure */ + cs->ics.driver = drvid; + cs->ics.command = ISDN_CMD_PROT_IO; /* protocol specific io */ + cs->ics.arg = DSS1_CMD_INVOKE; /* invoke supplementary service */ + cs->ics.parm.dss1_io.proc = (mode == 1) ? 7 : (mode == 2) ? 11 : 8; /* operation */ + cs->ics.parm.dss1_io.timeout = 4000; /* from ETS 300 207-1 */ + cs->ics.parm.dss1_io.datalen = p - tmp; /* total len */ + cs->ics.parm.dss1_io.data = tmp; /* start of buffer */ + + spin_lock_irqsave(&divert_lock, flags); + cs->ics.parm.dss1_io.ll_id = next_id++; /* id for callback */ + spin_unlock_irqrestore(&divert_lock, flags); + *procid = cs->ics.parm.dss1_io.ll_id; + + sprintf(cs->info, "%d 0x%lx %s%s 0 %s %02x %d%s%s\n", + (!mode) ? DIVERT_DEACTIVATE : (mode == 1) ? DIVERT_ACTIVATE : DIVERT_REPORT, + cs->ics.parm.dss1_io.ll_id, + (mode != 2) ? "" : "0 ", + divert_if.drv_to_name(cs->ics.driver), + msn, + service & 0xFF, + proc, + (mode != 1) ? "" : " 0 ", + (mode != 1) ? "" : fwd_nr); + + retval = divert_if.ll_cmd(&cs->ics); /* execute command */ + + if (!retval) + { cs->prev = NULL; + spin_lock_irqsave(&divert_lock, flags); + cs->next = divert_head; + divert_head = cs; + spin_unlock_irqrestore(&divert_lock, flags); + } + else + kfree(cs); + return (retval); } /* cf_command */ @@ -204,165 +204,165 @@ int cf_command(int drvid, int mode, /****************************************/ int deflect_extern_action(u_char cmd, ulong callid, char *to_nr) { struct call_struc *cs; - isdn_ctrl ic; - unsigned long flags; - int i; - - if ((cmd & 0x7F) > 2) return(-EINVAL); /* invalid command */ - cs = divert_head; /* start of parameter list */ - while (cs) - { if (cs->divert_id == callid) break; /* found */ - cs = cs->next; - } /* search entry */ - if (!cs) return(-EINVAL); /* invalid callid */ - - ic.driver = cs->ics.driver; - ic.arg = cs->ics.arg; - i = -EINVAL; - if (cs->akt_state == DEFLECT_AUTODEL) return(i); /* no valid call */ - switch (cmd & 0x7F) - { case 0: /* hangup */ - del_timer(&cs->timer); - ic.command = ISDN_CMD_HANGUP; - i = divert_if.ll_cmd(&ic); - spin_lock_irqsave(&divert_lock, flags); - cs->akt_state = DEFLECT_AUTODEL; /* delete after timeout */ - cs->timer.expires = jiffies + (HZ * AUTODEL_TIME); - add_timer(&cs->timer); - spin_unlock_irqrestore(&divert_lock, flags); - break; - - case 1: /* alert */ - if (cs->akt_state == DEFLECT_ALERT) return(0); - cmd &= 0x7F; /* never wait */ - del_timer(&cs->timer); - ic.command = ISDN_CMD_ALERT; - if ((i = divert_if.ll_cmd(&ic))) - { - spin_lock_irqsave(&divert_lock, flags); - cs->akt_state = DEFLECT_AUTODEL; /* delete after timeout */ - cs->timer.expires = jiffies + (HZ * AUTODEL_TIME); - add_timer(&cs->timer); - spin_unlock_irqrestore(&divert_lock, flags); - } - else - cs->akt_state = DEFLECT_ALERT; - break; - - case 2: /* redir */ - del_timer(&cs->timer); - strlcpy(cs->ics.parm.setup.phone, to_nr, sizeof(cs->ics.parm.setup.phone)); - strcpy(cs->ics.parm.setup.eazmsn, "Testtext manual"); - ic.command = ISDN_CMD_REDIR; - if ((i = divert_if.ll_cmd(&ic))) - { - spin_lock_irqsave(&divert_lock, flags); - cs->akt_state = DEFLECT_AUTODEL; /* delete after timeout */ - cs->timer.expires = jiffies + (HZ * AUTODEL_TIME); - add_timer(&cs->timer); - spin_unlock_irqrestore(&divert_lock, flags); - } - else - cs->akt_state = DEFLECT_ALERT; - break; - - } /* switch */ - return(i); + isdn_ctrl ic; + unsigned long flags; + int i; + + if ((cmd & 0x7F) > 2) return (-EINVAL); /* invalid command */ + cs = divert_head; /* start of parameter list */ + while (cs) + { if (cs->divert_id == callid) break; /* found */ + cs = cs->next; + } /* search entry */ + if (!cs) return (-EINVAL); /* invalid callid */ + + ic.driver = cs->ics.driver; + ic.arg = cs->ics.arg; + i = -EINVAL; + if (cs->akt_state == DEFLECT_AUTODEL) return (i); /* no valid call */ + switch (cmd & 0x7F) + { case 0: /* hangup */ + del_timer(&cs->timer); + ic.command = ISDN_CMD_HANGUP; + i = divert_if.ll_cmd(&ic); + spin_lock_irqsave(&divert_lock, flags); + cs->akt_state = DEFLECT_AUTODEL; /* delete after timeout */ + cs->timer.expires = jiffies + (HZ * AUTODEL_TIME); + add_timer(&cs->timer); + spin_unlock_irqrestore(&divert_lock, flags); + break; + + case 1: /* alert */ + if (cs->akt_state == DEFLECT_ALERT) return (0); + cmd &= 0x7F; /* never wait */ + del_timer(&cs->timer); + ic.command = ISDN_CMD_ALERT; + if ((i = divert_if.ll_cmd(&ic))) + { + spin_lock_irqsave(&divert_lock, flags); + cs->akt_state = DEFLECT_AUTODEL; /* delete after timeout */ + cs->timer.expires = jiffies + (HZ * AUTODEL_TIME); + add_timer(&cs->timer); + spin_unlock_irqrestore(&divert_lock, flags); + } + else + cs->akt_state = DEFLECT_ALERT; + break; + + case 2: /* redir */ + del_timer(&cs->timer); + strlcpy(cs->ics.parm.setup.phone, to_nr, sizeof(cs->ics.parm.setup.phone)); + strcpy(cs->ics.parm.setup.eazmsn, "Testtext manual"); + ic.command = ISDN_CMD_REDIR; + if ((i = divert_if.ll_cmd(&ic))) + { + spin_lock_irqsave(&divert_lock, flags); + cs->akt_state = DEFLECT_AUTODEL; /* delete after timeout */ + cs->timer.expires = jiffies + (HZ * AUTODEL_TIME); + add_timer(&cs->timer); + spin_unlock_irqrestore(&divert_lock, flags); + } + else + cs->akt_state = DEFLECT_ALERT; + break; + + } /* switch */ + return (i); } /* deflect_extern_action */ /********************************/ /* insert a new rule before idx */ /********************************/ int insertrule(int idx, divert_rule *newrule) -{ struct deflect_struc *ds,*ds1=NULL; - unsigned long flags; - - if (!(ds = kmalloc(sizeof(struct deflect_struc), - GFP_KERNEL))) - return(-ENOMEM); /* no memory */ - - ds->rule = *newrule; /* set rule */ - - spin_lock_irqsave(&divert_lock, flags); - - if (idx >= 0) - { ds1 = table_head; - while ((ds1) && (idx > 0)) - { idx--; - ds1 = ds1->next; - } - if (!ds1) idx = -1; - } - - if (idx < 0) - { ds->prev = table_tail; /* previous entry */ - ds->next = NULL; /* end of chain */ - if (ds->prev) - ds->prev->next = ds; /* last forward */ - else - table_head = ds; /* is first entry */ - table_tail = ds; /* end of queue */ - } - else - { ds->next = ds1; /* next entry */ - ds->prev = ds1->prev; /* prev entry */ - ds1->prev = ds; /* backward chain old element */ - if (!ds->prev) - table_head = ds; /* first element */ - } - - spin_unlock_irqrestore(&divert_lock, flags); - return(0); +{ struct deflect_struc *ds, *ds1 = NULL; + unsigned long flags; + + if (!(ds = kmalloc(sizeof(struct deflect_struc), + GFP_KERNEL))) + return (-ENOMEM); /* no memory */ + + ds->rule = *newrule; /* set rule */ + + spin_lock_irqsave(&divert_lock, flags); + + if (idx >= 0) + { ds1 = table_head; + while ((ds1) && (idx > 0)) + { idx--; + ds1 = ds1->next; + } + if (!ds1) idx = -1; + } + + if (idx < 0) + { ds->prev = table_tail; /* previous entry */ + ds->next = NULL; /* end of chain */ + if (ds->prev) + ds->prev->next = ds; /* last forward */ + else + table_head = ds; /* is first entry */ + table_tail = ds; /* end of queue */ + } + else + { ds->next = ds1; /* next entry */ + ds->prev = ds1->prev; /* prev entry */ + ds1->prev = ds; /* backward chain old element */ + if (!ds->prev) + table_head = ds; /* first element */ + } + + spin_unlock_irqrestore(&divert_lock, flags); + return (0); } /* insertrule */ /***********************************/ /* delete the rule at position idx */ /***********************************/ int deleterule(int idx) -{ struct deflect_struc *ds,*ds1; - unsigned long flags; - - if (idx < 0) - { spin_lock_irqsave(&divert_lock, flags); - ds = table_head; - table_head = NULL; - table_tail = NULL; - spin_unlock_irqrestore(&divert_lock, flags); - while (ds) - { ds1 = ds; - ds = ds->next; - kfree(ds1); - } - return(0); - } - - spin_lock_irqsave(&divert_lock, flags); - ds = table_head; - - while ((ds) && (idx > 0)) - { idx--; - ds = ds->next; - } - - if (!ds) - { - spin_unlock_irqrestore(&divert_lock, flags); - return(-EINVAL); - } - - if (ds->next) - ds->next->prev = ds->prev; /* backward chain */ - else - table_tail = ds->prev; /* end of chain */ - - if (ds->prev) - ds->prev->next = ds->next; /* forward chain */ - else - table_head = ds->next; /* start of chain */ - - spin_unlock_irqrestore(&divert_lock, flags); - kfree(ds); - return(0); +{ struct deflect_struc *ds, *ds1; + unsigned long flags; + + if (idx < 0) + { spin_lock_irqsave(&divert_lock, flags); + ds = table_head; + table_head = NULL; + table_tail = NULL; + spin_unlock_irqrestore(&divert_lock, flags); + while (ds) + { ds1 = ds; + ds = ds->next; + kfree(ds1); + } + return (0); + } + + spin_lock_irqsave(&divert_lock, flags); + ds = table_head; + + while ((ds) && (idx > 0)) + { idx--; + ds = ds->next; + } + + if (!ds) + { + spin_unlock_irqrestore(&divert_lock, flags); + return (-EINVAL); + } + + if (ds->next) + ds->next->prev = ds->prev; /* backward chain */ + else + table_tail = ds->prev; /* end of chain */ + + if (ds->prev) + ds->prev->next = ds->next; /* forward chain */ + else + table_head = ds->next; /* start of chain */ + + spin_unlock_irqrestore(&divert_lock, flags); + kfree(ds); + return (0); } /* deleterule */ /*******************************************/ @@ -370,16 +370,16 @@ int deleterule(int idx) /*******************************************/ divert_rule *getruleptr(int idx) { struct deflect_struc *ds = table_head; - - if (idx < 0) return(NULL); - while ((ds) && (idx >= 0)) - { if (!(idx--)) - { return(&ds->rule); - break; - } - ds = ds->next; - } - return(NULL); + + if (idx < 0) return (NULL); + while ((ds) && (idx >= 0)) + { if (!(idx--)) + { return (&ds->rule); + break; + } + ds = ds->next; + } + return (NULL); } /* getruleptr */ /*************************************************/ @@ -387,168 +387,168 @@ divert_rule *getruleptr(int idx) /*************************************************/ static int isdn_divert_icall(isdn_ctrl *ic) { int retval = 0; - unsigned long flags; - struct call_struc *cs = NULL; - struct deflect_struc *dv; - char *p,*p1; - u_char accept; - - /* first check the internal deflection table */ - for (dv = table_head; dv ; dv = dv->next ) - { /* scan table */ - if (((dv->rule.callopt == 1) && (ic->command == ISDN_STAT_ICALLW)) || - ((dv->rule.callopt == 2) && (ic->command == ISDN_STAT_ICALL))) - continue; /* call option check */ - if (!(dv->rule.drvid & (1L << ic->driver))) - continue; /* driver not matching */ - if ((dv->rule.si1) && (dv->rule.si1 != ic->parm.setup.si1)) - continue; /* si1 not matching */ - if ((dv->rule.si2) && (dv->rule.si2 != ic->parm.setup.si2)) - continue; /* si2 not matching */ - - p = dv->rule.my_msn; - p1 = ic->parm.setup.eazmsn; - accept = 0; - while (*p) - { /* complete compare */ - if (*p == '-') - { accept = 1; /* call accepted */ - break; - } - if (*p++ != *p1++) - break; /* not accepted */ - if ((!*p) && (!*p1)) - accept = 1; |