9f9338017a04020dcca0c6c1e13754ee745cfe8e
[linux-flexiantxendom0-3.2.10.git] / net / irda / irlan / irlan_common.c
1 /*********************************************************************
2  *                
3  * Filename:      irlan_common.c
4  * Version:       0.9
5  * Description:   IrDA LAN Access Protocol Implementation
6  * Status:        Experimental.
7  * Author:        Dag Brattli <dagb@cs.uit.no>
8  * Created at:    Sun Aug 31 20:14:37 1997
9  * Modified at:   Sun Dec 26 21:53:10 1999
10  * Modified by:   Dag Brattli <dagb@cs.uit.no>
11  * 
12  *     Copyright (c) 1997, 1999 Dag Brattli <dagb@cs.uit.no>, 
13  *     All Rights Reserved.
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  *     Neither Dag Brattli nor University of Tromsø admit liability nor
21  *     provide warranty for any of this software. This material is 
22  *     provided "AS-IS" and at no charge.
23  *
24  ********************************************************************/
25
26 #include <linux/config.h>
27 #include <linux/module.h>
28
29 #include <linux/kernel.h>
30 #include <linux/string.h>
31 #include <linux/init.h>
32 #include <linux/errno.h>
33 #include <linux/proc_fs.h>
34 #include <linux/netdevice.h>
35 #include <linux/etherdevice.h>
36
37 #include <asm/system.h>
38 #include <asm/bitops.h>
39 #include <asm/byteorder.h>
40
41 #include <net/irda/irda.h>
42 #include <net/irda/irttp.h>
43 #include <net/irda/irlmp.h>
44 #include <net/irda/iriap.h>
45 #include <net/irda/timer.h>
46
47 #include <net/irda/irlan_common.h>
48 #include <net/irda/irlan_client.h>
49 #include <net/irda/irlan_provider.h> 
50 #include <net/irda/irlan_eth.h>
51 #include <net/irda/irlan_filter.h>
52
53
54 /* 
55  * Send gratuitous ARP when connected to a new AP or not. May be a clever
56  * thing to do, but for some reason the machine crashes if you use DHCP. So
57  * lets not use it by default.
58  */
59 #undef CONFIG_IRLAN_SEND_GRATUITOUS_ARP
60
61 /* extern char sysctl_devname[]; */
62
63 /*
64  *  Master structure
65  */
66 hashbin_t *irlan = NULL;
67 static void *ckey;
68 static void *skey;
69
70 /* Module parameters */
71 static int eth = 0; /* Use "eth" or "irlan" name for devices */
72 static int access = ACCESS_PEER; /* PEER, DIRECT or HOSTED */
73
74 #ifdef CONFIG_PROC_FS
75 static char *irlan_state[] = {
76         "IRLAN_IDLE",
77         "IRLAN_QUERY",
78         "IRLAN_CONN", 
79         "IRLAN_INFO",
80         "IRLAN_MEDIA",
81         "IRLAN_OPEN",
82         "IRLAN_WAIT",
83         "IRLAN_ARB", 
84         "IRLAN_DATA",
85         "IRLAN_CLOSE",
86         "IRLAN_SYNC"
87 };
88
89 static char *irlan_access[] = {
90         "UNKNOWN",
91         "DIRECT",
92         "PEER",
93         "HOSTED"
94 };
95
96 static char *irlan_media[] = {
97         "UNKNOWN",
98         "802.3",
99         "802.5"
100 };
101 #endif /* CONFIG_PROC_FS */
102
103 static void __irlan_close(struct irlan_cb *self);
104 static int __irlan_insert_param(struct sk_buff *skb, char *param, int type, 
105                                 __u8 value_byte, __u16 value_short, 
106                                 __u8 *value_array, __u16 value_len);
107 void irlan_close_tsaps(struct irlan_cb *self);
108
109 #ifdef CONFIG_PROC_FS
110 static int irlan_proc_read(char *buf, char **start, off_t offset, int len);
111
112 extern struct proc_dir_entry *proc_irda;
113 #endif /* CONFIG_PROC_FS */
114
115 /*
116  * Function irlan_init (void)
117  *
118  *    Initialize IrLAN layer
119  *
120  */
121 int __init irlan_init(void)
122 {
123         struct irlan_cb *new;
124         __u16 hints;
125
126         IRDA_DEBUG(0, "%s()\n", __FUNCTION__ );
127         /* Allocate master structure */
128         irlan = hashbin_new(HB_LOCK);   /* protect from /proc */
129         if (irlan == NULL) {
130                 printk(KERN_WARNING "IrLAN: Can't allocate hashbin!\n");
131                 return -ENOMEM;
132         }
133 #ifdef CONFIG_PROC_FS
134         create_proc_info_entry("irlan", 0, proc_irda, irlan_proc_read);
135 #endif /* CONFIG_PROC_FS */
136
137         IRDA_DEBUG(4, "%s()\n", __FUNCTION__ );
138         hints = irlmp_service_to_hint(S_LAN);
139
140         /* Register with IrLMP as a client */
141         ckey = irlmp_register_client(hints, &irlan_client_discovery_indication,
142                                      NULL, NULL);
143         
144         /* Register with IrLMP as a service */
145         skey = irlmp_register_service(hints);
146
147         /* Start the master IrLAN instance (the only one for now) */
148         new = irlan_open(DEV_ADDR_ANY, DEV_ADDR_ANY);
149
150         /* The master will only open its (listen) control TSAP */
151         irlan_provider_open_ctrl_tsap(new);
152
153         /* Do some fast discovery! */
154         irlmp_discovery_request(DISCOVERY_DEFAULT_SLOTS);
155
156         return 0;
157 }
158
159 void __exit irlan_cleanup(void) 
160 {
161         IRDA_DEBUG(4, "%s()\n", __FUNCTION__ );
162
163         irlmp_unregister_client(ckey);
164         irlmp_unregister_service(skey);
165
166 #ifdef CONFIG_PROC_FS
167         remove_proc_entry("irlan", proc_irda);
168 #endif /* CONFIG_PROC_FS */
169         /*
170          *  Delete hashbin and close all irlan client instances in it
171          */
172         hashbin_delete(irlan, (FREE_FUNC) __irlan_close);
173 }
174
175 /*
176  * Function irlan_register_netdev (self)
177  *
178  *    Registers the network device to be used. We should don't register until
179  *    we have been binded to a particular provider or client.
180  */
181 int irlan_register_netdev(struct irlan_cb *self)
182 {
183         int i=0;
184
185         IRDA_DEBUG(0, "%s()\n", __FUNCTION__ );
186
187         /* Check if we should call the device eth<x> or irlan<x> */
188         if (!eth) {
189                 /* Get the first free irlan<x> name */
190                 do {
191                         sprintf(self->dev.name, "%s%d", "irlan", i++);
192                 } while (dev_get(self->dev.name));
193         }
194         
195         if (register_netdev(&self->dev) != 0) {
196                 IRDA_DEBUG(2, "%s(), register_netdev() failed!\n", __FUNCTION__ );
197                 return -1;
198         }
199         return 0;
200 }
201
202 /*
203  * Function irlan_open (void)
204  *
205  *    Open new instance of a client/provider, we should only register the 
206  *    network device if this instance is ment for a particular client/provider
207  */
208 struct irlan_cb *irlan_open(__u32 saddr, __u32 daddr)
209 {
210         struct irlan_cb *self;
211
212         IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
213         ASSERT(irlan != NULL, return NULL;);
214
215         /* 
216          *  Initialize the irlan structure. 
217          */
218         self = kmalloc(sizeof(struct irlan_cb), GFP_ATOMIC);
219         if (self == NULL)
220                 return NULL;
221         
222         memset(self, 0, sizeof(struct irlan_cb));
223
224         /*
225          *  Initialize local device structure
226          */
227         self->magic = IRLAN_MAGIC;
228
229         sprintf(self->dev.name, "%s", "unknown");
230
231         self->dev.priv = (void *) self;
232         self->dev.next = NULL;
233         self->dev.init = irlan_eth_init;
234         
235         self->saddr = saddr;
236         self->daddr = daddr;
237
238         /* Provider access can only be PEER, DIRECT, or HOSTED */
239         self->provider.access_type = access;
240         self->media = MEDIA_802_3;
241         self->disconnect_reason = LM_USER_REQUEST;
242         init_timer(&self->watchdog_timer);
243         init_timer(&self->client.kick_timer);
244         init_waitqueue_head(&self->open_wait);  
245
246         hashbin_insert(irlan, (irda_queue_t *) self, daddr, NULL);
247         
248         skb_queue_head_init(&self->client.txq);
249         
250         irlan_next_client_state(self, IRLAN_IDLE);
251         irlan_next_provider_state(self, IRLAN_IDLE);
252
253         irlan_register_netdev(self);
254
255         return self;
256 }
257 /*
258  * Function __irlan_close (self)
259  *
260  *    This function closes and deallocates the IrLAN client instances. Be 
261  *    aware that other functions which calles client_close() must call 
262  *    hashbin_remove() first!!!
263  */
264 static void __irlan_close(struct irlan_cb *self)
265 {
266         struct sk_buff *skb;
267
268         IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
269         
270         ASSERT(self != NULL, return;);
271         ASSERT(self->magic == IRLAN_MAGIC, return;);
272
273         del_timer(&self->watchdog_timer);
274         del_timer(&self->client.kick_timer);
275
276         /* Close all open connections and remove TSAPs */
277         irlan_close_tsaps(self);
278         
279         if (self->client.iriap) 
280                 iriap_close(self->client.iriap);
281
282         /* Remove frames queued on the control channel */
283         while ((skb = skb_dequeue(&self->client.txq)))
284                 dev_kfree_skb(skb);
285
286         unregister_netdev(&self->dev);
287         
288         self->magic = 0;
289         kfree(self);
290 }
291
292 /*
293  * Function irlan_connect_indication (instance, sap, qos, max_sdu_size, skb)
294  *
295  *    Here we receive the connect indication for the data channel
296  *
297  */
298 void irlan_connect_indication(void *instance, void *sap, struct qos_info *qos,
299                               __u32 max_sdu_size, __u8 max_header_size, 
300                               struct sk_buff *skb)
301 {
302         struct irlan_cb *self;
303         struct tsap_cb *tsap;
304
305         IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
306         
307         self = (struct irlan_cb *) instance;
308         tsap = (struct tsap_cb *) sap;
309         
310         ASSERT(self != NULL, return;);
311         ASSERT(self->magic == IRLAN_MAGIC, return;);
312         ASSERT(tsap == self->tsap_data,return;);
313
314         self->max_sdu_size = max_sdu_size;
315         self->max_header_size = max_header_size;
316
317         IRDA_DEBUG(0, "IrLAN, We are now connected!\n");
318
319         del_timer(&self->watchdog_timer);
320
321         /* If you want to pass the skb to *both* state machines, you will
322          * need to skb_clone() it, so that you don't free it twice.
323          * As the state machines don't need it, git rid of it here...
324          * Jean II */
325         if (skb)
326                 dev_kfree_skb(skb);
327
328         irlan_do_provider_event(self, IRLAN_DATA_CONNECT_INDICATION, NULL);
329         irlan_do_client_event(self, IRLAN_DATA_CONNECT_INDICATION, NULL);
330
331         if (self->provider.access_type == ACCESS_PEER) {
332                 /* 
333                  * Data channel is open, so we are now allowed to
334                  * configure the remote filter 
335                  */
336                 irlan_get_unicast_addr(self);
337                 irlan_open_unicast_addr(self);
338         }
339         /* Ready to transfer Ethernet frames (at last) */
340         netif_start_queue(&self->dev); /* Clear reason */
341 }
342
343 void irlan_connect_confirm(void *instance, void *sap, struct qos_info *qos, 
344                            __u32 max_sdu_size, __u8 max_header_size, 
345                            struct sk_buff *skb) 
346 {
347         struct irlan_cb *self;
348
349         self = (struct irlan_cb *) instance;
350
351         ASSERT(self != NULL, return;);
352         ASSERT(self->magic == IRLAN_MAGIC, return;);
353
354         self->max_sdu_size = max_sdu_size;
355         self->max_header_size = max_header_size;
356
357         /* TODO: we could set the MTU depending on the max_sdu_size */
358
359         IRDA_DEBUG(2, "IrLAN, We are now connected!\n");
360         del_timer(&self->watchdog_timer);
361
362         /* 
363          * Data channel is open, so we are now allowed to configure the remote
364          * filter 
365          */
366         irlan_get_unicast_addr(self);
367         irlan_open_unicast_addr(self);
368         
369         /* Open broadcast and multicast filter by default */
370         irlan_set_broadcast_filter(self, TRUE);
371         irlan_set_multicast_filter(self, TRUE);
372
373         /* Ready to transfer Ethernet frames */
374         netif_start_queue(&self->dev);
375         self->disconnect_reason = 0; /* Clear reason */
376 #ifdef CONFIG_IRLAN_SEND_GRATUITOUS_ARP
377         irlan_eth_send_gratuitous_arp(&self->dev);
378 #endif
379         wake_up_interruptible(&self->open_wait);
380 }
381
382 /*
383  * Function irlan_client_disconnect_indication (handle)
384  *
385  *    Callback function for the IrTTP layer. Indicates a disconnection of
386  *    the specified connection (handle)
387  */
388 void irlan_disconnect_indication(void *instance, void *sap, LM_REASON reason, 
389                                  struct sk_buff *userdata) 
390 {
391         struct irlan_cb *self;
392         struct tsap_cb *tsap;
393
394         IRDA_DEBUG(0, "%s(), reason=%d\n", __FUNCTION__ , reason);
395         
396         self = (struct irlan_cb *) instance;
397         tsap = (struct tsap_cb *) sap;
398
399         ASSERT(self != NULL, return;);
400         ASSERT(self->magic == IRLAN_MAGIC, return;);    
401         ASSERT(tsap != NULL, return;);
402         ASSERT(tsap->magic == TTP_TSAP_MAGIC, return;);
403         
404         ASSERT(tsap == self->tsap_data, return;);
405
406         IRDA_DEBUG(2, "IrLAN, data channel disconnected by peer!\n");
407
408         /* Save reason so we know if we should try to reconnect or not */
409         self->disconnect_reason = reason;
410         
411         switch (reason) {
412         case LM_USER_REQUEST: /* User request */
413                 IRDA_DEBUG(2, "%s(), User requested\n", __FUNCTION__ );
414                 break;
415         case LM_LAP_DISCONNECT: /* Unexpected IrLAP disconnect */
416                 IRDA_DEBUG(2, "%s(), Unexpected IrLAP disconnect\n", __FUNCTION__ );
417                 break;
418         case LM_CONNECT_FAILURE: /* Failed to establish IrLAP connection */
419                 IRDA_DEBUG(2, "%s(), IrLAP connect failed\n", __FUNCTION__ );
420                 break;
421         case LM_LAP_RESET:  /* IrLAP reset */
422                 IRDA_DEBUG(2, "%s(), IrLAP reset\n", __FUNCTION__ );
423                 break;
424         case LM_INIT_DISCONNECT:
425                 IRDA_DEBUG(2, "%s(), IrLMP connect failed\n", __FUNCTION__ );
426                 break;
427         default:
428                 ERROR("%s(), Unknown disconnect reason\n", __FUNCTION__);
429                 break;
430         }
431         
432         /* If you want to pass the skb to *both* state machines, you will
433          * need to skb_clone() it, so that you don't free it twice.
434          * As the state machines don't need it, git rid of it here...
435          * Jean II */
436         if (userdata)
437                 dev_kfree_skb(userdata);
438
439         irlan_do_client_event(self, IRLAN_LMP_DISCONNECT, NULL);
440         irlan_do_provider_event(self, IRLAN_LMP_DISCONNECT, NULL);
441         
442         wake_up_interruptible(&self->open_wait);
443 }
444
445 void irlan_open_data_tsap(struct irlan_cb *self)
446 {
447         struct tsap_cb *tsap;
448         notify_t notify;
449
450         IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
451
452         ASSERT(self != NULL, return;);
453         ASSERT(self->magic == IRLAN_MAGIC, return;);
454
455         /* Check if already open */
456         if (self->tsap_data)
457                 return;
458
459         irda_notify_init(&notify);
460         
461         notify.data_indication       = irlan_eth_receive;
462         notify.udata_indication      = irlan_eth_receive;
463         notify.connect_indication    = irlan_connect_indication;
464         notify.connect_confirm       = irlan_connect_confirm;
465         /*notify.flow_indication       = irlan_eth_flow_indication;*/
466         notify.disconnect_indication = irlan_disconnect_indication;
467         notify.instance              = self;
468         strlcpy(notify.name, "IrLAN data", sizeof(notify.name));
469
470         tsap = irttp_open_tsap(LSAP_ANY, DEFAULT_INITIAL_CREDIT, &notify);
471         if (!tsap) {
472                 IRDA_DEBUG(2, "%s(), Got no tsap!\n", __FUNCTION__ );
473                 return;
474         }
475         self->tsap_data = tsap;
476
477         /* 
478          *  This is the data TSAP selector which we will pass to the client
479          *  when the client ask for it.
480          */
481         self->stsap_sel_data = self->tsap_data->stsap_sel;
482 }
483
484 void irlan_close_tsaps(struct irlan_cb *self)
485 {
486         IRDA_DEBUG(4, "%s()\n", __FUNCTION__ );
487
488         ASSERT(self != NULL, return;);
489         ASSERT(self->magic == IRLAN_MAGIC, return;);
490
491         /* Disconnect and close all open TSAP connections */
492         if (self->tsap_data) {
493                 irttp_disconnect_request(self->tsap_data, NULL, P_NORMAL);
494                 irttp_close_tsap(self->tsap_data);
495                 self->tsap_data = NULL;
496         }
497         if (self->client.tsap_ctrl) {
498                 irttp_disconnect_request(self->client.tsap_ctrl, NULL, 
499                                          P_NORMAL);
500                 irttp_close_tsap(self->client.tsap_ctrl);
501                 self->client.tsap_ctrl = NULL;
502         }
503         if (self->provider.tsap_ctrl) {
504                 irttp_disconnect_request(self->provider.tsap_ctrl, NULL, 
505                                          P_NORMAL);
506                 irttp_close_tsap(self->provider.tsap_ctrl);
507                 self->provider.tsap_ctrl = NULL;
508         }
509         self->disconnect_reason = LM_USER_REQUEST;
510 }
511
512 /*
513  * Function irlan_ias_register (self, tsap_sel)
514  *
515  *    Register with LM-IAS
516  *
517  */
518 void irlan_ias_register(struct irlan_cb *self, __u8 tsap_sel)
519 {
520         struct ias_object *obj;
521         struct ias_value *new_value;
522
523         ASSERT(self != NULL, return;);
524         ASSERT(self->magic == IRLAN_MAGIC, return;);
525         
526         /* 
527          * Check if object has already been registered by a previous provider.
528          * If that is the case, we just change the value of the attribute
529          */
530         if (!irias_find_object("IrLAN")) {
531                 obj = irias_new_object("IrLAN", IAS_IRLAN_ID);
532                 irias_add_integer_attrib(obj, "IrDA:TinyTP:LsapSel", tsap_sel,
533                                          IAS_KERNEL_ATTR);
534                 irias_insert_object(obj);
535         } else {
536                 new_value = irias_new_integer_value(tsap_sel);
537                 irias_object_change_attribute("IrLAN", "IrDA:TinyTP:LsapSel",
538                                               new_value);
539         }
540         
541         /* Register PnP object only if not registered before */
542         if (!irias_find_object("PnP")) {
543                 obj = irias_new_object("PnP", IAS_PNP_ID);
544 #if 0
545                 irias_add_string_attrib(obj, "Name", sysctl_devname,
546                                         IAS_KERNEL_ATTR);
547 #else
548                 irias_add_string_attrib(obj, "Name", "Linux", IAS_KERNEL_ATTR);
549 #endif
550                 irias_add_string_attrib(obj, "DeviceID", "HWP19F0",
551                                         IAS_KERNEL_ATTR);
552                 irias_add_integer_attrib(obj, "CompCnt", 1, IAS_KERNEL_ATTR);
553                 if (self->provider.access_type == ACCESS_PEER)
554                         irias_add_string_attrib(obj, "Comp#01", "PNP8389",
555                                                 IAS_KERNEL_ATTR);
556                 else
557                         irias_add_string_attrib(obj, "Comp#01", "PNP8294",
558                                                 IAS_KERNEL_ATTR);
559
560                 irias_add_string_attrib(obj, "Manufacturer",
561                                         "Linux-IrDA Project", IAS_KERNEL_ATTR);
562                 irias_insert_object(obj);
563         }
564 }
565
566 /*
567  * Function irlan_run_ctrl_tx_queue (self)
568  *
569  *    Try to send the next command in the control transmit queue
570  *
571  */
572 int irlan_run_ctrl_tx_queue(struct irlan_cb *self)
573 {
574         struct sk_buff *skb;
575
576         IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
577
578         if (irda_lock(&self->client.tx_busy) == FALSE)
579                 return -EBUSY;
580
581         skb = skb_dequeue(&self->client.txq);
582         if (!skb) {
583                 self->client.tx_busy = FALSE;
584                 return 0;
585         }
586         
587         /* Check that it's really possible to send commands */
588         if ((self->client.tsap_ctrl == NULL) || 
589             (self->client.state == IRLAN_IDLE)) 
590         {
591                 self->client.tx_busy = FALSE;
592                 dev_kfree_skb(skb);
593                 return -1;
594         }
595         IRDA_DEBUG(2, "%s(), sending ...\n", __FUNCTION__ );
596
597         return irttp_data_request(self->client.tsap_ctrl, skb);
598 }
599
600 /*
601  * Function irlan_ctrl_data_request (self, skb)
602  *
603  *    This function makes sure that commands on the control channel is being
604  *    sent in a command/response fashion
605  */
606 void irlan_ctrl_data_request(struct irlan_cb *self, struct sk_buff *skb)
607 {
608         IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
609
610         /* Queue command */
611         skb_queue_tail(&self->client.txq, skb);
612
613         /* Try to send command */
614         irlan_run_ctrl_tx_queue(self);
615 }
616
617 /*
618  * Function irlan_get_provider_info (self)
619  *
620  *    Send Get Provider Information command to peer IrLAN layer
621  *
622  */
623 void irlan_get_provider_info(struct irlan_cb *self)
624 {
625         struct sk_buff *skb;
626         __u8 *frame;
627
628         IRDA_DEBUG(4, "%s()\n", __FUNCTION__ );
629         
630         ASSERT(self != NULL, return;);
631         ASSERT(self->magic == IRLAN_MAGIC, return;);
632
633         skb = dev_alloc_skb(64);
634         if (!skb)
635                 return;
636
637         /* Reserve space for TTP, LMP, and LAP header */
638         skb_reserve(skb, self->client.max_header_size);
639         skb_put(skb, 2);
640         
641         frame = skb->data;
642         
643         frame[0] = CMD_GET_PROVIDER_INFO;
644         frame[1] = 0x00;                 /* Zero parameters */
645         
646         irlan_ctrl_data_request(self, skb);
647 }
648
649 /*
650  * Function irlan_open_data_channel (self)
651  *
652  *    Send an Open Data Command to provider
653  *
654  */
655 void irlan_open_data_channel(struct irlan_cb *self) 
656 {
657         struct sk_buff *skb;
658         __u8 *frame;
659         
660         IRDA_DEBUG(4, "%s()\n", __FUNCTION__ );
661
662         ASSERT(self != NULL, return;);
663         ASSERT(self->magic == IRLAN_MAGIC, return;);
664         
665         skb = dev_alloc_skb(64);
666         if (!skb)
667                 return;
668
669         skb_reserve(skb, self->client.max_header_size);
670         skb_put(skb, 2);
671         
672         frame = skb->data;
673         
674         /* Build frame */
675         frame[0] = CMD_OPEN_DATA_CHANNEL;
676         frame[1] = 0x02; /* Two parameters */
677
678         irlan_insert_string_param(skb, "MEDIA", "802.3");
679         irlan_insert_string_param(skb, "ACCESS_TYPE", "DIRECT");
680         /* irlan_insert_string_param(skb, "MODE", "UNRELIABLE"); */
681
682 /*      self->use_udata = TRUE; */
683
684         irlan_ctrl_data_request(self, skb);
685 }
686
687 void irlan_close_data_channel(struct irlan_cb *self) 
688 {
689         struct sk_buff *skb;
690         __u8 *frame;
691         
692         IRDA_DEBUG(4, "%s()\n", __FUNCTION__ );
693
694         ASSERT(self != NULL, return;);
695         ASSERT(self->magic == IRLAN_MAGIC, return;);
696
697         /* Check if the TSAP is still there */
698         if (self->client.tsap_ctrl == NULL)
699                 return;
700
701         skb = dev_alloc_skb(64);
702         if (!skb)
703                 return;
704
705         skb_reserve(skb, self->client.max_header_size);
706         skb_put(skb, 2);
707         
708         frame = skb->data;
709         
710         /* Build frame */
711         frame[0] = CMD_CLOSE_DATA_CHAN;
712         frame[1] = 0x01; /* Two parameters */
713
714         irlan_insert_byte_param(skb, "DATA_CHAN", self->dtsap_sel_data);
715
716         irlan_ctrl_data_request(self, skb);
717 }
718
719 /*
720  * Function irlan_open_unicast_addr (self)
721  *
722  *    Make IrLAN provider accept ethernet frames addressed to the unicast 
723  *    address.
724  *
725  */
726 void irlan_open_unicast_addr(struct irlan_cb *self) 
727 {
728         struct sk_buff *skb;
729         __u8 *frame;
730         
731         IRDA_DEBUG(4, "%s()\n", __FUNCTION__ );
732
733         ASSERT(self != NULL, return;);
734         ASSERT(self->magic == IRLAN_MAGIC, return;);    
735         
736         skb = dev_alloc_skb(128);
737         if (!skb)
738                 return;
739
740         /* Reserve space for TTP, LMP, and LAP header */
741         skb_reserve(skb, self->max_header_size);
742         skb_put(skb, 2);
743         
744         frame = skb->data;
745         
746         frame[0] = CMD_FILTER_OPERATION;
747         frame[1] = 0x03;                 /* Three parameters */
748         irlan_insert_byte_param(skb, "DATA_CHAN" , self->dtsap_sel_data);
749         irlan_insert_string_param(skb, "FILTER_TYPE", "DIRECTED");
750         irlan_insert_string_param(skb, "FILTER_MODE", "FILTER"); 
751         
752         irlan_ctrl_data_request(self, skb);
753 }
754
755 /*
756  * Function irlan_set_broadcast_filter (self, status)
757  *
758  *    Make IrLAN provider accept ethernet frames addressed to the broadcast
759  *    address. Be careful with the use of this one, since there may be a lot
760  *    of broadcast traffic out there. We can still function without this
761  *    one but then _we_ have to initiate all communication with other
762  *    hosts, since ARP request for this host will not be answered.
763  */
764 void irlan_set_broadcast_filter(struct irlan_cb *self, int status) 
765 {
766         struct sk_buff *skb;
767         __u8 *frame;
768         
769         IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
770
771         ASSERT(self != NULL, return;);
772         ASSERT(self->magic == IRLAN_MAGIC, return;);
773         
774         skb = dev_alloc_skb(128);
775         if (!skb)
776                 return;
777
778         /* Reserve space for TTP, LMP, and LAP header */
779         skb_reserve(skb, self->client.max_header_size);
780         skb_put(skb, 2);
781         
782         frame = skb->data;
783         
784         frame[0] = CMD_FILTER_OPERATION;
785         frame[1] = 0x03;                 /* Three parameters */
786         irlan_insert_byte_param(skb, "DATA_CHAN", self->dtsap_sel_data);
787         irlan_insert_string_param(skb, "FILTER_TYPE", "BROADCAST");
788         if (status)
789                 irlan_insert_string_param(skb, "FILTER_MODE", "FILTER"); 
790         else
791                 irlan_insert_string_param(skb, "FILTER_MODE", "NONE"); 
792
793         irlan_ctrl_data_request(self, skb);
794 }
795
796 /*
797  * Function irlan_set_multicast_filter (self, status)
798  *
799  *    Make IrLAN provider accept ethernet frames addressed to the multicast
800  *    address. 
801  *
802  */
803 void irlan_set_multicast_filter(struct irlan_cb *self, int status) 
804 {
805         struct sk_buff *skb;
806         __u8 *frame;
807         
808         IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
809
810         ASSERT(self != NULL, return;);
811         ASSERT(self->magic == IRLAN_MAGIC, return;);
812
813         skb = dev_alloc_skb(128);
814         if (!skb)
815                 return;
816         
817         /* Reserve space for TTP, LMP, and LAP header */
818         skb_reserve(skb, self->client.max_header_size);
819         skb_put(skb, 2);
820         
821         frame = skb->data;
822         
823         frame[0] = CMD_FILTER_OPERATION;
824         frame[1] = 0x03;                 /* Three parameters */
825         irlan_insert_byte_param(skb, "DATA_CHAN", self->dtsap_sel_data);
826         irlan_insert_string_param(skb, "FILTER_TYPE", "MULTICAST");
827         if (status)
828                 irlan_insert_string_param(skb, "FILTER_MODE", "ALL"); 
829         else
830                 irlan_insert_string_param(skb, "FILTER_MODE", "NONE"); 
831
832         irlan_ctrl_data_request(self, skb);
833 }
834
835 /*
836  * Function irlan_get_unicast_addr (self)
837  *
838  *    Retrieves the unicast address from the IrLAN provider. This address
839  *    will be inserted into the devices structure, so the ethernet layer
840  *    can construct its packets.
841  *
842  */
843 void irlan_get_unicast_addr(struct irlan_cb *self) 
844 {
845         struct sk_buff *skb;
846         __u8 *frame;
847                 
848         IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
849
850         ASSERT(self != NULL, return;);
851         ASSERT(self->magic == IRLAN_MAGIC, return;);
852         
853         skb = dev_alloc_skb(128);
854         if (!skb)
855                 return;
856
857         /* Reserve space for TTP, LMP, and LAP header */
858         skb_reserve(skb, self->client.max_header_size);
859         skb_put(skb, 2);
860         
861         frame = skb->data;
862         
863         frame[0] = CMD_FILTER_OPERATION;
864         frame[1] = 0x03;                 /* Three parameters */
865         irlan_insert_byte_param(skb, "DATA_CHAN", self->dtsap_sel_data);
866         irlan_insert_string_param(skb, "FILTER_TYPE", "DIRECTED");
867         irlan_insert_string_param(skb, "FILTER_OPERATION", "DYNAMIC"); 
868         
869         irlan_ctrl_data_request(self, skb);
870 }
871
872 /*
873  * Function irlan_get_media_char (self)
874  *
875  *    
876  *
877  */
878 void irlan_get_media_char(struct irlan_cb *self) 
879 {
880         struct sk_buff *skb;
881         __u8 *frame;
882         
883         IRDA_DEBUG(4, "%s()\n", __FUNCTION__ );
884
885         ASSERT(self != NULL, return;);
886         ASSERT(self->magic == IRLAN_MAGIC, return;);
887         
888         skb = dev_alloc_skb(64);
889         if (!skb)
890                 return;
891
892         /* Reserve space for TTP, LMP, and LAP header */
893         skb_reserve(skb, self->client.max_header_size);
894         skb_put(skb, 2);
895         
896         frame = skb->data;
897         
898         /* Build frame */
899         frame[0] = CMD_GET_MEDIA_CHAR;
900         frame[1] = 0x01; /* One parameter */
901         
902         irlan_insert_string_param(skb, "MEDIA", "802.3");
903         irlan_ctrl_data_request(self, skb);
904 }
905
906 /*
907  * Function insert_byte_param (skb, param, value)
908  *
909  *    Insert byte parameter into frame
910  *
911  */
912 int irlan_insert_byte_param(struct sk_buff *skb, char *param, __u8 value)
913 {
914         return __irlan_insert_param(skb, param, IRLAN_BYTE, value, 0, NULL, 0);
915 }
916
917 int irlan_insert_short_param(struct sk_buff *skb, char *param, __u16 value)
918 {
919         return __irlan_insert_param(skb, param, IRLAN_SHORT, 0, value, NULL, 0);
920 }
921
922 /*
923  * Function insert_string (skb, param, value)
924  *
925  *    Insert string parameter into frame
926  *
927  */
928 int irlan_insert_string_param(struct sk_buff *skb, char *param, char *string)
929 {
930         int string_len = strlen(string);
931
932         return __irlan_insert_param(skb, param, IRLAN_ARRAY, 0, 0, string, 
933                                     string_len);
934 }
935
936 /*
937  * Function insert_array_param(skb, param, value, len_value)
938  *
939  *    Insert array parameter into frame
940  *
941  */
942 int irlan_insert_array_param(struct sk_buff *skb, char *name, __u8 *array,
943                              __u16 array_len)
944 {
945         return __irlan_insert_param(skb, name, IRLAN_ARRAY, 0, 0, array, 
946                                     array_len);
947 }
948
949 /*
950  * Function insert_param (skb, param, value, byte)
951  *
952  *    Insert parameter at end of buffer, structure of a parameter is:
953  *
954  *    -----------------------------------------------------------------------
955  *    | Name Length[1] | Param Name[1..255] | Val Length[2] | Value[0..1016]|
956  *    -----------------------------------------------------------------------
957  */
958 static int __irlan_insert_param(struct sk_buff *skb, char *param, int type, 
959                                 __u8 value_byte, __u16 value_short, 
960                                 __u8 *value_array, __u16 value_len)
961 {
962         __u8 *frame;
963         __u8 param_len;
964         __u16 tmp_le; /* Temporary value in little endian format */
965         int n=0;
966         
967         if (skb == NULL) {
968                 IRDA_DEBUG(2, "%s(), Got NULL skb\n", __FUNCTION__ );
969                 return 0;
970         }       
971
972         param_len = strlen(param);
973         switch (type) {
974         case IRLAN_BYTE:
975                 value_len = 1;
976                 break;
977         case IRLAN_SHORT:
978                 value_len = 2;
979                 break;
980         case IRLAN_ARRAY:
981                 ASSERT(value_array != NULL, return 0;);
982                 ASSERT(value_len > 0, return 0;);
983                 break;
984         default:
985                 IRDA_DEBUG(2, "%s(), Unknown parameter type!\n", __FUNCTION__ );
986                 return 0;
987                 break;
988         }
989         
990         /* Insert at end of sk-buffer */
991         frame = skb->tail;
992
993         /* Make space for data */
994         if (skb_tailroom(skb) < (param_len+value_len+3)) {
995                 IRDA_DEBUG(2, "%s(), No more space at end of skb\n", __FUNCTION__ );
996                 return 0;
997         }       
998         skb_put(skb, param_len+value_len+3);
999         
1000         /* Insert parameter length */
1001         frame[n++] = param_len;
1002         
1003         /* Insert parameter */
1004         memcpy(frame+n, param, param_len); n += param_len;
1005         
1006         /* Insert value length (2 byte little endian format, LSB first) */
1007         tmp_le = cpu_to_le16(value_len);
1008         memcpy(frame+n, &tmp_le, 2); n += 2; /* To avoid alignment problems */
1009
1010         /* Insert value */
1011         switch (type) {
1012         case IRLAN_BYTE:
1013                 frame[n++] = value_byte;
1014                 break;
1015         case IRLAN_SHORT:
1016                 tmp_le = cpu_to_le16(value_short);
1017                 memcpy(frame+n, &tmp_le, 2); n += 2;
1018                 break;
1019         case IRLAN_ARRAY:
1020                 memcpy(frame+n, value_array, value_len); n+=value_len;
1021                 break;
1022         default:
1023                 break;
1024         }
1025         ASSERT(n == (param_len+value_len+3), return 0;);
1026
1027         return param_len+value_len+3;
1028 }
1029
1030 /*
1031  * Function irlan_extract_param (buf, name, value, len)
1032  *
1033  *    Extracts a single parameter name/value pair from buffer and updates
1034  *    the buffer pointer to point to the next name/value pair. 
1035  */
1036 int irlan_extract_param(__u8 *buf, char *name, char *value, __u16 *len)
1037 {
1038         __u8 name_len;
1039         __u16 val_len;
1040         int n=0;
1041         
1042         IRDA_DEBUG(4, "%s()\n", __FUNCTION__ );
1043         
1044         /* get length of parameter name (1 byte) */
1045         name_len = buf[n++];
1046         
1047         if (name_len > 254) {
1048                 IRDA_DEBUG(2, "%s(), name_len > 254\n", __FUNCTION__ );
1049                 return -RSP_INVALID_COMMAND_FORMAT;
1050         }
1051         
1052         /* get parameter name */
1053         memcpy(name, buf+n, name_len);
1054         name[name_len] = '\0';
1055         n+=name_len;
1056         
1057         /*  
1058          *  Get length of parameter value (2 bytes in little endian 
1059          *  format) 
1060          */
1061         memcpy(&val_len, buf+n, 2); /* To avoid alignment problems */
1062         le16_to_cpus(&val_len); n+=2;
1063         
1064         if (val_len > 1016) {
1065                 IRDA_DEBUG(2, "%s(), parameter length to long\n", __FUNCTION__ );
1066                 return -RSP_INVALID_COMMAND_FORMAT;
1067         }
1068         *len = val_len;
1069
1070         /* get parameter value */
1071         memcpy(value, buf+n, val_len);
1072         value[val_len] = '\0';
1073         n+=val_len;
1074         
1075         IRDA_DEBUG(4, "Parameter: %s ", name); 
1076         IRDA_DEBUG(4, "Value: %s\n", value); 
1077
1078         return n;
1079 }
1080
1081 #ifdef CONFIG_PROC_FS
1082 /*
1083  * Function irlan_client_proc_read (buf, start, offset, len, unused)
1084  *
1085  *    Give some info to the /proc file system
1086  */
1087 static int irlan_proc_read(char *buf, char **start, off_t offset, int len)
1088 {
1089         struct irlan_cb *self;
1090         unsigned long flags;
1091         ASSERT(irlan != NULL, return 0;);
1092      
1093         len = 0;
1094         
1095         spin_lock_irqsave(&irlan->hb_spinlock, flags);
1096
1097         len += sprintf(buf+len, "IrLAN instances:\n");
1098         
1099         self = (struct irlan_cb *) hashbin_get_first(irlan);
1100         while (self != NULL) {
1101                 ASSERT(self->magic == IRLAN_MAGIC, break;);
1102                 
1103                 len += sprintf(buf+len, "ifname: %s,\n",
1104                                self->dev.name);
1105                 len += sprintf(buf+len, "client state: %s, ",
1106                                irlan_state[ self->client.state]);
1107                 len += sprintf(buf+len, "provider state: %s,\n",
1108                                irlan_state[ self->provider.state]);
1109                 len += sprintf(buf+len, "saddr: %#08x, ",
1110                                self->saddr);
1111                 len += sprintf(buf+len, "daddr: %#08x\n",
1112                                self->daddr);
1113                 len += sprintf(buf+len, "version: %d.%d,\n",
1114                                self->version[1], self->version[0]);
1115                 len += sprintf(buf+len, "access type: %s\n", 
1116                                irlan_access[self->client.access_type]);
1117                 len += sprintf(buf+len, "media: %s\n", 
1118                                irlan_media[self->media]);
1119                 
1120                 len += sprintf(buf+len, "local filter:\n");
1121                 len += sprintf(buf+len, "remote filter: ");
1122                 len += irlan_print_filter(self->client.filter_type, 
1123                                           buf+len);
1124                         
1125                 len += sprintf(buf+len, "tx busy: %s\n", 
1126                                netif_queue_stopped(&self->dev) ? "TRUE" : "FALSE");
1127                         
1128                 len += sprintf(buf+len, "\n");
1129
1130                 self = (struct irlan_cb *) hashbin_get_next(irlan);
1131         } 
1132         spin_unlock_irqrestore(&irlan->hb_spinlock, flags);
1133
1134         return len;
1135 }
1136 #endif
1137
1138 /*
1139  * Function print_ret_code (code)
1140  *
1141  *    Print return code of request to peer IrLAN layer.
1142  *
1143  */
1144 void print_ret_code(__u8 code) 
1145 {
1146         switch(code) {
1147         case 0:
1148                 printk(KERN_INFO "Success\n");
1149                 break;
1150         case 1:
1151                 WARNING("IrLAN: Insufficient resources\n");
1152                 break;
1153         case 2:
1154                 WARNING("IrLAN: Invalid command format\n");
1155                 break;
1156         case 3:
1157                 WARNING("IrLAN: Command not supported\n");
1158                 break;
1159         case 4:
1160                 WARNING("IrLAN: Parameter not supported\n");
1161                 break;
1162         case 5:
1163                 WARNING("IrLAN: Value not supported\n");
1164                 break;
1165         case 6:
1166                 WARNING("IrLAN: Not open\n");
1167                 break;
1168         case 7:
1169                 WARNING("IrLAN: Authentication required\n");
1170                 break;
1171         case 8:
1172                 WARNING("IrLAN: Invalid password\n");
1173                 break;
1174         case 9:
1175                 WARNING("IrLAN: Protocol error\n");
1176                 break;
1177         case 255:
1178                 WARNING("IrLAN: Asynchronous status\n");
1179                 break;
1180         }
1181 }
1182
1183 MODULE_AUTHOR("Dag Brattli <dagb@cs.uit.no>");
1184 MODULE_DESCRIPTION("The Linux IrDA LAN protocol"); 
1185 MODULE_LICENSE("GPL");
1186
1187 MODULE_PARM(eth, "i");
1188 MODULE_PARM_DESC(eth, "Name devices ethX (0) or irlanX (1)");
1189 MODULE_PARM(access, "i");
1190 MODULE_PARM_DESC(access, "Access type DIRECT=1, PEER=2, HOSTED=3");
1191
1192 /*
1193  * Function init_module (void)
1194  *
1195  *    Initialize the IrLAN module, this function is called by the
1196  *    modprobe(1) program.
1197  */
1198 module_init(irlan_init);
1199
1200 /*
1201  * Function cleanup_module (void)
1202  *
1203  *    Remove the IrLAN module, this function is called by the rmmod(1)
1204  *    program
1205  */
1206 module_exit(irlan_cleanup);
1207