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: Sun Dec 26 21:53:10 1999
10 * Modified by: Dag Brattli <dagb@cs.uit.no>
12 * Copyright (c) 1997, 1999 Dag Brattli <dagb@cs.uit.no>,
13 * All Rights Reserved.
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.
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.
24 ********************************************************************/
26 #include <linux/config.h>
27 #include <linux/module.h>
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>
37 #include <asm/system.h>
38 #include <asm/bitops.h>
39 #include <asm/byteorder.h>
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>
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>
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.
59 #undef CONFIG_IRLAN_SEND_GRATUITOUS_ARP
61 /* extern char sysctl_devname[]; */
66 hashbin_t
*irlan
= NULL
;
67 static __u32 ckey
, skey
;
69 /* Module parameters */
70 static int eth
= 0; /* Use "eth" or "irlan" name for devices */
71 static int access
= ACCESS_PEER
; /* PEER, DIRECT or HOSTED */
74 static char *irlan_state
[] = {
88 static char *irlan_access
[] = {
95 static char *irlan_media
[] = {
100 #endif /* CONFIG_PROC_FS */
102 static void __irlan_close(struct irlan_cb
*self
);
103 static int __irlan_insert_param(struct sk_buff
*skb
, char *param
, int type
,
104 __u8 value_byte
, __u16 value_short
,
105 __u8
*value_array
, __u16 value_len
);
106 void irlan_close_tsaps(struct irlan_cb
*self
);
108 #ifdef CONFIG_PROC_FS
109 static int irlan_proc_read(char *buf
, char **start
, off_t offset
, int len
);
111 extern struct proc_dir_entry
*proc_irda
;
112 #endif /* CONFIG_PROC_FS */
115 * Function irlan_init (void)
117 * Initialize IrLAN layer
120 int __init
irlan_init(void)
122 struct irlan_cb
*new;
125 IRDA_DEBUG(0, __FUNCTION__
"()\n");
126 /* Allocate master structure */
127 irlan
= hashbin_new(HB_LOCAL
);
129 printk(KERN_WARNING
"IrLAN: Can't allocate hashbin!\n");
132 #ifdef CONFIG_PROC_FS
133 create_proc_info_entry("irlan", 0, proc_irda
, irlan_proc_read
);
134 #endif /* CONFIG_PROC_FS */
136 IRDA_DEBUG(4, __FUNCTION__
"()\n");
137 hints
= irlmp_service_to_hint(S_LAN
);
139 /* Register with IrLMP as a client */
140 ckey
= irlmp_register_client(hints
, &irlan_client_discovery_indication
,
143 /* Register with IrLMP as a service */
144 skey
= irlmp_register_service(hints
);
146 /* Start the master IrLAN instance (the only one for now) */
147 new = irlan_open(DEV_ADDR_ANY
, DEV_ADDR_ANY
);
149 /* The master will only open its (listen) control TSAP */
150 irlan_provider_open_ctrl_tsap(new);
152 /* Do some fast discovery! */
153 irlmp_discovery_request(DISCOVERY_DEFAULT_SLOTS
);
158 void irlan_cleanup(void)
160 IRDA_DEBUG(4, __FUNCTION__
"()\n");
162 irlmp_unregister_client(ckey
);
163 irlmp_unregister_service(skey
);
165 #ifdef CONFIG_PROC_FS
166 remove_proc_entry("irlan", proc_irda
);
167 #endif /* CONFIG_PROC_FS */
169 * Delete hashbin and close all irlan client instances in it
171 hashbin_delete(irlan
, (FREE_FUNC
) __irlan_close
);
175 * Function irlan_register_netdev (self)
177 * Registers the network device to be used. We should don't register until
178 * we have been binded to a particular provider or client.
180 int irlan_register_netdev(struct irlan_cb
*self
)
184 IRDA_DEBUG(0, __FUNCTION__
"()\n");
186 /* Check if we should call the device eth<x> or irlan<x> */
188 /* Get the first free irlan<x> name */
190 sprintf(self
->dev
.name
, "%s%d", "irlan", i
++);
191 } while (dev_get(self
->dev
.name
));
194 if (register_netdev(&self
->dev
) != 0) {
195 IRDA_DEBUG(2, __FUNCTION__
"(), register_netdev() failed!\n");
202 * Function irlan_open (void)
204 * Open new instance of a client/provider, we should only register the
205 * network device if this instance is ment for a particular client/provider
207 struct irlan_cb
*irlan_open(__u32 saddr
, __u32 daddr
)
209 struct irlan_cb
*self
;
211 IRDA_DEBUG(2, __FUNCTION__
"()\n");
214 * Initialize the irlan structure.
216 self
= kmalloc(sizeof(struct irlan_cb
), GFP_ATOMIC
);
220 memset(self
, 0, sizeof(struct irlan_cb
));
223 * Initialize local device structure
225 self
->magic
= IRLAN_MAGIC
;
227 ASSERT(irlan
!= NULL
, return NULL
;);
229 sprintf(self
->dev
.name
, "%s", "unknown");
231 self
->dev
.priv
= (void *) self
;
232 self
->dev
.next
= NULL
;
233 self
->dev
.init
= irlan_eth_init
;
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
);
246 hashbin_insert(irlan
, (irda_queue_t
*) self
, daddr
, NULL
);
248 skb_queue_head_init(&self
->client
.txq
);
250 irlan_next_client_state(self
, IRLAN_IDLE
);
251 irlan_next_provider_state(self
, IRLAN_IDLE
);
253 irlan_register_netdev(self
);
258 * Function __irlan_close (self)
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!!!
264 static void __irlan_close(struct irlan_cb
*self
)
268 IRDA_DEBUG(2, __FUNCTION__
"()\n");
270 ASSERT(self
!= NULL
, return;);
271 ASSERT(self
->magic
== IRLAN_MAGIC
, return;);
273 del_timer(&self
->watchdog_timer
);
274 del_timer(&self
->client
.kick_timer
);
276 /* Close all open connections and remove TSAPs */
277 irlan_close_tsaps(self
);
279 if (self
->client
.iriap
)
280 iriap_close(self
->client
.iriap
);
282 /* Remove frames queued on the control channel */
283 while ((skb
= skb_dequeue(&self
->client
.txq
)))
286 unregister_netdev(&self
->dev
);
293 * Function irlan_connect_indication (instance, sap, qos, max_sdu_size, skb)
295 * Here we receive the connect indication for the data channel
298 void irlan_connect_indication(void *instance
, void *sap
, struct qos_info
*qos
,
299 __u32 max_sdu_size
, __u8 max_header_size
,
302 struct irlan_cb
*self
;
303 struct tsap_cb
*tsap
;
305 IRDA_DEBUG(2, __FUNCTION__
"()\n");
307 self
= (struct irlan_cb
*) instance
;
308 tsap
= (struct tsap_cb
*) sap
;
310 ASSERT(self
!= NULL
, return;);
311 ASSERT(self
->magic
== IRLAN_MAGIC
, return;);
312 ASSERT(tsap
== self
->tsap_data
,return;);
314 self
->max_sdu_size
= max_sdu_size
;
315 self
->max_header_size
= max_header_size
;
317 IRDA_DEBUG(0, "IrLAN, We are now connected!\n");
319 del_timer(&self
->watchdog_timer
);
321 irlan_do_provider_event(self
, IRLAN_DATA_CONNECT_INDICATION
, skb
);
322 irlan_do_client_event(self
, IRLAN_DATA_CONNECT_INDICATION
, skb
);
324 if (self
->provider
.access_type
== ACCESS_PEER
) {
326 * Data channel is open, so we are now allowed to
327 * configure the remote filter
329 irlan_get_unicast_addr(self
);
330 irlan_open_unicast_addr(self
);
332 /* Ready to transfer Ethernet frames (at last) */
333 netif_start_queue(&self
->dev
); /* Clear reason */
336 void irlan_connect_confirm(void *instance
, void *sap
, struct qos_info
*qos
,
337 __u32 max_sdu_size
, __u8 max_header_size
,
340 struct irlan_cb
*self
;
342 self
= (struct irlan_cb
*) instance
;
344 ASSERT(self
!= NULL
, return;);
345 ASSERT(self
->magic
== IRLAN_MAGIC
, return;);
347 self
->max_sdu_size
= max_sdu_size
;
348 self
->max_header_size
= max_header_size
;
350 /* TODO: we could set the MTU depending on the max_sdu_size */
352 IRDA_DEBUG(2, "IrLAN, We are now connected!\n");
353 del_timer(&self
->watchdog_timer
);
356 * Data channel is open, so we are now allowed to configure the remote
359 irlan_get_unicast_addr(self
);
360 irlan_open_unicast_addr(self
);
362 /* Open broadcast and multicast filter by default */
363 irlan_set_broadcast_filter(self
, TRUE
);
364 irlan_set_multicast_filter(self
, TRUE
);
366 /* Ready to transfer Ethernet frames */
367 netif_start_queue(&self
->dev
);
368 self
->disconnect_reason
= 0; /* Clear reason */
369 #ifdef CONFIG_IRLAN_SEND_GRATUITOUS_ARP
370 irlan_eth_send_gratuitous_arp(&self
->dev
);
372 wake_up_interruptible(&self
->open_wait
);
376 * Function irlan_client_disconnect_indication (handle)
378 * Callback function for the IrTTP layer. Indicates a disconnection of
379 * the specified connection (handle)
381 void irlan_disconnect_indication(void *instance
, void *sap
, LM_REASON reason
,
382 struct sk_buff
*userdata
)
384 struct irlan_cb
*self
;
385 struct tsap_cb
*tsap
;
387 IRDA_DEBUG(0, __FUNCTION__
"(), reason=%d\n", reason
);
389 self
= (struct irlan_cb
*) instance
;
390 tsap
= (struct tsap_cb
*) sap
;
392 ASSERT(self
!= NULL
, return;);
393 ASSERT(self
->magic
== IRLAN_MAGIC
, return;);
394 ASSERT(tsap
!= NULL
, return;);
395 ASSERT(tsap
->magic
== TTP_TSAP_MAGIC
, return;);
397 ASSERT(tsap
== self
->tsap_data
, return;);
399 IRDA_DEBUG(2, "IrLAN, data channel disconnected by peer!\n");
401 /* Save reason so we know if we should try to reconnect or not */
402 self
->disconnect_reason
= reason
;
405 case LM_USER_REQUEST
: /* User request */
406 IRDA_DEBUG(2, __FUNCTION__
"(), User requested\n");
408 case LM_LAP_DISCONNECT
: /* Unexpected IrLAP disconnect */
409 IRDA_DEBUG(2, __FUNCTION__
"(), Unexpected IrLAP disconnect\n");
411 case LM_CONNECT_FAILURE
: /* Failed to establish IrLAP connection */
412 IRDA_DEBUG(2, __FUNCTION__
"(), IrLAP connect failed\n");
414 case LM_LAP_RESET
: /* IrLAP reset */
415 IRDA_DEBUG(2, __FUNCTION__
"(), IrLAP reset\n");
417 case LM_INIT_DISCONNECT
:
418 IRDA_DEBUG(2, __FUNCTION__
"(), IrLMP connect failed\n");
421 ERROR(__FUNCTION__
"(), Unknown disconnect reason\n");
425 irlan_do_client_event(self
, IRLAN_LMP_DISCONNECT
, NULL
);
426 irlan_do_provider_event(self
, IRLAN_LMP_DISCONNECT
, NULL
);
428 wake_up_interruptible(&self
->open_wait
);
431 void irlan_open_data_tsap(struct irlan_cb
*self
)
433 struct tsap_cb
*tsap
;
436 IRDA_DEBUG(2, __FUNCTION__
"()\n");
438 ASSERT(self
!= NULL
, return;);
439 ASSERT(self
->magic
== IRLAN_MAGIC
, return;);
441 /* Check if already open */
445 irda_notify_init(¬ify
);
447 notify
.data_indication
= irlan_eth_receive
;
448 notify
.udata_indication
= irlan_eth_receive
;
449 notify
.connect_indication
= irlan_connect_indication
;
450 notify
.connect_confirm
= irlan_connect_confirm
;
451 /*notify.flow_indication = irlan_eth_flow_indication;*/
452 notify
.disconnect_indication
= irlan_disconnect_indication
;
453 notify
.instance
= self
;
454 strncpy(notify
.name
, "IrLAN data", NOTIFY_MAX_NAME
);
456 tsap
= irttp_open_tsap(LSAP_ANY
, DEFAULT_INITIAL_CREDIT
, ¬ify
);
458 IRDA_DEBUG(2, __FUNCTION__
"(), Got no tsap!\n");
461 self
->tsap_data
= tsap
;
464 * This is the data TSAP selector which we will pass to the client
465 * when the client ask for it.
467 self
->stsap_sel_data
= self
->tsap_data
->stsap_sel
;
470 void irlan_close_tsaps(struct irlan_cb
*self
)
472 IRDA_DEBUG(4, __FUNCTION__
"()\n");
474 ASSERT(self
!= NULL
, return;);
475 ASSERT(self
->magic
== IRLAN_MAGIC
, return;);
477 /* Disconnect and close all open TSAP connections */
478 if (self
->tsap_data
) {
479 irttp_disconnect_request(self
->tsap_data
, NULL
, P_NORMAL
);
480 irttp_close_tsap(self
->tsap_data
);
481 self
->tsap_data
= NULL
;
483 if (self
->client
.tsap_ctrl
) {
484 irttp_disconnect_request(self
->client
.tsap_ctrl
, NULL
,
486 irttp_close_tsap(self
->client
.tsap_ctrl
);
487 self
->client
.tsap_ctrl
= NULL
;
489 if (self
->provider
.tsap_ctrl
) {
490 irttp_disconnect_request(self
->provider
.tsap_ctrl
, NULL
,
492 irttp_close_tsap(self
->provider
.tsap_ctrl
);
493 self
->provider
.tsap_ctrl
= NULL
;
495 self
->disconnect_reason
= LM_USER_REQUEST
;
499 * Function irlan_ias_register (self, tsap_sel)
501 * Register with LM-IAS
504 void irlan_ias_register(struct irlan_cb
*self
, __u8 tsap_sel
)
506 struct ias_object
*obj
;
507 struct ias_value
*new_value
;
509 ASSERT(self
!= NULL
, return;);
510 ASSERT(self
->magic
== IRLAN_MAGIC
, return;);
513 * Check if object has already been registred by a previous provider.
514 * If that is the case, we just change the value of the attribute
516 if (!irias_find_object("IrLAN")) {
517 obj
= irias_new_object("IrLAN", IAS_IRLAN_ID
);
518 irias_add_integer_attrib(obj
, "IrDA:TinyTP:LsapSel", tsap_sel
,
520 irias_insert_object(obj
);
522 new_value
= irias_new_integer_value(tsap_sel
);
523 irias_object_change_attribute("IrLAN", "IrDA:TinyTP:LsapSel",
527 /* Register PnP object only if not registred before */
528 if (!irias_find_object("PnP")) {
529 obj
= irias_new_object("PnP", IAS_PNP_ID
);
531 irias_add_string_attrib(obj
, "Name", sysctl_devname
,
534 irias_add_string_attrib(obj
, "Name", "Linux", IAS_KERNEL_ATTR
);
536 irias_add_string_attrib(obj
, "DeviceID", "HWP19F0",
538 irias_add_integer_attrib(obj
, "CompCnt", 1, IAS_KERNEL_ATTR
);
539 if (self
->provider
.access_type
== ACCESS_PEER
)
540 irias_add_string_attrib(obj
, "Comp#01", "PNP8389",
543 irias_add_string_attrib(obj
, "Comp#01", "PNP8294",
546 irias_add_string_attrib(obj
, "Manufacturer",
547 "Linux-IrDA Project", IAS_KERNEL_ATTR
);
548 irias_insert_object(obj
);
553 * Function irlan_run_ctrl_tx_queue (self)
555 * Try to send the next command in the control transmit queue
558 int irlan_run_ctrl_tx_queue(struct irlan_cb
*self
)
562 IRDA_DEBUG(2, __FUNCTION__
"()\n");
564 if (irda_lock(&self
->client
.tx_busy
) == FALSE
)
567 skb
= skb_dequeue(&self
->client
.txq
);
569 self
->client
.tx_busy
= FALSE
;
573 /* Check that it's really possible to send commands */
574 if ((self
->client
.tsap_ctrl
== NULL
) ||
575 (self
->client
.state
== IRLAN_IDLE
))
577 self
->client
.tx_busy
= FALSE
;
581 IRDA_DEBUG(2, __FUNCTION__
"(), sending ...\n");
583 return irttp_data_request(self
->client
.tsap_ctrl
, skb
);
587 * Function irlan_ctrl_data_request (self, skb)
589 * This function makes sure that commands on the control channel is being
590 * sent in a command/response fashion
592 void irlan_ctrl_data_request(struct irlan_cb
*self
, struct sk_buff
*skb
)
594 IRDA_DEBUG(2, __FUNCTION__
"()\n");
597 skb_queue_tail(&self
->client
.txq
, skb
);
599 /* Try to send command */
600 irlan_run_ctrl_tx_queue(self
);
604 * Function irlan_get_provider_info (self)
606 * Send Get Provider Information command to peer IrLAN layer
609 void irlan_get_provider_info(struct irlan_cb
*self
)
614 IRDA_DEBUG(4, __FUNCTION__
"()\n");
616 ASSERT(self
!= NULL
, return;);
617 ASSERT(self
->magic
== IRLAN_MAGIC
, return;);
619 skb
= dev_alloc_skb(64);
623 /* Reserve space for TTP, LMP, and LAP header */
624 skb_reserve(skb
, self
->client
.max_header_size
);
629 frame
[0] = CMD_GET_PROVIDER_INFO
;
630 frame
[1] = 0x00; /* Zero parameters */
632 irlan_ctrl_data_request(self
, skb
);
636 * Function irlan_open_data_channel (self)
638 * Send an Open Data Command to provider
641 void irlan_open_data_channel(struct irlan_cb
*self
)
646 IRDA_DEBUG(4, __FUNCTION__
"()\n");
648 ASSERT(self
!= NULL
, return;);
649 ASSERT(self
->magic
== IRLAN_MAGIC
, return;);
651 skb
= dev_alloc_skb(64);
655 skb_reserve(skb
, self
->client
.max_header_size
);
661 frame
[0] = CMD_OPEN_DATA_CHANNEL
;
662 frame
[1] = 0x02; /* Two parameters */
664 irlan_insert_string_param(skb
, "MEDIA", "802.3");
665 irlan_insert_string_param(skb
, "ACCESS_TYPE", "DIRECT");
666 /* irlan_insert_string_param(skb, "MODE", "UNRELIABLE"); */
668 /* self->use_udata = TRUE; */
670 irlan_ctrl_data_request(self
, skb
);
673 void irlan_close_data_channel(struct irlan_cb
*self
)
678 IRDA_DEBUG(4, __FUNCTION__
"()\n");
680 ASSERT(self
!= NULL
, return;);
681 ASSERT(self
->magic
== IRLAN_MAGIC
, return;);
683 /* Check if the TSAP is still there */
684 if (self
->client
.tsap_ctrl
== NULL
)
687 skb
= dev_alloc_skb(64);
691 skb_reserve(skb
, self
->client
.max_header_size
);
697 frame
[0] = CMD_CLOSE_DATA_CHAN
;
698 frame
[1] = 0x01; /* Two parameters */
700 irlan_insert_byte_param(skb
, "DATA_CHAN", self
->dtsap_sel_data
);
702 irlan_ctrl_data_request(self
, skb
);
706 * Function irlan_open_unicast_addr (self)
708 * Make IrLAN provider accept ethernet frames addressed to the unicast
712 void irlan_open_unicast_addr(struct irlan_cb
*self
)
717 IRDA_DEBUG(4, __FUNCTION__
"()\n");
719 ASSERT(self
!= NULL
, return;);
720 ASSERT(self
->magic
== IRLAN_MAGIC
, return;);
722 skb
= dev_alloc_skb(128);
726 /* Reserve space for TTP, LMP, and LAP header */
727 skb_reserve(skb
, self
->max_header_size
);
732 frame
[0] = CMD_FILTER_OPERATION
;
733 frame
[1] = 0x03; /* Three parameters */
734 irlan_insert_byte_param(skb
, "DATA_CHAN" , self
->dtsap_sel_data
);
735 irlan_insert_string_param(skb
, "FILTER_TYPE", "DIRECTED");
736 irlan_insert_string_param(skb
, "FILTER_MODE", "FILTER");
738 irlan_ctrl_data_request(self
, skb
);
742 * Function irlan_set_broadcast_filter (self, status)
744 * Make IrLAN provider accept ethernet frames addressed to the broadcast
745 * address. Be careful with the use of this one, since there may be a lot
746 * of broadcast traffic out there. We can still function without this
747 * one but then _we_ have to initiate all communication with other
748 * hosts, since ARP request for this host will not be answered.
750 void irlan_set_broadcast_filter(struct irlan_cb
*self
, int status
)
755 IRDA_DEBUG(2, __FUNCTION__
"()\n");
757 ASSERT(self
!= NULL
, return;);
758 ASSERT(self
->magic
== IRLAN_MAGIC
, return;);
760 skb
= dev_alloc_skb(128);
764 /* Reserve space for TTP, LMP, and LAP header */
765 skb_reserve(skb
, self
->client
.max_header_size
);
770 frame
[0] = CMD_FILTER_OPERATION
;
771 frame
[1] = 0x03; /* Three parameters */
772 irlan_insert_byte_param(skb
, "DATA_CHAN", self
->dtsap_sel_data
);
773 irlan_insert_string_param(skb
, "FILTER_TYPE", "BROADCAST");
775 irlan_insert_string_param(skb
, "FILTER_MODE", "FILTER");
777 irlan_insert_string_param(skb
, "FILTER_MODE", "NONE");
779 irlan_ctrl_data_request(self
, skb
);
783 * Function irlan_set_multicast_filter (self, status)
785 * Make IrLAN provider accept ethernet frames addressed to the multicast
789 void irlan_set_multicast_filter(struct irlan_cb
*self
, int status
)
794 IRDA_DEBUG(2, __FUNCTION__
"()\n");
796 ASSERT(self
!= NULL
, return;);
797 ASSERT(self
->magic
== IRLAN_MAGIC
, return;);
799 skb
= dev_alloc_skb(128);
803 /* Reserve space for TTP, LMP, and LAP header */
804 skb_reserve(skb
, self
->client
.max_header_size
);
809 frame
[0] = CMD_FILTER_OPERATION
;
810 frame
[1] = 0x03; /* Three parameters */
811 irlan_insert_byte_param(skb
, "DATA_CHAN", self
->dtsap_sel_data
);
812 irlan_insert_string_param(skb
, "FILTER_TYPE", "MULTICAST");
814 irlan_insert_string_param(skb
, "FILTER_MODE", "ALL");
816 irlan_insert_string_param(skb
, "FILTER_MODE", "NONE");
818 irlan_ctrl_data_request(self
, skb
);
822 * Function irlan_get_unicast_addr (self)
824 * Retrives the unicast address from the IrLAN provider. This address
825 * will be inserted into the devices structure, so the ethernet layer
826 * can construct its packets.
829 void irlan_get_unicast_addr(struct irlan_cb
*self
)
834 IRDA_DEBUG(2, __FUNCTION__
"()\n");
836 ASSERT(self
!= NULL
, return;);
837 ASSERT(self
->magic
== IRLAN_MAGIC
, return;);
839 skb
= dev_alloc_skb(128);
843 /* Reserve space for TTP, LMP, and LAP header */
844 skb_reserve(skb
, self
->client
.max_header_size
);
849 frame
[0] = CMD_FILTER_OPERATION
;
850 frame
[1] = 0x03; /* Three parameters */
851 irlan_insert_byte_param(skb
, "DATA_CHAN", self
->dtsap_sel_data
);
852 irlan_insert_string_param(skb
, "FILTER_TYPE", "DIRECTED");
853 irlan_insert_string_param(skb
, "FILTER_OPERATION", "DYNAMIC");
855 irlan_ctrl_data_request(self
, skb
);
859 * Function irlan_get_media_char (self)
864 void irlan_get_media_char(struct irlan_cb
*self
)
869 IRDA_DEBUG(4, __FUNCTION__
"()\n");
871 ASSERT(self
!= NULL
, return;);
872 ASSERT(self
->magic
== IRLAN_MAGIC
, return;);
874 skb
= dev_alloc_skb(64);
878 /* Reserve space for TTP, LMP, and LAP header */
879 skb_reserve(skb
, self
->client
.max_header_size
);
885 frame
[0] = CMD_GET_MEDIA_CHAR
;
886 frame
[1] = 0x01; /* One parameter */
888 irlan_insert_string_param(skb
, "MEDIA", "802.3");
889 irlan_ctrl_data_request(self
, skb
);
893 * Function insert_byte_param (skb, param, value)
895 * Insert byte parameter into frame
898 int irlan_insert_byte_param(struct sk_buff
*skb
, char *param
, __u8 value
)
900 return __irlan_insert_param(skb
, param
, IRLAN_BYTE
, value
, 0, NULL
, 0);
903 int irlan_insert_short_param(struct sk_buff
*skb
, char *param
, __u16 value
)
905 return __irlan_insert_param(skb
, param
, IRLAN_SHORT
, 0, value
, NULL
, 0);
909 * Function insert_string (skb, param, value)
911 * Insert string parameter into frame
914 int irlan_insert_string_param(struct sk_buff
*skb
, char *param
, char *string
)
916 int string_len
= strlen(string
);
918 return __irlan_insert_param(skb
, param
, IRLAN_ARRAY
, 0, 0, string
,
923 * Function insert_array_param(skb, param, value, len_value)
925 * Insert array parameter into frame
928 int irlan_insert_array_param(struct sk_buff
*skb
, char *name
, __u8
*array
,
931 return __irlan_insert_param(skb
, name
, IRLAN_ARRAY
, 0, 0, array
,
936 * Function insert_param (skb, param, value, byte)
938 * Insert parameter at end of buffer, structure of a parameter is:
940 * -----------------------------------------------------------------------
941 * | Name Length[1] | Param Name[1..255] | Val Length[2] | Value[0..1016]|
942 * -----------------------------------------------------------------------
944 static int __irlan_insert_param(struct sk_buff
*skb
, char *param
, int type
,
945 __u8 value_byte
, __u16 value_short
,
946 __u8
*value_array
, __u16 value_len
)
950 __u16 tmp_le
; /* Temporary value in little endian format */
954 IRDA_DEBUG(2, __FUNCTION__
"(), Got NULL skb\n");
958 param_len
= strlen(param
);
967 ASSERT(value_array
!= NULL
, return 0;);
968 ASSERT(value_len
> 0, return 0;);
971 IRDA_DEBUG(2, __FUNCTION__
"(), Unknown parameter type!\n");
976 /* Insert at end of sk-buffer */
979 /* Make space for data */
980 if (skb_tailroom(skb
) < (param_len
+value_len
+3)) {
981 IRDA_DEBUG(2, __FUNCTION__
"(), No more space at end of skb\n");
984 skb_put(skb
, param_len
+value_len
+3);
986 /* Insert parameter length */
987 frame
[n
++] = param_len
;
989 /* Insert parameter */
990 memcpy(frame
+n
, param
, param_len
); n
+= param_len
;
992 /* Insert value length (2 byte little endian format, LSB first) */
993 tmp_le
= cpu_to_le16(value_len
);
994 memcpy(frame
+n
, &tmp_le
, 2); n
+= 2; /* To avoid alignment problems */
999 frame
[n
++] = value_byte
;
1002 tmp_le
= cpu_to_le16(value_short
);
1003 memcpy(frame
+n
, &tmp_le
, 2); n
+= 2;
1006 memcpy(frame
+n
, value_array
, value_len
); n
+=value_len
;
1011 ASSERT(n
== (param_len
+value_len
+3), return 0;);
1013 return param_len
+value_len
+3;
1017 * Function irlan_extract_param (buf, name, value, len)
1019 * Extracts a single parameter name/value pair from buffer and updates
1020 * the buffer pointer to point to the next name/value pair.
1022 int irlan_extract_param(__u8
*buf
, char *name
, char *value
, __u16
*len
)
1028 IRDA_DEBUG(4, __FUNCTION__
"()\n");
1030 /* get length of parameter name (1 byte) */
1031 name_len
= buf
[n
++];
1033 if (name_len
> 254) {
1034 IRDA_DEBUG(2, __FUNCTION__
"(), name_len > 254\n");
1035 return -RSP_INVALID_COMMAND_FORMAT
;
1038 /* get parameter name */
1039 memcpy(name
, buf
+n
, name_len
);
1040 name
[name_len
] = '\0';
1044 * Get length of parameter value (2 bytes in little endian
1047 memcpy(&val_len
, buf
+n
, 2); /* To avoid alignment problems */
1048 le16_to_cpus(&val_len
); n
+=2;
1050 if (val_len
> 1016) {
1051 IRDA_DEBUG(2, __FUNCTION__
"(), parameter length to long\n");
1052 return -RSP_INVALID_COMMAND_FORMAT
;
1056 /* get parameter value */
1057 memcpy(value
, buf
+n
, val_len
);
1058 value
[val_len
] = '\0';
1061 IRDA_DEBUG(4, "Parameter: %s ", name
);
1062 IRDA_DEBUG(4, "Value: %s\n", value
);
1067 #ifdef CONFIG_PROC_FS
1069 * Function irlan_client_proc_read (buf, start, offset, len, unused)
1071 * Give some info to the /proc file system
1073 static int irlan_proc_read(char *buf
, char **start
, off_t offset
, int len
)
1075 struct irlan_cb
*self
;
1076 unsigned long flags
;
1081 ASSERT(irlan
!= NULL
, return 0;);
1085 len
+= sprintf(buf
+len
, "IrLAN instances:\n");
1087 self
= (struct irlan_cb
*) hashbin_get_first(irlan
);
1088 while (self
!= NULL
) {
1089 ASSERT(self
->magic
== IRLAN_MAGIC
, return len
;);
1091 len
+= sprintf(buf
+len
, "ifname: %s,\n",
1093 len
+= sprintf(buf
+len
, "client state: %s, ",
1094 irlan_state
[ self
->client
.state
]);
1095 len
+= sprintf(buf
+len
, "provider state: %s,\n",
1096 irlan_state
[ self
->provider
.state
]);
1097 len
+= sprintf(buf
+len
, "saddr: %#08x, ",
1099 len
+= sprintf(buf
+len
, "daddr: %#08x\n",
1101 len
+= sprintf(buf
+len
, "version: %d.%d,\n",
1102 self
->version
[1], self
->version
[0]);
1103 len
+= sprintf(buf
+len
, "access type: %s\n",
1104 irlan_access
[self
->client
.access_type
]);
1105 len
+= sprintf(buf
+len
, "media: %s\n",
1106 irlan_media
[self
->media
]);
1108 len
+= sprintf(buf
+len
, "local filter:\n");
1109 len
+= sprintf(buf
+len
, "remote filter: ");
1110 len
+= irlan_print_filter(self
->client
.filter_type
,
1113 len
+= sprintf(buf
+len
, "tx busy: %s\n",
1114 netif_queue_stopped(&self
->dev
) ? "TRUE" : "FALSE");
1116 len
+= sprintf(buf
+len
, "\n");
1118 self
= (struct irlan_cb
*) hashbin_get_next(irlan
);
1120 restore_flags(flags
);
1127 * Function print_ret_code (code)
1129 * Print return code of request to peer IrLAN layer.
1132 void print_ret_code(__u8 code
)
1136 printk(KERN_INFO
"Success\n");
1139 WARNING("IrLAN: Insufficient resources\n");
1142 WARNING("IrLAN: Invalid command format\n");
1145 WARNING("IrLAN: Command not supported\n");
1148 WARNING("IrLAN: Parameter not supported\n");
1151 WARNING("IrLAN: Value not supported\n");
1154 WARNING("IrLAN: Not open\n");
1157 WARNING("IrLAN: Authentication required\n");
1160 WARNING("IrLAN: Invalid password\n");
1163 WARNING("IrLAN: Protocol error\n");
1166 WARNING("IrLAN: Asynchronous status\n");
1171 void irlan_mod_inc_use_count(void)
1178 void irlan_mod_dec_use_count(void)
1187 MODULE_AUTHOR("Dag Brattli <dagb@cs.uit.no>");
1188 MODULE_DESCRIPTION("The Linux IrDA LAN protocol");
1190 MODULE_PARM(eth
, "i");
1191 MODULE_PARM_DESC(eth
, "Name devices ethX (0) or irlanX (1)");
1192 MODULE_PARM(access
, "i");
1193 MODULE_PARM_DESC(access
, "Access type DIRECT=1, PEER=2, HOSTED=3");
1196 * Function init_module (void)
1198 * Initialize the IrLAN module, this function is called by the
1199 * modprobe(1) program.
1201 int init_module(void)
1203 return irlan_init();
1207 * Function cleanup_module (void)
1209 * Remove the IrLAN module, this function is called by the rmmod(1)
1212 void cleanup_module(void)
1214 /* Free some memory */