irlan_client_event.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534
  1. /*********************************************************************
  2. *
  3. * Filename: irlan_client_event.c
  4. * Version: 0.9
  5. * Description: IrLAN client state machine
  6. * Status: Experimental.
  7. * Author: Dag Brattli <dagb@cs.uit.no>
  8. * Created at: Sun Aug 31 20:14:37 1997
  9. * Modified at: Sun Dec 26 21:52:24 1999
  10. * Modified by: Dag Brattli <dagb@cs.uit.no>
  11. *
  12. * Copyright (c) 1998-1999 Dag Brattli <dagb@cs.uit.no>,
  13. * All Rights Reserved.
  14. *
  15. * This program is free software; you can redistribute it and/or
  16. * modify it under the terms of the GNU General Public License as
  17. * published by the Free Software Foundation; either version 2 of
  18. * the License, or (at your option) any later version.
  19. *
  20. * Neither Dag Brattli nor University of Tromsø admit liability nor
  21. * provide warranty for any of this software. This material is
  22. * provided "AS-IS" and at no charge.
  23. *
  24. ********************************************************************/
  25. #include <linux/skbuff.h>
  26. #include <net/irda/irda.h>
  27. #include <net/irda/timer.h>
  28. #include <net/irda/irmod.h>
  29. #include <net/irda/iriap.h>
  30. #include <net/irda/irlmp.h>
  31. #include <net/irda/irttp.h>
  32. #include <net/irda/irlan_common.h>
  33. #include <net/irda/irlan_client.h>
  34. #include <net/irda/irlan_event.h>
  35. static int irlan_client_state_idle (struct irlan_cb *self, IRLAN_EVENT event,
  36. struct sk_buff *skb);
  37. static int irlan_client_state_query(struct irlan_cb *self, IRLAN_EVENT event,
  38. struct sk_buff *skb);
  39. static int irlan_client_state_conn (struct irlan_cb *self, IRLAN_EVENT event,
  40. struct sk_buff *skb);
  41. static int irlan_client_state_info (struct irlan_cb *self, IRLAN_EVENT event,
  42. struct sk_buff *skb);
  43. static int irlan_client_state_media(struct irlan_cb *self, IRLAN_EVENT event,
  44. struct sk_buff *skb);
  45. static int irlan_client_state_open (struct irlan_cb *self, IRLAN_EVENT event,
  46. struct sk_buff *skb);
  47. static int irlan_client_state_wait (struct irlan_cb *self, IRLAN_EVENT event,
  48. struct sk_buff *skb);
  49. static int irlan_client_state_arb (struct irlan_cb *self, IRLAN_EVENT event,
  50. struct sk_buff *skb);
  51. static int irlan_client_state_data (struct irlan_cb *self, IRLAN_EVENT event,
  52. struct sk_buff *skb);
  53. static int irlan_client_state_close(struct irlan_cb *self, IRLAN_EVENT event,
  54. struct sk_buff *skb);
  55. static int irlan_client_state_sync (struct irlan_cb *self, IRLAN_EVENT event,
  56. struct sk_buff *skb);
  57. static int (*state[])(struct irlan_cb *, IRLAN_EVENT event, struct sk_buff *) =
  58. {
  59. irlan_client_state_idle,
  60. irlan_client_state_query,
  61. irlan_client_state_conn,
  62. irlan_client_state_info,
  63. irlan_client_state_media,
  64. irlan_client_state_open,
  65. irlan_client_state_wait,
  66. irlan_client_state_arb,
  67. irlan_client_state_data,
  68. irlan_client_state_close,
  69. irlan_client_state_sync
  70. };
  71. void irlan_do_client_event(struct irlan_cb *self, IRLAN_EVENT event,
  72. struct sk_buff *skb)
  73. {
  74. IRDA_ASSERT(self != NULL, return;);
  75. IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);
  76. (*state[ self->client.state]) (self, event, skb);
  77. }
  78. /*
  79. * Function irlan_client_state_idle (event, skb, info)
  80. *
  81. * IDLE, We are waiting for an indication that there is a provider
  82. * available.
  83. */
  84. static int irlan_client_state_idle(struct irlan_cb *self, IRLAN_EVENT event,
  85. struct sk_buff *skb)
  86. {
  87. IRDA_DEBUG(4, "%s()\n", __func__ );
  88. IRDA_ASSERT(self != NULL, return -1;);
  89. IRDA_ASSERT(self->magic == IRLAN_MAGIC, return -1;);
  90. switch (event) {
  91. case IRLAN_DISCOVERY_INDICATION:
  92. if (self->client.iriap) {
  93. IRDA_WARNING("%s(), busy with a previous query\n",
  94. __func__);
  95. return -EBUSY;
  96. }
  97. self->client.iriap = iriap_open(LSAP_ANY, IAS_CLIENT, self,
  98. irlan_client_get_value_confirm);
  99. /* Get some values from peer IAS */
  100. irlan_next_client_state(self, IRLAN_QUERY);
  101. iriap_getvaluebyclass_request(self->client.iriap,
  102. self->saddr, self->daddr,
  103. "IrLAN", "IrDA:TinyTP:LsapSel");
  104. break;
  105. case IRLAN_WATCHDOG_TIMEOUT:
  106. IRDA_DEBUG(2, "%s(), IRLAN_WATCHDOG_TIMEOUT\n", __func__ );
  107. break;
  108. default:
  109. IRDA_DEBUG(4, "%s(), Unknown event %d\n", __func__ , event);
  110. break;
  111. }
  112. if (skb)
  113. dev_kfree_skb(skb);
  114. return 0;
  115. }
  116. /*
  117. * Function irlan_client_state_query (event, skb, info)
  118. *
  119. * QUERY, We have queryed the remote IAS and is ready to connect
  120. * to provider, just waiting for the confirm.
  121. *
  122. */
  123. static int irlan_client_state_query(struct irlan_cb *self, IRLAN_EVENT event,
  124. struct sk_buff *skb)
  125. {
  126. IRDA_DEBUG(4, "%s()\n", __func__ );
  127. IRDA_ASSERT(self != NULL, return -1;);
  128. IRDA_ASSERT(self->magic == IRLAN_MAGIC, return -1;);
  129. switch(event) {
  130. case IRLAN_IAS_PROVIDER_AVAIL:
  131. IRDA_ASSERT(self->dtsap_sel_ctrl != 0, return -1;);
  132. self->client.open_retries = 0;
  133. irttp_connect_request(self->client.tsap_ctrl,
  134. self->dtsap_sel_ctrl,
  135. self->saddr, self->daddr, NULL,
  136. IRLAN_MTU, NULL);
  137. irlan_next_client_state(self, IRLAN_CONN);
  138. break;
  139. case IRLAN_IAS_PROVIDER_NOT_AVAIL:
  140. IRDA_DEBUG(2, "%s(), IAS_PROVIDER_NOT_AVAIL\n", __func__ );
  141. irlan_next_client_state(self, IRLAN_IDLE);
  142. /* Give the client a kick! */
  143. if ((self->provider.access_type == ACCESS_PEER) &&
  144. (self->provider.state != IRLAN_IDLE))
  145. irlan_client_wakeup(self, self->saddr, self->daddr);
  146. break;
  147. case IRLAN_LMP_DISCONNECT:
  148. case IRLAN_LAP_DISCONNECT:
  149. irlan_next_client_state(self, IRLAN_IDLE);
  150. break;
  151. case IRLAN_WATCHDOG_TIMEOUT:
  152. IRDA_DEBUG(2, "%s(), IRLAN_WATCHDOG_TIMEOUT\n", __func__ );
  153. break;
  154. default:
  155. IRDA_DEBUG(2, "%s(), Unknown event %d\n", __func__ , event);
  156. break;
  157. }
  158. if (skb)
  159. dev_kfree_skb(skb);
  160. return 0;
  161. }
  162. /*
  163. * Function irlan_client_state_conn (event, skb, info)
  164. *
  165. * CONN, We have connected to a provider but has not issued any
  166. * commands yet.
  167. *
  168. */
  169. static int irlan_client_state_conn(struct irlan_cb *self, IRLAN_EVENT event,
  170. struct sk_buff *skb)
  171. {
  172. IRDA_DEBUG(4, "%s()\n", __func__ );
  173. IRDA_ASSERT(self != NULL, return -1;);
  174. switch (event) {
  175. case IRLAN_CONNECT_COMPLETE:
  176. /* Send getinfo cmd */
  177. irlan_get_provider_info(self);
  178. irlan_next_client_state(self, IRLAN_INFO);
  179. break;
  180. case IRLAN_LMP_DISCONNECT:
  181. case IRLAN_LAP_DISCONNECT:
  182. irlan_next_client_state(self, IRLAN_IDLE);
  183. break;
  184. case IRLAN_WATCHDOG_TIMEOUT:
  185. IRDA_DEBUG(2, "%s(), IRLAN_WATCHDOG_TIMEOUT\n", __func__ );
  186. break;
  187. default:
  188. IRDA_DEBUG(2, "%s(), Unknown event %d\n", __func__ , event);
  189. break;
  190. }
  191. if (skb)
  192. dev_kfree_skb(skb);
  193. return 0;
  194. }
  195. /*
  196. * Function irlan_client_state_info (self, event, skb, info)
  197. *
  198. * INFO, We have issued a GetInfo command and is awaiting a reply.
  199. */
  200. static int irlan_client_state_info(struct irlan_cb *self, IRLAN_EVENT event,
  201. struct sk_buff *skb)
  202. {
  203. IRDA_DEBUG(4, "%s()\n", __func__ );
  204. IRDA_ASSERT(self != NULL, return -1;);
  205. switch (event) {
  206. case IRLAN_DATA_INDICATION:
  207. IRDA_ASSERT(skb != NULL, return -1;);
  208. irlan_client_parse_response(self, skb);
  209. irlan_next_client_state(self, IRLAN_MEDIA);
  210. irlan_get_media_char(self);
  211. break;
  212. case IRLAN_LMP_DISCONNECT:
  213. case IRLAN_LAP_DISCONNECT:
  214. irlan_next_client_state(self, IRLAN_IDLE);
  215. break;
  216. case IRLAN_WATCHDOG_TIMEOUT:
  217. IRDA_DEBUG(2, "%s(), IRLAN_WATCHDOG_TIMEOUT\n", __func__ );
  218. break;
  219. default:
  220. IRDA_DEBUG(2, "%s(), Unknown event %d\n", __func__ , event);
  221. break;
  222. }
  223. if (skb)
  224. dev_kfree_skb(skb);
  225. return 0;
  226. }
  227. /*
  228. * Function irlan_client_state_media (self, event, skb, info)
  229. *
  230. * MEDIA, The irlan_client has issued a GetMedia command and is awaiting a
  231. * reply.
  232. *
  233. */
  234. static int irlan_client_state_media(struct irlan_cb *self, IRLAN_EVENT event,
  235. struct sk_buff *skb)
  236. {
  237. IRDA_DEBUG(4, "%s()\n", __func__ );
  238. IRDA_ASSERT(self != NULL, return -1;);
  239. switch(event) {
  240. case IRLAN_DATA_INDICATION:
  241. irlan_client_parse_response(self, skb);
  242. irlan_open_data_channel(self);
  243. irlan_next_client_state(self, IRLAN_OPEN);
  244. break;
  245. case IRLAN_LMP_DISCONNECT:
  246. case IRLAN_LAP_DISCONNECT:
  247. irlan_next_client_state(self, IRLAN_IDLE);
  248. break;
  249. case IRLAN_WATCHDOG_TIMEOUT:
  250. IRDA_DEBUG(2, "%s(), IRLAN_WATCHDOG_TIMEOUT\n", __func__ );
  251. break;
  252. default:
  253. IRDA_DEBUG(2, "%s(), Unknown event %d\n", __func__ , event);
  254. break;
  255. }
  256. if (skb)
  257. dev_kfree_skb(skb);
  258. return 0;
  259. }
  260. /*
  261. * Function irlan_client_state_open (self, event, skb, info)
  262. *
  263. * OPEN, The irlan_client has issued a OpenData command and is awaiting a
  264. * reply
  265. *
  266. */
  267. static int irlan_client_state_open(struct irlan_cb *self, IRLAN_EVENT event,
  268. struct sk_buff *skb)
  269. {
  270. struct qos_info qos;
  271. IRDA_DEBUG(4, "%s()\n", __func__ );
  272. IRDA_ASSERT(self != NULL, return -1;);
  273. switch(event) {
  274. case IRLAN_DATA_INDICATION:
  275. irlan_client_parse_response(self, skb);
  276. /*
  277. * Check if we have got the remote TSAP for data
  278. * communications
  279. */
  280. IRDA_ASSERT(self->dtsap_sel_data != 0, return -1;);
  281. /* Check which access type we are dealing with */
  282. switch (self->client.access_type) {
  283. case ACCESS_PEER:
  284. if (self->provider.state == IRLAN_OPEN) {
  285. irlan_next_client_state(self, IRLAN_ARB);
  286. irlan_do_client_event(self, IRLAN_CHECK_CON_ARB,
  287. NULL);
  288. } else {
  289. irlan_next_client_state(self, IRLAN_WAIT);
  290. }
  291. break;
  292. case ACCESS_DIRECT:
  293. case ACCESS_HOSTED:
  294. qos.link_disc_time.bits = 0x01; /* 3 secs */
  295. irttp_connect_request(self->tsap_data,
  296. self->dtsap_sel_data,
  297. self->saddr, self->daddr, &qos,
  298. IRLAN_MTU, NULL);
  299. irlan_next_client_state(self, IRLAN_DATA);
  300. break;
  301. default:
  302. IRDA_DEBUG(2, "%s(), unknown access type!\n", __func__ );
  303. break;
  304. }
  305. break;
  306. case IRLAN_LMP_DISCONNECT:
  307. case IRLAN_LAP_DISCONNECT:
  308. irlan_next_client_state(self, IRLAN_IDLE);
  309. break;
  310. case IRLAN_WATCHDOG_TIMEOUT:
  311. IRDA_DEBUG(2, "%s(), IRLAN_WATCHDOG_TIMEOUT\n", __func__ );
  312. break;
  313. default:
  314. IRDA_DEBUG(2, "%s(), Unknown event %d\n", __func__ , event);
  315. break;
  316. }
  317. if (skb)
  318. dev_kfree_skb(skb);
  319. return 0;
  320. }
  321. /*
  322. * Function irlan_client_state_wait (self, event, skb, info)
  323. *
  324. * WAIT, The irlan_client is waiting for the local provider to enter the
  325. * provider OPEN state.
  326. *
  327. */
  328. static int irlan_client_state_wait(struct irlan_cb *self, IRLAN_EVENT event,
  329. struct sk_buff *skb)
  330. {
  331. IRDA_DEBUG(4, "%s()\n", __func__ );
  332. IRDA_ASSERT(self != NULL, return -1;);
  333. switch(event) {
  334. case IRLAN_PROVIDER_SIGNAL:
  335. irlan_next_client_state(self, IRLAN_ARB);
  336. irlan_do_client_event(self, IRLAN_CHECK_CON_ARB, NULL);
  337. break;
  338. case IRLAN_LMP_DISCONNECT:
  339. case IRLAN_LAP_DISCONNECT:
  340. irlan_next_client_state(self, IRLAN_IDLE);
  341. break;
  342. case IRLAN_WATCHDOG_TIMEOUT:
  343. IRDA_DEBUG(2, "%s(), IRLAN_WATCHDOG_TIMEOUT\n", __func__ );
  344. break;
  345. default:
  346. IRDA_DEBUG(2, "%s(), Unknown event %d\n", __func__ , event);
  347. break;
  348. }
  349. if (skb)
  350. dev_kfree_skb(skb);
  351. return 0;
  352. }
  353. static int irlan_client_state_arb(struct irlan_cb *self, IRLAN_EVENT event,
  354. struct sk_buff *skb)
  355. {
  356. struct qos_info qos;
  357. IRDA_DEBUG(2, "%s()\n", __func__ );
  358. IRDA_ASSERT(self != NULL, return -1;);
  359. switch(event) {
  360. case IRLAN_CHECK_CON_ARB:
  361. if (self->client.recv_arb_val == self->provider.send_arb_val) {
  362. irlan_next_client_state(self, IRLAN_CLOSE);
  363. irlan_close_data_channel(self);
  364. } else if (self->client.recv_arb_val <
  365. self->provider.send_arb_val)
  366. {
  367. qos.link_disc_time.bits = 0x01; /* 3 secs */
  368. irlan_next_client_state(self, IRLAN_DATA);
  369. irttp_connect_request(self->tsap_data,
  370. self->dtsap_sel_data,
  371. self->saddr, self->daddr, &qos,
  372. IRLAN_MTU, NULL);
  373. } else if (self->client.recv_arb_val >
  374. self->provider.send_arb_val)
  375. {
  376. IRDA_DEBUG(2, "%s(), lost the battle :-(\n", __func__ );
  377. }
  378. break;
  379. case IRLAN_DATA_CONNECT_INDICATION:
  380. irlan_next_client_state(self, IRLAN_DATA);
  381. break;
  382. case IRLAN_LMP_DISCONNECT:
  383. case IRLAN_LAP_DISCONNECT:
  384. irlan_next_client_state(self, IRLAN_IDLE);
  385. break;
  386. case IRLAN_WATCHDOG_TIMEOUT:
  387. IRDA_DEBUG(2, "%s(), IRLAN_WATCHDOG_TIMEOUT\n", __func__ );
  388. break;
  389. default:
  390. IRDA_DEBUG(2, "%s(), Unknown event %d\n", __func__ , event);
  391. break;
  392. }
  393. if (skb)
  394. dev_kfree_skb(skb);
  395. return 0;
  396. }
  397. /*
  398. * Function irlan_client_state_data (self, event, skb, info)
  399. *
  400. * DATA, The data channel is connected, allowing data transfers between
  401. * the local and remote machines.
  402. *
  403. */
  404. static int irlan_client_state_data(struct irlan_cb *self, IRLAN_EVENT event,
  405. struct sk_buff *skb)
  406. {
  407. IRDA_DEBUG(4, "%s()\n", __func__ );
  408. IRDA_ASSERT(self != NULL, return -1;);
  409. IRDA_ASSERT(self->magic == IRLAN_MAGIC, return -1;);
  410. switch(event) {
  411. case IRLAN_DATA_INDICATION:
  412. irlan_client_parse_response(self, skb);
  413. break;
  414. case IRLAN_LMP_DISCONNECT: /* FALLTHROUGH */
  415. case IRLAN_LAP_DISCONNECT:
  416. irlan_next_client_state(self, IRLAN_IDLE);
  417. break;
  418. default:
  419. IRDA_DEBUG(2, "%s(), Unknown event %d\n", __func__ , event);
  420. break;
  421. }
  422. if (skb)
  423. dev_kfree_skb(skb);
  424. return 0;
  425. }
  426. /*
  427. * Function irlan_client_state_close (self, event, skb, info)
  428. *
  429. *
  430. *
  431. */
  432. static int irlan_client_state_close(struct irlan_cb *self, IRLAN_EVENT event,
  433. struct sk_buff *skb)
  434. {
  435. IRDA_DEBUG(2, "%s()\n", __func__ );
  436. if (skb)
  437. dev_kfree_skb(skb);
  438. return 0;
  439. }
  440. /*
  441. * Function irlan_client_state_sync (self, event, skb, info)
  442. *
  443. *
  444. *
  445. */
  446. static int irlan_client_state_sync(struct irlan_cb *self, IRLAN_EVENT event,
  447. struct sk_buff *skb)
  448. {
  449. IRDA_DEBUG(2, "%s()\n", __func__ );
  450. if (skb)
  451. dev_kfree_skb(skb);
  452. return 0;
  453. }