diff options
Diffstat (limited to 'drivers/isdn/divert/isdn_divert.c')
-rw-r--r-- | drivers/isdn/divert/isdn_divert.c | 1475 |
1 files changed, 737 insertions, 738 deletions
diff --git a/drivers/isdn/divert/isdn_divert.c b/drivers/isdn/divert/isdn_divert.c index 48e6d220f62c..e61e55f1f193 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; - } /* complete compare */ - if (!accept) continue; /* not accepted */ - - if ((strcmp(dv->rule.caller,"0")) || (ic->parm.setup.phone[0])) - { p = dv->rule.caller; - p1 = ic->parm.setup.phone; - accept = 0; - while (*p) - { /* complete compare */ - if (*p == '-') - { accept = 1; /* call accepted */ - break; - } - if (*p++ != *p1++) - break; /* not accepted */ - if ((!*p) && (!*p1)) - accept = 1; - } /* complete compare */ - if (!accept) continue; /* not accepted */ - } - - switch (dv->rule.action) - { case DEFLECT_IGNORE: - return(0); - break; - - case DEFLECT_ALERT: - case DEFLECT_PROCEED: - case DEFLECT_REPORT: - case DEFLECT_REJECT: - if (dv->rule.action == DEFLECT_PROCEED) - if ((!if_used) || ((!extern_wait_max) && (!dv->rule.waittime))) - return(0); /* no external deflection needed */ - if (!(cs = kmalloc(sizeof(struct call_struc), GFP_ATOMIC))) - return(0); /* 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 = *ic; /* copy incoming data */ - if (!cs->ics.parm.setup.phone[0]) strcpy(cs->ics.parm.setup.phone,"0"); - if (!cs->ics.parm.setup.eazmsn[0]) strcpy(cs->ics.parm.setup.eazmsn,"0"); - cs->ics.parm.setup.screen = dv->rule.screen; - if (dv->rule.waittime) - cs->timer.expires = jiffies + (HZ * dv->rule.waittime); - else - if (dv->rule.action == DEFLECT_PROCEED) - cs->timer.expires = jiffies + (HZ * extern_wait_max); - else - cs->timer.expires = 0; - cs->akt_state = dv->rule.action; - spin_lock_irqsave(&divert_lock, flags); - cs->divert_id = next_id++; /* new sequence number */ - spin_unlock_irqrestore(&divert_lock, flags); - cs->prev = NULL; - if (cs->akt_state == DEFLECT_ALERT) - { strcpy(cs->deflect_dest,dv->rule.to_nr); - if (!cs->timer.expires) - { strcpy(ic->parm.setup.eazmsn,"Testtext direct"); - ic->parm.setup.screen = dv->rule.screen; - strlcpy(ic->parm.setup.phone, dv->rule.to_nr, sizeof(ic->parm.setup.phone)); - cs->akt_state = DEFLECT_AUTODEL; /* delete after timeout */ - cs->timer.expires = jiffies + (HZ * AUTODEL_TIME); - retval = 5; - } - else - retval = 1; /* alerting */ - } - else - { cs->deflect_dest[0] = '\0'; - retval = 4; /* only proceed */ - } - sprintf(cs->info,"%d 0x%lx %s %s %s %s 0x%x 0x%x %d %d %s\n", - cs->akt_state, - cs->divert_id, - divert_if.drv_to_name(cs->ics.driver), - (ic->command == ISDN_STAT_ICALLW) ? "1":"0", - cs->ics.parm.setup.phone, - cs->ics.parm.setup.eazmsn, - cs->ics.parm.setup.si1, - cs->ics.parm.setup.si2, - cs->ics.parm.setup.screen, - dv->rule.waittime, - cs->deflect_dest); - if ((dv->rule.action == DEFLECT_REPORT) || - (dv->rule.action == DEFLECT_REJECT)) - { put_info_buffer(cs->info); - kfree(cs); /* remove */ - return((dv->rule.action == DEFLECT_REPORT) ? 0:2); /* nothing to do */ - } - break; - - default: - return(0); /* ignore call */ - break; - } /* switch action */ - break; - } /* scan_table */ - - if (cs) - { cs->prev = NULL; - spin_lock_irqsave(&divert_lock, flags); - cs->next = divert_head; - divert_head = cs; - if (cs->timer.expires) add_timer(&cs->timer); - spin_unlock_irqrestore(&divert_lock, flags); - - put_info_buffer(cs->info); - return(retval); - } - else - return(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; + } /* complete compare */ + if (!accept) continue; /* not accepted */ + + if ((strcmp(dv->rule.caller, "0")) || (ic->parm.setup.phone[0])) + { p = dv->rule.caller; + p1 = ic->parm.setup.phone; + accept = 0; + while (*p) + { /* complete compare */ + if (*p == '-') + { accept = 1; /* call accepted */ + break; + } + if (*p++ != *p1++) + break; /* not accepted */ + if ((!*p) && (!*p1)) + accept = 1; + } /* complete compare */ + if (!accept) continue; /* not accepted */ + } + + switch (dv->rule.action) + { case DEFLECT_IGNORE: + return (0); + break; + + case DEFLECT_ALERT: + case DEFLECT_PROCEED: + case DEFLECT_REPORT: + case DEFLECT_REJECT: + if (dv->rule.action == DEFLECT_PROCEED) + if ((!if_used) || ((!extern_wait_max) && (!dv->rule.waittime))) + return (0); /* no external deflection needed */ + if (!(cs = kmalloc(sizeof(struct call_struc), GFP_ATOMIC))) + return (0); /* 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 = *ic; /* copy incoming data */ + if (!cs->ics.parm.setup.phone[0]) strcpy(cs->ics.parm.setup.phone, "0"); + if (!cs->ics.parm.setup.eazmsn[0]) strcpy(cs->ics.parm.setup.eazmsn, "0"); + cs->ics.parm.setup.screen = dv->rule.screen; + if (dv->rule.waittime) + cs->timer.expires = jiffies + (HZ * dv->rule.waittime); + else + if (dv->rule.action == DEFLECT_PROCEED) + cs->timer.expires = jiffies + (HZ * extern_wait_max); + else + cs->timer.expires = 0; + cs->akt_state = dv->rule.action; + spin_lock_irqsave(&divert_lock, flags); + cs->divert_id = next_id++; /* new sequence number */ + spin_unlock_irqrestore(&divert_lock, flags); + cs->prev = NULL; + if (cs->akt_state == DEFLECT_ALERT) + { strcpy(cs->deflect_dest, dv->rule.to_nr); + if (!cs->timer.expires) + { strcpy(ic->parm.setup.eazmsn, "Testtext direct"); + ic->parm.setup.screen = dv->rule.screen; + strlcpy(ic->parm.setup.phone, dv->rule.to_nr, sizeof(ic->parm.setup.phone)); + cs->akt_state = DEFLECT_AUTODEL; /* delete after timeout */ + cs->timer.expires = jiffies + (HZ * AUTODEL_TIME); + retval = 5; + } + else + retval = 1; /* alerting */ + } + else + { cs->deflect_dest[0] = '\0'; + retval = 4; /* only proceed */ + } + sprintf(cs->info, "%d 0x%lx %s %s %s %s 0x%x 0x%x %d %d %s\n", + cs->akt_state, + cs->divert_id, + divert_if.drv_to_name(cs->ics.driver), + (ic->command == ISDN_STAT_ICALLW) ? "1" : "0", + cs->ics.parm.setup.phone, + cs->ics.parm.setup.eazmsn, + cs->ics.parm.setup.si1, + cs->ics.parm.setup.si2, + cs->ics.parm.setup.screen, + dv->rule.waittime, + cs->deflect_dest); + if ((dv->rule.action == DEFLECT_REPORT) || + (dv->rule.action == DEFLECT_REJECT)) + { put_info_buffer(cs->info); + kfree(cs); /* remove */ + return ((dv->rule.action == DEFLECT_REPORT) ? 0 : 2); /* nothing to do */ + } + break; + + default: + return (0); /* ignore call */ + break; + } /* switch action */ + break; + } /* scan_table */ + + if (cs) + { cs->prev = NULL; + spin_lock_irqsave(&divert_lock, flags); + cs->next = divert_head; + divert_head = cs; + if (cs->timer.expires) add_timer(&cs->timer); + spin_unlock_irqrestore(&divert_lock, flags); + + put_info_buffer(cs->info); + return (retval); + } + else + return (0); } /* isdn_divert_icall */ void deleteprocs(void) -{ struct call_struc *cs, *cs1; - unsigned long flags; - - spin_lock_irqsave(&divert_lock, flags); - cs = divert_head; - divert_head = NULL; - while (cs) - { del_timer(&cs->timer); - cs1 = cs; - cs = cs->next; - kfree(cs1); - } - spin_unlock_irqrestore(&divert_lock, flags); +{ struct call_struc *cs, *cs1; + unsigned long flags; + + spin_lock_irqsave(&divert_lock, flags); + cs = divert_head; + divert_head = NULL; + while (cs) + { del_timer(&cs->timer); + cs1 = cs; + cs = cs->next; + kfree(cs1); + } + spin_unlock_irqrestore(&divert_lock, flags); } /* deleteprocs */ /****************************************************/ @@ -556,42 +556,42 @@ void deleteprocs(void) /****************************************************/ static int put_address(char *st, u_char *p, int len) { u_char retval = 0; - u_char adr_typ = 0; /* network standard */ - - if (len < 2) return(retval); - if (*p == 0xA1) - { retval = *(++p) + 2; /* total length */ - if (retval > len) return(0); /* too short */ - len = retval - 2; /* remaining length */ - if (len < 3) return(0); - if ((*(++p) != 0x0A) || (*(++p) != 1)) return(0); - adr_typ = *(++p); - len -= 3; - p++; - if (len < 2) return(0); - if (*p++ != 0x12) return(0); - if (*p > len) return(0); /* check number length */ - len = *p++; - } - else - if (*p == 0x80) - { retval = *(++p) + 2; /* total length */ - if (retval > len) return(0); - len = retval - 2; - p++; - } - else - return(0); /* invalid address information */ - - sprintf(st,"%d ",adr_typ); - st += strlen(st); - if (!len) - *st++ = '-'; - else - while (len--) - *st++ = *p++; - *st = '\0'; - return(retval); + u_char adr_typ = 0; /* network standard */ + + if (len < 2) return (retval); + if (*p == 0xA1) + { retval = *(++p) + 2; /* total length */ + if (retval > len) return (0); /* too short */ + len = retval - 2; /* remaining length */ + if (len < 3) return (0); + if ((*(++p) != 0x0A) || (*(++p) != 1)) return (0); + adr_typ = *(++p); + len -= 3; + p++; + if (len < 2) return (0); + if (*p++ != 0x12) return (0); + if (*p > len) return (0); /* check number length */ + len = *p++; + } + else + if (*p == 0x80) + { retval = *(++p) + 2; /* total length */ + if (retval > len) return (0); + len = retval - 2; + p++; + } + else + return (0); /* invalid address information */ + + sprintf(st, "%d ", adr_typ); + st += strlen(st); + if (!len) + *st++ = '-'; + else + while (len--) + *st++ = *p++; + *st = '\0'; + return (retval); } /* put_address */ /*************************************/ @@ -599,93 +599,93 @@ static int put_address(char *st, u_char *p, int len) /*************************************/ static int interrogate_success(isdn_ctrl *ic, struct call_struc *cs) { char *src = ic->parm.dss1_io.data; - int restlen = ic->parm.dss1_io.datalen; - int cnt = 1; - u_char n,n1; - char st[90], *p, *stp; - - if (restlen < 2) return(-100); /* frame too short */ - if (*src++ != 0x30) return(-101); - if ((n = *src++) > 0x81) return(-102); /* invalid length field */ - restlen -= 2; /* remaining bytes */ - if (n == 0x80) - { if (restlen < 2) return(-103); - if ((*(src+restlen-1)) || (*(src+restlen-2))) return(-104); - restlen -= 2; - } - else - if ( n == 0x81) - { n = *src++; - restlen--; - if (n > restlen) return(-105); - restlen = n; - } - else - if (n > restlen) return(-106); - else - restlen = n; /* standard format */ - if (restlen < 3) return(-107); /* no procedure */ - if ((*src++ != 2) || (*src++ != 1) || (*src++ != 0x0B)) return(-108); - restlen -= 3; - if (restlen < 2) return(-109); /* list missing */ - if (*src == 0x31) - { src++; - if ((n = *src++) > 0x81) return(-110); /* invalid length field */ - restlen -= 2; /* remaining bytes */ - if (n == 0x80) - { if (restlen < 2) return(-111); - if ((*(src+restlen-1)) || (*(src+restlen-2))) return(-112); - restlen -= 2; - } - else - if ( n == 0x81) - { n = *src++; - restlen--; - if (n > restlen) return(-113); - restlen = n; - } - else - if (n > restlen) return(-114); - else - restlen = n; /* standard format */ - } /* result list header */ - - while (restlen >= 2) - { stp = st; - sprintf(stp,"%d 0x%lx %d %s ",DIVERT_REPORT, ic->parm.dss1_io.ll_id, - cnt++,divert_if.drv_to_name(ic->driver)); - stp += strlen(stp); - if (*src++ != 0x30) return(-115); /* invalid enum */ - n = *src++; - restlen -= 2; - if (n > restlen) return(-116); /* enum length wrong */ - restlen -= n; - p = src; /* one entry */ - src += n; - if (!(n1 = put_address(stp,p,n & 0xFF))) continue; - stp += strlen(stp); - p += n1; - n -= n1; - if (n < 6) continue; /* no service and proc */ - if ((*p++ != 0x0A) || (*p++ != 1)) continue; - sprintf(stp," 0x%02x ",(*p++) & 0xFF); - stp += strlen(stp); - if ((*p++ != 0x0A) || (*p++ != 1)) continue; - sprintf(stp,"%d ",(*p++) & 0xFF); - stp += strlen(stp); - n -= 6; - if (n > 2) - { if (*p++ != 0x30) continue; - if (*p > (n-2)) continue; - n = *p++; - if (!(n1 = put_address(stp,p,n & 0xFF))) continue; - stp += strlen(stp); - } - sprintf(stp,"\n"); - put_info_buffer(st); - } /* while restlen */ - if (restlen) return(-117); - return(0); + int restlen = ic->parm.dss1_io.datalen; + int cnt = 1; + u_char n, n1; + char st[90], *p, *stp; + + if (restlen < 2) return (-100); /* frame too short */ + if (*src++ != 0x30) return (-101); + if ((n = *src++) > 0x81) return (-102); /* invalid length field */ + restlen -= 2; /* remaining bytes */ + if (n == 0x80) + { if (restlen < 2) return (-103); + if ((*(src + restlen - 1)) || (*(src + restlen - 2))) return (-104); + restlen -= 2; + } + else + if (n == 0x81) + { n = *src++; + restlen--; + if (n > restlen) return (-105); + restlen = n; + } + else + if (n > restlen) return (-106); + else + restlen = n; /* standard format */ + if (restlen < 3) return (-107); /* no procedure */ + if ((*src++ != 2) || (*src++ != 1) || (*src++ != 0x0B)) return (-108); + restlen -= 3; + if (restlen < 2) return (-109); /* list missing */ + if (*src == 0x31) + { src++; + if ((n = *src++) > 0x81) return (-110); /* invalid length field */ + restlen -= 2; /* remaining bytes */ + if (n == 0x80) + { if (restlen < 2) return (-111); + if ((*(src + restlen - 1)) || (*(src + restlen - 2))) return (-112); + restlen -= 2; + } + else + if (n == 0x81) + { n = *src++; + restlen--; + if (n > restlen) return (-113); + restlen = n; + } + else + if (n > restlen) return (-114); + else + restlen = n; /* standard format */ + } /* result list header */ + + while (restlen >= 2) + { stp = st; + sprintf(stp, "%d 0x%lx %d %s ", DIVERT_REPORT, ic->parm.dss1_io.ll_id, + cnt++, divert_if.drv_to_name(ic->driver)); + stp += strlen(stp); + if (*src++ != 0x30) return (-115); /* invalid enum */ + n = *src++; + restlen -= 2; + if (n > restlen) return (-116); /* enum length wrong */ + restlen -= n; + p = src; /* one entry */ + src += n; + if (!(n1 = put_address(stp, p, n & 0xFF))) continue; + stp += strlen(stp); + p += n1; + n -= n1; + if (n < 6) continue; /* no service and proc */ + if ((*p++ != 0x0A) || (*p++ != 1)) continue; + sprintf(stp, " 0x%02x ", (*p++) & 0xFF); + stp += strlen(stp); + if ((*p++ != 0x0A) || (*p++ != 1)) continue; + sprintf(stp, "%d ", (*p++) & 0xFF); + stp += strlen(stp); + n -= 6; + if (n > 2) + { if (*p++ != 0x30) continue; + if (*p > (n - 2)) continue; + n = *p++; + if (!(n1 = put_address(stp, p, n & 0xFF))) continue; + stp += strlen(stp); + } + sprintf(stp, "\n"); + put_info_buffer(st); + } /* while restlen */ + if (restlen) return (-117); + return (0); } /* interrogate_success */ /*********************************************/ @@ -693,90 +693,90 @@ static int interrogate_success(isdn_ctrl *ic, struct call_struc *cs) /*********************************************/ static int prot_stat_callback(isdn_ctrl *ic) { struct call_struc *cs, *cs1; - int i; - unsigned long flags; - - cs = divert_head; /* start of list */ - cs1 = NULL; - while (cs) - { if (ic->driver == cs->ics.driver) - { switch (cs->ics.arg) - { case DSS1_CMD_INVOKE: - if ((cs->ics.parm.dss1_io.ll_id == ic->parm.dss1_io.ll_id) && - (cs->ics.parm.dss1_io.hl_id == ic->parm.dss1_io.hl_id)) - { switch (ic->arg) - { case DSS1_STAT_INVOKE_ERR: - sprintf(cs->info,"128 0x%lx 0x%x\n", - ic->parm.dss1_io.ll_id, - ic->parm.dss1_io.timeout); - put_info_buffer(cs->info); - break; - - case DSS1_STAT_INVOKE_RES: - switch (cs->ics.parm.dss1_io.proc) - { case 7: - case 8: - put_info_buffer(cs->info); - break; - - case 11: - i = interrogate_success(ic,cs); - if (i) - sprintf(cs->info,"%d 0x%lx %d\n",DIVERT_REPORT, - ic->parm.dss1_io.ll_id,i); - put_info_buffer(cs->info); - break; - - default: - printk(KERN_WARNING "dss1_divert: unknown proc %d\n",cs->ics.parm.dss1_io.proc); - break; - } - - - break; - - default: - printk(KERN_WARNING "dss1_divert unknown invoke answer %lx\n",ic->arg); - break; - } - cs1 = cs; /* remember structure */ - cs = NULL; - continue; /* abort search */ - } /* id found */ - break; - - case DSS1_CMD_INVOKE_ABORT: - printk(KERN_WARNING "dss1_divert unhandled invoke abort\n"); - break; - - default: - printk(KERN_WARNING "dss1_divert unknown cmd 0x%lx\n",cs->ics.arg); - break; - } /* switch ics.arg */ - cs = cs->next; - } /* driver ok */ - } - - if (!cs1) - { printk(KERN_WARNING "dss1_divert unhandled process\n"); - return(0); - } - - if (cs1->ics.driver == -1) - { - spin_lock_irqsave(&divert_lock, flags); - del_timer(&cs1->timer); - if (cs1->prev) - cs1->prev->next = cs1->next; /* forward link */ - else - divert_head = cs1->next; - if (cs1->next) - cs1->next->prev = cs1->prev; /* back link */ - spin_unlock_irqrestore(&divert_lock, flags); - kfree(cs1); - } - - return(0); + int i; + unsigned long flags; + + cs = divert_head; /* start of list */ + cs1 = NULL; + while (cs) + { if (ic->driver == cs->ics.driver) + { switch (cs->ics.arg) + { case DSS1_CMD_INVOKE: + if ((cs->ics.parm.dss1_io.ll_id == ic->parm.dss1_io.ll_id) && + (cs->ics.parm.dss1_io.hl_id == ic->parm.dss1_io.hl_id)) + { switch (ic->arg) + { case DSS1_STAT_INVOKE_ERR: + sprintf(cs->info, "128 0x%lx 0x%x\n", + ic->parm.dss1_io.ll_id, + ic->parm.dss1_io.timeout); + put_info_buffer(cs->info); + break; + + case DSS1_STAT_INVOKE_RES: + switch (cs->ics.parm.dss1_io.proc) + { case 7: + case 8: + put_info_buffer(cs->info); + break; + + case 11: + i = interrogate_success(ic, cs); + if (i) + sprintf(cs->info, "%d 0x%lx %d\n", DIVERT_REPORT, + ic->parm.dss1_io.ll_id, i); + put_info_buffer(cs->info); + break; + + default: + printk(KERN_WARNING "dss1_divert: unknown proc %d\n", cs->ics.parm.dss1_io.proc); + break; + } + + + break; + + default: + printk(KERN_WARNING "dss1_divert unknown invoke answer %lx\n", ic->arg); + break; + } + cs1 = cs; /* remember structure */ + cs = NULL; + continue; /* abort search */ + } /* id found */ + break; + + case DSS1_CMD_INVOKE_ABORT: + printk(KERN_WARNING "dss1_divert unhandled invoke abort\n"); + break; + + default: + printk(KERN_WARNING "dss1_divert unknown cmd 0x%lx\n", cs->ics.arg); + break; + } /* switch ics.arg */ + cs = cs->next; + } /* driver ok */ + } + + if (!cs1) + { printk(KERN_WARNING "dss1_divert unhandled process\n"); + return (0); + } + + if (cs1->ics.driver == -1) + { + spin_lock_irqsave(&divert_lock, flags); + del_timer(&cs1->timer); + if (cs1->prev) + cs1->prev->next = cs1->next; /* forward link */ + else + divert_head = cs1->next; + if (cs1->next) + cs1->next->prev = cs1->prev; /* back link */ + spin_unlock_irqrestore(&divert_lock, flags); + kfree(cs1); + } + + return (0); } /* prot_stat_callback */ @@ -785,79 +785,78 @@ static int prot_stat_callback(isdn_ctrl *ic) /***************************/ static int isdn_divert_stat_callback(isdn_ctrl *ic) { struct call_struc *cs, *cs1; - unsigned long flags; - int retval; - - retval = -1; - cs = divert_head; /* start of list */ - while (cs) - { if ((ic->driver == cs->ics.driver) && (ic->arg == cs->ics.arg)) - { switch (ic->command) - { case ISDN_STAT_DHUP: - sprintf(cs->info,"129 0x%lx\n",cs->divert_id); - del_timer(&cs->timer); - cs->ics.driver = -1; - break; - - case ISDN_STAT_CAUSE: - sprintf(cs->info,"130 0x%lx %s\n",cs->divert_id,ic->parm.num); - break; - - case ISDN_STAT_REDIR: - sprintf(cs->info,"131 0x%lx\n",cs->divert_id); - del_timer(&cs->timer); - cs->ics.driver = -1; - break; - - default: - sprintf(cs->info,"999 0x%lx 0x%x\n",cs->divert_id,(int)(ic->command)); - break; - } - put_info_buffer(cs->info); - retval = 0; - } - cs1 = cs; - cs = cs->next; - if (cs1->ics.driver == -1) - { - spin_lock_irqsave(&divert_lock, flags); - if (cs1->prev) - cs1->prev->next = cs1->next; /* forward link */ - else - divert_head = cs1->next; - if (cs1->next) - cs1->next->prev = cs1->prev; /* back link */ - spin_unlock_irqrestore(&divert_lock, flags); - kfree(cs1); - } - } - return(retval); /* not found */ -} /* isdn_divert_stat_callback */ + unsigned long flags; + int retval; + + retval = -1; + cs = divert_head; /* start of list */ + while (cs) + { if ((ic->driver == cs->ics.driver) && (ic->arg == cs->ics.arg)) + { switch (ic->command) + { case ISDN_STAT_DHUP: + sprintf(cs->info, "129 0x%lx\n", cs->divert_id); + del_timer(&cs->timer); + cs->ics.driver = -1; + break; + + case ISDN_STAT_CAUSE: + sprintf(cs->info, "130 0x%lx %s\n", cs->divert_id, ic->parm.num); + break; + + case ISDN_STAT_REDIR: + sprintf(cs->info, "131 0x%lx\n", cs->divert_id); + del_timer(&cs->timer); + cs->ics.driver = -1; + break; + + default: + sprintf(cs->info, "999 0x%lx 0x%x\n", cs->divert_id, (int)(ic->command)); + break; + } + put_info_buffer(cs->info); + retval = 0; + } + cs1 = cs; + cs = cs->next; + if (cs1->ics.driver == -1) + { + spin_lock_irqsave(&divert_lock, flags); + if (cs1->prev) + cs1->prev->next = cs1->next; /* forward link */ + else + divert_head = cs1->next; + if (cs1->next) + cs1->next->prev = cs1->prev; /* back link */ + spin_unlock_irqrestore(&divert_lock, flags); + kfree(cs1); + } + } + return (retval); /* not found */ +} /* isdn_divert_stat_callback */ /********************/ /* callback from ll */ -/********************/ +/********************/ int ll_callback(isdn_ctrl *ic) { - switch (ic->command) - { case ISDN_STAT_ICALL: - case ISDN_STAT_ICALLW: - return(isdn_divert_icall(ic)); - break; - - case ISDN_STAT_PROT: - if ((ic->arg & 0xFF) == ISDN_PTYPE_EURO) - { if (ic->arg != DSS1_STAT_INVOKE_BRD) - return(prot_stat_callback(ic)); - else - return(0); /* DSS1 invoke broadcast */ - } - else - return(-1); /* protocol not euro */ - - default: - return(isdn_divert_stat_callback(ic)); - } + switch (ic->command) + { case ISDN_STAT_ICALL: + case ISDN_STAT_ICALLW: + return (isdn_divert_icall(ic)); + break; + + case ISDN_STAT_PROT: + if ((ic->arg & 0xFF) == ISDN_PTYPE_EURO) + { if (ic->arg != DSS1_STAT_INVOKE_BRD) + return (prot_stat_callback(ic)); + else + return (0); /* DSS1 invoke broadcast */ + } + else + return (-1); /* protocol not euro */ + + default: + return (isdn_divert_stat_callback(ic)); + } } /* ll_callback */ - |