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 /* FIXME: need to set users requested QoS */ 284 irlap_connect_request(self->irlap, self->daddr, NULL, 0); 285 break; 286 case LM_LAP_DISCONNECT_INDICATION: 287 IRDA_DEBUG(4, "%s(), Error LM_LAP_DISCONNECT_INDICATION\n", 288 __func__); 289 290 irlmp_next_lap_state(self, LAP_STANDBY); 291 break; 292 default: 293 IRDA_DEBUG(0, "%s(), Unknown event %s\n", 294 __func__, irlmp_event[event]); 295 break; 296 } 297} 298 299/* 300 * Function irlmp_state_u_connect (event, skb, info) 301 * 302 * U_CONNECT, The layer above has tried to open an LSAP connection but 303 * since the IrLAP connection does not exist, we must first start an 304 * IrLAP connection. We are now waiting response from IrLAP. 305 * */ 306static void irlmp_state_u_connect(struct lap_cb *self, IRLMP_EVENT event, 307 struct sk_buff *skb) 308{ 309 IRDA_DEBUG(2, "%s(), event=%s\n", __func__, irlmp_event[event]); 310 311 switch (event) { 312 case LM_LAP_CONNECT_INDICATION: 313 /* It's important to switch state first, to avoid IrLMP to 314 * think that the link is free since IrLMP may then start 315 * discovery before the connection is properly set up. DB. 316 */ 317 irlmp_next_lap_state(self, LAP_ACTIVE); 318 319 /* Just accept connection TODO, this should be fixed */ 320 irlap_connect_response(self->irlap, skb); 321 322 /* Tell LSAPs that they can start sending data */ 323 irlmp_do_all_lsap_event(self->lsaps, LM_LAP_CONNECT_CONFIRM); 324 325 /* Note : by the time we get there (LAP retries and co), 326 * the lsaps may already have gone. This avoid getting stuck 327 * forever in LAP_ACTIVE state - Jean II */ 328 if (HASHBIN_GET_SIZE(self->lsaps) == 0) { 329 IRDA_DEBUG(0, "%s() NO LSAPs !\n", __func__); 330 irlmp_start_idle_timer(self, LM_IDLE_TIMEOUT); 331 } 332 break; 333 case LM_LAP_CONNECT_REQUEST: 334 /* Already trying to connect */ 335 break; 336 case LM_LAP_CONNECT_CONFIRM: 337 /* For all lsap_ce E Associated do LS_Connect_confirm */ 338 irlmp_next_lap_state(self, LAP_ACTIVE); 339 340 /* Tell LSAPs that they can start sending data */ 341 irlmp_do_all_lsap_event(self->lsaps, LM_LAP_CONNECT_CONFIRM); 342 343 /* Note : by the time we get there (LAP retries and co), 344 * the lsaps may already have gone. This avoid getting stuck 345 * forever in LAP_ACTIVE state - Jean II */ 346 if (HASHBIN_GET_SIZE(self->lsaps) == 0) { 347 IRDA_DEBUG(0, "%s() NO LSAPs !\n", __func__); 348 irlmp_start_idle_timer(self, LM_IDLE_TIMEOUT); 349 } 350 break; 351 case LM_LAP_DISCONNECT_INDICATION: 352 IRDA_DEBUG(4, "%s(), LM_LAP_DISCONNECT_INDICATION\n", __func__); 353 irlmp_next_lap_state(self, LAP_STANDBY); 354 355 /* Send disconnect event to all LSAPs using this link */ 356 irlmp_do_all_lsap_event(self->lsaps, 357 LM_LAP_DISCONNECT_INDICATION); 358 break; 359 case LM_LAP_DISCONNECT_REQUEST: 360 IRDA_DEBUG(4, "%s(), LM_LAP_DISCONNECT_REQUEST\n", __func__); 361 362 /* One of the LSAP did timeout or was closed, if it was 363 * the last one, try to get out of here - Jean II */ 364 if (HASHBIN_GET_SIZE(self->lsaps) <= 1) { 365 irlap_disconnect_request(self->irlap); 366 } 367 break; 368 default: 369 IRDA_DEBUG(0, "%s(), Unknown event %s\n", 370 __func__, irlmp_event[event]); 371 break; 372 } 373} 374 375/* 376 * Function irlmp_state_active (event, skb, info) 377 * 378 * ACTIVE, IrLAP connection is active 379 * 380 */ 381static void irlmp_state_active(struct lap_cb *self, IRLMP_EVENT event, 382 struct sk_buff *skb) 383{ 384 IRDA_DEBUG(4, "%s()\n", __func__); 385 386 switch (event) { 387 case LM_LAP_CONNECT_REQUEST: 388 IRDA_DEBUG(4, "%s(), LS_CONNECT_REQUEST\n", __func__); 389 390 /* 391 * IrLAP may have a pending disconnect. We tried to close 392 * IrLAP, but it was postponed because the link was 393 * busy or we were still sending packets. As we now 394 * need it, make sure it stays on. Jean II 395 */ 396 irlap_clear_disconnect(self->irlap); 397 398 /* 399 * LAP connection already active, just bounce back! Since we 400 * don't know which LSAP that tried to do this, we have to 401 * notify all LSAPs using this LAP, but that should be safe to 402 * do anyway. 403 */ 404 irlmp_do_all_lsap_event(self->lsaps, LM_LAP_CONNECT_CONFIRM); 405 406 /* Needed by connect indication */ 407 irlmp_do_all_lsap_event(irlmp->unconnected_lsaps, 408 LM_LAP_CONNECT_CONFIRM); 409 /* Keep state */ 410 break; 411 case LM_LAP_DISCONNECT_REQUEST: 412 /* 413 * Need to find out if we should close IrLAP or not. If there 414 * is only one LSAP connection left on this link, that LSAP 415 * must be the one that tries to close IrLAP. It will be 416 * removed later and moved to the list of unconnected LSAPs 417 */ 418 if (HASHBIN_GET_SIZE(self->lsaps) > 0) { 419 /* Timer value is checked in irsysctl - Jean II */ 420 irlmp_start_idle_timer(self, sysctl_lap_keepalive_time * HZ / 1000); 421 } else { 422 /* No more connections, so close IrLAP */ 423 424 /* We don't want to change state just yet, because 425 * we want to reflect accurately the real state of 426 * the LAP, not the state we wish it was in, 427 * so that we don't lose LM_LAP_CONNECT_REQUEST. 428 * In some cases, IrLAP won't close the LAP 429 * immediately. For example, it might still be 430 * retrying packets or waiting for the pf bit. 431 * As the LAP always send a DISCONNECT_INDICATION 432 * in PCLOSE or SCLOSE, just change state on that. 433 * Jean II */ 434 irlap_disconnect_request(self->irlap); 435 } 436 break; 437 case LM_LAP_IDLE_TIMEOUT: 438 if (HASHBIN_GET_SIZE(self->lsaps) == 0) { 439 /* Same reasoning as above - keep state */ 440 irlap_disconnect_request(self->irlap); 441 } 442 break; 443 case LM_LAP_DISCONNECT_INDICATION: 444 irlmp_next_lap_state(self, LAP_STANDBY); 445 446 /* In some case, at this point our side has already closed 447 * all lsaps, and we are waiting for the idle_timer to 448 * expire. If another device reconnect immediately, the 449 * idle timer will expire in the midle of the connection 450 * initialisation, screwing up things a lot... 451 * Therefore, we must stop the timer... */ 452 irlmp_stop_idle_timer(self); 453 454 /* 455 * Inform all connected LSAP's using this link 456 */ 457 irlmp_do_all_lsap_event(self->lsaps, 458 LM_LAP_DISCONNECT_INDICATION); 459 460 /* Force an expiry of the discovery log. 461 * Now that the LAP is free, the system may attempt to 462 * connect to another device. Unfortunately, our entries 463 * are stale. There is a small window (<3s) before the 464 * normal discovery will run and where irlmp_connect_request() 465 * can get the wrong info, so make sure things get 466 * cleaned *NOW* ;-) - Jean II */ 467 irlmp_do_expiry(); 468 break; 469 default: 470 IRDA_DEBUG(0, "%s(), Unknown event %s\n", 471 __func__, irlmp_event[event]); 472 break; 473 } 474} 475 476/********************************************************************* 477 * 478 * LSAP connection control states 479 * 480 ********************************************************************/ 481 482/* 483 * Function irlmp_state_disconnected (event, skb, info) 484 * 485 * DISCONNECTED 486 * 487 */ 488static int irlmp_state_disconnected(struct lsap_cb *self, IRLMP_EVENT event, 489 struct sk_buff *skb) 490{ 491 int ret = 0; 492 493 IRDA_DEBUG(4, "%s()\n", __func__); 494 495 IRDA_ASSERT(self != NULL, return -1;); 496 IRDA_ASSERT(self->magic == LMP_LSAP_MAGIC, return -1;); 497 498 switch (event) { 499#ifdef CONFIG_IRDA_ULTRA 500 case LM_UDATA_INDICATION: 501 /* This is most bizarre. Those packets are aka unreliable 502 * connected, aka IrLPT or SOCK_DGRAM/IRDAPROTO_UNITDATA. 503 * Why do we pass them as Ultra ??? Jean II */ 504 irlmp_connless_data_indication(self, skb); 505 break; 506#endif /* CONFIG_IRDA_ULTRA */ 507 case LM_CONNECT_REQUEST: 508 IRDA_DEBUG(4, "%s(), LM_CONNECT_REQUEST\n", __func__); 509 510 if (self->conn_skb) { 511 IRDA_WARNING("%s: busy with another request!\n", 512 __func__); 513 return -EBUSY; 514 } 515 /* Don't forget to refcount it (see irlmp_connect_request()) */ 516 skb_get(skb); 517 self->conn_skb = skb; 518 519 irlmp_next_lsap_state(self, LSAP_SETUP_PEND); 520 521 /* Start watchdog timer (5 secs for now) */ 522 irlmp_start_watchdog_timer(self, 5*HZ); 523 524 irlmp_do_lap_event(self->lap, LM_LAP_CONNECT_REQUEST, NULL); 525 break; 526 case LM_CONNECT_INDICATION: 527 if (self->conn_skb) { 528 IRDA_WARNING("%s: busy with another request!\n", 529 __func__); 530 return -EBUSY; 531 } 532 /* Don't forget to refcount it (see irlap_driver_rcv()) */ 533 skb_get(skb); 534 self->conn_skb = skb; 535 536 irlmp_next_lsap_state(self, LSAP_CONNECT_PEND); 537 538 /* Start watchdog timer 539 * This is not mentionned in the spec, but there is a rare 540 * race condition that can get the socket stuck. 541 * If we receive this event while our LAP is closing down, 542 * the LM_LAP_CONNECT_REQUEST get lost and we get stuck in 543 * CONNECT_PEND state forever. 544 * The other cause of getting stuck down there is if the 545 * higher layer never reply to the CONNECT_INDICATION. 546 * Anyway, it make sense to make sure that we always have 547 * a backup plan. 1 second is plenty (should be immediate). 548 * Jean II */ 549 irlmp_start_watchdog_timer(self, 1*HZ); 550 551 irlmp_do_lap_event(self->lap, LM_LAP_CONNECT_REQUEST, NULL); 552 break; 553 default: 554 IRDA_DEBUG(1, "%s(), Unknown event %s on LSAP %#02x\n", 555 __func__, irlmp_event[event], self->slsap_sel); 556 break; 557 } 558 return ret; 559} 560 561/* 562 * Function irlmp_state_connect (self, event, skb) 563 * 564 * CONNECT 565 * 566 */ 567static int irlmp_state_connect(struct lsap_cb *self, IRLMP_EVENT event, 568 struct sk_buff *skb) 569{ 570 struct lsap_cb *lsap; 571 int ret = 0; 572 573 IRDA_DEBUG(4, "%s()\n", __func__); 574 575 IRDA_ASSERT(self != NULL, return -1;); 576 IRDA_ASSERT(self->magic == LMP_LSAP_MAGIC, return -1;); 577 578 switch (event) { 579 case LM_CONNECT_RESPONSE: 580 /* 581 * Bind this LSAP to the IrLAP link where the connect was 582 * received 583 */ 584 lsap = hashbin_remove(irlmp->unconnected_lsaps, (long) self, 585 NULL); 586 587 IRDA_ASSERT(lsap == self, return -1;); 588 IRDA_ASSERT(self->lap != NULL, return -1;); 589 IRDA_ASSERT(self->lap->lsaps != NULL, return -1;); 590 591 hashbin_insert(self->lap->lsaps, (irda_queue_t *) self, 592 (long) self, NULL); 593 594 set_bit(0, &self->connected); /* TRUE */ 595 596 irlmp_send_lcf_pdu(self->lap, self->dlsap_sel, 597 self->slsap_sel, CONNECT_CNF, skb); 598 599 del_timer(&self->watchdog_timer); 600 601 irlmp_next_lsap_state(self, LSAP_DATA_TRANSFER_READY); 602 break; 603 case LM_WATCHDOG_TIMEOUT: 604 /* May happen, who knows... 605 * Jean II */ 606 IRDA_DEBUG(0, "%s() WATCHDOG_TIMEOUT!\n", __func__); 607 608 /* Disconnect, get out... - Jean II */ 609 self->lap = NULL; 610 self->dlsap_sel = LSAP_ANY; 611 irlmp_next_lsap_state(self, LSAP_DISCONNECTED); 612 break; 613 default: 614 /* LM_LAP_DISCONNECT_INDICATION : Should never happen, we 615 * are *not* yet bound to the IrLAP link. Jean II */ 616 IRDA_DEBUG(0, "%s(), Unknown event %s on LSAP %#02x\n", 617 __func__, irlmp_event[event], self->slsap_sel); 618 break; 619 } 620 return ret; 621} 622 623/* 624 * Function irlmp_state_connect_pend (event, skb, info) 625 * 626 * CONNECT_PEND 627 * 628 */ 629static int irlmp_state_connect_pend(struct lsap_cb *self, IRLMP_EVENT event, 630 struct sk_buff *skb) 631{ 632 struct sk_buff *tx_skb; 633 int ret = 0; 634 635 IRDA_DEBUG(4, "%s()\n", __func__); 636 637 IRDA_ASSERT(self != NULL, return -1;); 638 IRDA_ASSERT(self->magic == LMP_LSAP_MAGIC, return -1;); 639 640 switch (event) { 641 case LM_CONNECT_REQUEST: 642 /* Keep state */ 643 break; 644 case LM_CONNECT_RESPONSE: 645 IRDA_DEBUG(0, "%s(), LM_CONNECT_RESPONSE, " 646 "no indication issued yet\n", __func__); 647 /* Keep state */ 648 break; 649 case LM_DISCONNECT_REQUEST: 650 IRDA_DEBUG(0, "%s(), LM_DISCONNECT_REQUEST, " 651 "not yet bound to IrLAP connection\n", __func__); 652 /* Keep state */ 653 break; 654 case LM_LAP_CONNECT_CONFIRM: 655 IRDA_DEBUG(4, "%s(), LS_CONNECT_CONFIRM\n", __func__); 656 irlmp_next_lsap_state(self, LSAP_CONNECT); 657 658 tx_skb = self->conn_skb; 659 self->conn_skb = NULL; 660 661 irlmp_connect_indication(self, tx_skb); 662 /* Drop reference count - see irlmp_connect_indication(). */ 663 dev_kfree_skb(tx_skb); 664 break; 665 case LM_WATCHDOG_TIMEOUT: 666 /* Will happen in some rare cases because of a race condition. 667 * Just make sure we don't stay there forever... 668 * Jean II */ 669 IRDA_DEBUG(0, "%s() WATCHDOG_TIMEOUT!\n", __func__); 670 671 /* Go back to disconnected mode, keep the socket waiting */ 672 self->lap = NULL; 673 self->dlsap_sel = LSAP_ANY; 674 if(self->conn_skb) 675 dev_kfree_skb(self->conn_skb); 676 self->conn_skb = NULL; 677 irlmp_next_lsap_state(self, LSAP_DISCONNECTED); 678 break; 679 default: 680 /* LM_LAP_DISCONNECT_INDICATION : Should never happen, we 681 * are *not* yet bound to the IrLAP link. Jean II */ 682 IRDA_DEBUG(0, "%s(), Unknown event %s on LSAP %#02x\n", 683 __func__, irlmp_event[event], self->slsap_sel); 684 break; 685 } 686 return ret; 687} 688 689/* 690 * Function irlmp_state_dtr (self, event, skb) 691 * 692 * DATA_TRANSFER_READY 693 * 694 */ 695static int irlmp_state_dtr(struct lsap_cb *self, IRLMP_EVENT event, 696 struct sk_buff *skb) 697{ 698 LM_REASON reason; 699 int ret = 0; 700 701 IRDA_DEBUG(4, "%s()\n", __func__); 702 703 IRDA_ASSERT(self != NULL, return -1;); 704 IRDA_ASSERT(self->magic == LMP_LSAP_MAGIC, return -1;); 705 IRDA_ASSERT(self->lap != NULL, return -1;); 706 707 switch (event) { 708 case LM_DATA_REQUEST: /* Optimize for the common case */ 709 irlmp_send_data_pdu(self->lap, self->dlsap_sel, 710 self->slsap_sel, FALSE, skb); 711 break; 712 case LM_DATA_INDICATION: /* Optimize for the common case */ 713 irlmp_data_indication(self, skb); 714 break; 715 case LM_UDATA_REQUEST: 716 IRDA_ASSERT(skb != NULL, return -1;); 717 irlmp_send_data_pdu(self->lap, self->dlsap_sel, 718 self->slsap_sel, TRUE, skb); 719 break; 720 case LM_UDATA_INDICATION: 721 irlmp_udata_indication(self, skb); 722 break; 723 case LM_CONNECT_REQUEST: 724 IRDA_DEBUG(0, "%s(), LM_CONNECT_REQUEST, " 725 "error, LSAP already connected\n", __func__); 726 /* Keep state */ 727 break; 728 case LM_CONNECT_RESPONSE: 729 IRDA_DEBUG(0, "%s(), LM_CONNECT_RESPONSE, " 730 "error, LSAP already connected\n", __func__); 731 /* Keep state */ 732 break; 733 case LM_DISCONNECT_REQUEST: 734 irlmp_send_lcf_pdu(self->lap, self->dlsap_sel, self->slsap_sel, 735 DISCONNECT, skb); 736 irlmp_next_lsap_state(self, LSAP_DISCONNECTED); 737 /* Called only from irlmp_disconnect_request(), will 738 * unbind from LAP over there. Jean II */ 739 740 /* Try to close the LAP connection if its still there */ 741 if (self->lap) { 742 IRDA_DEBUG(4, "%s(), trying to close IrLAP\n", 743 __func__); 744 irlmp_do_lap_event(self->lap, 745 LM_LAP_DISCONNECT_REQUEST, 746 NULL); 747 } 748 break; 749 case LM_LAP_DISCONNECT_INDICATION: 750 irlmp_next_lsap_state(self, LSAP_DISCONNECTED); 751 752 reason = irlmp_convert_lap_reason(self->lap->reason); 753 754 irlmp_disconnect_indication(self, reason, NULL); 755 break; 756 case LM_DISCONNECT_INDICATION: 757 irlmp_next_lsap_state(self, LSAP_DISCONNECTED); 758 759 IRDA_ASSERT(self->lap != NULL, return -1;); 760 IRDA_ASSERT(self->lap->magic == LMP_LAP_MAGIC, return -1;); 761 762 IRDA_ASSERT(skb != NULL, return -1;); 763 IRDA_ASSERT(skb->len > 3, return -1;); 764 reason = skb->data[3]; 765 766 /* Try to close the LAP connection */ 767 IRDA_DEBUG(4, "%s(), trying to close IrLAP\n", __func__); 768 irlmp_do_lap_event(self->lap, LM_LAP_DISCONNECT_REQUEST, NULL); 769 770 irlmp_disconnect_indication(self, reason, skb); 771 break; 772 default: 773 IRDA_DEBUG(0, "%s(), Unknown event %s on LSAP %#02x\n", 774 __func__, irlmp_event[event], self->slsap_sel); 775 break; 776 } 777 return ret; 778} 779 780/* 781 * Function irlmp_state_setup (event, skb, info) 782 * 783 * SETUP, Station Control has set up the underlying IrLAP connection. 784 * An LSAP connection request has been transmitted to the peer 785 * LSAP-Connection Control FSM and we are awaiting reply. 786 */ 787static int irlmp_state_setup(struct lsap_cb *self, IRLMP_EVENT event, 788 struct sk_buff *skb) 789{ 790 LM_REASON reason; 791 int ret = 0; 792 793 IRDA_ASSERT(self != NULL, return -1;); 794 IRDA_ASSERT(self->magic == LMP_LSAP_MAGIC, return -1;); 795 796 IRDA_DEBUG(4, "%s()\n", __func__); 797 798 switch (event) { 799 case LM_CONNECT_CONFIRM: 800 irlmp_next_lsap_state(self, LSAP_DATA_TRANSFER_READY); 801 802 del_timer(&self->watchdog_timer); 803 804 irlmp_connect_confirm(self, skb); 805 break; 806 case LM_DISCONNECT_INDICATION: 807 irlmp_next_lsap_state(self, LSAP_DISCONNECTED); 808 809 IRDA_ASSERT(self->lap != NULL, return -1;); 810 IRDA_ASSERT(self->lap->magic == LMP_LAP_MAGIC, return -1;); 811 812 IRDA_ASSERT(skb != NULL, return -1;); 813 IRDA_ASSERT(skb->len > 3, return -1;); 814 reason = skb->data[3]; 815 816 /* Try to close the LAP connection */ 817 IRDA_DEBUG(4, "%s(), trying to close IrLAP\n", __func__); 818 irlmp_do_lap_event(self->lap, LM_LAP_DISCONNECT_REQUEST, NULL); 819 820 irlmp_disconnect_indication(self, reason, skb); 821 break; 822 case LM_LAP_DISCONNECT_INDICATION: 823 irlmp_next_lsap_state(self, LSAP_DISCONNECTED); 824 825 del_timer(&self->watchdog_timer); 826 827 IRDA_ASSERT(self->lap != NULL, return -1;); 828 IRDA_ASSERT(self->lap->magic == LMP_LAP_MAGIC, return -1;); 829 830 reason = irlmp_convert_lap_reason(self->lap->reason); 831 832 irlmp_disconnect_indication(self, reason, skb); 833 break; 834 case LM_WATCHDOG_TIMEOUT: 835 IRDA_DEBUG(0, "%s() WATCHDOG_TIMEOUT!\n", __func__); 836 837 IRDA_ASSERT(self->lap != NULL, return -1;); 838 irlmp_do_lap_event(self->lap, LM_LAP_DISCONNECT_REQUEST, NULL); 839 irlmp_next_lsap_state(self, LSAP_DISCONNECTED); 840 841 irlmp_disconnect_indication(self, LM_CONNECT_FAILURE, NULL); 842 break; 843 default: 844 IRDA_DEBUG(0, "%s(), Unknown event %s on LSAP %#02x\n", 845 __func__, irlmp_event[event], self->slsap_sel); 846 break; 847 } 848 return ret; 849} 850 851/* 852 * Function irlmp_state_setup_pend (event, skb, info) 853 * 854 * SETUP_PEND, An LM_CONNECT_REQUEST has been received from the service 855 * user to set up an LSAP connection. A request has been sent to the 856 * LAP FSM to set up the underlying IrLAP connection, and we 857 * are awaiting confirm. 858 */ 859static int irlmp_state_setup_pend(struct lsap_cb *self, IRLMP_EVENT event, 860 struct sk_buff *skb) 861{ 862 struct sk_buff *tx_skb; 863 LM_REASON reason; 864 int ret = 0; 865 866 IRDA_DEBUG(4, "%s()\n", __func__); 867 868 IRDA_ASSERT(self != NULL, return -1;); 869 IRDA_ASSERT(irlmp != NULL, return -1;); 870 871 switch (event) { 872 case LM_LAP_CONNECT_CONFIRM: 873 IRDA_ASSERT(self->conn_skb != NULL, return -1;); 874 875 tx_skb = self->conn_skb; 876 self->conn_skb = NULL; 877 878 irlmp_send_lcf_pdu(self->lap, self->dlsap_sel, 879 self->slsap_sel, CONNECT_CMD, tx_skb); 880 /* Drop reference count - see irlap_data_request(). */ 881 dev_kfree_skb(tx_skb); 882 883 irlmp_next_lsap_state(self, LSAP_SETUP); 884 break; 885 case LM_WATCHDOG_TIMEOUT: 886 IRDA_DEBUG(0, "%s() : WATCHDOG_TIMEOUT !\n", __func__); 887 888 IRDA_ASSERT(self->lap != NULL, return -1;); 889 irlmp_do_lap_event(self->lap, LM_LAP_DISCONNECT_REQUEST, NULL); 890 irlmp_next_lsap_state(self, LSAP_DISCONNECTED); 891 892 irlmp_disconnect_indication(self, LM_CONNECT_FAILURE, NULL); 893 break; 894 case LM_LAP_DISCONNECT_INDICATION: /* LS_Disconnect.indication */ 895 del_timer( &self->watchdog_timer); 896 897 irlmp_next_lsap_state(self, LSAP_DISCONNECTED); 898 899 reason = irlmp_convert_lap_reason(self->lap->reason); 900 901 irlmp_disconnect_indication(self, reason, NULL); 902 break; 903 default: 904 IRDA_DEBUG(0, "%s(), Unknown event %s on LSAP %#02x\n", 905 __func__, irlmp_event[event], self->slsap_sel); 906 break; 907 } 908 return ret; 909} 910