1 /* $Id: tei.c,v 2.13 1999/07/21 14:46:28 keil Exp $
3 * Author Karsten Keil (keil@isdn4linux.de)
4 * based on the teles driver from Jan den Ouden
6 * This file is (c) under GNU PUBLIC LICENSE
7 * For changes and modifications please read
8 * ../../../Documentation/isdn/HiSax.cert
10 * Thanks to Jan den Ouden
14 * Revision 2.13 1999/07/21 14:46:28 keil
15 * changes from EICON certification
17 * Revision 2.12 1999/07/01 08:12:11 keil
18 * Common HiSax version for 2.0, 2.1, 2.2 and 2.3 kernel
20 * Revision 2.11 1998/11/15 23:55:24 keil
23 * Revision 2.10 1998/05/25 14:08:10 keil
25 * fixed X.75 and leased line to work again
26 * Point2Point and fixed TEI are runtime options now:
27 * hisaxctrl <id> 7 1 set PTP
28 * hisaxctrl <id> 8 <TEIVALUE *2 >
29 * set fixed TEI to TEIVALUE (0-63)
31 * Revision 2.9 1998/05/25 12:58:23 keil
32 * HiSax golden code from certification, Don't use !!!
33 * No leased lines, no X75, but many changes.
35 * Revision 2.8 1998/03/07 22:57:07 tsbogend
36 * made HiSax working on Linux/Alpha
38 * Revision 2.7 1998/02/12 23:08:11 keil
39 * change for 2.1.86 (removing FREE_READ/FREE_WRITE from [dev]_kfree_skb()
41 * Revision 2.6 1998/02/02 13:41:42 keil
42 * fix MDL_ASSIGN for PtP
44 * Revision 2.5 1997/11/06 17:09:12 keil
47 * Revision 2.4 1997/10/29 19:04:46 keil
50 * Revision 2.3 1997/10/01 09:21:43 fritz
51 * Removed old compatibility stuff for 2.0.X kernels.
52 * From now on, this code is for 2.1.X ONLY!
53 * Old stuff is still in the separate branch.
55 * Revision 2.2 1997/07/31 19:24:39 keil
58 * Revision 2.1 1997/07/31 11:50:16 keil
59 * ONE TEI and FIXED TEI handling
61 * Revision 2.0 1997/07/27 21:13:30 keil
64 * Revision 1.9 1997/06/26 11:18:02 keil
67 * Revision 1.8 1997/04/07 22:59:08 keil
68 * GFP_KERNEL --> GFP_ATOMIC
70 * Revision 1.7 1997/04/06 22:54:03 keil
73 * Old log removed/ KKe
76 #define __NO_VERSION__
79 #include <linux/random.h>
81 const char *tei_revision
= "$Revision: 2.13 $";
91 #define TEI_ENTITY_ID 0xf
95 {NULL
, 0, 0, NULL
, NULL
};
97 void tei_handler(struct PStack
*st
, u_char pr
, struct sk_buff
*skb
);
105 #define TEI_STATE_COUNT (ST_TEI_IDVERIFY+1)
107 static char *strTeiState
[] =
124 #define TEI_EVENT_COUNT (EV_T202+1)
126 static char *strTeiEvent
[] =
142 get_random_bytes(&x
, sizeof(x
));
146 static struct PStack
*
147 findtei(struct PStack
*st
, int tei
)
149 struct PStack
*ptr
= *(st
->l1
.stlistp
);
155 if (ptr
->l2
.tei
== tei
)
163 put_tei_msg(struct PStack
*st
, u_char m_id
, unsigned int ri
, u_char tei
)
168 if (!(skb
= alloc_skb(8, GFP_ATOMIC
))) {
169 printk(KERN_WARNING
"HiSax: No skb for TEI manager\n");
173 bp
= skb_put(skb
, 3);
174 bp
[0] = (TEI_SAPI
<< 2);
175 bp
[1] = (GROUP_TEI
<< 1) | 0x1;
177 bp
= skb_put(skb
, 5);
178 bp
[0] = TEI_ENTITY_ID
;
182 bp
[4] = (tei
<< 1) | 1;
183 st
->l2
.l2l1(st
, PH_DATA
| REQUEST
, skb
);
187 tei_id_request(struct FsmInst
*fi
, int event
, void *arg
)
189 struct PStack
*st
= fi
->userdata
;
191 if (st
->l2
.tei
!= -1) {
192 st
->ma
.tei_m
.printdebug(&st
->ma
.tei_m
,
193 "assign request for allready asigned tei %d",
197 st
->ma
.ri
= random_ri();
199 st
->ma
.tei_m
.printdebug(&st
->ma
.tei_m
,
200 "assign request ri %d", st
->ma
.ri
);
201 put_tei_msg(st
, ID_REQUEST
, st
->ma
.ri
, 127);
202 FsmChangeState(&st
->ma
.tei_m
, ST_TEI_IDREQ
);
203 FsmAddTimer(&st
->ma
.t202
, st
->ma
.T202
, EV_T202
, NULL
, 1);
208 tei_id_assign(struct FsmInst
*fi
, int event
, void *arg
)
210 struct PStack
*ost
, *st
= fi
->userdata
;
211 struct sk_buff
*skb
= arg
;
212 struct IsdnCardState
*cs
;
215 ri
= ((unsigned int) skb
->data
[1] << 8) + skb
->data
[2];
216 tei
= skb
->data
[4] >> 1;
218 st
->ma
.tei_m
.printdebug(&st
->ma
.tei_m
,
219 "identity assign ri %d tei %d", ri
, tei
);
220 if ((ost
= findtei(st
, tei
))) { /* same tei is in use */
221 if (ri
!= ost
->ma
.ri
) {
222 st
->ma
.tei_m
.printdebug(&st
->ma
.tei_m
,
223 "possible duplicate assignment tei %d", tei
);
224 ost
->l2
.l2tei(ost
, MDL_ERROR
| RESPONSE
, NULL
);
226 } else if (ri
== st
->ma
.ri
) {
227 FsmDelTimer(&st
->ma
.t202
, 1);
228 FsmChangeState(&st
->ma
.tei_m
, ST_TEI_NOP
);
229 st
->l3
.l3l2(st
, MDL_ASSIGN
| REQUEST
, (void *) (long) tei
);
230 cs
= (struct IsdnCardState
*) st
->l1
.hardware
;
231 cs
->cardmsg(cs
, MDL_ASSIGN
| REQUEST
, NULL
);
236 tei_id_test_dup(struct FsmInst
*fi
, int event
, void *arg
)
238 struct PStack
*ost
, *st
= fi
->userdata
;
239 struct sk_buff
*skb
= arg
;
242 ri
= ((unsigned int) skb
->data
[1] << 8) + skb
->data
[2];
243 tei
= skb
->data
[4] >> 1;
245 st
->ma
.tei_m
.printdebug(&st
->ma
.tei_m
,
246 "foreign identity assign ri %d tei %d", ri
, tei
);
247 if ((ost
= findtei(st
, tei
))) { /* same tei is in use */
248 st
->ma
.tei_m
.printdebug(&st
->ma
.tei_m
,
249 "possible duplicate assignment tei %d", tei
);
250 FsmEvent(&ost
->ma
.tei_m
, EV_VERIFY
, NULL
);
255 tei_id_denied(struct FsmInst
*fi
, int event
, void *arg
)
257 struct PStack
*st
= fi
->userdata
;
258 struct sk_buff
*skb
= arg
;
261 ri
= ((unsigned int) skb
->data
[1] << 8) + skb
->data
[2];
262 tei
= skb
->data
[4] >> 1;
264 st
->ma
.tei_m
.printdebug(&st
->ma
.tei_m
,
265 "identity denied ri %d tei %d", ri
, tei
);
269 tei_id_chk_req(struct FsmInst
*fi
, int event
, void *arg
)
271 struct PStack
*st
= fi
->userdata
;
272 struct sk_buff
*skb
= arg
;
275 tei
= skb
->data
[4] >> 1;
277 st
->ma
.tei_m
.printdebug(&st
->ma
.tei_m
,
278 "identity check req tei %d", tei
);
279 if ((st
->l2
.tei
!= -1) && ((tei
== GROUP_TEI
) || (tei
== st
->l2
.tei
))) {
280 FsmDelTimer(&st
->ma
.t202
, 4);
281 FsmChangeState(&st
->ma
.tei_m
, ST_TEI_NOP
);
282 put_tei_msg(st
, ID_CHK_RES
, random_ri(), st
->l2
.tei
);
287 tei_id_remove(struct FsmInst
*fi
, int event
, void *arg
)
289 struct PStack
*st
= fi
->userdata
;
290 struct sk_buff
*skb
= arg
;
291 struct IsdnCardState
*cs
;
294 tei
= skb
->data
[4] >> 1;
296 st
->ma
.tei_m
.printdebug(&st
->ma
.tei_m
,
297 "identity remove tei %d", tei
);
298 if ((st
->l2
.tei
!= -1) && ((tei
== GROUP_TEI
) || (tei
== st
->l2
.tei
))) {
299 FsmDelTimer(&st
->ma
.t202
, 5);
300 FsmChangeState(&st
->ma
.tei_m
, ST_TEI_NOP
);
301 st
->l3
.l3l2(st
, MDL_REMOVE
| REQUEST
, 0);
302 cs
= (struct IsdnCardState
*) st
->l1
.hardware
;
303 cs
->cardmsg(cs
, MDL_REMOVE
| REQUEST
, NULL
);
308 tei_id_verify(struct FsmInst
*fi
, int event
, void *arg
)
310 struct PStack
*st
= fi
->userdata
;
313 st
->ma
.tei_m
.printdebug(&st
->ma
.tei_m
,
314 "id verify request for tei %d", st
->l2
.tei
);
315 put_tei_msg(st
, ID_VERIFY
, 0, st
->l2
.tei
);
316 FsmChangeState(&st
->ma
.tei_m
, ST_TEI_IDVERIFY
);
317 FsmAddTimer(&st
->ma
.t202
, st
->ma
.T202
, EV_T202
, NULL
, 2);
322 tei_id_req_tout(struct FsmInst
*fi
, int event
, void *arg
)
324 struct PStack
*st
= fi
->userdata
;
325 struct IsdnCardState
*cs
;
328 st
->ma
.ri
= random_ri();
330 st
->ma
.tei_m
.printdebug(&st
->ma
.tei_m
,
331 "assign req(%d) ri %d", 4 - st
->ma
.N202
,
333 put_tei_msg(st
, ID_REQUEST
, st
->ma
.ri
, 127);
334 FsmAddTimer(&st
->ma
.t202
, st
->ma
.T202
, EV_T202
, NULL
, 3);
336 st
->ma
.tei_m
.printdebug(&st
->ma
.tei_m
, "assign req failed");
337 st
->l3
.l3l2(st
, MDL_ERROR
| RESPONSE
, 0);
338 cs
= (struct IsdnCardState
*) st
->l1
.hardware
;
339 cs
->cardmsg(cs
, MDL_REMOVE
| REQUEST
, NULL
);
340 FsmChangeState(fi
, ST_TEI_NOP
);
345 tei_id_ver_tout(struct FsmInst
*fi
, int event
, void *arg
)
347 struct PStack
*st
= fi
->userdata
;
348 struct IsdnCardState
*cs
;
352 st
->ma
.tei_m
.printdebug(&st
->ma
.tei_m
,
353 "id verify req(%d) for tei %d",
354 3 - st
->ma
.N202
, st
->l2
.tei
);
355 put_tei_msg(st
, ID_VERIFY
, 0, st
->l2
.tei
);
356 FsmAddTimer(&st
->ma
.t202
, st
->ma
.T202
, EV_T202
, NULL
, 4);
358 st
->ma
.tei_m
.printdebug(&st
->ma
.tei_m
,
359 "verify req for tei %d failed", st
->l2
.tei
);
360 st
->l3
.l3l2(st
, MDL_REMOVE
| REQUEST
, 0);
361 cs
= (struct IsdnCardState
*) st
->l1
.hardware
;
362 cs
->cardmsg(cs
, MDL_REMOVE
| REQUEST
, NULL
);
363 FsmChangeState(fi
, ST_TEI_NOP
);
368 tei_l1l2(struct PStack
*st
, int pr
, void *arg
)
370 struct sk_buff
*skb
= arg
;
373 if (test_bit(FLG_FIXED_TEI
, &st
->l2
.flag
)) {
374 idev_kfree_skb(skb
, FREE_READ
);
378 if (pr
== (PH_DATA
| INDICATION
)) {
380 st
->ma
.tei_m
.printdebug(&st
->ma
.tei_m
,
381 "short mgr frame %ld/3", skb
->len
);
382 } else if ((skb
->data
[0] != ((TEI_SAPI
<< 2) | 2)) ||
383 (skb
->data
[1] != ((GROUP_TEI
<< 1) | 1))) {
384 st
->ma
.tei_m
.printdebug(&st
->ma
.tei_m
,
385 "wrong mgr sapi/tei %x/%x",
386 skb
->data
[0], skb
->data
[1]);
387 } else if ((skb
->data
[2] & 0xef) != UI
) {
388 st
->ma
.tei_m
.printdebug(&st
->ma
.tei_m
,
389 "mgr frame is not ui %x", skb
->data
[2]);
393 st
->ma
.tei_m
.printdebug(&st
->ma
.tei_m
,
394 "short mgr frame %ld/5", skb
->len
);
395 } else if (skb
->data
[0] != TEI_ENTITY_ID
) {
396 /* wrong management entity identifier, ignore */
397 st
->ma
.tei_m
.printdebug(&st
->ma
.tei_m
,
398 "tei handler wrong entity id %x",
402 if (mt
== ID_ASSIGNED
)
403 FsmEvent(&st
->ma
.tei_m
, EV_ASSIGN
, skb
);
404 else if (mt
== ID_DENIED
)
405 FsmEvent(&st
->ma
.tei_m
, EV_DENIED
, skb
);
406 else if (mt
== ID_CHK_REQ
)
407 FsmEvent(&st
->ma
.tei_m
, EV_CHKREQ
, skb
);
408 else if (mt
== ID_REMOVE
)
409 FsmEvent(&st
->ma
.tei_m
, EV_REMOVE
, skb
);
411 st
->ma
.tei_m
.printdebug(&st
->ma
.tei_m
,
412 "tei handler wrong mt %x\n", mt
);
417 st
->ma
.tei_m
.printdebug(&st
->ma
.tei_m
,
418 "tei handler wrong pr %x\n", pr
);
420 idev_kfree_skb(skb
, FREE_READ
);
424 tei_l2tei(struct PStack
*st
, int pr
, void *arg
)
426 struct IsdnCardState
*cs
;
428 if (test_bit(FLG_FIXED_TEI
, &st
->l2
.flag
)) {
429 if (pr
== (MDL_ASSIGN
| INDICATION
)) {
431 st
->ma
.tei_m
.printdebug(&st
->ma
.tei_m
,
432 "fixed assign tei %d", st
->l2
.tei
);
433 st
->l3
.l3l2(st
, MDL_ASSIGN
| REQUEST
, (void *) (long) st
->l2
.tei
);
434 cs
= (struct IsdnCardState
*) st
->l1
.hardware
;
435 cs
->cardmsg(cs
, MDL_ASSIGN
| REQUEST
, NULL
);
440 case (MDL_ASSIGN
| INDICATION
):
441 FsmEvent(&st
->ma
.tei_m
, EV_IDREQ
, arg
);
443 case (MDL_ERROR
| REQUEST
):
444 FsmEvent(&st
->ma
.tei_m
, EV_VERIFY
, arg
);
452 tei_debug(struct FsmInst
*fi
, char *fmt
, ...)
455 struct PStack
*st
= fi
->userdata
;
458 VHiSax_putstatus(st
->l1
.hardware
, "tei ", fmt
, args
);
463 setstack_tei(struct PStack
*st
)
465 st
->l2
.l2tei
= tei_l2tei
;
466 st
->ma
.T202
= 2000; /* T202 2000 milliseconds */
467 st
->l1
.l1tei
= tei_l1l2
;
469 st
->ma
.tei_m
.fsm
= &teifsm
;
470 st
->ma
.tei_m
.state
= ST_TEI_NOP
;
471 st
->ma
.tei_m
.debug
= 1;
472 st
->ma
.tei_m
.userdata
= st
;
473 st
->ma
.tei_m
.userint
= 0;
474 st
->ma
.tei_m
.printdebug
= tei_debug
;
475 FsmInitTimer(&st
->ma
.tei_m
, &st
->ma
.t202
);
479 init_tei(struct IsdnCardState
*cs
, int protocol
)
484 release_tei(struct IsdnCardState
*cs
)
486 struct PStack
*st
= cs
->stlist
;
489 FsmDelTimer(&st
->ma
.t202
, 1);
494 static struct FsmNode TeiFnList
[] HISAX_INITDATA
=
496 {ST_TEI_NOP
, EV_IDREQ
, tei_id_request
},
497 {ST_TEI_NOP
, EV_ASSIGN
, tei_id_test_dup
},
498 {ST_TEI_NOP
, EV_VERIFY
, tei_id_verify
},
499 {ST_TEI_NOP
, EV_REMOVE
, tei_id_remove
},
500 {ST_TEI_NOP
, EV_CHKREQ
, tei_id_chk_req
},
501 {ST_TEI_IDREQ
, EV_T202
, tei_id_req_tout
},
502 {ST_TEI_IDREQ
, EV_ASSIGN
, tei_id_assign
},
503 {ST_TEI_IDREQ
, EV_DENIED
, tei_id_denied
},
504 {ST_TEI_IDVERIFY
, EV_T202
, tei_id_ver_tout
},
505 {ST_TEI_IDVERIFY
, EV_REMOVE
, tei_id_remove
},
506 {ST_TEI_IDVERIFY
, EV_CHKREQ
, tei_id_chk_req
},
509 #define TEI_FN_COUNT (sizeof(TeiFnList)/sizeof(struct FsmNode))
514 teifsm
.state_count
= TEI_STATE_COUNT
;
515 teifsm
.event_count
= TEI_EVENT_COUNT
;
516 teifsm
.strEvent
= strTeiEvent
;
517 teifsm
.strState
= strTeiState
;
518 FsmNew(&teifsm
, TeiFnList
, TEI_FN_COUNT
);