pre-2.3.4..
[davej-history.git] / drivers / isdn / hisax / l3dss1.c
blob0808d32a0b593041aeba1148c8348b3ad664d7c9
1 /* $Id: l3dss1.c,v 2.12 1998/11/15 23:55:10 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
15 * $Log: l3dss1.c,v $
16 * Revision 2.12 1998/11/15 23:55:10 keil
17 * changes from 2.0
19 * Revision 2.11 1998/08/13 23:36:51 keil
20 * HiSax 3.1 - don't work stable with current LinkLevel
22 * Revision 2.10 1998/05/25 14:10:20 keil
23 * HiSax 3.0
24 * X.75 and leased are working again.
26 * Revision 2.9 1998/05/25 12:58:17 keil
27 * HiSax golden code from certification, Don't use !!!
28 * No leased lines, no X75, but many changes.
30 * Revision 2.8 1998/03/19 13:18:47 keil
31 * Start of a CAPI like interface for supplementary Service
32 * first service: SUSPEND
34 * Revision 2.7 1998/02/12 23:08:01 keil
35 * change for 2.1.86 (removing FREE_READ/FREE_WRITE from [dev]_kfree_skb()
37 * Revision 2.6 1998/02/03 23:26:35 keil
38 * V110 extensions from Thomas Pfeiffer
40 * Revision 2.5 1998/02/02 13:34:28 keil
41 * Support australian Microlink net and german AOCD
43 * Revision 2.4 1997/11/06 17:12:25 keil
44 * KERN_NOTICE --> KERN_INFO
46 * Revision 2.3 1997/10/29 19:03:01 keil
47 * changes for 2.1
49 * Revision 2.2 1997/08/07 17:44:36 keil
50 * Fix RESTART
52 * Revision 2.1 1997/08/03 14:36:33 keil
53 * Implement RESTART procedure
55 * Revision 2.0 1997/07/27 21:15:43 keil
56 * New Callref based layer3
58 * Revision 1.17 1997/06/26 11:11:46 keil
59 * SET_SKBFREE now on creation of a SKB
61 * Revision 1.15 1997/04/17 11:50:48 keil
62 * pa->loc was undefined, if it was not send by the exchange
64 * Old log removed /KKe
68 #define __NO_VERSION__
69 #include "hisax.h"
70 #include "isdnl3.h"
71 #include "l3dss1.h"
72 #include <linux/ctype.h>
74 extern char *HiSax_getrev(const char *revision);
75 const char *dss1_revision = "$Revision: 2.12 $";
77 #define MsgHead(ptr, cref, mty) \
78 *ptr++ = 0x8; \
79 *ptr++ = 0x1; \
80 *ptr++ = cref^0x80; \
81 *ptr++ = mty
84 #if HISAX_DE_AOC
85 static void
86 l3dss1_parse_facility(struct l3_process *pc, u_char * p)
88 int qd_len = 0;
90 p++;
91 qd_len = *p++;
92 if (qd_len == 0) {
93 l3_debug(pc->st, "qd_len == 0");
94 return;
96 if ((*p & 0x1F) != 0x11) { /* Service discriminator, supplementary service */
97 l3_debug(pc->st, "supplementary service != 0x11");
98 return;
100 while (qd_len > 0 && !(*p & 0x80)) { /* extension ? */
101 p++;
102 qd_len--;
104 if (qd_len < 2) {
105 l3_debug(pc->st, "qd_len < 2");
106 return;
108 p++;
109 qd_len--;
110 if ((*p & 0xE0) != 0xA0) { /* class and form */
111 l3_debug(pc->st, "class and form != 0xA0");
112 return;
114 switch (*p & 0x1F) { /* component tag */
115 case 1: /* invoke */
117 unsigned char nlen = 0, ilen;
118 int ident;
120 p++;
121 qd_len--;
122 if (qd_len < 1) {
123 l3_debug(pc->st, "qd_len < 1");
124 break;
126 if (*p & 0x80) { /* length format */
127 l3_debug(pc->st, "*p & 0x80 length format");
128 break;
130 nlen = *p++;
131 qd_len--;
132 if (qd_len < nlen) {
133 l3_debug(pc->st, "qd_len < nlen");
134 return;
136 qd_len -= nlen;
138 if (nlen < 2) {
139 l3_debug(pc->st, "nlen < 2");
140 return;
142 if (*p != 0x02) { /* invoke identifier tag */
143 l3_debug(pc->st, "invoke identifier tag !=0x02");
144 return;
146 p++;
147 nlen--;
148 if (*p & 0x80) { /* length format */
149 l3_debug(pc->st, "*p & 0x80 length format 2");
150 break;
152 ilen = *p++;
153 nlen--;
154 if (ilen > nlen || ilen == 0) {
155 l3_debug(pc->st, "ilen > nlen || ilen == 0");
156 return;
158 nlen -= ilen;
159 ident = 0;
160 while (ilen > 0) {
161 ident = (ident << 8) | (*p++ & 0xFF); /* invoke identifier */
162 ilen--;
165 if (nlen < 2) {
166 l3_debug(pc->st, "nlen < 2 22");
167 return;
169 if (*p != 0x02) { /* operation value */
170 l3_debug(pc->st, "operation value !=0x02");
171 return;
173 p++;
174 nlen--;
175 ilen = *p++;
176 nlen--;
177 if (ilen > nlen || ilen == 0) {
178 l3_debug(pc->st, "ilen > nlen || ilen == 0 22");
179 return;
181 nlen -= ilen;
182 ident = 0;
183 while (ilen > 0) {
184 ident = (ident << 8) | (*p++ & 0xFF);
185 ilen--;
188 #define FOO1(s,a,b) \
189 while(nlen > 1) { \
190 int ilen = p[1]; \
191 if(nlen < ilen+2) { \
192 l3_debug(pc->st, "FOO1 nlen < ilen+2"); \
193 return; \
195 nlen -= ilen+2; \
196 if((*p & 0xFF) == (a)) { \
197 int nlen = ilen; \
198 p += 2; \
199 b; \
200 } else { \
201 p += ilen+2; \
205 switch (ident) {
206 default:
207 break;
208 case 0x22: /* during */
209 FOO1("1A", 0x30, FOO1("1C", 0xA1, FOO1("1D", 0x30, FOO1("1E", 0x02, ( {
210 ident = 0;
211 nlen = (nlen)?nlen:0; /* Make gcc happy */
212 while (ilen > 0) {
213 ident = (ident << 8) | *p++;
214 ilen--;
216 if (ident > pc->para.chargeinfo) {
217 pc->para.chargeinfo = ident;
218 pc->st->l3.l3l4(pc->st, CC_CHARGE | INDICATION, pc);
220 if (pc->st->l3.debug & L3_DEB_CHARGE) {
221 if (*(p + 2) == 0) {
222 l3_debug(pc->st, "charging info during %d", pc->para.chargeinfo);
224 else {
225 l3_debug(pc->st, "charging info final %d", pc->para.chargeinfo);
229 )))))
230 break;
231 case 0x24: /* final */
232 FOO1("2A", 0x30, FOO1("2B", 0x30, FOO1("2C", 0xA1, FOO1("2D", 0x30, FOO1("2E", 0x02, ( {
233 ident = 0;
234 nlen = (nlen)?nlen:0; /* Make gcc happy */
235 while (ilen > 0) {
236 ident = (ident << 8) | *p++;
237 ilen--;
239 if (ident > pc->para.chargeinfo) {
240 pc->para.chargeinfo = ident;
241 pc->st->l3.l3l4(pc->st, CC_CHARGE | INDICATION, pc);
243 if (pc->st->l3.debug & L3_DEB_CHARGE) {
244 l3_debug(pc->st, "charging info final %d", pc->para.chargeinfo);
247 ))))))
248 break;
250 #undef FOO1
253 break;
254 case 2: /* return result */
255 l3_debug(pc->st, "return result break");
256 break;
257 case 3: /* return error */
258 l3_debug(pc->st, "return error break");
259 break;
260 default:
261 l3_debug(pc->st, "default break");
262 break;
265 #endif
267 static int
268 l3dss1_check_messagetype_validity(int mt)
270 /* verify if a message type exists */
271 switch (mt) {
272 case MT_ALERTING:
273 case MT_CALL_PROCEEDING:
274 case MT_CONNECT:
275 case MT_CONNECT_ACKNOWLEDGE:
276 case MT_PROGRESS:
277 case MT_SETUP:
278 case MT_SETUP_ACKNOWLEDGE:
279 case MT_RESUME:
280 case MT_RESUME_ACKNOWLEDGE:
281 case MT_RESUME_REJECT:
282 case MT_SUSPEND:
283 case MT_SUSPEND_ACKNOWLEDGE:
284 case MT_SUSPEND_REJECT:
285 case MT_USER_INFORMATION:
286 case MT_DISCONNECT:
287 case MT_RELEASE:
288 case MT_RELEASE_COMPLETE:
289 case MT_RESTART:
290 case MT_RESTART_ACKNOWLEDGE:
291 case MT_SEGMENT:
292 case MT_CONGESTION_CONTROL:
293 case MT_INFORMATION:
294 case MT_FACILITY:
295 case MT_NOTIFY:
296 case MT_STATUS:
297 case MT_STATUS_ENQUIRY:
298 return(1);
299 default:
300 return(0);
302 return(0);
305 static void
306 l3dss1_message(struct l3_process *pc, u_char mt)
308 struct sk_buff *skb;
309 u_char *p;
311 if (!(skb = l3_alloc_skb(4)))
312 return;
313 p = skb_put(skb, 4);
314 MsgHead(p, pc->callref, mt);
315 l3_msg(pc->st, DL_DATA | REQUEST, skb);
318 static void
319 l3dss1_release_req(struct l3_process *pc, u_char pr, void *arg)
321 StopAllL3Timer(pc);
322 newl3state(pc, 19);
323 l3dss1_message(pc, MT_RELEASE);
324 L3AddTimer(&pc->timer, T308, CC_T308_1);
327 static void
328 l3dss1_release_cmpl(struct l3_process *pc, u_char pr, void *arg)
330 u_char *p;
331 struct sk_buff *skb = arg;
332 int cause = -1;
334 p = skb->data;
335 pc->para.loc = 0;
336 if ((p = findie(p, skb->len, IE_CAUSE, 0))) {
337 p++;
338 if (*p++ == 2)
339 pc->para.loc = *p++;
340 cause = *p & 0x7f;
342 dev_kfree_skb(skb);
343 StopAllL3Timer(pc);
344 pc->para.cause = cause;
345 newl3state(pc, 0);
346 pc->st->l3.l3l4(pc->st, CC_RELEASE | CONFIRM, pc);
347 release_l3_process(pc);
350 #if EXT_BEARER_CAPS
352 u_char *
353 EncodeASyncParams(u_char * p, u_char si2)
354 { // 7c 06 88 90 21 42 00 bb
356 p[0] = p[1] = 0;
357 p[2] = 0x80;
358 if (si2 & 32) // 7 data bits
360 p[2] += 16;
361 else // 8 data bits
363 p[2] += 24;
365 if (si2 & 16) // 2 stop bits
367 p[2] += 96;
368 else // 1 stop bit
370 p[2] = 32;
372 if (si2 & 8) // even parity
374 p[2] += 2;
375 else // no parity
377 p[2] += 3;
379 switch (si2 & 0x07) {
380 case 0:
381 p[0] = 66; // 1200 bit/s
383 break;
384 case 1:
385 p[0] = 88; // 1200/75 bit/s
387 break;
388 case 2:
389 p[0] = 87; // 75/1200 bit/s
391 break;
392 case 3:
393 p[0] = 67; // 2400 bit/s
395 break;
396 case 4:
397 p[0] = 69; // 4800 bit/s
399 break;
400 case 5:
401 p[0] = 72; // 9600 bit/s
403 break;
404 case 6:
405 p[0] = 73; // 14400 bit/s
407 break;
408 case 7:
409 p[0] = 75; // 19200 bit/s
411 break;
413 return p + 3;
416 u_char
417 EncodeSyncParams(u_char si2, u_char ai)
420 switch (si2) {
421 case 0:
422 return ai + 2; // 1200 bit/s
424 case 1:
425 return ai + 24; // 1200/75 bit/s
427 case 2:
428 return ai + 23; // 75/1200 bit/s
430 case 3:
431 return ai + 3; // 2400 bit/s
433 case 4:
434 return ai + 5; // 4800 bit/s
436 case 5:
437 return ai + 8; // 9600 bit/s
439 case 6:
440 return ai + 9; // 14400 bit/s
442 case 7:
443 return ai + 11; // 19200 bit/s
445 case 8:
446 return ai + 14; // 48000 bit/s
448 case 9:
449 return ai + 15; // 56000 bit/s
451 case 15:
452 return ai + 40; // negotiate bit/s
454 default:
455 break;
457 return ai;
461 static u_char
462 DecodeASyncParams(u_char si2, u_char * p)
464 u_char info;
466 switch (p[5]) {
467 case 66: // 1200 bit/s
469 break; // si2 don't change
471 case 88: // 1200/75 bit/s
473 si2 += 1;
474 break;
475 case 87: // 75/1200 bit/s
477 si2 += 2;
478 break;
479 case 67: // 2400 bit/s
481 si2 += 3;
482 break;
483 case 69: // 4800 bit/s
485 si2 += 4;
486 break;
487 case 72: // 9600 bit/s
489 si2 += 5;
490 break;
491 case 73: // 14400 bit/s
493 si2 += 6;
494 break;
495 case 75: // 19200 bit/s
497 si2 += 7;
498 break;
501 info = p[7] & 0x7f;
502 if ((info & 16) && (!(info & 8))) // 7 data bits
504 si2 += 32; // else 8 data bits
506 if ((info & 96) == 96) // 2 stop bits
508 si2 += 16; // else 1 stop bit
510 if ((info & 2) && (!(info & 1))) // even parity
512 si2 += 8; // else no parity
514 return si2;
518 static u_char
519 DecodeSyncParams(u_char si2, u_char info)
521 info &= 0x7f;
522 switch (info) {
523 case 40: // bit/s negotiation failed ai := 165 not 175!
525 return si2 + 15;
526 case 15: // 56000 bit/s failed, ai := 0 not 169 !
528 return si2 + 9;
529 case 14: // 48000 bit/s
531 return si2 + 8;
532 case 11: // 19200 bit/s
534 return si2 + 7;
535 case 9: // 14400 bit/s
537 return si2 + 6;
538 case 8: // 9600 bit/s
540 return si2 + 5;
541 case 5: // 4800 bit/s
543 return si2 + 4;
544 case 3: // 2400 bit/s
546 return si2 + 3;
547 case 23: // 75/1200 bit/s
549 return si2 + 2;
550 case 24: // 1200/75 bit/s
552 return si2 + 1;
553 default: // 1200 bit/s
555 return si2;
559 static u_char
560 DecodeSI2(struct sk_buff *skb)
562 u_char *p; //, *pend=skb->data + skb->len;
564 if ((p = findie(skb->data, skb->len, 0x7c, 0))) {
565 switch (p[4] & 0x0f) {
566 case 0x01:
567 if (p[1] == 0x04) // sync. Bitratenadaption
569 return DecodeSyncParams(160, p[5]); // V.110/X.30
571 else if (p[1] == 0x06) // async. Bitratenadaption
573 return DecodeASyncParams(192, p); // V.110/X.30
575 break;
576 case 0x08: // if (p[5] == 0x02) // sync. Bitratenadaption
578 return DecodeSyncParams(176, p[5]); // V.120
580 break;
583 return 0;
586 #endif
589 static void
590 l3dss1_setup_req(struct l3_process *pc, u_char pr,
591 void *arg)
593 struct sk_buff *skb;
594 u_char tmp[128];
595 u_char *p = tmp;
596 u_char channel = 0;
597 u_char screen = 0x80;
598 u_char *teln;
599 u_char *msn;
600 u_char *sub;
601 u_char *sp;
602 int l;
604 MsgHead(p, pc->callref, MT_SETUP);
607 * Set Bearer Capability, Map info from 1TR6-convention to EDSS1
609 #if HISAX_EURO_SENDCOMPLETE
610 *p++ = 0xa1; /* complete indicator */
611 #endif
612 switch (pc->para.setup.si1) {
613 case 1: /* Telephony */
614 *p++ = 0x4; /* BC-IE-code */
615 *p++ = 0x3; /* Length */
616 *p++ = 0x90; /* Coding Std. CCITT, 3.1 kHz audio */
617 *p++ = 0x90; /* Circuit-Mode 64kbps */
618 *p++ = 0xa3; /* A-Law Audio */
619 break;
620 case 5: /* Datatransmission 64k, BTX */
621 case 7: /* Datatransmission 64k */
622 default:
623 *p++ = 0x4; /* BC-IE-code */
624 *p++ = 0x2; /* Length */
625 *p++ = 0x88; /* Coding Std. CCITT, unrestr. dig. Inform. */
626 *p++ = 0x90; /* Circuit-Mode 64kbps */
627 break;
630 * What about info2? Mapping to High-Layer-Compatibility?
632 teln = pc->para.setup.phone;
633 if (*teln) {
634 /* parse number for special things */
635 if (!isdigit(*teln)) {
636 switch (0x5f & *teln) {
637 case 'C':
638 channel = 0x08;
639 case 'P':
640 channel |= 0x80;
641 teln++;
642 if (*teln == '1')
643 channel |= 0x01;
644 else
645 channel |= 0x02;
646 break;
647 case 'R':
648 screen = 0xA0;
649 break;
650 case 'D':
651 screen = 0x80;
652 break;
653 default:
654 if (pc->debug & L3_DEB_WARN)
655 l3_debug(pc->st, "Wrong MSN Code");
656 break;
658 teln++;
661 if (channel) {
662 *p++ = IE_CHANNEL_ID;
663 *p++ = 1;
664 *p++ = channel;
666 msn = pc->para.setup.eazmsn;
667 sub = NULL;
668 sp = msn;
669 while (*sp) {
670 if ('.' == *sp) {
671 sub = sp;
672 *sp = 0;
673 } else
674 sp++;
676 if (*msn) {
677 *p++ = 0x6c;
678 *p++ = strlen(msn) + (screen ? 2 : 1);
679 /* Classify as AnyPref. */
680 if (screen) {
681 *p++ = 0x01; /* Ext = '0'B, Type = '000'B, Plan = '0001'B. */
682 *p++ = screen;
683 } else
684 *p++ = 0x81; /* Ext = '1'B, Type = '000'B, Plan = '0001'B. */
685 while (*msn)
686 *p++ = *msn++ & 0x7f;
688 if (sub) {
689 *sub++ = '.';
690 *p++ = 0x6d; /* Calling party subaddress */
691 *p++ = strlen(sub) + 2;
692 *p++ = 0x80; /* NSAP coded */
693 *p++ = 0x50; /* local IDI format */
694 while (*sub)
695 *p++ = *sub++ & 0x7f;
697 sub = NULL;
698 sp = teln;
699 while (*sp) {
700 if ('.' == *sp) {
701 sub = sp;
702 *sp = 0;
703 } else
704 sp++;
706 *p++ = 0x70;
707 *p++ = strlen(teln) + 1;
708 /* Classify as AnyPref. */
709 *p++ = 0x81; /* Ext = '1'B, Type = '000'B, Plan = '0001'B. */
710 while (*teln)
711 *p++ = *teln++ & 0x7f;
713 if (sub) {
714 *sub++ = '.';
715 *p++ = 0x71; /* Called party subaddress */
716 *p++ = strlen(sub) + 2;
717 *p++ = 0x80; /* NSAP coded */
718 *p++ = 0x50; /* local IDI format */
719 while (*sub)
720 *p++ = *sub++ & 0x7f;
722 #if EXT_BEARER_CAPS
723 if ((pc->para.setup.si2 >= 160) && (pc->para.setup.si2 <= 175)) { // sync. Bitratenadaption, V.110/X.30
725 *p++ = 0x7c;
726 *p++ = 0x04;
727 *p++ = 0x88;
728 *p++ = 0x90;
729 *p++ = 0x21;
730 *p++ = EncodeSyncParams(pc->para.setup.si2 - 160, 0x80);
731 } else if ((pc->para.setup.si2 >= 176) && (pc->para.setup.si2 <= 191)) { // sync. Bitratenadaption, V.120
733 *p++ = 0x7c;
734 *p++ = 0x05;
735 *p++ = 0x88;
736 *p++ = 0x90;
737 *p++ = 0x28;
738 *p++ = EncodeSyncParams(pc->para.setup.si2 - 176, 0);
739 *p++ = 0x82;
740 } else if (pc->para.setup.si2 >= 192) { // async. Bitratenadaption, V.110/X.30
742 *p++ = 0x7c;
743 *p++ = 0x06;
744 *p++ = 0x88;
745 *p++ = 0x90;
746 *p++ = 0x21;
747 p = EncodeASyncParams(p, pc->para.setup.si2 - 192);
748 #if HISAX_SEND_STD_LLC_IE
749 } else {
750 *p++ = 0x7c;
751 *p++ = 0x02;
752 *p++ = 0x88;
753 *p++ = 0x90;
754 #endif
756 #endif
757 l = p - tmp;
758 if (!(skb = l3_alloc_skb(l)))
759 return;
760 memcpy(skb_put(skb, l), tmp, l);
761 L3DelTimer(&pc->timer);
762 L3AddTimer(&pc->timer, T303, CC_T303);
763 newl3state(pc, 1);
764 l3_msg(pc->st, DL_DATA | REQUEST, skb);
767 static void
768 l3dss1_call_proc(struct l3_process *pc, u_char pr, void *arg)
770 u_char *p;
771 struct sk_buff *skb = arg;
773 L3DelTimer(&pc->timer);
774 p = skb->data;
775 if ((p = findie(p, skb->len, IE_CHANNEL_ID, 0))) {
776 pc->para.bchannel = p[2] & 0x3;
777 if ((!pc->para.bchannel) && (pc->debug & L3_DEB_WARN))
778 l3_debug(pc->st, "setup answer without bchannel");
779 } else if (pc->debug & L3_DEB_WARN)
780 l3_debug(pc->st, "setup answer without bchannel");
781 dev_kfree_skb(skb);
782 newl3state(pc, 3);
783 L3AddTimer(&pc->timer, T310, CC_T310);
784 pc->st->l3.l3l4(pc->st, CC_PROCEEDING | INDICATION, pc);
787 static void
788 l3dss1_setup_ack(struct l3_process *pc, u_char pr, void *arg)
790 u_char *p;
791 struct sk_buff *skb = arg;
793 L3DelTimer(&pc->timer);
794 p = skb->data;
795 if ((p = findie(p, skb->len, IE_CHANNEL_ID, 0))) {
796 pc->para.bchannel = p[2] & 0x3;
797 if ((!pc->para.bchannel) && (pc->debug & L3_DEB_WARN))
798 l3_debug(pc->st, "setup answer without bchannel");
799 } else if (pc->debug & L3_DEB_WARN)
800 l3_debug(pc->st, "setup answer without bchannel");
801 dev_kfree_skb(skb);
802 newl3state(pc, 2);
803 L3AddTimer(&pc->timer, T304, CC_T304);
804 pc->st->l3.l3l4(pc->st, CC_MORE_INFO | INDICATION, pc);
807 static void
808 l3dss1_disconnect(struct l3_process *pc, u_char pr, void *arg)
810 u_char *p;
811 struct sk_buff *skb = arg;
812 int cause = -1;
814 StopAllL3Timer(pc);
815 p = skb->data;
816 pc->para.loc = 0;
817 if ((p = findie(p, skb->len, IE_CAUSE, 0))) {
818 p++;
819 if (*p++ == 2)
820 pc->para.loc = *p++;
821 cause = *p & 0x7f;
823 dev_kfree_skb(skb);
824 newl3state(pc, 12);
825 pc->para.cause = cause;
826 pc->st->l3.l3l4(pc->st, CC_DISCONNECT | INDICATION, pc);
829 static void
830 l3dss1_connect(struct l3_process *pc, u_char pr, void *arg)
832 struct sk_buff *skb = arg;
834 dev_kfree_skb(skb);
835 L3DelTimer(&pc->timer); /* T310 */
836 newl3state(pc, 10);
837 pc->para.chargeinfo = 0;
838 pc->st->l3.l3l4(pc->st, CC_SETUP | CONFIRM, pc);
841 static void
842 l3dss1_alerting(struct l3_process *pc, u_char pr, void *arg)
844 struct sk_buff *skb = arg;
846 dev_kfree_skb(skb);
847 L3DelTimer(&pc->timer); /* T304 */
848 newl3state(pc, 4);
849 pc->st->l3.l3l4(pc->st, CC_ALERTING | INDICATION, pc);
852 static void
853 l3dss1_msg_without_setup(struct l3_process *pc, u_char pr, void *arg)
855 /* This routine is called if here was no SETUP made (checks in dss1up and in
856 * l3dss1_setup) and a RELEASE_COMPLETE have to be sent with an error code
857 * MT_STATUS_ENQUIRE in the NULL state is handled too
859 u_char tmp[16];
860 u_char *p = tmp;
861 int l;
862 struct sk_buff *skb;
864 switch (pc->para.cause) {
865 case 81: /* 0x51 invalid callreference */
866 case 88: /* 0x58 incomp destination */
867 case 96: /* 0x60 mandory IE missing */
868 case 101: /* 0x65 incompatible Callstate */
869 MsgHead(p, pc->callref, MT_RELEASE_COMPLETE);
870 *p++ = IE_CAUSE;
871 *p++ = 0x2;
872 *p++ = 0x80;
873 *p++ = pc->para.cause | 0x80;
874 break;
875 default:
876 printk(KERN_ERR "HiSax internal error l3dss1_msg_without_setup\n");
877 return;
879 l = p - tmp;
880 if (!(skb = l3_alloc_skb(l)))
881 return;
882 memcpy(skb_put(skb, l), tmp, l);
883 l3_msg(pc->st, DL_DATA | REQUEST, skb);
884 release_l3_process(pc);
887 static void
888 l3dss1_setup(struct l3_process *pc, u_char pr, void *arg)
890 u_char *p, *ptmp[8];
891 int i;
892 int bcfound = 0;
893 char tmp[80];
894 struct sk_buff *skb = arg;
896 /* ETS 300-104 1.3.4 and 1.3.5
897 * we need to detect unknown inform. element from 0 to 7
899 p = skb->data;
900 for (i = 0; i < 8; i++)
901 ptmp[i] = skb->data;
902 if (findie(ptmp[1], skb->len, 0x01, 0)
903 || findie(ptmp[2], skb->len, 0x02, 0)
904 || findie(ptmp[3], skb->len, 0x03, 0)
905 || findie(ptmp[5], skb->len, 0x05, 0)
906 || findie(ptmp[6], skb->len, 0x06, 0)
907 || findie(ptmp[7], skb->len, 0x07, 0)) {
908 /* if ie is < 8 and not 0 nor 4, send RELEASE_COMPLETE
909 * cause 0x60
911 pc->para.cause = 0x60;
912 dev_kfree_skb(skb);
913 l3dss1_msg_without_setup(pc, pr, NULL);
914 return;
917 * Channel Identification
919 p = skb->data;
920 if ((p = findie(p, skb->len, IE_CHANNEL_ID, 0))) {
921 pc->para.bchannel = p[2] & 0x3;
922 if (pc->para.bchannel)
923 bcfound++;
924 else if (pc->debug & L3_DEB_WARN)
925 l3_debug(pc->st, "setup without bchannel");
926 } else {
927 if (pc->debug & L3_DEB_WARN)
928 l3_debug(pc->st, "setup without bchannel");
929 pc->para.cause = 0x60;
930 dev_kfree_skb(skb);
931 l3dss1_msg_without_setup(pc, pr, NULL);
932 return;
935 * Bearer Capabilities
937 p = skb->data;
938 if ((p = findie(p, skb->len, 0x04, 0))) {
939 pc->para.setup.si2 = 0;
940 switch (p[2] & 0x1f) {
941 case 0x00:
942 /* Speech */
943 case 0x10:
944 /* 3.1 Khz audio */
945 pc->para.setup.si1 = 1;
946 break;
947 case 0x08:
948 /* Unrestricted digital information */
949 pc->para.setup.si1 = 7;
950 /* JIM, 05.11.97 I wanna set service indicator 2 */
951 #if EXT_BEARER_CAPS
952 pc->para.setup.si2 = DecodeSI2(skb);
953 printk(KERN_DEBUG "HiSax: SI=%d, AI=%d\n",
954 pc->para.setup.si1, pc->para.setup.si2);
955 #endif
956 break;
957 case 0x09:
958 /* Restricted digital information */
959 pc->para.setup.si1 = 2;
960 break;
961 case 0x11:
962 /* Unrestr. digital information with tones/announcements */
963 pc->para.setup.si1 = 3;
964 break;
965 case 0x18:
966 /* Video */
967 pc->para.setup.si1 = 4;
968 break;
969 default:
970 pc->para.setup.si1 = 0;
972 } else {
973 if (pc->debug & L3_DEB_WARN)
974 l3_debug(pc->st, "setup without bearer capabilities");
975 /* ETS 300-104 1.3.3 */
976 pc->para.cause = 0x60;
977 dev_kfree_skb(skb);
978 l3dss1_msg_without_setup(pc, pr, NULL);
979 return;
982 p = skb->data;
983 if ((p = findie(p, skb->len, 0x70, 0)))
984 iecpy(pc->para.setup.eazmsn, p, 1);
985 else
986 pc->para.setup.eazmsn[0] = 0;
988 p = skb->data;
989 if ((p = findie(p, skb->len, 0x71, 0))) {
990 /* Called party subaddress */
991 if ((p[1] >= 2) && (p[2] == 0x80) && (p[3] == 0x50)) {
992 tmp[0] = '.';
993 iecpy(&tmp[1], p, 2);
994 strcat(pc->para.setup.eazmsn, tmp);
995 } else if (pc->debug & L3_DEB_WARN)
996 l3_debug(pc->st, "wrong called subaddress");
998 p = skb->data;
999 if ((p = findie(p, skb->len, 0x6c, 0))) {
1000 pc->para.setup.plan = p[2];
1001 if (p[2] & 0x80) {
1002 iecpy(pc->para.setup.phone, p, 1);
1003 pc->para.setup.screen = 0;
1004 } else {
1005 iecpy(pc->para.setup.phone, p, 2);
1006 pc->para.setup.screen = p[3];
1008 } else {
1009 pc->para.setup.phone[0] = 0;
1010 pc->para.setup.plan = 0;
1011 pc->para.setup.screen = 0;
1013 p = skb->data;
1014 if ((p = findie(p, skb->len, 0x6d, 0))) {
1015 /* Calling party subaddress */
1016 if ((p[1] >= 2) && (p[2] == 0x80) && (p[3] == 0x50)) {
1017 tmp[0] = '.';
1018 iecpy(&tmp[1], p, 2);
1019 strcat(pc->para.setup.phone, tmp);
1020 } else if (pc->debug & L3_DEB_WARN)
1021 l3_debug(pc->st, "wrong calling subaddress");
1023 dev_kfree_skb(skb);
1025 if (bcfound) {
1026 if ((pc->para.setup.si1 != 7) && (pc->debug & L3_DEB_WARN)) {
1027 l3_debug(pc->st, "non-digital call: %s -> %s",
1028 pc->para.setup.phone, pc->para.setup.eazmsn);
1030 if ((pc->para.setup.si1 != 7) &&
1031 test_bit(FLG_PTP, &pc->st->l2.flag)) {
1032 pc->para.cause = 0x58;
1033 l3dss1_msg_without_setup(pc, pr, NULL);
1034 return;
1036 newl3state(pc, 6);
1037 pc->st->l3.l3l4(pc->st, CC_SETUP | INDICATION, pc);
1038 } else
1039 release_l3_process(pc);
1042 static void
1043 l3dss1_reset(struct l3_process *pc, u_char pr, void *arg)
1045 release_l3_process(pc);
1048 static void
1049 l3dss1_setup_rsp(struct l3_process *pc, u_char pr,
1050 void *arg)
1052 newl3state(pc, 8);
1053 l3dss1_message(pc, MT_CONNECT);
1054 L3DelTimer(&pc->timer);
1055 L3AddTimer(&pc->timer, T313, CC_T313);
1058 static void
1059 l3dss1_connect_ack(struct l3_process *pc, u_char pr, void *arg)
1061 struct sk_buff *skb = arg;
1063 dev_kfree_skb(skb);
1064 newl3state(pc, 10);
1065 L3DelTimer(&pc->timer);
1066 pc->st->l3.l3l4(pc->st, CC_SETUP_COMPL | INDICATION, pc);
1069 static void
1070 l3dss1_disconnect_req(struct l3_process *pc, u_char pr, void *arg)
1072 struct sk_buff *skb;
1073 u_char tmp[16];
1074 u_char *p = tmp;
1075 int l;
1076 u_char cause = 0x10;
1078 if (pc->para.cause > 0)
1079 cause = pc->para.cause;
1081 StopAllL3Timer(pc);
1083 MsgHead(p, pc->callref, MT_DISCONNECT);
1085 *p++ = IE_CAUSE;
1086 *p++ = 0x2;
1087 *p++ = 0x80;
1088 *p++ = cause | 0x80;
1090 l = p - tmp;
1091 if (!(skb = l3_alloc_skb(l)))
1092 return;
1093 memcpy(skb_put(skb, l), tmp, l);
1094 newl3state(pc, 11);
1095 l3_msg(pc->st, DL_DATA | REQUEST, skb);
1096 L3AddTimer(&pc->timer, T305, CC_T305);
1099 static void
1100 l3dss1_reject_req(struct l3_process *pc, u_char pr, void *arg)
1102 struct sk_buff *skb;
1103 u_char tmp[16];
1104 u_char *p = tmp;
1105 int l;
1106 u_char cause = 0x95;
1108 if (pc->para.cause > 0)
1109 cause = pc->para.cause;
1111 MsgHead(p, pc->callref, MT_RELEASE_COMPLETE);
1113 *p++ = IE_CAUSE;
1114 *p++ = 0x2;
1115 *p++ = 0x80;
1116 *p++ = cause;
1118 l = p - tmp;
1119 if (!(skb = l3_alloc_skb(l)))
1120 return;
1121 memcpy(skb_put(skb, l), tmp, l);
1122 l3_msg(pc->st, DL_DATA | REQUEST, skb);
1123 pc->st->l3.l3l4(pc->st, CC_RELEASE | INDICATION, pc);
1124 newl3state(pc, 0);
1125 release_l3_process(pc);
1128 static void
1129 l3dss1_release(struct l3_process *pc, u_char pr, void *arg)
1131 u_char *p;
1132 struct sk_buff *skb = arg;
1133 int cause = -1;
1135 p = skb->data;
1136 if ((p = findie(p, skb->len, IE_CAUSE, 0))) {
1137 p++;
1138 if (*p++ == 2)
1139 pc->para.loc = *p++;
1140 cause = *p & 0x7f;
1142 p = skb->data;
1143 if ((p = findie(p, skb->len, IE_FACILITY, 0))) {
1144 #if HISAX_DE_AOC
1145 l3dss1_parse_facility(pc, p);
1146 #else
1147 p = NULL;
1148 #endif
1150 dev_kfree_skb(skb);
1151 StopAllL3Timer(pc);
1152 pc->para.cause = cause;
1153 l3dss1_message(pc, MT_RELEASE_COMPLETE);
1154 pc->st->l3.l3l4(pc->st, CC_RELEASE | INDICATION, pc);
1155 newl3state(pc, 0);
1156 release_l3_process(pc);
1159 static void
1160 l3dss1_alert_req(struct l3_process *pc, u_char pr,
1161 void *arg)
1163 newl3state(pc, 7);
1164 l3dss1_message(pc, MT_ALERTING);
1167 static void
1168 l3dss1_status_enq(struct l3_process *pc, u_char pr, void *arg)
1170 u_char tmp[16];
1171 u_char *p = tmp;
1172 int l;
1173 struct sk_buff *skb = arg;
1175 dev_kfree_skb(skb);
1177 MsgHead(p, pc->callref, MT_STATUS);
1179 *p++ = IE_CAUSE;
1180 *p++ = 0x2;
1181 *p++ = 0x80;
1182 *p++ = 0x9E; /* answer status enquire */
1184 *p++ = 0x14; /* CallState */
1185 *p++ = 0x1;
1186 *p++ = pc->state & 0x3f;
1188 l = p - tmp;
1189 if (!(skb = l3_alloc_skb(l)))
1190 return;
1191 memcpy(skb_put(skb, l), tmp, l);
1192 l3_msg(pc->st, DL_DATA | REQUEST, skb);
1195 static void
1196 l3dss1_status_req(struct l3_process *pc, u_char pr, void *arg)
1198 /* ETS 300-104 7.4.1, 8.4.1, 10.3.1, 11.4.1, 12.4.1, 13.4.1, 14.4.1...
1199 if setup has been made and a non expected message type is received, we must send MT_STATUS cause 0x62 */
1200 u_char tmp[16];
1201 u_char *p = tmp;
1202 int l;
1203 struct sk_buff *skb = arg;
1205 dev_kfree_skb(skb);
1207 MsgHead(p, pc->callref, MT_STATUS);
1209 *p++ = IE_CAUSE;
1210 *p++ = 0x2;
1211 *p++ = 0x80;
1212 *p++ = 0x62 | 0x80; /* status sending */
1214 *p++ = 0x14; /* CallState */
1215 *p++ = 0x1;
1216 *p++ = pc->state & 0x3f;
1218 l = p - tmp;
1219 if (!(skb = l3_alloc_skb(l)))
1220 return;
1221 memcpy(skb_put(skb, l), tmp, l);
1222 l3_msg(pc->st, DL_DATA | REQUEST, skb);
1225 static void
1226 l3dss1_release_ind(struct l3_process *pc, u_char pr, void *arg)
1228 u_char *p;
1229 struct sk_buff *skb = arg;
1230 int callState = 0;
1231 p = skb->data;
1233 if ((p = findie(p, skb->len, IE_CALL_STATE, 0))) {
1234 p++;
1235 if (1 == *p++)
1236 callState = *p;
1238 if (callState == 0) {
1239 /* ETS 300-104 7.6.1, 8.6.1, 10.6.1... and 16.1
1240 * set down layer 3 without sending any message
1242 pc->st->l3.l3l4(pc->st, CC_RELEASE | INDICATION, pc);
1243 newl3state(pc, 0);
1244 release_l3_process(pc);
1245 } else {
1246 pc->st->l3.l3l4(pc->st, CC_IGNORE | INDICATION, pc);
1250 static void
1251 l3dss1_t303(struct l3_process *pc, u_char pr, void *arg)
1253 if (pc->N303 > 0) {
1254 pc->N303--;
1255 L3DelTimer(&pc->timer);
1256 l3dss1_setup_req(pc, pr, arg);
1257 } else {
1258 L3DelTimer(&pc->timer);
1259 pc->st->l3.l3l4(pc->st, CC_NOSETUP_RSP, pc);
1260 release_l3_process(pc);
1264 static void
1265 l3dss1_t304(struct l3_process *pc, u_char pr, void *arg)
1267 L3DelTimer(&pc->timer);
1268 pc->para.cause = 0xE6;
1269 l3dss1_disconnect_req(pc, pr, NULL);
1270 pc->st->l3.l3l4(pc->st, CC_SETUP_ERR, pc);
1274 static void
1275 l3dss1_t305(struct l3_process *pc, u_char pr, void *arg)
1277 u_char tmp[16];
1278 u_char *p = tmp;
1279 int l;
1280 struct sk_buff *skb;
1281 u_char cause = 0x90;
1283 L3DelTimer(&pc->timer);
1284 if (pc->para.cause > 0)
1285 cause = pc->para.cause | 0x80;
1287 MsgHead(p, pc->callref, MT_RELEASE);
1289 *p++ = IE_CAUSE;
1290 *p++ = 0x2;
1291 *p++ = 0x80;
1292 *p++ = cause;
1294 l = p - tmp;
1295 if (!(skb = l3_alloc_skb(l)))
1296 return;
1297 memcpy(skb_put(skb, l), tmp, l);
1298 newl3state(pc, 19);
1299 l3_msg(pc->st, DL_DATA | REQUEST, skb);
1300 L3AddTimer(&pc->timer, T308, CC_T308_1);
1303 static void
1304 l3dss1_t310(struct l3_process *pc, u_char pr, void *arg)
1306 L3DelTimer(&pc->timer);
1307 pc->para.cause = 0xE6;
1308 l3dss1_disconnect_req(pc, pr, NULL);
1309 pc->st->l3.l3l4(pc->st, CC_SETUP_ERR, pc);
1312 static void
1313 l3dss1_t313(struct l3_process *pc, u_char pr, void *arg)
1315 L3DelTimer(&pc->timer);
1316 pc->para.cause = 0xE6;
1317 l3dss1_disconnect_req(pc, pr, NULL);
1318 pc->st->l3.l3l4(pc->st, CC_CONNECT_ERR, pc);
1321 static void
1322 l3dss1_t308_1(struct l3_process *pc, u_char pr, void *arg)
1324 newl3state(pc, 19);
1325 L3DelTimer(&pc->timer);
1326 l3dss1_message(pc, MT_RELEASE);
1327 L3AddTimer(&pc->timer, T308, CC_T308_2);
1330 static void
1331 l3dss1_t308_2(struct l3_process *pc, u_char pr, void *arg)
1333 L3DelTimer(&pc->timer);
1334 pc->st->l3.l3l4(pc->st, CC_RELEASE_ERR, pc);
1335 release_l3_process(pc);
1338 static void
1339 l3dss1_t318(struct l3_process *pc, u_char pr, void *arg)
1341 L3DelTimer(&pc->timer);
1342 pc->para.cause = 0x66; /* Timer expiry */
1343 pc->para.loc = 0; /* local */
1344 pc->st->l3.l3l4(pc->st, CC_RESUME_ERR, pc);
1345 newl3state(pc, 19);
1346 l3dss1_message(pc, MT_RELEASE);
1347 L3AddTimer(&pc->timer, T308, CC_T308_1);
1350 static void
1351 l3dss1_t319(struct l3_process *pc, u_char pr, void *arg)
1353 L3DelTimer(&pc->timer);
1354 pc->para.cause = 0x66; /* Timer expiry */
1355 pc->para.loc = 0; /* local */
1356 pc->st->l3.l3l4(pc->st, CC_SUSPEND_ERR, pc);
1357 newl3state(pc, 10);
1360 static void
1361 l3dss1_restart(struct l3_process *pc, u_char pr, void *arg)
1363 L3DelTimer(&pc->timer);
1364 pc->st->l3.l3l4(pc->st, CC_DLRL | INDICATION, pc);
1365 release_l3_process(pc);
1368 static void
1369 l3dss1_status(struct l3_process *pc, u_char pr, void *arg)
1371 u_char *p;
1372 char tmp[64], *t;
1373 int l;
1374 struct sk_buff *skb = arg;
1375 int cause, callState;
1377 cause = callState = -1;
1378 p = skb->data;
1379 t = tmp;
1380 if ((p = findie(p, skb->len, IE_CAUSE, 0))) {
1381 p++;
1382 l = *p++;
1383 t += sprintf(t, "Status CR %x Cause:", pc->callref);
1384 while (l--) {
1385 cause = *p;
1386 t += sprintf(t, " %2x", *p++);
1388 } else
1389 sprintf(t, "Status CR %x no Cause", pc->callref);
1390 l3_debug(pc->st, tmp);
1391 p = skb->data;
1392 t = tmp;
1393 t += sprintf(t, "Status state %x ", pc->state);
1394 if ((p = findie(p, skb->len, IE_CALL_STATE, 0))) {
1395 p++;
1396 if (1 == *p++) {
1397 callState = *p;
1398 t += sprintf(t, "peer state %x", *p);
1399 } else
1400 t += sprintf(t, "peer state len error");
1401 } else
1402 sprintf(t, "no peer state");
1403 l3_debug(pc->st, tmp);
1404 if (((cause & 0x7f) == 0x6f) && (callState == 0)) {
1405 /* ETS 300-104 7.6.1, 8.6.1, 10.6.1...
1406 * if received MT_STATUS with cause == 0x6f and call
1407 * state == 0, then we must set down layer 3
1409 l3dss1_release_ind(pc, pr, arg);
1410 } else
1411 dev_kfree_skb(skb);
1414 static void
1415 l3dss1_facility(struct l3_process *pc, u_char pr, void *arg)
1417 u_char *p;
1418 struct sk_buff *skb = arg;
1420 p = skb->data;
1421 if ((p = findie(p, skb->len, IE_FACILITY, 0))) {
1422 #if HISAX_DE_AOC
1423 l3dss1_parse_facility(pc, p);
1424 #else
1425 p = NULL;
1426 #endif
1430 static void
1431 l3dss1_suspend_req(struct l3_process *pc, u_char pr, void *arg)
1433 struct sk_buff *skb;
1434 u_char tmp[32];
1435 u_char *p = tmp;
1436 u_char i, l;
1437 u_char *msg = pc->chan->setup.phone;
1439 MsgHead(p, pc->callref, MT_SUSPEND);
1441 *p++ = IE_CALLID;
1442 l = *msg++;
1443 if (l && (l <= 10)) { /* Max length 10 octets */
1444 *p++ = l;
1445 for (i = 0; i < l; i++)
1446 *p++ = *msg++;
1447 } else {
1448 l3_debug(pc->st, "SUS wrong CALLID len %d", l);
1449 return;
1451 l = p - tmp;
1452 if (!(skb = l3_alloc_skb(l)))
1453 return;
1454 memcpy(skb_put(skb, l), tmp, l);
1455 l3_msg(pc->st, DL_DATA | REQUEST, skb);
1456 newl3state(pc, 15);
1457 L3AddTimer(&pc->timer, T319, CC_T319);
1460 static void
1461 l3dss1_suspend_ack(struct l3_process *pc, u_char pr, void *arg)
1463 struct sk_buff *skb = arg;
1465 L3DelTimer(&pc->timer);
1466 newl3state(pc, 0);
1467 dev_kfree_skb(skb);
1468 pc->para.cause = -1;
1469 pc->st->l3.l3l4(pc->st, CC_SUSPEND | CONFIRM, pc);
1470 release_l3_process(pc);
1473 static void
1474 l3dss1_suspend_rej(struct l3_process *pc, u_char pr, void *arg)
1476 u_char *p;
1477 struct sk_buff *skb = arg;
1478 int cause = -1;
1480 L3DelTimer(&pc->timer);
1481 p = skb->data;
1482 if ((p = findie(p, skb->len, IE_CAUSE, 0))) {
1483 p++;
1484 if (*p++ == 2)
1485 pc->para.loc = *p++;
1486 cause = *p & 0x7f;
1488 dev_kfree_skb(skb);
1489 pc->para.cause = cause;
1490 pc->st->l3.l3l4(pc->st, CC_SUSPEND_ERR, pc);
1491 newl3state(pc, 10);
1494 static void
1495 l3dss1_resume_req(struct l3_process *pc, u_char pr, void *arg)
1497 struct sk_buff *skb;
1498 u_char tmp[32];
1499 u_char *p = tmp;
1500 u_char i, l;
1501 u_char *msg = pc->para.setup.phone;
1503 MsgHead(p, pc->callref, MT_RESUME);
1505 *p++ = IE_CALLID;
1506 l = *msg++;
1507 if (l && (l <= 10)) { /* Max length 10 octets */
1508 *p++ = l;
1509 for (i = 0; i < l; i++)
1510 *p++ = *msg++;
1511 } else {
1512 l3_debug(pc->st, "RES wrong CALLID len %d", l);
1513 return;
1515 l = p - tmp;
1516 if (!(skb = l3_alloc_skb(l)))
1517 return;
1518 memcpy(skb_put(skb, l), tmp, l);
1519 l3_msg(pc->st, DL_DATA | REQUEST, skb);
1520 newl3state(pc, 17);
1521 L3AddTimer(&pc->timer, T319, CC_T319);
1524 static void
1525 l3dss1_resume_ack(struct l3_process *pc, u_char pr, void *arg)
1527 u_char *p;
1528 struct sk_buff *skb = arg;
1530 L3DelTimer(&pc->timer);
1531 p = skb->data;
1532 if ((p = findie(p, skb->len, IE_CHANNEL_ID, 0))) {
1533 pc->para.bchannel = p[2] & 0x3;
1534 if ((!pc->para.bchannel) && (pc->debug & L3_DEB_WARN))
1535 l3_debug(pc->st, "resume ack without bchannel");
1536 } else if (pc->debug & L3_DEB_WARN)
1537 l3_debug(pc->st, "resume ack without bchannel");
1538 dev_kfree_skb(skb);
1539 pc->st->l3.l3l4(pc->st, CC_RESUME | CONFIRM, pc);
1540 newl3state(pc, 10);
1543 static void
1544 l3dss1_resume_rej(struct l3_process *pc, u_char pr, void *arg)
1546 u_char *p;
1547 struct sk_buff *skb = arg;
1548 int cause = -1;
1550 L3DelTimer(&pc->timer);
1551 p = skb->data;
1552 if ((p = findie(p, skb->len, IE_CAUSE, 0))) {
1553 p++;
1554 if (*p++ == 2)
1555 pc->para.loc = *p++;
1556 cause = *p & 0x7f;
1558 dev_kfree_skb(skb);
1559 pc->para.cause = cause;
1560 newl3state(pc, 0);
1561 pc->st->l3.l3l4(pc->st, CC_RESUME_ERR, pc);
1562 release_l3_process(pc);
1565 static void
1566 l3dss1_global_restart(struct l3_process *pc, u_char pr, void *arg)
1568 u_char tmp[32];
1569 u_char *p;
1570 u_char ri, ch = 0, chan = 0;
1571 int l;
1572 struct sk_buff *skb = arg;
1573 struct l3_process *up;
1575 newl3state(pc, 2);
1576 L3DelTimer(&pc->timer);
1577 p = skb->data;
1578 if ((p = findie(p, skb->len, IE_RESTART_IND, 0))) {
1579 ri = p[2];
1580 l3_debug(pc->st, "Restart %x", ri);
1581 } else {
1582 l3_debug(pc->st, "Restart without restart IE");
1583 ri = 0x86;
1585 p = skb->data;
1586 if ((p = findie(p, skb->len, IE_CHANNEL_ID, 0))) {
1587 chan = p[2] & 3;
1588 ch = p[2];
1589 if (pc->st->l3.debug)
1590 l3_debug(pc->st, "Restart for channel %d", chan);
1592 dev_kfree_skb(skb);
1593 newl3state(pc, 2);
1594 up = pc->st->l3.proc;
1595 while (up) {
1596 if ((ri & 7) == 7)
1597 up->st->lli.l4l3(up->st, CC_RESTART | REQUEST, up);
1598 else if (up->para.bchannel == chan)
1599 up->st->lli.l4l3(up->st, CC_RESTART | REQUEST, up);
1600 up = up->next;
1602 p = tmp;
1603 MsgHead(p, pc->callref, MT_RESTART_ACKNOWLEDGE);
1604 if (chan) {
1605 *p++ = IE_CHANNEL_ID;
1606 *p++ = 1;
1607 *p++ = ch | 0x80;
1609 *p++ = 0x79; /* RESTART Ind */
1610 *p++ = 1;
1611 *p++ = ri;
1612 l = p - tmp;
1613 if (!(skb = l3_alloc_skb(l)))
1614 return;
1615 memcpy(skb_put(skb, l), tmp, l);
1616 newl3state(pc, 0);
1617 l3_msg(pc->st, DL_DATA | REQUEST, skb);
1619 /* *INDENT-OFF* */
1620 static struct stateentry downstatelist[] =
1622 {SBIT(0),
1623 CC_SETUP | REQUEST, l3dss1_setup_req},
1624 {SBIT(0),
1625 CC_RESUME | REQUEST, l3dss1_resume_req},
1626 {SBIT(1) | SBIT(2) | SBIT(3) | SBIT(4) | SBIT(6) | SBIT(7) | SBIT(8) | SBIT(10),
1627 CC_DISCONNECT | REQUEST, l3dss1_disconnect_req},
1628 {SBIT(12),
1629 CC_RELEASE | REQUEST, l3dss1_release_req},
1630 {ALL_STATES,
1631 CC_DLRL | REQUEST, l3dss1_reset},
1632 {ALL_STATES,
1633 CC_RESTART | REQUEST, l3dss1_restart},
1634 {SBIT(6),
1635 CC_IGNORE | REQUEST, l3dss1_reset},
1636 {SBIT(6),
1637 CC_REJECT | REQUEST, l3dss1_reject_req},
1638 {SBIT(6),
1639 CC_ALERTING | REQUEST, l3dss1_alert_req},
1640 {SBIT(6) | SBIT(7),
1641 CC_SETUP | RESPONSE, l3dss1_setup_rsp},
1642 {SBIT(10),
1643 CC_SUSPEND | REQUEST, l3dss1_suspend_req},
1644 {SBIT(1),
1645 CC_T303, l3dss1_t303},
1646 {SBIT(2),
1647 CC_T304, l3dss1_t304},
1648 {SBIT(3),
1649 CC_T310, l3dss1_t310},
1650 {SBIT(8),
1651 CC_T313, l3dss1_t313},
1652 {SBIT(11),
1653 CC_T305, l3dss1_t305},
1654 {SBIT(15),
1655 CC_T319, l3dss1_t319},
1656 {SBIT(17),
1657 CC_T318, l3dss1_t318},
1658 {SBIT(19),
1659 CC_T308_1, l3dss1_t308_1},
1660 {SBIT(19),
1661 CC_T308_2, l3dss1_t308_2},
1664 #define DOWNSLLEN \
1665 (sizeof(downstatelist) / sizeof(struct stateentry))
1667 static struct stateentry datastatelist[] =
1669 {ALL_STATES,
1670 MT_STATUS_ENQUIRY, l3dss1_status_enq},
1671 {ALL_STATES,
1672 MT_FACILITY, l3dss1_facility},
1673 {SBIT(19),
1674 MT_STATUS, l3dss1_release_ind},
1675 {ALL_STATES,
1676 MT_STATUS, l3dss1_status},
1677 {SBIT(0) | SBIT(6),
1678 MT_SETUP, l3dss1_setup},
1679 {SBIT(1) | SBIT(2),
1680 MT_CALL_PROCEEDING, l3dss1_call_proc},
1681 {SBIT(3) | SBIT(4) | SBIT(8) | SBIT(10) | SBIT(11) | SBIT(19),
1682 MT_CALL_PROCEEDING, l3dss1_status_req},
1683 {SBIT(1),
1684 MT_SETUP_ACKNOWLEDGE, l3dss1_setup_ack},
1685 {SBIT(2) | SBIT(3) | SBIT(4) | SBIT(8) | SBIT(10) | SBIT(11) | SBIT(19),
1686 MT_SETUP_ACKNOWLEDGE, l3dss1_status_req},
1687 {SBIT(1) | SBIT(2) | SBIT(3),
1688 MT_ALERTING, l3dss1_alerting},
1689 {SBIT(4) | SBIT(8) | SBIT(10) | SBIT(11) | SBIT(19),
1690 MT_ALERTING, l3dss1_status_req},
1691 {SBIT(0) | SBIT(1) | SBIT(2) | SBIT(3) | SBIT(4) | SBIT(7) | SBIT(8) | SBIT(10) |
1692 SBIT(11) | SBIT(12) | SBIT(15) | SBIT(17) | SBIT(19),
1693 MT_RELEASE_COMPLETE, l3dss1_release_cmpl},
1694 {SBIT(1) | SBIT(2) | SBIT(3) | SBIT(4) | SBIT(7) | SBIT(8) | SBIT(10) |
1695 SBIT(11) | SBIT(12) | SBIT(15) /* | SBIT(17) | SBIT(19)*/,
1696 MT_RELEASE, l3dss1_release},
1697 {SBIT(19), MT_RELEASE, l3dss1_release_ind},
1698 {SBIT(1) | SBIT(2) | SBIT(3) | SBIT(4) | SBIT(7) | SBIT(8) | SBIT(10) | SBIT(15),
1699 MT_DISCONNECT, l3dss1_disconnect},
1700 {SBIT(11),
1701 MT_DISCONNECT, l3dss1_release_req},
1702 {SBIT(1) | SBIT(2) | SBIT(3) | SBIT(4),
1703 MT_CONNECT, l3dss1_connect},
1704 {SBIT(8) | SBIT(10) | SBIT(11) | SBIT(19),
1705 MT_CONNECT, l3dss1_status_req},
1706 {SBIT(1) | SBIT(2) | SBIT(3) | SBIT(4) | SBIT(11) | SBIT(19),
1707 MT_CONNECT_ACKNOWLEDGE, l3dss1_status_req},
1708 {SBIT(8),
1709 MT_CONNECT_ACKNOWLEDGE, l3dss1_connect_ack},
1710 {SBIT(15),
1711 MT_SUSPEND_ACKNOWLEDGE, l3dss1_suspend_ack},
1712 {SBIT(15),
1713 MT_SUSPEND_REJECT, l3dss1_suspend_rej},
1714 {SBIT(17),
1715 MT_RESUME_ACKNOWLEDGE, l3dss1_resume_ack},
1716 {SBIT(17),
1717 MT_RESUME_REJECT, l3dss1_resume_rej},
1718 {SBIT(1) | SBIT(2) | SBIT(3) | SBIT(4) | SBIT(8) | SBIT(10) | SBIT(11) | SBIT(15) | SBIT(17) | SBIT(19),
1719 MT_INVALID, l3dss1_status_req},
1722 #define DATASLLEN \
1723 (sizeof(datastatelist) / sizeof(struct stateentry))
1725 static struct stateentry globalmes_list[] =
1727 {ALL_STATES,
1728 MT_STATUS, l3dss1_status},
1729 {SBIT(0),
1730 MT_RESTART, l3dss1_global_restart},
1731 /* {SBIT(1),
1732 MT_RESTART_ACKNOWLEDGE, l3dss1_restart_ack},
1735 #define GLOBALM_LEN \
1736 (sizeof(globalmes_list) / sizeof(struct stateentry))
1737 /* *INDENT-ON* */
1740 static void
1741 global_handler(struct PStack *st, int mt, struct sk_buff *skb)
1743 int i;
1744 struct l3_process *proc = st->l3.global;
1746 for (i = 0; i < GLOBALM_LEN; i++)
1747 if ((mt == globalmes_list[i].primitive) &&
1748 ((1 << proc->state) & globalmes_list[i].state))
1749 break;
1750 if (i == GLOBALM_LEN) {
1751 dev_kfree_skb(skb);
1752 if (st->l3.debug & L3_DEB_STATE) {
1753 l3_debug(st, "dss1 global state %d mt %x unhandled",
1754 proc->state, mt);
1756 return;
1757 } else {
1758 if (st->l3.debug & L3_DEB_STATE) {
1759 l3_debug(st, "dss1 global %d mt %x",
1760 proc->state, mt);
1762 globalmes_list[i].rout(proc, mt, skb);
1766 static void
1767 dss1up(struct PStack *st, int pr, void *arg)
1769 int i, mt, cr, cause, callState;
1770 char *ptr;
1771 struct sk_buff *skb = arg;
1772 struct l3_process *proc;
1774 switch (pr) {
1775 case (DL_DATA | INDICATION):
1776 case (DL_UNIT_DATA | INDICATION):
1777 break;
1778 case (DL_ESTABLISH | CONFIRM):
1779 case (DL_ESTABLISH | INDICATION):
1780 case (DL_RELEASE | INDICATION):
1781 case (DL_RELEASE | CONFIRM):
1782 l3_msg(st, pr, arg);
1783 return;
1784 break;
1786 if (skb->data[0] != PROTO_DIS_EURO) {
1787 if (st->l3.debug & L3_DEB_PROTERR) {
1788 l3_debug(st, "dss1up%sunexpected discriminator %x message len %d",
1789 (pr == (DL_DATA | INDICATION)) ? " " : "(broadcast) ",
1790 skb->data[0], skb->len);
1792 dev_kfree_skb(skb);
1793 return;
1795 cr = getcallref(skb->data);
1796 mt = skb->data[skb->data[1] + 2];
1797 if (!cr) { /* Global CallRef */
1798 global_handler(st, mt, skb);
1799 return;
1800 } else if (cr == -1) { /* Dummy Callref */
1801 dev_kfree_skb(skb);
1802 return;
1803 } else if (!(proc = getl3proc(st, cr))) {
1804 /* No transaction process exist, that means no call with
1805 * this callreference is active
1807 if (mt == MT_SETUP) {
1808 /* Setup creates a new transaction process */
1809 if (!(proc = new_l3_process(st, cr))) {
1810 /* May be to answer with RELEASE_COMPLETE and
1811 * CAUSE 0x2f "Resource unavailable", but this
1812 * need a new_l3_process too ... arghh
1814 dev_kfree_skb(skb);
1815 return;
1817 } else if (mt == MT_STATUS) {
1818 cause = 0;
1819 if ((ptr = findie(skb->data, skb->len, IE_CAUSE, 0)) != NULL) {
1820 ptr++;
1821 if (*ptr++ == 2)
1822 ptr++;
1823 cause = *ptr & 0x7f;
1825 callState = 0;
1826 if ((ptr = findie(skb->data, skb->len, IE_CALL_STATE, 0)) != NULL) {
1827 ptr++;
1828 if (*ptr++ == 2)
1829 ptr++;
1830 callState = *ptr;
1832 if (callState == 0) {
1833 /* ETS 300-104 part 2.4.1
1834 * if setup has not been made and a message type
1835 * MT_STATUS is received with call state == 0,
1836 * we must send nothing
1838 dev_kfree_skb(skb);
1839 return;
1840 } else {
1841 /* ETS 300-104 part 2.4.2
1842 * if setup has not been made and a message type
1843 * MT_STATUS is received with call state != 0,
1844 * we must send MT_RELEASE_COMPLETE cause 101
1846 dev_kfree_skb(skb);
1847 if ((proc = new_l3_process(st, cr))) {
1848 proc->para.cause = 0x65; /* 101 */
1849 l3dss1_msg_without_setup(proc, 0, NULL);
1851 return;
1853 } else if (mt == MT_RELEASE_COMPLETE) {
1854 dev_kfree_skb(skb);
1855 return;
1856 } else {
1857 /* ETS 300-104 part 2
1858 * if setup has not been made and a message type
1859 * (except MT_SETUP and RELEASE_COMPLETE) is received,
1860 * we must send MT_RELEASE_COMPLETE cause 81 */
1861 dev_kfree_skb(skb);
1862 if ((proc = new_l3_process(st, cr))) {
1863 proc->para.cause = 0x51; /* 81 */
1864 l3dss1_msg_without_setup(proc, 0, NULL);
1866 return;
1868 } else if (!l3dss1_check_messagetype_validity(mt)) {
1869 /* ETS 300-104 7.4.2, 8.4.2, 10.3.2, 11.4.2, 12.4.2, 13.4.2,
1870 * 14.4.2...
1871 * if setup has been made and invalid message type is received,
1872 * we must send MT_STATUS cause 0x62
1874 mt = MT_INVALID; /* sorry, not clean, but do the right thing ;-) */
1876 for (i = 0; i < DATASLLEN; i++)
1877 if ((mt == datastatelist[i].primitive) &&
1878 ((1 << proc->state) & datastatelist[i].state))
1879 break;
1880 if (i == DATASLLEN) {
1881 dev_kfree_skb(skb);
1882 if (st->l3.debug & L3_DEB_STATE) {
1883 l3_debug(st, "dss1up%sstate %d mt %x unhandled",
1884 (pr == (DL_DATA | INDICATION)) ? " " : "(broadcast) ",
1885 proc->state, mt);
1887 return;
1888 } else {
1889 if (st->l3.debug & L3_DEB_STATE) {
1890 l3_debug(st, "dss1up%sstate %d mt %x",
1891 (pr == (DL_DATA | INDICATION)) ? " " : "(broadcast) ",
1892 proc->state, mt);
1894 datastatelist[i].rout(proc, pr, skb);
1898 static void
1899 dss1down(struct PStack *st, int pr, void *arg)
1901 int i, cr;
1902 struct l3_process *proc;
1903 struct Channel *chan;
1905 if (((DL_ESTABLISH | REQUEST) == pr) || ((DL_RELEASE | REQUEST) == pr)) {
1906 l3_msg(st, pr, NULL);
1907 return;
1908 } else if (((CC_SETUP | REQUEST) == pr) || ((CC_RESUME | REQUEST) == pr)) {
1909 chan = arg;
1910 cr = newcallref();
1911 cr |= 0x80;
1912 if ((proc = new_l3_process(st, cr))) {
1913 proc->chan = chan;
1914 chan->proc = proc;
1915 proc->para.setup = chan->setup;
1916 proc->callref = cr;
1918 } else {
1919 proc = arg;
1921 if (!proc) {
1922 printk(KERN_ERR "HiSax dss1down without proc pr=%04x\n", pr);
1923 return;
1925 for (i = 0; i < DOWNSLLEN; i++)
1926 if ((pr == downstatelist[i].primitive) &&
1927 ((1 << proc->state) & downstatelist[i].state))
1928 break;
1929 if (i == DOWNSLLEN) {
1930 if (st->l3.debug & L3_DEB_STATE) {
1931 l3_debug(st, "dss1down state %d prim %d unhandled",
1932 proc->state, pr);
1934 } else {
1935 if (st->l3.debug & L3_DEB_STATE) {
1936 l3_debug(st, "dss1down state %d prim %d",
1937 proc->state, pr);
1939 downstatelist[i].rout(proc, pr, arg);
1943 void
1944 setstack_dss1(struct PStack *st)
1946 char tmp[64];
1948 st->lli.l4l3 = dss1down;
1949 st->l2.l2l3 = dss1up;
1950 st->l3.N303 = 1;
1951 if (!(st->l3.global = kmalloc(sizeof(struct l3_process), GFP_ATOMIC))) {
1952 printk(KERN_ERR "HiSax can't get memory for dss1 global CR\n");
1953 } else {
1954 st->l3.global->state = 0;
1955 st->l3.global->callref = 0;
1956 st->l3.global->next = NULL;
1957 st->l3.global->debug = L3_DEB_WARN;
1958 st->l3.global->st = st;
1959 st->l3.global->N303 = 1;
1960 L3InitTimer(st->l3.global, &st->l3.global->timer);
1962 strcpy(tmp, dss1_revision);
1963 printk(KERN_INFO "HiSax: DSS1 Rev. %s\n", HiSax_getrev(tmp));