linux/net/irda/irlan/irlan_provider_event.c
<<
>>
Prefs
   1/*********************************************************************
   2 *
   3 * Filename:      irlan_provider_event.c
   4 * Version:       0.9
   5 * Description:   IrLAN provider 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:   Sat Oct 30 12:52:41 1999
  10 * Modified by:   Dag Brattli <dagb@cs.uit.no>
  11 *
  12 *     Copyright (c) 1998-1999 Dag Brattli <dagb@cs.uit.no>, All Rights Reserved.
  13 *
  14 *     This program is free software; you can redistribute it and/or
  15 *     modify it under the terms of the GNU General Public License as
  16 *     published by the Free Software Foundation; either version 2 of
  17 *     the License, or (at your option) any later version.
  18 *
  19 *     Neither Dag Brattli nor University of Tromsø admit liability nor
  20 *     provide warranty for any of this software. This material is
  21 *     provided "AS-IS" and at no charge.
  22 *
  23 ********************************************************************/
  24
  25#include <net/irda/irda.h>
  26#include <net/irda/iriap.h>
  27#include <net/irda/irlmp.h>
  28#include <net/irda/irttp.h>
  29
  30#include <net/irda/irlan_provider.h>
  31#include <net/irda/irlan_event.h>
  32
  33static int irlan_provider_state_idle(struct irlan_cb *self, IRLAN_EVENT event,
  34                                     struct sk_buff *skb);
  35static int irlan_provider_state_info(struct irlan_cb *self, IRLAN_EVENT event,
  36                                     struct sk_buff *skb);
  37static int irlan_provider_state_open(struct irlan_cb *self, IRLAN_EVENT event,
  38                                     struct sk_buff *skb);
  39static int irlan_provider_state_data(struct irlan_cb *self, IRLAN_EVENT event,
  40                                     struct sk_buff *skb);
  41
  42static int (*state[])(struct irlan_cb *self, IRLAN_EVENT event,
  43                      struct sk_buff *skb) =
  44{
  45        irlan_provider_state_idle,
  46        NULL, /* Query */
  47        NULL, /* Info */
  48        irlan_provider_state_info,
  49        NULL, /* Media */
  50        irlan_provider_state_open,
  51        NULL, /* Wait */
  52        NULL, /* Arb */
  53        irlan_provider_state_data,
  54        NULL, /* Close */
  55        NULL, /* Sync */
  56};
  57
  58void irlan_do_provider_event(struct irlan_cb *self, IRLAN_EVENT event,
  59                             struct sk_buff *skb)
  60{
  61        IRDA_ASSERT(*state[ self->provider.state] != NULL, return;);
  62
  63        (*state[self->provider.state]) (self, event, skb);
  64}
  65
  66/*
  67 * Function irlan_provider_state_idle (event, skb, info)
  68 *
  69 *    IDLE, We are waiting for an indication that there is a provider
  70 *    available.
  71 */
  72static int irlan_provider_state_idle(struct irlan_cb *self, IRLAN_EVENT event,
  73                                     struct sk_buff *skb)
  74{
  75        IRDA_ASSERT(self != NULL, return -1;);
  76
  77        switch(event) {
  78        case IRLAN_CONNECT_INDICATION:
  79             irlan_provider_connect_response( self, self->provider.tsap_ctrl);
  80             irlan_next_provider_state( self, IRLAN_INFO);
  81             break;
  82        default:
  83                pr_debug("%s(), Unknown event %d\n", __func__ , event);
  84                break;
  85        }
  86        if (skb)
  87                dev_kfree_skb(skb);
  88
  89        return 0;
  90}
  91
  92/*
  93 * Function irlan_provider_state_info (self, event, skb, info)
  94 *
  95 *    INFO, We have issued a GetInfo command and is awaiting a reply.
  96 */
  97static int irlan_provider_state_info(struct irlan_cb *self, IRLAN_EVENT event,
  98                                     struct sk_buff *skb)
  99{
 100        int ret;
 101
 102        IRDA_ASSERT(self != NULL, return -1;);
 103
 104        switch(event) {
 105        case IRLAN_GET_INFO_CMD:
 106                /* Be sure to use 802.3 in case of peer mode */
 107                if (self->provider.access_type == ACCESS_PEER) {
 108                        self->media = MEDIA_802_3;
 109
 110                        /* Check if client has started yet */
 111                        if (self->client.state == IRLAN_IDLE) {
 112                                /* This should get the client going */
 113                                irlmp_discovery_request(8);
 114                        }
 115                }
 116
 117                irlan_provider_send_reply(self, CMD_GET_PROVIDER_INFO,
 118                                          RSP_SUCCESS);
 119                /* Keep state */
 120                break;
 121        case IRLAN_GET_MEDIA_CMD:
 122                irlan_provider_send_reply(self, CMD_GET_MEDIA_CHAR,
 123                                          RSP_SUCCESS);
 124                /* Keep state */
 125                break;
 126        case IRLAN_OPEN_DATA_CMD:
 127                ret = irlan_parse_open_data_cmd(self, skb);
 128                if (self->provider.access_type == ACCESS_PEER) {
 129                        /* FIXME: make use of random functions! */
 130                        self->provider.send_arb_val = (jiffies & 0xffff);
 131                }
 132                irlan_provider_send_reply(self, CMD_OPEN_DATA_CHANNEL, ret);
 133
 134                if (ret == RSP_SUCCESS) {
 135                        irlan_next_provider_state(self, IRLAN_OPEN);
 136
 137                        /* Signal client that we are now open */
 138                        irlan_do_client_event(self, IRLAN_PROVIDER_SIGNAL, NULL);
 139                }
 140                break;
 141        case IRLAN_LMP_DISCONNECT:  /* FALLTHROUGH */
 142        case IRLAN_LAP_DISCONNECT:
 143                irlan_next_provider_state(self, IRLAN_IDLE);
 144                break;
 145        default:
 146                pr_debug("%s(), Unknown event %d\n", __func__ , event);
 147                break;
 148        }
 149        if (skb)
 150                dev_kfree_skb(skb);
 151
 152        return 0;
 153}
 154
 155/*
 156 * Function irlan_provider_state_open (self, event, skb, info)
 157 *
 158 *    OPEN, The client has issued a OpenData command and is awaiting a
 159 *    reply
 160 *
 161 */
 162static int irlan_provider_state_open(struct irlan_cb *self, IRLAN_EVENT event,
 163                                     struct sk_buff *skb)
 164{
 165        IRDA_ASSERT(self != NULL, return -1;);
 166
 167        switch(event) {
 168        case IRLAN_FILTER_CONFIG_CMD:
 169                irlan_provider_parse_command(self, CMD_FILTER_OPERATION, skb);
 170                irlan_provider_send_reply(self, CMD_FILTER_OPERATION,
 171                                          RSP_SUCCESS);
 172                /* Keep state */
 173                break;
 174        case IRLAN_DATA_CONNECT_INDICATION:
 175                irlan_next_provider_state(self, IRLAN_DATA);
 176                irlan_provider_connect_response(self, self->tsap_data);
 177                break;
 178        case IRLAN_LMP_DISCONNECT:  /* FALLTHROUGH */
 179        case IRLAN_LAP_DISCONNECT:
 180                irlan_next_provider_state(self, IRLAN_IDLE);
 181                break;
 182        default:
 183                pr_debug("%s(), Unknown event %d\n", __func__ , event);
 184                break;
 185        }
 186        if (skb)
 187                dev_kfree_skb(skb);
 188
 189        return 0;
 190}
 191
 192/*
 193 * Function irlan_provider_state_data (self, event, skb, info)
 194 *
 195 *    DATA, The data channel is connected, allowing data transfers between
 196 *    the local and remote machines.
 197 *
 198 */
 199static int irlan_provider_state_data(struct irlan_cb *self, IRLAN_EVENT event,
 200                                     struct sk_buff *skb)
 201{
 202        IRDA_ASSERT(self != NULL, return -1;);
 203        IRDA_ASSERT(self->magic == IRLAN_MAGIC, return -1;);
 204
 205        switch(event) {
 206        case IRLAN_FILTER_CONFIG_CMD:
 207                irlan_provider_parse_command(self, CMD_FILTER_OPERATION, skb);
 208                irlan_provider_send_reply(self, CMD_FILTER_OPERATION,
 209                                          RSP_SUCCESS);
 210                break;
 211        case IRLAN_LMP_DISCONNECT: /* FALLTHROUGH */
 212        case IRLAN_LAP_DISCONNECT:
 213                irlan_next_provider_state(self, IRLAN_IDLE);
 214                break;
 215        default:
 216                pr_debug("%s(), Unknown event %d\n", __func__ , event);
 217                break;
 218        }
 219        if (skb)
 220                dev_kfree_skb(skb);
 221
 222        return 0;
 223}
 224
 225
 226
 227
 228
 229
 230
 231
 232
 233
 234