Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
ircomm_event.c
Go to the documentation of this file.
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) {
103  ret = self->issue.connect_request(self, skb, info);
104  break;
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) {
133  ircomm_connect_confirm(self, skb, info);
134  break;
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) {
162  ret = self->issue.connect_response(self, skb);
163  break;
166  ret = self->issue.disconnect_request(self, skb, info);
167  break;
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;
197  ircomm_process_data(self, skb);
198  break;
200  ircomm_data_indication(self, skb);
201  break;
203  /* Just send a separate frame for now */
204  ret = self->issue.data_request(self, skb, skb->len);
205  break;
209  ircomm_disconnect_indication(self, skb, info);
210  break;
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  */
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 }