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/gfp.h>
21 #include <linux/init.h>
22 #include <linux/random.h>
24 const char *tei_revision
= "$Revision: 2.20.2.3 $";
34 #define TEI_ENTITY_ID 0xf
36 static struct Fsm teifsm
;
38 void tei_handler(struct PStack
*st
, u_char pr
, struct sk_buff
*skb
);
46 #define TEI_STATE_COUNT (ST_TEI_IDVERIFY + 1)
48 static char *strTeiState
[] =
65 #define TEI_EVENT_COUNT (EV_T202 + 1)
67 static char *strTeiEvent
[] =
83 get_random_bytes(&x
, sizeof(x
));
87 static struct PStack
*
88 findtei(struct PStack
*st
, int tei
)
90 struct PStack
*ptr
= *(st
->l1
.stlistp
);
96 if (ptr
->l2
.tei
== tei
)
104 put_tei_msg(struct PStack
*st
, u_char m_id
, unsigned int ri
, u_char tei
)
109 if (!(skb
= alloc_skb(8, GFP_ATOMIC
))) {
110 printk(KERN_WARNING
"HiSax: No skb for TEI manager\n");
113 bp
= skb_put(skb
, 3);
114 bp
[0] = (TEI_SAPI
<< 2);
115 bp
[1] = (GROUP_TEI
<< 1) | 0x1;
117 bp
= skb_put(skb
, 5);
118 bp
[0] = TEI_ENTITY_ID
;
122 bp
[4] = (tei
<< 1) | 1;
123 st
->l2
.l2l1(st
, PH_DATA
| REQUEST
, skb
);
127 tei_id_request(struct FsmInst
*fi
, int event
, void *arg
)
129 struct PStack
*st
= fi
->userdata
;
131 if (st
->l2
.tei
!= -1) {
132 st
->ma
.tei_m
.printdebug(&st
->ma
.tei_m
,
133 "assign request for already assigned tei %d",
137 st
->ma
.ri
= random_ri();
139 st
->ma
.tei_m
.printdebug(&st
->ma
.tei_m
,
140 "assign request ri %d", st
->ma
.ri
);
141 put_tei_msg(st
, ID_REQUEST
, st
->ma
.ri
, 127);
142 FsmChangeState(&st
->ma
.tei_m
, ST_TEI_IDREQ
);
143 FsmAddTimer(&st
->ma
.t202
, st
->ma
.T202
, EV_T202
, NULL
, 1);
148 tei_id_assign(struct FsmInst
*fi
, int event
, void *arg
)
150 struct PStack
*ost
, *st
= fi
->userdata
;
151 struct sk_buff
*skb
= arg
;
152 struct IsdnCardState
*cs
;
155 ri
= ((unsigned int) skb
->data
[1] << 8) + skb
->data
[2];
156 tei
= skb
->data
[4] >> 1;
158 st
->ma
.tei_m
.printdebug(&st
->ma
.tei_m
,
159 "identity assign ri %d tei %d", ri
, tei
);
160 if ((ost
= findtei(st
, tei
))) { /* same tei is in use */
161 if (ri
!= ost
->ma
.ri
) {
162 st
->ma
.tei_m
.printdebug(&st
->ma
.tei_m
,
163 "possible duplicate assignment tei %d", tei
);
164 ost
->l2
.l2tei(ost
, MDL_ERROR
| RESPONSE
, NULL
);
166 } else if (ri
== st
->ma
.ri
) {
167 FsmDelTimer(&st
->ma
.t202
, 1);
168 FsmChangeState(&st
->ma
.tei_m
, ST_TEI_NOP
);
169 st
->l3
.l3l2(st
, MDL_ASSIGN
| REQUEST
, (void *) (long) tei
);
170 cs
= (struct IsdnCardState
*) st
->l1
.hardware
;
171 cs
->cardmsg(cs
, MDL_ASSIGN
| REQUEST
, NULL
);
176 tei_id_test_dup(struct FsmInst
*fi
, int event
, void *arg
)
178 struct PStack
*ost
, *st
= fi
->userdata
;
179 struct sk_buff
*skb
= arg
;
182 ri
= ((unsigned int) skb
->data
[1] << 8) + skb
->data
[2];
183 tei
= skb
->data
[4] >> 1;
185 st
->ma
.tei_m
.printdebug(&st
->ma
.tei_m
,
186 "foreign identity assign ri %d tei %d", ri
, tei
);
187 if ((ost
= findtei(st
, tei
))) { /* same tei is in use */
188 if (ri
!= ost
->ma
.ri
) { /* and it wasn't our request */
189 st
->ma
.tei_m
.printdebug(&st
->ma
.tei_m
,
190 "possible duplicate assignment tei %d", tei
);
191 FsmEvent(&ost
->ma
.tei_m
, EV_VERIFY
, NULL
);
197 tei_id_denied(struct FsmInst
*fi
, int event
, void *arg
)
199 struct PStack
*st
= fi
->userdata
;
200 struct sk_buff
*skb
= arg
;
203 ri
= ((unsigned int) skb
->data
[1] << 8) + skb
->data
[2];
204 tei
= skb
->data
[4] >> 1;
206 st
->ma
.tei_m
.printdebug(&st
->ma
.tei_m
,
207 "identity denied ri %d tei %d", ri
, tei
);
211 tei_id_chk_req(struct FsmInst
*fi
, int event
, void *arg
)
213 struct PStack
*st
= fi
->userdata
;
214 struct sk_buff
*skb
= arg
;
217 tei
= skb
->data
[4] >> 1;
219 st
->ma
.tei_m
.printdebug(&st
->ma
.tei_m
,
220 "identity check req tei %d", tei
);
221 if ((st
->l2
.tei
!= -1) && ((tei
== GROUP_TEI
) || (tei
== st
->l2
.tei
))) {
222 FsmDelTimer(&st
->ma
.t202
, 4);
223 FsmChangeState(&st
->ma
.tei_m
, ST_TEI_NOP
);
224 put_tei_msg(st
, ID_CHK_RES
, random_ri(), st
->l2
.tei
);
229 tei_id_remove(struct FsmInst
*fi
, int event
, void *arg
)
231 struct PStack
*st
= fi
->userdata
;
232 struct sk_buff
*skb
= arg
;
233 struct IsdnCardState
*cs
;
236 tei
= skb
->data
[4] >> 1;
238 st
->ma
.tei_m
.printdebug(&st
->ma
.tei_m
,
239 "identity remove tei %d", tei
);
240 if ((st
->l2
.tei
!= -1) && ((tei
== GROUP_TEI
) || (tei
== st
->l2
.tei
))) {
241 FsmDelTimer(&st
->ma
.t202
, 5);
242 FsmChangeState(&st
->ma
.tei_m
, ST_TEI_NOP
);
243 st
->l3
.l3l2(st
, MDL_REMOVE
| REQUEST
, NULL
);
244 cs
= (struct IsdnCardState
*) st
->l1
.hardware
;
245 cs
->cardmsg(cs
, MDL_REMOVE
| REQUEST
, NULL
);
250 tei_id_verify(struct FsmInst
*fi
, int event
, void *arg
)
252 struct PStack
*st
= fi
->userdata
;
255 st
->ma
.tei_m
.printdebug(&st
->ma
.tei_m
,
256 "id verify request for tei %d", st
->l2
.tei
);
257 put_tei_msg(st
, ID_VERIFY
, 0, st
->l2
.tei
);
258 FsmChangeState(&st
->ma
.tei_m
, ST_TEI_IDVERIFY
);
259 FsmAddTimer(&st
->ma
.t202
, st
->ma
.T202
, EV_T202
, NULL
, 2);
264 tei_id_req_tout(struct FsmInst
*fi
, int event
, void *arg
)
266 struct PStack
*st
= fi
->userdata
;
267 struct IsdnCardState
*cs
;
270 st
->ma
.ri
= random_ri();
272 st
->ma
.tei_m
.printdebug(&st
->ma
.tei_m
,
273 "assign req(%d) ri %d", 4 - st
->ma
.N202
,
275 put_tei_msg(st
, ID_REQUEST
, st
->ma
.ri
, 127);
276 FsmAddTimer(&st
->ma
.t202
, st
->ma
.T202
, EV_T202
, NULL
, 3);
278 st
->ma
.tei_m
.printdebug(&st
->ma
.tei_m
, "assign req failed");
279 st
->l3
.l3l2(st
, MDL_ERROR
| RESPONSE
, NULL
);
280 cs
= (struct IsdnCardState
*) st
->l1
.hardware
;
281 cs
->cardmsg(cs
, MDL_REMOVE
| REQUEST
, NULL
);
282 FsmChangeState(fi
, ST_TEI_NOP
);
287 tei_id_ver_tout(struct FsmInst
*fi
, int event
, void *arg
)
289 struct PStack
*st
= fi
->userdata
;
290 struct IsdnCardState
*cs
;
294 st
->ma
.tei_m
.printdebug(&st
->ma
.tei_m
,
295 "id verify req(%d) for tei %d",
296 3 - st
->ma
.N202
, st
->l2
.tei
);
297 put_tei_msg(st
, ID_VERIFY
, 0, st
->l2
.tei
);
298 FsmAddTimer(&st
->ma
.t202
, st
->ma
.T202
, EV_T202
, NULL
, 4);
300 st
->ma
.tei_m
.printdebug(&st
->ma
.tei_m
,
301 "verify req for tei %d failed", st
->l2
.tei
);
302 st
->l3
.l3l2(st
, MDL_REMOVE
| REQUEST
, NULL
);
303 cs
= (struct IsdnCardState
*) st
->l1
.hardware
;
304 cs
->cardmsg(cs
, MDL_REMOVE
| REQUEST
, NULL
);
305 FsmChangeState(fi
, ST_TEI_NOP
);
310 tei_l1l2(struct PStack
*st
, int pr
, void *arg
)
312 struct sk_buff
*skb
= arg
;
315 if (test_bit(FLG_FIXED_TEI
, &st
->l2
.flag
)) {
320 if (pr
== (PH_DATA
| INDICATION
)) {
322 st
->ma
.tei_m
.printdebug(&st
->ma
.tei_m
,
323 "short mgr frame %ld/3", skb
->len
);
324 } else if ((skb
->data
[0] != ((TEI_SAPI
<< 2) | 2)) ||
325 (skb
->data
[1] != ((GROUP_TEI
<< 1) | 1))) {
326 st
->ma
.tei_m
.printdebug(&st
->ma
.tei_m
,
327 "wrong mgr sapi/tei %x/%x",
328 skb
->data
[0], skb
->data
[1]);
329 } else if ((skb
->data
[2] & 0xef) != UI
) {
330 st
->ma
.tei_m
.printdebug(&st
->ma
.tei_m
,
331 "mgr frame is not ui %x", skb
->data
[2]);
335 st
->ma
.tei_m
.printdebug(&st
->ma
.tei_m
,
336 "short mgr frame %ld/5", skb
->len
);
337 } else if (skb
->data
[0] != TEI_ENTITY_ID
) {
338 /* wrong management entity identifier, ignore */
339 st
->ma
.tei_m
.printdebug(&st
->ma
.tei_m
,
340 "tei handler wrong entity id %x",
344 if (mt
== ID_ASSIGNED
)
345 FsmEvent(&st
->ma
.tei_m
, EV_ASSIGN
, skb
);
346 else if (mt
== ID_DENIED
)
347 FsmEvent(&st
->ma
.tei_m
, EV_DENIED
, skb
);
348 else if (mt
== ID_CHK_REQ
)
349 FsmEvent(&st
->ma
.tei_m
, EV_CHKREQ
, skb
);
350 else if (mt
== ID_REMOVE
)
351 FsmEvent(&st
->ma
.tei_m
, EV_REMOVE
, skb
);
353 st
->ma
.tei_m
.printdebug(&st
->ma
.tei_m
,
354 "tei handler wrong mt %x\n", mt
);
359 st
->ma
.tei_m
.printdebug(&st
->ma
.tei_m
,
360 "tei handler wrong pr %x\n", pr
);
366 tei_l2tei(struct PStack
*st
, int pr
, void *arg
)
368 struct IsdnCardState
*cs
;
370 if (test_bit(FLG_FIXED_TEI
, &st
->l2
.flag
)) {
371 if (pr
== (MDL_ASSIGN
| INDICATION
)) {
373 st
->ma
.tei_m
.printdebug(&st
->ma
.tei_m
,
374 "fixed assign tei %d", st
->l2
.tei
);
375 st
->l3
.l3l2(st
, MDL_ASSIGN
| REQUEST
, (void *) (long) st
->l2
.tei
);
376 cs
= (struct IsdnCardState
*) st
->l1
.hardware
;
377 cs
->cardmsg(cs
, MDL_ASSIGN
| REQUEST
, NULL
);
382 case (MDL_ASSIGN
| INDICATION
):
383 FsmEvent(&st
->ma
.tei_m
, EV_IDREQ
, arg
);
385 case (MDL_ERROR
| REQUEST
):
386 FsmEvent(&st
->ma
.tei_m
, EV_VERIFY
, arg
);
394 tei_debug(struct FsmInst
*fi
, char *fmt
, ...)
397 struct PStack
*st
= fi
->userdata
;
400 VHiSax_putstatus(st
->l1
.hardware
, "tei ", fmt
, args
);
405 setstack_tei(struct PStack
*st
)
407 st
->l2
.l2tei
= tei_l2tei
;
408 st
->ma
.T202
= 2000; /* T202 2000 milliseconds */
409 st
->l1
.l1tei
= tei_l1l2
;
411 st
->ma
.tei_m
.fsm
= &teifsm
;
412 st
->ma
.tei_m
.state
= ST_TEI_NOP
;
413 st
->ma
.tei_m
.debug
= 1;
414 st
->ma
.tei_m
.userdata
= st
;
415 st
->ma
.tei_m
.userint
= 0;
416 st
->ma
.tei_m
.printdebug
= tei_debug
;
417 FsmInitTimer(&st
->ma
.tei_m
, &st
->ma
.t202
);
421 init_tei(struct IsdnCardState
*cs
, int protocol
)
426 release_tei(struct IsdnCardState
*cs
)
428 struct PStack
*st
= cs
->stlist
;
431 FsmDelTimer(&st
->ma
.t202
, 1);
436 static struct FsmNode TeiFnList
[] __initdata
=
438 {ST_TEI_NOP
, EV_IDREQ
, tei_id_request
},
439 {ST_TEI_NOP
, EV_ASSIGN
, tei_id_test_dup
},
440 {ST_TEI_NOP
, EV_VERIFY
, tei_id_verify
},
441 {ST_TEI_NOP
, EV_REMOVE
, tei_id_remove
},
442 {ST_TEI_NOP
, EV_CHKREQ
, tei_id_chk_req
},
443 {ST_TEI_IDREQ
, EV_T202
, tei_id_req_tout
},
444 {ST_TEI_IDREQ
, EV_ASSIGN
, tei_id_assign
},
445 {ST_TEI_IDREQ
, EV_DENIED
, tei_id_denied
},
446 {ST_TEI_IDVERIFY
, EV_T202
, tei_id_ver_tout
},
447 {ST_TEI_IDVERIFY
, EV_REMOVE
, tei_id_remove
},
448 {ST_TEI_IDVERIFY
, EV_CHKREQ
, tei_id_chk_req
},
454 teifsm
.state_count
= TEI_STATE_COUNT
;
455 teifsm
.event_count
= TEI_EVENT_COUNT
;
456 teifsm
.strEvent
= strTeiEvent
;
457 teifsm
.strState
= strTeiState
;
458 return FsmNew(&teifsm
, TeiFnList
, ARRAY_SIZE(TeiFnList
));