• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /netgear-R7000-V1.0.7.12_1.2.5/components/opensource/linux/linux-2.6.36/net/irda/ircomm/
1/*********************************************************************
2 *
3 * Filename:      ircomm_event.c
4 * Version:       1.0
5 * Description:   IrCOMM layer state machine
6 * Status:        Stable
7 * Author:        Dag Brattli <dagb@cs.uit.no>
8 * Created at:    Sun Jun  6 20:33:11 1999
9 * Modified at:   Sun Dec 12 13:44:32 1999
10 * Modified by:   Dag Brattli <dagb@cs.uit.no>
11 *
12 *     Copyright (c) 1999 Dag Brattli, 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 *     This program is distributed in the hope that it will be useful,
20 *     but WITHOUT ANY WARRANTY; without even the implied warranty of
21 *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 *     GNU General Public License for more details.
23 *
24 *     You should have received a copy of the GNU General Public License
25 *     along with this program; if not, write to the Free Software
26 *     Foundation, Inc., 59 Temple Place, Suite 330, Boston,
27 *     MA 02111-1307 USA
28 *
29 ********************************************************************/
30
31#include <linux/proc_fs.h>
32#include <linux/init.h>
33
34#include <net/irda/irda.h>
35#include <net/irda/irlmp.h>
36#include <net/irda/iriap.h>
37#include <net/irda/irttp.h>
38#include <net/irda/irias_object.h>
39
40#include <net/irda/ircomm_core.h>
41#include <net/irda/ircomm_event.h>
42
43static int ircomm_state_idle(struct ircomm_cb *self, IRCOMM_EVENT event,
44			     struct sk_buff *skb, struct ircomm_info *info);
45static int ircomm_state_waiti(struct ircomm_cb *self, IRCOMM_EVENT event,
46			      struct sk_buff *skb, struct ircomm_info *info);
47static int ircomm_state_waitr(struct ircomm_cb *self, IRCOMM_EVENT event,
48			      struct sk_buff *skb, struct ircomm_info *info);
49static int ircomm_state_conn(struct ircomm_cb *self, IRCOMM_EVENT event,
50			     struct sk_buff *skb, struct ircomm_info *info);
51
52const char *const ircomm_state[] = {
53	"IRCOMM_IDLE",
54	"IRCOMM_WAITI",
55	"IRCOMM_WAITR",
56	"IRCOMM_CONN",
57};
58
59#ifdef CONFIG_IRDA_DEBUG
60static const char *const ircomm_event[] = {
61	"IRCOMM_CONNECT_REQUEST",
62	"IRCOMM_CONNECT_RESPONSE",
63	"IRCOMM_TTP_CONNECT_INDICATION",
64	"IRCOMM_LMP_CONNECT_INDICATION",
65	"IRCOMM_TTP_CONNECT_CONFIRM",
66	"IRCOMM_LMP_CONNECT_CONFIRM",
67
68	"IRCOMM_LMP_DISCONNECT_INDICATION",
69	"IRCOMM_TTP_DISCONNECT_INDICATION",
70	"IRCOMM_DISCONNECT_REQUEST",
71
72	"IRCOMM_TTP_DATA_INDICATION",
73	"IRCOMM_LMP_DATA_INDICATION",
74	"IRCOMM_DATA_REQUEST",
75	"IRCOMM_CONTROL_REQUEST",
76	"IRCOMM_CONTROL_INDICATION",
77};
78#endif /* CONFIG_IRDA_DEBUG */
79
80static int (*state[])(struct ircomm_cb *self, IRCOMM_EVENT event,
81		      struct sk_buff *skb, struct ircomm_info *info) =
82{
83	ircomm_state_idle,
84	ircomm_state_waiti,
85	ircomm_state_waitr,
86	ircomm_state_conn,
87};
88
89/*
90 * Function ircomm_state_idle (self, event, skb)
91 *
92 *    IrCOMM is currently idle
93 *
94 */
95static int ircomm_state_idle(struct ircomm_cb *self, IRCOMM_EVENT event,
96			     struct sk_buff *skb, struct ircomm_info *info)
97{
98	int ret = 0;
99
100	switch (event) {
101	case IRCOMM_CONNECT_REQUEST:
102		ircomm_next_state(self, IRCOMM_WAITI);
103		ret = self->issue.connect_request(self, skb, info);
104		break;
105	case IRCOMM_TTP_CONNECT_INDICATION:
106	case IRCOMM_LMP_CONNECT_INDICATION:
107		ircomm_next_state(self, IRCOMM_WAITR);
108		ircomm_connect_indication(self, skb, info);
109		break;
110	default:
111		IRDA_DEBUG(4, "%s(), unknown event: %s\n", __func__ ,
112			   ircomm_event[event]);
113		ret = -EINVAL;
114	}
115	return ret;
116}
117
118/*
119 * Function ircomm_state_waiti (self, event, skb)
120 *
121 *    The IrCOMM user has requested an IrCOMM connection to the remote
122 *    device and is awaiting confirmation
123 */
124static int ircomm_state_waiti(struct ircomm_cb *self, IRCOMM_EVENT event,
125			      struct sk_buff *skb, struct ircomm_info *info)
126{
127	int ret = 0;
128
129	switch (event) {
130	case IRCOMM_TTP_CONNECT_CONFIRM:
131	case IRCOMM_LMP_CONNECT_CONFIRM:
132		ircomm_next_state(self, IRCOMM_CONN);
133		ircomm_connect_confirm(self, skb, info);
134		break;
135	case IRCOMM_TTP_DISCONNECT_INDICATION:
136	case IRCOMM_LMP_DISCONNECT_INDICATION:
137		ircomm_next_state(self, IRCOMM_IDLE);
138		ircomm_disconnect_indication(self, skb, info);
139		break;
140	default:
141		IRDA_DEBUG(0, "%s(), unknown event: %s\n", __func__ ,
142			   ircomm_event[event]);
143		ret = -EINVAL;
144	}
145	return ret;
146}
147
148/*
149 * Function ircomm_state_waitr (self, event, skb)
150 *
151 *    IrCOMM has received an incoming connection request and is awaiting
152 *    response from the user
153 */
154static int ircomm_state_waitr(struct ircomm_cb *self, IRCOMM_EVENT event,
155			      struct sk_buff *skb, struct ircomm_info *info)
156{
157	int ret = 0;
158
159	switch (event) {
160	case IRCOMM_CONNECT_RESPONSE:
161		ircomm_next_state(self, IRCOMM_CONN);
162		ret = self->issue.connect_response(self, skb);
163		break;
164	case IRCOMM_DISCONNECT_REQUEST:
165		ircomm_next_state(self, IRCOMM_IDLE);
166		ret = self->issue.disconnect_request(self, skb, info);
167		break;
168	case IRCOMM_TTP_DISCONNECT_INDICATION:
169	case IRCOMM_LMP_DISCONNECT_INDICATION:
170		ircomm_next_state(self, IRCOMM_IDLE);
171		ircomm_disconnect_indication(self, skb, info);
172		break;
173	default:
174		IRDA_DEBUG(0, "%s(), unknown event = %s\n", __func__ ,
175			   ircomm_event[event]);
176		ret = -EINVAL;
177	}
178	return ret;
179}
180
181/*
182 * Function ircomm_state_conn (self, event, skb)
183 *
184 *    IrCOMM is connected to the peer IrCOMM device
185 *
186 */
187static int ircomm_state_conn(struct ircomm_cb *self, IRCOMM_EVENT event,
188			     struct sk_buff *skb, struct ircomm_info *info)
189{
190	int ret = 0;
191
192	switch (event) {
193	case IRCOMM_DATA_REQUEST:
194		ret = self->issue.data_request(self, skb, 0);
195		break;
196	case IRCOMM_TTP_DATA_INDICATION:
197		ircomm_process_data(self, skb);
198		break;
199	case IRCOMM_LMP_DATA_INDICATION:
200		ircomm_data_indication(self, skb);
201		break;
202	case IRCOMM_CONTROL_REQUEST:
203		/* Just send a separate frame for now */
204		ret = self->issue.data_request(self, skb, skb->len);
205		break;
206	case IRCOMM_TTP_DISCONNECT_INDICATION:
207	case IRCOMM_LMP_DISCONNECT_INDICATION:
208		ircomm_next_state(self, IRCOMM_IDLE);
209		ircomm_disconnect_indication(self, skb, info);
210		break;
211	case IRCOMM_DISCONNECT_REQUEST:
212		ircomm_next_state(self, IRCOMM_IDLE);
213		ret = self->issue.disconnect_request(self, skb, info);
214		break;
215	default:
216		IRDA_DEBUG(0, "%s(), unknown event = %s\n", __func__ ,
217			   ircomm_event[event]);
218		ret = -EINVAL;
219	}
220	return ret;
221}
222
223/*
224 * Function ircomm_do_event (self, event, skb)
225 *
226 *    Process event
227 *
228 */
229int ircomm_do_event(struct ircomm_cb *self, IRCOMM_EVENT event,
230		    struct sk_buff *skb, struct ircomm_info *info)
231{
232	IRDA_DEBUG(4, "%s: state=%s, event=%s\n", __func__ ,
233		   ircomm_state[self->state], ircomm_event[event]);
234
235	return (*state[self->state])(self, event, skb, info);
236}
237
238/*
239 * Function ircomm_next_state (self, state)
240 *
241 *    Switch state
242 *
243 */
244void ircomm_next_state(struct ircomm_cb *self, IRCOMM_STATE state)
245{
246	self->state = state;
247
248	IRDA_DEBUG(4, "%s: next state=%s, service type=%d\n", __func__ ,
249		   ircomm_state[self->state], self->service_type);
250}
251