Merge with Linux 2.4.0-test6-pre9.
[linux-2.6/linux-mips.git] / drivers / isdn / hisax / l3dss1.c
blob32ae7576f95db049150c442759c712ec0c280f84
1 /* $Id: l3dss1.c,v 2.29 2000/06/26 08:59:14 keil Exp $
3 * EURO/DSS1 D-channel protocol
5 * Author Karsten Keil (keil@isdn4linux.de)
6 * based on the teles driver from Jan den Ouden
8 * This file is (c) under GNU PUBLIC LICENSE
9 * For changes and modifications please read
10 * ../../../Documentation/isdn/HiSax.cert
12 * Thanks to Jan den Ouden
13 * Fritz Elfert
17 #define __NO_VERSION__
18 #include "hisax.h"
19 #include "isdnl3.h"
20 #include "l3dss1.h"
21 #include <linux/ctype.h>
22 #include <linux/config.h>
24 extern char *HiSax_getrev(const char *revision);
25 const char *dss1_revision = "$Revision: 2.29 $";
27 #define EXT_BEARER_CAPS 1
29 #define MsgHead(ptr, cref, mty) \
30 *ptr++ = 0x8; \
31 if (cref == -1) { \
32 *ptr++ = 0x0; \
33 } else { \
34 *ptr++ = 0x1; \
35 *ptr++ = cref^0x80; \
36 } \
37 *ptr++ = mty
40 /**********************************************/
41 /* get a new invoke id for remote operations. */
42 /* Only a return value != 0 is valid */
43 /**********************************************/
44 static unsigned char new_invoke_id(struct PStack *p)
46 unsigned char retval;
47 int flags,i;
49 i = 32; /* maximum search depth */
51 save_flags(flags);
52 cli();
54 retval = p->prot.dss1.last_invoke_id + 1; /* try new id */
55 while ((i) && (p->prot.dss1.invoke_used[retval >> 3] == 0xFF)) {
56 p->prot.dss1.last_invoke_id = (retval & 0xF8) + 8;
57 i--;
59 if (i) {
60 while (p->prot.dss1.invoke_used[retval >> 3] & (1 << (retval & 7)))
61 retval++;
62 } else
63 retval = 0;
64 p->prot.dss1.last_invoke_id = retval;
65 p->prot.dss1.invoke_used[retval >> 3] |= (1 << (retval & 7));
66 restore_flags(flags);
68 return(retval);
69 } /* new_invoke_id */
71 /*************************/
72 /* free a used invoke id */
73 /*************************/
74 static void free_invoke_id(struct PStack *p, unsigned char id)
75 { int flags;
77 if (!id) return; /* 0 = invalid value */
79 save_flags(flags);
80 cli();
81 p->prot.dss1.invoke_used[id >> 3] &= ~(1 << (id & 7));
82 restore_flags(flags);
83 } /* free_invoke_id */
86 /**********************************************************/
87 /* create a new l3 process and fill in dss1 specific data */
88 /**********************************************************/
89 static struct l3_process
90 *dss1_new_l3_process(struct PStack *st, int cr)
91 { struct l3_process *proc;
93 if (!(proc = new_l3_process(st, cr)))
94 return(NULL);
96 proc->prot.dss1.invoke_id = 0;
97 proc->prot.dss1.remote_operation = 0;
98 proc->prot.dss1.uus1_data[0] = '\0';
100 return(proc);
101 } /* dss1_new_l3_process */
103 /************************************************/
104 /* free a l3 process and all dss1 specific data */
105 /************************************************/
106 static void
107 dss1_release_l3_process(struct l3_process *p)
109 free_invoke_id(p->st,p->prot.dss1.invoke_id);
110 release_l3_process(p);
111 } /* dss1_release_l3_process */
113 /********************************************************/
114 /* search a process with invoke id id and dummy callref */
115 /********************************************************/
116 static struct l3_process *
117 l3dss1_search_dummy_proc(struct PStack *st, int id)
118 { struct l3_process *pc = st->l3.proc; /* start of processes */
120 if (!id) return(NULL);
122 while (pc)
123 { if ((pc->callref == -1) && (pc->prot.dss1.invoke_id == id))
124 return(pc);
125 pc = pc->next;
127 return(NULL);
128 } /* l3dss1_search_dummy_proc */
130 /*******************************************************************/
131 /* called when a facility message with a dummy callref is received */
132 /* and a return result is delivered. id specifies the invoke id. */
133 /*******************************************************************/
134 static void
135 l3dss1_dummy_return_result(struct PStack *st, int id, u_char *p, u_char nlen)
136 { isdn_ctrl ic;
137 struct IsdnCardState *cs;
138 struct l3_process *pc = NULL;
140 if ((pc = l3dss1_search_dummy_proc(st, id)))
141 { L3DelTimer(&pc->timer); /* remove timer */
143 cs = pc->st->l1.hardware;
144 ic.driver = cs->myid;
145 ic.command = ISDN_STAT_PROT;
146 ic.arg = DSS1_STAT_INVOKE_RES;
147 ic.parm.dss1_io.hl_id = pc->prot.dss1.invoke_id;
148 ic.parm.dss1_io.ll_id = pc->prot.dss1.ll_id;
149 ic.parm.dss1_io.proc = pc->prot.dss1.proc;
150 ic.parm.dss1_io.timeout= 0;
151 ic.parm.dss1_io.datalen = nlen;
152 ic.parm.dss1_io.data = p;
153 free_invoke_id(pc->st, pc->prot.dss1.invoke_id);
154 pc->prot.dss1.invoke_id = 0; /* reset id */
156 cs->iif.statcallb(&ic);
157 dss1_release_l3_process(pc);
159 else
160 l3_debug(st, "dummy return result id=0x%x result len=%d",id,nlen);
161 } /* l3dss1_dummy_return_result */
163 /*******************************************************************/
164 /* called when a facility message with a dummy callref is received */
165 /* and a return error is delivered. id specifies the invoke id. */
166 /*******************************************************************/
167 static void
168 l3dss1_dummy_error_return(struct PStack *st, int id, ulong error)
169 { isdn_ctrl ic;
170 struct IsdnCardState *cs;
171 struct l3_process *pc = NULL;
173 if ((pc = l3dss1_search_dummy_proc(st, id)))
174 { L3DelTimer(&pc->timer); /* remove timer */
176 cs = pc->st->l1.hardware;
177 ic.driver = cs->myid;
178 ic.command = ISDN_STAT_PROT;
179 ic.arg = DSS1_STAT_INVOKE_ERR;
180 ic.parm.dss1_io.hl_id = pc->prot.dss1.invoke_id;
181 ic.parm.dss1_io.ll_id = pc->prot.dss1.ll_id;
182 ic.parm.dss1_io.proc = pc->prot.dss1.proc;
183 ic.parm.dss1_io.timeout= error;
184 ic.parm.dss1_io.datalen = 0;
185 ic.parm.dss1_io.data = NULL;
186 free_invoke_id(pc->st, pc->prot.dss1.invoke_id);
187 pc->prot.dss1.invoke_id = 0; /* reset id */
189 cs->iif.statcallb(&ic);
190 dss1_release_l3_process(pc);
192 else
193 l3_debug(st, "dummy return error id=0x%x error=0x%lx",id,error);
194 } /* l3dss1_error_return */
196 /*******************************************************************/
197 /* called when a facility message with a dummy callref is received */
198 /* and a invoke is delivered. id specifies the invoke id. */
199 /*******************************************************************/
200 static void
201 l3dss1_dummy_invoke(struct PStack *st, int cr, int id,
202 int ident, u_char *p, u_char nlen)
203 { isdn_ctrl ic;
204 struct IsdnCardState *cs;
206 l3_debug(st, "dummy invoke %s id=0x%x ident=0x%x datalen=%d",
207 (cr == -1) ? "local" : "broadcast",id,ident,nlen);
208 if (cr >= -1) return; /* ignore local data */
210 cs = st->l1.hardware;
211 ic.driver = cs->myid;
212 ic.command = ISDN_STAT_PROT;
213 ic.arg = DSS1_STAT_INVOKE_BRD;
214 ic.parm.dss1_io.hl_id = id;
215 ic.parm.dss1_io.ll_id = 0;
216 ic.parm.dss1_io.proc = ident;
217 ic.parm.dss1_io.timeout= 0;
218 ic.parm.dss1_io.datalen = nlen;
219 ic.parm.dss1_io.data = p;
221 cs->iif.statcallb(&ic);
222 } /* l3dss1_dummy_invoke */
224 static void
225 l3dss1_parse_facility(struct PStack *st, struct l3_process *pc,
226 int cr, u_char * p)
228 int qd_len = 0;
229 unsigned char nlen = 0, ilen, cp_tag;
230 int ident, id;
231 ulong err_ret;
233 if (pc)
234 st = pc->st; /* valid Stack */
235 else
236 if ((!st) || (cr >= 0)) return; /* neither pc nor st specified */
238 p++;
239 qd_len = *p++;
240 if (qd_len == 0) {
241 l3_debug(st, "qd_len == 0");
242 return;
244 if ((*p & 0x1F) != 0x11) { /* Service discriminator, supplementary service */
245 l3_debug(st, "supplementary service != 0x11");
246 return;
248 while (qd_len > 0 && !(*p & 0x80)) { /* extension ? */
249 p++;
250 qd_len--;
252 if (qd_len < 2) {
253 l3_debug(st, "qd_len < 2");
254 return;
256 p++;
257 qd_len--;
258 if ((*p & 0xE0) != 0xA0) { /* class and form */
259 l3_debug(st, "class and form != 0xA0");
260 return;
263 cp_tag = *p & 0x1F; /* remember tag value */
265 p++;
266 qd_len--;
267 if (qd_len < 1)
268 { l3_debug(st, "qd_len < 1");
269 return;
271 if (*p & 0x80)
272 { /* length format indefinite or limited */
273 nlen = *p++ & 0x7F; /* number of len bytes or indefinite */
274 if ((qd_len-- < ((!nlen) ? 3 : (1 + nlen))) ||
275 (nlen > 1))
276 { l3_debug(st, "length format error or not implemented");
277 return;
279 if (nlen == 1)
280 { nlen = *p++; /* complete length */
281 qd_len--;
283 else
284 { qd_len -= 2; /* trailing null bytes */
285 if ((*(p+qd_len)) || (*(p+qd_len+1)))
286 { l3_debug(st,"length format indefinite error");
287 return;
289 nlen = qd_len;
292 else
293 { nlen = *p++;
294 qd_len--;
296 if (qd_len < nlen)
297 { l3_debug(st, "qd_len < nlen");
298 return;
300 qd_len -= nlen;
302 if (nlen < 2)
303 { l3_debug(st, "nlen < 2");
304 return;
306 if (*p != 0x02)
307 { /* invoke identifier tag */
308 l3_debug(st, "invoke identifier tag !=0x02");
309 return;
311 p++;
312 nlen--;
313 if (*p & 0x80)
314 { /* length format */
315 l3_debug(st, "invoke id length format 2");
316 return;
318 ilen = *p++;
319 nlen--;
320 if (ilen > nlen || ilen == 0)
321 { l3_debug(st, "ilen > nlen || ilen == 0");
322 return;
324 nlen -= ilen;
325 id = 0;
326 while (ilen > 0)
327 { id = (id << 8) | (*p++ & 0xFF); /* invoke identifier */
328 ilen--;
331 switch (cp_tag) { /* component tag */
332 case 1: /* invoke */
333 if (nlen < 2) {
334 l3_debug(st, "nlen < 2 22");
335 return;
337 if (*p != 0x02) { /* operation value */
338 l3_debug(st, "operation value !=0x02");
339 return;
341 p++;
342 nlen--;
343 ilen = *p++;
344 nlen--;
345 if (ilen > nlen || ilen == 0) {
346 l3_debug(st, "ilen > nlen || ilen == 0 22");
347 return;
349 nlen -= ilen;
350 ident = 0;
351 while (ilen > 0) {
352 ident = (ident << 8) | (*p++ & 0xFF);
353 ilen--;
356 if (!pc)
357 { l3dss1_dummy_invoke(st, cr, id, ident, p, nlen);
358 return;
360 #if HISAX_DE_AOC
363 #define FOO1(s,a,b) \
364 while(nlen > 1) { \
365 int ilen = p[1]; \
366 if(nlen < ilen+2) { \
367 l3_debug(st, "FOO1 nlen < ilen+2"); \
368 return; \
370 nlen -= ilen+2; \
371 if((*p & 0xFF) == (a)) { \
372 int nlen = ilen; \
373 p += 2; \
374 b; \
375 } else { \
376 p += ilen+2; \
380 switch (ident) {
381 case 0x22: /* during */
382 FOO1("1A", 0x30, FOO1("1C", 0xA1, FOO1("1D", 0x30, FOO1("1E", 0x02, ( {
383 ident = 0;
384 nlen = (nlen)?nlen:0; /* Make gcc happy */
385 while (ilen > 0) {
386 ident = (ident << 8) | *p++;
387 ilen--;
389 if (ident > pc->para.chargeinfo) {
390 pc->para.chargeinfo = ident;
391 st->l3.l3l4(st, CC_CHARGE | INDICATION, pc);
393 if (st->l3.debug & L3_DEB_CHARGE) {
394 if (*(p + 2) == 0) {
395 l3_debug(st, "charging info during %d", pc->para.chargeinfo);
397 else {
398 l3_debug(st, "charging info final %d", pc->para.chargeinfo);
402 )))))
403 break;
404 case 0x24: /* final */
405 FOO1("2A", 0x30, FOO1("2B", 0x30, FOO1("2C", 0xA1, FOO1("2D", 0x30, FOO1("2E", 0x02, ( {
406 ident = 0;
407 nlen = (nlen)?nlen:0; /* Make gcc happy */
408 while (ilen > 0) {
409 ident = (ident << 8) | *p++;
410 ilen--;
412 if (ident > pc->para.chargeinfo) {
413 pc->para.chargeinfo = ident;
414 st->l3.l3l4(st, CC_CHARGE | INDICATION, pc);
416 if (st->l3.debug & L3_DEB_CHARGE) {
417 l3_debug(st, "charging info final %d", pc->para.chargeinfo);
420 ))))))
421 break;
422 default:
423 l3_debug(st, "invoke break invalid ident %02x",ident);
424 break;
426 #undef FOO1
429 #else not HISAX_DE_AOC
430 l3_debug(st, "invoke break");
431 #endif not HISAX_DE_AOC
432 break;
433 case 2: /* return result */
434 /* if no process available handle separately */
435 if (!pc)
436 { if (cr == -1)
437 l3dss1_dummy_return_result(st, id, p, nlen);
438 return;
440 if ((pc->prot.dss1.invoke_id) && (pc->prot.dss1.invoke_id == id))
441 { /* Diversion successfull */
442 free_invoke_id(st,pc->prot.dss1.invoke_id);
443 pc->prot.dss1.remote_result = 0; /* success */
444 pc->prot.dss1.invoke_id = 0;
445 pc->redir_result = pc->prot.dss1.remote_result;
446 st->l3.l3l4(st, CC_REDIR | INDICATION, pc); } /* Diversion successfull */
447 else
448 l3_debug(st,"return error unknown identifier");
449 break;
450 case 3: /* return error */
451 err_ret = 0;
452 if (nlen < 2)
453 { l3_debug(st, "return error nlen < 2");
454 return;
456 if (*p != 0x02)
457 { /* result tag */
458 l3_debug(st, "invoke error tag !=0x02");
459 return;
461 p++;
462 nlen--;
463 if (*p > 4)
464 { /* length format */
465 l3_debug(st, "invoke return errlen > 4 ");
466 return;
468 ilen = *p++;
469 nlen--;
470 if (ilen > nlen || ilen == 0)
471 { l3_debug(st, "error return ilen > nlen || ilen == 0");
472 return;
474 nlen -= ilen;
475 while (ilen > 0)
476 { err_ret = (err_ret << 8) | (*p++ & 0xFF); /* error value */
477 ilen--;
479 /* if no process available handle separately */
480 if (!pc)
481 { if (cr == -1)
482 l3dss1_dummy_error_return(st, id, err_ret);
483 return;
485 if ((pc->prot.dss1.invoke_id) && (pc->prot.dss1.invoke_id == id))
486 { /* Deflection error */
487 free_invoke_id(st,pc->prot.dss1.invoke_id);
488 pc->prot.dss1.remote_result = err_ret; /* result */
489 pc->prot.dss1.invoke_id = 0;
490 pc->redir_result = pc->prot.dss1.remote_result;
491 st->l3.l3l4(st, CC_REDIR | INDICATION, pc);
492 } /* Deflection error */
493 else
494 l3_debug(st,"return result unknown identifier");
495 break;
496 default:
497 l3_debug(st, "facility default break tag=0x%02x",cp_tag);
498 break;
502 static void
503 l3dss1_message(struct l3_process *pc, u_char mt)
505 struct sk_buff *skb;
506 u_char *p;
508 if (!(skb = l3_alloc_skb(4)))
509 return;
510 p = skb_put(skb, 4);
511 MsgHead(p, pc->callref, mt);
512 l3_msg(pc->st, DL_DATA | REQUEST, skb);
515 static void
516 l3dss1_message_cause(struct l3_process *pc, u_char mt, u_char cause)
518 struct sk_buff *skb;
519 u_char tmp[16];
520 u_char *p = tmp;
521 int l;
523 MsgHead(p, pc->callref, mt);
524 *p++ = IE_CAUSE;
525 *p++ = 0x2;
526 *p++ = 0x80;
527 *p++ = cause | 0x80;
529 l = p - tmp;
530 if (!(skb = l3_alloc_skb(l)))
531 return;
532 memcpy(skb_put(skb, l), tmp, l);
533 l3_msg(pc->st, DL_DATA | REQUEST, skb);
536 static void
537 l3dss1_status_send(struct l3_process *pc, u_char pr, void *arg)
539 u_char tmp[16];
540 u_char *p = tmp;
541 int l;
542 struct sk_buff *skb;
544 MsgHead(p, pc->callref, MT_STATUS);
546 *p++ = IE_CAUSE;
547 *p++ = 0x2;
548 *p++ = 0x80;
549 *p++ = pc->para.cause | 0x80;
551 *p++ = IE_CALL_STATE;
552 *p++ = 0x1;
553 *p++ = pc->state & 0x3f;
555 l = p - tmp;
556 if (!(skb = l3_alloc_skb(l)))
557 return;
558 memcpy(skb_put(skb, l), tmp, l);
559 l3_msg(pc->st, DL_DATA | REQUEST, skb);
562 static void
563 l3dss1_msg_without_setup(struct l3_process *pc, u_char pr, void *arg)
565 /* This routine is called if here was no SETUP made (checks in dss1up and in
566 * l3dss1_setup) and a RELEASE_COMPLETE have to be sent with an error code
567 * MT_STATUS_ENQUIRE in the NULL state is handled too
569 u_char tmp[16];
570 u_char *p = tmp;
571 int l;
572 struct sk_buff *skb;
574 switch (pc->para.cause) {
575 case 81: /* invalid callreference */
576 case 88: /* incomp destination */
577 case 96: /* mandory IE missing */
578 case 100: /* invalid IE contents */
579 case 101: /* incompatible Callstate */
580 MsgHead(p, pc->callref, MT_RELEASE_COMPLETE);
581 *p++ = IE_CAUSE;
582 *p++ = 0x2;
583 *p++ = 0x80;
584 *p++ = pc->para.cause | 0x80;
585 break;
586 default:
587 printk(KERN_ERR "HiSax l3dss1_msg_without_setup wrong cause %d\n",
588 pc->para.cause);
589 return;
591 l = p - tmp;
592 if (!(skb = l3_alloc_skb(l)))
593 return;
594 memcpy(skb_put(skb, l), tmp, l);
595 l3_msg(pc->st, DL_DATA | REQUEST, skb);
596 dss1_release_l3_process(pc);
599 static int ie_ALERTING[] = {IE_BEARER, IE_CHANNEL_ID | IE_MANDATORY_1,
600 IE_FACILITY, IE_PROGRESS, IE_DISPLAY, IE_SIGNAL, IE_HLC,
601 IE_USER_USER, -1};
602 static int ie_CALL_PROCEEDING[] = {IE_BEARER, IE_CHANNEL_ID | IE_MANDATORY_1,
603 IE_FACILITY, IE_PROGRESS, IE_DISPLAY, IE_HLC, -1};
604 static int ie_CONNECT[] = {IE_BEARER, IE_CHANNEL_ID | IE_MANDATORY_1,
605 IE_FACILITY, IE_PROGRESS, IE_DISPLAY, IE_DATE, IE_SIGNAL,
606 IE_CONNECT_PN, IE_CONNECT_SUB, IE_LLC, IE_HLC, IE_USER_USER, -1};
607 static int ie_CONNECT_ACKNOWLEDGE[] = {IE_CHANNEL_ID, IE_DISPLAY, IE_SIGNAL, -1};
608 static int ie_DISCONNECT[] = {IE_CAUSE | IE_MANDATORY, IE_FACILITY,
609 IE_PROGRESS, IE_DISPLAY, IE_SIGNAL, IE_USER_USER, -1};
610 static int ie_INFORMATION[] = {IE_COMPLETE, IE_DISPLAY, IE_KEYPAD, IE_SIGNAL,
611 IE_CALLED_PN, -1};
612 static int ie_NOTIFY[] = {IE_BEARER, IE_NOTIFY | IE_MANDATORY, IE_DISPLAY, -1};
613 static int ie_PROGRESS[] = {IE_BEARER, IE_CAUSE, IE_FACILITY, IE_PROGRESS |
614 IE_MANDATORY, IE_DISPLAY, IE_HLC, IE_USER_USER, -1};
615 static int ie_RELEASE[] = {IE_CAUSE | IE_MANDATORY_1, IE_FACILITY, IE_DISPLAY,
616 IE_SIGNAL, IE_USER_USER, -1};
617 /* a RELEASE_COMPLETE with errors don't require special actions
618 static int ie_RELEASE_COMPLETE[] = {IE_CAUSE | IE_MANDATORY_1, IE_DISPLAY, IE_SIGNAL, IE_USER_USER, -1};
620 static int ie_RESUME_ACKNOWLEDGE[] = {IE_CHANNEL_ID| IE_MANDATORY, IE_FACILITY,
621 IE_DISPLAY, -1};
622 static int ie_RESUME_REJECT[] = {IE_CAUSE | IE_MANDATORY, IE_DISPLAY, -1};
623 static int ie_SETUP[] = {IE_COMPLETE, IE_BEARER | IE_MANDATORY,
624 IE_CHANNEL_ID| IE_MANDATORY, IE_FACILITY, IE_PROGRESS,
625 IE_NET_FAC, IE_DISPLAY, IE_KEYPAD, IE_SIGNAL, IE_CALLING_PN,
626 IE_CALLING_SUB, IE_CALLED_PN, IE_CALLED_SUB, IE_REDIR_NR,
627 IE_LLC, IE_HLC, IE_USER_USER, -1};
628 static int ie_SETUP_ACKNOWLEDGE[] = {IE_CHANNEL_ID | IE_MANDATORY, IE_FACILITY,
629 IE_PROGRESS, IE_DISPLAY, IE_SIGNAL, -1};
630 static int ie_STATUS[] = {IE_CAUSE | IE_MANDATORY, IE_CALL_STATE |
631 IE_MANDATORY, IE_DISPLAY, -1};
632 static int ie_STATUS_ENQUIRY[] = {IE_DISPLAY, -1};
633 static int ie_SUSPEND_ACKNOWLEDGE[] = {IE_DISPLAY, IE_FACILITY, -1};
634 static int ie_SUSPEND_REJECT[] = {IE_CAUSE | IE_MANDATORY, IE_DISPLAY, -1};
635 /* not used
636 * static int ie_CONGESTION_CONTROL[] = {IE_CONGESTION | IE_MANDATORY,
637 * IE_CAUSE | IE_MANDATORY, IE_DISPLAY, -1};
638 * static int ie_USER_INFORMATION[] = {IE_MORE_DATA, IE_USER_USER | IE_MANDATORY, -1};
639 * static int ie_RESTART[] = {IE_CHANNEL_ID, IE_DISPLAY, IE_RESTART_IND |
640 * IE_MANDATORY, -1};
642 static int ie_FACILITY[] = {IE_FACILITY | IE_MANDATORY, IE_DISPLAY, -1};
643 static int comp_required[] = {1,2,3,5,6,7,9,10,11,14,15,-1};
644 static int l3_valid_states[] = {0,1,2,3,4,6,7,8,9,10,11,12,15,17,19,25,-1};
646 struct ie_len {
647 int ie;
648 int len;
651 static
652 struct ie_len max_ie_len[] = {
653 {IE_SEGMENT, 4},
654 {IE_BEARER, 12},
655 {IE_CAUSE, 32},
656 {IE_CALL_ID, 10},
657 {IE_CALL_STATE, 3},
658 {IE_CHANNEL_ID, 34},
659 {IE_FACILITY, 255},
660 {IE_PROGRESS, 4},
661 {IE_NET_FAC, 255},
662 {IE_NOTIFY, 3},
663 {IE_DISPLAY, 82},
664 {IE_DATE, 8},
665 {IE_KEYPAD, 34},
666 {IE_SIGNAL, 3},
667 {IE_INFORATE, 6},
668 {IE_E2E_TDELAY, 11},
669 {IE_TDELAY_SEL, 5},
670 {IE_PACK_BINPARA, 3},
671 {IE_PACK_WINSIZE, 4},
672 {IE_PACK_SIZE, 4},
673 {IE_CUG, 7},
674 {IE_REV_CHARGE, 3},
675 {IE_CALLING_PN, 24},
676 {IE_CALLING_SUB, 23},
677 {IE_CALLED_PN, 24},
678 {IE_CALLED_SUB, 23},
679 {IE_REDIR_NR, 255},
680 {IE_TRANS_SEL, 255},
681 {IE_RESTART_IND, 3},
682 {IE_LLC, 18},
683 {IE_HLC, 5},
684 {IE_USER_USER, 131},
685 {-1,0},
688 static int
689 getmax_ie_len(u_char ie) {
690 int i = 0;
691 while (max_ie_len[i].ie != -1) {
692 if (max_ie_len[i].ie == ie)
693 return(max_ie_len[i].len);
694 i++;
696 return(255);
699 static int
700 ie_in_set(struct l3_process *pc, u_char ie, int *checklist) {
701 int ret = 1;
703 while (*checklist != -1) {
704 if ((*checklist & 0xff) == ie) {
705 if (ie & 0x80)
706 return(-ret);
707 else
708 return(ret);
710 ret++;
711 checklist++;
713 return(0);
716 static int
717 check_infoelements(struct l3_process *pc, struct sk_buff *skb, int *checklist)
719 int *cl = checklist;
720 u_char mt;
721 u_char *p, ie;
722 int l, newpos, oldpos;
723 int err_seq = 0, err_len = 0, err_compr = 0, err_ureg = 0;
725 p = skb->data;
726 /* skip cr */
727 p++;
728 l = (*p++) & 0xf;
729 p += l;
730 mt = *p++;
731 oldpos = 0;
732 /* shift codeset procedure not implemented in the moment */
733 while ((p - skb->data) < skb->len) {
734 if ((newpos = ie_in_set(pc, *p, cl))) {
735 if (newpos > 0) {
736 if (newpos < oldpos)
737 err_seq++;
738 else
739 oldpos = newpos;
741 } else {
742 if (ie_in_set(pc, *p, comp_required))
743 err_compr++;
744 else
745 err_ureg++;
747 ie = *p++;
748 if (ie & 0x80) {
749 l = 1;
750 } else {
751 l = *p++;
752 p += l;
753 l += 2;
755 if (l > getmax_ie_len(ie))
756 err_len++;
758 if (err_compr | err_ureg | err_len | err_seq) {
759 if (pc->debug & L3_DEB_CHECK)
760 l3_debug(pc->st, "check_infoelements mt %x %d/%d/%d/%d",
761 mt, err_compr, err_ureg, err_len, err_seq);
762 if (err_compr)
763 return(ERR_IE_COMPREHENSION);
764 if (err_ureg)
765 return(ERR_IE_UNRECOGNIZED);
766 if (err_len)
767 return(ERR_IE_LENGTH);
768 if (err_seq)
769 return(ERR_IE_SEQUENCE);
771 return(0);
774 /* verify if a message type exists and contain no IE error */
775 static int
776 l3dss1_check_messagetype_validity(struct l3_process *pc, int mt, void *arg)
778 switch (mt) {
779 case MT_ALERTING:
780 case MT_CALL_PROCEEDING:
781 case MT_CONNECT:
782 case MT_CONNECT_ACKNOWLEDGE:
783 case MT_DISCONNECT:
784 case MT_INFORMATION:
785 case MT_FACILITY:
786 case MT_NOTIFY:
787 case MT_PROGRESS:
788 case MT_RELEASE:
789 case MT_RELEASE_COMPLETE:
790 case MT_SETUP:
791 case MT_SETUP_ACKNOWLEDGE:
792 case MT_RESUME_ACKNOWLEDGE:
793 case MT_RESUME_REJECT:
794 case MT_SUSPEND_ACKNOWLEDGE:
795 case MT_SUSPEND_REJECT:
796 case MT_USER_INFORMATION:
797 case MT_RESTART:
798 case MT_RESTART_ACKNOWLEDGE:
799 case MT_CONGESTION_CONTROL:
800 case MT_STATUS:
801 case MT_STATUS_ENQUIRY:
802 if (pc->debug & L3_DEB_CHECK)
803 l3_debug(pc->st, "l3dss1_check_messagetype_validity mt(%x) OK", mt);
804 break;
805 case MT_RESUME: /* RESUME only in user->net */
806 case MT_SUSPEND: /* SUSPEND only in user->net */
807 default:
808 if (pc->debug & (L3_DEB_CHECK | L3_DEB_WARN))
809 l3_debug(pc->st, "l3dss1_check_messagetype_validity mt(%x) fail", mt);
810 pc->para.cause = 97;
811 l3dss1_status_send(pc, 0, NULL);
812 return(1);
814 return(0);
817 static void
818 l3dss1_std_ie_err(struct l3_process *pc, int ret) {
820 if (pc->debug & L3_DEB_CHECK)
821 l3_debug(pc->st, "check_infoelements ret %d", ret);
822 switch(ret) {
823 case 0:
824 break;
825 case ERR_IE_COMPREHENSION:
826 pc->para.cause = 96;
827 l3dss1_status_send(pc, 0, NULL);
828 break;
829 case ERR_IE_UNRECOGNIZED:
830 pc->para.cause = 99;
831 l3dss1_status_send(pc, 0, NULL);
832 break;
833 case ERR_IE_LENGTH:
834 pc->para.cause = 100;
835 l3dss1_status_send(pc, 0, NULL);
836 break;
837 case ERR_IE_SEQUENCE:
838 default:
839 break;
843 static int
844 l3dss1_get_channel_id(struct l3_process *pc, struct sk_buff *skb) {
845 u_char *p;
847 p = skb->data;
848 if ((p = findie(p, skb->len, IE_CHANNEL_ID, 0))) {
849 p++;
850 if (*p != 1) { /* len for BRI = 1 */
851 if (pc->debug & L3_DEB_WARN)
852 l3_debug(pc->st, "wrong chid len %d", *p);
853 return (-2);
855 p++;
856 if (*p & 0x60) { /* only base rate interface */
857 if (pc->debug & L3_DEB_WARN)
858 l3_debug(pc->st, "wrong chid %x", *p);
859 return (-3);
861 return(*p & 0x3);
862 } else
863 return(-1);
866 static int
867 l3dss1_get_cause(struct l3_process *pc, struct sk_buff *skb) {
868 u_char l, i=0;
869 u_char *p;
871 p = skb->data;
872 pc->para.cause = 31;
873 pc->para.loc = 0;
874 if ((p = findie(p, skb->len, IE_CAUSE, 0))) {
875 p++;
876 l = *p++;
877 if (l>30)
878 return(1);
879 if (l) {
880 pc->para.loc = *p++;
881 l--;
882 } else {
883 return(2);
885 if (l && !(pc->para.loc & 0x80)) {
886 l--;
887 p++; /* skip recommendation */
889 if (l) {
890 pc->para.cause = *p++;
891 l--;
892 if (!(pc->para.cause & 0x80))
893 return(3);
894 } else
895 return(4);
896 while (l && (i<6)) {
897 pc->para.diag[i++] = *p++;
898 l--;
900 } else
901 return(-1);
902 return(0);
905 static void
906 l3dss1_msg_with_uus(struct l3_process *pc, u_char cmd)
908 struct sk_buff *skb;
909 u_char tmp[16+40];
910 u_char *p = tmp;
911 int l;
913 MsgHead(p, pc->callref, cmd);
915 if (pc->prot.dss1.uus1_data[0])
916 { *p++ = IE_USER_USER; /* UUS info element */
917 *p++ = strlen(pc->prot.dss1.uus1_data) + 1;
918 *p++ = 0x04; /* IA5 chars */
919 strcpy(p,pc->prot.dss1.uus1_data);
920 p += strlen(pc->prot.dss1.uus1_data);
921 pc->prot.dss1.uus1_data[0] = '\0';
924 l = p - tmp;
925 if (!(skb = l3_alloc_skb(l)))
926 return;
927 memcpy(skb_put(skb, l), tmp, l);
928 l3_msg(pc->st, DL_DATA | REQUEST, skb);
929 } /* l3dss1_msg_with_uus */
931 static void
932 l3dss1_release_req(struct l3_process *pc, u_char pr, void *arg)
934 StopAllL3Timer(pc);
935 newl3state(pc, 19);
936 if (!pc->prot.dss1.uus1_data[0])
937 l3dss1_message(pc, MT_RELEASE);
938 else
939 l3dss1_msg_with_uus(pc, MT_RELEASE);
940 L3AddTimer(&pc->timer, T308, CC_T308_1);
943 static void
944 l3dss1_release_cmpl(struct l3_process *pc, u_char pr, void *arg)
946 struct sk_buff *skb = arg;
947 int ret;
949 if ((ret = l3dss1_get_cause(pc, skb))>0) {
950 if (pc->debug & L3_DEB_WARN)
951 l3_debug(pc->st, "RELCMPL get_cause ret(%d)",ret);
952 } else if (ret < 0)
953 pc->para.cause = NO_CAUSE;
954 StopAllL3Timer(pc);
955 newl3state(pc, 0);
956 pc->st->l3.l3l4(pc->st, CC_RELEASE | CONFIRM, pc);
957 dss1_release_l3_process(pc);
960 #if EXT_BEARER_CAPS
962 u_char *
963 EncodeASyncParams(u_char * p, u_char si2)
964 { // 7c 06 88 90 21 42 00 bb
966 p[0] = 0;
967 p[1] = 0x40; // Intermediate rate: 16 kbit/s jj 2000.02.19
968 p[2] = 0x80;
969 if (si2 & 32) // 7 data bits
971 p[2] += 16;
972 else // 8 data bits
974 p[2] += 24;
976 if (si2 & 16) // 2 stop bits
978 p[2] += 96;
979 else // 1 stop bit
981 p[2] += 32;
983 if (si2 & 8) // even parity
985 p[2] += 2;
986 else // no parity
988 p[2] += 3;
990 switch (si2 & 0x07) {
991 case 0:
992 p[0] = 66; // 1200 bit/s
994 break;
995 case 1:
996 p[0] = 88; // 1200/75 bit/s
998 break;
999 case 2:
1000 p[0] = 87; // 75/1200 bit/s
1002 break;
1003 case 3:
1004 p[0] = 67; // 2400 bit/s
1006 break;
1007 case 4:
1008 p[0] = 69; // 4800 bit/s
1010 break;
1011 case 5:
1012 p[0] = 72; // 9600 bit/s
1014 break;
1015 case 6:
1016 p[0] = 73; // 14400 bit/s
1018 break;
1019 case 7:
1020 p[0] = 75; // 19200 bit/s
1022 break;
1024 return p + 3;
1027 u_char
1028 EncodeSyncParams(u_char si2, u_char ai)
1031 switch (si2) {
1032 case 0:
1033 return ai + 2; // 1200 bit/s
1035 case 1:
1036 return ai + 24; // 1200/75 bit/s
1038 case 2:
1039 return ai + 23; // 75/1200 bit/s
1041 case 3:
1042 return ai + 3; // 2400 bit/s
1044 case 4:
1045 return ai + 5; // 4800 bit/s
1047 case 5:
1048 return ai + 8; // 9600 bit/s
1050 case 6:
1051 return ai + 9; // 14400 bit/s
1053 case 7:
1054 return ai + 11; // 19200 bit/s
1056 case 8:
1057 return ai + 14; // 48000 bit/s
1059 case 9:
1060 return ai + 15; // 56000 bit/s
1062 case 15:
1063 return ai + 40; // negotiate bit/s
1065 default:
1066 break;
1068 return ai;
1072 static u_char
1073 DecodeASyncParams(u_char si2, u_char * p)
1075 u_char info;
1077 switch (p[5]) {
1078 case 66: // 1200 bit/s
1080 break; // si2 don't change
1082 case 88: // 1200/75 bit/s
1084 si2 += 1;
1085 break;
1086 case 87: // 75/1200 bit/s
1088 si2 += 2;
1089 break;
1090 case 67: // 2400 bit/s
1092 si2 += 3;
1093 break;
1094 case 69: // 4800 bit/s
1096 si2 += 4;
1097 break;
1098 case 72: // 9600 bit/s
1100 si2 += 5;
1101 break;
1102 case 73: // 14400 bit/s
1104 si2 += 6;
1105 break;
1106 case 75: // 19200 bit/s
1108 si2 += 7;
1109 break;
1112 info = p[7] & 0x7f;
1113 if ((info & 16) && (!(info & 8))) // 7 data bits
1115 si2 += 32; // else 8 data bits
1117 if ((info & 96) == 96) // 2 stop bits
1119 si2 += 16; // else 1 stop bit
1121 if ((info & 2) && (!(info & 1))) // even parity
1123 si2 += 8; // else no parity
1125 return si2;
1129 static u_char
1130 DecodeSyncParams(u_char si2, u_char info)
1132 info &= 0x7f;
1133 switch (info) {
1134 case 40: // bit/s negotiation failed ai := 165 not 175!
1136 return si2 + 15;
1137 case 15: // 56000 bit/s failed, ai := 0 not 169 !
1139 return si2 + 9;
1140 case 14: // 48000 bit/s
1142 return si2 + 8;
1143 case 11: // 19200 bit/s
1145 return si2 + 7;
1146 case 9: // 14400 bit/s
1148 return si2 + 6;
1149 case 8: // 9600 bit/s
1151 return si2 + 5;
1152 case 5: // 4800 bit/s
1154 return si2 + 4;
1155 case 3: // 2400 bit/s
1157 return si2 + 3;
1158 case 23: // 75/1200 bit/s
1160 return si2 + 2;
1161 case 24: // 1200/75 bit/s
1163 return si2 + 1;
1164 default: // 1200 bit/s
1166 return si2;
1170 static u_char
1171 DecodeSI2(struct sk_buff *skb)
1173 u_char *p; //, *pend=skb->data + skb->len;
1175 if ((p = findie(skb->data, skb->len, 0x7c, 0))) {
1176 switch (p[4] & 0x0f) {
1177 case 0x01:
1178 if (p[1] == 0x04) // sync. Bitratenadaption
1180 return DecodeSyncParams(160, p[5]); // V.110/X.30
1182 else if (p[1] == 0x06) // async. Bitratenadaption
1184 return DecodeASyncParams(192, p); // V.110/X.30
1186 break;
1187 case 0x08: // if (p[5] == 0x02) // sync. Bitratenadaption
1188 if (p[1] > 3)
1189 return DecodeSyncParams(176, p[5]); // V.120
1190 break;
1193 return 0;
1196 #endif
1199 static void
1200 l3dss1_setup_req(struct l3_process *pc, u_char pr,
1201 void *arg)
1203 struct sk_buff *skb;
1204 u_char tmp[128];
1205 u_char *p = tmp;
1206 u_char channel = 0;
1208 u_char send_keypad;
1209 u_char screen = 0x80;
1210 u_char *teln;
1211 u_char *msn;
1212 u_char *sub;
1213 u_char *sp;
1214 int l;
1216 MsgHead(p, pc->callref, MT_SETUP);
1218 teln = pc->para.setup.phone;
1219 #ifndef CONFIG_HISAX_NO_KEYPAD
1220 send_keypad = (strchr(teln,'*') || strchr(teln,'#')) ? 1 : 0;
1221 #else
1222 send_keypad = 0;
1223 #endif
1224 #ifndef CONFIG_HISAX_NO_SENDCOMPLETE
1225 if (!send_keypad)
1226 *p++ = 0xa1; /* complete indicator */
1227 #endif
1229 * Set Bearer Capability, Map info from 1TR6-convention to EDSS1
1231 switch (pc->para.setup.si1) {
1232 case 1: /* Telephony */
1233 *p++ = IE_BEARER;
1234 *p++ = 0x3; /* Length */
1235 *p++ = 0x90; /* Coding Std. CCITT, 3.1 kHz audio */
1236 *p++ = 0x90; /* Circuit-Mode 64kbps */
1237 *p++ = 0xa3; /* A-Law Audio */
1238 break;
1239 case 5: /* Datatransmission 64k, BTX */
1240 case 7: /* Datatransmission 64k */
1241 default:
1242 *p++ = IE_BEARER;
1243 *p++ = 0x2; /* Length */
1244 *p++ = 0x88; /* Coding Std. CCITT, unrestr. dig. Inform. */
1245 *p++ = 0x90; /* Circuit-Mode 64kbps */
1246 break;
1249 if (send_keypad) {
1250 *p++ = IE_KEYPAD;
1251 *p++ = strlen(teln);
1252 while (*teln)
1253 *p++ = (*teln++) & 0x7F;
1257 * What about info2? Mapping to High-Layer-Compatibility?
1259 if ((*teln) && (!send_keypad)) {
1260 /* parse number for special things */
1261 if (!isdigit(*teln)) {
1262 switch (0x5f & *teln) {
1263 case 'C':
1264 channel = 0x08;
1265 case 'P':
1266 channel |= 0x80;
1267 teln++;
1268 if (*teln == '1')
1269 channel |= 0x01;
1270 else
1271 channel |= 0x02;
1272 break;
1273 case 'R':
1274 screen = 0xA0;
1275 break;
1276 case 'D':
1277 screen = 0x80;
1278 break;
1280 default:
1281 if (pc->debug & L3_DEB_WARN)
1282 l3_debug(pc->st, "Wrong MSN Code");
1283 break;
1285 teln++;
1288 if (channel) {
1289 *p++ = IE_CHANNEL_ID;
1290 *p++ = 1;
1291 *p++ = channel;
1293 msn = pc->para.setup.eazmsn;
1294 sub = NULL;
1295 sp = msn;
1296 while (*sp) {
1297 if ('.' == *sp) {
1298 sub = sp;
1299 *sp = 0;
1300 } else
1301 sp++;
1303 if (*msn) {
1304 *p++ = IE_CALLING_PN;
1305 *p++ = strlen(msn) + (screen ? 2 : 1);
1306 /* Classify as AnyPref. */
1307 if (screen) {
1308 *p++ = 0x01; /* Ext = '0'B, Type = '000'B, Plan = '0001'B. */
1309 *p++ = screen;
1310 } else
1311 *p++ = 0x81; /* Ext = '1'B, Type = '000'B, Plan = '0001'B. */
1312 while (*msn)
1313 *p++ = *msn++ & 0x7f;
1315 if (sub) {
1316 *sub++ = '.';
1317 *p++ = IE_CALLING_SUB;
1318 *p++ = strlen(sub) + 2;
1319 *p++ = 0x80; /* NSAP coded */
1320 *p++ = 0x50; /* local IDI format */
1321 while (*sub)
1322 *p++ = *sub++ & 0x7f;
1324 sub = NULL;
1325 sp = teln;
1326 while (*sp) {
1327 if ('.' == *sp) {
1328 sub = sp;
1329 *sp = 0;
1330 } else
1331 sp++;
1334 if (!send_keypad) {
1335 *p++ = IE_CALLED_PN;
1336 *p++ = strlen(teln) + 1;
1337 /* Classify as AnyPref. */
1338 *p++ = 0x81; /* Ext = '1'B, Type = '000'B, Plan = '0001'B. */
1339 while (*teln)
1340 *p++ = *teln++ & 0x7f;
1342 if (sub) {
1343 *sub++ = '.';
1344 *p++ = IE_CALLED_SUB;
1345 *p++ = strlen(sub) + 2;
1346 *p++ = 0x80; /* NSAP coded */
1347 *p++ = 0x50; /* local IDI format */
1348 while (*sub)
1349 *p++ = *sub++ & 0x7f;
1352 #if EXT_BEARER_CAPS
1353 if ((pc->para.setup.si2 >= 160) && (pc->para.setup.si2 <= 175)) { // sync. Bitratenadaption, V.110/X.30
1355 *p++ = IE_LLC;
1356 *p++ = 0x04;
1357 *p++ = 0x88;
1358 *p++ = 0x90;
1359 *p++ = 0x21;
1360 *p++ = EncodeSyncParams(pc->para.setup.si2 - 160, 0x80);
1361 } else if ((pc->para.setup.si2 >= 176) && (pc->para.setup.si2 <= 191)) { // sync. Bitratenadaption, V.120
1363 *p++ = IE_LLC;
1364 *p++ = 0x05;
1365 *p++ = 0x88;
1366 *p++ = 0x90;
1367 *p++ = 0x28;
1368 *p++ = EncodeSyncParams(pc->para.setup.si2 - 176, 0);
1369 *p++ = 0x82;
1370 } else if (pc->para.setup.si2 >= 192) { // async. Bitratenadaption, V.110/X.30
1372 *p++ = IE_LLC;
1373 *p++ = 0x06;
1374 *p++ = 0x88;
1375 *p++ = 0x90;
1376 *p++ = 0x21;
1377 p = EncodeASyncParams(p, pc->para.setup.si2 - 192);
1378 #ifndef CONFIG_HISAX_NO_LLC
1379 } else {
1380 switch (pc->para.setup.si1) {
1381 case 1: /* Telephony */
1382 *p++ = IE_LLC;
1383 *p++ = 0x3; /* Length */
1384 *p++ = 0x90; /* Coding Std. CCITT, 3.1 kHz audio */
1385 *p++ = 0x90; /* Circuit-Mode 64kbps */
1386 *p++ = 0xa3; /* A-Law Audio */
1387 break;
1388 case 5: /* Datatransmission 64k, BTX */
1389 case 7: /* Datatransmission 64k */
1390 default:
1391 *p++ = IE_LLC;
1392 *p++ = 0x2; /* Length */
1393 *p++ = 0x88; /* Coding Std. CCITT, unrestr. dig. Inform. */
1394 *p++ = 0x90; /* Circuit-Mode 64kbps */
1395 break;
1397 #endif
1399 #endif
1400 l = p - tmp;
1401 if (!(skb = l3_alloc_skb(l)))
1402 return;
1403 memcpy(skb_put(skb, l), tmp, l);
1404 L3DelTimer(&pc->timer);
1405 L3AddTimer(&pc->timer, T303, CC_T303);
1406 newl3state(pc, 1);
1407 l3_msg(pc->st, DL_DATA | REQUEST, skb);
1410 static void
1411 l3dss1_call_proc(struct l3_process *pc, u_char pr, void *arg)
1413 struct sk_buff *skb = arg;
1414 int id, ret;
1416 if ((id = l3dss1_get_channel_id(pc, skb)) >= 0) {
1417 if ((0 == id) || ((3 == id) && (0x10 == pc->para.moderate))) {
1418 if (pc->debug & L3_DEB_WARN)
1419 l3_debug(pc->st, "setup answer with wrong chid %x", id);
1420 pc->para.cause = 100;
1421 l3dss1_status_send(pc, pr, NULL);
1422 return;
1424 pc->para.bchannel = id;
1425 } else if (1 == pc->state) {
1426 if (pc->debug & L3_DEB_WARN)
1427 l3_debug(pc->st, "setup answer wrong chid (ret %d)", id);
1428 if (id == -1)
1429 pc->para.cause = 96;
1430 else
1431 pc->para.cause = 100;
1432 l3dss1_status_send(pc, pr, NULL);
1433 return;
1435 /* Now we are on none mandatory IEs */
1436 ret = check_infoelements(pc, skb, ie_CALL_PROCEEDING);
1437 if (ERR_IE_COMPREHENSION == ret) {
1438 l3dss1_std_ie_err(pc, ret);
1439 return;
1441 L3DelTimer(&pc->timer);
1442 newl3state(pc, 3);
1443 L3AddTimer(&pc->timer, T310, CC_T310);
1444 if (ret) /* STATUS for none mandatory IE errors after actions are taken */
1445 l3dss1_std_ie_err(pc, ret);
1446 pc->st->l3.l3l4(pc->st, CC_PROCEEDING | INDICATION, pc);
1449 static void
1450 l3dss1_setup_ack(struct l3_process *pc, u_char pr, void *arg)
1452 struct sk_buff *skb = arg;
1453 int id, ret;
1455 if ((id = l3dss1_get_channel_id(pc, skb)) >= 0) {
1456 if ((0 == id) || ((3 == id) && (0x10 == pc->para.moderate))) {
1457 if (pc->debug & L3_DEB_WARN)
1458 l3_debug(pc->st, "setup answer with wrong chid %x", id);
1459 pc->para.cause = 100;
1460 l3dss1_status_send(pc, pr, NULL);
1461 return;
1463 pc->para.bchannel = id;
1464 } else {
1465 if (pc->debug & L3_DEB_WARN)
1466 l3_debug(pc->st, "setup answer wrong chid (ret %d)", id);
1467 if (id == -1)
1468 pc->para.cause = 96;
1469 else
1470 pc->para.cause = 100;
1471 l3dss1_status_send(pc, pr, NULL);
1472 return;
1474 /* Now we are on none mandatory IEs */
1475 ret = check_infoelements(pc, skb, ie_SETUP_ACKNOWLEDGE);
1476 if (ERR_IE_COMPREHENSION == ret) {
1477 l3dss1_std_ie_err(pc, ret);
1478 return;
1480 L3DelTimer(&pc->timer);
1481 newl3state(pc, 2);
1482 L3AddTimer(&pc->timer, T304, CC_T304);
1483 if (ret) /* STATUS for none mandatory IE errors after actions are taken */
1484 l3dss1_std_ie_err(pc, ret);
1485 pc->st->l3.l3l4(pc->st, CC_MORE_INFO | INDICATION, pc);
1488 static void
1489 l3dss1_disconnect(struct l3_process *pc, u_char pr, void *arg)
1491 struct sk_buff *skb = arg;
1492 u_char *p;
1493 int ret;
1494 u_char cause = 0;
1496 StopAllL3Timer(pc);
1497 if ((ret = l3dss1_get_cause(pc, skb))) {
1498 if (pc->debug & L3_DEB_WARN)
1499 l3_debug(pc->st, "DISC get_cause ret(%d)", ret);
1500 if (ret < 0)
1501 cause = 96;
1502 else if (ret > 0)
1503 cause = 100;
1505 if ((p = findie(skb->data, skb->len, IE_FACILITY, 0)))
1506 l3dss1_parse_facility(pc->st, pc, pc->callref, p);
1507 ret = check_infoelements(pc, skb, ie_DISCONNECT);
1508 if (ERR_IE_COMPREHENSION == ret)
1509 cause = 96;
1510 else if ((!cause) && (ERR_IE_UNRECOGNIZED == ret))
1511 cause = 99;
1512 ret = pc->state;
1513 newl3state(pc, 12);
1514 if (cause)
1515 newl3state(pc, 19);
1516 if (11 != ret)
1517 pc->st->l3.l3l4(pc->st, CC_DISCONNECT | INDICATION, pc);
1518 else if (!cause)
1519 l3dss1_release_req(pc, pr, NULL);
1520 if (cause) {
1521 l3dss1_message_cause(pc, MT_RELEASE, cause);
1522 L3AddTimer(&pc->timer, T308, CC_T308_1);
1526 static void
1527 l3dss1_connect(struct l3_process *pc, u_char pr, void *arg)
1529 struct sk_buff *skb = arg;
1530 int ret;
1532 ret = check_infoelements(pc, skb, ie_CONNECT);
1533 if (ERR_IE_COMPREHENSION == ret) {
1534 l3dss1_std_ie_err(pc, ret);
1535 return;
1537 L3DelTimer(&pc->timer); /* T310 */
1538 newl3state(pc, 10);
1539 pc->para.chargeinfo = 0;
1540 /* here should inserted COLP handling KKe */
1541 if (ret)
1542 l3dss1_std_ie_err(pc, ret);
1543 pc->st->l3.l3l4(pc->st, CC_SETUP | CONFIRM, pc);
1546 static void
1547 l3dss1_alerting(struct l3_process *pc, u_char pr, void *arg)
1549 struct sk_buff *skb = arg;
1550 int ret;
1552 ret = check_infoelements(pc, skb, ie_ALERTING);
1553 if (ERR_IE_COMPREHENSION == ret) {
1554 l3dss1_std_ie_err(pc, ret);
1555 return;
1557 L3DelTimer(&pc->timer); /* T304 */
1558 newl3state(pc, 4);
1559 if (ret)
1560 l3dss1_std_ie_err(pc, ret);
1561 pc->st->l3.l3l4(pc->st, CC_ALERTING | INDICATION, pc);
1564 static void
1565 l3dss1_setup(struct l3_process *pc, u_char pr, void *arg)
1567 u_char *p;
1568 int bcfound = 0;
1569 char tmp[80];
1570 struct sk_buff *skb = arg;
1571 int id;
1572 int err = 0;
1575 * Bearer Capabilities
1577 p = skb->data;
1578 /* only the first occurence 'll be detected ! */
1579 if ((p = findie(p, skb->len, 0x04, 0))) {
1580 if ((p[1] < 2) || (p[1] > 11))
1581 err = 1;
1582 else {
1583 pc->para.setup.si2 = 0;
1584 switch (p[2] & 0x7f) {
1585 case 0x00: /* Speech */
1586 case 0x10: /* 3.1 Khz audio */
1587 pc->para.setup.si1 = 1;
1588 break;
1589 case 0x08: /* Unrestricted digital information */
1590 pc->para.setup.si1 = 7;
1591 /* JIM, 05.11.97 I wanna set service indicator 2 */
1592 #if EXT_BEARER_CAPS
1593 pc->para.setup.si2 = DecodeSI2(skb);
1594 #endif
1595 break;
1596 case 0x09: /* Restricted digital information */
1597 pc->para.setup.si1 = 2;
1598 break;
1599 case 0x11:
1600 /* Unrestr. digital information with
1601 * tones/announcements ( or 7 kHz audio
1603 pc->para.setup.si1 = 3;
1604 break;
1605 case 0x18: /* Video */
1606 pc->para.setup.si1 = 4;
1607 break;
1608 default:
1609 err = 2;
1610 break;
1612 switch (p[3] & 0x7f) {
1613 case 0x40: /* packed mode */
1614 pc->para.setup.si1 = 8;
1615 break;
1616 case 0x10: /* 64 kbit */
1617 case 0x11: /* 2*64 kbit */
1618 case 0x13: /* 384 kbit */
1619 case 0x15: /* 1536 kbit */
1620 case 0x17: /* 1920 kbit */
1621 pc->para.moderate = p[3] & 0x7f;
1622 break;
1623 default:
1624 err = 3;
1625 break;
1628 if (pc->debug & L3_DEB_SI)
1629 l3_debug(pc->st, "SI=%d, AI=%d",
1630 pc->para.setup.si1, pc->para.setup.si2);
1631 if (err) {
1632 if (pc->debug & L3_DEB_WARN)
1633 l3_debug(pc->st, "setup with wrong bearer(l=%d:%x,%x)",
1634 p[1], p[2], p[3]);
1635 pc->para.cause = 100;
1636 l3dss1_msg_without_setup(pc, pr, NULL);
1637 return;
1639 } else {
1640 if (pc->debug & L3_DEB_WARN)
1641 l3_debug(pc->st, "setup without bearer capabilities");
1642 /* ETS 300-104 1.3.3 */
1643 pc->para.cause = 96;
1644 l3dss1_msg_without_setup(pc, pr, NULL);
1645 return;
1648 * Channel Identification
1650 if ((id = l3dss1_get_channel_id(pc, skb)) >= 0) {
1651 if ((pc->para.bchannel = id)) {
1652 if ((3 == id) && (0x10 == pc->para.moderate)) {
1653 if (pc->debug & L3_DEB_WARN)
1654 l3_debug(pc->st, "setup with wrong chid %x",
1655 id);
1656 pc->para.cause = 100;
1657 l3dss1_msg_without_setup(pc, pr, NULL);
1658 return;
1660 bcfound++;
1661 } else
1662 { if (pc->debug & L3_DEB_WARN)
1663 l3_debug(pc->st, "setup without bchannel, call waiting");
1664 bcfound++;
1666 } else {
1667 if (pc->debug & L3_DEB_WARN)
1668 l3_debug(pc->st, "setup with wrong chid ret %d", id);
1669 if (id == -1)
1670 pc->para.cause = 96;
1671 else
1672 pc->para.cause = 100;
1673 l3dss1_msg_without_setup(pc, pr, NULL);
1674 return;
1676 /* Now we are on none mandatory IEs */
1677 err = check_infoelements(pc, skb, ie_SETUP);
1678 if (ERR_IE_COMPREHENSION == err) {
1679 pc->para.cause = 96;
1680 l3dss1_msg_without_setup(pc, pr, NULL);
1681 return;
1683 p = skb->data;
1684 if ((p = findie(p, skb->len, 0x70, 0)))
1685 iecpy(pc->para.setup.eazmsn, p, 1);
1686 else
1687 pc->para.setup.eazmsn[0] = 0;
1689 p = skb->data;
1690 if ((p = findie(p, skb->len, 0x71, 0))) {
1691 /* Called party subaddress */
1692 if ((p[1] >= 2) && (p[2] == 0x80) && (p[3] == 0x50)) {
1693 tmp[0] = '.';
1694 iecpy(&tmp[1], p, 2);
1695 strcat(pc->para.setup.eazmsn, tmp);
1696 } else if (pc->debug & L3_DEB_WARN)
1697 l3_debug(pc->st, "wrong called subaddress");
1699 p = skb->data;
1700 if ((p = findie(p, skb->len, 0x6c, 0))) {
1701 pc->para.setup.plan = p[2];
1702 if (p[2] & 0x80) {
1703 iecpy(pc->para.setup.phone, p, 1);
1704 pc->para.setup.screen = 0;
1705 } else {
1706 iecpy(pc->para.setup.phone, p, 2);
1707 pc->para.setup.screen = p[3];
1709 } else {
1710 pc->para.setup.phone[0] = 0;
1711 pc->para.setup.plan = 0;
1712 pc->para.setup.screen = 0;
1714 p = skb->data;
1715 if ((p = findie(p, skb->len, 0x6d, 0))) {
1716 /* Calling party subaddress */
1717 if ((p[1] >= 2) && (p[2] == 0x80) && (p[3] == 0x50)) {
1718 tmp[0] = '.';
1719 iecpy(&tmp[1], p, 2);
1720 strcat(pc->para.setup.phone, tmp);
1721 } else if (pc->debug & L3_DEB_WARN)
1722 l3_debug(pc->st, "wrong calling subaddress");
1724 newl3state(pc, 6);
1725 if (err) /* STATUS for none mandatory IE errors after actions are taken */
1726 l3dss1_std_ie_err(pc, err);
1727 pc->st->l3.l3l4(pc->st, CC_SETUP | INDICATION, pc);
1730 static void
1731 l3dss1_reset(struct l3_process *pc, u_char pr, void *arg)
1733 dss1_release_l3_process(pc);
1736 static void
1737 l3dss1_disconnect_req(struct l3_process *pc, u_char pr, void *arg)
1739 struct sk_buff *skb;
1740 u_char tmp[16+40];
1741 u_char *p = tmp;
1742 int l;
1743 u_char cause = 16;
1745 if (pc->para.cause != NO_CAUSE)
1746 cause = pc->para.cause;
1748 StopAllL3Timer(pc);
1750 MsgHead(p, pc->callref, MT_DISCONNECT);
1752 *p++ = IE_CAUSE;
1753 *p++ = 0x2;
1754 *p++ = 0x80;
1755 *p++ = cause | 0x80;
1757 if (pc->prot.dss1.uus1_data[0])
1758 { *p++ = IE_USER_USER; /* UUS info element */
1759 *p++ = strlen(pc->prot.dss1.uus1_data) + 1;
1760 *p++ = 0x04; /* IA5 chars */
1761 strcpy(p,pc->prot.dss1.uus1_data);
1762 p += strlen(pc->prot.dss1.uus1_data);
1763 pc->prot.dss1.uus1_data[0] = '\0';
1766 l = p - tmp;
1767 if (!(skb = l3_alloc_skb(l)))
1768 return;
1769 memcpy(skb_put(skb, l), tmp, l);
1770 newl3state(pc, 11);
1771 l3_msg(pc->st, DL_DATA | REQUEST, skb);
1772 L3AddTimer(&pc->timer, T305, CC_T305);
1775 static void
1776 l3dss1_setup_rsp(struct l3_process *pc, u_char pr,
1777 void *arg)
1779 if (!pc->para.bchannel)
1780 { if (pc->debug & L3_DEB_WARN)
1781 l3_debug(pc->st, "D-chan connect for waiting call");
1782 l3dss1_disconnect_req(pc, pr, arg);
1783 return;
1785 newl3state(pc, 8);
1786 l3dss1_message(pc, MT_CONNECT);
1787 L3DelTimer(&pc->timer);
1788 L3AddTimer(&pc->timer, T313, CC_T313);
1791 static void
1792 l3dss1_connect_ack(struct l3_process *pc, u_char pr, void *arg)
1794 struct sk_buff *skb = arg;
1795 int ret;
1797 ret = check_infoelements(pc, skb, ie_CONNECT_ACKNOWLEDGE);
1798 if (ERR_IE_COMPREHENSION == ret) {
1799 l3dss1_std_ie_err(pc, ret);
1800 return;
1802 newl3state(pc, 10);
1803 L3DelTimer(&pc->timer);
1804 if (ret)
1805 l3dss1_std_ie_err(pc, ret);
1806 pc->st->l3.l3l4(pc->st, CC_SETUP_COMPL | INDICATION, pc);
1809 static void
1810 l3dss1_reject_req(struct l3_process *pc, u_char pr, void *arg)
1812 struct sk_buff *skb;
1813 u_char tmp[16];
1814 u_char *p = tmp;
1815 int l;
1816 u_char cause = 21;
1818 if (pc->para.cause != NO_CAUSE)
1819 cause = pc->para.cause;
1821 MsgHead(p, pc->callref, MT_RELEASE_COMPLETE);
1823 *p++ = IE_CAUSE;
1824 *p++ = 0x2;
1825 *p++ = 0x80;
1826 *p++ = cause | 0x80;
1828 l = p - tmp;
1829 if (!(skb = l3_alloc_skb(l)))
1830 return;
1831 memcpy(skb_put(skb, l), tmp, l);
1832 l3_msg(pc->st, DL_DATA | REQUEST, skb);
1833 pc->st->l3.l3l4(pc->st, CC_RELEASE | INDICATION, pc);
1834 newl3state(pc, 0);
1835 dss1_release_l3_process(pc);
1838 static void
1839 l3dss1_release(struct l3_process *pc, u_char pr, void *arg)
1841 struct sk_buff *skb = arg;
1842 u_char *p;
1843 int ret, cause=0;
1845 StopAllL3Timer(pc);
1846 if ((ret = l3dss1_get_cause(pc, skb))>0) {
1847 if (pc->debug & L3_DEB_WARN)
1848 l3_debug(pc->st, "REL get_cause ret(%d)", ret);
1849 } else if (ret<0)
1850 pc->para.cause = NO_CAUSE;
1851 if ((p = findie(skb->data, skb->len, IE_FACILITY, 0))) {
1852 l3dss1_parse_facility(pc->st, pc, pc->callref, p);
1854 if ((ret<0) && (pc->state != 11))
1855 cause = 96;
1856 else if (ret>0)
1857 cause = 100;
1858 ret = check_infoelements(pc, skb, ie_RELEASE);
1859 if (ERR_IE_COMPREHENSION == ret)
1860 cause = 96;
1861 else if ((ERR_IE_UNRECOGNIZED == ret) && (!cause))
1862 cause = 99;
1863 if (cause)
1864 l3dss1_message_cause(pc, MT_RELEASE_COMPLETE, cause);
1865 else
1866 l3dss1_message(pc, MT_RELEASE_COMPLETE);
1867 pc->st->l3.l3l4(pc->st, CC_RELEASE | INDICATION, pc);
1868 newl3state(pc, 0);
1869 dss1_release_l3_process(pc);
1872 static void
1873 l3dss1_alert_req(struct l3_process *pc, u_char pr,
1874 void *arg)
1876 newl3state(pc, 7);
1877 if (!pc->prot.dss1.uus1_data[0])
1878 l3dss1_message(pc, MT_ALERTING);
1879 else
1880 l3dss1_msg_with_uus(pc, MT_ALERTING);
1883 static void
1884 l3dss1_proceed_req(struct l3_process *pc, u_char pr,
1885 void *arg)
1887 newl3state(pc, 9);
1888 l3dss1_message(pc, MT_CALL_PROCEEDING);
1889 pc->st->l3.l3l4(pc->st, CC_PROCEED_SEND | INDICATION, pc);
1892 /********************************************/
1893 /* deliver a incoming display message to HL */
1894 /********************************************/
1895 static void
1896 l3dss1_deliver_display(struct l3_process *pc, int pr, u_char *infp)
1897 { u_char len;
1898 isdn_ctrl ic;
1899 struct IsdnCardState *cs;
1900 char *p;
1902 if (*infp++ != IE_DISPLAY) return;
1903 if ((len = *infp++) > 80) return; /* total length <= 82 */
1904 if (!pc->chan) return;
1906 p = ic.parm.display;
1907 while (len--)
1908 *p++ = *infp++;
1909 *p = '\0';
1910 ic.command = ISDN_STAT_DISPLAY;
1911 cs = pc->st->l1.hardware;
1912 ic.driver = cs->myid;
1913 ic.arg = pc->chan->chan;
1914 cs->iif.statcallb(&ic);
1915 } /* l3dss1_deliver_display */
1918 static void
1919 l3dss1_progress(struct l3_process *pc, u_char pr, void *arg)
1921 struct sk_buff *skb = arg;
1922 int err = 0;
1923 u_char *p;
1925 if ((p = findie(skb->data, skb->len, IE_PROGRESS, 0))) {
1926 if (p[1] != 2) {
1927 err = 1;
1928 pc->para.cause = 100;
1929 } else if (p[2] & 0x60) {
1930 switch (p[2]) {
1931 case 0x80:
1932 case 0x81:
1933 case 0x82:
1934 case 0x84:
1935 case 0x85:
1936 case 0x87:
1937 case 0x8a:
1938 switch (p[3]) {
1939 case 0x81:
1940 case 0x82:
1941 case 0x83:
1942 case 0x84:
1943 case 0x88:
1944 break;
1945 default:
1946 err = 2;
1947 pc->para.cause = 100;
1948 break;
1950 break;
1951 default:
1952 err = 3;
1953 pc->para.cause = 100;
1954 break;
1957 } else {
1958 pc->para.cause = 96;
1959 err = 4;
1961 if (err) {
1962 if (pc->debug & L3_DEB_WARN)
1963 l3_debug(pc->st, "progress error %d", err);
1964 l3dss1_status_send(pc, pr, NULL);
1965 return;
1967 /* Now we are on none mandatory IEs */
1968 err = check_infoelements(pc, skb, ie_PROGRESS);
1969 if (err)
1970 l3dss1_std_ie_err(pc, err);
1971 if (ERR_IE_COMPREHENSION != err)
1972 pc->st->l3.l3l4(pc->st, CC_PROGRESS | INDICATION, pc);
1975 static void
1976 l3dss1_notify(struct l3_process *pc, u_char pr, void *arg)
1978 struct sk_buff *skb = arg;
1979 int err = 0;
1980 u_char *p;
1982 if ((p = findie(skb->data, skb->len, IE_NOTIFY, 0))) {
1983 if (p[1] != 1) {
1984 err = 1;
1985 pc->para.cause = 100;
1986 } else {
1987 switch (p[2]) {
1988 case 0x80:
1989 case 0x81:
1990 case 0x82:
1991 break;
1992 default:
1993 pc->para.cause = 100;
1994 err = 2;
1995 break;
1998 } else {
1999 pc->para.cause = 96;
2000 err = 3;
2002 if (err) {
2003 if (pc->debug & L3_DEB_WARN)
2004 l3_debug(pc->st, "notify error %d", err);
2005 l3dss1_status_send(pc, pr, NULL);
2006 return;
2008 /* Now we are on none mandatory IEs */
2009 err = check_infoelements(pc, skb, ie_NOTIFY);
2010 if (err)
2011 l3dss1_std_ie_err(pc, err);
2012 if (ERR_IE_COMPREHENSION != err)
2013 pc->st->l3.l3l4(pc->st, CC_NOTIFY | INDICATION, pc);
2016 static void
2017 l3dss1_status_enq(struct l3_process *pc, u_char pr, void *arg)
2019 int ret;
2020 struct sk_buff *skb = arg;
2022 ret = check_infoelements(pc, skb, ie_STATUS_ENQUIRY);
2023 l3dss1_std_ie_err(pc, ret);
2024 pc->para.cause = 30; /* response to STATUS_ENQUIRY */
2025 l3dss1_status_send(pc, pr, NULL);
2028 static void
2029 l3dss1_information(struct l3_process *pc, u_char pr, void *arg)
2031 int ret;
2032 struct sk_buff *skb = arg;
2034 ret = check_infoelements(pc, skb, ie_INFORMATION);
2035 l3dss1_std_ie_err(pc, ret);
2038 /******************************/
2039 /* handle deflection requests */
2040 /******************************/
2041 static void l3dss1_redir_req(struct l3_process *pc, u_char pr, void *arg)
2043 struct sk_buff *skb;
2044 u_char tmp[128];
2045 u_char *p = tmp;
2046 u_char *subp;
2047 u_char len_phone = 0;
2048 u_char len_sub = 0;
2049 int l;
2052 strcpy(pc->prot.dss1.uus1_data,pc->chan->setup.eazmsn); /* copy uus element if available */
2053 if (!pc->chan->setup.phone[0])
2054 { pc->para.cause = -1;
2055 l3dss1_disconnect_req(pc,pr,arg); /* disconnect immediately */
2056 return;
2057 } /* only uus */
2059 if (pc->prot.dss1.invoke_id)
2060 free_invoke_id(pc->st,pc->prot.dss1.invoke_id);
2062 if (!(pc->prot.dss1.invoke_id = new_invoke_id(pc->st)))
2063 return;
2065 MsgHead(p, pc->callref, MT_FACILITY);
2067 for (subp = pc->chan->setup.phone; (*subp) && (*subp != '.'); subp++) len_phone++; /* len of phone number */
2068 if (*subp++ == '.') len_sub = strlen(subp) + 2; /* length including info subadress element */
2070 *p++ = 0x1c; /* Facility info element */
2071 *p++ = len_phone + len_sub + 2 + 2 + 8 + 3 + 3; /* length of element */
2072 *p++ = 0x91; /* remote operations protocol */
2073 *p++ = 0xa1; /* invoke component */
2075 *p++ = len_phone + len_sub + 2 + 2 + 8 + 3; /* length of data */
2076 *p++ = 0x02; /* invoke id tag, integer */
2077 *p++ = 0x01; /* length */
2078 *p++ = pc->prot.dss1.invoke_id; /* invoke id */
2079 *p++ = 0x02; /* operation value tag, integer */
2080 *p++ = 0x01; /* length */
2081 *p++ = 0x0D; /* Call Deflect */
2083 *p++ = 0x30; /* sequence phone number */
2084 *p++ = len_phone + 2 + 2 + 3 + len_sub; /* length */
2086 *p++ = 0x30; /* Deflected to UserNumber */
2087 *p++ = len_phone+2+len_sub; /* length */
2088 *p++ = 0x80; /* NumberDigits */
2089 *p++ = len_phone; /* length */
2090 for (l = 0; l < len_phone; l++)
2091 *p++ = pc->chan->setup.phone[l];
2093 if (len_sub)
2094 { *p++ = 0x04; /* called party subadress */
2095 *p++ = len_sub - 2;
2096 while (*subp) *p++ = *subp++;
2099 *p++ = 0x01; /* screening identifier */
2100 *p++ = 0x01;
2101 *p++ = pc->chan->setup.screen;
2103 l = p - tmp;
2104 if (!(skb = l3_alloc_skb(l))) return;
2105 memcpy(skb_put(skb, l), tmp, l);
2107 l3_msg(pc->st, DL_DATA | REQUEST, skb);
2108 } /* l3dss1_redir_req */
2110 /********************************************/
2111 /* handle deflection request in early state */
2112 /********************************************/
2113 static void l3dss1_redir_req_early(struct l3_process *pc, u_char pr, void *arg)
2115 l3dss1_proceed_req(pc,pr,arg);
2116 l3dss1_redir_req(pc,pr,arg);
2117 } /* l3dss1_redir_req_early */
2119 /***********************************************/
2120 /* handle special commands for this protocol. */
2121 /* Examples are call independant services like */
2122 /* remote operations with dummy callref. */
2123 /***********************************************/
2124 static int l3dss1_cmd_global(struct PStack *st, isdn_ctrl *ic)
2125 { u_char id;
2126 u_char temp[265];
2127 u_char *p = temp;
2128 int i, l, proc_len;
2129 struct sk_buff *skb;
2130 struct l3_process *pc = NULL;
2132 switch (ic->arg)
2133 { case DSS1_CMD_INVOKE:
2134 if (ic->parm.dss1_io.datalen < 0) return(-2); /* invalid parameter */
2136 for (proc_len = 1, i = ic->parm.dss1_io.proc >> 8; i; i++)
2137 i = i >> 8; /* add one byte */
2138 l = ic->parm.dss1_io.datalen + proc_len + 8; /* length excluding ie header */
2139 if (l > 255)
2140 return(-2); /* too long */
2142 if (!(id = new_invoke_id(st)))
2143 return(0); /* first get a invoke id -> return if no available */
2145 i = -1;
2146 MsgHead(p, i, MT_FACILITY); /* build message head */
2147 *p++ = 0x1C; /* Facility IE */
2148 *p++ = l; /* length of ie */
2149 *p++ = 0x91; /* remote operations */
2150 *p++ = 0xA1; /* invoke */
2151 *p++ = l - 3; /* length of invoke */
2152 *p++ = 0x02; /* invoke id tag */
2153 *p++ = 0x01; /* length is 1 */
2154 *p++ = id; /* invoke id */
2155 *p++ = 0x02; /* operation */
2156 *p++ = proc_len; /* length of operation */
2158 for (i = proc_len; i; i--)
2159 *p++ = (ic->parm.dss1_io.proc >> (i-1)) & 0xFF;
2160 memcpy(p, ic->parm.dss1_io.data, ic->parm.dss1_io.datalen); /* copy data */
2161 l = (p - temp) + ic->parm.dss1_io.datalen; /* total length */
2163 if (ic->parm.dss1_io.timeout > 0)
2164 if (!(pc = dss1_new_l3_process(st, -1)))
2165 { free_invoke_id(st, id);
2166 return(-2);
2168 pc->prot.dss1.ll_id = ic->parm.dss1_io.ll_id; /* remember id */
2169 pc->prot.dss1.proc = ic->parm.dss1_io.proc; /* and procedure */
2171 if (!(skb = l3_alloc_skb(l)))
2172 { free_invoke_id(st, id);
2173 if (pc) dss1_release_l3_process(pc);
2174 return(-2);
2176 memcpy(skb_put(skb, l), temp, l);
2178 if (pc)
2179 { pc->prot.dss1.invoke_id = id; /* remember id */
2180 L3AddTimer(&pc->timer, ic->parm.dss1_io.timeout, CC_TDSS1_IO | REQUEST);
2183 l3_msg(st, DL_DATA | REQUEST, skb);
2184 ic->parm.dss1_io.hl_id = id; /* return id */
2185 return(0);
2187 case DSS1_CMD_INVOKE_ABORT:
2188 if ((pc = l3dss1_search_dummy_proc(st, ic->parm.dss1_io.hl_id)))
2189 { L3DelTimer(&pc->timer); /* remove timer */
2190 dss1_release_l3_process(pc);
2191 return(0);
2193 else
2194 { l3_debug(st, "l3dss1_cmd_global abort unknown id");
2195 return(-2);
2197 break;
2199 default:
2200 l3_debug(st, "l3dss1_cmd_global unknown cmd 0x%lx", ic->arg);
2201 return(-1);
2202 } /* switch ic-> arg */
2203 return(-1);
2204 } /* l3dss1_cmd_global */
2206 static void
2207 l3dss1_io_timer(struct l3_process *pc)
2208 { isdn_ctrl ic;
2209 struct IsdnCardState *cs = pc->st->l1.hardware;
2211 L3DelTimer(&pc->timer); /* remove timer */
2213 ic.driver = cs->myid;
2214 ic.command = ISDN_STAT_PROT;
2215 ic.arg = DSS1_STAT_INVOKE_ERR;
2216 ic.parm.dss1_io.hl_id = pc->prot.dss1.invoke_id;
2217 ic.parm.dss1_io.ll_id = pc->prot.dss1.ll_id;
2218 ic.parm.dss1_io.proc = pc->prot.dss1.proc;
2219 ic.parm.dss1_io.timeout= -1;
2220 ic.parm.dss1_io.datalen = 0;
2221 ic.parm.dss1_io.data = NULL;
2222 free_invoke_id(pc->st, pc->prot.dss1.invoke_id);
2223 pc->prot.dss1.invoke_id = 0; /* reset id */
2225 cs->iif.statcallb(&ic);
2227 dss1_release_l3_process(pc);
2228 } /* l3dss1_io_timer */
2230 static void
2231 l3dss1_release_ind(struct l3_process *pc, u_char pr, void *arg)
2233 u_char *p;
2234 struct sk_buff *skb = arg;
2235 int callState = 0;
2236 p = skb->data;
2238 if ((p = findie(p, skb->len, IE_CALL_STATE, 0))) {
2239 p++;
2240 if (1 == *p++)
2241 callState = *p;
2243 if (callState == 0) {
2244 /* ETS 300-104 7.6.1, 8.6.1, 10.6.1... and 16.1
2245 * set down layer 3 without sending any message
2247 pc->st->l3.l3l4(pc->st, CC_RELEASE | INDICATION, pc);
2248 newl3state(pc, 0);
2249 dss1_release_l3_process(pc);
2250 } else {
2251 pc->st->l3.l3l4(pc->st, CC_IGNORE | INDICATION, pc);
2255 static void
2256 l3dss1_dummy(struct l3_process *pc, u_char pr, void *arg)
2260 static void
2261 l3dss1_t303(struct l3_process *pc, u_char pr, void *arg)
2263 if (pc->N303 > 0) {
2264 pc->N303--;
2265 L3DelTimer(&pc->timer);
2266 l3dss1_setup_req(pc, pr, arg);
2267 } else {
2268 L3DelTimer(&pc->timer);
2269 l3dss1_message_cause(pc, MT_RELEASE_COMPLETE, 102);
2270 pc->st->l3.l3l4(pc->st, CC_NOSETUP_RSP, pc);
2271 dss1_release_l3_process(pc);
2275 static void
2276 l3dss1_t304(struct l3_process *pc, u_char pr, void *arg)
2278 L3DelTimer(&pc->timer);
2279 pc->para.cause = 102;
2280 l3dss1_disconnect_req(pc, pr, NULL);
2281 pc->st->l3.l3l4(pc->st, CC_SETUP_ERR, pc);
2285 static void
2286 l3dss1_t305(struct l3_process *pc, u_char pr, void *arg)
2288 u_char tmp[16];
2289 u_char *p = tmp;
2290 int l;
2291 struct sk_buff *skb;
2292 u_char cause = 16;
2294 L3DelTimer(&pc->timer);
2295 if (pc->para.cause != NO_CAUSE)
2296 cause = pc->para.cause;
2298 MsgHead(p, pc->callref, MT_RELEASE);
2300 *p++ = IE_CAUSE;
2301 *p++ = 0x2;
2302 *p++ = 0x80;
2303 *p++ = cause | 0x80;
2305 l = p - tmp;
2306 if (!(skb = l3_alloc_skb(l)))
2307 return;
2308 memcpy(skb_put(skb, l), tmp, l);
2309 newl3state(pc, 19);
2310 l3_msg(pc->st, DL_DATA | REQUEST, skb);
2311 L3AddTimer(&pc->timer, T308, CC_T308_1);
2314 static void
2315 l3dss1_t310(struct l3_process *pc, u_char pr, void *arg)
2317 L3DelTimer(&pc->timer);
2318 pc->para.cause = 102;
2319 l3dss1_disconnect_req(pc, pr, NULL);
2320 pc->st->l3.l3l4(pc->st, CC_SETUP_ERR, pc);
2323 static void
2324 l3dss1_t313(struct l3_process *pc, u_char pr, void *arg)
2326 L3DelTimer(&pc->timer);
2327 pc->para.cause = 102;
2328 l3dss1_disconnect_req(pc, pr, NULL);
2329 pc->st->l3.l3l4(pc->st, CC_CONNECT_ERR, pc);
2332 static void
2333 l3dss1_t308_1(struct l3_process *pc, u_char pr, void *arg)
2335 newl3state(pc, 19);
2336 L3DelTimer(&pc->timer);
2337 l3dss1_message(pc, MT_RELEASE);
2338 L3AddTimer(&pc->timer, T308, CC_T308_2);
2341 static void
2342 l3dss1_t308_2(struct l3_process *pc, u_char pr, void *arg)
2344 L3DelTimer(&pc->timer);
2345 pc->st->l3.l3l4(pc->st, CC_RELEASE_ERR, pc);
2346 dss1_release_l3_process(pc);
2349 static void
2350 l3dss1_t318(struct l3_process *pc, u_char pr, void *arg)
2352 L3DelTimer(&pc->timer);
2353 pc->para.cause = 102; /* Timer expiry */
2354 pc->para.loc = 0; /* local */
2355 pc->st->l3.l3l4(pc->st, CC_RESUME_ERR, pc);
2356 newl3state(pc, 19);
2357 l3dss1_message(pc, MT_RELEASE);
2358 L3AddTimer(&pc->timer, T308, CC_T308_1);
2361 static void
2362 l3dss1_t319(struct l3_process *pc, u_char pr, void *arg)
2364 L3DelTimer(&pc->timer);
2365 pc->para.cause = 102; /* Timer expiry */
2366 pc->para.loc = 0; /* local */
2367 pc->st->l3.l3l4(pc->st, CC_SUSPEND_ERR, pc);
2368 newl3state(pc, 10);
2371 static void
2372 l3dss1_restart(struct l3_process *pc, u_char pr, void *arg)
2374 L3DelTimer(&pc->timer);
2375 pc->st->l3.l3l4(pc->st, CC_RELEASE | INDICATION, pc);
2376 dss1_release_l3_process(pc);
2379 static void
2380 l3dss1_status(struct l3_process *pc, u_char pr, void *arg)
2382 u_char *p;
2383 struct sk_buff *skb = arg;
2384 int ret;
2385 u_char cause = 0, callState = 0;
2387 if ((ret = l3dss1_get_cause(pc, skb))) {
2388 if (pc->debug & L3_DEB_WARN)
2389 l3_debug(pc->st, "STATUS get_cause ret(%d)",ret);
2390 if (ret < 0)
2391 cause = 96;
2392 else if (ret > 0)
2393 cause = 100;
2395 if ((p = findie(skb->data, skb->len, IE_CALL_STATE, 0))) {
2396 p++;
2397 if (1 == *p++) {
2398 callState = *p;
2399 if (!ie_in_set(pc, *p, l3_valid_states))
2400 cause = 100;
2401 } else
2402 cause = 100;
2403 } else
2404 cause = 96;
2405 if (!cause) { /* no error before */
2406 ret = check_infoelements(pc, skb, ie_STATUS);
2407 if (ERR_IE_COMPREHENSION == ret)
2408 cause = 96;
2409 else if (ERR_IE_UNRECOGNIZED == ret)
2410 cause = 99;
2412 if (cause) {
2413 u_char tmp;
2415 if (pc->debug & L3_DEB_WARN)
2416 l3_debug(pc->st, "STATUS error(%d/%d)",ret,cause);
2417 tmp = pc->para.cause;
2418 pc->para.cause = cause;
2419 l3dss1_status_send(pc, 0, NULL);
2420 if (cause == 99)
2421 pc->para.cause = tmp;
2422 else
2423 return;
2425 cause = pc->para.cause;
2426 if (((cause & 0x7f) == 111) && (callState == 0)) {
2427 /* ETS 300-104 7.6.1, 8.6.1, 10.6.1...
2428 * if received MT_STATUS with cause == 111 and call
2429 * state == 0, then we must set down layer 3
2431 pc->st->l3.l3l4(pc->st, CC_RELEASE | INDICATION, pc);
2432 newl3state(pc, 0);
2433 dss1_release_l3_process(pc);
2437 static void
2438 l3dss1_facility(struct l3_process *pc, u_char pr, void *arg)
2440 struct sk_buff *skb = arg;
2441 int ret;
2443 ret = check_infoelements(pc, skb, ie_FACILITY);
2444 l3dss1_std_ie_err(pc, ret);
2446 u_char *p;
2447 if ((p = findie(skb->data, skb->len, IE_FACILITY, 0)))
2448 l3dss1_parse_facility(pc->st, pc, pc->callref, p);
2452 static void
2453 l3dss1_suspend_req(struct l3_process *pc, u_char pr, void *arg)
2455 struct sk_buff *skb;
2456 u_char tmp[32];
2457 u_char *p = tmp;
2458 u_char i, l;
2459 u_char *msg = pc->chan->setup.phone;
2461 MsgHead(p, pc->callref, MT_SUSPEND);
2462 l = *msg++;
2463 if (l && (l <= 10)) { /* Max length 10 octets */
2464 *p++ = IE_CALL_ID;
2465 *p++ = l;
2466 for (i = 0; i < l; i++)
2467 *p++ = *msg++;
2468 } else if (l) {
2469 l3_debug(pc->st, "SUS wrong CALL_ID len %d", l);
2470 return;
2472 l = p - tmp;
2473 if (!(skb = l3_alloc_skb(l)))
2474 return;
2475 memcpy(skb_put(skb, l), tmp, l);
2476 l3_msg(pc->st, DL_DATA | REQUEST, skb);
2477 newl3state(pc, 15);
2478 L3AddTimer(&pc->timer, T319, CC_T319);
2481 static void
2482 l3dss1_suspend_ack(struct l3_process *pc, u_char pr, void *arg)
2484 struct sk_buff *skb = arg;
2485 int ret;
2487 L3DelTimer(&pc->timer);
2488 newl3state(pc, 0);
2489 pc->para.cause = NO_CAUSE;
2490 pc->st->l3.l3l4(pc->st, CC_SUSPEND | CONFIRM, pc);
2491 /* We don't handle suspend_ack for IE errors now */
2492 if ((ret = check_infoelements(pc, skb, ie_SUSPEND_ACKNOWLEDGE)))
2493 if (pc->debug & L3_DEB_WARN)
2494 l3_debug(pc->st, "SUSPACK check ie(%d)",ret);
2495 dss1_release_l3_process(pc);
2498 static void
2499 l3dss1_suspend_rej(struct l3_process *pc, u_char pr, void *arg)
2501 struct sk_buff *skb = arg;
2502 int ret;
2504 if ((ret = l3dss1_get_cause(pc, skb))) {
2505 if (pc->debug & L3_DEB_WARN)
2506 l3_debug(pc->st, "SUSP_REJ get_cause ret(%d)",ret);
2507 if (ret < 0)
2508 pc->para.cause = 96;
2509 else
2510 pc->para.cause = 100;
2511 l3dss1_status_send(pc, pr, NULL);
2512 return;
2514 ret = check_infoelements(pc, skb, ie_SUSPEND_REJECT);
2515 if (ERR_IE_COMPREHENSION == ret) {
2516 l3dss1_std_ie_err(pc, ret);
2517 return;
2519 L3DelTimer(&pc->timer);
2520 pc->st->l3.l3l4(pc->st, CC_SUSPEND_ERR, pc);
2521 newl3state(pc, 10);
2522 if (ret) /* STATUS for none mandatory IE errors after actions are taken */
2523 l3dss1_std_ie_err(pc, ret);
2526 static void
2527 l3dss1_resume_req(struct l3_process *pc, u_char pr, void *arg)
2529 struct sk_buff *skb;
2530 u_char tmp[32];
2531 u_char *p = tmp;
2532 u_char i, l;
2533 u_char *msg = pc->para.setup.phone;
2535 MsgHead(p, pc->callref, MT_RESUME);
2537 l = *msg++;
2538 if (l && (l <= 10)) { /* Max length 10 octets */
2539 *p++ = IE_CALL_ID;
2540 *p++ = l;
2541 for (i = 0; i < l; i++)
2542 *p++ = *msg++;
2543 } else if (l) {
2544 l3_debug(pc->st, "RES wrong CALL_ID len %d", l);
2545 return;
2547 l = p - tmp;
2548 if (!(skb = l3_alloc_skb(l)))
2549 return;
2550 memcpy(skb_put(skb, l), tmp, l);
2551 l3_msg(pc->st, DL_DATA | REQUEST, skb);
2552 newl3state(pc, 17);
2553 L3AddTimer(&pc->timer, T318, CC_T318);
2556 static void
2557 l3dss1_resume_ack(struct l3_process *pc, u_char pr, void *arg)
2559 struct sk_buff *skb = arg;
2560 int id, ret;
2562 if ((id = l3dss1_get_channel_id(pc, skb)) > 0) {
2563 if ((0 == id) || ((3 == id) && (0x10 == pc->para.moderate))) {
2564 if (pc->debug & L3_DEB_WARN)
2565 l3_debug(pc->st, "resume ack with wrong chid %x", id);
2566 pc->para.cause = 100;
2567 l3dss1_status_send(pc, pr, NULL);
2568 return;
2570 pc->para.bchannel = id;
2571 } else if (1 == pc->state) {
2572 if (pc->debug & L3_DEB_WARN)
2573 l3_debug(pc->st, "resume ack without chid (ret %d)", id);
2574 pc->para.cause = 96;
2575 l3dss1_status_send(pc, pr, NULL);
2576 return;
2578 ret = check_infoelements(pc, skb, ie_RESUME_ACKNOWLEDGE);
2579 if (ERR_IE_COMPREHENSION == ret) {
2580 l3dss1_std_ie_err(pc, ret);
2581 return;
2583 L3DelTimer(&pc->timer);
2584 pc->st->l3.l3l4(pc->st, CC_RESUME | CONFIRM, pc);
2585 newl3state(pc, 10);
2586 if (ret) /* STATUS for none mandatory IE errors after actions are taken */
2587 l3dss1_std_ie_err(pc, ret);
2590 static void
2591 l3dss1_resume_rej(struct l3_process *pc, u_char pr, void *arg)
2593 struct sk_buff *skb = arg;
2594 int ret;
2596 if ((ret = l3dss1_get_cause(pc, skb))) {
2597 if (pc->debug & L3_DEB_WARN)
2598 l3_debug(pc->st, "RES_REJ get_cause ret(%d)",ret);
2599 if (ret < 0)
2600 pc->para.cause = 96;
2601 else
2602 pc->para.cause = 100;
2603 l3dss1_status_send(pc, pr, NULL);
2604 return;
2606 ret = check_infoelements(pc, skb, ie_RESUME_REJECT);
2607 if (ERR_IE_COMPREHENSION == ret) {
2608 l3dss1_std_ie_err(pc, ret);
2609 return;
2611 L3DelTimer(&pc->timer);
2612 pc->st->l3.l3l4(pc->st, CC_RESUME_ERR, pc);
2613 newl3state(pc, 0);
2614 if (ret) /* STATUS for none mandatory IE errors after actions are taken */
2615 l3dss1_std_ie_err(pc, ret);
2616 dss1_release_l3_process(pc);
2619 static void
2620 l3dss1_global_restart(struct l3_process *pc, u_char pr, void *arg)
2622 u_char tmp[32];
2623 u_char *p;
2624 u_char ri, ch = 0, chan = 0;
2625 int l;
2626 struct sk_buff *skb = arg;
2627 struct l3_process *up;
2629 newl3state(pc, 2);
2630 L3DelTimer(&pc->timer);
2631 p = skb->data;
2632 if ((p = findie(p, skb->len, IE_RESTART_IND, 0))) {
2633 ri = p[2];
2634 l3_debug(pc->st, "Restart %x", ri);
2635 } else {
2636 l3_debug(pc->st, "Restart without restart IE");
2637 ri = 0x86;
2639 p = skb->data;
2640 if ((p = findie(p, skb->len, IE_CHANNEL_ID, 0))) {
2641 chan = p[2] & 3;
2642 ch = p[2];
2643 if (pc->st->l3.debug)
2644 l3_debug(pc->st, "Restart for channel %d", chan);
2646 newl3state(pc, 2);
2647 up = pc->st->l3.proc;
2648 while (up) {
2649 if ((ri & 7) == 7)
2650 up->st->lli.l4l3(up->st, CC_RESTART | REQUEST, up);
2651 else if (up->para.bchannel == chan)
2652 up->st->lli.l4l3(up->st, CC_RESTART | REQUEST, up);
2653 up = up->next;
2655 p = tmp;
2656 MsgHead(p, pc->callref, MT_RESTART_ACKNOWLEDGE);
2657 if (chan) {
2658 *p++ = IE_CHANNEL_ID;
2659 *p++ = 1;
2660 *p++ = ch | 0x80;
2662 *p++ = 0x79; /* RESTART Ind */
2663 *p++ = 1;
2664 *p++ = ri;
2665 l = p - tmp;
2666 if (!(skb = l3_alloc_skb(l)))
2667 return;
2668 memcpy(skb_put(skb, l), tmp, l);
2669 newl3state(pc, 0);
2670 l3_msg(pc->st, DL_DATA | REQUEST, skb);
2673 static void
2674 l3dss1_dl_reset(struct l3_process *pc, u_char pr, void *arg)
2676 pc->para.cause = 0x29; /* Temporary failure */
2677 pc->para.loc = 0;
2678 l3dss1_disconnect_req(pc, pr, NULL);
2679 pc->st->l3.l3l4(pc->st, CC_SETUP_ERR, pc);
2682 static void
2683 l3dss1_dl_release(struct l3_process *pc, u_char pr, void *arg)
2685 newl3state(pc, 0);
2686 pc->para.cause = 0x1b; /* Destination out of order */
2687 pc->para.loc = 0;
2688 pc->st->l3.l3l4(pc->st, CC_RELEASE | INDICATION, pc);
2689 release_l3_process(pc);
2692 static void
2693 l3dss1_dl_reestablish(struct l3_process *pc, u_char pr, void *arg)
2695 L3DelTimer(&pc->timer);
2696 L3AddTimer(&pc->timer, T309, CC_T309);
2697 l3_msg(pc->st, DL_ESTABLISH | REQUEST, NULL);
2700 static void
2701 l3dss1_dl_reest_status(struct l3_process *pc, u_char pr, void *arg)
2703 L3DelTimer(&pc->timer);
2705 pc->para.cause = 0x1F; /* normal, unspecified */
2706 l3dss1_status_send(pc, 0, NULL);
2709 /* *INDENT-OFF* */
2710 static struct stateentry downstatelist[] =
2712 {SBIT(0),
2713 CC_SETUP | REQUEST, l3dss1_setup_req},
2714 {SBIT(0),
2715 CC_RESUME | REQUEST, l3dss1_resume_req},
2716 {SBIT(1) | SBIT(2) | SBIT(3) | SBIT(4) | SBIT(6) | SBIT(7) | SBIT(8) | SBIT(9) | SBIT(10),
2717 CC_DISCONNECT | REQUEST, l3dss1_disconnect_req},
2718 {SBIT(12),
2719 CC_RELEASE | REQUEST, l3dss1_release_req},
2720 {ALL_STATES,
2721 CC_RESTART | REQUEST, l3dss1_restart},
2722 {SBIT(6),
2723 CC_IGNORE | REQUEST, l3dss1_reset},
2724 {SBIT(6),
2725 CC_REJECT | REQUEST, l3dss1_reject_req},
2726 {SBIT(6),
2727 CC_PROCEED_SEND | REQUEST, l3dss1_proceed_req},
2728 {SBIT(6) | SBIT(9),
2729 CC_ALERTING | REQUEST, l3dss1_alert_req},
2730 {SBIT(6) | SBIT(7) | SBIT(9),
2731 CC_SETUP | RESPONSE, l3dss1_setup_rsp},
2732 {SBIT(10),
2733 CC_SUSPEND | REQUEST, l3dss1_suspend_req},
2734 {SBIT(6),
2735 CC_PROCEED_SEND | REQUEST, l3dss1_proceed_req},
2736 {SBIT(7) | SBIT(9),
2737 CC_REDIR | REQUEST, l3dss1_redir_req},
2738 {SBIT(6),
2739 CC_REDIR | REQUEST, l3dss1_redir_req_early},
2740 {SBIT(9) | SBIT(25),
2741 CC_DISCONNECT | REQUEST, l3dss1_disconnect_req},
2742 {SBIT(1),
2743 CC_T303, l3dss1_t303},
2744 {SBIT(2),
2745 CC_T304, l3dss1_t304},
2746 {SBIT(3),
2747 CC_T310, l3dss1_t310},
2748 {SBIT(8),
2749 CC_T313, l3dss1_t313},
2750 {SBIT(11),
2751 CC_T305, l3dss1_t305},
2752 {SBIT(15),
2753 CC_T319, l3dss1_t319},
2754 {SBIT(17),
2755 CC_T318, l3dss1_t318},
2756 {SBIT(19),
2757 CC_T308_1, l3dss1_t308_1},
2758 {SBIT(19),
2759 CC_T308_2, l3dss1_t308_2},
2760 {SBIT(10),
2761 CC_T309, l3dss1_dl_release},
2764 #define DOWNSLLEN \
2765 (sizeof(downstatelist) / sizeof(struct stateentry))
2767 static struct stateentry datastatelist[] =
2769 {ALL_STATES,
2770 MT_STATUS_ENQUIRY, l3dss1_status_enq},
2771 {ALL_STATES,
2772 MT_FACILITY, l3dss1_facility},
2773 {SBIT(19),
2774 MT_STATUS, l3dss1_release_ind},
2775 {ALL_STATES,
2776 MT_STATUS, l3dss1_status},
2777 {SBIT(0),
2778 MT_SETUP, l3dss1_setup},
2779 {SBIT(6) | SBIT(7) | SBIT(8) | SBIT(9) | SBIT(10) | SBIT(11) | SBIT(12) |
2780 SBIT(15) | SBIT(17) | SBIT(19) | SBIT(25),
2781 MT_SETUP, l3dss1_dummy},
2782 {SBIT(1) | SBIT(2),
2783 MT_CALL_PROCEEDING, l3dss1_call_proc},
2784 {SBIT(1),
2785 MT_SETUP_ACKNOWLEDGE, l3dss1_setup_ack},
2786 {SBIT(2) | SBIT(3),
2787 MT_ALERTING, l3dss1_alerting},
2788 {SBIT(2) | SBIT(3),
2789 MT_PROGRESS, l3dss1_progress},
2790 {SBIT(2) | SBIT(3) | SBIT(4) | SBIT(7) | SBIT(8) | SBIT(9) | SBIT(10) |
2791 SBIT(11) | SBIT(12) | SBIT(15) | SBIT(17) | SBIT(19) | SBIT(25),
2792 MT_INFORMATION, l3dss1_information},
2793 {SBIT(10) | SBIT(11) | SBIT(15),
2794 MT_NOTIFY, l3dss1_notify},
2795 {SBIT(0) | SBIT(1) | SBIT(2) | SBIT(3) | SBIT(4) | SBIT(7) | SBIT(8) | SBIT(10) |
2796 SBIT(11) | SBIT(12) | SBIT(15) | SBIT(17) | SBIT(19) | SBIT(25),
2797 MT_RELEASE_COMPLETE, l3dss1_release_cmpl},
2798 {SBIT(1) | SBIT(2) | SBIT(3) | SBIT(4) | SBIT(7) | SBIT(8) | SBIT(9) | SBIT(10) | SBIT(11) | SBIT(12) | SBIT(15) | SBIT(17) | SBIT(25),
2799 MT_RELEASE, l3dss1_release},
2800 {SBIT(19), MT_RELEASE, l3dss1_release_ind},
2801 {SBIT(1) | SBIT(2) | SBIT(3) | SBIT(4) | SBIT(7) | SBIT(8) | SBIT(9) | SBIT(10) | SBIT(11) | SBIT(15) | SBIT(17) | SBIT(25),
2802 MT_DISCONNECT, l3dss1_disconnect},
2803 {SBIT(19),
2804 MT_DISCONNECT, l3dss1_dummy},
2805 {SBIT(1) | SBIT(2) | SBIT(3) | SBIT(4),
2806 MT_CONNECT, l3dss1_connect},
2807 {SBIT(8),
2808 MT_CONNECT_ACKNOWLEDGE, l3dss1_connect_ack},
2809 {SBIT(15),
2810 MT_SUSPEND_ACKNOWLEDGE, l3dss1_suspend_ack},
2811 {SBIT(15),
2812 MT_SUSPEND_REJECT, l3dss1_suspend_rej},
2813 {SBIT(17),
2814 MT_RESUME_ACKNOWLEDGE, l3dss1_resume_ack},
2815 {SBIT(17),
2816 MT_RESUME_REJECT, l3dss1_resume_rej},
2819 #define DATASLLEN \
2820 (sizeof(datastatelist) / sizeof(struct stateentry))
2822 static struct stateentry globalmes_list[] =
2824 {ALL_STATES,
2825 MT_STATUS, l3dss1_status},
2826 {SBIT(0),
2827 MT_RESTART, l3dss1_global_restart},
2828 /* {SBIT(1),
2829 MT_RESTART_ACKNOWLEDGE, l3dss1_restart_ack},
2832 #define GLOBALM_LEN \
2833 (sizeof(globalmes_list) / sizeof(struct stateentry))
2835 static struct stateentry manstatelist[] =
2837 {SBIT(2),
2838 DL_ESTABLISH | INDICATION, l3dss1_dl_reset},
2839 {SBIT(10),
2840 DL_ESTABLISH | CONFIRM, l3dss1_dl_reest_status},
2841 {SBIT(10),
2842 DL_RELEASE | INDICATION, l3dss1_dl_reestablish},
2843 {ALL_STATES,
2844 DL_RELEASE | INDICATION, l3dss1_dl_release},
2847 #define MANSLLEN \
2848 (sizeof(manstatelist) / sizeof(struct stateentry))
2849 /* *INDENT-ON* */
2852 static void
2853 global_handler(struct PStack *st, int mt, struct sk_buff *skb)
2855 u_char tmp[16];
2856 u_char *p = tmp;
2857 int l;
2858 int i;
2859 struct l3_process *proc = st->l3.global;
2861 proc->callref = skb->data[2]; /* cr flag */
2862 for (i = 0; i < GLOBALM_LEN; i++)
2863 if ((mt == globalmes_list[i].primitive) &&
2864 ((1 << proc->state) & globalmes_list[i].state))
2865 break;
2866 if (i == GLOBALM_LEN) {
2867 if (st->l3.debug & L3_DEB_STATE) {
2868 l3_debug(st, "dss1 global state %d mt %x unhandled",
2869 proc->state, mt);
2871 MsgHead(p, proc->callref, MT_STATUS);
2872 *p++ = IE_CAUSE;
2873 *p++ = 0x2;
2874 *p++ = 0x80;
2875 *p++ = 81 |0x80; /* invalid cr */
2876 *p++ = 0x14; /* CallState */
2877 *p++ = 0x1;
2878 *p++ = proc->state & 0x3f;
2879 l = p - tmp;
2880 if (!(skb = l3_alloc_skb(l)))
2881 return;
2882 memcpy(skb_put(skb, l), tmp, l);
2883 l3_msg(proc->st, DL_DATA | REQUEST, skb);
2884 } else {
2885 if (st->l3.debug & L3_DEB_STATE) {
2886 l3_debug(st, "dss1 global %d mt %x",
2887 proc->state, mt);
2889 globalmes_list[i].rout(proc, mt, skb);
2893 static void
2894 dss1up(struct PStack *st, int pr, void *arg)
2896 int i, mt, cr, cause, callState;
2897 char *ptr;
2898 u_char *p;
2899 struct sk_buff *skb = arg;
2900 struct l3_process *proc;
2902 switch (pr) {
2903 case (DL_DATA | INDICATION):
2904 case (DL_UNIT_DATA | INDICATION):
2905 break;
2906 case (DL_ESTABLISH | CONFIRM):
2907 case (DL_ESTABLISH | INDICATION):
2908 case (DL_RELEASE | INDICATION):
2909 case (DL_RELEASE | CONFIRM):
2910 l3_msg(st, pr, arg);
2911 return;
2912 break;
2913 default:
2914 printk(KERN_ERR "HiSax dss1up unknown pr=%04x\n", pr);
2915 return;
2917 if (skb->len < 3) {
2918 l3_debug(st, "dss1up frame too short(%d)", skb->len);
2919 dev_kfree_skb(skb);
2920 return;
2923 if (skb->data[0] != PROTO_DIS_EURO) {
2924 if (st->l3.debug & L3_DEB_PROTERR) {
2925 l3_debug(st, "dss1up%sunexpected discriminator %x message len %d",
2926 (pr == (DL_DATA | INDICATION)) ? " " : "(broadcast) ",
2927 skb->data[0], skb->len);
2929 dev_kfree_skb(skb);
2930 return;
2932 cr = getcallref(skb->data);
2933 if (skb->len < ((skb->data[1] & 0x0f) + 3)) {
2934 l3_debug(st, "dss1up frame too short(%d)", skb->len);
2935 dev_kfree_skb(skb);
2936 return;
2938 mt = skb->data[skb->data[1] + 2];
2939 if (st->l3.debug & L3_DEB_STATE)
2940 l3_debug(st, "dss1up cr %d", cr);
2941 if (cr == -2) { /* wrong Callref */
2942 if (st->l3.debug & L3_DEB_WARN)
2943 l3_debug(st, "dss1up wrong Callref");
2944 dev_kfree_skb(skb);
2945 return;
2946 } else if (cr == -1) { /* Dummy Callref */
2947 if (mt == MT_FACILITY)
2948 if ((p = findie(skb->data, skb->len, IE_FACILITY, 0))) {
2949 l3dss1_parse_facility(st, NULL,
2950 (pr == (DL_DATA | INDICATION)) ? -1 : -2, p);
2951 dev_kfree_skb(skb);
2952 return;
2954 if (st->l3.debug & L3_DEB_WARN)
2955 l3_debug(st, "dss1up dummy Callref (no facility msg or ie)");
2956 dev_kfree_skb(skb);
2957 return;
2958 } else if ((((skb->data[1] & 0x0f) == 1) && (0==(cr & 0x7f))) ||
2959 (((skb->data[1] & 0x0f) == 2) && (0==(cr & 0x7fff)))) { /* Global CallRef */
2960 if (st->l3.debug & L3_DEB_STATE)
2961 l3_debug(st, "dss1up Global CallRef");
2962 global_handler(st, mt, skb);
2963 dev_kfree_skb(skb);
2964 return;
2965 } else if (!(proc = getl3proc(st, cr))) {
2966 /* No transaction process exist, that means no call with
2967 * this callreference is active
2969 if (mt == MT_SETUP) {
2970 /* Setup creates a new transaction process */
2971 if (skb->data[2] & 0x80) {
2972 /* Setup with wrong CREF flag */
2973 if (st->l3.debug & L3_DEB_STATE)
2974 l3_debug(st, "dss1up wrong CRef flag");
2975 dev_kfree_skb(skb);
2976 return;
2978 if (!(proc = dss1_new_l3_process(st, cr))) {
2979 /* May be to answer with RELEASE_COMPLETE and
2980 * CAUSE 0x2f "Resource unavailable", but this
2981 * need a new_l3_process too ... arghh
2983 dev_kfree_skb(skb);
2984 return;
2986 } else if (mt == MT_STATUS) {
2987 cause = 0;
2988 if ((ptr = findie(skb->data, skb->len, IE_CAUSE, 0)) != NULL) {
2989 ptr++;
2990 if (*ptr++ == 2)
2991 ptr++;
2992 cause = *ptr & 0x7f;
2994 callState = 0;
2995 if ((ptr = findie(skb->data, skb->len, IE_CALL_STATE, 0)) != NULL) {
2996 ptr++;
2997 if (*ptr++ == 2)
2998 ptr++;
2999 callState = *ptr;
3001 /* ETS 300-104 part 2.4.1
3002 * if setup has not been made and a message type
3003 * MT_STATUS is received with call state == 0,
3004 * we must send nothing
3006 if (callState != 0) {
3007 /* ETS 300-104 part 2.4.2
3008 * if setup has not been made and a message type
3009 * MT_STATUS is received with call state != 0,
3010 * we must send MT_RELEASE_COMPLETE cause 101
3012 if ((proc = dss1_new_l3_process(st, cr))) {
3013 proc->para.cause = 101;
3014 l3dss1_msg_without_setup(proc, 0, NULL);
3017 dev_kfree_skb(skb);
3018 return;
3019 } else if (mt == MT_RELEASE_COMPLETE) {
3020 dev_kfree_skb(skb);
3021 return;
3022 } else {
3023 /* ETS 300-104 part 2
3024 * if setup has not been made and a message type
3025 * (except MT_SETUP and RELEASE_COMPLETE) is received,
3026 * we must send MT_RELEASE_COMPLETE cause 81 */
3027 dev_kfree_skb(skb);
3028 if ((proc = dss1_new_l3_process(st, cr))) {
3029 proc->para.cause = 81;
3030 l3dss1_msg_without_setup(proc, 0, NULL);
3032 return;
3035 if (l3dss1_check_messagetype_validity(proc, mt, skb)) {
3036 dev_kfree_skb(skb);
3037 return;
3039 if ((p = findie(skb->data, skb->len, IE_DISPLAY, 0)) != NULL)
3040 l3dss1_deliver_display(proc, pr, p); /* Display IE included */
3041 for (i = 0; i < DATASLLEN; i++)
3042 if ((mt == datastatelist[i].primitive) &&
3043 ((1 << proc->state) & datastatelist[i].state))
3044 break;
3045 if (i == DATASLLEN) {
3046 if (st->l3.debug & L3_DEB_STATE) {
3047 l3_debug(st, "dss1up%sstate %d mt %#x unhandled",
3048 (pr == (DL_DATA | INDICATION)) ? " " : "(broadcast) ",
3049 proc->state, mt);
3051 if ((MT_RELEASE_COMPLETE != mt) && (MT_RELEASE != mt)) {
3052 proc->para.cause = 101;
3053 l3dss1_status_send(proc, pr, skb);
3055 } else {
3056 if (st->l3.debug & L3_DEB_STATE) {
3057 l3_debug(st, "dss1up%sstate %d mt %x",
3058 (pr == (DL_DATA | INDICATION)) ? " " : "(broadcast) ",
3059 proc->state, mt);
3061 datastatelist[i].rout(proc, pr, skb);
3063 dev_kfree_skb(skb);
3064 return;
3067 static void
3068 dss1down(struct PStack *st, int pr, void *arg)
3070 int i, cr;
3071 struct l3_process *proc;
3072 struct Channel *chan;
3074 if ((DL_ESTABLISH | REQUEST) == pr) {
3075 l3_msg(st, pr, NULL);
3076 return;
3077 } else if (((CC_SETUP | REQUEST) == pr) || ((CC_RESUME | REQUEST) == pr)) {
3078 chan = arg;
3079 cr = newcallref();
3080 cr |= 0x80;
3081 if ((proc = dss1_new_l3_process(st, cr))) {
3082 proc->chan = chan;
3083 chan->proc = proc;
3084 memcpy (&proc->para.setup, &chan->setup, sizeof (chan->setup));
3085 proc->callref = cr;
3087 } else {
3088 proc = arg;
3090 if (!proc) {
3091 printk(KERN_ERR "HiSax dss1down without proc pr=%04x\n", pr);
3092 return;
3095 if ( pr == (CC_TDSS1_IO | REQUEST)) {
3096 l3dss1_io_timer(proc); /* timer expires */
3097 return;
3100 for (i = 0; i < DOWNSLLEN; i++)
3101 if ((pr == downstatelist[i].primitive) &&
3102 ((1 << proc->state) & downstatelist[i].state))
3103 break;
3104 if (i == DOWNSLLEN) {
3105 if (st->l3.debug & L3_DEB_STATE) {
3106 l3_debug(st, "dss1down state %d prim %#x unhandled",
3107 proc->state, pr);
3109 } else {
3110 if (st->l3.debug & L3_DEB_STATE) {
3111 l3_debug(st, "dss1down state %d prim %#x",
3112 proc->state, pr);
3114 downstatelist[i].rout(proc, pr, arg);
3118 static void
3119 dss1man(struct PStack *st, int pr, void *arg)
3121 int i;
3122 struct l3_process *proc = arg;
3124 if (!proc) {
3125 printk(KERN_ERR "HiSax dss1man without proc pr=%04x\n", pr);
3126 return;
3128 for (i = 0; i < MANSLLEN; i++)
3129 if ((pr == manstatelist[i].primitive) &&
3130 ((1 << proc->state) & manstatelist[i].state))
3131 break;
3132 if (i == MANSLLEN) {
3133 if (st->l3.debug & L3_DEB_STATE) {
3134 l3_debug(st, "cr %d dss1man state %d prim %#x unhandled",
3135 proc->callref & 0x7f, proc->state, pr);
3137 } else {
3138 if (st->l3.debug & L3_DEB_STATE) {
3139 l3_debug(st, "cr %d dss1man state %d prim %#x",
3140 proc->callref & 0x7f, proc->state, pr);
3142 manstatelist[i].rout(proc, pr, arg);
3146 void
3147 setstack_dss1(struct PStack *st)
3149 char tmp[64];
3150 int i;
3152 st->lli.l4l3 = dss1down;
3153 st->lli.l4l3_proto = l3dss1_cmd_global;
3154 st->l2.l2l3 = dss1up;
3155 st->l3.l3ml3 = dss1man;
3156 st->l3.N303 = 1;
3157 st->prot.dss1.last_invoke_id = 0;
3158 st->prot.dss1.invoke_used[0] = 1; /* Bit 0 must always be set to 1 */
3159 i = 1;
3160 while (i < 32)
3161 st->prot.dss1.invoke_used[i++] = 0;
3163 if (!(st->l3.global = kmalloc(sizeof(struct l3_process), GFP_ATOMIC))) {
3164 printk(KERN_ERR "HiSax can't get memory for dss1 global CR\n");
3165 } else {
3166 st->l3.global->state = 0;
3167 st->l3.global->callref = 0;
3168 st->l3.global->next = NULL;
3169 st->l3.global->debug = L3_DEB_WARN;
3170 st->l3.global->st = st;
3171 st->l3.global->N303 = 1;
3172 st->l3.global->prot.dss1.invoke_id = 0;
3174 L3InitTimer(st->l3.global, &st->l3.global->timer);
3176 strcpy(tmp, dss1_revision);
3177 printk(KERN_INFO "HiSax: DSS1 Rev. %s\n", HiSax_getrev(tmp));