]> git.karo-electronics.de Git - mv-sheeva.git/blob - net/irda/irlan/irlan_client.c
include cleanup: Update gfp.h and slab.h includes to prepare for breaking implicit...
[mv-sheeva.git] / net / irda / irlan / irlan_client.c
1 /*********************************************************************
2  *
3  * Filename:      irlan_client.c
4  * Version:       0.9
5  * Description:   IrDA LAN Access Protocol (IrLAN) Client
6  * Status:        Experimental.
7  * Author:        Dag Brattli <dagb@cs.uit.no>
8  * Created at:    Sun Aug 31 20:14:37 1997
9  * Modified at:   Tue Dec 14 15:47:02 1999
10  * Modified by:   Dag Brattli <dagb@cs.uit.no>
11  * Sources:       skeleton.c by Donald Becker <becker@CESDIS.gsfc.nasa.gov>
12  *                slip.c by Laurence Culhane, <loz@holmes.demon.co.uk>
13  *                          Fred N. van Kempen, <waltje@uwalt.nl.mugnet.org>
14  *
15  *     Copyright (c) 1998-1999 Dag Brattli <dagb@cs.uit.no>,
16  *     All Rights Reserved.
17  *
18  *     This program is free software; you can redistribute it and/or
19  *     modify it under the terms of the GNU General Public License as
20  *     published by the Free Software Foundation; either version 2 of
21  *     the License, or (at your option) any later version.
22  *
23  *     Neither Dag Brattli nor University of Tromsø admit liability nor
24  *     provide warranty for any of this software. This material is
25  *     provided "AS-IS" and at no charge.
26  *
27  ********************************************************************/
28
29 #include <linux/kernel.h>
30 #include <linux/string.h>
31 #include <linux/slab.h>
32 #include <linux/errno.h>
33 #include <linux/init.h>
34 #include <linux/netdevice.h>
35 #include <linux/etherdevice.h>
36 #include <linux/if_arp.h>
37 #include <linux/bitops.h>
38 #include <net/arp.h>
39
40 #include <asm/system.h>
41 #include <asm/byteorder.h>
42
43 #include <net/irda/irda.h>
44 #include <net/irda/irttp.h>
45 #include <net/irda/irlmp.h>
46 #include <net/irda/irias_object.h>
47 #include <net/irda/iriap.h>
48 #include <net/irda/timer.h>
49
50 #include <net/irda/irlan_common.h>
51 #include <net/irda/irlan_event.h>
52 #include <net/irda/irlan_eth.h>
53 #include <net/irda/irlan_provider.h>
54 #include <net/irda/irlan_client.h>
55
56 #undef CONFIG_IRLAN_GRATUITOUS_ARP
57
58 static void irlan_client_ctrl_disconnect_indication(void *instance, void *sap,
59                                                     LM_REASON reason,
60                                                     struct sk_buff *);
61 static int irlan_client_ctrl_data_indication(void *instance, void *sap,
62                                              struct sk_buff *skb);
63 static void irlan_client_ctrl_connect_confirm(void *instance, void *sap,
64                                               struct qos_info *qos,
65                                               __u32 max_sdu_size,
66                                               __u8 max_header_size,
67                                               struct sk_buff *);
68 static void irlan_check_response_param(struct irlan_cb *self, char *param,
69                                        char *value, int val_len);
70 static void irlan_client_open_ctrl_tsap(struct irlan_cb *self);
71
72 static void irlan_client_kick_timer_expired(void *data)
73 {
74         struct irlan_cb *self = (struct irlan_cb *) data;
75
76         IRDA_DEBUG(2, "%s()\n", __func__ );
77
78         IRDA_ASSERT(self != NULL, return;);
79         IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);
80
81         /*
82          * If we are in peer mode, the client may not have got the discovery
83          * indication it needs to make progress. If the client is still in
84          * IDLE state, we must kick it to, but only if the provider is not IDLE
85          */
86         if ((self->provider.access_type == ACCESS_PEER) &&
87             (self->client.state == IRLAN_IDLE) &&
88             (self->provider.state != IRLAN_IDLE)) {
89                 irlan_client_wakeup(self, self->saddr, self->daddr);
90         }
91 }
92
93 static void irlan_client_start_kick_timer(struct irlan_cb *self, int timeout)
94 {
95         IRDA_DEBUG(4, "%s()\n", __func__ );
96
97         irda_start_timer(&self->client.kick_timer, timeout, (void *) self,
98                          irlan_client_kick_timer_expired);
99 }
100
101 /*
102  * Function irlan_client_wakeup (self, saddr, daddr)
103  *
104  *    Wake up client
105  *
106  */
107 void irlan_client_wakeup(struct irlan_cb *self, __u32 saddr, __u32 daddr)
108 {
109         IRDA_DEBUG(1, "%s()\n", __func__ );
110
111         IRDA_ASSERT(self != NULL, return;);
112         IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);
113
114         /*
115          * Check if we are already awake, or if we are a provider in direct
116          * mode (in that case we must leave the client idle
117          */
118         if ((self->client.state != IRLAN_IDLE) ||
119             (self->provider.access_type == ACCESS_DIRECT))
120         {
121                         IRDA_DEBUG(0, "%s(), already awake!\n", __func__ );
122                         return;
123         }
124
125         /* Addresses may have changed! */
126         self->saddr = saddr;
127         self->daddr = daddr;
128
129         if (self->disconnect_reason == LM_USER_REQUEST) {
130                         IRDA_DEBUG(0, "%s(), still stopped by user\n", __func__ );
131                         return;
132         }
133
134         /* Open TSAPs */
135         irlan_client_open_ctrl_tsap(self);
136         irlan_open_data_tsap(self);
137
138         irlan_do_client_event(self, IRLAN_DISCOVERY_INDICATION, NULL);
139
140         /* Start kick timer */
141         irlan_client_start_kick_timer(self, 2*HZ);
142 }
143
144 /*
145  * Function irlan_discovery_indication (daddr)
146  *
147  *    Remote device with IrLAN server support discovered
148  *
149  */
150 void irlan_client_discovery_indication(discinfo_t *discovery,
151                                        DISCOVERY_MODE mode,
152                                        void *priv)
153 {
154         struct irlan_cb *self;
155         __u32 saddr, daddr;
156
157         IRDA_DEBUG(1, "%s()\n", __func__ );
158
159         IRDA_ASSERT(discovery != NULL, return;);
160
161         /*
162          * I didn't check it, but I bet that IrLAN suffer from the same
163          * deficiency as IrComm and doesn't handle two instances
164          * simultaneously connecting to each other.
165          * Same workaround, drop passive discoveries.
166          * Jean II */
167         if(mode == DISCOVERY_PASSIVE)
168                 return;
169
170         saddr = discovery->saddr;
171         daddr = discovery->daddr;
172
173         /* Find instance */
174         rcu_read_lock();
175         self = irlan_get_any();
176         if (self) {
177                 IRDA_ASSERT(self->magic == IRLAN_MAGIC, goto out;);
178
179                 IRDA_DEBUG(1, "%s(), Found instance (%08x)!\n", __func__ ,
180                       daddr);
181
182                 irlan_client_wakeup(self, saddr, daddr);
183         }
184 IRDA_ASSERT_LABEL(out:)
185         rcu_read_unlock();
186 }
187
188 /*
189  * Function irlan_client_data_indication (handle, skb)
190  *
191  *    This function gets the data that is received on the control channel
192  *
193  */
194 static int irlan_client_ctrl_data_indication(void *instance, void *sap,
195                                              struct sk_buff *skb)
196 {
197         struct irlan_cb *self;
198
199         IRDA_DEBUG(2, "%s()\n", __func__ );
200
201         self = (struct irlan_cb *) instance;
202
203         IRDA_ASSERT(self != NULL, return -1;);
204         IRDA_ASSERT(self->magic == IRLAN_MAGIC, return -1;);
205         IRDA_ASSERT(skb != NULL, return -1;);
206
207         irlan_do_client_event(self, IRLAN_DATA_INDICATION, skb);
208
209         /* Ready for a new command */
210         IRDA_DEBUG(2, "%s(), clearing tx_busy\n", __func__ );
211         self->client.tx_busy = FALSE;
212
213         /* Check if we have some queued commands waiting to be sent */
214         irlan_run_ctrl_tx_queue(self);
215
216         return 0;
217 }
218
219 static void irlan_client_ctrl_disconnect_indication(void *instance, void *sap,
220                                                     LM_REASON reason,
221                                                     struct sk_buff *userdata)
222 {
223         struct irlan_cb *self;
224         struct tsap_cb *tsap;
225         struct sk_buff *skb;
226
227         IRDA_DEBUG(4, "%s(), reason=%d\n", __func__ , reason);
228
229         self = (struct irlan_cb *) instance;
230         tsap = (struct tsap_cb *) sap;
231
232         IRDA_ASSERT(self != NULL, return;);
233         IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);
234         IRDA_ASSERT(tsap != NULL, return;);
235         IRDA_ASSERT(tsap->magic == TTP_TSAP_MAGIC, return;);
236
237         IRDA_ASSERT(tsap == self->client.tsap_ctrl, return;);
238
239         /* Remove frames queued on the control channel */
240         while ((skb = skb_dequeue(&self->client.txq)) != NULL) {
241                 dev_kfree_skb(skb);
242         }
243         self->client.tx_busy = FALSE;
244
245         irlan_do_client_event(self, IRLAN_LMP_DISCONNECT, NULL);
246 }
247
248 /*
249  * Function irlan_client_open_tsaps (self)
250  *
251  *    Initialize callbacks and open IrTTP TSAPs
252  *
253  */
254 static void irlan_client_open_ctrl_tsap(struct irlan_cb *self)
255 {
256         struct tsap_cb *tsap;
257         notify_t notify;
258
259         IRDA_DEBUG(4, "%s()\n", __func__ );
260
261         IRDA_ASSERT(self != NULL, return;);
262         IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);
263
264         /* Check if already open */
265         if (self->client.tsap_ctrl)
266                 return;
267
268         irda_notify_init(&notify);
269
270         /* Set up callbacks */
271         notify.data_indication       = irlan_client_ctrl_data_indication;
272         notify.connect_confirm       = irlan_client_ctrl_connect_confirm;
273         notify.disconnect_indication = irlan_client_ctrl_disconnect_indication;
274         notify.instance = self;
275         strlcpy(notify.name, "IrLAN ctrl (c)", sizeof(notify.name));
276
277         tsap = irttp_open_tsap(LSAP_ANY, DEFAULT_INITIAL_CREDIT, &notify);
278         if (!tsap) {
279                 IRDA_DEBUG(2, "%s(), Got no tsap!\n", __func__ );
280                 return;
281         }
282         self->client.tsap_ctrl = tsap;
283 }
284
285 /*
286  * Function irlan_client_connect_confirm (handle, skb)
287  *
288  *    Connection to peer IrLAN laye confirmed
289  *
290  */
291 static void irlan_client_ctrl_connect_confirm(void *instance, void *sap,
292                                               struct qos_info *qos,
293                                               __u32 max_sdu_size,
294                                               __u8 max_header_size,
295                                               struct sk_buff *skb)
296 {
297         struct irlan_cb *self;
298
299         IRDA_DEBUG(4, "%s()\n", __func__ );
300
301         self = (struct irlan_cb *) instance;
302
303         IRDA_ASSERT(self != NULL, return;);
304         IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);
305
306         self->client.max_sdu_size = max_sdu_size;
307         self->client.max_header_size = max_header_size;
308
309         /* TODO: we could set the MTU depending on the max_sdu_size */
310
311         irlan_do_client_event(self, IRLAN_CONNECT_COMPLETE, NULL);
312 }
313
314 /*
315  * Function print_ret_code (code)
316  *
317  *    Print return code of request to peer IrLAN layer.
318  *
319  */
320 static void print_ret_code(__u8 code)
321 {
322         switch(code) {
323         case 0:
324                 printk(KERN_INFO "Success\n");
325                 break;
326         case 1:
327                 IRDA_WARNING("IrLAN: Insufficient resources\n");
328                 break;
329         case 2:
330                 IRDA_WARNING("IrLAN: Invalid command format\n");
331                 break;
332         case 3:
333                 IRDA_WARNING("IrLAN: Command not supported\n");
334                 break;
335         case 4:
336                 IRDA_WARNING("IrLAN: Parameter not supported\n");
337                 break;
338         case 5:
339                 IRDA_WARNING("IrLAN: Value not supported\n");
340                 break;
341         case 6:
342                 IRDA_WARNING("IrLAN: Not open\n");
343                 break;
344         case 7:
345                 IRDA_WARNING("IrLAN: Authentication required\n");
346                 break;
347         case 8:
348                 IRDA_WARNING("IrLAN: Invalid password\n");
349                 break;
350         case 9:
351                 IRDA_WARNING("IrLAN: Protocol error\n");
352                 break;
353         case 255:
354                 IRDA_WARNING("IrLAN: Asynchronous status\n");
355                 break;
356         }
357 }
358
359 /*
360  * Function irlan_client_parse_response (self, skb)
361  *
362  *    Extract all parameters from received buffer, then feed them to
363  *    check_params for parsing
364  */
365 void irlan_client_parse_response(struct irlan_cb *self, struct sk_buff *skb)
366 {
367         __u8 *frame;
368         __u8 *ptr;
369         int count;
370         int ret;
371         __u16 val_len;
372         int i;
373         char *name;
374         char *value;
375
376         IRDA_ASSERT(skb != NULL, return;);
377
378         IRDA_DEBUG(4, "%s() skb->len=%d\n", __func__ , (int) skb->len);
379
380         IRDA_ASSERT(self != NULL, return;);
381         IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);
382
383         if (!skb) {
384                 IRDA_ERROR("%s(), Got NULL skb!\n", __func__);
385                 return;
386         }
387         frame = skb->data;
388
389         /*
390          *  Check return code and print it if not success
391          */
392         if (frame[0]) {
393                 print_ret_code(frame[0]);
394                 return;
395         }
396
397         name = kmalloc(255, GFP_ATOMIC);
398         if (!name)
399                 return;
400         value = kmalloc(1016, GFP_ATOMIC);
401         if (!value) {
402                 kfree(name);
403                 return;
404         }
405
406         /* How many parameters? */
407         count = frame[1];
408
409         IRDA_DEBUG(4, "%s(), got %d parameters\n", __func__ , count);
410
411         ptr = frame+2;
412
413         /* For all parameters */
414         for (i=0; i<count;i++) {
415                 ret = irlan_extract_param(ptr, name, value, &val_len);
416                 if (ret < 0) {
417                         IRDA_DEBUG(2, "%s(), IrLAN, Error!\n", __func__ );
418                         break;
419                 }
420                 ptr += ret;
421                 irlan_check_response_param(self, name, value, val_len);
422         }
423         /* Cleanup */
424         kfree(name);
425         kfree(value);
426 }
427
428 /*
429  * Function irlan_check_response_param (self, param, value, val_len)
430  *
431  *     Check which parameter is received and update local variables
432  *
433  */
434 static void irlan_check_response_param(struct irlan_cb *self, char *param,
435                                        char *value, int val_len)
436 {
437         __u16 tmp_cpu; /* Temporary value in host order */
438         __u8 *bytes;
439         int i;
440
441         IRDA_DEBUG(4, "%s(), parm=%s\n", __func__ , param);
442
443         IRDA_ASSERT(self != NULL, return;);
444         IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);
445
446         /* Media type */
447         if (strcmp(param, "MEDIA") == 0) {
448                 if (strcmp(value, "802.3") == 0)
449                         self->media = MEDIA_802_3;
450                 else
451                         self->media = MEDIA_802_5;
452                 return;
453         }
454         if (strcmp(param, "FILTER_TYPE") == 0) {
455                 if (strcmp(value, "DIRECTED") == 0)
456                         self->client.filter_type |= IRLAN_DIRECTED;
457                 else if (strcmp(value, "FUNCTIONAL") == 0)
458                         self->client.filter_type |= IRLAN_FUNCTIONAL;
459                 else if (strcmp(value, "GROUP") == 0)
460                         self->client.filter_type |= IRLAN_GROUP;
461                 else if (strcmp(value, "MAC_FRAME") == 0)
462                         self->client.filter_type |= IRLAN_MAC_FRAME;
463                 else if (strcmp(value, "MULTICAST") == 0)
464                         self->client.filter_type |= IRLAN_MULTICAST;
465                 else if (strcmp(value, "BROADCAST") == 0)
466                         self->client.filter_type |= IRLAN_BROADCAST;
467                 else if (strcmp(value, "IPX_SOCKET") == 0)
468                         self->client.filter_type |= IRLAN_IPX_SOCKET;
469
470         }
471         if (strcmp(param, "ACCESS_TYPE") == 0) {
472                 if (strcmp(value, "DIRECT") == 0)
473                         self->client.access_type = ACCESS_DIRECT;
474                 else if (strcmp(value, "PEER") == 0)
475                         self->client.access_type = ACCESS_PEER;
476                 else if (strcmp(value, "HOSTED") == 0)
477                         self->client.access_type = ACCESS_HOSTED;
478                 else {
479                         IRDA_DEBUG(2, "%s(), unknown access type!\n", __func__ );
480                 }
481         }
482         /* IRLAN version */
483         if (strcmp(param, "IRLAN_VER") == 0) {
484                 IRDA_DEBUG(4, "IrLAN version %d.%d\n", (__u8) value[0],
485                       (__u8) value[1]);
486
487                 self->version[0] = value[0];
488                 self->version[1] = value[1];
489                 return;
490         }
491         /* Which remote TSAP to use for data channel */
492         if (strcmp(param, "DATA_CHAN") == 0) {
493                 self->dtsap_sel_data = value[0];
494                 IRDA_DEBUG(4, "Data TSAP = %02x\n", self->dtsap_sel_data);
495                 return;
496         }
497         if (strcmp(param, "CON_ARB") == 0) {
498                 memcpy(&tmp_cpu, value, 2); /* Align value */
499                 le16_to_cpus(&tmp_cpu);     /* Convert to host order */
500                 self->client.recv_arb_val = tmp_cpu;
501                 IRDA_DEBUG(2, "%s(), receive arb val=%d\n", __func__ ,
502                            self->client.recv_arb_val);
503         }
504         if (strcmp(param, "MAX_FRAME") == 0) {
505                 memcpy(&tmp_cpu, value, 2); /* Align value */
506                 le16_to_cpus(&tmp_cpu);     /* Convert to host order */
507                 self->client.max_frame = tmp_cpu;
508                 IRDA_DEBUG(4, "%s(), max frame=%d\n", __func__ ,
509                            self->client.max_frame);
510         }
511
512         /* RECONNECT_KEY, in case the link goes down! */
513         if (strcmp(param, "RECONNECT_KEY") == 0) {
514                 IRDA_DEBUG(4, "Got reconnect key: ");
515                 /* for (i = 0; i < val_len; i++) */
516 /*                      printk("%02x", value[i]); */
517                 memcpy(self->client.reconnect_key, value, val_len);
518                 self->client.key_len = val_len;
519                 IRDA_DEBUG(4, "\n");
520         }
521         /* FILTER_ENTRY, have we got an ethernet address? */
522         if (strcmp(param, "FILTER_ENTRY") == 0) {
523                 bytes = value;
524                 IRDA_DEBUG(4, "Ethernet address = %pM\n", bytes);
525                 for (i = 0; i < 6; i++)
526                         self->dev->dev_addr[i] = bytes[i];
527         }
528 }
529
530 /*
531  * Function irlan_client_get_value_confirm (obj_id, value)
532  *
533  *    Got results from remote LM-IAS
534  *
535  */
536 void irlan_client_get_value_confirm(int result, __u16 obj_id,
537                                     struct ias_value *value, void *priv)
538 {
539         struct irlan_cb *self;
540
541         IRDA_DEBUG(4, "%s()\n", __func__ );
542
543         IRDA_ASSERT(priv != NULL, return;);
544
545         self = (struct irlan_cb *) priv;
546         IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);
547
548         /* We probably don't need to make any more queries */
549         iriap_close(self->client.iriap);
550         self->client.iriap = NULL;
551
552         /* Check if request succeeded */
553         if (result != IAS_SUCCESS) {
554                 IRDA_DEBUG(2, "%s(), got NULL value!\n", __func__ );
555                 irlan_do_client_event(self, IRLAN_IAS_PROVIDER_NOT_AVAIL,
556                                       NULL);
557                 return;
558         }
559
560         switch (value->type) {
561         case IAS_INTEGER:
562                 self->dtsap_sel_ctrl = value->t.integer;
563
564                 if (value->t.integer != -1) {
565                         irlan_do_client_event(self, IRLAN_IAS_PROVIDER_AVAIL,
566                                               NULL);
567                         return;
568                 }
569                 irias_delete_value(value);
570                 break;
571         default:
572                 IRDA_DEBUG(2, "%s(), unknown type!\n", __func__ );
573                 break;
574         }
575         irlan_do_client_event(self, IRLAN_IAS_PROVIDER_NOT_AVAIL, NULL);
576 }