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