Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
l3_1tr6.c
Go to the documentation of this file.
1 /* $Id: l3_1tr6.c,v 2.15.2.3 2004/01/13 14:31:25 keil Exp $
2  *
3  * German 1TR6 D-channel protocol
4  *
5  * Author Karsten Keil
6  * Copyright by Karsten Keil <[email protected]>
7  *
8  * This software may be used and distributed according to the terms
9  * of the GNU General Public License, incorporated herein by reference.
10  *
11  * For changes and modifications please read
12  * Documentation/isdn/HiSax.cert
13  *
14  */
15 
16 #include "hisax.h"
17 #include "l3_1tr6.h"
18 #include "isdnl3.h"
19 #include <linux/ctype.h>
20 
21 extern char *HiSax_getrev(const char *revision);
22 static const char *l3_1tr6_revision = "$Revision: 2.15.2.3 $";
23 
24 #define MsgHead(ptr, cref, mty, dis) \
25  *ptr++ = dis; \
26  *ptr++ = 0x1; \
27  *ptr++ = cref ^ 0x80; \
28  *ptr++ = mty
29 
30 static void
31 l3_1TR6_message(struct l3_process *pc, u_char mt, u_char pd)
32 {
33  struct sk_buff *skb;
34  u_char *p;
35 
36  if (!(skb = l3_alloc_skb(4)))
37  return;
38  p = skb_put(skb, 4);
39  MsgHead(p, pc->callref, mt, pd);
40  l3_msg(pc->st, DL_DATA | REQUEST, skb);
41 }
42 
43 static void
44 l3_1tr6_release_req(struct l3_process *pc, u_char pr, void *arg)
45 {
46  StopAllL3Timer(pc);
47  newl3state(pc, 19);
48  l3_1TR6_message(pc, MT_N1_REL, PROTO_DIS_N1);
49  L3AddTimer(&pc->timer, T308, CC_T308_1);
50 }
51 
52 static void
53 l3_1tr6_invalid(struct l3_process *pc, u_char pr, void *arg)
54 {
55  struct sk_buff *skb = arg;
56 
57  dev_kfree_skb(skb);
58  l3_1tr6_release_req(pc, 0, NULL);
59 }
60 
61 static void
62 l3_1tr6_error(struct l3_process *pc, u_char *msg, struct sk_buff *skb)
63 {
64  dev_kfree_skb(skb);
65  if (pc->st->l3.debug & L3_DEB_WARN)
66  l3_debug(pc->st, msg);
67  l3_1tr6_release_req(pc, 0, NULL);
68 }
69 
70 static void
71 l3_1tr6_setup_req(struct l3_process *pc, u_char pr, void *arg)
72 {
73  struct sk_buff *skb;
74  u_char tmp[128];
75  u_char *p = tmp;
76  u_char *teln;
77  u_char *eaz;
78  u_char channel = 0;
79  int l;
80 
81  MsgHead(p, pc->callref, MT_N1_SETUP, PROTO_DIS_N1);
82  teln = pc->para.setup.phone;
83  pc->para.spv = 0;
84  if (!isdigit(*teln)) {
85  switch (0x5f & *teln) {
86  case 'S':
87  pc->para.spv = 1;
88  break;
89  case 'C':
90  channel = 0x08;
91  case 'P':
92  channel |= 0x80;
93  teln++;
94  if (*teln == '1')
95  channel |= 0x01;
96  else
97  channel |= 0x02;
98  break;
99  default:
100  if (pc->st->l3.debug & L3_DEB_WARN)
101  l3_debug(pc->st, "Wrong MSN Code");
102  break;
103  }
104  teln++;
105  }
106  if (channel) {
107  *p++ = 0x18; /* channel indicator */
108  *p++ = 1;
109  *p++ = channel;
110  }
111  if (pc->para.spv) { /* SPV ? */
112  /* NSF SPV */
113  *p++ = WE0_netSpecFac;
114  *p++ = 4; /* Laenge */
115  *p++ = 0;
116  *p++ = FAC_SPV; /* SPV */
117  *p++ = pc->para.setup.si1; /* 0 for all Services */
118  *p++ = pc->para.setup.si2; /* 0 for all Services */
119  *p++ = WE0_netSpecFac;
120  *p++ = 4; /* Laenge */
121  *p++ = 0;
122  *p++ = FAC_Activate; /* aktiviere SPV (default) */
123  *p++ = pc->para.setup.si1; /* 0 for all Services */
124  *p++ = pc->para.setup.si2; /* 0 for all Services */
125  }
126  eaz = pc->para.setup.eazmsn;
127  if (*eaz) {
128  *p++ = WE0_origAddr;
129  *p++ = strlen(eaz) + 1;
130  /* Classify as AnyPref. */
131  *p++ = 0x81; /* Ext = '1'B, Type = '000'B, Plan = '0001'B. */
132  while (*eaz)
133  *p++ = *eaz++ & 0x7f;
134  }
135  *p++ = WE0_destAddr;
136  *p++ = strlen(teln) + 1;
137  /* Classify as AnyPref. */
138  *p++ = 0x81; /* Ext = '1'B, Type = '000'B, Plan = '0001'B. */
139  while (*teln)
140  *p++ = *teln++ & 0x7f;
141 
142  *p++ = WE_Shift_F6;
143  /* Codesatz 6 fuer Service */
144  *p++ = WE6_serviceInd;
145  *p++ = 2; /* len=2 info,info2 */
146  *p++ = pc->para.setup.si1;
147  *p++ = pc->para.setup.si2;
148 
149  l = p - tmp;
150  if (!(skb = l3_alloc_skb(l)))
151  return;
152  memcpy(skb_put(skb, l), tmp, l);
153  L3DelTimer(&pc->timer);
154  L3AddTimer(&pc->timer, T303, CC_T303);
155  newl3state(pc, 1);
156  l3_msg(pc->st, DL_DATA | REQUEST, skb);
157 }
158 
159 static void
160 l3_1tr6_setup(struct l3_process *pc, u_char pr, void *arg)
161 {
162  u_char *p;
163  int bcfound = 0;
164  char tmp[80];
165  struct sk_buff *skb = arg;
166 
167  /* Channel Identification */
168  p = findie(skb->data, skb->len, WE0_chanID, 0);
169  if (p) {
170  if (p[1] != 1) {
171  l3_1tr6_error(pc, "setup wrong chanID len", skb);
172  return;
173  }
174  if ((p[2] & 0xf4) != 0x80) {
175  l3_1tr6_error(pc, "setup wrong WE0_chanID", skb);
176  return;
177  }
178  if ((pc->para.bchannel = p[2] & 0x3))
179  bcfound++;
180  } else {
181  l3_1tr6_error(pc, "missing setup chanID", skb);
182  return;
183  }
184 
185  p = skb->data;
186  if ((p = findie(p, skb->len, WE6_serviceInd, 6))) {
187  pc->para.setup.si1 = p[2];
188  pc->para.setup.si2 = p[3];
189  } else {
190  l3_1tr6_error(pc, "missing setup SI", skb);
191  return;
192  }
193 
194  p = skb->data;
195  if ((p = findie(p, skb->len, WE0_destAddr, 0)))
196  iecpy(pc->para.setup.eazmsn, p, 1);
197  else
198  pc->para.setup.eazmsn[0] = 0;
199 
200  p = skb->data;
201  if ((p = findie(p, skb->len, WE0_origAddr, 0))) {
202  iecpy(pc->para.setup.phone, p, 1);
203  } else
204  pc->para.setup.phone[0] = 0;
205 
206  p = skb->data;
207  pc->para.spv = 0;
208  if ((p = findie(p, skb->len, WE0_netSpecFac, 0))) {
209  if ((FAC_SPV == p[3]) || (FAC_Activate == p[3]))
210  pc->para.spv = 1;
211  }
212  dev_kfree_skb(skb);
213 
214  /* Signal all services, linklevel takes care of Service-Indicator */
215  if (bcfound) {
216  if ((pc->para.setup.si1 != 7) && (pc->st->l3.debug & L3_DEB_WARN)) {
217  sprintf(tmp, "non-digital call: %s -> %s",
218  pc->para.setup.phone,
219  pc->para.setup.eazmsn);
220  l3_debug(pc->st, tmp);
221  }
222  newl3state(pc, 6);
223  pc->st->l3.l3l4(pc->st, CC_SETUP | INDICATION, pc);
224  } else
225  release_l3_process(pc);
226 }
227 
228 static void
229 l3_1tr6_setup_ack(struct l3_process *pc, u_char pr, void *arg)
230 {
231  u_char *p;
232  struct sk_buff *skb = arg;
233 
234  L3DelTimer(&pc->timer);
235  p = skb->data;
236  newl3state(pc, 2);
237  if ((p = findie(p, skb->len, WE0_chanID, 0))) {
238  if (p[1] != 1) {
239  l3_1tr6_error(pc, "setup_ack wrong chanID len", skb);
240  return;
241  }
242  if ((p[2] & 0xf4) != 0x80) {
243  l3_1tr6_error(pc, "setup_ack wrong WE0_chanID", skb);
244  return;
245  }
246  pc->para.bchannel = p[2] & 0x3;
247  } else {
248  l3_1tr6_error(pc, "missing setup_ack WE0_chanID", skb);
249  return;
250  }
251  dev_kfree_skb(skb);
252  L3AddTimer(&pc->timer, T304, CC_T304);
253  pc->st->l3.l3l4(pc->st, CC_MORE_INFO | INDICATION, pc);
254 }
255 
256 static void
257 l3_1tr6_call_sent(struct l3_process *pc, u_char pr, void *arg)
258 {
259  u_char *p;
260  struct sk_buff *skb = arg;
261 
262  L3DelTimer(&pc->timer);
263  p = skb->data;
264  if ((p = findie(p, skb->len, WE0_chanID, 0))) {
265  if (p[1] != 1) {
266  l3_1tr6_error(pc, "call sent wrong chanID len", skb);
267  return;
268  }
269  if ((p[2] & 0xf4) != 0x80) {
270  l3_1tr6_error(pc, "call sent wrong WE0_chanID", skb);
271  return;
272  }
273  if ((pc->state == 2) && (pc->para.bchannel != (p[2] & 0x3))) {
274  l3_1tr6_error(pc, "call sent wrong chanID value", skb);
275  return;
276  }
277  pc->para.bchannel = p[2] & 0x3;
278  } else {
279  l3_1tr6_error(pc, "missing call sent WE0_chanID", skb);
280  return;
281  }
282  dev_kfree_skb(skb);
283  L3AddTimer(&pc->timer, T310, CC_T310);
284  newl3state(pc, 3);
285  pc->st->l3.l3l4(pc->st, CC_PROCEEDING | INDICATION, pc);
286 }
287 
288 static void
289 l3_1tr6_alert(struct l3_process *pc, u_char pr, void *arg)
290 {
291  struct sk_buff *skb = arg;
292 
293  dev_kfree_skb(skb);
294  L3DelTimer(&pc->timer); /* T304 */
295  newl3state(pc, 4);
296  pc->st->l3.l3l4(pc->st, CC_ALERTING | INDICATION, pc);
297 }
298 
299 static void
300 l3_1tr6_info(struct l3_process *pc, u_char pr, void *arg)
301 {
302  u_char *p;
303  int i, tmpcharge = 0;
304  char a_charge[8], tmp[32];
305  struct sk_buff *skb = arg;
306 
307  p = skb->data;
308  if ((p = findie(p, skb->len, WE6_chargingInfo, 6))) {
309  iecpy(a_charge, p, 1);
310  for (i = 0; i < strlen(a_charge); i++) {
311  tmpcharge *= 10;
312  tmpcharge += a_charge[i] & 0xf;
313  }
314  if (tmpcharge > pc->para.chargeinfo) {
315  pc->para.chargeinfo = tmpcharge;
316  pc->st->l3.l3l4(pc->st, CC_CHARGE | INDICATION, pc);
317  }
318  if (pc->st->l3.debug & L3_DEB_CHARGE) {
319  sprintf(tmp, "charging info %d", pc->para.chargeinfo);
320  l3_debug(pc->st, tmp);
321  }
322  } else if (pc->st->l3.debug & L3_DEB_CHARGE)
323  l3_debug(pc->st, "charging info not found");
324  dev_kfree_skb(skb);
325 
326 }
327 
328 static void
329 l3_1tr6_info_s2(struct l3_process *pc, u_char pr, void *arg)
330 {
331  struct sk_buff *skb = arg;
332 
333  dev_kfree_skb(skb);
334 }
335 
336 static void
337 l3_1tr6_connect(struct l3_process *pc, u_char pr, void *arg)
338 {
339  struct sk_buff *skb = arg;
340 
341  L3DelTimer(&pc->timer); /* T310 */
342  if (!findie(skb->data, skb->len, WE6_date, 6)) {
343  l3_1tr6_error(pc, "missing connect date", skb);
344  return;
345  }
346  newl3state(pc, 10);
347  dev_kfree_skb(skb);
348  pc->para.chargeinfo = 0;
349  pc->st->l3.l3l4(pc->st, CC_SETUP | CONFIRM, pc);
350 }
351 
352 static void
353 l3_1tr6_rel(struct l3_process *pc, u_char pr, void *arg)
354 {
355  struct sk_buff *skb = arg;
356  u_char *p;
357 
358  p = skb->data;
359  if ((p = findie(p, skb->len, WE0_cause, 0))) {
360  if (p[1] > 0) {
361  pc->para.cause = p[2];
362  if (p[1] > 1)
363  pc->para.loc = p[3];
364  else
365  pc->para.loc = 0;
366  } else {
367  pc->para.cause = 0;
368  pc->para.loc = 0;
369  }
370  } else {
371  pc->para.cause = NO_CAUSE;
372  l3_1tr6_error(pc, "missing REL cause", skb);
373  return;
374  }
375  dev_kfree_skb(skb);
376  StopAllL3Timer(pc);
377  newl3state(pc, 0);
378  l3_1TR6_message(pc, MT_N1_REL_ACK, PROTO_DIS_N1);
379  pc->st->l3.l3l4(pc->st, CC_RELEASE | INDICATION, pc);
380  release_l3_process(pc);
381 }
382 
383 static void
384 l3_1tr6_rel_ack(struct l3_process *pc, u_char pr, void *arg)
385 {
386  struct sk_buff *skb = arg;
387 
388  dev_kfree_skb(skb);
389  StopAllL3Timer(pc);
390  newl3state(pc, 0);
391  pc->para.cause = NO_CAUSE;
392  pc->st->l3.l3l4(pc->st, CC_RELEASE | CONFIRM, pc);
393  release_l3_process(pc);
394 }
395 
396 static void
397 l3_1tr6_disc(struct l3_process *pc, u_char pr, void *arg)
398 {
399  struct sk_buff *skb = arg;
400  u_char *p;
401  int i, tmpcharge = 0;
402  char a_charge[8], tmp[32];
403 
404  StopAllL3Timer(pc);
405  p = skb->data;
406  if ((p = findie(p, skb->len, WE6_chargingInfo, 6))) {
407  iecpy(a_charge, p, 1);
408  for (i = 0; i < strlen(a_charge); i++) {
409  tmpcharge *= 10;
410  tmpcharge += a_charge[i] & 0xf;
411  }
412  if (tmpcharge > pc->para.chargeinfo) {
413  pc->para.chargeinfo = tmpcharge;
414  pc->st->l3.l3l4(pc->st, CC_CHARGE | INDICATION, pc);
415  }
416  if (pc->st->l3.debug & L3_DEB_CHARGE) {
417  sprintf(tmp, "charging info %d", pc->para.chargeinfo);
418  l3_debug(pc->st, tmp);
419  }
420  } else if (pc->st->l3.debug & L3_DEB_CHARGE)
421  l3_debug(pc->st, "charging info not found");
422 
423 
424  p = skb->data;
425  if ((p = findie(p, skb->len, WE0_cause, 0))) {
426  if (p[1] > 0) {
427  pc->para.cause = p[2];
428  if (p[1] > 1)
429  pc->para.loc = p[3];
430  else
431  pc->para.loc = 0;
432  } else {
433  pc->para.cause = 0;
434  pc->para.loc = 0;
435  }
436  } else {
437  if (pc->st->l3.debug & L3_DEB_WARN)
438  l3_debug(pc->st, "cause not found");
439  pc->para.cause = NO_CAUSE;
440  }
441  if (!findie(skb->data, skb->len, WE6_date, 6)) {
442  l3_1tr6_error(pc, "missing connack date", skb);
443  return;
444  }
445  dev_kfree_skb(skb);
446  newl3state(pc, 12);
447  pc->st->l3.l3l4(pc->st, CC_DISCONNECT | INDICATION, pc);
448 }
449 
450 
451 static void
452 l3_1tr6_connect_ack(struct l3_process *pc, u_char pr, void *arg)
453 {
454  struct sk_buff *skb = arg;
455 
456  if (!findie(skb->data, skb->len, WE6_date, 6)) {
457  l3_1tr6_error(pc, "missing connack date", skb);
458  return;
459  }
460  dev_kfree_skb(skb);
461  newl3state(pc, 10);
462  pc->para.chargeinfo = 0;
463  L3DelTimer(&pc->timer);
464  pc->st->l3.l3l4(pc->st, CC_SETUP_COMPL | INDICATION, pc);
465 }
466 
467 static void
468 l3_1tr6_alert_req(struct l3_process *pc, u_char pr, void *arg)
469 {
470  newl3state(pc, 7);
471  l3_1TR6_message(pc, MT_N1_ALERT, PROTO_DIS_N1);
472 }
473 
474 static void
475 l3_1tr6_setup_rsp(struct l3_process *pc, u_char pr, void *arg)
476 {
477  struct sk_buff *skb;
478  u_char tmp[24];
479  u_char *p = tmp;
480  int l;
481 
482  MsgHead(p, pc->callref, MT_N1_CONN, PROTO_DIS_N1);
483  if (pc->para.spv) { /* SPV ? */
484  /* NSF SPV */
485  *p++ = WE0_netSpecFac;
486  *p++ = 4; /* Laenge */
487  *p++ = 0;
488  *p++ = FAC_SPV; /* SPV */
489  *p++ = pc->para.setup.si1;
490  *p++ = pc->para.setup.si2;
491  *p++ = WE0_netSpecFac;
492  *p++ = 4; /* Laenge */
493  *p++ = 0;
494  *p++ = FAC_Activate; /* aktiviere SPV */
495  *p++ = pc->para.setup.si1;
496  *p++ = pc->para.setup.si2;
497  }
498  newl3state(pc, 8);
499  l = p - tmp;
500  if (!(skb = l3_alloc_skb(l)))
501  return;
502  memcpy(skb_put(skb, l), tmp, l);
503  l3_msg(pc->st, DL_DATA | REQUEST, skb);
504  L3DelTimer(&pc->timer);
505  L3AddTimer(&pc->timer, T313, CC_T313);
506 }
507 
508 static void
509 l3_1tr6_reset(struct l3_process *pc, u_char pr, void *arg)
510 {
511  release_l3_process(pc);
512 }
513 
514 static void
515 l3_1tr6_disconnect_req(struct l3_process *pc, u_char pr, void *arg)
516 {
517  struct sk_buff *skb;
518  u_char tmp[16];
519  u_char *p = tmp;
520  int l;
521  u_char cause = 0x10;
522  u_char clen = 1;
523 
524  if (pc->para.cause > 0)
525  cause = pc->para.cause;
526  /* Map DSS1 causes */
527  switch (cause & 0x7f) {
528  case 0x10:
529  clen = 0;
530  break;
531  case 0x11:
532  cause = CAUSE_UserBusy;
533  break;
534  case 0x15:
535  cause = CAUSE_CallRejected;
536  break;
537  }
538  StopAllL3Timer(pc);
539  MsgHead(p, pc->callref, MT_N1_DISC, PROTO_DIS_N1);
540  *p++ = WE0_cause;
541  *p++ = clen; /* Laenge */
542  if (clen)
543  *p++ = cause | 0x80;
544  newl3state(pc, 11);
545  l = p - tmp;
546  if (!(skb = l3_alloc_skb(l)))
547  return;
548  memcpy(skb_put(skb, l), tmp, l);
549  l3_msg(pc->st, DL_DATA | REQUEST, skb);
550  L3AddTimer(&pc->timer, T305, CC_T305);
551 }
552 
553 static void
554 l3_1tr6_t303(struct l3_process *pc, u_char pr, void *arg)
555 {
556  if (pc->N303 > 0) {
557  pc->N303--;
558  L3DelTimer(&pc->timer);
559  l3_1tr6_setup_req(pc, pr, arg);
560  } else {
561  L3DelTimer(&pc->timer);
562  pc->para.cause = 0;
563  l3_1tr6_disconnect_req(pc, 0, NULL);
564  }
565 }
566 
567 static void
568 l3_1tr6_t304(struct l3_process *pc, u_char pr, void *arg)
569 {
570  L3DelTimer(&pc->timer);
571  pc->para.cause = 0xE6;
572  l3_1tr6_disconnect_req(pc, pr, NULL);
573  pc->st->l3.l3l4(pc->st, CC_SETUP_ERR, pc);
574 }
575 
576 static void
577 l3_1tr6_t305(struct l3_process *pc, u_char pr, void *arg)
578 {
579  struct sk_buff *skb;
580  u_char tmp[16];
581  u_char *p = tmp;
582  int l;
583  u_char cause = 0x90;
584  u_char clen = 1;
585 
586  L3DelTimer(&pc->timer);
587  if (pc->para.cause != NO_CAUSE)
588  cause = pc->para.cause;
589  /* Map DSS1 causes */
590  switch (cause & 0x7f) {
591  case 0x10:
592  clen = 0;
593  break;
594  case 0x15:
595  cause = CAUSE_CallRejected;
596  break;
597  }
598  MsgHead(p, pc->callref, MT_N1_REL, PROTO_DIS_N1);
599  *p++ = WE0_cause;
600  *p++ = clen; /* Laenge */
601  if (clen)
602  *p++ = cause;
603  newl3state(pc, 19);
604  l = p - tmp;
605  if (!(skb = l3_alloc_skb(l)))
606  return;
607  memcpy(skb_put(skb, l), tmp, l);
608  l3_msg(pc->st, DL_DATA | REQUEST, skb);
609  L3AddTimer(&pc->timer, T308, CC_T308_1);
610 }
611 
612 static void
613 l3_1tr6_t310(struct l3_process *pc, u_char pr, void *arg)
614 {
615  L3DelTimer(&pc->timer);
616  pc->para.cause = 0xE6;
617  l3_1tr6_disconnect_req(pc, pr, NULL);
618  pc->st->l3.l3l4(pc->st, CC_SETUP_ERR, pc);
619 }
620 
621 static void
622 l3_1tr6_t313(struct l3_process *pc, u_char pr, void *arg)
623 {
624  L3DelTimer(&pc->timer);
625  pc->para.cause = 0xE6;
626  l3_1tr6_disconnect_req(pc, pr, NULL);
627  pc->st->l3.l3l4(pc->st, CC_CONNECT_ERR, pc);
628 }
629 
630 static void
631 l3_1tr6_t308_1(struct l3_process *pc, u_char pr, void *arg)
632 {
633  L3DelTimer(&pc->timer);
634  l3_1TR6_message(pc, MT_N1_REL, PROTO_DIS_N1);
635  L3AddTimer(&pc->timer, T308, CC_T308_2);
636  newl3state(pc, 19);
637 }
638 
639 static void
640 l3_1tr6_t308_2(struct l3_process *pc, u_char pr, void *arg)
641 {
642  L3DelTimer(&pc->timer);
643  pc->st->l3.l3l4(pc->st, CC_RELEASE_ERR, pc);
644  release_l3_process(pc);
645 }
646 
647 static void
648 l3_1tr6_dl_reset(struct l3_process *pc, u_char pr, void *arg)
649 {
650  pc->para.cause = CAUSE_LocalProcErr;
651  l3_1tr6_disconnect_req(pc, pr, NULL);
652  pc->st->l3.l3l4(pc->st, CC_SETUP_ERR, pc);
653 }
654 
655 static void
656 l3_1tr6_dl_release(struct l3_process *pc, u_char pr, void *arg)
657 {
658  newl3state(pc, 0);
659  pc->para.cause = 0x1b; /* Destination out of order */
660  pc->para.loc = 0;
661  pc->st->l3.l3l4(pc->st, CC_RELEASE | INDICATION, pc);
662  release_l3_process(pc);
663 }
664 
665 /* *INDENT-OFF* */
666 static struct stateentry downstl[] =
667 {
668  {SBIT(0),
669  CC_SETUP | REQUEST, l3_1tr6_setup_req},
670  {SBIT(1) | SBIT(2) | SBIT(3) | SBIT(4) | SBIT(6) | SBIT(7) | SBIT(8) |
671  SBIT(10),
672  CC_DISCONNECT | REQUEST, l3_1tr6_disconnect_req},
673  {SBIT(12),
674  CC_RELEASE | REQUEST, l3_1tr6_release_req},
675  {SBIT(6),
676  CC_IGNORE | REQUEST, l3_1tr6_reset},
677  {SBIT(6),
678  CC_REJECT | REQUEST, l3_1tr6_disconnect_req},
679  {SBIT(6),
680  CC_ALERTING | REQUEST, l3_1tr6_alert_req},
681  {SBIT(6) | SBIT(7),
682  CC_SETUP | RESPONSE, l3_1tr6_setup_rsp},
683  {SBIT(1),
684  CC_T303, l3_1tr6_t303},
685  {SBIT(2),
686  CC_T304, l3_1tr6_t304},
687  {SBIT(3),
688  CC_T310, l3_1tr6_t310},
689  {SBIT(8),
690  CC_T313, l3_1tr6_t313},
691  {SBIT(11),
692  CC_T305, l3_1tr6_t305},
693  {SBIT(19),
694  CC_T308_1, l3_1tr6_t308_1},
695  {SBIT(19),
696  CC_T308_2, l3_1tr6_t308_2},
697 };
698 
699 static struct stateentry datastln1[] =
700 {
701  {SBIT(0),
702  MT_N1_INVALID, l3_1tr6_invalid},
703  {SBIT(0),
704  MT_N1_SETUP, l3_1tr6_setup},
705  {SBIT(1),
706  MT_N1_SETUP_ACK, l3_1tr6_setup_ack},
707  {SBIT(1) | SBIT(2),
708  MT_N1_CALL_SENT, l3_1tr6_call_sent},
709  {SBIT(1) | SBIT(2) | SBIT(3) | SBIT(4) | SBIT(7) | SBIT(8) | SBIT(10),
710  MT_N1_DISC, l3_1tr6_disc},
711  {SBIT(2) | SBIT(3) | SBIT(4),
712  MT_N1_ALERT, l3_1tr6_alert},
713  {SBIT(2) | SBIT(3) | SBIT(4),
714  MT_N1_CONN, l3_1tr6_connect},
715  {SBIT(2),
716  MT_N1_INFO, l3_1tr6_info_s2},
717  {SBIT(8),
718  MT_N1_CONN_ACK, l3_1tr6_connect_ack},
719  {SBIT(10),
720  MT_N1_INFO, l3_1tr6_info},
721  {SBIT(0) | SBIT(1) | SBIT(2) | SBIT(3) | SBIT(4) | SBIT(7) | SBIT(8) |
722  SBIT(10) | SBIT(11) | SBIT(12) | SBIT(15) | SBIT(17),
723  MT_N1_REL, l3_1tr6_rel},
724  {SBIT(19),
725  MT_N1_REL, l3_1tr6_rel_ack},
726  {SBIT(0) | SBIT(1) | SBIT(2) | SBIT(3) | SBIT(4) | SBIT(7) | SBIT(8) |
727  SBIT(10) | SBIT(11) | SBIT(12) | SBIT(15) | SBIT(17),
728  MT_N1_REL_ACK, l3_1tr6_invalid},
729  {SBIT(19),
730  MT_N1_REL_ACK, l3_1tr6_rel_ack}
731 };
732 
733 static struct stateentry manstatelist[] =
734 {
735  {SBIT(2),
736  DL_ESTABLISH | INDICATION, l3_1tr6_dl_reset},
737  {ALL_STATES,
738  DL_RELEASE | INDICATION, l3_1tr6_dl_release},
739 };
740 
741 /* *INDENT-ON* */
742 
743 static void
744 up1tr6(struct PStack *st, int pr, void *arg)
745 {
746  int i, mt, cr;
747  struct l3_process *proc;
748  struct sk_buff *skb = arg;
749  char tmp[80];
750 
751  switch (pr) {
752  case (DL_DATA | INDICATION):
753  case (DL_UNIT_DATA | INDICATION):
754  break;
755  case (DL_ESTABLISH | CONFIRM):
756  case (DL_ESTABLISH | INDICATION):
757  case (DL_RELEASE | INDICATION):
758  case (DL_RELEASE | CONFIRM):
759  l3_msg(st, pr, arg);
760  return;
761  break;
762  }
763  if (skb->len < 4) {
764  if (st->l3.debug & L3_DEB_PROTERR) {
765  sprintf(tmp, "up1tr6 len only %d", skb->len);
766  l3_debug(st, tmp);
767  }
768  dev_kfree_skb(skb);
769  return;
770  }
771  if ((skb->data[0] & 0xfe) != PROTO_DIS_N0) {
772  if (st->l3.debug & L3_DEB_PROTERR) {
773  sprintf(tmp, "up1tr6%sunexpected discriminator %x message len %d",
774  (pr == (DL_DATA | INDICATION)) ? " " : "(broadcast) ",
775  skb->data[0], skb->len);
776  l3_debug(st, tmp);
777  }
778  dev_kfree_skb(skb);
779  return;
780  }
781  if (skb->data[1] != 1) {
782  if (st->l3.debug & L3_DEB_PROTERR) {
783  sprintf(tmp, "up1tr6 CR len not 1");
784  l3_debug(st, tmp);
785  }
786  dev_kfree_skb(skb);
787  return;
788  }
789  cr = skb->data[2];
790  mt = skb->data[3];
791  if (skb->data[0] == PROTO_DIS_N0) {
792  dev_kfree_skb(skb);
793  if (st->l3.debug & L3_DEB_STATE) {
794  sprintf(tmp, "up1tr6%s N0 mt %x unhandled",
795  (pr == (DL_DATA | INDICATION)) ? " " : "(broadcast) ", mt);
796  l3_debug(st, tmp);
797  }
798  } else if (skb->data[0] == PROTO_DIS_N1) {
799  if (!(proc = getl3proc(st, cr))) {
800  if (mt == MT_N1_SETUP) {
801  if (cr < 128) {
802  if (!(proc = new_l3_process(st, cr))) {
803  if (st->l3.debug & L3_DEB_PROTERR) {
804  sprintf(tmp, "up1tr6 no roc mem");
805  l3_debug(st, tmp);
806  }
807  dev_kfree_skb(skb);
808  return;
809  }
810  } else {
811  dev_kfree_skb(skb);
812  return;
813  }
814  } else if ((mt == MT_N1_REL) || (mt == MT_N1_REL_ACK) ||
815  (mt == MT_N1_CANC_ACK) || (mt == MT_N1_CANC_REJ) ||
816  (mt == MT_N1_REG_ACK) || (mt == MT_N1_REG_REJ) ||
817  (mt == MT_N1_SUSP_ACK) || (mt == MT_N1_RES_REJ) ||
818  (mt == MT_N1_INFO)) {
819  dev_kfree_skb(skb);
820  return;
821  } else {
822  if (!(proc = new_l3_process(st, cr))) {
823  if (st->l3.debug & L3_DEB_PROTERR) {
824  sprintf(tmp, "up1tr6 no roc mem");
825  l3_debug(st, tmp);
826  }
827  dev_kfree_skb(skb);
828  return;
829  }
830  mt = MT_N1_INVALID;
831  }
832  }
833  for (i = 0; i < ARRAY_SIZE(datastln1); i++)
834  if ((mt == datastln1[i].primitive) &&
835  ((1 << proc->state) & datastln1[i].state))
836  break;
837  if (i == ARRAY_SIZE(datastln1)) {
838  dev_kfree_skb(skb);
839  if (st->l3.debug & L3_DEB_STATE) {
840  sprintf(tmp, "up1tr6%sstate %d mt %x unhandled",
841  (pr == (DL_DATA | INDICATION)) ? " " : "(broadcast) ",
842  proc->state, mt);
843  l3_debug(st, tmp);
844  }
845  return;
846  } else {
847  if (st->l3.debug & L3_DEB_STATE) {
848  sprintf(tmp, "up1tr6%sstate %d mt %x",
849  (pr == (DL_DATA | INDICATION)) ? " " : "(broadcast) ",
850  proc->state, mt);
851  l3_debug(st, tmp);
852  }
853  datastln1[i].rout(proc, pr, skb);
854  }
855  }
856 }
857 
858 static void
859 down1tr6(struct PStack *st, int pr, void *arg)
860 {
861  int i, cr;
862  struct l3_process *proc;
863  struct Channel *chan;
864  char tmp[80];
865 
866  if ((DL_ESTABLISH | REQUEST) == pr) {
867  l3_msg(st, pr, NULL);
868  return;
869  } else if ((CC_SETUP | REQUEST) == pr) {
870  chan = arg;
871  cr = newcallref();
872  cr |= 0x80;
873  if (!(proc = new_l3_process(st, cr))) {
874  return;
875  } else {
876  proc->chan = chan;
877  chan->proc = proc;
878  memcpy(&proc->para.setup, &chan->setup, sizeof(setup_parm));
879  proc->callref = cr;
880  }
881  } else {
882  proc = arg;
883  }
884 
885  for (i = 0; i < ARRAY_SIZE(downstl); i++)
886  if ((pr == downstl[i].primitive) &&
887  ((1 << proc->state) & downstl[i].state))
888  break;
889  if (i == ARRAY_SIZE(downstl)) {
890  if (st->l3.debug & L3_DEB_STATE) {
891  sprintf(tmp, "down1tr6 state %d prim %d unhandled",
892  proc->state, pr);
893  l3_debug(st, tmp);
894  }
895  } else {
896  if (st->l3.debug & L3_DEB_STATE) {
897  sprintf(tmp, "down1tr6 state %d prim %d",
898  proc->state, pr);
899  l3_debug(st, tmp);
900  }
901  downstl[i].rout(proc, pr, arg);
902  }
903 }
904 
905 static void
906 man1tr6(struct PStack *st, int pr, void *arg)
907 {
908  int i;
909  struct l3_process *proc = arg;
910 
911  if (!proc) {
912  printk(KERN_ERR "HiSax man1tr6 without proc pr=%04x\n", pr);
913  return;
914  }
915  for (i = 0; i < ARRAY_SIZE(manstatelist); i++)
916  if ((pr == manstatelist[i].primitive) &&
917  ((1 << proc->state) & manstatelist[i].state))
918  break;
919  if (i == ARRAY_SIZE(manstatelist)) {
920  if (st->l3.debug & L3_DEB_STATE) {
921  l3_debug(st, "cr %d man1tr6 state %d prim %d unhandled",
922  proc->callref & 0x7f, proc->state, pr);
923  }
924  } else {
925  if (st->l3.debug & L3_DEB_STATE) {
926  l3_debug(st, "cr %d man1tr6 state %d prim %d",
927  proc->callref & 0x7f, proc->state, pr);
928  }
929  manstatelist[i].rout(proc, pr, arg);
930  }
931 }
932 
933 void
934 setstack_1tr6(struct PStack *st)
935 {
936  char tmp[64];
937 
938  st->lli.l4l3 = down1tr6;
939  st->l2.l2l3 = up1tr6;
940  st->l3.l3ml3 = man1tr6;
941  st->l3.N303 = 0;
942 
943  strcpy(tmp, l3_1tr6_revision);
944  printk(KERN_INFO "HiSax: 1TR6 Rev. %s\n", HiSax_getrev(tmp));
945 }