irlmp_event.c 26 KB

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