Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
ircomm_ttp.c
Go to the documentation of this file.
1 /*********************************************************************
2  *
3  * Filename: ircomm_ttp.c
4  * Version: 1.0
5  * Description: Interface between IrCOMM and IrTTP
6  * Status: Stable
7  * Author: Dag Brattli <[email protected]>
8  * Created at: Sun Jun 6 20:48:27 1999
9  * Modified at: Mon Dec 13 11:35:13 1999
10  * Modified by: Dag Brattli <[email protected]>
11  *
12  * Copyright (c) 1999 Dag Brattli, All Rights Reserved.
13  * Copyright (c) 2000-2003 Jean Tourrilhes <[email protected]>
14  *
15  * This program is free software; you can redistribute it and/or
16  * modify it under the terms of the GNU General Public License as
17  * published by the Free Software Foundation; either version 2 of
18  * the License, or (at your option) any later version.
19  *
20  * This program is distributed in the hope that it will be useful,
21  * but WITHOUT ANY WARRANTY; without even the implied warranty of
22  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23  * GNU General Public License for more details.
24  *
25  * You should have received a copy of the GNU General Public License
26  * along with this program; if not, write to the Free Software
27  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
28  * MA 02111-1307 USA
29  *
30  ********************************************************************/
31 
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 
39 #include <net/irda/ircomm_event.h>
40 #include <net/irda/ircomm_ttp.h>
41 
42 static int ircomm_ttp_data_indication(void *instance, void *sap,
43  struct sk_buff *skb);
44 static void ircomm_ttp_connect_confirm(void *instance, void *sap,
45  struct qos_info *qos,
46  __u32 max_sdu_size,
48  struct sk_buff *skb);
49 static void ircomm_ttp_connect_indication(void *instance, void *sap,
50  struct qos_info *qos,
51  __u32 max_sdu_size,
53  struct sk_buff *skb);
54 static void ircomm_ttp_flow_indication(void *instance, void *sap,
55  LOCAL_FLOW cmd);
56 static void ircomm_ttp_disconnect_indication(void *instance, void *sap,
58  struct sk_buff *skb);
59 static int ircomm_ttp_data_request(struct ircomm_cb *self,
60  struct sk_buff *skb,
61  int clen);
62 static int ircomm_ttp_connect_request(struct ircomm_cb *self,
63  struct sk_buff *userdata,
64  struct ircomm_info *info);
65 static int ircomm_ttp_connect_response(struct ircomm_cb *self,
66  struct sk_buff *userdata);
67 static int ircomm_ttp_disconnect_request(struct ircomm_cb *self,
68  struct sk_buff *userdata,
69  struct ircomm_info *info);
70 
71 /*
72  * Function ircomm_open_tsap (self)
73  *
74  *
75  *
76  */
77 int ircomm_open_tsap(struct ircomm_cb *self)
78 {
80 
81  IRDA_DEBUG(4, "%s()\n", __func__ );
82 
83  /* Register callbacks */
84  irda_notify_init(&notify);
85  notify.data_indication = ircomm_ttp_data_indication;
86  notify.connect_confirm = ircomm_ttp_connect_confirm;
87  notify.connect_indication = ircomm_ttp_connect_indication;
88  notify.flow_indication = ircomm_ttp_flow_indication;
89  notify.disconnect_indication = ircomm_ttp_disconnect_indication;
90  notify.instance = self;
91  strlcpy(notify.name, "IrCOMM", sizeof(notify.name));
92 
94  &notify);
95  if (!self->tsap) {
96  IRDA_DEBUG(0, "%sfailed to allocate tsap\n", __func__ );
97  return -1;
98  }
99  self->slsap_sel = self->tsap->stsap_sel;
100 
101  /*
102  * Initialize the call-table for issuing commands
103  */
104  self->issue.data_request = ircomm_ttp_data_request;
105  self->issue.connect_request = ircomm_ttp_connect_request;
106  self->issue.connect_response = ircomm_ttp_connect_response;
107  self->issue.disconnect_request = ircomm_ttp_disconnect_request;
108 
109  return 0;
110 }
111 
112 /*
113  * Function ircomm_ttp_connect_request (self, userdata)
114  *
115  *
116  *
117  */
118 static int ircomm_ttp_connect_request(struct ircomm_cb *self,
119  struct sk_buff *userdata,
120  struct ircomm_info *info)
121 {
122  int ret = 0;
123 
124  IRDA_DEBUG(4, "%s()\n", __func__ );
125 
126  /* Don't forget to refcount it - should be NULL anyway */
127  if(userdata)
128  skb_get(userdata);
129 
130  ret = irttp_connect_request(self->tsap, info->dlsap_sel,
131  info->saddr, info->daddr, NULL,
132  TTP_SAR_DISABLE, userdata);
133 
134  return ret;
135 }
136 
137 /*
138  * Function ircomm_ttp_connect_response (self, skb)
139  *
140  *
141  *
142  */
143 static int ircomm_ttp_connect_response(struct ircomm_cb *self,
144  struct sk_buff *userdata)
145 {
146  int ret;
147 
148  IRDA_DEBUG(4, "%s()\n", __func__ );
149 
150  /* Don't forget to refcount it - should be NULL anyway */
151  if(userdata)
152  skb_get(userdata);
153 
154  ret = irttp_connect_response(self->tsap, TTP_SAR_DISABLE, userdata);
155 
156  return ret;
157 }
158 
159 /*
160  * Function ircomm_ttp_data_request (self, userdata)
161  *
162  * Send IrCOMM data to IrTTP layer. Currently we do not try to combine
163  * control data with pure data, so they will be sent as separate frames.
164  * Should not be a big problem though, since control frames are rare. But
165  * some of them are sent after connection establishment, so this can
166  * increase the latency a bit.
167  */
168 static int ircomm_ttp_data_request(struct ircomm_cb *self,
169  struct sk_buff *skb,
170  int clen)
171 {
172  int ret;
173 
174  IRDA_ASSERT(skb != NULL, return -1;);
175 
176  IRDA_DEBUG(2, "%s(), clen=%d\n", __func__ , clen);
177 
178  /*
179  * Insert clen field, currently we either send data only, or control
180  * only frames, to make things easier and avoid queueing
181  */
182  IRDA_ASSERT(skb_headroom(skb) >= IRCOMM_HEADER_SIZE, return -1;);
183 
184  /* Don't forget to refcount it - see ircomm_tty_do_softint() */
185  skb_get(skb);
186 
188 
189  skb->data[0] = clen;
190 
191  ret = irttp_data_request(self->tsap, skb);
192  if (ret) {
193  IRDA_ERROR("%s(), failed\n", __func__);
194  /* irttp_data_request already free the packet */
195  }
196 
197  return ret;
198 }
199 
200 /*
201  * Function ircomm_ttp_data_indication (instance, sap, skb)
202  *
203  * Incoming data
204  *
205  */
206 static int ircomm_ttp_data_indication(void *instance, void *sap,
207  struct sk_buff *skb)
208 {
209  struct ircomm_cb *self = (struct ircomm_cb *) instance;
210 
211  IRDA_DEBUG(4, "%s()\n", __func__ );
212 
213  IRDA_ASSERT(self != NULL, return -1;);
214  IRDA_ASSERT(self->magic == IRCOMM_MAGIC, return -1;);
215  IRDA_ASSERT(skb != NULL, return -1;);
216 
218 
219  /* Drop reference count - see ircomm_tty_data_indication(). */
220  dev_kfree_skb(skb);
221 
222  return 0;
223 }
224 
225 static void ircomm_ttp_connect_confirm(void *instance, void *sap,
226  struct qos_info *qos,
227  __u32 max_sdu_size,
229  struct sk_buff *skb)
230 {
231  struct ircomm_cb *self = (struct ircomm_cb *) instance;
232  struct ircomm_info info;
233 
234  IRDA_DEBUG(4, "%s()\n", __func__ );
235 
236  IRDA_ASSERT(self != NULL, return;);
237  IRDA_ASSERT(self->magic == IRCOMM_MAGIC, return;);
238  IRDA_ASSERT(skb != NULL, return;);
239  IRDA_ASSERT(qos != NULL, goto out;);
240 
241  if (max_sdu_size != TTP_SAR_DISABLE) {
242  IRDA_ERROR("%s(), SAR not allowed for IrCOMM!\n",
243  __func__);
244  goto out;
245  }
246 
247  info.max_data_size = irttp_get_max_seg_size(self->tsap)
249  info.max_header_size = max_header_size + IRCOMM_HEADER_SIZE;
250  info.qos = qos;
251 
252  ircomm_do_event(self, IRCOMM_TTP_CONNECT_CONFIRM, skb, &info);
253 
254 out:
255  /* Drop reference count - see ircomm_tty_connect_confirm(). */
256  dev_kfree_skb(skb);
257 }
258 
259 /*
260  * Function ircomm_ttp_connect_indication (instance, sap, qos, max_sdu_size,
261  * max_header_size, skb)
262  *
263  *
264  *
265  */
266 static void ircomm_ttp_connect_indication(void *instance, void *sap,
267  struct qos_info *qos,
268  __u32 max_sdu_size,
269  __u8 max_header_size,
270  struct sk_buff *skb)
271 {
272  struct ircomm_cb *self = (struct ircomm_cb *)instance;
273  struct ircomm_info info;
274 
275  IRDA_DEBUG(4, "%s()\n", __func__ );
276 
277  IRDA_ASSERT(self != NULL, return;);
278  IRDA_ASSERT(self->magic == IRCOMM_MAGIC, return;);
279  IRDA_ASSERT(skb != NULL, return;);
280  IRDA_ASSERT(qos != NULL, goto out;);
281 
282  if (max_sdu_size != TTP_SAR_DISABLE) {
283  IRDA_ERROR("%s(), SAR not allowed for IrCOMM!\n",
284  __func__);
285  goto out;
286  }
287 
288  info.max_data_size = irttp_get_max_seg_size(self->tsap)
290  info.max_header_size = max_header_size + IRCOMM_HEADER_SIZE;
291  info.qos = qos;
292 
294 
295 out:
296  /* Drop reference count - see ircomm_tty_connect_indication(). */
297  dev_kfree_skb(skb);
298 }
299 
300 /*
301  * Function ircomm_ttp_disconnect_request (self, userdata, info)
302  *
303  *
304  *
305  */
306 static int ircomm_ttp_disconnect_request(struct ircomm_cb *self,
307  struct sk_buff *userdata,
308  struct ircomm_info *info)
309 {
310  int ret;
311 
312  /* Don't forget to refcount it - should be NULL anyway */
313  if(userdata)
314  skb_get(userdata);
315 
316  ret = irttp_disconnect_request(self->tsap, userdata, P_NORMAL);
317 
318  return ret;
319 }
320 
321 /*
322  * Function ircomm_ttp_disconnect_indication (instance, sap, reason, skb)
323  *
324  *
325  *
326  */
327 static void ircomm_ttp_disconnect_indication(void *instance, void *sap,
329  struct sk_buff *skb)
330 {
331  struct ircomm_cb *self = (struct ircomm_cb *) instance;
332  struct ircomm_info info;
333 
334  IRDA_DEBUG(2, "%s()\n", __func__ );
335 
336  IRDA_ASSERT(self != NULL, return;);
337  IRDA_ASSERT(self->magic == IRCOMM_MAGIC, return;);
338 
339  info.reason = reason;
340 
342 
343  /* Drop reference count - see ircomm_tty_disconnect_indication(). */
344  if(skb)
345  dev_kfree_skb(skb);
346 }
347 
348 /*
349  * Function ircomm_ttp_flow_indication (instance, sap, cmd)
350  *
351  * Layer below is telling us to start or stop the flow of data
352  *
353  */
354 static void ircomm_ttp_flow_indication(void *instance, void *sap,
355  LOCAL_FLOW cmd)
356 {
357  struct ircomm_cb *self = (struct ircomm_cb *) instance;
358 
359  IRDA_DEBUG(4, "%s()\n", __func__ );
360 
361  IRDA_ASSERT(self != NULL, return;);
362  IRDA_ASSERT(self->magic == IRCOMM_MAGIC, return;);
363 
364  if (self->notify.flow_indication)
365  self->notify.flow_indication(self->notify.instance, self, cmd);
366 }
367 
368