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