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 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_DEBUG(4, __FUNCTION__ "()\n"); 76 77 ASSERT(self != NULL, return -1;); 78 79 switch(event) { 80 case IRLAN_CONNECT_INDICATION: 81 irlan_provider_connect_response( self, self->provider.tsap_ctrl); 82 irlan_next_provider_state( self, IRLAN_INFO); 83 break; 84 default: 85 IRDA_DEBUG(4, __FUNCTION__ "(), Unknown event %d\n", event); 86 break; 87 } 88 if (skb) 89 dev_kfree_skb(skb); 90 91 return 0; 92} 93 94/* 95 * Function irlan_provider_state_info (self, event, skb, info) 96 * 97 * INFO, We have issued a GetInfo command and is awaiting a reply. 98 */ 99static int irlan_provider_state_info(struct irlan_cb *self, IRLAN_EVENT event, 100 struct sk_buff *skb) 101{ 102 int ret; 103 104 IRDA_DEBUG(4, __FUNCTION__ "()\n"); 105 106 ASSERT(self != NULL, return -1;); 107 108 switch(event) { 109 case IRLAN_GET_INFO_CMD: 110 /* Be sure to use 802.3 in case of peer mode */ 111 if (self->provider.access_type == ACCESS_PEER) { 112 self->media = MEDIA_802_3; 113 114 /* Check if client has started yet */ 115 if (self->client.state == IRLAN_IDLE) { 116 /* This should get the client going */ 117 irlmp_discovery_request(8); 118 } 119 } 120 121 irlan_provider_send_reply(self, CMD_GET_PROVIDER_INFO, 122 RSP_SUCCESS); 123 /* Keep state */ 124 break; 125 case IRLAN_GET_MEDIA_CMD: 126 irlan_provider_send_reply(self, CMD_GET_MEDIA_CHAR, 127 RSP_SUCCESS); 128 /* Keep state */ 129 break; 130 case IRLAN_OPEN_DATA_CMD: 131 ret = irlan_parse_open_data_cmd(self, skb); 132 if (self->provider.access_type == ACCESS_PEER) { 133 self->provider.send_arb_val = (jiffies & 0xffff); 134 } 135 irlan_provider_send_reply(self, CMD_OPEN_DATA_CHANNEL, ret); 136 137 if (ret == RSP_SUCCESS) { 138 irlan_next_provider_state(self, IRLAN_OPEN); 139 140 /* Signal client that we are now open */ 141 irlan_do_client_event(self, IRLAN_PROVIDER_SIGNAL, NULL); 142 } 143 break; 144 case IRLAN_LMP_DISCONNECT: /* FALLTHROUGH */ 145 case IRLAN_LAP_DISCONNECT: 146 irlan_next_provider_state(self, IRLAN_IDLE); 147 break; 148 default: 149 IRDA_DEBUG( 0, __FUNCTION__ "(), Unknown event %d\n", event); 150 break; 151 } 152 if (skb) 153 dev_kfree_skb(skb); 154 155 return 0; 156} 157 158/* 159 * Function irlan_provider_state_open (self, event, skb, info) 160 * 161 * OPEN, The client has issued a OpenData command and is awaiting a 162 * reply 163 * 164 */ 165static int irlan_provider_state_open(struct irlan_cb *self, IRLAN_EVENT event, 166 struct sk_buff *skb) 167{ 168 IRDA_DEBUG(4, __FUNCTION__ "()\n"); 169 170 ASSERT(self != NULL, return -1;); 171 172 switch(event) { 173 case IRLAN_FILTER_CONFIG_CMD: 174 irlan_provider_parse_command(self, CMD_FILTER_OPERATION, skb); 175 irlan_provider_send_reply(self, CMD_FILTER_OPERATION, 176 RSP_SUCCESS); 177 /* Keep state */ 178 break; 179 case IRLAN_DATA_CONNECT_INDICATION: 180 irlan_next_provider_state(self, IRLAN_DATA); 181 irlan_provider_connect_response(self, self->tsap_data); 182 break; 183 case IRLAN_LMP_DISCONNECT: /* FALLTHROUGH */ 184 case IRLAN_LAP_DISCONNECT: 185 irlan_next_provider_state(self, IRLAN_IDLE); 186 break; 187 default: 188 IRDA_DEBUG(2, __FUNCTION__ "(), Unknown event %d\n", event); 189 break; 190 } 191 if (skb) 192 dev_kfree_skb(skb); 193 194 return 0; 195} 196 197/* 198 * Function irlan_provider_state_data (self, event, skb, info) 199 * 200 * DATA, The data channel is connected, allowing data transfers between 201 * the local and remote machines. 202 * 203 */ 204static int irlan_provider_state_data(struct irlan_cb *self, IRLAN_EVENT event, 205 struct sk_buff *skb) 206{ 207 IRDA_DEBUG(4, __FUNCTION__ "()\n"); 208 209 ASSERT(self != NULL, return -1;); 210 ASSERT(self->magic == IRLAN_MAGIC, return -1;); 211 212 switch(event) { 213 case IRLAN_FILTER_CONFIG_CMD: 214 irlan_provider_parse_command(self, CMD_FILTER_OPERATION, skb); 215 irlan_provider_send_reply(self, CMD_FILTER_OPERATION, 216 RSP_SUCCESS); 217 break; 218 case IRLAN_LMP_DISCONNECT: /* FALLTHROUGH */ 219 case IRLAN_LAP_DISCONNECT: 220 irlan_next_provider_state(self, IRLAN_IDLE); 221 break; 222 default: 223 IRDA_DEBUG( 0, __FUNCTION__ "(), Unknown event %d\n", event); 224 break; 225 } 226 if (skb) 227 dev_kfree_skb(skb); 228 229 return 0; 230} 231 232 233 234 235 236 237 238 239 240 241