Commit | Line | Data |
---|---|---|
1da177e4 | 1 | /********************************************************************* |
6819bc2e | 2 | * |
1da177e4 LT |
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> | |
6819bc2e | 11 | * |
1da177e4 | 12 | * Copyright (c) 1999 Dag Brattli, All Rights Reserved. |
6819bc2e YH |
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 | |
1da177e4 | 17 | * the License, or (at your option) any later version. |
6819bc2e | 18 | * |
1da177e4 LT |
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. | |
6819bc2e YH |
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, | |
1da177e4 | 27 | * MA 02111-1307 USA |
6819bc2e | 28 | * |
1da177e4 LT |
29 | ********************************************************************/ |
30 | ||
1da177e4 LT |
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 | ||
6819bc2e | 43 | static int ircomm_state_idle(struct ircomm_cb *self, IRCOMM_EVENT event, |
1da177e4 | 44 | struct sk_buff *skb, struct ircomm_info *info); |
6819bc2e | 45 | static int ircomm_state_waiti(struct ircomm_cb *self, IRCOMM_EVENT event, |
1da177e4 | 46 | struct sk_buff *skb, struct ircomm_info *info); |
6819bc2e | 47 | static int ircomm_state_waitr(struct ircomm_cb *self, IRCOMM_EVENT event, |
1da177e4 | 48 | struct sk_buff *skb, struct ircomm_info *info); |
6819bc2e | 49 | static int ircomm_state_conn(struct ircomm_cb *self, IRCOMM_EVENT event, |
1da177e4 LT |
50 | struct sk_buff *skb, struct ircomm_info *info); |
51 | ||
36cbd3dc | 52 | const char *const ircomm_state[] = { |
1da177e4 LT |
53 | "IRCOMM_IDLE", |
54 | "IRCOMM_WAITI", | |
55 | "IRCOMM_WAITR", | |
56 | "IRCOMM_CONN", | |
57 | }; | |
58 | ||
59 | #ifdef CONFIG_IRDA_DEBUG | |
36cbd3dc | 60 | static const char *const ircomm_event[] = { |
1da177e4 | 61 | "IRCOMM_CONNECT_REQUEST", |
6819bc2e YH |
62 | "IRCOMM_CONNECT_RESPONSE", |
63 | "IRCOMM_TTP_CONNECT_INDICATION", | |
1da177e4 | 64 | "IRCOMM_LMP_CONNECT_INDICATION", |
6819bc2e | 65 | "IRCOMM_TTP_CONNECT_CONFIRM", |
1da177e4 LT |
66 | "IRCOMM_LMP_CONNECT_CONFIRM", |
67 | ||
6819bc2e | 68 | "IRCOMM_LMP_DISCONNECT_INDICATION", |
1da177e4 | 69 | "IRCOMM_TTP_DISCONNECT_INDICATION", |
6819bc2e | 70 | "IRCOMM_DISCONNECT_REQUEST", |
1da177e4 | 71 | |
6819bc2e | 72 | "IRCOMM_TTP_DATA_INDICATION", |
1da177e4 | 73 | "IRCOMM_LMP_DATA_INDICATION", |
6819bc2e YH |
74 | "IRCOMM_DATA_REQUEST", |
75 | "IRCOMM_CONTROL_REQUEST", | |
76 | "IRCOMM_CONTROL_INDICATION", | |
1da177e4 LT |
77 | }; |
78 | #endif /* CONFIG_IRDA_DEBUG */ | |
79 | ||
80 | static int (*state[])(struct ircomm_cb *self, IRCOMM_EVENT event, | |
6819bc2e | 81 | struct sk_buff *skb, struct ircomm_info *info) = |
1da177e4 LT |
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 | */ | |
6819bc2e | 95 | static int ircomm_state_idle(struct ircomm_cb *self, IRCOMM_EVENT event, |
1da177e4 LT |
96 | struct sk_buff *skb, struct ircomm_info *info) |
97 | { | |
98 | int ret = 0; | |
99 | ||
100 | switch (event) { | |
101 | case IRCOMM_CONNECT_REQUEST: | |
6819bc2e | 102 | ircomm_next_state(self, IRCOMM_WAITI); |
1da177e4 LT |
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: | |
0dc47877 | 111 | IRDA_DEBUG(4, "%s(), unknown event: %s\n", __func__ , |
1da177e4 LT |
112 | ircomm_event[event]); |
113 | ret = -EINVAL; | |
114 | } | |
115 | return ret; | |
116 | } | |
117 | ||
118 | /* | |
119 | * Function ircomm_state_waiti (self, event, skb) | |
120 | * | |
6819bc2e | 121 | * The IrCOMM user has requested an IrCOMM connection to the remote |
1da177e4 LT |
122 | * device and is awaiting confirmation |
123 | */ | |
6819bc2e | 124 | static int ircomm_state_waiti(struct ircomm_cb *self, IRCOMM_EVENT event, |
1da177e4 LT |
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: | |
0dc47877 | 141 | IRDA_DEBUG(0, "%s(), unknown event: %s\n", __func__ , |
1da177e4 LT |
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 | */ | |
6819bc2e YH |
154 | static int ircomm_state_waitr(struct ircomm_cb *self, IRCOMM_EVENT event, |
155 | struct sk_buff *skb, struct ircomm_info *info) | |
1da177e4 LT |
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: | |
0dc47877 | 174 | IRDA_DEBUG(0, "%s(), unknown event = %s\n", __func__ , |
1da177e4 LT |
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 | */ | |
6819bc2e | 187 | static int ircomm_state_conn(struct ircomm_cb *self, IRCOMM_EVENT event, |
1da177e4 LT |
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: | |
0dc47877 | 216 | IRDA_DEBUG(0, "%s(), unknown event = %s\n", __func__ , |
1da177e4 LT |
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 | */ | |
229 | int ircomm_do_event(struct ircomm_cb *self, IRCOMM_EVENT event, | |
6819bc2e | 230 | struct sk_buff *skb, struct ircomm_info *info) |
1da177e4 | 231 | { |
0dc47877 | 232 | IRDA_DEBUG(4, "%s: state=%s, event=%s\n", __func__ , |
1da177e4 LT |
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 | */ | |
244 | void ircomm_next_state(struct ircomm_cb *self, IRCOMM_STATE state) | |
245 | { | |
246 | self->state = state; | |
6819bc2e | 247 | |
0dc47877 | 248 | IRDA_DEBUG(4, "%s: next state=%s, service type=%d\n", __func__ , |
1da177e4 LT |
249 | ircomm_state[self->state], self->service_type); |
250 | } |