l3_1tr6.c 21 KB

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