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