1 /* $Id: tei.c,v 2.20.2.3 2004/01/13 14:31:26 keil Exp $
4 * based on the teles driver from Jan den Ouden
5 * Copyright by Karsten Keil <keil@isdn4linux.de>
7 * This software may be used and distributed according to the terms
8 * of the GNU General Public License, incorporated herein by reference.
10 * For changes and modifications please read
11 * Documentation/isdn/HiSax.cert
13 * Thanks to Jan den Ouden
20 #include <linux/init.h>
21 #include <linux/random.h>
23 const char *tei_revision
= "$Revision: 2.20.2.3 $";
33 #define TEI_ENTITY_ID 0xf
35 static struct Fsm teifsm
;
37 void tei_handler(struct PStack
*st
, u_char pr
, struct sk_buff
*skb
);
45 #define TEI_STATE_COUNT (ST_TEI_IDVERIFY+1)
47 static char *strTeiState
[] =
64 #define TEI_EVENT_COUNT (EV_T202+1)
66 static char *strTeiEvent
[] =
82 get_random_bytes(&x
, sizeof(x
));
86 static struct PStack
*
87 findtei(struct PStack
*st
, int tei
)
89 struct PStack
*ptr
= *(st
->l1
.stlistp
);
95 if (ptr
->l2
.tei
== tei
)
103 put_tei_msg(struct PStack
*st
, u_char m_id
, unsigned int ri
, u_char tei
)
108 if (!(skb
= alloc_skb(8, GFP_ATOMIC
))) {
109 printk(KERN_WARNING
"HiSax: No skb for TEI manager\n");
112 bp
= skb_put(skb
, 3);
113 bp
[0] = (TEI_SAPI
<< 2);
114 bp
[1] = (GROUP_TEI
<< 1) | 0x1;
116 bp
= skb_put(skb
, 5);
117 bp
[0] = TEI_ENTITY_ID
;
121 bp
[4] = (tei
<< 1) | 1;
122 st
->l2
.l2l1(st
, PH_DATA
| REQUEST
, skb
);
126 tei_id_request(struct FsmInst
*fi
, int event
, void *arg
)
128 struct PStack
*st
= fi
->userdata
;
130 if (st
->l2
.tei
!= -1) {
131 st
->ma
.tei_m
.printdebug(&st
->ma
.tei_m
,
132 "assign request for allready asigned tei %d",
136 st
->ma
.ri
= random_ri();
138 st
->ma
.tei_m
.printdebug(&st
->ma
.tei_m
,
139 "assign request ri %d", st
->ma
.ri
);
140 put_tei_msg(st
, ID_REQUEST
, st
->ma
.ri
, 127);
141 FsmChangeState(&st
->ma
.tei_m
, ST_TEI_IDREQ
);
142 FsmAddTimer(&st
->ma
.t202
, st
->ma
.T202
, EV_T202
, NULL
, 1);
147 tei_id_assign(struct FsmInst
*fi
, int event
, void *arg
)
149 struct PStack
*ost
, *st
= fi
->userdata
;
150 struct sk_buff
*skb
= arg
;
151 struct IsdnCardState
*cs
;
154 ri
= ((unsigned int) skb
->data
[1] << 8) + skb
->data
[2];
155 tei
= skb
->data
[4] >> 1;
157 st
->ma
.tei_m
.printdebug(&st
->ma
.tei_m
,
158 "identity assign ri %d tei %d", ri
, tei
);
159 if ((ost
= findtei(st
, tei
))) { /* same tei is in use */
160 if (ri
!= ost
->ma
.ri
) {
161 st
->ma
.tei_m
.printdebug(&st
->ma
.tei_m
,
162 "possible duplicate assignment tei %d", tei
);
163 ost
->l2
.l2tei(ost
, MDL_ERROR
| RESPONSE
, NULL
);
165 } else if (ri
== st
->ma
.ri
) {
166 FsmDelTimer(&st
->ma
.t202
, 1);
167 FsmChangeState(&st
->ma
.tei_m
, ST_TEI_NOP
);
168 st
->l3
.l3l2(st
, MDL_ASSIGN
| REQUEST
, (void *) (long) tei
);
169 cs
= (struct IsdnCardState
*) st
->l1
.hardware
;
170 cs
->cardmsg(cs
, MDL_ASSIGN
| REQUEST
, NULL
);
175 tei_id_test_dup(struct FsmInst
*fi
, int event
, void *arg
)
177 struct PStack
*ost
, *st
= fi
->userdata
;
178 struct sk_buff
*skb
= arg
;
181 ri
= ((unsigned int) skb
->data
[1] << 8) + skb
->data
[2];
182 tei
= skb
->data
[4] >> 1;
184 st
->ma
.tei_m
.printdebug(&st
->ma
.tei_m
,
185 "foreign identity assign ri %d tei %d", ri
, tei
);
186 if ((ost
= findtei(st
, tei
))) { /* same tei is in use */
187 if (ri
!= ost
->ma
.ri
) { /* and it wasn't our request */
188 st
->ma
.tei_m
.printdebug(&st
->ma
.tei_m
,
189 "possible duplicate assignment tei %d", tei
);
190 FsmEvent(&ost
->ma
.tei_m
, EV_VERIFY
, NULL
);
196 tei_id_denied(struct FsmInst
*fi
, int event
, void *arg
)
198 struct PStack
*st
= fi
->userdata
;
199 struct sk_buff
*skb
= arg
;
202 ri
= ((unsigned int) skb
->data
[1] << 8) + skb
->data
[2];
203 tei
= skb
->data
[4] >> 1;
205 st
->ma
.tei_m
.printdebug(&st
->ma
.tei_m
,
206 "identity denied ri %d tei %d", ri
, tei
);
210 tei_id_chk_req(struct FsmInst
*fi
, int event
, void *arg
)
212 struct PStack
*st
= fi
->userdata
;
213 struct sk_buff
*skb
= arg
;
216 tei
= skb
->data
[4] >> 1;
218 st
->ma
.tei_m
.printdebug(&st
->ma
.tei_m
,
219 "identity check req tei %d", tei
);
220 if ((st
->l2
.tei
!= -1) && ((tei
== GROUP_TEI
) || (tei
== st
->l2
.tei
))) {
221 FsmDelTimer(&st
->ma
.t202
, 4);
222 FsmChangeState(&st
->ma
.tei_m
, ST_TEI_NOP
);
223 put_tei_msg(st
, ID_CHK_RES
, random_ri(), st
->l2
.tei
);
228 tei_id_remove(struct FsmInst
*fi
, int event
, void *arg
)
230 struct PStack
*st
= fi
->userdata
;
231 struct sk_buff
*skb
= arg
;
232 struct IsdnCardState
*cs
;
235 tei
= skb
->data
[4] >> 1;
237 st
->ma
.tei_m
.printdebug(&st
->ma
.tei_m
,
238 "identity remove tei %d", tei
);
239 if ((st
->l2
.tei
!= -1) && ((tei
== GROUP_TEI
) || (tei
== st
->l2
.tei
))) {
240 FsmDelTimer(&st
->ma
.t202
, 5);
241 FsmChangeState(&st
->ma
.tei_m
, ST_TEI_NOP
);
242 st
->l3
.l3l2(st
, MDL_REMOVE
| REQUEST
, NULL
);
243 cs
= (struct IsdnCardState
*) st
->l1
.hardware
;
244 cs
->cardmsg(cs
, MDL_REMOVE
| REQUEST
, NULL
);
249 tei_id_verify(struct FsmInst
*fi
, int event
, void *arg
)
251 struct PStack
*st
= fi
->userdata
;
254 st
->ma
.tei_m
.printdebug(&st
->ma
.tei_m
,
255 "id verify request for tei %d", st
->l2
.tei
);
256 put_tei_msg(st
, ID_VERIFY
, 0, st
->l2
.tei
);
257 FsmChangeState(&st
->ma
.tei_m
, ST_TEI_IDVERIFY
);
258 FsmAddTimer(&st
->ma
.t202
, st
->ma
.T202
, EV_T202
, NULL
, 2);
263 tei_id_req_tout(struct FsmInst
*fi
, int event
, void *arg
)
265 struct PStack
*st
= fi
->userdata
;
266 struct IsdnCardState
*cs
;
269 st
->ma
.ri
= random_ri();
271 st
->ma
.tei_m
.printdebug(&st
->ma
.tei_m
,
272 "assign req(%d) ri %d", 4 - st
->ma
.N202
,
274 put_tei_msg(st
, ID_REQUEST
, st
->ma
.ri
, 127);
275 FsmAddTimer(&st
->ma
.t202
, st
->ma
.T202
, EV_T202
, NULL
, 3);
277 st
->ma
.tei_m
.printdebug(&st
->ma
.tei_m
, "assign req failed");
278 st
->l3
.l3l2(st
, MDL_ERROR
| RESPONSE
, NULL
);
279 cs
= (struct IsdnCardState
*) st
->l1
.hardware
;
280 cs
->cardmsg(cs
, MDL_REMOVE
| REQUEST
, NULL
);
281 FsmChangeState(fi
, ST_TEI_NOP
);
286 tei_id_ver_tout(struct FsmInst
*fi
, int event
, void *arg
)
288 struct PStack
*st
= fi
->userdata
;
289 struct IsdnCardState
*cs
;
293 st
->ma
.tei_m
.printdebug(&st
->ma
.tei_m
,
294 "id verify req(%d) for tei %d",
295 3 - st
->ma
.N202
, st
->l2
.tei
);
296 put_tei_msg(st
, ID_VERIFY
, 0, st
->l2
.tei
);
297 FsmAddTimer(&st
->ma
.t202
, st
->ma
.T202
, EV_T202
, NULL
, 4);
299 st
->ma
.tei_m
.printdebug(&st
->ma
.tei_m
,
300 "verify req for tei %d failed", st
->l2
.tei
);
301 st
->l3
.l3l2(st
, MDL_REMOVE
| REQUEST
, NULL
);
302 cs
= (struct IsdnCardState
*) st
->l1
.hardware
;
303 cs
->cardmsg(cs
, MDL_REMOVE
| REQUEST
, NULL
);
304 FsmChangeState(fi
, ST_TEI_NOP
);
309 tei_l1l2(struct PStack
*st
, int pr
, void *arg
)
311 struct sk_buff
*skb
= arg
;
314 if (test_bit(FLG_FIXED_TEI
, &st
->l2
.flag
)) {
319 if (pr
== (PH_DATA
| INDICATION
)) {
321 st
->ma
.tei_m
.printdebug(&st
->ma
.tei_m
,
322 "short mgr frame %ld/3", skb
->len
);
323 } else if ((skb
->data
[0] != ((TEI_SAPI
<< 2) | 2)) ||
324 (skb
->data
[1] != ((GROUP_TEI
<< 1) | 1))) {
325 st
->ma
.tei_m
.printdebug(&st
->ma
.tei_m
,
326 "wrong mgr sapi/tei %x/%x",
327 skb
->data
[0], skb
->data
[1]);
328 } else if ((skb
->data
[2] & 0xef) != UI
) {
329 st
->ma
.tei_m
.printdebug(&st
->ma
.tei_m
,
330 "mgr frame is not ui %x", skb
->data
[2]);
334 st
->ma
.tei_m
.printdebug(&st
->ma
.tei_m
,
335 "short mgr frame %ld/5", skb
->len
);
336 } else if (skb
->data
[0] != TEI_ENTITY_ID
) {
337 /* wrong management entity identifier, ignore */
338 st
->ma
.tei_m
.printdebug(&st
->ma
.tei_m
,
339 "tei handler wrong entity id %x",
343 if (mt
== ID_ASSIGNED
)
344 FsmEvent(&st
->ma
.tei_m
, EV_ASSIGN
, skb
);
345 else if (mt
== ID_DENIED
)
346 FsmEvent(&st
->ma
.tei_m
, EV_DENIED
, skb
);
347 else if (mt
== ID_CHK_REQ
)
348 FsmEvent(&st
->ma
.tei_m
, EV_CHKREQ
, skb
);
349 else if (mt
== ID_REMOVE
)
350 FsmEvent(&st
->ma
.tei_m
, EV_REMOVE
, skb
);
352 st
->ma
.tei_m
.printdebug(&st
->ma
.tei_m
,
353 "tei handler wrong mt %x\n", mt
);
358 st
->ma
.tei_m
.printdebug(&st
->ma
.tei_m
,
359 "tei handler wrong pr %x\n", pr
);
365 tei_l2tei(struct PStack
*st
, int pr
, void *arg
)
367 struct IsdnCardState
*cs
;
369 if (test_bit(FLG_FIXED_TEI
, &st
->l2
.flag
)) {
370 if (pr
== (MDL_ASSIGN
| INDICATION
)) {
372 st
->ma
.tei_m
.printdebug(&st
->ma
.tei_m
,
373 "fixed assign tei %d", st
->l2
.tei
);
374 st
->l3
.l3l2(st
, MDL_ASSIGN
| REQUEST
, (void *) (long) st
->l2
.tei
);
375 cs
= (struct IsdnCardState
*) st
->l1
.hardware
;
376 cs
->cardmsg(cs
, MDL_ASSIGN
| REQUEST
, NULL
);
381 case (MDL_ASSIGN
| INDICATION
):
382 FsmEvent(&st
->ma
.tei_m
, EV_IDREQ
, arg
);
384 case (MDL_ERROR
| REQUEST
):
385 FsmEvent(&st
->ma
.tei_m
, EV_VERIFY
, arg
);
393 tei_debug(struct FsmInst
*fi
, char *fmt
, ...)
396 struct PStack
*st
= fi
->userdata
;
399 VHiSax_putstatus(st
->l1
.hardware
, "tei ", fmt
, args
);
404 setstack_tei(struct PStack
*st
)
406 st
->l2
.l2tei
= tei_l2tei
;
407 st
->ma
.T202
= 2000; /* T202 2000 milliseconds */
408 st
->l1
.l1tei
= tei_l1l2
;
410 st
->ma
.tei_m
.fsm
= &teifsm
;
411 st
->ma
.tei_m
.state
= ST_TEI_NOP
;
412 st
->ma
.tei_m
.debug
= 1;
413 st
->ma
.tei_m
.userdata
= st
;
414 st
->ma
.tei_m
.userint
= 0;
415 st
->ma
.tei_m
.printdebug
= tei_debug
;
416 FsmInitTimer(&st
->ma
.tei_m
, &st
->ma
.t202
);
420 init_tei(struct IsdnCardState
*cs
, int protocol
)
425 release_tei(struct IsdnCardState
*cs
)
427 struct PStack
*st
= cs
->stlist
;
430 FsmDelTimer(&st
->ma
.t202
, 1);
435 static struct FsmNode TeiFnList
[] __initdata
=
437 {ST_TEI_NOP
, EV_IDREQ
, tei_id_request
},
438 {ST_TEI_NOP
, EV_ASSIGN
, tei_id_test_dup
},
439 {ST_TEI_NOP
, EV_VERIFY
, tei_id_verify
},
440 {ST_TEI_NOP
, EV_REMOVE
, tei_id_remove
},
441 {ST_TEI_NOP
, EV_CHKREQ
, tei_id_chk_req
},
442 {ST_TEI_IDREQ
, EV_T202
, tei_id_req_tout
},
443 {ST_TEI_IDREQ
, EV_ASSIGN
, tei_id_assign
},
444 {ST_TEI_IDREQ
, EV_DENIED
, tei_id_denied
},
445 {ST_TEI_IDVERIFY
, EV_T202
, tei_id_ver_tout
},
446 {ST_TEI_IDVERIFY
, EV_REMOVE
, tei_id_remove
},
447 {ST_TEI_IDVERIFY
, EV_CHKREQ
, tei_id_chk_req
},
453 teifsm
.state_count
= TEI_STATE_COUNT
;
454 teifsm
.event_count
= TEI_EVENT_COUNT
;
455 teifsm
.strEvent
= strTeiEvent
;
456 teifsm
.strState
= strTeiState
;
457 return FsmNew(&teifsm
, TeiFnList
, ARRAY_SIZE(TeiFnList
));