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: Tue Jan 19 23:11:30 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>
48 static void __irlan_close( struct irlan_cb
*self
);
53 hashbin_t
*irlan
= NULL
;
56 static int irlan_proc_read( char *buf
, char **start
, off_t offset
,
59 extern struct proc_dir_entry proc_irda
;
61 struct proc_dir_entry proc_irlan
= {
63 S_IFREG
| S_IRUGO
, 1, 0, 0,
70 * Function irlan_init (void)
72 * Initialize IrLAN layer
75 __initfunc(int irlan_init( void))
77 /* Allocate master array */
78 irlan
= hashbin_new( HB_LOCAL
);
80 printk( KERN_WARNING
"IrLAN: Can't allocate hashbin!\n");
84 proc_register( &proc_irda
, &proc_irlan
);
85 #endif /* CONFIG_PROC_FS */
90 void irlan_cleanup(void)
92 DEBUG( 4, __FUNCTION__
"()\n");
95 proc_unregister( &proc_irda
, proc_irlan
.low_ino
);
98 * Delete hashbin and close all irlan client instances in it
100 hashbin_delete( irlan
, (FREE_FUNC
) __irlan_close
);
105 * Function irlan_open (void)
110 struct irlan_cb
*irlan_open(void)
112 struct irlan_cb
*self
;
114 DEBUG( 4, __FUNCTION__
"()\n");
117 * Initialize the irlan structure.
119 self
= kmalloc( sizeof(struct irlan_cb
), GFP_ATOMIC
);
123 memset( self
, 0, sizeof( struct irlan_cb
));
126 * Initialize local device structure
128 self
->magic
= IRLAN_MAGIC
;
133 * Function irlan_close (self)
135 * This function closes and deallocates the IrLAN client instances. Be
136 * aware that other functions which calles client_close() must call
137 * hashbin_remove() first!!!
140 void __irlan_close( struct irlan_cb
*self
)
142 DEBUG( 4, __FUNCTION__
"()\n");
144 ASSERT( self
!= NULL
, return;);
145 ASSERT( self
->magic
== IRLAN_MAGIC
, return;);
148 * Disconnect open TSAP connections
150 if ( self
->tsap_data
) {
151 irttp_disconnect_request( self
->tsap_data
, NULL
, P_HIGH
);
153 /* FIXME: this will close the tsap before the disconenct
154 * frame has been sent
156 /* irttp_close_tsap( self->tsap_data); */
158 if ( self
->tsap_ctrl
) {
159 irttp_disconnect_request( self
->tsap_ctrl
, NULL
, P_HIGH
);
161 /* irttp_close_tsap( self->tsap_control); */
164 unregister_netdev( &self
->dev
);
167 * Make sure that nobody uses this instance anymore!
172 * Dealloacte structure
178 * Function irlan_close (self)
183 void irlan_close( struct irlan_cb
*self
)
185 struct irlan_cb
*entry
;
187 DEBUG( 4, __FUNCTION__
"()\n");
189 ASSERT( self
!= NULL
, return;);
190 ASSERT( self
->magic
== IRLAN_MAGIC
, return;);
192 entry
= hashbin_remove( irlan
, self
->daddr
, NULL
);
194 ASSERT( entry
== self
, return;);
196 __irlan_close( self
);
200 * Function irlan_get_provider_info (self)
202 * Send Get Provider Information command to peer IrLAN layer
205 void irlan_get_provider_info( struct irlan_cb
*self
)
210 DEBUG( 4, __FUNCTION__
"()\n");
212 ASSERT( self
!= NULL
, return;);
213 ASSERT( self
->magic
== IRLAN_MAGIC
, return;);
215 skb
= dev_alloc_skb( 64);
217 DEBUG( 0, __FUNCTION__
218 "(), Could not allocate an skb of length %d\n", 64);
222 /* Reserve space for TTP, LMP, and LAP header */
223 skb_reserve( skb
, TTP_HEADER
+LMP_HEADER
+LAP_HEADER
);
228 frame
[0] = CMD_GET_PROVIDER_INFO
;
229 frame
[1] = 0x00; /* Zero parameters */
231 irttp_data_request( self
->tsap_ctrl
, skb
);
235 * Function irlan_open_data_channel (self)
237 * Send an Open Data Command to provider
240 void irlan_open_data_channel( struct irlan_cb
*self
)
245 DEBUG( 4, __FUNCTION__
"()\n");
247 ASSERT( self
!= NULL
, return;);
248 ASSERT( self
->magic
== IRLAN_MAGIC
, return;);
250 skb
= dev_alloc_skb( 64);
252 DEBUG( 0, __FUNCTION__
253 "(), Could not allocate an skb of length %d\n", 64);
257 /* Reserve space for TTP, LMP, and LAP header */
258 skb_reserve( skb
, TTP_HEADER
+LMP_HEADER
+LAP_HEADER
);
264 frame
[0] = CMD_OPEN_DATA_CHANNEL
;
265 frame
[1] = 0x02; /* Two parameters */
267 insert_string_param( skb
, "MEDIA", "802.3");
268 insert_string_param( skb
, "ACCESS_TYPE", "DIRECT");
269 /* insert_string_param( skb, "MODE", "UNRELIABLE"); */
271 /* self->use_udata = TRUE; */
273 irttp_data_request( self
->tsap_ctrl
, skb
);
277 * Function irlan_open_unicast_addr (self)
279 * Make IrLAN provider accept ethernet frames addressed to the unicast
283 void irlan_open_unicast_addr( struct irlan_cb
*self
)
288 DEBUG( 4, __FUNCTION__
"()\n");
290 ASSERT( self
!= NULL
, return;);
291 ASSERT( self
->magic
== IRLAN_MAGIC
, return;);
293 skb
= dev_alloc_skb( 128);
295 DEBUG( 0, __FUNCTION__
296 "(), Could not allocate an skb of length %d\n", 64);
300 /* Reserve space for TTP, LMP, and LAP header */
301 skb_reserve( skb
, TTP_HEADER
+LMP_HEADER
+LAP_HEADER
);
306 frame
[0] = CMD_FILTER_OPERATION
;
307 frame
[1] = 0x03; /* Three parameters */
308 insert_byte_param( skb
, "DATA_CHAN" , self
->dtsap_sel_data
);
309 insert_string_param( skb
, "FILTER_TYPE", "DIRECTED");
310 insert_string_param( skb
, "FILTER_MODE", "FILTER");
312 irttp_data_request( self
->tsap_ctrl
, skb
);
316 * Function irlan_set_broadcast_filter (self, status)
318 * Make IrLAN provider accept ethernet frames addressed to the broadcast
319 * address. Be careful with the use of this one, sice there may be a lot
320 * of broadcast traffic out there. We can still function without this
321 * one but then _we_ have to initiate all communication with other
322 * hosts, sice ARP request for this host will not be answered.
324 void irlan_set_broadcast_filter( struct irlan_cb
*self
, int status
)
329 DEBUG( 4, __FUNCTION__
"()\n");
331 ASSERT( self
!= NULL
, return;);
332 ASSERT( self
->magic
== IRLAN_MAGIC
, return;);
334 /* Should only be used by client */
338 skb
= dev_alloc_skb( 128);
340 DEBUG( 0, __FUNCTION__
341 "(), Could not allocate an skb of length %d\n", 64);
345 /* Reserve space for TTP, LMP, and LAP header */
346 skb_reserve( skb
, TTP_HEADER
+LMP_HEADER
+LAP_HEADER
);
351 frame
[0] = CMD_FILTER_OPERATION
;
352 frame
[1] = 0x03; /* Three parameters */
353 insert_byte_param( skb
, "DATA_CHAN", self
->dtsap_sel_data
);
354 insert_string_param( skb
, "FILTER_TYPE", "BROADCAST");
356 insert_string_param( skb
, "FILTER_MODE", "FILTER");
358 insert_string_param( skb
, "FILTER_MODE", "NONE");
360 irttp_data_request( self
->tsap_ctrl
, skb
);
364 * Function irlan_set_multicast_filter (self, status)
366 * Make IrLAN provider accept ethernet frames addressed to the multicast
370 void irlan_set_multicast_filter( struct irlan_cb
*self
, int status
)
375 DEBUG( 4, __FUNCTION__
"()\n");
377 ASSERT( self
!= NULL
, return;);
378 ASSERT( self
->magic
== IRLAN_MAGIC
, return;);
380 /* Should only be used by client */
384 skb
= dev_alloc_skb( 128);
386 DEBUG( 0, __FUNCTION__
387 "(), Could not allocate an skb of length %d\n", 64);
391 /* Reserve space for TTP, LMP, and LAP header */
392 skb_reserve( skb
, TTP_HEADER
+LMP_HEADER
+LAP_HEADER
);
397 frame
[0] = CMD_FILTER_OPERATION
;
398 frame
[1] = 0x03; /* Three parameters */
399 insert_byte_param( skb
, "DATA_CHAN", self
->dtsap_sel_data
);
400 insert_string_param( skb
, "FILTER_TYPE", "MULTICAST");
402 insert_string_param( skb
, "FILTER_MODE", "ALL");
404 insert_string_param( skb
, "FILTER_MODE", "NONE");
406 irttp_data_request( self
->tsap_ctrl
, skb
);
410 * Function irlan_get_unicast_addr (self)
412 * Retrives the unicast address from the IrLAN provider. This address
413 * will be inserted into the devices structure, so the ethernet layer
414 * can construct its packets.
417 void irlan_get_unicast_addr( struct irlan_cb
*self
)
422 DEBUG( 4, __FUNCTION__
"()\n");
424 ASSERT( self
!= NULL
, return;);
425 ASSERT( self
->magic
== IRLAN_MAGIC
, return;);
427 skb
= dev_alloc_skb( 128);
429 DEBUG( 0, "irlan_client_get_unicast_addr: "
430 "Could not allocate an sk_buff of length %d\n", 64);
434 /* Reserve space for TTP, LMP, and LAP header */
435 skb_reserve( skb
, TTP_HEADER
+LMP_HEADER
+LAP_HEADER
);
440 frame
[0] = CMD_FILTER_OPERATION
;
441 frame
[1] = 0x03; /* Three parameters */
442 insert_byte_param( skb
, "DATA_CHAN", self
->dtsap_sel_data
);
443 insert_string_param( skb
, "FILTER_TYPE", "DIRECTED");
444 insert_string_param( skb
, "FILTER_OPERATION", "DYNAMIC");
446 irttp_data_request( self
->tsap_ctrl
, skb
);
450 * Function irlan_get_media_char (self)
455 void irlan_get_media_char( struct irlan_cb
*self
)
460 DEBUG( 4, __FUNCTION__
"()\n");
462 ASSERT( self
!= NULL
, return;);
463 ASSERT( self
->magic
== IRLAN_MAGIC
, return;);
465 skb
= dev_alloc_skb( 64);
467 DEBUG( 0,"irlan_server_get_media_char: "
468 "Could not allocate an sk_buff of length %d\n", 64);
472 /* Reserve space for TTP, LMP, and LAP header */
473 skb_reserve( skb
, TTP_HEADER
+LMP_HEADER
+LAP_HEADER
);
479 frame
[0] = CMD_GET_MEDIA_CHAR
;
480 frame
[1] = 0x01; /* One parameter */
482 insert_string_param( skb
, "MEDIA", "802.3");
484 irttp_data_request( self
->tsap_ctrl
, skb
);
488 * Function insert_byte_param (skb, param, value)
490 * Insert byte parameter into frame
493 int insert_byte_param( struct sk_buff
*skb
, char *param
, __u8 value
)
501 DEBUG( 0, "insert_param: Got NULL skb\n");
505 len_param
= strlen( param
);
509 * Insert at end of sk-buffer
513 /* Make space for data */
514 if ( skb_tailroom(skb
) < (len_param
+len_value
+3)) {
515 DEBUG( 0, "insert_param: No more space at end of skb\n");
518 skb_put( skb
, len_param
+len_value
+3);
520 /* Insert parameter length */
521 frame
[n
++] = len_param
;
523 /* Insert parameter */
524 memcpy( frame
+n
, param
, len_param
);
527 /* Insert value length ( 2 byte little endian format, LSB first) */
528 frame
[n
++] = len_value
& 0xff;
529 frame
[n
++] = len_value
>> 8;
533 return len_param
+len_value
+3;
537 * Function insert_string (skb, param, value)
539 * Insert string parameter into frame
542 int insert_string_param( struct sk_buff
*skb
, char *param
, char *value
)
550 DEBUG( 0, "insert_param: Got NULL skb\n");
553 len_param
= strlen( param
);
554 len_value
= strlen( value
);
557 * Insert at end of sk-buffer
561 /* Make space for data */
562 if ( skb_tailroom(skb
) < (len_param
+len_value
+3)) {
563 DEBUG( 0, "insert_param: No more space at end of skb\n");
566 skb_put( skb
, len_param
+len_value
+3);
568 /* Insert parameter length */
569 frame
[n
++] = len_param
;
571 /* Insert parameter */
572 memcpy( frame
+n
, param
, len_param
);
575 /* Insert value length ( 2 byte little endian format, LSB first) */
576 frame
[n
++] = len_value
& 0xff;
577 frame
[n
++] = len_value
>> 8;
579 memcpy( frame
+n
, value
, len_value
);
582 return len_param
+len_value
+3;
586 * Function insert_array_param( skb, param, value, len_value)
588 * Insert array parameter into frame
591 int insert_array_param( struct sk_buff
*skb
, char *name
, __u8
*value
,
599 DEBUG( 0, __FUNCTION__
"(), Got NULL skb\n");
602 name_len
= strlen( name
);
605 * Insert at end of sk-buffer
609 /* Make space for data */
610 if ( skb_tailroom(skb
) < (name_len
+value_len
+3)) {
611 DEBUG( 0, __FUNCTION__
"(), No more space at end of skb\n");
614 skb_put( skb
, name_len
+value_len
+3);
616 /* Insert parameter length */
617 frame
[n
++] = name_len
;
619 /* Insert parameter */
620 memcpy( frame
+n
, name
, name_len
);
623 /* Insert value length ( 2 byte little endian format, LSB first) */
624 /* FIXME: should we use htons() here? */
625 frame
[n
++] = value_len
& 0xff;
626 frame
[n
++] = value_len
>> 8;
628 memcpy( frame
+n
, value
, value_len
);
631 return name_len
+value_len
+3;
635 * Function insert_param (skb, param, value, byte)
637 * Insert parameter at end of buffer, structure of a parameter is:
639 * -----------------------------------------------------------------------
640 * | Name Length[1] | Param Name[1..255] | Val Length[2] | Value[0..1016]|
641 * -----------------------------------------------------------------------
643 int insert_param( struct sk_buff
*skb
, char *param
, int type
, char *value_char
,
644 __u8 value_byte
, __u16 value_short
)
652 DEBUG( 0, "insert_param: Got NULL skb\n");
658 len_param
= strlen( param
);
661 ASSERT( value_char
!= NULL
, return 0;);
662 len_value
= strlen( value_char
);
671 DEBUG( 0, "Error in insert_param!\n");
677 * Insert at end of sk-buffer
681 /* Make space for data */
682 if ( skb_tailroom(skb
) < (len_param
+len_value
+3)) {
683 DEBUG( 0, "insert_param: No more space at end of skb\n");
686 skb_put( skb
, len_param
+len_value
+3);
688 /* Insert parameter length */
689 frame
[n
++] = len_param
;
691 /* Insert parameter */
692 memcpy( frame
+n
, param
, len_param
); n
+= len_param
;
694 /* Insert value length ( 2 byte little endian format, LSB first) */
695 frame
[n
++] = len_value
& 0xff;
696 frame
[n
++] = len_value
>> 8;
701 memcpy( frame
+n
, value_char
, len_value
); n
+=len_value
;
704 frame
[n
++] = value_byte
;
707 frame
[n
++] = value_short
& 0xff;
708 frame
[n
++] = (value_short
>> 8) & 0xff;
713 ASSERT( n
== (len_param
+len_value
+3), return 0;);
715 return len_param
+len_value
+3;
719 * Function irlan_get_response_param (buf, param, value)
721 * Extracts a single parameter name/value pair from buffer and updates
722 * the buffer pointer to point to the next name/value pair.
725 int irlan_get_response_param( __u8
*buf
, char *name
, char *value
, int *len
)
731 DEBUG( 4, "irlan_get_response_param()\n");
733 /* get length of parameter name ( 1 byte) */
736 if (name_len
> 254) {
737 DEBUG( 0, __FUNCTION__
"(), name_len > 254\n");
741 /* get parameter name */
742 memcpy( name
, buf
+n
, name_len
);
743 name
[ name_len
] = '\0';
747 * Get length of parameter value ( 2 bytes in little endian
750 val_len
= buf
[n
++] & 0xff;
751 val_len
|= buf
[n
++] << 8;
753 if (val_len
> 1016) {
754 DEBUG( 0, __FUNCTION__
"(), parameter length to long\n");
760 /* get parameter value */
761 memcpy( value
, buf
+n
, val_len
);
762 value
[ val_len
] = '\0';
765 DEBUG( 4, "Parameter: %s ", name
);
766 DEBUG( 4, "Value: %s\n", value
);
771 #ifdef CONFIG_PROC_FS
773 * Function irlan_client_proc_read (buf, start, offset, len, unused)
775 * Give some info to the /proc file system
777 static int irlan_proc_read( char *buf
, char **start
, off_t offset
,
780 struct irlan_cb
*self
;
782 ASSERT( irlan
!= NULL
, return 0;);
786 len
+= sprintf( buf
+len
, "IrLAN\n");
788 self
= ( struct irlan_cb
*) hashbin_get_first( irlan
);
789 while ( self
!= NULL
) {
790 ASSERT( self
->magic
== IRLAN_MAGIC
, return len
;);
792 len
+= sprintf( buf
+len
, "ifname: %s, ",
794 /* len += sprintf( buf+len, "state: %s, ", */
795 /* irlan_client_state[ self->state]); */
796 len
+= sprintf( buf
+len
, "saddr: %#08x\n",
798 len
+= sprintf( buf
+len
, "daddr: %#08x\n",
800 len
+= sprintf( buf
+len
, "tbusy: %s\n", self
->dev
.tbusy
?
803 len
+= sprintf( buf
+len
, "\n");
805 self
= ( struct irlan_cb
*) hashbin_get_next( irlan
);
806 DEBUG( 4, "self=%p\n", self
);
813 * Function print_ret_code (code)
815 * Print return code of request to peer IrLAN layer.
818 void print_ret_code( __u8 code
)
822 printk( KERN_INFO
"Success\n");
825 printk( KERN_WARNING
"Insufficient resources\n");
828 printk( KERN_WARNING
"Invalid command format\n");
831 printk( KERN_WARNING
"Command not supported\n");
834 printk( KERN_WARNING
"Parameter not supported\n");
837 printk( KERN_WARNING
"Value not supported\n");
840 printk( KERN_WARNING
"Not open\n");
843 printk( KERN_WARNING
"Authentication required\n");
846 printk( KERN_WARNING
"Invalid password\n");
849 printk( KERN_WARNING
"Protocol error\n");
852 printk( KERN_WARNING
"Asynchronous status\n");
859 MODULE_AUTHOR("Dag Brattli <dagb@cs.uit.no>");
860 MODULE_DESCRIPTION("The Linux IrDA LAN protocol");
863 * Function init_module (void)
865 * Initialize the IrLAN module, this function is called by the
866 * modprobe(1) program.
868 int init_module(void)
870 DEBUG( 4, __FUNCTION__
"(), irlan.c\n");
878 * Function cleanup_module (void)
880 * Remove the IrLAN module, this function is called by the rmmod(1)
883 void cleanup_module(void)
885 DEBUG( 4, "--> irlan, cleanup_module\n");
886 /* No need to check MOD_IN_USE, as sys_delete_module() checks. */
888 /* Free some memory */
891 DEBUG( 4, "irlan, cleanup_module -->\n");