iriap_event.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497
  1. /*********************************************************************
  2. *
  3. * Filename: iriap_event.c
  4. * Version: 0.1
  5. * Description: IAP Finite State Machine
  6. * Status: Experimental.
  7. * Author: Dag Brattli <dagb@cs.uit.no>
  8. * Created at: Thu Aug 21 00:02:07 1997
  9. * Modified at: Wed Mar 1 11:28:34 2000
  10. * Modified by: Dag Brattli <dagb@cs.uit.no>
  11. *
  12. * Copyright (c) 1997, 1999-2000 Dag Brattli <dagb@cs.uit.no>,
  13. * All Rights Reserved.
  14. * Copyright (c) 2000-2003 Jean Tourrilhes <jt@hpl.hp.com>
  15. *
  16. * This program is free software; you can redistribute it and/or
  17. * modify it under the terms of the GNU General Public License as
  18. * published by the Free Software Foundation; either version 2 of
  19. * the License, or (at your option) any later version.
  20. *
  21. * Neither Dag Brattli nor University of Tromsø admit liability nor
  22. * provide warranty for any of this software. This material is
  23. * provided "AS-IS" and at no charge.
  24. *
  25. ********************************************************************/
  26. #include <linux/slab.h>
  27. #include <net/irda/irda.h>
  28. #include <net/irda/irlmp.h>
  29. #include <net/irda/iriap.h>
  30. #include <net/irda/iriap_event.h>
  31. static void state_s_disconnect (struct iriap_cb *self, IRIAP_EVENT event,
  32. struct sk_buff *skb);
  33. static void state_s_connecting (struct iriap_cb *self, IRIAP_EVENT event,
  34. struct sk_buff *skb);
  35. static void state_s_call (struct iriap_cb *self, IRIAP_EVENT event,
  36. struct sk_buff *skb);
  37. static void state_s_make_call (struct iriap_cb *self, IRIAP_EVENT event,
  38. struct sk_buff *skb);
  39. static void state_s_calling (struct iriap_cb *self, IRIAP_EVENT event,
  40. struct sk_buff *skb);
  41. static void state_s_outstanding (struct iriap_cb *self, IRIAP_EVENT event,
  42. struct sk_buff *skb);
  43. static void state_s_replying (struct iriap_cb *self, IRIAP_EVENT event,
  44. struct sk_buff *skb);
  45. static void state_s_wait_for_call(struct iriap_cb *self, IRIAP_EVENT event,
  46. struct sk_buff *skb);
  47. static void state_s_wait_active (struct iriap_cb *self, IRIAP_EVENT event,
  48. struct sk_buff *skb);
  49. static void state_r_disconnect (struct iriap_cb *self, IRIAP_EVENT event,
  50. struct sk_buff *skb);
  51. static void state_r_call (struct iriap_cb *self, IRIAP_EVENT event,
  52. struct sk_buff *skb);
  53. static void state_r_waiting (struct iriap_cb *self, IRIAP_EVENT event,
  54. struct sk_buff *skb);
  55. static void state_r_wait_active (struct iriap_cb *self, IRIAP_EVENT event,
  56. struct sk_buff *skb);
  57. static void state_r_receiving (struct iriap_cb *self, IRIAP_EVENT event,
  58. struct sk_buff *skb);
  59. static void state_r_execute (struct iriap_cb *self, IRIAP_EVENT event,
  60. struct sk_buff *skb);
  61. static void state_r_returning (struct iriap_cb *self, IRIAP_EVENT event,
  62. struct sk_buff *skb);
  63. static void (*iriap_state[])(struct iriap_cb *self, IRIAP_EVENT event,
  64. struct sk_buff *skb) = {
  65. /* Client FSM */
  66. state_s_disconnect,
  67. state_s_connecting,
  68. state_s_call,
  69. /* S-Call FSM */
  70. state_s_make_call,
  71. state_s_calling,
  72. state_s_outstanding,
  73. state_s_replying,
  74. state_s_wait_for_call,
  75. state_s_wait_active,
  76. /* Server FSM */
  77. state_r_disconnect,
  78. state_r_call,
  79. /* R-Connect FSM */
  80. state_r_waiting,
  81. state_r_wait_active,
  82. state_r_receiving,
  83. state_r_execute,
  84. state_r_returning,
  85. };
  86. void iriap_next_client_state(struct iriap_cb *self, IRIAP_STATE state)
  87. {
  88. IRDA_ASSERT(self != NULL, return;);
  89. IRDA_ASSERT(self->magic == IAS_MAGIC, return;);
  90. self->client_state = state;
  91. }
  92. void iriap_next_call_state(struct iriap_cb *self, IRIAP_STATE state)
  93. {
  94. IRDA_ASSERT(self != NULL, return;);
  95. IRDA_ASSERT(self->magic == IAS_MAGIC, return;);
  96. self->call_state = state;
  97. }
  98. void iriap_next_server_state(struct iriap_cb *self, IRIAP_STATE state)
  99. {
  100. IRDA_ASSERT(self != NULL, return;);
  101. IRDA_ASSERT(self->magic == IAS_MAGIC, return;);
  102. self->server_state = state;
  103. }
  104. void iriap_next_r_connect_state(struct iriap_cb *self, IRIAP_STATE state)
  105. {
  106. IRDA_ASSERT(self != NULL, return;);
  107. IRDA_ASSERT(self->magic == IAS_MAGIC, return;);
  108. self->r_connect_state = state;
  109. }
  110. void iriap_do_client_event(struct iriap_cb *self, IRIAP_EVENT event,
  111. struct sk_buff *skb)
  112. {
  113. IRDA_ASSERT(self != NULL, return;);
  114. IRDA_ASSERT(self->magic == IAS_MAGIC, return;);
  115. (*iriap_state[ self->client_state]) (self, event, skb);
  116. }
  117. void iriap_do_call_event(struct iriap_cb *self, IRIAP_EVENT event,
  118. struct sk_buff *skb)
  119. {
  120. IRDA_ASSERT(self != NULL, return;);
  121. IRDA_ASSERT(self->magic == IAS_MAGIC, return;);
  122. (*iriap_state[ self->call_state]) (self, event, skb);
  123. }
  124. void iriap_do_server_event(struct iriap_cb *self, IRIAP_EVENT event,
  125. struct sk_buff *skb)
  126. {
  127. IRDA_ASSERT(self != NULL, return;);
  128. IRDA_ASSERT(self->magic == IAS_MAGIC, return;);
  129. (*iriap_state[ self->server_state]) (self, event, skb);
  130. }
  131. void iriap_do_r_connect_event(struct iriap_cb *self, IRIAP_EVENT event,
  132. struct sk_buff *skb)
  133. {
  134. IRDA_ASSERT(self != NULL, return;);
  135. IRDA_ASSERT(self->magic == IAS_MAGIC, return;);
  136. (*iriap_state[ self->r_connect_state]) (self, event, skb);
  137. }
  138. /*
  139. * Function state_s_disconnect (event, skb)
  140. *
  141. * S-Disconnect, The device has no LSAP connection to a particular
  142. * remote device.
  143. */
  144. static void state_s_disconnect(struct iriap_cb *self, IRIAP_EVENT event,
  145. struct sk_buff *skb)
  146. {
  147. IRDA_ASSERT(self != NULL, return;);
  148. IRDA_ASSERT(self->magic == IAS_MAGIC, return;);
  149. switch (event) {
  150. case IAP_CALL_REQUEST_GVBC:
  151. iriap_next_client_state(self, S_CONNECTING);
  152. IRDA_ASSERT(self->request_skb == NULL, return;);
  153. /* Don't forget to refcount it -
  154. * see iriap_getvaluebyclass_request(). */
  155. skb_get(skb);
  156. self->request_skb = skb;
  157. iriap_connect_request(self);
  158. break;
  159. case IAP_LM_DISCONNECT_INDICATION:
  160. break;
  161. default:
  162. pr_debug("%s(), Unknown event %d\n", __func__, event);
  163. break;
  164. }
  165. }
  166. /*
  167. * Function state_s_connecting (self, event, skb)
  168. *
  169. * S-Connecting
  170. *
  171. */
  172. static void state_s_connecting(struct iriap_cb *self, IRIAP_EVENT event,
  173. struct sk_buff *skb)
  174. {
  175. IRDA_ASSERT(self != NULL, return;);
  176. IRDA_ASSERT(self->magic == IAS_MAGIC, return;);
  177. switch (event) {
  178. case IAP_LM_CONNECT_CONFIRM:
  179. /*
  180. * Jump to S-Call FSM
  181. */
  182. iriap_do_call_event(self, IAP_CALL_REQUEST, skb);
  183. /* iriap_call_request(self, 0,0,0); */
  184. iriap_next_client_state(self, S_CALL);
  185. break;
  186. case IAP_LM_DISCONNECT_INDICATION:
  187. /* Abort calls */
  188. iriap_next_call_state(self, S_MAKE_CALL);
  189. iriap_next_client_state(self, S_DISCONNECT);
  190. break;
  191. default:
  192. pr_debug("%s(), Unknown event %d\n", __func__, event);
  193. break;
  194. }
  195. }
  196. /*
  197. * Function state_s_call (self, event, skb)
  198. *
  199. * S-Call, The device can process calls to a specific remote
  200. * device. Whenever the LSAP connection is disconnected, this state
  201. * catches that event and clears up
  202. */
  203. static void state_s_call(struct iriap_cb *self, IRIAP_EVENT event,
  204. struct sk_buff *skb)
  205. {
  206. IRDA_ASSERT(self != NULL, return;);
  207. switch (event) {
  208. case IAP_LM_DISCONNECT_INDICATION:
  209. /* Abort calls */
  210. iriap_next_call_state(self, S_MAKE_CALL);
  211. iriap_next_client_state(self, S_DISCONNECT);
  212. break;
  213. default:
  214. pr_debug("state_s_call: Unknown event %d\n", event);
  215. break;
  216. }
  217. }
  218. /*
  219. * Function state_s_make_call (event, skb)
  220. *
  221. * S-Make-Call
  222. *
  223. */
  224. static void state_s_make_call(struct iriap_cb *self, IRIAP_EVENT event,
  225. struct sk_buff *skb)
  226. {
  227. struct sk_buff *tx_skb;
  228. IRDA_ASSERT(self != NULL, return;);
  229. switch (event) {
  230. case IAP_CALL_REQUEST:
  231. /* Already refcounted - see state_s_disconnect() */
  232. tx_skb = self->request_skb;
  233. self->request_skb = NULL;
  234. irlmp_data_request(self->lsap, tx_skb);
  235. iriap_next_call_state(self, S_OUTSTANDING);
  236. break;
  237. default:
  238. pr_debug("%s(), Unknown event %d\n", __func__, event);
  239. break;
  240. }
  241. }
  242. /*
  243. * Function state_s_calling (event, skb)
  244. *
  245. * S-Calling
  246. *
  247. */
  248. static void state_s_calling(struct iriap_cb *self, IRIAP_EVENT event,
  249. struct sk_buff *skb)
  250. {
  251. pr_debug("%s(), Not implemented\n", __func__);
  252. }
  253. /*
  254. * Function state_s_outstanding (event, skb)
  255. *
  256. * S-Outstanding, The device is waiting for a response to a command
  257. *
  258. */
  259. static void state_s_outstanding(struct iriap_cb *self, IRIAP_EVENT event,
  260. struct sk_buff *skb)
  261. {
  262. IRDA_ASSERT(self != NULL, return;);
  263. switch (event) {
  264. case IAP_RECV_F_LST:
  265. /*iriap_send_ack(self);*/
  266. /*LM_Idle_request(idle); */
  267. iriap_next_call_state(self, S_WAIT_FOR_CALL);
  268. break;
  269. default:
  270. pr_debug("%s(), Unknown event %d\n", __func__, event);
  271. break;
  272. }
  273. }
  274. /*
  275. * Function state_s_replying (event, skb)
  276. *
  277. * S-Replying, The device is collecting a multiple part response
  278. */
  279. static void state_s_replying(struct iriap_cb *self, IRIAP_EVENT event,
  280. struct sk_buff *skb)
  281. {
  282. pr_debug("%s(), Not implemented\n", __func__);
  283. }
  284. /*
  285. * Function state_s_wait_for_call (event, skb)
  286. *
  287. * S-Wait-for-Call
  288. *
  289. */
  290. static void state_s_wait_for_call(struct iriap_cb *self, IRIAP_EVENT event,
  291. struct sk_buff *skb)
  292. {
  293. pr_debug("%s(), Not implemented\n", __func__);
  294. }
  295. /*
  296. * Function state_s_wait_active (event, skb)
  297. *
  298. * S-Wait-Active
  299. *
  300. */
  301. static void state_s_wait_active(struct iriap_cb *self, IRIAP_EVENT event,
  302. struct sk_buff *skb)
  303. {
  304. pr_debug("%s(), Not implemented\n", __func__);
  305. }
  306. /**************************************************************************
  307. *
  308. * Server FSM
  309. *
  310. **************************************************************************/
  311. /*
  312. * Function state_r_disconnect (self, event, skb)
  313. *
  314. * LM-IAS server is disconnected (not processing any requests!)
  315. *
  316. */
  317. static void state_r_disconnect(struct iriap_cb *self, IRIAP_EVENT event,
  318. struct sk_buff *skb)
  319. {
  320. struct sk_buff *tx_skb;
  321. switch (event) {
  322. case IAP_LM_CONNECT_INDICATION:
  323. tx_skb = alloc_skb(LMP_MAX_HEADER, GFP_ATOMIC);
  324. if (tx_skb == NULL)
  325. return;
  326. /* Reserve space for MUX_CONTROL and LAP header */
  327. skb_reserve(tx_skb, LMP_MAX_HEADER);
  328. irlmp_connect_response(self->lsap, tx_skb);
  329. /*LM_Idle_request(idle); */
  330. iriap_next_server_state(self, R_CALL);
  331. /*
  332. * Jump to R-Connect FSM, we skip R-Waiting since we do not
  333. * care about LM_Idle_request()!
  334. */
  335. iriap_next_r_connect_state(self, R_RECEIVING);
  336. break;
  337. default:
  338. pr_debug("%s(), unknown event %d\n", __func__, event);
  339. break;
  340. }
  341. }
  342. /*
  343. * Function state_r_call (self, event, skb)
  344. */
  345. static void state_r_call(struct iriap_cb *self, IRIAP_EVENT event,
  346. struct sk_buff *skb)
  347. {
  348. switch (event) {
  349. case IAP_LM_DISCONNECT_INDICATION:
  350. /* Abort call */
  351. iriap_next_server_state(self, R_DISCONNECT);
  352. iriap_next_r_connect_state(self, R_WAITING);
  353. break;
  354. default:
  355. pr_debug("%s(), unknown event!\n", __func__);
  356. break;
  357. }
  358. }
  359. /*
  360. * R-Connect FSM
  361. */
  362. /*
  363. * Function state_r_waiting (self, event, skb)
  364. */
  365. static void state_r_waiting(struct iriap_cb *self, IRIAP_EVENT event,
  366. struct sk_buff *skb)
  367. {
  368. pr_debug("%s(), Not implemented\n", __func__);
  369. }
  370. static void state_r_wait_active(struct iriap_cb *self, IRIAP_EVENT event,
  371. struct sk_buff *skb)
  372. {
  373. pr_debug("%s(), Not implemented\n", __func__);
  374. }
  375. /*
  376. * Function state_r_receiving (self, event, skb)
  377. *
  378. * We are receiving a command
  379. *
  380. */
  381. static void state_r_receiving(struct iriap_cb *self, IRIAP_EVENT event,
  382. struct sk_buff *skb)
  383. {
  384. switch (event) {
  385. case IAP_RECV_F_LST:
  386. iriap_next_r_connect_state(self, R_EXECUTE);
  387. iriap_call_indication(self, skb);
  388. break;
  389. default:
  390. pr_debug("%s(), unknown event!\n", __func__);
  391. break;
  392. }
  393. }
  394. /*
  395. * Function state_r_execute (self, event, skb)
  396. *
  397. * The server is processing the request
  398. *
  399. */
  400. static void state_r_execute(struct iriap_cb *self, IRIAP_EVENT event,
  401. struct sk_buff *skb)
  402. {
  403. IRDA_ASSERT(skb != NULL, return;);
  404. IRDA_ASSERT(self != NULL, return;);
  405. IRDA_ASSERT(self->magic == IAS_MAGIC, return;);
  406. switch (event) {
  407. case IAP_CALL_RESPONSE:
  408. /*
  409. * Since we don't implement the Waiting state, we return
  410. * to state Receiving instead, DB.
  411. */
  412. iriap_next_r_connect_state(self, R_RECEIVING);
  413. /* Don't forget to refcount it - see
  414. * iriap_getvaluebyclass_response(). */
  415. skb_get(skb);
  416. irlmp_data_request(self->lsap, skb);
  417. break;
  418. default:
  419. pr_debug("%s(), unknown event!\n", __func__);
  420. break;
  421. }
  422. }
  423. static void state_r_returning(struct iriap_cb *self, IRIAP_EVENT event,
  424. struct sk_buff *skb)
  425. {
  426. pr_debug("%s(), event=%d\n", __func__, event);
  427. switch (event) {
  428. case IAP_RECV_F_LST:
  429. break;
  430. default:
  431. break;
  432. }
  433. }