irlmp_event.c 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912
  1. /*********************************************************************
  2. *
  3. * Filename: irlmp_event.c
  4. * Version: 0.8
  5. * Description: An IrDA LMP event driver for Linux
  6. * Status: Experimental.
  7. * Author: Dag Brattli <dagb@cs.uit.no>
  8. * Created at: Mon Aug 4 20:40:53 1997
  9. * Modified at: Tue Dec 14 23:04:16 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. * 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/config.h>
  27. #include <linux/kernel.h>
  28. #include <net/irda/irda.h>
  29. #include <net/irda/timer.h>
  30. #include <net/irda/irlap.h>
  31. #include <net/irda/irlmp.h>
  32. #include <net/irda/irlmp_frame.h>
  33. #include <net/irda/irlmp_event.h>
  34. const char *irlmp_state[] = {
  35. "LAP_STANDBY",
  36. "LAP_U_CONNECT",
  37. "LAP_ACTIVE",
  38. };
  39. const char *irlsap_state[] = {
  40. "LSAP_DISCONNECTED",
  41. "LSAP_CONNECT",
  42. "LSAP_CONNECT_PEND",
  43. "LSAP_DATA_TRANSFER_READY",
  44. "LSAP_SETUP",
  45. "LSAP_SETUP_PEND",
  46. };
  47. #ifdef CONFIG_IRDA_DEBUG
  48. static const char *irlmp_event[] = {
  49. "LM_CONNECT_REQUEST",
  50. "LM_CONNECT_CONFIRM",
  51. "LM_CONNECT_RESPONSE",
  52. "LM_CONNECT_INDICATION",
  53. "LM_DISCONNECT_INDICATION",
  54. "LM_DISCONNECT_REQUEST",
  55. "LM_DATA_REQUEST",
  56. "LM_UDATA_REQUEST",
  57. "LM_DATA_INDICATION",
  58. "LM_UDATA_INDICATION",
  59. "LM_WATCHDOG_TIMEOUT",
  60. /* IrLAP events */
  61. "LM_LAP_CONNECT_REQUEST",
  62. "LM_LAP_CONNECT_INDICATION",
  63. "LM_LAP_CONNECT_CONFIRM",
  64. "LM_LAP_DISCONNECT_INDICATION",
  65. "LM_LAP_DISCONNECT_REQUEST",
  66. "LM_LAP_DISCOVERY_REQUEST",
  67. "LM_LAP_DISCOVERY_CONFIRM",
  68. "LM_LAP_IDLE_TIMEOUT",
  69. };
  70. #endif /* CONFIG_IRDA_DEBUG */
  71. /* LAP Connection control proto declarations */
  72. static void irlmp_state_standby (struct lap_cb *, IRLMP_EVENT,
  73. struct sk_buff *);
  74. static void irlmp_state_u_connect(struct lap_cb *, IRLMP_EVENT,
  75. struct sk_buff *);
  76. static void irlmp_state_active (struct lap_cb *, IRLMP_EVENT,
  77. struct sk_buff *);
  78. /* LSAP Connection control proto declarations */
  79. static int irlmp_state_disconnected(struct lsap_cb *, IRLMP_EVENT,
  80. struct sk_buff *);
  81. static int irlmp_state_connect (struct lsap_cb *, IRLMP_EVENT,
  82. struct sk_buff *);
  83. static int irlmp_state_connect_pend(struct lsap_cb *, IRLMP_EVENT,
  84. struct sk_buff *);
  85. static int irlmp_state_dtr (struct lsap_cb *, IRLMP_EVENT,
  86. struct sk_buff *);
  87. static int irlmp_state_setup (struct lsap_cb *, IRLMP_EVENT,
  88. struct sk_buff *);
  89. static int irlmp_state_setup_pend (struct lsap_cb *, IRLMP_EVENT,
  90. struct sk_buff *);
  91. static void (*lap_state[]) (struct lap_cb *, IRLMP_EVENT, struct sk_buff *) =
  92. {
  93. irlmp_state_standby,
  94. irlmp_state_u_connect,
  95. irlmp_state_active,
  96. };
  97. static int (*lsap_state[])( struct lsap_cb *, IRLMP_EVENT, struct sk_buff *) =
  98. {
  99. irlmp_state_disconnected,
  100. irlmp_state_connect,
  101. irlmp_state_connect_pend,
  102. irlmp_state_dtr,
  103. irlmp_state_setup,
  104. irlmp_state_setup_pend
  105. };
  106. static inline void irlmp_next_lap_state(struct lap_cb *self,
  107. IRLMP_STATE state)
  108. {
  109. /*
  110. IRDA_DEBUG(4, "%s(), LMP LAP = %s\n", __FUNCTION__, irlmp_state[state]);
  111. */
  112. self->lap_state = state;
  113. }
  114. static inline void irlmp_next_lsap_state(struct lsap_cb *self,
  115. LSAP_STATE state)
  116. {
  117. /*
  118. IRDA_ASSERT(self != NULL, return;);
  119. IRDA_DEBUG(4, "%s(), LMP LSAP = %s\n", __FUNCTION__, irlsap_state[state]);
  120. */
  121. self->lsap_state = state;
  122. }
  123. /* Do connection control events */
  124. int irlmp_do_lsap_event(struct lsap_cb *self, IRLMP_EVENT event,
  125. struct sk_buff *skb)
  126. {
  127. IRDA_ASSERT(self != NULL, return -1;);
  128. IRDA_ASSERT(self->magic == LMP_LSAP_MAGIC, return -1;);
  129. IRDA_DEBUG(4, "%s(), EVENT = %s, STATE = %s\n",
  130. __FUNCTION__, irlmp_event[event], irlsap_state[ self->lsap_state]);
  131. return (*lsap_state[self->lsap_state]) (self, event, skb);
  132. }
  133. /*
  134. * Function do_lap_event (event, skb, info)
  135. *
  136. * Do IrLAP control events
  137. *
  138. */
  139. void irlmp_do_lap_event(struct lap_cb *self, IRLMP_EVENT event,
  140. struct sk_buff *skb)
  141. {
  142. IRDA_ASSERT(self != NULL, return;);
  143. IRDA_ASSERT(self->magic == LMP_LAP_MAGIC, return;);
  144. IRDA_DEBUG(4, "%s(), EVENT = %s, STATE = %s\n", __FUNCTION__,
  145. irlmp_event[event],
  146. irlmp_state[self->lap_state]);
  147. (*lap_state[self->lap_state]) (self, event, skb);
  148. }
  149. void irlmp_discovery_timer_expired(void *data)
  150. {
  151. IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
  152. /* We always cleanup the log (active & passive discovery) */
  153. irlmp_do_expiry();
  154. /* Active discovery is conditional */
  155. if (sysctl_discovery)
  156. irlmp_do_discovery(sysctl_discovery_slots);
  157. /* Restart timer */
  158. irlmp_start_discovery_timer(irlmp, sysctl_discovery_timeout * HZ);
  159. }
  160. void irlmp_watchdog_timer_expired(void *data)
  161. {
  162. struct lsap_cb *self = (struct lsap_cb *) data;
  163. IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
  164. IRDA_ASSERT(self != NULL, return;);
  165. IRDA_ASSERT(self->magic == LMP_LSAP_MAGIC, return;);
  166. irlmp_do_lsap_event(self, LM_WATCHDOG_TIMEOUT, NULL);
  167. }
  168. void irlmp_idle_timer_expired(void *data)
  169. {
  170. struct lap_cb *self = (struct lap_cb *) data;
  171. IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
  172. IRDA_ASSERT(self != NULL, return;);
  173. IRDA_ASSERT(self->magic == LMP_LAP_MAGIC, return;);
  174. irlmp_do_lap_event(self, LM_LAP_IDLE_TIMEOUT, NULL);
  175. }
  176. /*
  177. * Send an event on all LSAPs attached to this LAP.
  178. */
  179. static inline void
  180. irlmp_do_all_lsap_event(hashbin_t * lsap_hashbin,
  181. IRLMP_EVENT event)
  182. {
  183. struct lsap_cb *lsap;
  184. struct lsap_cb *lsap_next;
  185. /* Note : this function use the new hashbin_find_next()
  186. * function, instead of the old hashbin_get_next().
  187. * This make sure that we are always pointing one lsap
  188. * ahead, so that if the current lsap is removed as the
  189. * result of sending the event, we don't care.
  190. * Also, as we store the context ourselves, if an enumeration
  191. * of the same lsap hashbin happens as the result of sending the
  192. * event, we don't care.
  193. * The only problem is if the next lsap is removed. In that case,
  194. * hashbin_find_next() will return NULL and we will abort the
  195. * enumeration. - Jean II */
  196. /* Also : we don't accept any skb in input. We can *NOT* pass
  197. * the same skb to multiple clients safely, we would need to
  198. * skb_clone() it. - Jean II */
  199. lsap = (struct lsap_cb *) hashbin_get_first(lsap_hashbin);
  200. while (NULL != hashbin_find_next(lsap_hashbin,
  201. (long) lsap,
  202. NULL,
  203. (void *) &lsap_next) ) {
  204. irlmp_do_lsap_event(lsap, event, NULL);
  205. lsap = lsap_next;
  206. }
  207. }
  208. /*********************************************************************
  209. *
  210. * LAP connection control states
  211. *
  212. ********************************************************************/
  213. /*
  214. * Function irlmp_state_standby (event, skb, info)
  215. *
  216. * STANDBY, The IrLAP connection does not exist.
  217. *
  218. */
  219. static void irlmp_state_standby(struct lap_cb *self, IRLMP_EVENT event,
  220. struct sk_buff *skb)
  221. {
  222. IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
  223. IRDA_ASSERT(self->irlap != NULL, return;);
  224. switch (event) {
  225. case LM_LAP_DISCOVERY_REQUEST:
  226. /* irlmp_next_station_state( LMP_DISCOVER); */
  227. irlap_discovery_request(self->irlap, &irlmp->discovery_cmd);
  228. break;
  229. case LM_LAP_CONNECT_INDICATION:
  230. /* It's important to switch state first, to avoid IrLMP to
  231. * think that the link is free since IrLMP may then start
  232. * discovery before the connection is properly set up. DB.
  233. */
  234. irlmp_next_lap_state(self, LAP_ACTIVE);
  235. /* Just accept connection TODO, this should be fixed */
  236. irlap_connect_response(self->irlap, skb);
  237. break;
  238. case LM_LAP_CONNECT_REQUEST:
  239. IRDA_DEBUG(4, "%s() LS_CONNECT_REQUEST\n", __FUNCTION__);
  240. irlmp_next_lap_state(self, LAP_U_CONNECT);
  241. /* FIXME: need to set users requested QoS */
  242. irlap_connect_request(self->irlap, self->daddr, NULL, 0);
  243. break;
  244. case LM_LAP_DISCONNECT_INDICATION:
  245. IRDA_DEBUG(4, "%s(), Error LM_LAP_DISCONNECT_INDICATION\n",
  246. __FUNCTION__);
  247. irlmp_next_lap_state(self, LAP_STANDBY);
  248. break;
  249. default:
  250. IRDA_DEBUG(0, "%s(), Unknown event %s\n",
  251. __FUNCTION__, irlmp_event[event]);
  252. break;
  253. }
  254. }
  255. /*
  256. * Function irlmp_state_u_connect (event, skb, info)
  257. *
  258. * U_CONNECT, The layer above has tried to open an LSAP connection but
  259. * since the IrLAP connection does not exist, we must first start an
  260. * IrLAP connection. We are now waiting response from IrLAP.
  261. * */
  262. static void irlmp_state_u_connect(struct lap_cb *self, IRLMP_EVENT event,
  263. struct sk_buff *skb)
  264. {
  265. IRDA_DEBUG(2, "%s(), event=%s\n", __FUNCTION__, irlmp_event[event]);
  266. switch (event) {
  267. case LM_LAP_CONNECT_INDICATION:
  268. /* It's important to switch state first, to avoid IrLMP to
  269. * think that the link is free since IrLMP may then start
  270. * discovery before the connection is properly set up. DB.
  271. */
  272. irlmp_next_lap_state(self, LAP_ACTIVE);
  273. /* Just accept connection TODO, this should be fixed */
  274. irlap_connect_response(self->irlap, skb);
  275. /* Tell LSAPs that they can start sending data */
  276. irlmp_do_all_lsap_event(self->lsaps, LM_LAP_CONNECT_CONFIRM);
  277. /* Note : by the time we get there (LAP retries and co),
  278. * the lsaps may already have gone. This avoid getting stuck
  279. * forever in LAP_ACTIVE state - Jean II */
  280. if (HASHBIN_GET_SIZE(self->lsaps) == 0) {
  281. IRDA_DEBUG(0, "%s() NO LSAPs !\n", __FUNCTION__);
  282. irlmp_start_idle_timer(self, LM_IDLE_TIMEOUT);
  283. }
  284. break;
  285. case LM_LAP_CONNECT_REQUEST:
  286. /* Already trying to connect */
  287. break;
  288. case LM_LAP_CONNECT_CONFIRM:
  289. /* For all lsap_ce E Associated do LS_Connect_confirm */
  290. irlmp_next_lap_state(self, LAP_ACTIVE);
  291. /* Tell LSAPs that they can start sending data */
  292. irlmp_do_all_lsap_event(self->lsaps, LM_LAP_CONNECT_CONFIRM);
  293. /* Note : by the time we get there (LAP retries and co),
  294. * the lsaps may already have gone. This avoid getting stuck
  295. * forever in LAP_ACTIVE state - Jean II */
  296. if (HASHBIN_GET_SIZE(self->lsaps) == 0) {
  297. IRDA_DEBUG(0, "%s() NO LSAPs !\n", __FUNCTION__);
  298. irlmp_start_idle_timer(self, LM_IDLE_TIMEOUT);
  299. }
  300. break;
  301. case LM_LAP_DISCONNECT_INDICATION:
  302. IRDA_DEBUG(4, "%s(), LM_LAP_DISCONNECT_INDICATION\n", __FUNCTION__);
  303. irlmp_next_lap_state(self, LAP_STANDBY);
  304. /* Send disconnect event to all LSAPs using this link */
  305. irlmp_do_all_lsap_event(self->lsaps,
  306. LM_LAP_DISCONNECT_INDICATION);
  307. break;
  308. case LM_LAP_DISCONNECT_REQUEST:
  309. IRDA_DEBUG(4, "%s(), LM_LAP_DISCONNECT_REQUEST\n", __FUNCTION__);
  310. /* One of the LSAP did timeout or was closed, if it was
  311. * the last one, try to get out of here - Jean II */
  312. if (HASHBIN_GET_SIZE(self->lsaps) <= 1) {
  313. irlap_disconnect_request(self->irlap);
  314. }
  315. break;
  316. default:
  317. IRDA_DEBUG(0, "%s(), Unknown event %s\n",
  318. __FUNCTION__, irlmp_event[event]);
  319. break;
  320. }
  321. }
  322. /*
  323. * Function irlmp_state_active (event, skb, info)
  324. *
  325. * ACTIVE, IrLAP connection is active
  326. *
  327. */
  328. static void irlmp_state_active(struct lap_cb *self, IRLMP_EVENT event,
  329. struct sk_buff *skb)
  330. {
  331. IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
  332. switch (event) {
  333. case LM_LAP_CONNECT_REQUEST:
  334. IRDA_DEBUG(4, "%s(), LS_CONNECT_REQUEST\n", __FUNCTION__);
  335. /*
  336. * IrLAP may have a pending disconnect. We tried to close
  337. * IrLAP, but it was postponed because the link was
  338. * busy or we were still sending packets. As we now
  339. * need it, make sure it stays on. Jean II
  340. */
  341. irlap_clear_disconnect(self->irlap);
  342. /*
  343. * LAP connection already active, just bounce back! Since we
  344. * don't know which LSAP that tried to do this, we have to
  345. * notify all LSAPs using this LAP, but that should be safe to
  346. * do anyway.
  347. */
  348. irlmp_do_all_lsap_event(self->lsaps, LM_LAP_CONNECT_CONFIRM);
  349. /* Needed by connect indication */
  350. irlmp_do_all_lsap_event(irlmp->unconnected_lsaps,
  351. LM_LAP_CONNECT_CONFIRM);
  352. /* Keep state */
  353. break;
  354. case LM_LAP_DISCONNECT_REQUEST:
  355. /*
  356. * Need to find out if we should close IrLAP or not. If there
  357. * is only one LSAP connection left on this link, that LSAP
  358. * must be the one that tries to close IrLAP. It will be
  359. * removed later and moved to the list of unconnected LSAPs
  360. */
  361. if (HASHBIN_GET_SIZE(self->lsaps) > 0) {
  362. /* Timer value is checked in irsysctl - Jean II */
  363. irlmp_start_idle_timer(self, sysctl_lap_keepalive_time * HZ / 1000);
  364. } else {
  365. /* No more connections, so close IrLAP */
  366. /* We don't want to change state just yet, because
  367. * we want to reflect accurately the real state of
  368. * the LAP, not the state we wish it was in,
  369. * so that we don't lose LM_LAP_CONNECT_REQUEST.
  370. * In some cases, IrLAP won't close the LAP
  371. * immediately. For example, it might still be
  372. * retrying packets or waiting for the pf bit.
  373. * As the LAP always send a DISCONNECT_INDICATION
  374. * in PCLOSE or SCLOSE, just change state on that.
  375. * Jean II */
  376. irlap_disconnect_request(self->irlap);
  377. }
  378. break;
  379. case LM_LAP_IDLE_TIMEOUT:
  380. if (HASHBIN_GET_SIZE(self->lsaps) == 0) {
  381. /* Same reasoning as above - keep state */
  382. irlap_disconnect_request(self->irlap);
  383. }
  384. break;
  385. case LM_LAP_DISCONNECT_INDICATION:
  386. irlmp_next_lap_state(self, LAP_STANDBY);
  387. /* In some case, at this point our side has already closed
  388. * all lsaps, and we are waiting for the idle_timer to
  389. * expire. If another device reconnect immediately, the
  390. * idle timer will expire in the midle of the connection
  391. * initialisation, screwing up things a lot...
  392. * Therefore, we must stop the timer... */
  393. irlmp_stop_idle_timer(self);
  394. /*
  395. * Inform all connected LSAP's using this link
  396. */
  397. irlmp_do_all_lsap_event(self->lsaps,
  398. LM_LAP_DISCONNECT_INDICATION);
  399. /* Force an expiry of the discovery log.
  400. * Now that the LAP is free, the system may attempt to
  401. * connect to another device. Unfortunately, our entries
  402. * are stale. There is a small window (<3s) before the
  403. * normal discovery will run and where irlmp_connect_request()
  404. * can get the wrong info, so make sure things get
  405. * cleaned *NOW* ;-) - Jean II */
  406. irlmp_do_expiry();
  407. break;
  408. default:
  409. IRDA_DEBUG(0, "%s(), Unknown event %s\n",
  410. __FUNCTION__, irlmp_event[event]);
  411. break;
  412. }
  413. }
  414. /*********************************************************************
  415. *
  416. * LSAP connection control states
  417. *
  418. ********************************************************************/
  419. /*
  420. * Function irlmp_state_disconnected (event, skb, info)
  421. *
  422. * DISCONNECTED
  423. *
  424. */
  425. static int irlmp_state_disconnected(struct lsap_cb *self, IRLMP_EVENT event,
  426. struct sk_buff *skb)
  427. {
  428. int ret = 0;
  429. IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
  430. IRDA_ASSERT(self != NULL, return -1;);
  431. IRDA_ASSERT(self->magic == LMP_LSAP_MAGIC, return -1;);
  432. switch (event) {
  433. #ifdef CONFIG_IRDA_ULTRA
  434. case LM_UDATA_INDICATION:
  435. /* This is most bizzare. Those packets are aka unreliable
  436. * connected, aka IrLPT or SOCK_DGRAM/IRDAPROTO_UNITDATA.
  437. * Why do we pass them as Ultra ??? Jean II */
  438. irlmp_connless_data_indication(self, skb);
  439. break;
  440. #endif /* CONFIG_IRDA_ULTRA */
  441. case LM_CONNECT_REQUEST:
  442. IRDA_DEBUG(4, "%s(), LM_CONNECT_REQUEST\n", __FUNCTION__);
  443. if (self->conn_skb) {
  444. IRDA_WARNING("%s: busy with another request!\n",
  445. __FUNCTION__);
  446. return -EBUSY;
  447. }
  448. /* Don't forget to refcount it (see irlmp_connect_request()) */
  449. skb_get(skb);
  450. self->conn_skb = skb;
  451. irlmp_next_lsap_state(self, LSAP_SETUP_PEND);
  452. /* Start watchdog timer (5 secs for now) */
  453. irlmp_start_watchdog_timer(self, 5*HZ);
  454. irlmp_do_lap_event(self->lap, LM_LAP_CONNECT_REQUEST, NULL);
  455. break;
  456. case LM_CONNECT_INDICATION:
  457. if (self->conn_skb) {
  458. IRDA_WARNING("%s: busy with another request!\n",
  459. __FUNCTION__);
  460. return -EBUSY;
  461. }
  462. /* Don't forget to refcount it (see irlap_driver_rcv()) */
  463. skb_get(skb);
  464. self->conn_skb = skb;
  465. irlmp_next_lsap_state(self, LSAP_CONNECT_PEND);
  466. /* Start watchdog timer
  467. * This is not mentionned in the spec, but there is a rare
  468. * race condition that can get the socket stuck.
  469. * If we receive this event while our LAP is closing down,
  470. * the LM_LAP_CONNECT_REQUEST get lost and we get stuck in
  471. * CONNECT_PEND state forever.
  472. * The other cause of getting stuck down there is if the
  473. * higher layer never reply to the CONNECT_INDICATION.
  474. * Anyway, it make sense to make sure that we always have
  475. * a backup plan. 1 second is plenty (should be immediate).
  476. * Jean II */
  477. irlmp_start_watchdog_timer(self, 1*HZ);
  478. irlmp_do_lap_event(self->lap, LM_LAP_CONNECT_REQUEST, NULL);
  479. break;
  480. default:
  481. IRDA_DEBUG(1, "%s(), Unknown event %s on LSAP %#02x\n",
  482. __FUNCTION__, irlmp_event[event], self->slsap_sel);
  483. break;
  484. }
  485. return ret;
  486. }
  487. /*
  488. * Function irlmp_state_connect (self, event, skb)
  489. *
  490. * CONNECT
  491. *
  492. */
  493. static int irlmp_state_connect(struct lsap_cb *self, IRLMP_EVENT event,
  494. struct sk_buff *skb)
  495. {
  496. struct lsap_cb *lsap;
  497. int ret = 0;
  498. IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
  499. IRDA_ASSERT(self != NULL, return -1;);
  500. IRDA_ASSERT(self->magic == LMP_LSAP_MAGIC, return -1;);
  501. switch (event) {
  502. case LM_CONNECT_RESPONSE:
  503. /*
  504. * Bind this LSAP to the IrLAP link where the connect was
  505. * received
  506. */
  507. lsap = hashbin_remove(irlmp->unconnected_lsaps, (long) self,
  508. NULL);
  509. IRDA_ASSERT(lsap == self, return -1;);
  510. IRDA_ASSERT(self->lap != NULL, return -1;);
  511. IRDA_ASSERT(self->lap->lsaps != NULL, return -1;);
  512. hashbin_insert(self->lap->lsaps, (irda_queue_t *) self,
  513. (long) self, NULL);
  514. set_bit(0, &self->connected); /* TRUE */
  515. irlmp_send_lcf_pdu(self->lap, self->dlsap_sel,
  516. self->slsap_sel, CONNECT_CNF, skb);
  517. del_timer(&self->watchdog_timer);
  518. irlmp_next_lsap_state(self, LSAP_DATA_TRANSFER_READY);
  519. break;
  520. case LM_WATCHDOG_TIMEOUT:
  521. /* May happen, who knows...
  522. * Jean II */
  523. IRDA_DEBUG(0, "%s() WATCHDOG_TIMEOUT!\n", __FUNCTION__);
  524. /* Disconnect, get out... - Jean II */
  525. self->lap = NULL;
  526. self->dlsap_sel = LSAP_ANY;
  527. irlmp_next_lsap_state(self, LSAP_DISCONNECTED);
  528. break;
  529. default:
  530. /* LM_LAP_DISCONNECT_INDICATION : Should never happen, we
  531. * are *not* yet bound to the IrLAP link. Jean II */
  532. IRDA_DEBUG(0, "%s(), Unknown event %s on LSAP %#02x\n",
  533. __FUNCTION__, irlmp_event[event], self->slsap_sel);
  534. break;
  535. }
  536. return ret;
  537. }
  538. /*
  539. * Function irlmp_state_connect_pend (event, skb, info)
  540. *
  541. * CONNECT_PEND
  542. *
  543. */
  544. static int irlmp_state_connect_pend(struct lsap_cb *self, IRLMP_EVENT event,
  545. struct sk_buff *skb)
  546. {
  547. struct sk_buff *tx_skb;
  548. int ret = 0;
  549. IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
  550. IRDA_ASSERT(self != NULL, return -1;);
  551. IRDA_ASSERT(self->magic == LMP_LSAP_MAGIC, return -1;);
  552. switch (event) {
  553. case LM_CONNECT_REQUEST:
  554. /* Keep state */
  555. break;
  556. case LM_CONNECT_RESPONSE:
  557. IRDA_DEBUG(0, "%s(), LM_CONNECT_RESPONSE, "
  558. "no indication issued yet\n", __FUNCTION__);
  559. /* Keep state */
  560. break;
  561. case LM_DISCONNECT_REQUEST:
  562. IRDA_DEBUG(0, "%s(), LM_DISCONNECT_REQUEST, "
  563. "not yet bound to IrLAP connection\n", __FUNCTION__);
  564. /* Keep state */
  565. break;
  566. case LM_LAP_CONNECT_CONFIRM:
  567. IRDA_DEBUG(4, "%s(), LS_CONNECT_CONFIRM\n", __FUNCTION__);
  568. irlmp_next_lsap_state(self, LSAP_CONNECT);
  569. tx_skb = self->conn_skb;
  570. self->conn_skb = NULL;
  571. irlmp_connect_indication(self, tx_skb);
  572. /* Drop reference count - see irlmp_connect_indication(). */
  573. dev_kfree_skb(tx_skb);
  574. break;
  575. case LM_WATCHDOG_TIMEOUT:
  576. /* Will happen in some rare cases because of a race condition.
  577. * Just make sure we don't stay there forever...
  578. * Jean II */
  579. IRDA_DEBUG(0, "%s() WATCHDOG_TIMEOUT!\n", __FUNCTION__);
  580. /* Go back to disconnected mode, keep the socket waiting */
  581. self->lap = NULL;
  582. self->dlsap_sel = LSAP_ANY;
  583. if(self->conn_skb)
  584. dev_kfree_skb(self->conn_skb);
  585. self->conn_skb = NULL;
  586. irlmp_next_lsap_state(self, LSAP_DISCONNECTED);
  587. break;
  588. default:
  589. /* LM_LAP_DISCONNECT_INDICATION : Should never happen, we
  590. * are *not* yet bound to the IrLAP link. Jean II */
  591. IRDA_DEBUG(0, "%s(), Unknown event %s on LSAP %#02x\n",
  592. __FUNCTION__, irlmp_event[event], self->slsap_sel);
  593. break;
  594. }
  595. return ret;
  596. }
  597. /*
  598. * Function irlmp_state_dtr (self, event, skb)
  599. *
  600. * DATA_TRANSFER_READY
  601. *
  602. */
  603. static int irlmp_state_dtr(struct lsap_cb *self, IRLMP_EVENT event,
  604. struct sk_buff *skb)
  605. {
  606. LM_REASON reason;
  607. int ret = 0;
  608. IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
  609. IRDA_ASSERT(self != NULL, return -1;);
  610. IRDA_ASSERT(self->magic == LMP_LSAP_MAGIC, return -1;);
  611. IRDA_ASSERT(self->lap != NULL, return -1;);
  612. switch (event) {
  613. case LM_DATA_REQUEST: /* Optimize for the common case */
  614. irlmp_send_data_pdu(self->lap, self->dlsap_sel,
  615. self->slsap_sel, FALSE, skb);
  616. break;
  617. case LM_DATA_INDICATION: /* Optimize for the common case */
  618. irlmp_data_indication(self, skb);
  619. break;
  620. case LM_UDATA_REQUEST:
  621. IRDA_ASSERT(skb != NULL, return -1;);
  622. irlmp_send_data_pdu(self->lap, self->dlsap_sel,
  623. self->slsap_sel, TRUE, skb);
  624. break;
  625. case LM_UDATA_INDICATION:
  626. irlmp_udata_indication(self, skb);
  627. break;
  628. case LM_CONNECT_REQUEST:
  629. IRDA_DEBUG(0, "%s(), LM_CONNECT_REQUEST, "
  630. "error, LSAP already connected\n", __FUNCTION__);
  631. /* Keep state */
  632. break;
  633. case LM_CONNECT_RESPONSE:
  634. IRDA_DEBUG(0, "%s(), LM_CONNECT_RESPONSE, "
  635. "error, LSAP already connected\n", __FUNCTION__);
  636. /* Keep state */
  637. break;
  638. case LM_DISCONNECT_REQUEST:
  639. irlmp_send_lcf_pdu(self->lap, self->dlsap_sel, self->slsap_sel,
  640. DISCONNECT, skb);
  641. irlmp_next_lsap_state(self, LSAP_DISCONNECTED);
  642. /* Called only from irlmp_disconnect_request(), will
  643. * unbind from LAP over there. Jean II */
  644. /* Try to close the LAP connection if its still there */
  645. if (self->lap) {
  646. IRDA_DEBUG(4, "%s(), trying to close IrLAP\n",
  647. __FUNCTION__);
  648. irlmp_do_lap_event(self->lap,
  649. LM_LAP_DISCONNECT_REQUEST,
  650. NULL);
  651. }
  652. break;
  653. case LM_LAP_DISCONNECT_INDICATION:
  654. irlmp_next_lsap_state(self, LSAP_DISCONNECTED);
  655. reason = irlmp_convert_lap_reason(self->lap->reason);
  656. irlmp_disconnect_indication(self, reason, NULL);
  657. break;
  658. case LM_DISCONNECT_INDICATION:
  659. irlmp_next_lsap_state(self, LSAP_DISCONNECTED);
  660. IRDA_ASSERT(self->lap != NULL, return -1;);
  661. IRDA_ASSERT(self->lap->magic == LMP_LAP_MAGIC, return -1;);
  662. IRDA_ASSERT(skb != NULL, return -1;);
  663. IRDA_ASSERT(skb->len > 3, return -1;);
  664. reason = skb->data[3];
  665. /* Try to close the LAP connection */
  666. IRDA_DEBUG(4, "%s(), trying to close IrLAP\n", __FUNCTION__);
  667. irlmp_do_lap_event(self->lap, LM_LAP_DISCONNECT_REQUEST, NULL);
  668. irlmp_disconnect_indication(self, reason, skb);
  669. break;
  670. default:
  671. IRDA_DEBUG(0, "%s(), Unknown event %s on LSAP %#02x\n",
  672. __FUNCTION__, irlmp_event[event], self->slsap_sel);
  673. break;
  674. }
  675. return ret;
  676. }
  677. /*
  678. * Function irlmp_state_setup (event, skb, info)
  679. *
  680. * SETUP, Station Control has set up the underlying IrLAP connection.
  681. * An LSAP connection request has been transmitted to the peer
  682. * LSAP-Connection Control FSM and we are awaiting reply.
  683. */
  684. static int irlmp_state_setup(struct lsap_cb *self, IRLMP_EVENT event,
  685. struct sk_buff *skb)
  686. {
  687. LM_REASON reason;
  688. int ret = 0;
  689. IRDA_ASSERT(self != NULL, return -1;);
  690. IRDA_ASSERT(self->magic == LMP_LSAP_MAGIC, return -1;);
  691. IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
  692. switch (event) {
  693. case LM_CONNECT_CONFIRM:
  694. irlmp_next_lsap_state(self, LSAP_DATA_TRANSFER_READY);
  695. del_timer(&self->watchdog_timer);
  696. irlmp_connect_confirm(self, skb);
  697. break;
  698. case LM_DISCONNECT_INDICATION:
  699. irlmp_next_lsap_state(self, LSAP_DISCONNECTED);
  700. IRDA_ASSERT(self->lap != NULL, return -1;);
  701. IRDA_ASSERT(self->lap->magic == LMP_LAP_MAGIC, return -1;);
  702. IRDA_ASSERT(skb != NULL, return -1;);
  703. IRDA_ASSERT(skb->len > 3, return -1;);
  704. reason = skb->data[3];
  705. /* Try to close the LAP connection */
  706. IRDA_DEBUG(4, "%s(), trying to close IrLAP\n", __FUNCTION__);
  707. irlmp_do_lap_event(self->lap, LM_LAP_DISCONNECT_REQUEST, NULL);
  708. irlmp_disconnect_indication(self, reason, skb);
  709. break;
  710. case LM_LAP_DISCONNECT_INDICATION:
  711. irlmp_next_lsap_state(self, LSAP_DISCONNECTED);
  712. del_timer(&self->watchdog_timer);
  713. IRDA_ASSERT(self->lap != NULL, return -1;);
  714. IRDA_ASSERT(self->lap->magic == LMP_LAP_MAGIC, return -1;);
  715. reason = irlmp_convert_lap_reason(self->lap->reason);
  716. irlmp_disconnect_indication(self, reason, skb);
  717. break;
  718. case LM_WATCHDOG_TIMEOUT:
  719. IRDA_DEBUG(0, "%s() WATCHDOG_TIMEOUT!\n", __FUNCTION__);
  720. IRDA_ASSERT(self->lap != NULL, return -1;);
  721. irlmp_do_lap_event(self->lap, LM_LAP_DISCONNECT_REQUEST, NULL);
  722. irlmp_next_lsap_state(self, LSAP_DISCONNECTED);
  723. irlmp_disconnect_indication(self, LM_CONNECT_FAILURE, NULL);
  724. break;
  725. default:
  726. IRDA_DEBUG(0, "%s(), Unknown event %s on LSAP %#02x\n",
  727. __FUNCTION__, irlmp_event[event], self->slsap_sel);
  728. break;
  729. }
  730. return ret;
  731. }
  732. /*
  733. * Function irlmp_state_setup_pend (event, skb, info)
  734. *
  735. * SETUP_PEND, An LM_CONNECT_REQUEST has been received from the service
  736. * user to set up an LSAP connection. A request has been sent to the
  737. * LAP FSM to set up the underlying IrLAP connection, and we
  738. * are awaiting confirm.
  739. */
  740. static int irlmp_state_setup_pend(struct lsap_cb *self, IRLMP_EVENT event,
  741. struct sk_buff *skb)
  742. {
  743. struct sk_buff *tx_skb;
  744. LM_REASON reason;
  745. int ret = 0;
  746. IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
  747. IRDA_ASSERT(self != NULL, return -1;);
  748. IRDA_ASSERT(irlmp != NULL, return -1;);
  749. switch (event) {
  750. case LM_LAP_CONNECT_CONFIRM:
  751. IRDA_ASSERT(self->conn_skb != NULL, return -1;);
  752. tx_skb = self->conn_skb;
  753. self->conn_skb = NULL;
  754. irlmp_send_lcf_pdu(self->lap, self->dlsap_sel,
  755. self->slsap_sel, CONNECT_CMD, tx_skb);
  756. /* Drop reference count - see irlap_data_request(). */
  757. dev_kfree_skb(tx_skb);
  758. irlmp_next_lsap_state(self, LSAP_SETUP);
  759. break;
  760. case LM_WATCHDOG_TIMEOUT:
  761. IRDA_DEBUG(0, "%s() : WATCHDOG_TIMEOUT !\n", __FUNCTION__);
  762. IRDA_ASSERT(self->lap != NULL, return -1;);
  763. irlmp_do_lap_event(self->lap, LM_LAP_DISCONNECT_REQUEST, NULL);
  764. irlmp_next_lsap_state(self, LSAP_DISCONNECTED);
  765. irlmp_disconnect_indication(self, LM_CONNECT_FAILURE, NULL);
  766. break;
  767. case LM_LAP_DISCONNECT_INDICATION: /* LS_Disconnect.indication */
  768. del_timer( &self->watchdog_timer);
  769. irlmp_next_lsap_state(self, LSAP_DISCONNECTED);
  770. reason = irlmp_convert_lap_reason(self->lap->reason);
  771. irlmp_disconnect_indication(self, reason, NULL);
  772. break;
  773. default:
  774. IRDA_DEBUG(0, "%s(), Unknown event %s on LSAP %#02x\n",
  775. __FUNCTION__, irlmp_event[event], self->slsap_sel);
  776. break;
  777. }
  778. return ret;
  779. }