Import 2.2.8pre3
[davej-history.git] / net / irda / irlan / irlan_common.c
blob6a30574ca765951ffa3aa58d4079a02899a5f6b8
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: Thu Apr 22 23:13:47 1999
10 * Modified by: Dag Brattli <dagb@cs.uit.no>
12 * Copyright (c) 1997 Dag Brattli <dagb@cs.uit.no>, All Rights Reserved.
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.
19 * Neither Dag Brattli nor University of Tromsø admit liability nor
20 * provide warranty for any of this software. This material is
21 * provided "AS-IS" and at no charge.
23 ********************************************************************/
25 #include <linux/config.h>
26 #include <linux/module.h>
28 #include <linux/kernel.h>
29 #include <linux/string.h>
30 #include <linux/init.h>
31 #include <linux/errno.h>
32 #include <linux/proc_fs.h>
33 #include <linux/netdevice.h>
34 #include <linux/etherdevice.h>
36 #include <asm/system.h>
37 #include <asm/bitops.h>
38 #include <asm/byteorder.h>
40 #include <net/irda/irda.h>
41 #include <net/irda/irttp.h>
42 #include <net/irda/irlmp.h>
43 #include <net/irda/iriap.h>
44 #include <net/irda/timer.h>
46 #include <net/irda/irlan_common.h>
47 #include <net/irda/irlan_client.h>
48 #include <net/irda/irlan_provider.h>
49 #include <net/irda/irlan_eth.h>
50 #include <net/irda/irlan_filter.h>
52 /* extern char sysctl_devname[]; */
55 * Master structure
57 hashbin_t *irlan = NULL;
58 static __u32 ckey, skey;
60 /* Module parameters */
61 static int eth = 0; /* Use "eth" or "irlan" name for devices */
62 static int access = ACCESS_PEER; /* PEER, DIRECT or HOSTED */
63 static int timeout = IRLAN_TIMEOUT;
65 static char *irlan_state[] = {
66 "IRLAN_IDLE",
67 "IRLAN_QUERY",
68 "IRLAN_CONN",
69 "IRLAN_INFO",
70 "IRLAN_MEDIA",
71 "IRLAN_OPEN",
72 "IRLAN_WAIT",
73 "IRLAN_ARB",
74 "IRLAN_DATA",
75 "IRLAN_CLOSE",
76 "IRLAN_SYNC"
79 static char *irlan_access[] = {
80 "UNKNOWN",
81 "DIRECT",
82 "PEER",
83 "HOSTED"
86 static char *irlan_media[] = {
87 "UNKNOWN",
88 "802.3",
89 "802.5"
92 static void __irlan_close(struct irlan_cb *self);
93 static int __irlan_insert_param(struct sk_buff *skb, char *param, int type,
94 __u8 value_byte, __u16 value_short,
95 __u8 *value_array, __u16 value_len);
96 static void irlan_close_tsaps(struct irlan_cb *self);
98 #ifdef CONFIG_PROC_FS
99 static int irlan_proc_read(char *buf, char **start, off_t offset, int len,
100 int unused);
102 extern struct proc_dir_entry *proc_irda;
103 #endif
105 void irlan_watchdog_timer_expired(unsigned long data)
107 struct irmanager_event mgr_event;
108 struct irlan_cb *self, *entry;
110 DEBUG(0, __FUNCTION__ "()\n");
112 self = (struct irlan_cb *) data;
114 ASSERT(self != NULL, return;);
115 ASSERT(self->magic == IRLAN_MAGIC, return;);
117 /* Check if device still configured */
118 if (self->dev.start) {
119 mgr_event.event = EVENT_IRLAN_STOP;
120 sprintf(mgr_event.devname, "%s", self->ifname);
121 irmanager_notify(&mgr_event);
124 * We set this to false, so that irlan_dev_close known that
125 * notify_irmanager should actually be set to TRUE again
126 * instead of FALSE, since this close has not been initiated
127 * by the user.
129 self->notify_irmanager = FALSE;
130 } else {
131 DEBUG(0, __FUNCTION__ "(), recycling instance!\n");
132 if (self->netdev_registered) {
133 DEBUG(0, __FUNCTION__ "(), removing netdev!\n");
134 unregister_netdev(&self->dev);
135 self->netdev_registered = FALSE;
138 /* Unbind from daddr */
139 entry = hashbin_remove(irlan, self->daddr, NULL);
140 ASSERT(entry == self, return;);
142 self->daddr = DEV_ADDR_ANY;
143 self->saddr = DEV_ADDR_ANY;
145 DEBUG(2, __FUNCTION__ "(), daddr=%08x\n", self->daddr);
146 hashbin_insert(irlan, (QUEUE*) self, self->daddr, NULL);
151 * Function irlan_start_watchdog_timer (self, timeout)
156 void irlan_start_watchdog_timer(struct irlan_cb *self, int timeout)
158 DEBUG(4, __FUNCTION__ "()\n");
160 irda_start_timer(&self->watchdog_timer, timeout, (unsigned long) self,
161 irlan_watchdog_timer_expired);
165 * Function irlan_init (void)
167 * Initialize IrLAN layer
170 __initfunc(int irlan_init(void))
172 struct irlan_cb *new;
173 __u16 hints;
175 DEBUG(4, __FUNCTION__"()\n");
177 /* Allocate master array */
178 irlan = hashbin_new(HB_LOCAL);
179 if (irlan == NULL) {
180 printk(KERN_WARNING "IrLAN: Can't allocate hashbin!\n");
181 return -ENOMEM;
183 #ifdef CONFIG_PROC_FS
184 create_proc_entry("irlan", 0, proc_irda)->get_info = irlan_proc_read;
185 #endif /* CONFIG_PROC_FS */
187 DEBUG(4, __FUNCTION__ "()\n");
189 hints = irlmp_service_to_hint(S_LAN);
191 /* Register with IrLMP as a client */
192 ckey = irlmp_register_client(hints, irlan_client_discovery_indication,
193 NULL);
195 /* Register with IrLMP as a service */
196 skey = irlmp_register_service(hints);
198 /* Start the first IrLAN instance */
199 new = irlan_open(DEV_ADDR_ANY, DEV_ADDR_ANY, FALSE);
201 irlan_open_data_tsap(new);
202 irlan_client_open_ctrl_tsap(new);
203 irlan_provider_open_ctrl_tsap(new);
205 /* Do some fast discovery! */
206 irlmp_discovery_request(DISCOVERY_DEFAULT_SLOTS);
208 return 0;
211 void irlan_cleanup(void)
213 DEBUG(4, __FUNCTION__ "()\n");
215 irlmp_unregister_client(ckey);
217 irlmp_unregister_service(skey);
219 #ifdef CONFIG_PROC_FS
220 remove_proc_entry("irlan", proc_irda);
221 #endif /* CONFIG_PROC_FS */
223 * Delete hashbin and close all irlan client instances in it
225 hashbin_delete(irlan, (FREE_FUNC) __irlan_close);
229 * Function irlan_register_netdev (self)
231 * Registers the network device to be used. We should don't register until
232 * we have been binded to a particular provider or client.
234 int irlan_register_netdev(struct irlan_cb *self)
236 int i=0;
238 DEBUG(0, __FUNCTION__ "()\n");
240 /* Check if we should call the device eth<x> or irlan<x> */
241 if (!eth) {
242 /* Get the first free irlan<x> name */
243 do {
244 sprintf(self->ifname, "%s%d", "irlan", i++);
245 } while (dev_get(self->ifname) != NULL);
247 self->dev.name = self->ifname;
249 if (register_netdev(&self->dev) != 0) {
250 DEBUG(2, __FUNCTION__ "(), register_netdev() failed!\n");
251 return -1;
253 self->netdev_registered = TRUE;
255 return 0;
259 * Function irlan_open (void)
261 * Open new instance of a client/provider, we should only register the
262 * network device if this instance is ment for a particular client/provider
264 struct irlan_cb *irlan_open(__u32 saddr, __u32 daddr, int netdev)
266 struct irlan_cb *self;
268 DEBUG(2, __FUNCTION__ "()\n");
271 * Initialize the irlan structure.
273 self = kmalloc(sizeof(struct irlan_cb), GFP_ATOMIC);
274 if (self == NULL)
275 return NULL;
277 memset(self, 0, sizeof(struct irlan_cb));
280 * Initialize local device structure
282 self->magic = IRLAN_MAGIC;
284 ASSERT(irlan != NULL, return NULL;);
286 sprintf(self->ifname, "%s", "unknown");
288 self->dev.priv = (void *) self;
289 self->dev.next = NULL;
290 self->dev.init = irlan_eth_init;
292 self->saddr = saddr;
293 self->daddr = daddr;
295 /* Provider access can only be PEER, DIRECT, or HOSTED */
296 self->access_type = access;
297 self->media = MEDIA_802_3;
299 self->notify_irmanager = TRUE;
301 init_timer(&self->watchdog_timer);
302 init_timer(&self->client.kick_timer);
304 hashbin_insert(irlan, (QUEUE *) self, daddr, NULL);
306 irlan_next_client_state(self, IRLAN_IDLE);
307 irlan_next_provider_state(self, IRLAN_IDLE);
309 /* Register network device now, or wait until some later time? */
310 if (netdev)
311 irlan_register_netdev(self);
313 return self;
316 * Function irlan_close (self)
318 * This function closes and deallocates the IrLAN client instances. Be
319 * aware that other functions which calles client_close() must call
320 * hashbin_remove() first!!!
323 static void __irlan_close(struct irlan_cb *self)
325 DEBUG(0, __FUNCTION__ "()\n");
327 ASSERT(self != NULL, return;);
328 ASSERT(self->magic == IRLAN_MAGIC, return;);
330 del_timer(&self->watchdog_timer);
331 del_timer(&self->client.kick_timer);
333 /* Close all open connections and remove TSAPs */
334 irlan_close_tsaps(self);
336 if (self->netdev_registered) {
337 unregister_netdev(&self->dev);
338 self->netdev_registered = FALSE;
341 self->magic = 0;
342 kfree(self);
346 * Function irlan_close (self)
348 * Close instance
351 void irlan_close(struct irlan_cb *self)
353 struct irlan_cb *entry;
355 DEBUG(0, __FUNCTION__ "()\n");
357 ASSERT(self != NULL, return;);
358 ASSERT(self->magic == IRLAN_MAGIC, return;);
360 /* Check if device is still configured */
361 if (self->dev.start) {
362 DEBUG(2, __FUNCTION__
363 "(), Device still configured, closing later!\n");
364 return;
366 DEBUG(2, __FUNCTION__ "(), daddr=%08x\n", self->daddr);
367 entry = hashbin_remove(irlan, self->daddr, NULL);
369 ASSERT(entry == self, return;);
371 __irlan_close(self);
374 void irlan_connect_indication(void *instance, void *sap, struct qos_info *qos,
375 __u32 max_sdu_size, struct sk_buff *skb)
377 struct irlan_cb *self;
378 struct tsap_cb *tsap;
380 DEBUG(2, __FUNCTION__ "()\n");
382 self = (struct irlan_cb *) instance;
383 tsap = (struct tsap_cb *) sap;
385 ASSERT(self != NULL, return;);
386 ASSERT(self->magic == IRLAN_MAGIC, return;);
387 ASSERT(tsap == self->tsap_data,return;);
389 DEBUG(2, "IrLAN, We are now connected!\n");
390 del_timer(&self->watchdog_timer);
392 irlan_do_provider_event(self, IRLAN_DATA_CONNECT_INDICATION, skb);
393 irlan_do_client_event(self, IRLAN_DATA_CONNECT_INDICATION, skb);
395 if (self->access_type == ACCESS_PEER) {
397 * Data channel is open, so we are now allowed to
398 * configure the remote filter
400 irlan_get_unicast_addr(self);
401 irlan_open_unicast_addr(self);
403 /* Ready to transfer Ethernet frames */
404 self->dev.tbusy = 0;
407 void irlan_connect_confirm(void *instance, void *sap, struct qos_info *qos,
408 __u32 max_sdu_size, struct sk_buff *skb)
410 struct irlan_cb *self;
412 DEBUG(2, __FUNCTION__ "()\n");
414 self = (struct irlan_cb *) instance;
416 ASSERT(self != NULL, return;);
417 ASSERT(self->magic == IRLAN_MAGIC, return;);
419 /* TODO: we could set the MTU depending on the max_sdu_size */
421 DEBUG(2, "IrLAN, We are now connected!\n");
422 del_timer(&self->watchdog_timer);
425 * Data channel is open, so we are now allowed to configure the remote
426 * filter
428 irlan_get_unicast_addr(self);
429 irlan_open_unicast_addr(self);
431 /* Ready to transfer Ethernet frames */
432 self->dev.tbusy = 0;
436 * Function irlan_client_disconnect_indication (handle)
438 * Callback function for the IrTTP layer. Indicates a disconnection of
439 * the specified connection (handle)
441 void irlan_disconnect_indication(void *instance, void *sap, LM_REASON reason,
442 struct sk_buff *userdata)
444 struct irlan_cb *self;
445 struct tsap_cb *tsap;
447 DEBUG(2, __FUNCTION__ "(), reason=%d\n", reason);
449 self = (struct irlan_cb *) instance;
450 tsap = (struct tsap_cb *) sap;
452 ASSERT(self != NULL, return;);
453 ASSERT(self->magic == IRLAN_MAGIC, return;);
454 ASSERT(tsap != NULL, return;);
455 ASSERT(tsap->magic == TTP_TSAP_MAGIC, return;);
457 ASSERT(tsap == self->tsap_data, return;);
459 DEBUG(2, "IrLAN, data channel disconnected by peer!\n");
461 switch(reason) {
462 case LM_USER_REQUEST: /* User request */
463 //irlan_close(self);
464 break;
465 case LM_LAP_DISCONNECT: /* Unexpected IrLAP disconnect */
466 irlan_start_watchdog_timer(self, IRLAN_TIMEOUT);
467 break;
468 case LM_CONNECT_FAILURE: /* Failed to establish IrLAP connection */
469 DEBUG(2, __FUNCTION__ "(), LM_CONNECT_FAILURE not impl\n");
470 break;
471 case LM_LAP_RESET: /* IrLAP reset */
472 DEBUG(2, __FUNCTION__ "(), LM_CONNECT_FAILURE not impl\n");
473 break;
474 case LM_INIT_DISCONNECT:
475 DEBUG(2, __FUNCTION__ "(), LM_CONNECT_FAILURE not impl\n");
476 break;
477 default:
478 break;
481 /* Stop IP from transmitting more packets */
482 /* irlan_client_flow_indication(handle, FLOW_STOP, priv); */
484 irlan_do_client_event(self, IRLAN_LMP_DISCONNECT, NULL);
485 irlan_do_provider_event(self, IRLAN_LMP_DISCONNECT, NULL);
488 void irlan_open_data_tsap(struct irlan_cb *self)
490 struct notify_t notify;
491 struct tsap_cb *tsap;
493 DEBUG(4, __FUNCTION__ "()\n");
495 ASSERT(self != NULL, return;);
496 ASSERT(self->magic == IRLAN_MAGIC, return;);
498 /* Check if already open */
499 if (self->tsap_data)
500 return;
502 irda_notify_init(&notify);
504 notify.data_indication = irlan_eth_receive;
505 notify.udata_indication = irlan_eth_receive;
506 notify.connect_indication = irlan_connect_indication;
507 notify.connect_confirm = irlan_connect_confirm;
508 notify.flow_indication = irlan_eth_flow_indication;
509 notify.disconnect_indication = irlan_disconnect_indication;
510 notify.instance = self;
511 strncpy(notify.name, "IrLAN data", NOTIFY_MAX_NAME);
513 tsap = irttp_open_tsap(LSAP_ANY, DEFAULT_INITIAL_CREDIT, &notify);
514 if (!tsap) {
515 DEBUG(2, __FUNCTION__ "(), Got no tsap!\n");
516 return;
518 self->tsap_data = tsap;
521 * This is the data TSAP selector which we will pass to the client
522 * when the client ask for it.
524 self->stsap_sel_data = self->tsap_data->stsap_sel;
527 void irlan_close_tsaps(struct irlan_cb *self)
529 DEBUG(4, __FUNCTION__ "()\n");
531 ASSERT(self != NULL, return;);
532 ASSERT(self->magic == IRLAN_MAGIC, return;);
535 * Disconnect and close all open TSAP connections
537 if (self->tsap_data) {
538 irttp_disconnect_request(self->tsap_data, NULL, P_NORMAL);
539 irttp_close_tsap(self->tsap_data);
540 self->tsap_data = NULL;
543 if (self->client.tsap_ctrl) {
544 irttp_disconnect_request(self->client.tsap_ctrl, NULL,
545 P_NORMAL);
546 irttp_close_tsap(self->client.tsap_ctrl);
547 self->client.tsap_ctrl = NULL;
549 if (self->provider.tsap_ctrl) {
550 irttp_disconnect_request(self->provider.tsap_ctrl, NULL,
551 P_NORMAL);
552 irttp_close_tsap(self->provider.tsap_ctrl);
553 self->provider.tsap_ctrl = NULL;
558 * Function irlan_ias_register (self, tsap_sel)
560 * Register with LM-IAS
563 void irlan_ias_register(struct irlan_cb *self, __u8 tsap_sel)
565 struct ias_object *obj;
566 struct ias_value *new_value;
568 ASSERT(self != NULL, return;);
569 ASSERT(self->magic == IRLAN_MAGIC, return;);
572 * Check if object has already been registred by a previous provider.
573 * If that is the case, we just change the value of the attribute
575 if (!irias_find_object("IrLAN")) {
576 obj = irias_new_object("IrLAN", IAS_IRLAN_ID);
577 irias_add_integer_attrib(obj, "IrDA:TinyTP:LsapSel", tsap_sel);
578 irias_insert_object(obj);
579 } else {
580 new_value = irias_new_integer_value(tsap_sel);
581 irias_object_change_attribute("IrLAN", "IrDA:TinyTP:LsapSel",
582 new_value);
585 /* Register PnP object only if not registred before */
586 if (!irias_find_object("PnP")) {
587 obj = irias_new_object("PnP", IAS_PNP_ID);
588 #if 0
589 irias_add_string_attrib(obj, "Name", sysctl_devname);
590 #else
591 irias_add_string_attrib(obj, "Name", "Linux");
592 #endif
593 irias_add_string_attrib(obj, "DeviceID", "HWP19F0");
594 irias_add_integer_attrib(obj, "CompCnt", 2);
595 irias_add_string_attrib(obj, "Comp#01", "PNP8294");
596 irias_add_string_attrib(obj, "Comp#02", "PNP8389");
597 irias_add_string_attrib(obj, "Manufacturer", "Linux-IrDA Project");
598 irias_insert_object(obj);
603 * Function irlan_get_provider_info (self)
605 * Send Get Provider Information command to peer IrLAN layer
608 void irlan_get_provider_info(struct irlan_cb *self)
610 struct sk_buff *skb;
611 __u8 *frame;
613 DEBUG(4, __FUNCTION__ "()\n");
615 ASSERT(self != NULL, return;);
616 ASSERT(self->magic == IRLAN_MAGIC, return;);
618 skb = dev_alloc_skb(64);
619 if (!skb)
620 return;
622 /* Reserve space for TTP, LMP, and LAP header */
623 skb_reserve(skb, TTP_HEADER+LMP_HEADER+LAP_HEADER);
624 skb_put(skb, 2);
626 frame = skb->data;
628 frame[0] = CMD_GET_PROVIDER_INFO;
629 frame[1] = 0x00; /* Zero parameters */
631 irttp_data_request(self->client.tsap_ctrl, skb);
635 * Function irlan_open_data_channel (self)
637 * Send an Open Data Command to provider
640 void irlan_open_data_channel(struct irlan_cb *self)
642 struct sk_buff *skb;
643 __u8 *frame;
645 DEBUG(4, __FUNCTION__ "()\n");
647 ASSERT(self != NULL, return;);
648 ASSERT(self->magic == IRLAN_MAGIC, return;);
650 skb = dev_alloc_skb(64);
651 if (!skb)
652 return;
654 skb_reserve(skb, TTP_HEADER+LMP_HEADER+LAP_HEADER);
655 skb_put(skb, 2);
657 frame = skb->data;
659 /* Build frame */
660 frame[0] = CMD_OPEN_DATA_CHANNEL;
661 frame[1] = 0x02; /* Two parameters */
663 irlan_insert_string_param(skb, "MEDIA", "802.3");
664 irlan_insert_string_param(skb, "ACCESS_TYPE", "DIRECT");
665 /* irlan_insert_string_param(skb, "MODE", "UNRELIABLE"); */
667 /* self->use_udata = TRUE; */
669 irttp_data_request(self->client.tsap_ctrl, skb);
672 void irlan_close_data_channel(struct irlan_cb *self)
674 struct sk_buff *skb;
675 __u8 *frame;
677 DEBUG(4, __FUNCTION__ "()\n");
679 ASSERT(self != NULL, return;);
680 ASSERT(self->magic == IRLAN_MAGIC, return;);
682 skb = dev_alloc_skb(64);
683 if (!skb)
684 return;
686 skb_reserve(skb, TTP_HEADER+LMP_HEADER+LAP_HEADER);
687 skb_put(skb, 2);
689 frame = skb->data;
691 /* Build frame */
692 frame[0] = CMD_CLOSE_DATA_CHAN;
693 frame[1] = 0x01; /* Two parameters */
695 irlan_insert_byte_param(skb, "DATA_CHAN", self->dtsap_sel_data);
697 irttp_data_request(self->client.tsap_ctrl, skb);
701 * Function irlan_open_unicast_addr (self)
703 * Make IrLAN provider accept ethernet frames addressed to the unicast
704 * address.
707 void irlan_open_unicast_addr(struct irlan_cb *self)
709 struct sk_buff *skb;
710 __u8 *frame;
712 DEBUG(4, __FUNCTION__ "()\n");
714 ASSERT(self != NULL, return;);
715 ASSERT(self->magic == IRLAN_MAGIC, return;);
717 skb = dev_alloc_skb(128);
718 if (!skb)
719 return;
721 /* Reserve space for TTP, LMP, and LAP header */
722 skb_reserve(skb, TTP_HEADER+LMP_HEADER+LAP_HEADER);
723 skb_put(skb, 2);
725 frame = skb->data;
727 frame[0] = CMD_FILTER_OPERATION;
728 frame[1] = 0x03; /* Three parameters */
729 irlan_insert_byte_param(skb, "DATA_CHAN" , self->dtsap_sel_data);
730 irlan_insert_string_param(skb, "FILTER_TYPE", "DIRECTED");
731 irlan_insert_string_param(skb, "FILTER_MODE", "FILTER");
733 irttp_data_request(self->client.tsap_ctrl, skb);
737 * Function irlan_set_broadcast_filter (self, status)
739 * Make IrLAN provider accept ethernet frames addressed to the broadcast
740 * address. Be careful with the use of this one, since there may be a lot
741 * of broadcast traffic out there. We can still function without this
742 * one but then _we_ have to initiate all communication with other
743 * hosts, since ARP request for this host will not be answered.
745 void irlan_set_broadcast_filter(struct irlan_cb *self, int status)
747 struct sk_buff *skb;
748 __u8 *frame;
750 DEBUG(2, __FUNCTION__ "()\n");
752 ASSERT(self != NULL, return;);
753 ASSERT(self->magic == IRLAN_MAGIC, return;);
755 skb = dev_alloc_skb(128);
756 if (!skb)
757 return;
759 /* Reserve space for TTP, LMP, and LAP header */
760 skb_reserve(skb, TTP_HEADER+LMP_HEADER+LAP_HEADER);
761 skb_put(skb, 2);
763 frame = skb->data;
765 frame[0] = CMD_FILTER_OPERATION;
766 frame[1] = 0x03; /* Three parameters */
767 irlan_insert_byte_param(skb, "DATA_CHAN", self->dtsap_sel_data);
768 irlan_insert_string_param(skb, "FILTER_TYPE", "BROADCAST");
769 if (status)
770 irlan_insert_string_param(skb, "FILTER_MODE", "FILTER");
771 else
772 irlan_insert_string_param(skb, "FILTER_MODE", "NONE");
774 irttp_data_request(self->client.tsap_ctrl, skb);
778 * Function irlan_set_multicast_filter (self, status)
780 * Make IrLAN provider accept ethernet frames addressed to the multicast
781 * address.
784 void irlan_set_multicast_filter(struct irlan_cb *self, int status)
786 struct sk_buff *skb;
787 __u8 *frame;
789 DEBUG(2, __FUNCTION__ "()\n");
791 ASSERT(self != NULL, return;);
792 ASSERT(self->magic == IRLAN_MAGIC, return;);
794 skb = dev_alloc_skb(128);
795 if (!skb)
796 return;
798 /* Reserve space for TTP, LMP, and LAP header */
799 skb_reserve(skb, TTP_HEADER+LMP_HEADER+LAP_HEADER);
800 skb_put(skb, 2);
802 frame = skb->data;
804 frame[0] = CMD_FILTER_OPERATION;
805 frame[1] = 0x03; /* Three parameters */
806 irlan_insert_byte_param(skb, "DATA_CHAN", self->dtsap_sel_data);
807 irlan_insert_string_param(skb, "FILTER_TYPE", "MULTICAST");
808 if (status)
809 irlan_insert_string_param(skb, "FILTER_MODE", "ALL");
810 else
811 irlan_insert_string_param(skb, "FILTER_MODE", "NONE");
813 irttp_data_request(self->client.tsap_ctrl, skb);
817 * Function irlan_get_unicast_addr (self)
819 * Retrives the unicast address from the IrLAN provider. This address
820 * will be inserted into the devices structure, so the ethernet layer
821 * can construct its packets.
824 void irlan_get_unicast_addr(struct irlan_cb *self)
826 struct sk_buff *skb;
827 __u8 *frame;
829 DEBUG(2, __FUNCTION__ "()\n");
831 ASSERT(self != NULL, return;);
832 ASSERT(self->magic == IRLAN_MAGIC, return;);
834 skb = dev_alloc_skb(128);
835 if (!skb)
836 return;
838 /* Reserve space for TTP, LMP, and LAP header */
839 skb_reserve(skb, TTP_HEADER+LMP_HEADER+LAP_HEADER);
840 skb_put(skb, 2);
842 frame = skb->data;
844 frame[0] = CMD_FILTER_OPERATION;
845 frame[1] = 0x03; /* Three parameters */
846 irlan_insert_byte_param(skb, "DATA_CHAN", self->dtsap_sel_data);
847 irlan_insert_string_param(skb, "FILTER_TYPE", "DIRECTED");
848 irlan_insert_string_param(skb, "FILTER_OPERATION", "DYNAMIC");
850 irttp_data_request(self->client.tsap_ctrl, skb);
854 * Function irlan_get_media_char (self)
859 void irlan_get_media_char(struct irlan_cb *self)
861 struct sk_buff *skb;
862 __u8 *frame;
864 DEBUG(4, __FUNCTION__ "()\n");
866 ASSERT(self != NULL, return;);
867 ASSERT(self->magic == IRLAN_MAGIC, return;);
869 skb = dev_alloc_skb(64);
870 if (!skb)
871 return;
873 /* Reserve space for TTP, LMP, and LAP header */
874 skb_reserve(skb, TTP_HEADER+LMP_HEADER+LAP_HEADER);
875 skb_put(skb, 2);
877 frame = skb->data;
879 /* Build frame */
880 frame[0] = CMD_GET_MEDIA_CHAR;
881 frame[1] = 0x01; /* One parameter */
883 irlan_insert_string_param(skb, "MEDIA", "802.3");
885 irttp_data_request(self->client.tsap_ctrl, skb);
889 * Function insert_byte_param (skb, param, value)
891 * Insert byte parameter into frame
894 int irlan_insert_byte_param(struct sk_buff *skb, char *param, __u8 value)
896 return __irlan_insert_param(skb, param, IRLAN_BYTE, value, 0, NULL, 0);
899 int irlan_insert_short_param(struct sk_buff *skb, char *param, __u16 value)
901 return __irlan_insert_param(skb, param, IRLAN_SHORT, 0, value, NULL, 0);
905 * Function insert_string (skb, param, value)
907 * Insert string parameter into frame
910 int irlan_insert_string_param(struct sk_buff *skb, char *param, char *string)
912 int string_len = strlen(string);
914 return __irlan_insert_param(skb, param, IRLAN_ARRAY, 0, 0, string,
915 string_len);
919 * Function insert_array_param(skb, param, value, len_value)
921 * Insert array parameter into frame
924 int irlan_insert_array_param(struct sk_buff *skb, char *name, __u8 *array,
925 __u16 array_len)
927 return __irlan_insert_param(skb, name, IRLAN_ARRAY, 0, 0, array,
928 array_len);
932 * Function insert_param (skb, param, value, byte)
934 * Insert parameter at end of buffer, structure of a parameter is:
936 * -----------------------------------------------------------------------
937 * | Name Length[1] | Param Name[1..255] | Val Length[2] | Value[0..1016]|
938 * -----------------------------------------------------------------------
940 static int __irlan_insert_param(struct sk_buff *skb, char *param, int type,
941 __u8 value_byte, __u16 value_short,
942 __u8 *value_array, __u16 value_len)
944 __u8 *frame;
945 __u8 param_len;
946 __u16 tmp_le; /* Temporary value in little endian format */
947 int n=0;
949 if (skb == NULL) {
950 DEBUG(2, __FUNCTION__ "(), Got NULL skb\n");
951 return 0;
954 param_len = strlen(param);
955 switch (type) {
956 case IRLAN_BYTE:
957 value_len = 1;
958 break;
959 case IRLAN_SHORT:
960 value_len = 2;
961 break;
962 case IRLAN_ARRAY:
963 ASSERT(value_array != NULL, return 0;);
964 ASSERT(value_len > 0, return 0;);
965 break;
966 default:
967 DEBUG(2, __FUNCTION__ "(), Unknown parameter type!\n");
968 return 0;
969 break;
972 /* Insert at end of sk-buffer */
973 frame = skb->tail;
975 /* Make space for data */
976 if (skb_tailroom(skb) < (param_len+value_len+3)) {
977 DEBUG(2, __FUNCTION__ "(), No more space at end of skb\n");
978 return 0;
980 skb_put(skb, param_len+value_len+3);
982 /* Insert parameter length */
983 frame[n++] = param_len;
985 /* Insert parameter */
986 memcpy(frame+n, param, param_len); n += param_len;
988 /* Insert value length (2 byte little endian format, LSB first) */
989 tmp_le = cpu_to_le16(value_len);
990 memcpy(frame+n, &tmp_le, 2); n += 2; /* To avoid alignment problems */
992 /* Insert value */
993 switch (type) {
994 case IRLAN_BYTE:
995 frame[n++] = value_byte;
996 break;
997 case IRLAN_SHORT:
998 tmp_le = cpu_to_le16(value_short);
999 memcpy(frame+n, &tmp_le, 2); n += 2;
1000 break;
1001 case IRLAN_ARRAY:
1002 memcpy(frame+n, value_array, value_len); n+=value_len;
1003 break;
1004 default:
1005 break;
1007 ASSERT(n == (param_len+value_len+3), return 0;);
1009 return param_len+value_len+3;
1013 * Function irlan_extract_param (buf, name, value, len)
1015 * Extracts a single parameter name/value pair from buffer and updates
1016 * the buffer pointer to point to the next name/value pair.
1018 int irlan_extract_param(__u8 *buf, char *name, char *value, __u16 *len)
1020 __u8 name_len;
1021 __u16 val_len;
1022 int n=0;
1024 DEBUG(4, __FUNCTION__ "()\n");
1026 /* get length of parameter name (1 byte) */
1027 name_len = buf[n++];
1029 if (name_len > 254) {
1030 DEBUG(2, __FUNCTION__ "(), name_len > 254\n");
1031 return -RSP_INVALID_COMMAND_FORMAT;
1034 /* get parameter name */
1035 memcpy(name, buf+n, name_len);
1036 name[ name_len] = '\0';
1037 n+=name_len;
1040 * Get length of parameter value (2 bytes in little endian
1041 * format)
1043 memcpy(&val_len, buf+n, 2); /* To avoid alignment problems */
1044 le16_to_cpus(&val_len); n+=2;
1046 if (val_len > 1016) {
1047 DEBUG(2, __FUNCTION__ "(), parameter length to long\n");
1048 return -RSP_INVALID_COMMAND_FORMAT;
1050 *len = val_len;
1052 /* get parameter value */
1053 memcpy(value, buf+n, val_len);
1054 value[ val_len] = '\0';
1055 n+=val_len;
1057 DEBUG(4, "Parameter: %s ", name);
1058 DEBUG(4, "Value: %s\n", value);
1060 return n;
1063 #ifdef CONFIG_PROC_FS
1065 * Function irlan_client_proc_read (buf, start, offset, len, unused)
1067 * Give some info to the /proc file system
1069 static int irlan_proc_read(char *buf, char **start, off_t offset, int len,
1070 int unused)
1072 struct irlan_cb *self;
1073 unsigned long flags;
1075 save_flags(flags);
1076 cli();
1078 ASSERT(irlan != NULL, return 0;);
1080 len = 0;
1082 len += sprintf(buf+len, "IrLAN instances:\n");
1084 self = (struct irlan_cb *) hashbin_get_first(irlan);
1085 while (self != NULL) {
1086 ASSERT(self->magic == IRLAN_MAGIC, return len;);
1088 len += sprintf(buf+len, "ifname: %s,\n",
1089 self->ifname);
1090 len += sprintf(buf+len, "client state: %s, ",
1091 irlan_state[ self->client.state]);
1092 len += sprintf(buf+len, "provider state: %s,\n",
1093 irlan_state[ self->provider.state]);
1094 len += sprintf(buf+len, "saddr: %#08x, ",
1095 self->saddr);
1096 len += sprintf(buf+len, "daddr: %#08x\n",
1097 self->daddr);
1098 len += sprintf(buf+len, "version: %d.%d,\n",
1099 self->version[1], self->version[0]);
1100 len += sprintf(buf+len, "access type: %s\n",
1101 irlan_access[ self->access_type]);
1102 len += sprintf(buf+len, "media: %s\n",
1103 irlan_media[ self->media]);
1105 len += sprintf(buf+len, "local filter:\n");
1106 len += sprintf(buf+len, "remote filter: ");
1107 len += irlan_print_filter(self->client.filter_type, buf+len);
1109 len += sprintf(buf+len, "tx busy: %s\n", self->dev.tbusy ?
1110 "TRUE" : "FALSE");
1112 len += sprintf(buf+len, "\n");
1114 self = (struct irlan_cb *) hashbin_get_next(irlan);
1116 restore_flags(flags);
1118 return len;
1120 #endif
1123 * Function print_ret_code (code)
1125 * Print return code of request to peer IrLAN layer.
1128 void print_ret_code(__u8 code)
1130 switch(code) {
1131 case 0:
1132 printk(KERN_INFO "Success\n");
1133 break;
1134 case 1:
1135 printk(KERN_WARNING "Insufficient resources\n");
1136 break;
1137 case 2:
1138 printk(KERN_WARNING "Invalid command format\n");
1139 break;
1140 case 3:
1141 printk(KERN_WARNING "Command not supported\n");
1142 break;
1143 case 4:
1144 printk(KERN_WARNING "Parameter not supported\n");
1145 break;
1146 case 5:
1147 printk(KERN_WARNING "Value not supported\n");
1148 break;
1149 case 6:
1150 printk(KERN_WARNING "Not open\n");
1151 break;
1152 case 7:
1153 printk(KERN_WARNING "Authentication required\n");
1154 break;
1155 case 8:
1156 printk(KERN_WARNING "Invalid password\n");
1157 break;
1158 case 9:
1159 printk(KERN_WARNING "Protocol error\n");
1160 break;
1161 case 255:
1162 printk(KERN_WARNING "Asynchronous status\n");
1163 break;
1167 void irlan_mod_inc_use_count(void)
1169 #ifdef MODULE
1170 MOD_INC_USE_COUNT;
1171 #endif
1174 void irlan_mod_dec_use_count(void)
1176 #ifdef MODULE
1177 MOD_DEC_USE_COUNT;
1178 #endif
1181 #ifdef MODULE
1183 MODULE_AUTHOR("Dag Brattli <dagb@cs.uit.no>");
1184 MODULE_DESCRIPTION("The Linux IrDA LAN protocol");
1186 MODULE_PARM(eth, "i");
1187 MODULE_PARM(access, "i");
1188 MODULE_PARM(timeout, "i");
1191 * Function init_module (void)
1193 * Initialize the IrLAN module, this function is called by the
1194 * modprobe(1) program.
1196 int init_module(void)
1198 return irlan_init();
1202 * Function cleanup_module (void)
1204 * Remove the IrLAN module, this function is called by the rmmod(1)
1205 * program
1207 void cleanup_module(void)
1209 /* Free some memory */
1210 irlan_cleanup();
1213 #endif /* MODULE */