irlmp_event.c 25 KB

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