blob: 9195f9fd628f9c0c8c013286593a1655a5899bcf [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/* $Id: tei.c,v 2.20.2.3 2004/01/13 14:31:26 keil Exp $
2 *
3 * Author Karsten Keil
4 * based on the teles driver from Jan den Ouden
5 * Copyright by Karsten Keil <keil@isdn4linux.de>
Joe Perches475be4d2012-02-19 19:52:38 -08006 *
Linus Torvalds1da177e2005-04-16 15:20:36 -07007 * This software may be used and distributed according to the terms
8 * of the GNU General Public License, incorporated herein by reference.
9 *
10 * For changes and modifications please read
11 * Documentation/isdn/HiSax.cert
12 *
13 * Thanks to Jan den Ouden
14 * Fritz Elfert
15 *
16 */
17
18#include "hisax.h"
19#include "isdnl2.h"
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090020#include <linux/gfp.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070021#include <linux/init.h>
22#include <linux/random.h>
23
24const char *tei_revision = "$Revision: 2.20.2.3 $";
25
26#define ID_REQUEST 1
27#define ID_ASSIGNED 2
28#define ID_DENIED 3
29#define ID_CHK_REQ 4
30#define ID_CHK_RES 5
31#define ID_REMOVE 6
32#define ID_VERIFY 7
33
34#define TEI_ENTITY_ID 0xf
35
36static struct Fsm teifsm;
37
38void tei_handler(struct PStack *st, u_char pr, struct sk_buff *skb);
39
40enum {
41 ST_TEI_NOP,
42 ST_TEI_IDREQ,
43 ST_TEI_IDVERIFY,
44};
45
Joe Perches475be4d2012-02-19 19:52:38 -080046#define TEI_STATE_COUNT (ST_TEI_IDVERIFY + 1)
Linus Torvalds1da177e2005-04-16 15:20:36 -070047
48static char *strTeiState[] =
49{
50 "ST_TEI_NOP",
51 "ST_TEI_IDREQ",
52 "ST_TEI_IDVERIFY",
53};
54
55enum {
56 EV_IDREQ,
57 EV_ASSIGN,
58 EV_DENIED,
59 EV_CHKREQ,
60 EV_REMOVE,
61 EV_VERIFY,
62 EV_T202,
63};
64
Joe Perches475be4d2012-02-19 19:52:38 -080065#define TEI_EVENT_COUNT (EV_T202 + 1)
Linus Torvalds1da177e2005-04-16 15:20:36 -070066
67static char *strTeiEvent[] =
68{
69 "EV_IDREQ",
70 "EV_ASSIGN",
71 "EV_DENIED",
72 "EV_CHKREQ",
73 "EV_REMOVE",
74 "EV_VERIFY",
75 "EV_T202",
76};
77
Adrian Bunk672c3fd2005-06-25 14:59:18 -070078static unsigned int
Linus Torvalds1da177e2005-04-16 15:20:36 -070079random_ri(void)
80{
81 unsigned int x;
82
83 get_random_bytes(&x, sizeof(x));
84 return (x & 0xffff);
85}
86
87static struct PStack *
88findtei(struct PStack *st, int tei)
89{
90 struct PStack *ptr = *(st->l1.stlistp);
91
92 if (tei == 127)
93 return (NULL);
94
95 while (ptr)
96 if (ptr->l2.tei == tei)
97 return (ptr);
98 else
99 ptr = ptr->next;
100 return (NULL);
101}
102
103static void
104put_tei_msg(struct PStack *st, u_char m_id, unsigned int ri, u_char tei)
105{
106 struct sk_buff *skb;
107 u_char *bp;
108
109 if (!(skb = alloc_skb(8, GFP_ATOMIC))) {
110 printk(KERN_WARNING "HiSax: No skb for TEI manager\n");
111 return;
112 }
113 bp = skb_put(skb, 3);
114 bp[0] = (TEI_SAPI << 2);
115 bp[1] = (GROUP_TEI << 1) | 0x1;
116 bp[2] = UI;
117 bp = skb_put(skb, 5);
118 bp[0] = TEI_ENTITY_ID;
119 bp[1] = ri >> 8;
120 bp[2] = ri & 0xff;
121 bp[3] = m_id;
122 bp[4] = (tei << 1) | 1;
123 st->l2.l2l1(st, PH_DATA | REQUEST, skb);
124}
125
126static void
127tei_id_request(struct FsmInst *fi, int event, void *arg)
128{
129 struct PStack *st = fi->userdata;
130
131 if (st->l2.tei != -1) {
132 st->ma.tei_m.printdebug(&st->ma.tei_m,
Joe Perches475be4d2012-02-19 19:52:38 -0800133 "assign request for already assigned tei %d",
134 st->l2.tei);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700135 return;
136 }
137 st->ma.ri = random_ri();
138 if (st->ma.debug)
139 st->ma.tei_m.printdebug(&st->ma.tei_m,
Joe Perches475be4d2012-02-19 19:52:38 -0800140 "assign request ri %d", st->ma.ri);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700141 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);
144 st->ma.N202 = 3;
145}
146
147static void
148tei_id_assign(struct FsmInst *fi, int event, void *arg)
149{
150 struct PStack *ost, *st = fi->userdata;
151 struct sk_buff *skb = arg;
152 struct IsdnCardState *cs;
153 int ri, tei;
154
155 ri = ((unsigned int) skb->data[1] << 8) + skb->data[2];
156 tei = skb->data[4] >> 1;
157 if (st->ma.debug)
158 st->ma.tei_m.printdebug(&st->ma.tei_m,
Joe Perches475be4d2012-02-19 19:52:38 -0800159 "identity assign ri %d tei %d", ri, tei);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700160 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,
Joe Perches475be4d2012-02-19 19:52:38 -0800163 "possible duplicate assignment tei %d", tei);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700164 ost->l2.l2tei(ost, MDL_ERROR | RESPONSE, NULL);
165 }
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);
172 }
173}
174
175static void
176tei_id_test_dup(struct FsmInst *fi, int event, void *arg)
177{
178 struct PStack *ost, *st = fi->userdata;
179 struct sk_buff *skb = arg;
180 int tei, ri;
181
182 ri = ((unsigned int) skb->data[1] << 8) + skb->data[2];
183 tei = skb->data[4] >> 1;
184 if (st->ma.debug)
185 st->ma.tei_m.printdebug(&st->ma.tei_m,
Joe Perches475be4d2012-02-19 19:52:38 -0800186 "foreign identity assign ri %d tei %d", ri, tei);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700187 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,
Joe Perches475be4d2012-02-19 19:52:38 -0800190 "possible duplicate assignment tei %d", tei);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700191 FsmEvent(&ost->ma.tei_m, EV_VERIFY, NULL);
192 }
Joe Perches475be4d2012-02-19 19:52:38 -0800193 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700194}
195
196static void
197tei_id_denied(struct FsmInst *fi, int event, void *arg)
198{
199 struct PStack *st = fi->userdata;
200 struct sk_buff *skb = arg;
201 int ri, tei;
202
203 ri = ((unsigned int) skb->data[1] << 8) + skb->data[2];
204 tei = skb->data[4] >> 1;
205 if (st->ma.debug)
206 st->ma.tei_m.printdebug(&st->ma.tei_m,
Joe Perches475be4d2012-02-19 19:52:38 -0800207 "identity denied ri %d tei %d", ri, tei);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700208}
209
210static void
211tei_id_chk_req(struct FsmInst *fi, int event, void *arg)
212{
213 struct PStack *st = fi->userdata;
214 struct sk_buff *skb = arg;
215 int tei;
216
217 tei = skb->data[4] >> 1;
218 if (st->ma.debug)
219 st->ma.tei_m.printdebug(&st->ma.tei_m,
Joe Perches475be4d2012-02-19 19:52:38 -0800220 "identity check req tei %d", tei);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700221 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);
225 }
226}
227
228static void
229tei_id_remove(struct FsmInst *fi, int event, void *arg)
230{
231 struct PStack *st = fi->userdata;
232 struct sk_buff *skb = arg;
233 struct IsdnCardState *cs;
234 int tei;
235
236 tei = skb->data[4] >> 1;
237 if (st->ma.debug)
238 st->ma.tei_m.printdebug(&st->ma.tei_m,
Joe Perches475be4d2012-02-19 19:52:38 -0800239 "identity remove tei %d", tei);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700240 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);
246 }
247}
248
249static void
250tei_id_verify(struct FsmInst *fi, int event, void *arg)
251{
252 struct PStack *st = fi->userdata;
253
254 if (st->ma.debug)
255 st->ma.tei_m.printdebug(&st->ma.tei_m,
Joe Perches475be4d2012-02-19 19:52:38 -0800256 "id verify request for tei %d", st->l2.tei);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700257 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);
260 st->ma.N202 = 2;
261}
262
263static void
264tei_id_req_tout(struct FsmInst *fi, int event, void *arg)
265{
266 struct PStack *st = fi->userdata;
267 struct IsdnCardState *cs;
268
269 if (--st->ma.N202) {
270 st->ma.ri = random_ri();
271 if (st->ma.debug)
272 st->ma.tei_m.printdebug(&st->ma.tei_m,
Joe Perches475be4d2012-02-19 19:52:38 -0800273 "assign req(%d) ri %d", 4 - st->ma.N202,
274 st->ma.ri);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700275 put_tei_msg(st, ID_REQUEST, st->ma.ri, 127);
276 FsmAddTimer(&st->ma.t202, st->ma.T202, EV_T202, NULL, 3);
277 } else {
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);
283 }
284}
285
286static void
287tei_id_ver_tout(struct FsmInst *fi, int event, void *arg)
288{
289 struct PStack *st = fi->userdata;
290 struct IsdnCardState *cs;
291
292 if (--st->ma.N202) {
293 if (st->ma.debug)
294 st->ma.tei_m.printdebug(&st->ma.tei_m,
Joe Perches475be4d2012-02-19 19:52:38 -0800295 "id verify req(%d) for tei %d",
296 3 - st->ma.N202, st->l2.tei);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700297 put_tei_msg(st, ID_VERIFY, 0, st->l2.tei);
298 FsmAddTimer(&st->ma.t202, st->ma.T202, EV_T202, NULL, 4);
299 } else {
300 st->ma.tei_m.printdebug(&st->ma.tei_m,
Joe Perches475be4d2012-02-19 19:52:38 -0800301 "verify req for tei %d failed", st->l2.tei);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700302 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);
306 }
307}
308
309static void
310tei_l1l2(struct PStack *st, int pr, void *arg)
311{
312 struct sk_buff *skb = arg;
313 int mt;
314
315 if (test_bit(FLG_FIXED_TEI, &st->l2.flag)) {
316 dev_kfree_skb(skb);
317 return;
318 }
319
320 if (pr == (PH_DATA | INDICATION)) {
321 if (skb->len < 3) {
322 st->ma.tei_m.printdebug(&st->ma.tei_m,
Joe Perches475be4d2012-02-19 19:52:38 -0800323 "short mgr frame %ld/3", skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700324 } 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,
Joe Perches475be4d2012-02-19 19:52:38 -0800327 "wrong mgr sapi/tei %x/%x",
328 skb->data[0], skb->data[1]);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700329 } else if ((skb->data[2] & 0xef) != UI) {
330 st->ma.tei_m.printdebug(&st->ma.tei_m,
Joe Perches475be4d2012-02-19 19:52:38 -0800331 "mgr frame is not ui %x", skb->data[2]);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700332 } else {
333 skb_pull(skb, 3);
334 if (skb->len < 5) {
335 st->ma.tei_m.printdebug(&st->ma.tei_m,
Joe Perches475be4d2012-02-19 19:52:38 -0800336 "short mgr frame %ld/5", skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700337 } else if (skb->data[0] != TEI_ENTITY_ID) {
338 /* wrong management entity identifier, ignore */
339 st->ma.tei_m.printdebug(&st->ma.tei_m,
Joe Perches475be4d2012-02-19 19:52:38 -0800340 "tei handler wrong entity id %x",
341 skb->data[0]);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700342 } else {
343 mt = skb->data[3];
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);
352 else {
353 st->ma.tei_m.printdebug(&st->ma.tei_m,
Joe Perches475be4d2012-02-19 19:52:38 -0800354 "tei handler wrong mt %x\n", mt);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700355 }
356 }
357 }
358 } else {
359 st->ma.tei_m.printdebug(&st->ma.tei_m,
Joe Perches475be4d2012-02-19 19:52:38 -0800360 "tei handler wrong pr %x\n", pr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700361 }
362 dev_kfree_skb(skb);
363}
364
365static void
366tei_l2tei(struct PStack *st, int pr, void *arg)
367{
368 struct IsdnCardState *cs;
369
370 if (test_bit(FLG_FIXED_TEI, &st->l2.flag)) {
371 if (pr == (MDL_ASSIGN | INDICATION)) {
372 if (st->ma.debug)
373 st->ma.tei_m.printdebug(&st->ma.tei_m,
Joe Perches475be4d2012-02-19 19:52:38 -0800374 "fixed assign tei %d", st->l2.tei);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700375 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);
378 }
379 return;
380 }
381 switch (pr) {
Joe Perches475be4d2012-02-19 19:52:38 -0800382 case (MDL_ASSIGN | INDICATION):
383 FsmEvent(&st->ma.tei_m, EV_IDREQ, arg);
384 break;
385 case (MDL_ERROR | REQUEST):
386 FsmEvent(&st->ma.tei_m, EV_VERIFY, arg);
387 break;
388 default:
389 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700390 }
391}
392
393static void
394tei_debug(struct FsmInst *fi, char *fmt, ...)
395{
396 va_list args;
397 struct PStack *st = fi->userdata;
398
399 va_start(args, fmt);
400 VHiSax_putstatus(st->l1.hardware, "tei ", fmt, args);
401 va_end(args);
402}
403
404void
405setstack_tei(struct PStack *st)
406{
407 st->l2.l2tei = tei_l2tei;
408 st->ma.T202 = 2000; /* T202 2000 milliseconds */
409 st->l1.l1tei = tei_l1l2;
410 st->ma.debug = 1;
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);
418}
419
420void
421init_tei(struct IsdnCardState *cs, int protocol)
422{
423}
424
425void
426release_tei(struct IsdnCardState *cs)
427{
428 struct PStack *st = cs->stlist;
429
430 while (st) {
431 FsmDelTimer(&st->ma.t202, 1);
432 st = st->next;
433 }
434}
435
436static struct FsmNode TeiFnList[] __initdata =
437{
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},
449};
450
Linus Torvalds1da177e2005-04-16 15:20:36 -0700451int __init
452TeiNew(void)
453{
454 teifsm.state_count = TEI_STATE_COUNT;
455 teifsm.event_count = TEI_EVENT_COUNT;
456 teifsm.strEvent = strTeiEvent;
457 teifsm.strState = strTeiState;
Karsten Keilba2d6cc2009-07-24 18:26:08 +0200458 return FsmNew(&teifsm, TeiFnList, ARRAY_SIZE(TeiFnList));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700459}
460
461void
462TeiFree(void)
463{
464 FsmFree(&teifsm);
465}