linux/net/irda/irlan/irlan_client_event.c
<<
>>
Prefs
   1/*********************************************************************
   2 *
   3 * Filename:      irlan_client_event.c
   4 * Version:       0.9
   5 * Description:   IrLAN client state machine
   6 * Status:        Experimental.
   7 * Author:        Dag Brattli <dagb@cs.uit.no>
   8 * Created at:    Sun Aug 31 20:14:37 1997
   9 * Modified at:   Sun Dec 26 21:52:24 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 *
  15 *     This program is free software; you can redistribute it and/or
  16 *     modify it under the terms of the GNU General Public License as
  17 *     published by the Free Software Foundation; either version 2 of
  18 *     the License, or (at your option) any later version.
  19 *
  20 *     Neither Dag Brattli nor University of Tromsø admit liability nor
  21 *     provide warranty for any of this software. This material is
  22 *     provided "AS-IS" and at no charge.
  23 *
  24 ********************************************************************/
  25
  26#include <linux/skbuff.h>
  27
  28#include <net/irda/irda.h>
  29#include <net/irda/timer.h>
  30#include <net/irda/irmod.h>
  31#include <net/irda/iriap.h>
  32#include <net/irda/irlmp.h>
  33#include <net/irda/irttp.h>
  34
  35#include <net/irda/irlan_common.h>
  36#include <net/irda/irlan_client.h>
  37#include <net/irda/irlan_event.h>
  38
  39static int irlan_client_state_idle (struct irlan_cb *self, IRLAN_EVENT event,
  40                                    struct sk_buff *skb);
  41static int irlan_client_state_query(struct irlan_cb *self, IRLAN_EVENT event,
  42                                    struct sk_buff *skb);
  43static int irlan_client_state_conn (struct irlan_cb *self, IRLAN_EVENT event,
  44                                    struct sk_buff *skb);
  45static int irlan_client_state_info (struct irlan_cb *self, IRLAN_EVENT event,
  46                                    struct sk_buff *skb);
  47static int irlan_client_state_media(struct irlan_cb *self, IRLAN_EVENT event,
  48                                    struct sk_buff *skb);
  49static int irlan_client_state_open (struct irlan_cb *self, IRLAN_EVENT event,
  50                                    struct sk_buff *skb);
  51static int irlan_client_state_wait (struct irlan_cb *self, IRLAN_EVENT event,
  52                                    struct sk_buff *skb);
  53static int irlan_client_state_arb  (struct irlan_cb *self, IRLAN_EVENT event,
  54                                    struct sk_buff *skb);
  55static int irlan_client_state_data (struct irlan_cb *self, IRLAN_EVENT event,
  56                                    struct sk_buff *skb);
  57static int irlan_client_state_close(struct irlan_cb *self, IRLAN_EVENT event,
  58                                    struct sk_buff *skb);
  59static int irlan_client_state_sync (struct irlan_cb *self, IRLAN_EVENT event,
  60                                    struct sk_buff *skb);
  61
  62static int (*state[])(struct irlan_cb *, IRLAN_EVENT event, struct sk_buff *) =
  63{
  64        irlan_client_state_idle,
  65        irlan_client_state_query,
  66        irlan_client_state_conn,
  67        irlan_client_state_info,
  68        irlan_client_state_media,
  69        irlan_client_state_open,
  70        irlan_client_state_wait,
  71        irlan_client_state_arb,
  72        irlan_client_state_data,
  73        irlan_client_state_close,
  74        irlan_client_state_sync
  75};
  76
  77void irlan_do_client_event(struct irlan_cb *self, IRLAN_EVENT event,
  78                           struct sk_buff *skb)
  79{
  80        IRDA_ASSERT(self != NULL, return;);
  81        IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);
  82
  83        (*state[ self->client.state]) (self, event, skb);
  84}
  85
  86/*
  87 * Function irlan_client_state_idle (event, skb, info)
  88 *
  89 *    IDLE, We are waiting for an indication that there is a provider
  90 *    available.
  91 */
  92static int irlan_client_state_idle(struct irlan_cb *self, IRLAN_EVENT event,
  93                                   struct sk_buff *skb)
  94{
  95        IRDA_DEBUG(4, "%s()\n", __func__ );
  96
  97        IRDA_ASSERT(self != NULL, return -1;);
  98        IRDA_ASSERT(self->magic == IRLAN_MAGIC, return -1;);
  99
 100        switch (event) {
 101        case IRLAN_DISCOVERY_INDICATION:
 102                if (self->client.iriap) {
 103                        IRDA_WARNING("%s(), busy with a previous query\n",
 104                                     __func__);
 105                        return -EBUSY;
 106                }
 107
 108                self->client.iriap = iriap_open(LSAP_ANY, IAS_CLIENT, self,
 109                                                irlan_client_get_value_confirm);
 110                /* Get some values from peer IAS */
 111                irlan_next_client_state(self, IRLAN_QUERY);
 112                iriap_getvaluebyclass_request(self->client.iriap,
 113                                              self->saddr, self->daddr,
 114                                              "IrLAN", "IrDA:TinyTP:LsapSel");
 115                break;
 116        case IRLAN_WATCHDOG_TIMEOUT:
 117                IRDA_DEBUG(2, "%s(), IRLAN_WATCHDOG_TIMEOUT\n", __func__ );
 118                break;
 119        default:
 120                IRDA_DEBUG(4, "%s(), Unknown event %d\n", __func__ , event);
 121                break;
 122        }
 123        if (skb)
 124                dev_kfree_skb(skb);
 125
 126        return 0;
 127}
 128
 129/*
 130 * Function irlan_client_state_query (event, skb, info)
 131 *
 132 *    QUERY, We have queryed the remote IAS and is ready to connect
 133 *    to provider, just waiting for the confirm.
 134 *
 135 */
 136static int irlan_client_state_query(struct irlan_cb *self, IRLAN_EVENT event,
 137                                    struct sk_buff *skb)
 138{
 139        IRDA_DEBUG(4, "%s()\n", __func__ );
 140
 141        IRDA_ASSERT(self != NULL, return -1;);
 142        IRDA_ASSERT(self->magic == IRLAN_MAGIC, return -1;);
 143
 144        switch(event) {
 145        case IRLAN_IAS_PROVIDER_AVAIL:
 146                IRDA_ASSERT(self->dtsap_sel_ctrl != 0, return -1;);
 147
 148                self->client.open_retries = 0;
 149
 150                irttp_connect_request(self->client.tsap_ctrl,
 151                                      self->dtsap_sel_ctrl,
 152                                      self->saddr, self->daddr, NULL,
 153                                      IRLAN_MTU, NULL);
 154                irlan_next_client_state(self, IRLAN_CONN);
 155                break;
 156        case IRLAN_IAS_PROVIDER_NOT_AVAIL:
 157                IRDA_DEBUG(2, "%s(), IAS_PROVIDER_NOT_AVAIL\n", __func__ );
 158                irlan_next_client_state(self, IRLAN_IDLE);
 159
 160                /* Give the client a kick! */
 161                if ((self->provider.access_type == ACCESS_PEER) &&
 162                    (self->provider.state != IRLAN_IDLE))
 163                        irlan_client_wakeup(self, self->saddr, self->daddr);
 164                break;
 165        case IRLAN_LMP_DISCONNECT:
 166        case IRLAN_LAP_DISCONNECT:
 167                irlan_next_client_state(self, IRLAN_IDLE);
 168                break;
 169        case IRLAN_WATCHDOG_TIMEOUT:
 170                IRDA_DEBUG(2, "%s(), IRLAN_WATCHDOG_TIMEOUT\n", __func__ );
 171                break;
 172        default:
 173                IRDA_DEBUG(2, "%s(), Unknown event %d\n", __func__ , event);
 174                break;
 175        }
 176        if (skb)
 177                dev_kfree_skb(skb);
 178
 179        return 0;
 180}
 181
 182/*
 183 * Function irlan_client_state_conn (event, skb, info)
 184 *
 185 *    CONN, We have connected to a provider but has not issued any
 186 *    commands yet.
 187 *
 188 */
 189static int irlan_client_state_conn(struct irlan_cb *self, IRLAN_EVENT event,
 190                                   struct sk_buff *skb)
 191{
 192        IRDA_DEBUG(4, "%s()\n", __func__ );
 193
 194        IRDA_ASSERT(self != NULL, return -1;);
 195
 196        switch (event) {
 197        case IRLAN_CONNECT_COMPLETE:
 198                /* Send getinfo cmd */
 199                irlan_get_provider_info(self);
 200                irlan_next_client_state(self, IRLAN_INFO);
 201                break;
 202        case IRLAN_LMP_DISCONNECT:
 203        case IRLAN_LAP_DISCONNECT:
 204                irlan_next_client_state(self, IRLAN_IDLE);
 205                break;
 206        case IRLAN_WATCHDOG_TIMEOUT:
 207                IRDA_DEBUG(2, "%s(), IRLAN_WATCHDOG_TIMEOUT\n", __func__ );
 208                break;
 209        default:
 210                IRDA_DEBUG(2, "%s(), Unknown event %d\n", __func__ , event);
 211                break;
 212        }
 213        if (skb)
 214                dev_kfree_skb(skb);
 215
 216        return 0;
 217}
 218
 219/*
 220 * Function irlan_client_state_info (self, event, skb, info)
 221 *
 222 *    INFO, We have issued a GetInfo command and is awaiting a reply.
 223 */
 224static int irlan_client_state_info(struct irlan_cb *self, IRLAN_EVENT event,
 225                                   struct sk_buff *skb)
 226{
 227        IRDA_DEBUG(4, "%s()\n", __func__ );
 228
 229        IRDA_ASSERT(self != NULL, return -1;);
 230
 231        switch (event) {
 232        case IRLAN_DATA_INDICATION:
 233                IRDA_ASSERT(skb != NULL, return -1;);
 234
 235                irlan_client_parse_response(self, skb);
 236
 237                irlan_next_client_state(self, IRLAN_MEDIA);
 238
 239                irlan_get_media_char(self);
 240                break;
 241
 242        case IRLAN_LMP_DISCONNECT:
 243        case IRLAN_LAP_DISCONNECT:
 244                irlan_next_client_state(self, IRLAN_IDLE);
 245                break;
 246        case IRLAN_WATCHDOG_TIMEOUT:
 247                IRDA_DEBUG(2, "%s(), IRLAN_WATCHDOG_TIMEOUT\n", __func__ );
 248                break;
 249        default:
 250                IRDA_DEBUG(2, "%s(), Unknown event %d\n", __func__ , event);
 251                break;
 252        }
 253        if (skb)
 254                dev_kfree_skb(skb);
 255
 256        return 0;
 257}
 258
 259/*
 260 * Function irlan_client_state_media (self, event, skb, info)
 261 *
 262 *    MEDIA, The irlan_client has issued a GetMedia command and is awaiting a
 263 *    reply.
 264 *
 265 */
 266static int irlan_client_state_media(struct irlan_cb *self, IRLAN_EVENT event,
 267                                    struct sk_buff *skb)
 268{
 269        IRDA_DEBUG(4, "%s()\n", __func__ );
 270
 271        IRDA_ASSERT(self != NULL, return -1;);
 272
 273        switch(event) {
 274        case IRLAN_DATA_INDICATION:
 275                irlan_client_parse_response(self, skb);
 276                irlan_open_data_channel(self);
 277                irlan_next_client_state(self, IRLAN_OPEN);
 278                break;
 279        case IRLAN_LMP_DISCONNECT:
 280        case IRLAN_LAP_DISCONNECT:
 281                irlan_next_client_state(self, IRLAN_IDLE);
 282                break;
 283        case IRLAN_WATCHDOG_TIMEOUT:
 284                IRDA_DEBUG(2, "%s(), IRLAN_WATCHDOG_TIMEOUT\n", __func__ );
 285                break;
 286        default:
 287                IRDA_DEBUG(2, "%s(), Unknown event %d\n", __func__ , event);
 288                break;
 289        }
 290        if (skb)
 291                dev_kfree_skb(skb);
 292
 293        return 0;
 294}
 295
 296/*
 297 * Function irlan_client_state_open (self, event, skb, info)
 298 *
 299 *    OPEN, The irlan_client has issued a OpenData command and is awaiting a
 300 *    reply
 301 *
 302 */
 303static int irlan_client_state_open(struct irlan_cb *self, IRLAN_EVENT event,
 304                                   struct sk_buff *skb)
 305{
 306        struct qos_info qos;
 307
 308        IRDA_DEBUG(4, "%s()\n", __func__ );
 309
 310        IRDA_ASSERT(self != NULL, return -1;);
 311
 312        switch(event) {
 313        case IRLAN_DATA_INDICATION:
 314                irlan_client_parse_response(self, skb);
 315
 316                /*
 317                 *  Check if we have got the remote TSAP for data
 318                 *  communications
 319                 */
 320                IRDA_ASSERT(self->dtsap_sel_data != 0, return -1;);
 321
 322                /* Check which access type we are dealing with */
 323                switch (self->client.access_type) {
 324                case ACCESS_PEER:
 325                    if (self->provider.state == IRLAN_OPEN) {
 326
 327                            irlan_next_client_state(self, IRLAN_ARB);
 328                            irlan_do_client_event(self, IRLAN_CHECK_CON_ARB,
 329                                                  NULL);
 330                    } else {
 331
 332                            irlan_next_client_state(self, IRLAN_WAIT);
 333                    }
 334                    break;
 335                case ACCESS_DIRECT:
 336                case ACCESS_HOSTED:
 337                        qos.link_disc_time.bits = 0x01; /* 3 secs */
 338
 339                        irttp_connect_request(self->tsap_data,
 340                                              self->dtsap_sel_data,
 341                                              self->saddr, self->daddr, &qos,
 342                                              IRLAN_MTU, NULL);
 343
 344                        irlan_next_client_state(self, IRLAN_DATA);
 345                        break;
 346                default:
 347                        IRDA_DEBUG(2, "%s(), unknown access type!\n", __func__ );
 348                        break;
 349                }
 350                break;
 351        case IRLAN_LMP_DISCONNECT:
 352        case IRLAN_LAP_DISCONNECT:
 353                irlan_next_client_state(self, IRLAN_IDLE);
 354                break;
 355        case IRLAN_WATCHDOG_TIMEOUT:
 356                IRDA_DEBUG(2, "%s(), IRLAN_WATCHDOG_TIMEOUT\n", __func__ );
 357                break;
 358        default:
 359                IRDA_DEBUG(2, "%s(), Unknown event %d\n", __func__ , event);
 360                break;
 361        }
 362
 363        if (skb)
 364                dev_kfree_skb(skb);
 365
 366        return 0;
 367}
 368
 369/*
 370 * Function irlan_client_state_wait (self, event, skb, info)
 371 *
 372 *    WAIT, The irlan_client is waiting for the local provider to enter the
 373 *    provider OPEN state.
 374 *
 375 */
 376static int irlan_client_state_wait(struct irlan_cb *self, IRLAN_EVENT event,
 377                                   struct sk_buff *skb)
 378{
 379        IRDA_DEBUG(4, "%s()\n", __func__ );
 380
 381        IRDA_ASSERT(self != NULL, return -1;);
 382
 383        switch(event) {
 384        case IRLAN_PROVIDER_SIGNAL:
 385                irlan_next_client_state(self, IRLAN_ARB);
 386                irlan_do_client_event(self, IRLAN_CHECK_CON_ARB, NULL);
 387                break;
 388        case IRLAN_LMP_DISCONNECT:
 389        case IRLAN_LAP_DISCONNECT:
 390                irlan_next_client_state(self, IRLAN_IDLE);
 391                break;
 392        case IRLAN_WATCHDOG_TIMEOUT:
 393                IRDA_DEBUG(2, "%s(), IRLAN_WATCHDOG_TIMEOUT\n", __func__ );
 394                break;
 395        default:
 396                IRDA_DEBUG(2, "%s(), Unknown event %d\n", __func__ , event);
 397                break;
 398        }
 399        if (skb)
 400                dev_kfree_skb(skb);
 401
 402        return 0;
 403}
 404
 405static int irlan_client_state_arb(struct irlan_cb *self, IRLAN_EVENT event,
 406                                  struct sk_buff *skb)
 407{
 408        struct qos_info qos;
 409
 410        IRDA_DEBUG(2, "%s()\n", __func__ );
 411
 412        IRDA_ASSERT(self != NULL, return -1;);
 413
 414        switch(event) {
 415        case IRLAN_CHECK_CON_ARB:
 416                if (self->client.recv_arb_val == self->provider.send_arb_val) {
 417                        irlan_next_client_state(self, IRLAN_CLOSE);
 418                        irlan_close_data_channel(self);
 419                } else if (self->client.recv_arb_val <
 420                           self->provider.send_arb_val)
 421                {
 422                        qos.link_disc_time.bits = 0x01; /* 3 secs */
 423
 424                        irlan_next_client_state(self, IRLAN_DATA);
 425                        irttp_connect_request(self->tsap_data,
 426                                              self->dtsap_sel_data,
 427                                              self->saddr, self->daddr, &qos,
 428                                              IRLAN_MTU, NULL);
 429                } else if (self->client.recv_arb_val >
 430                           self->provider.send_arb_val)
 431                {
 432                        IRDA_DEBUG(2, "%s(), lost the battle :-(\n", __func__ );
 433                }
 434                break;
 435        case IRLAN_DATA_CONNECT_INDICATION:
 436                irlan_next_client_state(self, IRLAN_DATA);
 437                break;
 438        case IRLAN_LMP_DISCONNECT:
 439        case IRLAN_LAP_DISCONNECT:
 440                irlan_next_client_state(self, IRLAN_IDLE);
 441                break;
 442        case IRLAN_WATCHDOG_TIMEOUT:
 443                IRDA_DEBUG(2, "%s(), IRLAN_WATCHDOG_TIMEOUT\n", __func__ );
 444                break;
 445        default:
 446                IRDA_DEBUG(2, "%s(), Unknown event %d\n", __func__ , event);
 447                break;
 448        }
 449        if (skb)
 450                dev_kfree_skb(skb);
 451
 452        return 0;
 453}
 454
 455/*
 456 * Function irlan_client_state_data (self, event, skb, info)
 457 *
 458 *    DATA, The data channel is connected, allowing data transfers between
 459 *    the local and remote machines.
 460 *
 461 */
 462static int irlan_client_state_data(struct irlan_cb *self, IRLAN_EVENT event,
 463                                   struct sk_buff *skb)
 464{
 465        IRDA_DEBUG(4, "%s()\n", __func__ );
 466
 467        IRDA_ASSERT(self != NULL, return -1;);
 468        IRDA_ASSERT(self->magic == IRLAN_MAGIC, return -1;);
 469
 470        switch(event) {
 471        case IRLAN_DATA_INDICATION:
 472                irlan_client_parse_response(self, skb);
 473                break;
 474        case IRLAN_LMP_DISCONNECT: /* FALLTHROUGH */
 475        case IRLAN_LAP_DISCONNECT:
 476                irlan_next_client_state(self, IRLAN_IDLE);
 477                break;
 478        default:
 479                IRDA_DEBUG(2, "%s(), Unknown event %d\n", __func__ , event);
 480                break;
 481        }
 482        if (skb)
 483                dev_kfree_skb(skb);
 484
 485        return 0;
 486}
 487
 488/*
 489 * Function irlan_client_state_close (self, event, skb, info)
 490 *
 491 *
 492 *
 493 */
 494static int irlan_client_state_close(struct irlan_cb *self, IRLAN_EVENT event,
 495                                    struct sk_buff *skb)
 496{
 497        IRDA_DEBUG(2, "%s()\n", __func__ );
 498
 499        if (skb)
 500                dev_kfree_skb(skb);
 501
 502        return 0;
 503}
 504
 505/*
 506 * Function irlan_client_state_sync (self, event, skb, info)
 507 *
 508 *
 509 *
 510 */
 511static int irlan_client_state_sync(struct irlan_cb *self, IRLAN_EVENT event,
 512                                   struct sk_buff *skb)
 513{
 514        IRDA_DEBUG(2, "%s()\n", __func__ );
 515
 516        if (skb)
 517                dev_kfree_skb(skb);
 518
 519        return 0;
 520}
 521
 522
 523
 524
 525
 526
 527
 528
 529
 530
 531
 532
 533
 534