1 /*********************************************************************
3 * Filename: irlan_common.c
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[]; */
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
[] = {
79 static char *irlan_access
[] = {
86 static char *irlan_media
[] = {
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
);
99 static int irlan_proc_read(char *buf
, char **start
, off_t offset
, int len
,
102 extern struct proc_dir_entry
*proc_irda
;
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
129 self
->notify_irmanager
= FALSE
;
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;
175 DEBUG(4, __FUNCTION__
"()\n");
177 /* Allocate master array */
178 irlan
= hashbin_new(HB_LOCAL
);
180 printk(KERN_WARNING
"IrLAN: Can't allocate hashbin!\n");
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
,
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
);
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
)
238 DEBUG(0, __FUNCTION__
"()\n");
240 /* Check if we should call the device eth<x> or irlan<x> */
242 /* Get the first free irlan<x> name */
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");
253 self
->netdev_registered
= TRUE
;
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
);
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
;
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? */
311 irlan_register_netdev(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
;
346 * Function irlan_close (self)
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");
366 DEBUG(2, __FUNCTION__
"(), daddr=%08x\n", self
->daddr
);
367 entry
= hashbin_remove(irlan
, self
->daddr
, NULL
);
369 ASSERT(entry
== self
, return;);
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 */
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
428 irlan_get_unicast_addr(self
);
429 irlan_open_unicast_addr(self
);
431 /* Ready to transfer Ethernet frames */
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");
462 case LM_USER_REQUEST
: /* User request */
465 case LM_LAP_DISCONNECT
: /* Unexpected IrLAP disconnect */
466 irlan_start_watchdog_timer(self
, IRLAN_TIMEOUT
);
468 case LM_CONNECT_FAILURE
: /* Failed to establish IrLAP connection */
469 DEBUG(2, __FUNCTION__
"(), LM_CONNECT_FAILURE not impl\n");
471 case LM_LAP_RESET
: /* IrLAP reset */
472 DEBUG(2, __FUNCTION__
"(), LM_CONNECT_FAILURE not impl\n");
474 case LM_INIT_DISCONNECT
:
475 DEBUG(2, __FUNCTION__
"(), LM_CONNECT_FAILURE not impl\n");
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 */
502 irda_notify_init(¬ify
);
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
, ¬ify
);
515 DEBUG(2, __FUNCTION__
"(), Got no tsap!\n");
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
,
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
,
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
);
580 new_value
= irias_new_integer_value(tsap_sel
);
581 irias_object_change_attribute("IrLAN", "IrDA:TinyTP:LsapSel",
585 /* Register PnP object only if not registred before */
586 if (!irias_find_object("PnP")) {
587 obj
= irias_new_object("PnP", IAS_PNP_ID
);
589 irias_add_string_attrib(obj
, "Name", sysctl_devname
);
591 irias_add_string_attrib(obj
, "Name", "Linux");
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
)
613 DEBUG(4, __FUNCTION__
"()\n");
615 ASSERT(self
!= NULL
, return;);
616 ASSERT(self
->magic
== IRLAN_MAGIC
, return;);
618 skb
= dev_alloc_skb(64);
622 /* Reserve space for TTP, LMP, and LAP header */
623 skb_reserve(skb
, TTP_HEADER
+LMP_HEADER
+LAP_HEADER
);
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
)
645 DEBUG(4, __FUNCTION__
"()\n");
647 ASSERT(self
!= NULL
, return;);
648 ASSERT(self
->magic
== IRLAN_MAGIC
, return;);
650 skb
= dev_alloc_skb(64);
654 skb_reserve(skb
, TTP_HEADER
+LMP_HEADER
+LAP_HEADER
);
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
)
677 DEBUG(4, __FUNCTION__
"()\n");
679 ASSERT(self
!= NULL
, return;);
680 ASSERT(self
->magic
== IRLAN_MAGIC
, return;);
682 skb
= dev_alloc_skb(64);
686 skb_reserve(skb
, TTP_HEADER
+LMP_HEADER
+LAP_HEADER
);
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
707 void irlan_open_unicast_addr(struct irlan_cb
*self
)
712 DEBUG(4, __FUNCTION__
"()\n");
714 ASSERT(self
!= NULL
, return;);
715 ASSERT(self
->magic
== IRLAN_MAGIC
, return;);
717 skb
= dev_alloc_skb(128);
721 /* Reserve space for TTP, LMP, and LAP header */
722 skb_reserve(skb
, TTP_HEADER
+LMP_HEADER
+LAP_HEADER
);
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
)
750 DEBUG(2, __FUNCTION__
"()\n");
752 ASSERT(self
!= NULL
, return;);
753 ASSERT(self
->magic
== IRLAN_MAGIC
, return;);
755 skb
= dev_alloc_skb(128);
759 /* Reserve space for TTP, LMP, and LAP header */
760 skb_reserve(skb
, TTP_HEADER
+LMP_HEADER
+LAP_HEADER
);
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");
770 irlan_insert_string_param(skb
, "FILTER_MODE", "FILTER");
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
784 void irlan_set_multicast_filter(struct irlan_cb
*self
, int status
)
789 DEBUG(2, __FUNCTION__
"()\n");
791 ASSERT(self
!= NULL
, return;);
792 ASSERT(self
->magic
== IRLAN_MAGIC
, return;);
794 skb
= dev_alloc_skb(128);
798 /* Reserve space for TTP, LMP, and LAP header */
799 skb_reserve(skb
, TTP_HEADER
+LMP_HEADER
+LAP_HEADER
);
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");
809 irlan_insert_string_param(skb
, "FILTER_MODE", "ALL");
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
)
829 DEBUG(2, __FUNCTION__
"()\n");
831 ASSERT(self
!= NULL
, return;);
832 ASSERT(self
->magic
== IRLAN_MAGIC
, return;);
834 skb
= dev_alloc_skb(128);
838 /* Reserve space for TTP, LMP, and LAP header */
839 skb_reserve(skb
, TTP_HEADER
+LMP_HEADER
+LAP_HEADER
);
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
)
864 DEBUG(4, __FUNCTION__
"()\n");
866 ASSERT(self
!= NULL
, return;);
867 ASSERT(self
->magic
== IRLAN_MAGIC
, return;);
869 skb
= dev_alloc_skb(64);
873 /* Reserve space for TTP, LMP, and LAP header */
874 skb_reserve(skb
, TTP_HEADER
+LMP_HEADER
+LAP_HEADER
);
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
,
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
,
927 return __irlan_insert_param(skb
, name
, IRLAN_ARRAY
, 0, 0, array
,
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
)
946 __u16 tmp_le
; /* Temporary value in little endian format */
950 DEBUG(2, __FUNCTION__
"(), Got NULL skb\n");
954 param_len
= strlen(param
);
963 ASSERT(value_array
!= NULL
, return 0;);
964 ASSERT(value_len
> 0, return 0;);
967 DEBUG(2, __FUNCTION__
"(), Unknown parameter type!\n");
972 /* Insert at end of sk-buffer */
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");
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 */
995 frame
[n
++] = value_byte
;
998 tmp_le
= cpu_to_le16(value_short
);
999 memcpy(frame
+n
, &tmp_le
, 2); n
+= 2;
1002 memcpy(frame
+n
, value_array
, value_len
); n
+=value_len
;
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
)
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';
1040 * Get length of parameter value (2 bytes in little endian
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
;
1052 /* get parameter value */
1053 memcpy(value
, buf
+n
, val_len
);
1054 value
[ val_len
] = '\0';
1057 DEBUG(4, "Parameter: %s ", name
);
1058 DEBUG(4, "Value: %s\n", value
);
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
,
1072 struct irlan_cb
*self
;
1073 unsigned long flags
;
1078 ASSERT(irlan
!= NULL
, return 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",
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, ",
1096 len
+= sprintf(buf
+len
, "daddr: %#08x\n",
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
?
1112 len
+= sprintf(buf
+len
, "\n");
1114 self
= (struct irlan_cb
*) hashbin_get_next(irlan
);
1116 restore_flags(flags
);
1123 * Function print_ret_code (code)
1125 * Print return code of request to peer IrLAN layer.
1128 void print_ret_code(__u8 code
)
1132 printk(KERN_INFO
"Success\n");
1135 printk(KERN_WARNING
"Insufficient resources\n");
1138 printk(KERN_WARNING
"Invalid command format\n");
1141 printk(KERN_WARNING
"Command not supported\n");
1144 printk(KERN_WARNING
"Parameter not supported\n");
1147 printk(KERN_WARNING
"Value not supported\n");
1150 printk(KERN_WARNING
"Not open\n");
1153 printk(KERN_WARNING
"Authentication required\n");
1156 printk(KERN_WARNING
"Invalid password\n");
1159 printk(KERN_WARNING
"Protocol error\n");
1162 printk(KERN_WARNING
"Asynchronous status\n");
1167 void irlan_mod_inc_use_count(void)
1174 void irlan_mod_dec_use_count(void)
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)
1207 void cleanup_module(void)
1209 /* Free some memory */