aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/isdn/divert/divert_init.c33
-rw-r--r--drivers/isdn/divert/isdn_divert.c423
-rw-r--r--drivers/isdn/divert/isdn_divert.h28
3 files changed, 237 insertions, 247 deletions
diff --git a/drivers/isdn/divert/divert_init.c b/drivers/isdn/divert/divert_init.c
index 5374c25f036c..267dede13bfd 100644
--- a/drivers/isdn/divert/divert_init.c
+++ b/drivers/isdn/divert/divert_init.c
@@ -22,13 +22,13 @@ MODULE_LICENSE("GPL");
22/****************************************/ 22/****************************************/
23/* structure containing interface to hl */ 23/* structure containing interface to hl */
24/****************************************/ 24/****************************************/
25isdn_divert_if divert_if = 25isdn_divert_if divert_if = {
26{ DIVERT_IF_MAGIC, /* magic value */ 26 DIVERT_IF_MAGIC, /* magic value */
27 DIVERT_CMD_REG, /* register cmd */ 27 DIVERT_CMD_REG, /* register cmd */
28 ll_callback, /* callback routine from ll */ 28 ll_callback, /* callback routine from ll */
29 NULL, /* command still not specified */ 29 NULL, /* command still not specified */
30 NULL, /* drv_to_name */ 30 NULL, /* drv_to_name */
31 NULL, /* name_to_drv */ 31 NULL, /* name_to_drv */
32}; 32};
33 33
34/*************************/ 34/*************************/
@@ -36,14 +36,15 @@ isdn_divert_if divert_if =
36/* no cmd line parms */ 36/* no cmd line parms */
37/*************************/ 37/*************************/
38static int __init divert_init(void) 38static int __init divert_init(void)
39{ int i; 39{
40 int i;
40 41
41 if (divert_dev_init()) 42 if (divert_dev_init()) {
42 { printk(KERN_WARNING "dss1_divert: cannot install device, not loaded\n"); 43 printk(KERN_WARNING "dss1_divert: cannot install device, not loaded\n");
43 return (-EIO); 44 return (-EIO);
44 } 45 }
45 if ((i = DIVERT_REG_NAME(&divert_if)) != DIVERT_NO_ERR) 46 if ((i = DIVERT_REG_NAME(&divert_if)) != DIVERT_NO_ERR) {
46 { divert_dev_deinit(); 47 divert_dev_deinit();
47 printk(KERN_WARNING "dss1_divert: error %d registering module, not loaded\n", i); 48 printk(KERN_WARNING "dss1_divert: error %d registering module, not loaded\n", i);
48 return (-EIO); 49 return (-EIO);
49 } 50 }
@@ -61,13 +62,13 @@ static void __exit divert_exit(void)
61 62
62 spin_lock_irqsave(&divert_lock, flags); 63 spin_lock_irqsave(&divert_lock, flags);
63 divert_if.cmd = DIVERT_CMD_REL; /* release */ 64 divert_if.cmd = DIVERT_CMD_REL; /* release */
64 if ((i = DIVERT_REG_NAME(&divert_if)) != DIVERT_NO_ERR) 65 if ((i = DIVERT_REG_NAME(&divert_if)) != DIVERT_NO_ERR) {
65 { printk(KERN_WARNING "dss1_divert: error %d releasing module\n", i); 66 printk(KERN_WARNING "dss1_divert: error %d releasing module\n", i);
66 spin_unlock_irqrestore(&divert_lock, flags); 67 spin_unlock_irqrestore(&divert_lock, flags);
67 return; 68 return;
68 } 69 }
69 if (divert_dev_deinit()) 70 if (divert_dev_deinit()) {
70 { printk(KERN_WARNING "dss1_divert: device busy, remove cancelled\n"); 71 printk(KERN_WARNING "dss1_divert: device busy, remove cancelled\n");
71 spin_unlock_irqrestore(&divert_lock, flags); 72 spin_unlock_irqrestore(&divert_lock, flags);
72 return; 73 return;
73 } 74 }
diff --git a/drivers/isdn/divert/isdn_divert.c b/drivers/isdn/divert/isdn_divert.c
index e61e55f1f193..db432e635496 100644
--- a/drivers/isdn/divert/isdn_divert.c
+++ b/drivers/isdn/divert/isdn_divert.c
@@ -19,8 +19,8 @@
19/**********************************/ 19/**********************************/
20/* structure keeping calling info */ 20/* structure keeping calling info */
21/**********************************/ 21/**********************************/
22struct call_struc 22struct call_struc {
23{ isdn_ctrl ics; /* delivered setup + driver parameters */ 23 isdn_ctrl ics; /* delivered setup + driver parameters */
24 ulong divert_id; /* Id delivered to user */ 24 ulong divert_id; /* Id delivered to user */
25 unsigned char akt_state; /* actual state */ 25 unsigned char akt_state; /* actual state */
26 char deflect_dest[35]; /* deflection destination */ 26 char deflect_dest[35]; /* deflection destination */
@@ -34,8 +34,8 @@ struct call_struc
34/********************************************/ 34/********************************************/
35/* structure keeping deflection table entry */ 35/* structure keeping deflection table entry */
36/********************************************/ 36/********************************************/
37struct deflect_struc 37struct deflect_struc {
38{ struct deflect_struc *next, *prev; 38 struct deflect_struc *next, *prev;
39 divert_rule rule; /* used rule */ 39 divert_rule rule; /* used rule */
40}; 40};
41 41
@@ -64,16 +64,16 @@ static void deflect_timer_expire(ulong arg)
64 del_timer(&cs->timer); /* delete active timer */ 64 del_timer(&cs->timer); /* delete active timer */
65 spin_unlock_irqrestore(&divert_lock, flags); 65 spin_unlock_irqrestore(&divert_lock, flags);
66 66
67 switch (cs->akt_state) 67 switch (cs->akt_state) {
68 { case DEFLECT_PROCEED: 68 case DEFLECT_PROCEED:
69 cs->ics.command = ISDN_CMD_HANGUP; /* cancel action */ 69 cs->ics.command = ISDN_CMD_HANGUP; /* cancel action */
70 divert_if.ll_cmd(&cs->ics); 70 divert_if.ll_cmd(&cs->ics);
71 spin_lock_irqsave(&divert_lock, flags); 71 spin_lock_irqsave(&divert_lock, flags);
72 cs->akt_state = DEFLECT_AUTODEL; /* delete after timeout */ 72 cs->akt_state = DEFLECT_AUTODEL; /* delete after timeout */
73 cs->timer.expires = jiffies + (HZ * AUTODEL_TIME); 73 cs->timer.expires = jiffies + (HZ * AUTODEL_TIME);
74 add_timer(&cs->timer); 74 add_timer(&cs->timer);
75 spin_unlock_irqrestore(&divert_lock, flags); 75 spin_unlock_irqrestore(&divert_lock, flags);
76 break; 76 break;
77 77
78 case DEFLECT_ALERT: 78 case DEFLECT_ALERT:
79 cs->ics.command = ISDN_CMD_REDIR; /* protocol */ 79 cs->ics.command = ISDN_CMD_REDIR; /* protocol */
@@ -111,7 +111,8 @@ static void deflect_timer_expire(ulong arg)
111int cf_command(int drvid, int mode, 111int cf_command(int drvid, int mode,
112 u_char proc, char *msn, 112 u_char proc, char *msn,
113 u_char service, char *fwd_nr, ulong *procid) 113 u_char service, char *fwd_nr, ulong *procid)
114{ unsigned long flags; 114{
115 unsigned long flags;
115 int retval, msnlen; 116 int retval, msnlen;
116 int fwd_len; 117 int fwd_len;
117 char *p, *ielenp, tmp[60]; 118 char *p, *ielenp, tmp[60];
@@ -130,8 +131,8 @@ int cf_command(int drvid, int mode,
130 *p++ = 1; /* length */ 131 *p++ = 1; /* length */
131 *p++ = service; /* service to handle */ 132 *p++ = service; /* service to handle */
132 133
133 if (mode == 1) 134 if (mode == 1) {
134 { if (!*fwd_nr) return (-EINVAL); /* destination missing */ 135 if (!*fwd_nr) return (-EINVAL); /* destination missing */
135 if (strchr(fwd_nr, '.')) return (-EINVAL); /* subaddress not allowed */ 136 if (strchr(fwd_nr, '.')) return (-EINVAL); /* subaddress not allowed */
136 fwd_len = strlen(fwd_nr); 137 fwd_len = strlen(fwd_nr);
137 *p++ = 0x30; /* number enumeration */ 138 *p++ = 0x30; /* number enumeration */
@@ -144,12 +145,12 @@ int cf_command(int drvid, int mode,
144 145
145 msnlen = strlen(msn); 146 msnlen = strlen(msn);
146 *p++ = 0x80; /* msn number */ 147 *p++ = 0x80; /* msn number */
147 if (msnlen > 1) 148 if (msnlen > 1) {
148 { *p++ = msnlen; /* length */ 149 *p++ = msnlen; /* length */
149 strcpy(p, msn); 150 strcpy(p, msn);
150 p += msnlen; 151 p += msnlen;
151 } 152 } else
152 else *p++ = 0; 153 *p++ = 0;
153 154
154 *ielenp = p - ielenp - 1; /* set total IE length */ 155 *ielenp = p - ielenp - 1; /* set total IE length */
155 156
@@ -186,14 +187,13 @@ int cf_command(int drvid, int mode,
186 187
187 retval = divert_if.ll_cmd(&cs->ics); /* execute command */ 188 retval = divert_if.ll_cmd(&cs->ics); /* execute command */
188 189
189 if (!retval) 190 if (!retval) {
190 { cs->prev = NULL; 191 cs->prev = NULL;
191 spin_lock_irqsave(&divert_lock, flags); 192 spin_lock_irqsave(&divert_lock, flags);
192 cs->next = divert_head; 193 cs->next = divert_head;
193 divert_head = cs; 194 divert_head = cs;
194 spin_unlock_irqrestore(&divert_lock, flags); 195 spin_unlock_irqrestore(&divert_lock, flags);
195 } 196 } else
196 else
197 kfree(cs); 197 kfree(cs);
198 return (retval); 198 return (retval);
199} /* cf_command */ 199} /* cf_command */
@@ -203,15 +203,16 @@ int cf_command(int drvid, int mode,
203/* handle a external deflection command */ 203/* handle a external deflection command */
204/****************************************/ 204/****************************************/
205int deflect_extern_action(u_char cmd, ulong callid, char *to_nr) 205int deflect_extern_action(u_char cmd, ulong callid, char *to_nr)
206{ struct call_struc *cs; 206{
207 struct call_struc *cs;
207 isdn_ctrl ic; 208 isdn_ctrl ic;
208 unsigned long flags; 209 unsigned long flags;
209 int i; 210 int i;
210 211
211 if ((cmd & 0x7F) > 2) return (-EINVAL); /* invalid command */ 212 if ((cmd & 0x7F) > 2) return (-EINVAL); /* invalid command */
212 cs = divert_head; /* start of parameter list */ 213 cs = divert_head; /* start of parameter list */
213 while (cs) 214 while (cs) {
214 { if (cs->divert_id == callid) break; /* found */ 215 if (cs->divert_id == callid) break; /* found */
215 cs = cs->next; 216 cs = cs->next;
216 } /* search entry */ 217 } /* search entry */
217 if (!cs) return (-EINVAL); /* invalid callid */ 218 if (!cs) return (-EINVAL); /* invalid callid */
@@ -220,32 +221,30 @@ int deflect_extern_action(u_char cmd, ulong callid, char *to_nr)
220 ic.arg = cs->ics.arg; 221 ic.arg = cs->ics.arg;
221 i = -EINVAL; 222 i = -EINVAL;
222 if (cs->akt_state == DEFLECT_AUTODEL) return (i); /* no valid call */ 223 if (cs->akt_state == DEFLECT_AUTODEL) return (i); /* no valid call */
223 switch (cmd & 0x7F) 224 switch (cmd & 0x7F) {
224 { case 0: /* hangup */ 225 case 0: /* hangup */
225 del_timer(&cs->timer); 226 del_timer(&cs->timer);
226 ic.command = ISDN_CMD_HANGUP; 227 ic.command = ISDN_CMD_HANGUP;
227 i = divert_if.ll_cmd(&ic); 228 i = divert_if.ll_cmd(&ic);
228 spin_lock_irqsave(&divert_lock, flags); 229 spin_lock_irqsave(&divert_lock, flags);
229 cs->akt_state = DEFLECT_AUTODEL; /* delete after timeout */ 230 cs->akt_state = DEFLECT_AUTODEL; /* delete after timeout */
230 cs->timer.expires = jiffies + (HZ * AUTODEL_TIME); 231 cs->timer.expires = jiffies + (HZ * AUTODEL_TIME);
231 add_timer(&cs->timer); 232 add_timer(&cs->timer);
232 spin_unlock_irqrestore(&divert_lock, flags); 233 spin_unlock_irqrestore(&divert_lock, flags);
233 break; 234 break;
234 235
235 case 1: /* alert */ 236 case 1: /* alert */
236 if (cs->akt_state == DEFLECT_ALERT) return (0); 237 if (cs->akt_state == DEFLECT_ALERT) return (0);
237 cmd &= 0x7F; /* never wait */ 238 cmd &= 0x7F; /* never wait */
238 del_timer(&cs->timer); 239 del_timer(&cs->timer);
239 ic.command = ISDN_CMD_ALERT; 240 ic.command = ISDN_CMD_ALERT;
240 if ((i = divert_if.ll_cmd(&ic))) 241 if ((i = divert_if.ll_cmd(&ic))) {
241 {
242 spin_lock_irqsave(&divert_lock, flags); 242 spin_lock_irqsave(&divert_lock, flags);
243 cs->akt_state = DEFLECT_AUTODEL; /* delete after timeout */ 243 cs->akt_state = DEFLECT_AUTODEL; /* delete after timeout */
244 cs->timer.expires = jiffies + (HZ * AUTODEL_TIME); 244 cs->timer.expires = jiffies + (HZ * AUTODEL_TIME);
245 add_timer(&cs->timer); 245 add_timer(&cs->timer);
246 spin_unlock_irqrestore(&divert_lock, flags); 246 spin_unlock_irqrestore(&divert_lock, flags);
247 } 247 } else
248 else
249 cs->akt_state = DEFLECT_ALERT; 248 cs->akt_state = DEFLECT_ALERT;
250 break; 249 break;
251 250
@@ -254,15 +253,13 @@ int deflect_extern_action(u_char cmd, ulong callid, char *to_nr)
254 strlcpy(cs->ics.parm.setup.phone, to_nr, sizeof(cs->ics.parm.setup.phone)); 253 strlcpy(cs->ics.parm.setup.phone, to_nr, sizeof(cs->ics.parm.setup.phone));
255 strcpy(cs->ics.parm.setup.eazmsn, "Testtext manual"); 254 strcpy(cs->ics.parm.setup.eazmsn, "Testtext manual");
256 ic.command = ISDN_CMD_REDIR; 255 ic.command = ISDN_CMD_REDIR;
257 if ((i = divert_if.ll_cmd(&ic))) 256 if ((i = divert_if.ll_cmd(&ic))) {
258 {
259 spin_lock_irqsave(&divert_lock, flags); 257 spin_lock_irqsave(&divert_lock, flags);
260 cs->akt_state = DEFLECT_AUTODEL; /* delete after timeout */ 258 cs->akt_state = DEFLECT_AUTODEL; /* delete after timeout */
261 cs->timer.expires = jiffies + (HZ * AUTODEL_TIME); 259 cs->timer.expires = jiffies + (HZ * AUTODEL_TIME);
262 add_timer(&cs->timer); 260 add_timer(&cs->timer);
263 spin_unlock_irqrestore(&divert_lock, flags); 261 spin_unlock_irqrestore(&divert_lock, flags);
264 } 262 } else
265 else
266 cs->akt_state = DEFLECT_ALERT; 263 cs->akt_state = DEFLECT_ALERT;
267 break; 264 break;
268 265
@@ -274,19 +271,19 @@ int deflect_extern_action(u_char cmd, ulong callid, char *to_nr)
274/* insert a new rule before idx */ 271/* insert a new rule before idx */
275/********************************/ 272/********************************/
276int insertrule(int idx, divert_rule *newrule) 273int insertrule(int idx, divert_rule *newrule)
277{ struct deflect_struc *ds, *ds1 = NULL; 274{
275 struct deflect_struc *ds, *ds1 = NULL;
278 unsigned long flags; 276 unsigned long flags;
279 277
280 if (!(ds = kmalloc(sizeof(struct deflect_struc), 278 if (!(ds = kmalloc(sizeof(struct deflect_struc), GFP_KERNEL)))
281 GFP_KERNEL)))
282 return (-ENOMEM); /* no memory */ 279 return (-ENOMEM); /* no memory */
283 280
284 ds->rule = *newrule; /* set rule */ 281 ds->rule = *newrule; /* set rule */
285 282
286 spin_lock_irqsave(&divert_lock, flags); 283 spin_lock_irqsave(&divert_lock, flags);
287 284
288 if (idx >= 0) 285 if (idx >= 0) {
289 { ds1 = table_head; 286 ds1 = table_head;
290 while ((ds1) && (idx > 0)) 287 while ((ds1) && (idx > 0))
291 { idx--; 288 { idx--;
292 ds1 = ds1->next; 289 ds1 = ds1->next;
@@ -294,17 +291,16 @@ int insertrule(int idx, divert_rule *newrule)
294 if (!ds1) idx = -1; 291 if (!ds1) idx = -1;
295 } 292 }
296 293
297 if (idx < 0) 294 if (idx < 0) {
298 { ds->prev = table_tail; /* previous entry */ 295 ds->prev = table_tail; /* previous entry */
299 ds->next = NULL; /* end of chain */ 296 ds->next = NULL; /* end of chain */
300 if (ds->prev) 297 if (ds->prev)
301 ds->prev->next = ds; /* last forward */ 298 ds->prev->next = ds; /* last forward */
302 else 299 else
303 table_head = ds; /* is first entry */ 300 table_head = ds; /* is first entry */
304 table_tail = ds; /* end of queue */ 301 table_tail = ds; /* end of queue */
305 } 302 } else {
306 else 303 ds->next = ds1; /* next entry */
307 { ds->next = ds1; /* next entry */
308 ds->prev = ds1->prev; /* prev entry */ 304 ds->prev = ds1->prev; /* prev entry */
309 ds1->prev = ds; /* backward chain old element */ 305 ds1->prev = ds; /* backward chain old element */
310 if (!ds->prev) 306 if (!ds->prev)
@@ -319,17 +315,18 @@ int insertrule(int idx, divert_rule *newrule)
319/* delete the rule at position idx */ 315/* delete the rule at position idx */
320/***********************************/ 316/***********************************/
321int deleterule(int idx) 317int deleterule(int idx)
322{ struct deflect_struc *ds, *ds1; 318{
319 struct deflect_struc *ds, *ds1;
323 unsigned long flags; 320 unsigned long flags;
324 321
325 if (idx < 0) 322 if (idx < 0) {
326 { spin_lock_irqsave(&divert_lock, flags); 323 spin_lock_irqsave(&divert_lock, flags);
327 ds = table_head; 324 ds = table_head;
328 table_head = NULL; 325 table_head = NULL;
329 table_tail = NULL; 326 table_tail = NULL;
330 spin_unlock_irqrestore(&divert_lock, flags); 327 spin_unlock_irqrestore(&divert_lock, flags);
331 while (ds) 328 while (ds) {
332 { ds1 = ds; 329 ds1 = ds;
333 ds = ds->next; 330 ds = ds->next;
334 kfree(ds1); 331 kfree(ds1);
335 } 332 }
@@ -339,13 +336,12 @@ int deleterule(int idx)
339 spin_lock_irqsave(&divert_lock, flags); 336 spin_lock_irqsave(&divert_lock, flags);
340 ds = table_head; 337 ds = table_head;
341 338
342 while ((ds) && (idx > 0)) 339 while ((ds) && (idx > 0)) {
343 { idx--; 340 idx--;
344 ds = ds->next; 341 ds = ds->next;
345 } 342 }
346 343
347 if (!ds) 344 if (!ds) {
348 {
349 spin_unlock_irqrestore(&divert_lock, flags); 345 spin_unlock_irqrestore(&divert_lock, flags);
350 return (-EINVAL); 346 return (-EINVAL);
351 } 347 }
@@ -369,12 +365,13 @@ int deleterule(int idx)
369/* get a pointer to a specific rule number */ 365/* get a pointer to a specific rule number */
370/*******************************************/ 366/*******************************************/
371divert_rule *getruleptr(int idx) 367divert_rule *getruleptr(int idx)
372{ struct deflect_struc *ds = table_head; 368{
369 struct deflect_struc *ds = table_head;
373 370
374 if (idx < 0) return (NULL); 371 if (idx < 0) return (NULL);
375 while ((ds) && (idx >= 0)) 372 while ((ds) && (idx >= 0)) {
376 { if (!(idx--)) 373 if (!(idx--)) {
377 { return (&ds->rule); 374 return (&ds->rule);
378 break; 375 break;
379 } 376 }
380 ds = ds->next; 377 ds = ds->next;
@@ -386,7 +383,8 @@ divert_rule *getruleptr(int idx)
386/* called from common module on an incoming call */ 383/* called from common module on an incoming call */
387/*************************************************/ 384/*************************************************/
388static int isdn_divert_icall(isdn_ctrl *ic) 385static int isdn_divert_icall(isdn_ctrl *ic)
389{ int retval = 0; 386{
387 int retval = 0;
390 unsigned long flags; 388 unsigned long flags;
391 struct call_struc *cs = NULL; 389 struct call_struc *cs = NULL;
392 struct deflect_struc *dv; 390 struct deflect_struc *dv;
@@ -394,8 +392,8 @@ static int isdn_divert_icall(isdn_ctrl *ic)
394 u_char accept; 392 u_char accept;
395 393
396 /* first check the internal deflection table */ 394 /* first check the internal deflection table */
397 for (dv = table_head; dv; dv = dv->next) 395 for (dv = table_head; dv; dv = dv->next) {
398 { /* scan table */ 396 /* scan table */
399 if (((dv->rule.callopt == 1) && (ic->command == ISDN_STAT_ICALLW)) || 397 if (((dv->rule.callopt == 1) && (ic->command == ISDN_STAT_ICALLW)) ||
400 ((dv->rule.callopt == 2) && (ic->command == ISDN_STAT_ICALL))) 398 ((dv->rule.callopt == 2) && (ic->command == ISDN_STAT_ICALL)))
401 continue; /* call option check */ 399 continue; /* call option check */
@@ -409,10 +407,10 @@ static int isdn_divert_icall(isdn_ctrl *ic)
409 p = dv->rule.my_msn; 407 p = dv->rule.my_msn;
410 p1 = ic->parm.setup.eazmsn; 408 p1 = ic->parm.setup.eazmsn;
411 accept = 0; 409 accept = 0;
412 while (*p) 410 while (*p) {
413 { /* complete compare */ 411 /* complete compare */
414 if (*p == '-') 412 if (*p == '-') {
415 { accept = 1; /* call accepted */ 413 accept = 1; /* call accepted */
416 break; 414 break;
417 } 415 }
418 if (*p++ != *p1++) 416 if (*p++ != *p1++)
@@ -422,14 +420,15 @@ static int isdn_divert_icall(isdn_ctrl *ic)
422 } /* complete compare */ 420 } /* complete compare */
423 if (!accept) continue; /* not accepted */ 421 if (!accept) continue; /* not accepted */
424 422
425 if ((strcmp(dv->rule.caller, "0")) || (ic->parm.setup.phone[0])) 423 if ((strcmp(dv->rule.caller, "0")) ||
426 { p = dv->rule.caller; 424 (ic->parm.setup.phone[0])) {
425 p = dv->rule.caller;
427 p1 = ic->parm.setup.phone; 426 p1 = ic->parm.setup.phone;
428 accept = 0; 427 accept = 0;
429 while (*p) 428 while (*p) {
430 { /* complete compare */ 429 /* complete compare */
431 if (*p == '-') 430 if (*p == '-') {
432 { accept = 1; /* call accepted */ 431 accept = 1; /* call accepted */
433 break; 432 break;
434 } 433 }
435 if (*p++ != *p1++) 434 if (*p++ != *p1++)
@@ -440,10 +439,10 @@ static int isdn_divert_icall(isdn_ctrl *ic)
440 if (!accept) continue; /* not accepted */ 439 if (!accept) continue; /* not accepted */
441 } 440 }
442 441
443 switch (dv->rule.action) 442 switch (dv->rule.action) {
444 { case DEFLECT_IGNORE: 443 case DEFLECT_IGNORE:
445 return (0); 444 return (0);
446 break; 445 break;
447 446
448 case DEFLECT_ALERT: 447 case DEFLECT_ALERT:
449 case DEFLECT_PROCEED: 448 case DEFLECT_PROCEED:
@@ -465,31 +464,29 @@ static int isdn_divert_icall(isdn_ctrl *ic)
465 cs->ics.parm.setup.screen = dv->rule.screen; 464 cs->ics.parm.setup.screen = dv->rule.screen;
466 if (dv->rule.waittime) 465 if (dv->rule.waittime)
467 cs->timer.expires = jiffies + (HZ * dv->rule.waittime); 466 cs->timer.expires = jiffies + (HZ * dv->rule.waittime);
467 else if (dv->rule.action == DEFLECT_PROCEED)
468 cs->timer.expires = jiffies + (HZ * extern_wait_max);
468 else 469 else
469 if (dv->rule.action == DEFLECT_PROCEED) 470 cs->timer.expires = 0;
470 cs->timer.expires = jiffies + (HZ * extern_wait_max);
471 else
472 cs->timer.expires = 0;
473 cs->akt_state = dv->rule.action; 471 cs->akt_state = dv->rule.action;
474 spin_lock_irqsave(&divert_lock, flags); 472 spin_lock_irqsave(&divert_lock, flags);
475 cs->divert_id = next_id++; /* new sequence number */ 473 cs->divert_id = next_id++; /* new sequence number */
476 spin_unlock_irqrestore(&divert_lock, flags); 474 spin_unlock_irqrestore(&divert_lock, flags);
477 cs->prev = NULL; 475 cs->prev = NULL;
478 if (cs->akt_state == DEFLECT_ALERT) 476 if (cs->akt_state == DEFLECT_ALERT) {
479 { strcpy(cs->deflect_dest, dv->rule.to_nr); 477 strcpy(cs->deflect_dest, dv->rule.to_nr);
480 if (!cs->timer.expires) 478 if (!cs->timer.expires) {
481 { strcpy(ic->parm.setup.eazmsn, "Testtext direct"); 479 strcpy(ic->parm.setup.eazmsn,
480 "Testtext direct");
482 ic->parm.setup.screen = dv->rule.screen; 481 ic->parm.setup.screen = dv->rule.screen;
483 strlcpy(ic->parm.setup.phone, dv->rule.to_nr, sizeof(ic->parm.setup.phone)); 482 strlcpy(ic->parm.setup.phone, dv->rule.to_nr, sizeof(ic->parm.setup.phone));
484 cs->akt_state = DEFLECT_AUTODEL; /* delete after timeout */ 483 cs->akt_state = DEFLECT_AUTODEL; /* delete after timeout */
485 cs->timer.expires = jiffies + (HZ * AUTODEL_TIME); 484 cs->timer.expires = jiffies + (HZ * AUTODEL_TIME);
486 retval = 5; 485 retval = 5;
487 } 486 } else
488 else
489 retval = 1; /* alerting */ 487 retval = 1; /* alerting */
490 } 488 } else {
491 else 489 cs->deflect_dest[0] = '\0';
492 { cs->deflect_dest[0] = '\0';
493 retval = 4; /* only proceed */ 490 retval = 4; /* only proceed */
494 } 491 }
495 sprintf(cs->info, "%d 0x%lx %s %s %s %s 0x%x 0x%x %d %d %s\n", 492 sprintf(cs->info, "%d 0x%lx %s %s %s %s 0x%x 0x%x %d %d %s\n",
@@ -505,8 +502,8 @@ static int isdn_divert_icall(isdn_ctrl *ic)
505 dv->rule.waittime, 502 dv->rule.waittime,
506 cs->deflect_dest); 503 cs->deflect_dest);
507 if ((dv->rule.action == DEFLECT_REPORT) || 504 if ((dv->rule.action == DEFLECT_REPORT) ||
508 (dv->rule.action == DEFLECT_REJECT)) 505 (dv->rule.action == DEFLECT_REJECT)) {
509 { put_info_buffer(cs->info); 506 put_info_buffer(cs->info);
510 kfree(cs); /* remove */ 507 kfree(cs); /* remove */
511 return ((dv->rule.action == DEFLECT_REPORT) ? 0 : 2); /* nothing to do */ 508 return ((dv->rule.action == DEFLECT_REPORT) ? 0 : 2); /* nothing to do */
512 } 509 }
@@ -519,8 +516,8 @@ static int isdn_divert_icall(isdn_ctrl *ic)
519 break; 516 break;
520 } /* scan_table */ 517 } /* scan_table */
521 518
522 if (cs) 519 if (cs) {
523 { cs->prev = NULL; 520 cs->prev = NULL;
524 spin_lock_irqsave(&divert_lock, flags); 521 spin_lock_irqsave(&divert_lock, flags);
525 cs->next = divert_head; 522 cs->next = divert_head;
526 divert_head = cs; 523 divert_head = cs;
@@ -529,21 +526,21 @@ static int isdn_divert_icall(isdn_ctrl *ic)
529 526
530 put_info_buffer(cs->info); 527 put_info_buffer(cs->info);
531 return (retval); 528 return (retval);
532 } 529 } else
533 else
534 return (0); 530 return (0);
535} /* isdn_divert_icall */ 531} /* isdn_divert_icall */
536 532
537 533
538void deleteprocs(void) 534void deleteprocs(void)
539{ struct call_struc *cs, *cs1; 535{
536 struct call_struc *cs, *cs1;
540 unsigned long flags; 537 unsigned long flags;
541 538
542 spin_lock_irqsave(&divert_lock, flags); 539 spin_lock_irqsave(&divert_lock, flags);
543 cs = divert_head; 540 cs = divert_head;
544 divert_head = NULL; 541 divert_head = NULL;
545 while (cs) 542 while (cs) {
546 { del_timer(&cs->timer); 543 del_timer(&cs->timer);
547 cs1 = cs; 544 cs1 = cs;
548 cs = cs->next; 545 cs = cs->next;
549 kfree(cs1); 546 kfree(cs1);
@@ -555,12 +552,13 @@ void deleteprocs(void)
555/* put a address including address type into buffer */ 552/* put a address including address type into buffer */
556/****************************************************/ 553/****************************************************/
557static int put_address(char *st, u_char *p, int len) 554static int put_address(char *st, u_char *p, int len)
558{ u_char retval = 0; 555{
556 u_char retval = 0;
559 u_char adr_typ = 0; /* network standard */ 557 u_char adr_typ = 0; /* network standard */
560 558
561 if (len < 2) return (retval); 559 if (len < 2) return (retval);
562 if (*p == 0xA1) 560 if (*p == 0xA1) {
563 { retval = *(++p) + 2; /* total length */ 561 retval = *(++p) + 2; /* total length */
564 if (retval > len) return (0); /* too short */ 562 if (retval > len) return (0); /* too short */
565 len = retval - 2; /* remaining length */ 563 len = retval - 2; /* remaining length */
566 if (len < 3) return (0); 564 if (len < 3) return (0);
@@ -572,16 +570,13 @@ static int put_address(char *st, u_char *p, int len)
572 if (*p++ != 0x12) return (0); 570 if (*p++ != 0x12) return (0);
573 if (*p > len) return (0); /* check number length */ 571 if (*p > len) return (0); /* check number length */
574 len = *p++; 572 len = *p++;
575 } 573 } else if (*p == 0x80) {
576 else 574 retval = *(++p) + 2; /* total length */
577 if (*p == 0x80) 575 if (retval > len) return (0);
578 { retval = *(++p) + 2; /* total length */ 576 len = retval - 2;
579 if (retval > len) return (0); 577 p++;
580 len = retval - 2; 578 } else
581 p++; 579 return (0); /* invalid address information */
582 }
583 else
584 return (0); /* invalid address information */
585 580
586 sprintf(st, "%d ", adr_typ); 581 sprintf(st, "%d ", adr_typ);
587 st += strlen(st); 582 st += strlen(st);
@@ -598,7 +593,8 @@ static int put_address(char *st, u_char *p, int len)
598/* report a successful interrogation */ 593/* report a successful interrogation */
599/*************************************/ 594/*************************************/
600static int interrogate_success(isdn_ctrl *ic, struct call_struc *cs) 595static int interrogate_success(isdn_ctrl *ic, struct call_struc *cs)
601{ char *src = ic->parm.dss1_io.data; 596{
597 char *src = ic->parm.dss1_io.data;
602 int restlen = ic->parm.dss1_io.datalen; 598 int restlen = ic->parm.dss1_io.datalen;
603 int cnt = 1; 599 int cnt = 1;
604 u_char n, n1; 600 u_char n, n1;
@@ -608,50 +604,44 @@ static int interrogate_success(isdn_ctrl *ic, struct call_struc *cs)
608 if (*src++ != 0x30) return (-101); 604 if (*src++ != 0x30) return (-101);
609 if ((n = *src++) > 0x81) return (-102); /* invalid length field */ 605 if ((n = *src++) > 0x81) return (-102); /* invalid length field */
610 restlen -= 2; /* remaining bytes */ 606 restlen -= 2; /* remaining bytes */
611 if (n == 0x80) 607 if (n == 0x80) {
612 { if (restlen < 2) return (-103); 608 if (restlen < 2) return (-103);
613 if ((*(src + restlen - 1)) || (*(src + restlen - 2))) return (-104); 609 if ((*(src + restlen - 1)) || (*(src + restlen - 2))) return (-104);
614 restlen -= 2; 610 restlen -= 2;
615 } 611 } else if (n == 0x81) {
612 n = *src++;
613 restlen--;
614 if (n > restlen) return (-105);
615 restlen = n;
616 } else if (n > restlen)
617 return (-106);
616 else 618 else
617 if (n == 0x81) 619 restlen = n; /* standard format */
618 { n = *src++;
619 restlen--;
620 if (n > restlen) return (-105);
621 restlen = n;
622 }
623 else
624 if (n > restlen) return (-106);
625 else
626 restlen = n; /* standard format */
627 if (restlen < 3) return (-107); /* no procedure */ 620 if (restlen < 3) return (-107); /* no procedure */
628 if ((*src++ != 2) || (*src++ != 1) || (*src++ != 0x0B)) return (-108); 621 if ((*src++ != 2) || (*src++ != 1) || (*src++ != 0x0B)) return (-108);
629 restlen -= 3; 622 restlen -= 3;
630 if (restlen < 2) return (-109); /* list missing */ 623 if (restlen < 2) return (-109); /* list missing */
631 if (*src == 0x31) 624 if (*src == 0x31) {
632 { src++; 625 src++;
633 if ((n = *src++) > 0x81) return (-110); /* invalid length field */ 626 if ((n = *src++) > 0x81) return (-110); /* invalid length field */
634 restlen -= 2; /* remaining bytes */ 627 restlen -= 2; /* remaining bytes */
635 if (n == 0x80) 628 if (n == 0x80) {
636 { if (restlen < 2) return (-111); 629 if (restlen < 2) return (-111);
637 if ((*(src + restlen - 1)) || (*(src + restlen - 2))) return (-112); 630 if ((*(src + restlen - 1)) || (*(src + restlen - 2))) return (-112);
638 restlen -= 2; 631 restlen -= 2;
639 } 632 } else if (n == 0x81) {
633 n = *src++;
634 restlen--;
635 if (n > restlen) return (-113);
636 restlen = n;
637 } else if (n > restlen)
638 return (-114);
640 else 639 else
641 if (n == 0x81) 640 restlen = n; /* standard format */
642 { n = *src++;
643 restlen--;
644 if (n > restlen) return (-113);
645 restlen = n;
646 }
647 else
648 if (n > restlen) return (-114);
649 else
650 restlen = n; /* standard format */
651 } /* result list header */ 641 } /* result list header */
652 642
653 while (restlen >= 2) 643 while (restlen >= 2) {
654 { stp = st; 644 stp = st;
655 sprintf(stp, "%d 0x%lx %d %s ", DIVERT_REPORT, ic->parm.dss1_io.ll_id, 645 sprintf(stp, "%d 0x%lx %d %s ", DIVERT_REPORT, ic->parm.dss1_io.ll_id,
656 cnt++, divert_if.drv_to_name(ic->driver)); 646 cnt++, divert_if.drv_to_name(ic->driver));
657 stp += strlen(stp); 647 stp += strlen(stp);
@@ -674,8 +664,8 @@ static int interrogate_success(isdn_ctrl *ic, struct call_struc *cs)
674 sprintf(stp, "%d ", (*p++) & 0xFF); 664 sprintf(stp, "%d ", (*p++) & 0xFF);
675 stp += strlen(stp); 665 stp += strlen(stp);
676 n -= 6; 666 n -= 6;
677 if (n > 2) 667 if (n > 2) {
678 { if (*p++ != 0x30) continue; 668 if (*p++ != 0x30) continue;
679 if (*p > (n - 2)) continue; 669 if (*p > (n - 2)) continue;
680 n = *p++; 670 n = *p++;
681 if (!(n1 = put_address(stp, p, n & 0xFF))) continue; 671 if (!(n1 = put_address(stp, p, n & 0xFF))) continue;
@@ -692,58 +682,58 @@ static int interrogate_success(isdn_ctrl *ic, struct call_struc *cs)
692/* callback for protocol specific extensions */ 682/* callback for protocol specific extensions */
693/*********************************************/ 683/*********************************************/
694static int prot_stat_callback(isdn_ctrl *ic) 684static int prot_stat_callback(isdn_ctrl *ic)
695{ struct call_struc *cs, *cs1; 685{
686 struct call_struc *cs, *cs1;
696 int i; 687 int i;
697 unsigned long flags; 688 unsigned long flags;
698 689
699 cs = divert_head; /* start of list */ 690 cs = divert_head; /* start of list */
700 cs1 = NULL; 691 cs1 = NULL;
701 while (cs) 692 while (cs) {
702 { if (ic->driver == cs->ics.driver) 693 if (ic->driver == cs->ics.driver) {
703 { switch (cs->ics.arg) 694 switch (cs->ics.arg) {
704 { case DSS1_CMD_INVOKE: 695 case DSS1_CMD_INVOKE:
705 if ((cs->ics.parm.dss1_io.ll_id == ic->parm.dss1_io.ll_id) && 696 if ((cs->ics.parm.dss1_io.ll_id == ic->parm.dss1_io.ll_id) &&
706 (cs->ics.parm.dss1_io.hl_id == ic->parm.dss1_io.hl_id)) 697 (cs->ics.parm.dss1_io.hl_id == ic->parm.dss1_io.hl_id)) {
707 { switch (ic->arg) 698 switch (ic->arg) {
708 { case DSS1_STAT_INVOKE_ERR: 699 case DSS1_STAT_INVOKE_ERR:
709 sprintf(cs->info, "128 0x%lx 0x%x\n", 700 sprintf(cs->info, "128 0x%lx 0x%x\n",
710 ic->parm.dss1_io.ll_id, 701 ic->parm.dss1_io.ll_id,
711 ic->parm.dss1_io.timeout); 702 ic->parm.dss1_io.timeout);
712 put_info_buffer(cs->info); 703 put_info_buffer(cs->info);
713 break; 704 break;
714 705
715 case DSS1_STAT_INVOKE_RES: 706 case DSS1_STAT_INVOKE_RES:
716 switch (cs->ics.parm.dss1_io.proc) 707 switch (cs->ics.parm.dss1_io.proc) {
717 { case 7: 708 case 7:
718 case 8: 709 case 8:
719 put_info_buffer(cs->info); 710 put_info_buffer(cs->info);
720 break; 711 break;
721
722 case 11:
723 i = interrogate_success(ic, cs);
724 if (i)
725 sprintf(cs->info, "%d 0x%lx %d\n", DIVERT_REPORT,
726 ic->parm.dss1_io.ll_id, i);
727 put_info_buffer(cs->info);
728 break;
729
730 default:
731 printk(KERN_WARNING "dss1_divert: unknown proc %d\n", cs->ics.parm.dss1_io.proc);
732 break;
733 }
734
735 712
713 case 11:
714 i = interrogate_success(ic, cs);
715 if (i)
716 sprintf(cs->info, "%d 0x%lx %d\n", DIVERT_REPORT,
717 ic->parm.dss1_io.ll_id, i);
718 put_info_buffer(cs->info);
736 break; 719 break;
737 720
738 default: 721 default:
739 printk(KERN_WARNING "dss1_divert unknown invoke answer %lx\n", ic->arg); 722 printk(KERN_WARNING "dss1_divert: unknown proc %d\n", cs->ics.parm.dss1_io.proc);
740 break; 723 break;
741 } 724 }
742 cs1 = cs; /* remember structure */ 725
743 cs = NULL; 726 break;
744 continue; /* abort search */ 727
745 } /* id found */ 728 default:
746 break; 729 printk(KERN_WARNING "dss1_divert unknown invoke answer %lx\n", ic->arg);
730 break;
731 }
732 cs1 = cs; /* remember structure */
733 cs = NULL;
734 continue; /* abort search */
735 } /* id found */
736 break;
747 737
748 case DSS1_CMD_INVOKE_ABORT: 738 case DSS1_CMD_INVOKE_ABORT:
749 printk(KERN_WARNING "dss1_divert unhandled invoke abort\n"); 739 printk(KERN_WARNING "dss1_divert unhandled invoke abort\n");
@@ -757,13 +747,12 @@ static int prot_stat_callback(isdn_ctrl *ic)
757 } /* driver ok */ 747 } /* driver ok */
758 } 748 }
759 749
760 if (!cs1) 750 if (!cs1) {
761 { printk(KERN_WARNING "dss1_divert unhandled process\n"); 751 printk(KERN_WARNING "dss1_divert unhandled process\n");
762 return (0); 752 return (0);
763 } 753 }
764 754
765 if (cs1->ics.driver == -1) 755 if (cs1->ics.driver == -1) {
766 {
767 spin_lock_irqsave(&divert_lock, flags); 756 spin_lock_irqsave(&divert_lock, flags);
768 del_timer(&cs1->timer); 757 del_timer(&cs1->timer);
769 if (cs1->prev) 758 if (cs1->prev)
@@ -784,20 +773,22 @@ static int prot_stat_callback(isdn_ctrl *ic)
784/* status callback from HL */ 773/* status callback from HL */
785/***************************/ 774/***************************/
786static int isdn_divert_stat_callback(isdn_ctrl *ic) 775static int isdn_divert_stat_callback(isdn_ctrl *ic)
787{ struct call_struc *cs, *cs1; 776{
777 struct call_struc *cs, *cs1;
788 unsigned long flags; 778 unsigned long flags;
789 int retval; 779 int retval;
790 780
791 retval = -1; 781 retval = -1;
792 cs = divert_head; /* start of list */ 782 cs = divert_head; /* start of list */
793 while (cs) 783 while (cs) {
794 { if ((ic->driver == cs->ics.driver) && (ic->arg == cs->ics.arg)) 784 if ((ic->driver == cs->ics.driver) &&
795 { switch (ic->command) 785 (ic->arg == cs->ics.arg)) {
796 { case ISDN_STAT_DHUP: 786 switch (ic->command) {
797 sprintf(cs->info, "129 0x%lx\n", cs->divert_id); 787 case ISDN_STAT_DHUP:
798 del_timer(&cs->timer); 788 sprintf(cs->info, "129 0x%lx\n", cs->divert_id);
799 cs->ics.driver = -1; 789 del_timer(&cs->timer);
800 break; 790 cs->ics.driver = -1;
791 break;
801 792
802 case ISDN_STAT_CAUSE: 793 case ISDN_STAT_CAUSE:
803 sprintf(cs->info, "130 0x%lx %s\n", cs->divert_id, ic->parm.num); 794 sprintf(cs->info, "130 0x%lx %s\n", cs->divert_id, ic->parm.num);
@@ -818,8 +809,7 @@ static int isdn_divert_stat_callback(isdn_ctrl *ic)
818 } 809 }
819 cs1 = cs; 810 cs1 = cs;
820 cs = cs->next; 811 cs = cs->next;
821 if (cs1->ics.driver == -1) 812 if (cs1->ics.driver == -1) {
822 {
823 spin_lock_irqsave(&divert_lock, flags); 813 spin_lock_irqsave(&divert_lock, flags);
824 if (cs1->prev) 814 if (cs1->prev)
825 cs1->prev->next = cs1->next; /* forward link */ 815 cs1->prev->next = cs1->next; /* forward link */
@@ -840,20 +830,19 @@ static int isdn_divert_stat_callback(isdn_ctrl *ic)
840/********************/ 830/********************/
841int ll_callback(isdn_ctrl *ic) 831int ll_callback(isdn_ctrl *ic)
842{ 832{
843 switch (ic->command) 833 switch (ic->command) {
844 { case ISDN_STAT_ICALL: 834 case ISDN_STAT_ICALL:
845 case ISDN_STAT_ICALLW: 835 case ISDN_STAT_ICALLW:
846 return (isdn_divert_icall(ic)); 836 return (isdn_divert_icall(ic));
847 break; 837 break;
848 838
849 case ISDN_STAT_PROT: 839 case ISDN_STAT_PROT:
850 if ((ic->arg & 0xFF) == ISDN_PTYPE_EURO) 840 if ((ic->arg & 0xFF) == ISDN_PTYPE_EURO) {
851 { if (ic->arg != DSS1_STAT_INVOKE_BRD) 841 if (ic->arg != DSS1_STAT_INVOKE_BRD)
852 return (prot_stat_callback(ic)); 842 return (prot_stat_callback(ic));
853 else 843 else
854 return (0); /* DSS1 invoke broadcast */ 844 return (0); /* DSS1 invoke broadcast */
855 } 845 } else
856 else
857 return (-1); /* protocol not euro */ 846 return (-1); /* protocol not euro */
858 847
859 default: 848 default:
diff --git a/drivers/isdn/divert/isdn_divert.h b/drivers/isdn/divert/isdn_divert.h
index 42f289320d2d..55033dd872c0 100644
--- a/drivers/isdn/divert/isdn_divert.h
+++ b/drivers/isdn/divert/isdn_divert.h
@@ -43,8 +43,8 @@
43 43
44#define DEFLECT_ALL_IDS 0xFFFFFFFF /* all drivers selected */ 44#define DEFLECT_ALL_IDS 0xFFFFFFFF /* all drivers selected */
45 45
46typedef struct 46typedef struct {
47{ ulong drvid; /* driver ids, bit mapped */ 47 ulong drvid; /* driver ids, bit mapped */
48 char my_msn[35]; /* desired msn, subaddr allowed */ 48 char my_msn[35]; /* desired msn, subaddr allowed */
49 char caller[35]; /* caller id, partial string with * + subaddr allowed */ 49 char caller[35]; /* caller id, partial string with * + subaddr allowed */
50 char to_nr[35]; /* deflected to number incl. subaddress */ 50 char to_nr[35]; /* deflected to number incl. subaddress */
@@ -65,18 +65,18 @@ typedef struct
65 u_char waittime; /* maximum wait time for proceeding */ 65 u_char waittime; /* maximum wait time for proceeding */
66} divert_rule; 66} divert_rule;
67 67
68typedef union 68typedef union {
69{ int drv_version; /* return of driver version */ 69 int drv_version; /* return of driver version */
70 struct 70 struct {
71 { int drvid; /* id of driver */ 71 int drvid; /* id of driver */
72 char drvnam[30]; /* name of driver */ 72 char drvnam[30]; /* name of driver */
73 } getid; 73 } getid;
74 struct 74 struct {
75 { int ruleidx; /* index of rule */ 75 int ruleidx; /* index of rule */
76 divert_rule rule; /* rule parms */ 76 divert_rule rule; /* rule parms */
77 } getsetrule; 77 } getsetrule;
78 struct 78 struct {
79 { u_char subcmd; /* 0 = hangup/reject, 79 u_char subcmd; /* 0 = hangup/reject,
80 1 = alert, 80 1 = alert,
81 2 = deflect */ 81 2 = deflect */
82 ulong callid; /* id of call delivered by ascii output */ 82 ulong callid; /* id of call delivered by ascii output */
@@ -84,8 +84,8 @@ typedef union
84 else uus1 string (maxlen 31), 84 else uus1 string (maxlen 31),
85 data from rule used if empty */ 85 data from rule used if empty */
86 } fwd_ctrl; 86 } fwd_ctrl;
87 struct 87 struct {
88 { int drvid; /* id of driver */ 88 int drvid; /* id of driver */
89 u_char cfproc; /* cfu = 0, cfb = 1, cfnr = 2 */ 89 u_char cfproc; /* cfu = 0, cfb = 1, cfnr = 2 */
90 ulong procid; /* process id returned when no error */ 90 ulong procid; /* process id returned when no error */
91 u_char service; /* basically coded service, 0 = all */ 91 u_char service; /* basically coded service, 0 = all */
@@ -104,8 +104,8 @@ typedef union
104/**************************************************/ 104/**************************************************/
105/* structure keeping ascii info for device output */ 105/* structure keeping ascii info for device output */
106/**************************************************/ 106/**************************************************/
107struct divert_info 107struct divert_info {
108{ struct divert_info *next; 108 struct divert_info *next;
109 ulong usage_cnt; /* number of files still to work */ 109 ulong usage_cnt; /* number of files still to work */
110 char info_start[2]; /* info string start */ 110 char info_start[2]; /* info string start */
111}; 111};