irlmp_event.c 26 KB

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