Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/net/irda/ircomm/ircomm_event.c
15111 views
1
/*********************************************************************
2
*
3
* Filename: ircomm_event.c
4
* Version: 1.0
5
* Description: IrCOMM layer state machine
6
* Status: Stable
7
* Author: Dag Brattli <[email protected]>
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 <[email protected]>
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
43
static int ircomm_state_idle(struct ircomm_cb *self, IRCOMM_EVENT event,
44
struct sk_buff *skb, struct ircomm_info *info);
45
static int ircomm_state_waiti(struct ircomm_cb *self, IRCOMM_EVENT event,
46
struct sk_buff *skb, struct ircomm_info *info);
47
static int ircomm_state_waitr(struct ircomm_cb *self, IRCOMM_EVENT event,
48
struct sk_buff *skb, struct ircomm_info *info);
49
static int ircomm_state_conn(struct ircomm_cb *self, IRCOMM_EVENT event,
50
struct sk_buff *skb, struct ircomm_info *info);
51
52
const char *const ircomm_state[] = {
53
"IRCOMM_IDLE",
54
"IRCOMM_WAITI",
55
"IRCOMM_WAITR",
56
"IRCOMM_CONN",
57
};
58
59
#ifdef CONFIG_IRDA_DEBUG
60
static 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
80
static 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
*/
95
static 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
*/
124
static 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
*/
154
static 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
*/
187
static 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
*/
229
int 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
*/
244
void 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
252