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