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