OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [drivers/] [isdn/] [divert/] [isdn_divert.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/* $Id: isdn_divert.c,v 1.1.1.1 2004-04-15 02:05:30 phoenix Exp $
2
 *
3
 * DSS1 main diversion supplementary handling for i4l.
4
 *
5
 * Copyright 1999       by Werner Cornelius (werner@isdn4linux.de)
6
 *
7
 * This software may be used and distributed according to the terms
8
 * of the GNU General Public License, incorporated herein by reference.
9
 *
10
 */
11
 
12
#include <linux/version.h>
13
#include <linux/proc_fs.h>
14
#include "isdn_divert.h"
15
 
16
/**********************************/
17
/* structure keeping calling info */
18
/**********************************/
19
struct call_struc
20
  { isdn_ctrl ics; /* delivered setup + driver parameters */
21
    ulong divert_id; /* Id delivered to user */
22
    unsigned char akt_state; /* actual state */
23
    char deflect_dest[35]; /* deflection destination */
24
    struct timer_list timer; /* timer control structure */
25
    char info[90]; /* device info output */
26
    struct call_struc *next; /* pointer to next entry */
27
    struct call_struc *prev;
28
  };
29
 
30
 
31
/********************************************/
32
/* structure keeping deflection table entry */
33
/********************************************/
34
struct deflect_struc
35
  { struct deflect_struc *next,*prev;
36
    divert_rule rule; /* used rule */
37
  };
38
 
39
 
40
/*****************************************/
41
/* variables for main diversion services */
42
/*****************************************/
43
/* diversion/deflection processes */
44
static struct call_struc *divert_head = NULL; /* head of remembered entrys */
45
static ulong next_id = 1; /* next info id */
46
static struct deflect_struc *table_head = NULL;
47
static struct deflect_struc *table_tail = NULL;
48
static unsigned char extern_wait_max = 4; /* maximum wait in s for external process */
49
 
50
/***************************/
51
/* timer callback function */
52
/***************************/
53
static void deflect_timer_expire(ulong arg)
54
{ unsigned long flags;
55
  struct call_struc *cs = (struct call_struc *) arg;
56
 
57
  save_flags(flags);
58
  cli();
59
  del_timer(&cs->timer); /* delete active timer */
60
  restore_flags(flags);
61
 
62
  switch(cs->akt_state)
63
   { case DEFLECT_PROCEED:
64
       cs->ics.command = ISDN_CMD_HANGUP; /* cancel action */
65
       divert_if.ll_cmd(&cs->ics);
66
       save_flags(flags);
67
       cli();
68
       cs->akt_state = DEFLECT_AUTODEL; /* delete after timeout */
69
       cs->timer.expires = jiffies + (HZ * AUTODEL_TIME);
70
       add_timer(&cs->timer);
71
       restore_flags(flags);
72
       break;
73
 
74
     case DEFLECT_ALERT:
75
       cs->ics.command = ISDN_CMD_REDIR; /* protocol */
76
       strcpy(cs->ics.parm.setup.phone,cs->deflect_dest);
77
       strcpy(cs->ics.parm.setup.eazmsn,"Testtext delayed");
78
       divert_if.ll_cmd(&cs->ics);
79
       save_flags(flags);
80
       cli();
81
       cs->akt_state = DEFLECT_AUTODEL; /* delete after timeout */
82
       cs->timer.expires = jiffies + (HZ * AUTODEL_TIME);
83
       add_timer(&cs->timer);
84
       restore_flags(flags);
85
       break;
86
 
87
     case DEFLECT_AUTODEL:
88
     default:
89
       save_flags(flags);
90
       cli();
91
       if (cs->prev)
92
         cs->prev->next = cs->next; /* forward link */
93
        else
94
         divert_head = cs->next;
95
       if (cs->next)
96
         cs->next->prev = cs->prev; /* back link */
97
       restore_flags(flags);
98
       kfree(cs);
99
       return;
100
 
101
   } /* switch */
102
} /* deflect_timer_func */
103
 
104
 
105
/*****************************************/
106
/* handle call forwarding de/activations */
107
/* 0 = deact, 1 = act, 2 = interrogate   */
108
/*****************************************/
109
int cf_command(int drvid, int mode,
110
               u_char proc, char *msn,
111
               u_char service, char *fwd_nr, ulong *procid)
112
{ unsigned long flags;
113
  int retval,msnlen;
114
  int fwd_len;
115
  char *p,*ielenp,tmp[60];
116
  struct call_struc *cs;
117
 
118
  if (strchr(msn,'.')) return(-EINVAL); /* subaddress not allowed in msn */
119
  if ((proc & 0x7F) > 2) return(-EINVAL);
120
  proc &= 3;
121
  p = tmp;
122
  *p++ = 0x30; /* enumeration */
123
  ielenp = p++; /* remember total length position */
124
  *p++ = 0xa; /* proc tag */
125
  *p++ = 1;   /* length */
126
  *p++ = proc & 0x7F; /* procedure to de/activate/interrogate */
127
  *p++ = 0xa; /* service tag */
128
  *p++ = 1;   /* length */
129
  *p++ = service; /* service to handle */
130
 
131
  if (mode == 1)
132
   { if (!*fwd_nr) return(-EINVAL); /* destination missing */
133
     if (strchr(fwd_nr,'.')) return(-EINVAL); /* subaddress not allowed */
134
     fwd_len = strlen(fwd_nr);
135
     *p++ = 0x30; /* number enumeration */
136
     *p++ = fwd_len + 2; /* complete forward to len */
137
     *p++ = 0x80; /* fwd to nr */
138
     *p++ = fwd_len; /* length of number */
139
     strcpy(p,fwd_nr); /* copy number */
140
     p += fwd_len; /* pointer beyond fwd */
141
   } /* activate */
142
 
143
  msnlen = strlen(msn);
144
  *p++ = 0x80; /* msn number */
145
  if (msnlen > 1)
146
   { *p++ = msnlen; /* length */
147
     strcpy(p,msn);
148
     p += msnlen;
149
   }
150
  else *p++ = 0;
151
 
152
  *ielenp = p - ielenp - 1; /* set total IE length */
153
 
154
  /* allocate mem for information struct */
155
  if (!(cs = (struct call_struc *) kmalloc(sizeof(struct call_struc), GFP_ATOMIC)))
156
             return(-ENOMEM); /* no memory */
157
  init_timer(&cs->timer);
158
  cs->info[0] = '\0';
159
  cs->timer.function = deflect_timer_expire;
160
  cs->timer.data = (ulong) cs; /* pointer to own structure */
161
  cs->ics.driver = drvid;
162
  cs->ics.command = ISDN_CMD_PROT_IO; /* protocol specific io */
163
  cs->ics.arg = DSS1_CMD_INVOKE; /* invoke supplementary service */
164
  cs->ics.parm.dss1_io.proc = (mode == 1) ? 7: (mode == 2) ? 11:8; /* operation */
165
  cs->ics.parm.dss1_io.timeout = 4000; /* from ETS 300 207-1 */
166
  cs->ics.parm.dss1_io.datalen = p - tmp; /* total len */
167
  cs->ics.parm.dss1_io.data = tmp; /* start of buffer */
168
 
169
  save_flags(flags);
170
  cli();
171
  cs->ics.parm.dss1_io.ll_id = next_id++; /* id for callback */
172
  restore_flags(flags);
173
  *procid = cs->ics.parm.dss1_io.ll_id;
174
 
175
  sprintf(cs->info,"%d 0x%lx %s%s 0 %s %02x %d%s%s\n",
176
          (!mode ) ? DIVERT_DEACTIVATE : (mode == 1) ? DIVERT_ACTIVATE : DIVERT_REPORT,
177
          cs->ics.parm.dss1_io.ll_id,
178
          (mode != 2) ? "" : "0 ",
179
          divert_if.drv_to_name(cs->ics.driver),
180
          msn,
181
          service & 0xFF,
182
          proc,
183
          (mode != 1) ? "" : " 0 ",
184
          (mode != 1) ? "" : fwd_nr);
185
 
186
  retval = divert_if.ll_cmd(&cs->ics); /* excute command */
187
 
188
  if (!retval)
189
   { cs->prev = NULL;
190
     save_flags(flags);
191
     cli();
192
     cs->next = divert_head;
193
     divert_head = cs;
194
     restore_flags(flags);
195
   }
196
  else
197
   kfree(cs);
198
  return(retval);
199
} /* cf_command */
200
 
201
 
202
/****************************************/
203
/* handle a external deflection command */
204
/****************************************/
205
int deflect_extern_action(u_char cmd, ulong callid, char *to_nr)
206
{ struct call_struc *cs;
207
  isdn_ctrl ic;
208
  unsigned long flags;
209
  int i;
210
 
211
  if ((cmd & 0x7F) > 2) return(-EINVAL); /* invalid command */
212
  cs = divert_head; /* start of parameter list */
213
  while (cs)
214
   { if (cs->divert_id == callid) break; /* found */
215
     cs = cs->next;
216
   } /* search entry */
217
  if (!cs) return(-EINVAL); /* invalid callid */
218
 
219
  ic.driver = cs->ics.driver;
220
  ic.arg = cs->ics.arg;
221
  i = -EINVAL;
222
  if (cs->akt_state == DEFLECT_AUTODEL) return(i); /* no valid call */
223
  switch (cmd & 0x7F)
224
   { case 0: /* hangup */
225
       del_timer(&cs->timer);
226
       ic.command = ISDN_CMD_HANGUP;
227
       i = divert_if.ll_cmd(&ic);
228
       save_flags(flags);
229
       cli();
230
       cs->akt_state = DEFLECT_AUTODEL; /* delete after timeout */
231
       cs->timer.expires = jiffies + (HZ * AUTODEL_TIME);
232
       add_timer(&cs->timer);
233
       restore_flags(flags);
234
     break;
235
 
236
     case 1: /* alert */
237
       if (cs->akt_state == DEFLECT_ALERT) return(0);
238
       cmd &= 0x7F; /* never wait */
239
       del_timer(&cs->timer);
240
       ic.command = ISDN_CMD_ALERT;
241
       if ((i = divert_if.ll_cmd(&ic)))
242
        { save_flags(flags);
243
          cli();
244
          cs->akt_state = DEFLECT_AUTODEL; /* delete after timeout */
245
          cs->timer.expires = jiffies + (HZ * AUTODEL_TIME);
246
          add_timer(&cs->timer);
247
          restore_flags(flags);
248
        }
249
       else
250
          cs->akt_state = DEFLECT_ALERT;
251
     break;
252
 
253
     case 2: /* redir */
254
       del_timer(&cs->timer);
255
       strcpy(cs->ics.parm.setup.phone, to_nr);
256
       strcpy(cs->ics.parm.setup.eazmsn, "Testtext manual");
257
       ic.command = ISDN_CMD_REDIR;
258
       if ((i = divert_if.ll_cmd(&ic)))
259
        { save_flags(flags);
260
          cli();
261
          cs->akt_state = DEFLECT_AUTODEL; /* delete after timeout */
262
          cs->timer.expires = jiffies + (HZ * AUTODEL_TIME);
263
          add_timer(&cs->timer);
264
          restore_flags(flags);
265
        }
266
       else
267
          cs->akt_state = DEFLECT_ALERT;
268
     break;
269
 
270
   } /* switch */
271
  return(i);
272
} /* deflect_extern_action */
273
 
274
/********************************/
275
/* insert a new rule before idx */
276
/********************************/
277
int insertrule(int idx, divert_rule *newrule)
278
{ struct deflect_struc *ds,*ds1=NULL;
279
  unsigned long flags;
280
 
281
  if (!(ds = (struct deflect_struc *) kmalloc(sizeof(struct deflect_struc),
282
                                              GFP_KERNEL)))
283
    return(-ENOMEM); /* no memory */
284
 
285
  ds->rule = *newrule; /* set rule */
286
 
287
  save_flags(flags);
288
  cli();
289
 
290
  if (idx >= 0)
291
   { ds1 = table_head;
292
     while ((ds1) && (idx > 0))
293
      { idx--;
294
        ds1 = ds1->next;
295
      }
296
     if (!ds1) idx = -1;
297
   }
298
 
299
  if (idx < 0)
300
   { ds->prev = table_tail; /* previous entry */
301
     ds->next = NULL; /* end of chain */
302
     if (ds->prev)
303
       ds->prev->next = ds; /* last forward */
304
      else
305
        table_head = ds; /* is first entry */
306
     table_tail = ds; /* end of queue */
307
   }
308
  else
309
    { ds->next = ds1; /* next entry */
310
      ds->prev = ds1->prev; /* prev entry */
311
      ds1->prev = ds; /* backward chain old element */
312
      if (!ds->prev)
313
        table_head = ds; /* first element */
314
   }
315
 
316
  restore_flags(flags);
317
  return(0);
318
} /* insertrule */
319
 
320
/***********************************/
321
/* delete the rule at position idx */
322
/***********************************/
323
int deleterule(int idx)
324
{ struct deflect_struc *ds,*ds1;
325
  unsigned long flags;
326
 
327
  if (idx < 0)
328
   { save_flags(flags);
329
     cli();
330
     ds = table_head;
331
     table_head = NULL;
332
     table_tail = NULL;
333
     restore_flags(flags);
334
     while (ds)
335
      { ds1 = ds;
336
        ds = ds->next;
337
        kfree(ds1);
338
      }
339
     return(0);
340
   }
341
 
342
  save_flags(flags);
343
  cli();
344
  ds = table_head;
345
 
346
  while ((ds) && (idx > 0))
347
   { idx--;
348
     ds = ds->next;
349
   }
350
 
351
  if (!ds)
352
   { restore_flags(flags);
353
     return(-EINVAL);
354
   }
355
 
356
  if (ds->next)
357
    ds->next->prev = ds->prev; /* backward chain */
358
   else
359
     table_tail = ds->prev; /* end of chain */
360
 
361
  if (ds->prev)
362
    ds->prev->next = ds->next; /* forward chain */
363
   else
364
     table_head = ds->next; /* start of chain */
365
 
366
  restore_flags(flags);
367
  kfree(ds);
368
  return(0);
369
} /* deleterule */
370
 
371
/*******************************************/
372
/* get a pointer to a specific rule number */
373
/*******************************************/
374
divert_rule *getruleptr(int idx)
375
{ struct deflect_struc *ds = table_head;
376
 
377
  if (idx < 0) return(NULL);
378
  while ((ds) && (idx >= 0))
379
   { if (!(idx--))
380
      { return(&ds->rule);
381
        break;
382
      }
383
     ds = ds->next;
384
   }
385
  return(NULL);
386
} /* getruleptr */
387
 
388
/*************************************************/
389
/* called from common module on an incoming call */
390
/*************************************************/
391
int isdn_divert_icall(isdn_ctrl *ic)
392
{ int retval = 0;
393
  unsigned long flags;
394
  struct call_struc *cs = NULL;
395
  struct deflect_struc *dv;
396
  char *p,*p1;
397
  u_char accept;
398
 
399
  /* first check the internal deflection table */
400
  for (dv = table_head; dv ; dv = dv->next )
401
   { /* scan table */
402
     if (((dv->rule.callopt == 1) && (ic->command == ISDN_STAT_ICALLW)) ||
403
         ((dv->rule.callopt == 2) && (ic->command == ISDN_STAT_ICALL)))
404
       continue; /* call option check */
405
     if (!(dv->rule.drvid & (1L << ic->driver)))
406
       continue; /* driver not matching */
407
     if ((dv->rule.si1) && (dv->rule.si1 != ic->parm.setup.si1))
408
       continue; /* si1 not matching */
409
     if ((dv->rule.si2) && (dv->rule.si2 != ic->parm.setup.si2))
410
       continue; /* si2 not matching */
411
 
412
     p = dv->rule.my_msn;
413
     p1 = ic->parm.setup.eazmsn;
414
     accept = 0;
415
     while (*p)
416
      { /* complete compare */
417
        if (*p == '-')
418
          { accept = 1; /* call accepted */
419
            break;
420
          }
421
        if (*p++ != *p1++)
422
          break; /* not accepted */
423
        if ((!*p) && (!*p1))
424
          accept = 1;
425
      } /* complete compare */
426
     if (!accept) continue; /* not accepted */
427
 
428
     if ((strcmp(dv->rule.caller,"0")) || (ic->parm.setup.phone[0]))
429
      { p = dv->rule.caller;
430
        p1 = ic->parm.setup.phone;
431
        accept = 0;
432
        while (*p)
433
         { /* complete compare */
434
           if (*p == '-')
435
            { accept = 1; /* call accepted */
436
              break;
437
            }
438
           if (*p++ != *p1++)
439
             break; /* not accepted */
440
           if ((!*p) && (!*p1))
441
             accept = 1;
442
         } /* complete compare */
443
        if (!accept) continue; /* not accepted */
444
      }
445
 
446
     switch (dv->rule.action)
447
       { case DEFLECT_IGNORE:
448
           return(0);
449
           break;
450
 
451
         case DEFLECT_ALERT:
452
         case DEFLECT_PROCEED:
453
         case DEFLECT_REPORT:
454
         case DEFLECT_REJECT:
455
           if (dv->rule.action == DEFLECT_PROCEED)
456
            if ((!if_used) || ((!extern_wait_max) && (!dv->rule.waittime)))
457
              return(0); /* no external deflection needed */
458
           if (!(cs = (struct call_struc *) kmalloc(sizeof(struct call_struc), GFP_ATOMIC)))
459
             return(0); /* no memory */
460
           init_timer(&cs->timer);
461
           cs->info[0] = '\0';
462
           cs->timer.function = deflect_timer_expire;
463
           cs->timer.data = (ulong) cs; /* pointer to own structure */
464
 
465
           cs->ics = *ic; /* copy incoming data */
466
           if (!cs->ics.parm.setup.phone[0]) strcpy(cs->ics.parm.setup.phone,"0");
467
           if (!cs->ics.parm.setup.eazmsn[0]) strcpy(cs->ics.parm.setup.eazmsn,"0");
468
           cs->ics.parm.setup.screen = dv->rule.screen;
469
           if (dv->rule.waittime)
470
             cs->timer.expires = jiffies + (HZ * dv->rule.waittime);
471
           else
472
            if (dv->rule.action == DEFLECT_PROCEED)
473
              cs->timer.expires = jiffies + (HZ * extern_wait_max);
474
            else
475
              cs->timer.expires = 0;
476
           cs->akt_state = dv->rule.action;
477
           save_flags(flags);
478
           cli();
479
           cs->divert_id = next_id++; /* new sequence number */
480
           restore_flags(flags);
481
           cs->prev = NULL;
482
           if (cs->akt_state == DEFLECT_ALERT)
483
             { strcpy(cs->deflect_dest,dv->rule.to_nr);
484
               if (!cs->timer.expires)
485
                 { strcpy(ic->parm.setup.eazmsn,"Testtext direct");
486
                   ic->parm.setup.screen = dv->rule.screen;
487
                   strcpy(ic->parm.setup.phone,dv->rule.to_nr);
488
                   cs->akt_state = DEFLECT_AUTODEL; /* delete after timeout */
489
                   cs->timer.expires = jiffies + (HZ * AUTODEL_TIME);
490
                   retval = 5;
491
                 }
492
               else
493
                 retval = 1; /* alerting */
494
             }
495
           else
496
             { cs->deflect_dest[0] = '\0';
497
               retval = 4; /* only proceed */
498
             }
499
           sprintf(cs->info,"%d 0x%lx %s %s %s %s 0x%x 0x%x %d %d %s\n",
500
                   cs->akt_state,
501
                   cs->divert_id,
502
                   divert_if.drv_to_name(cs->ics.driver),
503
                   (ic->command == ISDN_STAT_ICALLW) ? "1":"0",
504
                   cs->ics.parm.setup.phone,
505
                   cs->ics.parm.setup.eazmsn,
506
                   cs->ics.parm.setup.si1,
507
                   cs->ics.parm.setup.si2,
508
                   cs->ics.parm.setup.screen,
509
                   dv->rule.waittime,
510
                   cs->deflect_dest);
511
           if ((dv->rule.action == DEFLECT_REPORT) ||
512
               (dv->rule.action == DEFLECT_REJECT))
513
            { put_info_buffer(cs->info);
514
              kfree(cs); /* remove */
515
              return((dv->rule.action == DEFLECT_REPORT) ? 0:2); /* nothing to do */
516
            }
517
           break;
518
 
519
         default:
520
           return(0); /* ignore call */
521
           break;
522
       } /* switch action */
523
     break;
524
   } /* scan_table */
525
 
526
  if (cs)
527
   { cs->prev = NULL;
528
     save_flags(flags);
529
     cli();
530
     cs->next = divert_head;
531
     divert_head = cs;
532
     if (cs->timer.expires) add_timer(&cs->timer);
533
     restore_flags(flags);
534
 
535
     put_info_buffer(cs->info);
536
     return(retval);
537
   }
538
  else
539
     return(0);
540
} /* isdn_divert_icall */
541
 
542
 
543
void deleteprocs(void)
544
{ struct call_struc *cs, *cs1;
545
  unsigned long flags;
546
 
547
  save_flags(flags);
548
  cli();
549
  cs = divert_head;
550
  divert_head = NULL;
551
  while (cs)
552
   { del_timer(&cs->timer);
553
     cs1 = cs;
554
     cs = cs->next;
555
     kfree(cs1);
556
   }
557
  restore_flags(flags);
558
} /* deleteprocs */
559
 
560
/****************************************************/
561
/* put a address including address type into buffer */
562
/****************************************************/
563
int put_address(char *st, u_char *p, int len)
564
{ u_char retval = 0;
565
  u_char adr_typ = 0; /* network standard */
566
 
567
  if (len < 2) return(retval);
568
  if (*p == 0xA1)
569
   { retval = *(++p) + 2; /* total length */
570
     if (retval > len) return(0); /* too short */
571
     len = retval - 2; /* remaining length */
572
     if (len < 3) return(0);
573
     if ((*(++p) != 0x0A) || (*(++p) != 1)) return(0);
574
     adr_typ = *(++p);
575
     len -= 3;
576
     p++;
577
     if (len < 2) return(0);
578
     if (*p++ != 0x12) return(0);
579
     if (*p > len) return(0); /* check number length */
580
     len = *p++;
581
   }
582
  else
583
   if (*p == 0x80)
584
    { retval = *(++p) + 2; /* total length */
585
      if (retval > len) return(0);
586
      len = retval - 2;
587
      p++;
588
    }
589
   else
590
    return(0); /* invalid address information */
591
 
592
  sprintf(st,"%d ",adr_typ);
593
  st += strlen(st);
594
  if (!len)
595
    *st++ = '-';
596
  else
597
   while (len--)
598
     *st++ = *p++;
599
  *st = '\0';
600
  return(retval);
601
} /* put_address */
602
 
603
/*************************************/
604
/* report a succesfull interrogation */
605
/*************************************/
606
int interrogate_success(isdn_ctrl *ic, struct call_struc *cs)
607
{ char *src = ic->parm.dss1_io.data;
608
  int restlen = ic->parm.dss1_io.datalen;
609
  int cnt = 1;
610
  u_char n,n1;
611
  char st[90], *p, *stp;
612
 
613
  if (restlen < 2) return(-100); /* frame too short */
614
  if (*src++ != 0x30) return(-101);
615
  if ((n = *src++) > 0x81) return(-102); /* invalid length field */
616
  restlen -= 2; /* remaining bytes */
617
  if (n == 0x80)
618
   { if (restlen < 2) return(-103);
619
     if ((*(src+restlen-1)) || (*(src+restlen-2))) return(-104);
620
     restlen -= 2;
621
   }
622
  else
623
   if ( n == 0x81)
624
    { n = *src++;
625
      restlen--;
626
      if (n > restlen) return(-105);
627
      restlen = n;
628
    }
629
   else
630
    if (n > restlen) return(-106);
631
     else
632
      restlen = n; /* standard format */
633
  if (restlen < 3) return(-107); /* no procedure */
634
  if ((*src++ != 2) || (*src++ != 1) || (*src++ != 0x0B)) return(-108);
635
  restlen -= 3;
636
  if (restlen < 2) return(-109); /* list missing */
637
  if (*src == 0x31)
638
   { src++;
639
     if ((n = *src++) > 0x81) return(-110); /* invalid length field */
640
     restlen -= 2; /* remaining bytes */
641
     if (n == 0x80)
642
      { if (restlen < 2) return(-111);
643
        if ((*(src+restlen-1)) || (*(src+restlen-2))) return(-112);
644
        restlen -= 2;
645
      }
646
     else
647
      if ( n == 0x81)
648
       { n = *src++;
649
         restlen--;
650
         if (n > restlen) return(-113);
651
         restlen = n;
652
       }
653
      else
654
       if (n > restlen) return(-114);
655
        else
656
         restlen = n; /* standard format */
657
   } /* result list header */
658
 
659
  while (restlen >= 2)
660
   { stp = st;
661
     sprintf(stp,"%d 0x%lx %d %s ",DIVERT_REPORT, ic->parm.dss1_io.ll_id,
662
                 cnt++,divert_if.drv_to_name(ic->driver));
663
     stp += strlen(stp);
664
     if (*src++ != 0x30) return(-115); /* invalid enum */
665
     n = *src++;
666
     restlen -= 2;
667
     if (n > restlen) return(-116); /* enum length wrong */
668
     restlen -= n;
669
     p = src; /* one entry */
670
     src += n;
671
     if (!(n1 = put_address(stp,p,n & 0xFF))) continue;
672
     stp += strlen(stp);
673
     p += n1;
674
     n -= n1;
675
     if (n < 6) continue; /* no service and proc */
676
     if ((*p++ != 0x0A) || (*p++ != 1)) continue;
677
     sprintf(stp," 0x%02x ",(*p++) & 0xFF);
678
     stp += strlen(stp);
679
     if ((*p++ != 0x0A) || (*p++ != 1)) continue;
680
     sprintf(stp,"%d ",(*p++) & 0xFF);
681
     stp += strlen(stp);
682
     n -= 6;
683
     if (n > 2)
684
      { if (*p++ != 0x30) continue;
685
        if (*p > (n-2)) continue;
686
        n = *p++;
687
        if (!(n1 = put_address(stp,p,n & 0xFF))) continue;
688
        stp += strlen(stp);
689
      }
690
     sprintf(stp,"\n");
691
     put_info_buffer(st);
692
   } /* while restlen */
693
  if (restlen) return(-117);
694
  return(0);
695
} /* interrogate_success */
696
 
697
/*********************************************/
698
/* callback for protocol specific extensions */
699
/*********************************************/
700
int prot_stat_callback(isdn_ctrl *ic)
701
{ struct call_struc *cs, *cs1;
702
  int i;
703
  unsigned long flags;
704
 
705
  cs = divert_head; /* start of list */
706
  cs1 = NULL;
707
  while (cs)
708
   { if (ic->driver == cs->ics.driver)
709
      { switch (cs->ics.arg)
710
         { case DSS1_CMD_INVOKE:
711
             if ((cs->ics.parm.dss1_io.ll_id == ic->parm.dss1_io.ll_id) &&
712
                 (cs->ics.parm.dss1_io.hl_id == ic->parm.dss1_io.hl_id))
713
              { switch (ic->arg)
714
                {  case DSS1_STAT_INVOKE_ERR:
715
                     sprintf(cs->info,"128 0x%lx 0x%x\n",
716
                             ic->parm.dss1_io.ll_id,
717
                             ic->parm.dss1_io.timeout);
718
                     put_info_buffer(cs->info);
719
                   break;
720
 
721
                   case DSS1_STAT_INVOKE_RES:
722
                     switch (cs->ics.parm.dss1_io.proc)
723
                      {  case  7:
724
                         case  8:
725
                            put_info_buffer(cs->info);
726
                           break;
727
 
728
                         case  11:
729
                           i = interrogate_success(ic,cs);
730
                           if (i)
731
                             sprintf(cs->info,"%d 0x%lx %d\n",DIVERT_REPORT,
732
                                     ic->parm.dss1_io.ll_id,i);
733
                           put_info_buffer(cs->info);
734
                           break;
735
 
736
                         default:
737
                           printk(KERN_WARNING "dss1_divert: unknown proc %d\n",cs->ics.parm.dss1_io.proc);
738
                           break;
739
                      }
740
 
741
 
742
                   break;
743
 
744
                   default:
745
                     printk(KERN_WARNING "dss1_divert unknown invoke answer %lx\n",ic->arg);
746
                   break;
747
                 }
748
                cs1 = cs; /* remember structure */
749
                cs = NULL;
750
                continue; /* abort search */
751
              } /* id found */
752
           break;
753
 
754
           case DSS1_CMD_INVOKE_ABORT:
755
             printk(KERN_WARNING "dss1_divert unhandled invoke abort\n");
756
           break;
757
 
758
           default:
759
             printk(KERN_WARNING "dss1_divert unknown cmd 0x%lx\n",cs->ics.arg);
760
           break;
761
         } /* switch ics.arg */
762
        cs = cs->next;
763
      } /* driver ok */
764
   }
765
 
766
  if (!cs1)
767
   { printk(KERN_WARNING "dss1_divert unhandled process\n");
768
     return(0);
769
   }
770
 
771
  if (cs1->ics.driver == -1)
772
   { save_flags(flags);
773
     cli();
774
     del_timer(&cs1->timer);
775
     if (cs1->prev)
776
       cs1->prev->next = cs1->next; /* forward link */
777
     else
778
       divert_head = cs1->next;
779
     if (cs1->next)
780
       cs1->next->prev = cs1->prev; /* back link */
781
     restore_flags(flags);
782
     kfree(cs1);
783
   }
784
 
785
  return(0);
786
} /* prot_stat_callback */
787
 
788
 
789
/***************************/
790
/* status callback from HL */
791
/***************************/
792
int isdn_divert_stat_callback(isdn_ctrl *ic)
793
{ struct call_struc *cs, *cs1;
794
  unsigned long flags;
795
  int retval;
796
 
797
  retval = -1;
798
  cs = divert_head; /* start of list */
799
     while (cs)
800
      { if ((ic->driver == cs->ics.driver) && (ic->arg == cs->ics.arg))
801
         { switch (ic->command)
802
            { case ISDN_STAT_DHUP:
803
                sprintf(cs->info,"129 0x%lx\n",cs->divert_id);
804
                del_timer(&cs->timer);
805
                cs->ics.driver = -1;
806
                break;
807
 
808
              case ISDN_STAT_CAUSE:
809
                sprintf(cs->info,"130 0x%lx %s\n",cs->divert_id,ic->parm.num);
810
                break;
811
 
812
              case ISDN_STAT_REDIR:
813
                sprintf(cs->info,"131 0x%lx\n",cs->divert_id);
814
                del_timer(&cs->timer);
815
                cs->ics.driver = -1;
816
                break;
817
 
818
              default:
819
                sprintf(cs->info,"999 0x%lx 0x%x\n",cs->divert_id,(int)(ic->command));
820
                break;
821
            }
822
          put_info_buffer(cs->info);
823
          retval = 0;
824
         }
825
        cs1 = cs;
826
        cs = cs->next;
827
        if (cs1->ics.driver == -1)
828
          {
829
            save_flags(flags);
830
            cli();
831
            if (cs1->prev)
832
              cs1->prev->next = cs1->next; /* forward link */
833
            else
834
              divert_head = cs1->next;
835
            if (cs1->next)
836
              cs1->next->prev = cs1->prev; /* back link */
837
            restore_flags(flags);
838
            kfree(cs1);
839
          }
840
      }
841
  return(retval); /* not found */
842
} /* isdn_divert_stat_callback */
843
 
844
 
845
/********************/
846
/* callback from ll */
847
/********************/
848
int ll_callback(isdn_ctrl *ic)
849
{
850
  switch (ic->command)
851
   { case ISDN_STAT_ICALL:
852
     case ISDN_STAT_ICALLW:
853
       return(isdn_divert_icall(ic));
854
     break;
855
 
856
     case ISDN_STAT_PROT:
857
       if ((ic->arg & 0xFF) == ISDN_PTYPE_EURO)
858
        { if (ic->arg != DSS1_STAT_INVOKE_BRD)
859
            return(prot_stat_callback(ic));
860
          else
861
            return(0); /* DSS1 invoke broadcast */
862
        }
863
       else
864
         return(-1); /* protocol not euro */
865
 
866
     default:
867
       return(isdn_divert_stat_callback(ic));
868
   }
869
} /* ll_callback */
870
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.