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/module.h>
28 #include <linux/kernel.h>
29 #include <linux/string.h>
30 #include <linux/gfp.h>
31 #include <linux/init.h>
32 #include <linux/errno.h>
33 #include <linux/proc_fs.h>
34 #include <linux/sched.h>
35 #include <linux/seq_file.h>
36 #include <linux/random.h>
37 #include <linux/netdevice.h>
38 #include <linux/etherdevice.h>
39 #include <linux/rtnetlink.h>
40 #include <linux/moduleparam.h>
41 #include <linux/bitops.h>
43 #include <asm/byteorder.h>
45 #include <net/irda/irda.h>
46 #include <net/irda/irttp.h>
47 #include <net/irda/irlmp.h>
48 #include <net/irda/iriap.h>
49 #include <net/irda/timer.h>
51 #include <net/irda/irlan_common.h>
52 #include <net/irda/irlan_client.h>
53 #include <net/irda/irlan_provider.h>
54 #include <net/irda/irlan_eth.h>
55 #include <net/irda/irlan_filter.h>
58 /* extern char sysctl_devname[]; */
63 static LIST_HEAD(irlans
);
68 /* Module parameters */
69 static bool eth
; /* Use "eth" or "irlan" name for devices */
70 static int access
= ACCESS_PEER
; /* PEER, DIRECT or HOSTED */
73 static const char *const irlan_access
[] = {
80 static const char *const irlan_media
[] = {
86 extern struct proc_dir_entry
*proc_irda
;
88 static int irlan_seq_open(struct inode
*inode
, struct file
*file
);
90 static const struct file_operations irlan_fops
= {
92 .open
= irlan_seq_open
,
95 .release
= seq_release
,
98 extern struct proc_dir_entry
*proc_irda
;
99 #endif /* CONFIG_PROC_FS */
101 static struct irlan_cb __init
*irlan_open(__u32 saddr
, __u32 daddr
);
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 static void irlan_open_unicast_addr(struct irlan_cb
*self
);
107 static void irlan_get_unicast_addr(struct irlan_cb
*self
);
108 void irlan_close_tsaps(struct irlan_cb
*self
);
111 * Function irlan_init (void)
113 * Initialize IrLAN layer
116 static int __init
irlan_init(void)
118 struct irlan_cb
*new;
121 #ifdef CONFIG_PROC_FS
122 { struct proc_dir_entry
*proc
;
123 proc
= proc_create("irlan", 0, proc_irda
, &irlan_fops
);
125 printk(KERN_ERR
"irlan_init: can't create /proc entry!\n");
129 #endif /* CONFIG_PROC_FS */
131 hints
= irlmp_service_to_hint(S_LAN
);
133 /* Register with IrLMP as a client */
134 ckey
= irlmp_register_client(hints
, &irlan_client_discovery_indication
,
139 /* Register with IrLMP as a service */
140 skey
= irlmp_register_service(hints
);
144 /* Start the master IrLAN instance (the only one for now) */
145 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 irlmp_unregister_service(skey
);
160 irlmp_unregister_client(ckey
);
162 #ifdef CONFIG_PROC_FS
163 remove_proc_entry("irlan", proc_irda
);
164 #endif /* CONFIG_PROC_FS */
169 static void __exit
irlan_cleanup(void)
171 struct irlan_cb
*self
, *next
;
173 irlmp_unregister_client(ckey
);
174 irlmp_unregister_service(skey
);
176 #ifdef CONFIG_PROC_FS
177 remove_proc_entry("irlan", proc_irda
);
178 #endif /* CONFIG_PROC_FS */
180 /* Cleanup any leftover network devices */
182 list_for_each_entry_safe(self
, next
, &irlans
, dev_list
) {
189 * Function irlan_open (void)
191 * Open new instance of a client/provider, we should only register the
192 * network device if this instance is ment for a particular client/provider
194 static struct irlan_cb __init
*irlan_open(__u32 saddr
, __u32 daddr
)
196 struct net_device
*dev
;
197 struct irlan_cb
*self
;
199 /* Create network device with irlan */
200 dev
= alloc_irlandev(eth
? "eth%d" : "irlan%d");
204 self
= netdev_priv(dev
);
208 * Initialize local device structure
210 self
->magic
= IRLAN_MAGIC
;
214 /* Provider access can only be PEER, DIRECT, or HOSTED */
215 self
->provider
.access_type
= access
;
216 if (access
== ACCESS_DIRECT
) {
218 * Since we are emulating an IrLAN sever we will have to
219 * give ourself an ethernet address!
221 dev
->dev_addr
[0] = 0x40;
222 dev
->dev_addr
[1] = 0x00;
223 dev
->dev_addr
[2] = 0x00;
224 dev
->dev_addr
[3] = 0x00;
225 get_random_bytes(dev
->dev_addr
+4, 1);
226 get_random_bytes(dev
->dev_addr
+5, 1);
229 self
->media
= MEDIA_802_3
;
230 self
->disconnect_reason
= LM_USER_REQUEST
;
231 init_timer(&self
->watchdog_timer
);
232 init_timer(&self
->client
.kick_timer
);
233 init_waitqueue_head(&self
->open_wait
);
235 skb_queue_head_init(&self
->client
.txq
);
237 irlan_next_client_state(self
, IRLAN_IDLE
);
238 irlan_next_provider_state(self
, IRLAN_IDLE
);
240 if (register_netdev(dev
)) {
241 pr_debug("%s(), register_netdev() failed!\n",
247 list_add_rcu(&self
->dev_list
, &irlans
);
254 * Function __irlan_close (self)
256 * This function closes and deallocates the IrLAN client instances. Be
257 * aware that other functions which calls client_close() must
258 * remove self from irlans list first.
260 static void __irlan_close(struct irlan_cb
*self
)
263 IRDA_ASSERT(self
!= NULL
, return;);
264 IRDA_ASSERT(self
->magic
== IRLAN_MAGIC
, return;);
266 del_timer_sync(&self
->watchdog_timer
);
267 del_timer_sync(&self
->client
.kick_timer
);
269 /* Close all open connections and remove TSAPs */
270 irlan_close_tsaps(self
);
272 if (self
->client
.iriap
)
273 iriap_close(self
->client
.iriap
);
275 /* Remove frames queued on the control channel */
276 skb_queue_purge(&self
->client
.txq
);
278 /* Unregister and free self via destructor */
279 unregister_netdevice(self
->dev
);
282 /* Find any instance of irlan, used for client discovery wakeup */
283 struct irlan_cb
*irlan_get_any(void)
285 struct irlan_cb
*self
;
287 list_for_each_entry_rcu(self
, &irlans
, dev_list
) {
294 * Function irlan_connect_indication (instance, sap, qos, max_sdu_size, skb)
296 * Here we receive the connect indication for the data channel
299 static void irlan_connect_indication(void *instance
, void *sap
,
300 struct qos_info
*qos
,
302 __u8 max_header_size
,
305 struct irlan_cb
*self
;
306 struct tsap_cb
*tsap
;
311 IRDA_ASSERT(self
!= NULL
, return;);
312 IRDA_ASSERT(self
->magic
== IRLAN_MAGIC
, return;);
313 IRDA_ASSERT(tsap
== self
->tsap_data
,return;);
315 self
->max_sdu_size
= max_sdu_size
;
316 self
->max_header_size
= max_header_size
;
318 pr_debug("%s: We are now connected!\n", __func__
);
320 del_timer(&self
->watchdog_timer
);
322 /* If you want to pass the skb to *both* state machines, you will
323 * need to skb_clone() it, so that you don't free it twice.
324 * As the state machines don't need it, git rid of it here...
329 irlan_do_provider_event(self
, IRLAN_DATA_CONNECT_INDICATION
, NULL
);
330 irlan_do_client_event(self
, IRLAN_DATA_CONNECT_INDICATION
, NULL
);
332 if (self
->provider
.access_type
== ACCESS_PEER
) {
334 * Data channel is open, so we are now allowed to
335 * configure the remote filter
337 irlan_get_unicast_addr(self
);
338 irlan_open_unicast_addr(self
);
340 /* Ready to transfer Ethernet frames (at last) */
341 netif_start_queue(self
->dev
); /* Clear reason */
344 static void irlan_connect_confirm(void *instance
, void *sap
,
345 struct qos_info
*qos
,
347 __u8 max_header_size
,
350 struct irlan_cb
*self
;
354 IRDA_ASSERT(self
!= NULL
, return;);
355 IRDA_ASSERT(self
->magic
== IRLAN_MAGIC
, return;);
357 self
->max_sdu_size
= max_sdu_size
;
358 self
->max_header_size
= max_header_size
;
360 /* TODO: we could set the MTU depending on the max_sdu_size */
362 pr_debug("%s: We are now connected!\n", __func__
);
363 del_timer(&self
->watchdog_timer
);
366 * Data channel is open, so we are now allowed to configure the remote
369 irlan_get_unicast_addr(self
);
370 irlan_open_unicast_addr(self
);
372 /* Open broadcast and multicast filter by default */
373 irlan_set_broadcast_filter(self
, TRUE
);
374 irlan_set_multicast_filter(self
, TRUE
);
376 /* Ready to transfer Ethernet frames */
377 netif_start_queue(self
->dev
);
378 self
->disconnect_reason
= 0; /* Clear reason */
379 wake_up_interruptible(&self
->open_wait
);
383 * Function irlan_client_disconnect_indication (handle)
385 * Callback function for the IrTTP layer. Indicates a disconnection of
386 * the specified connection (handle)
388 static void irlan_disconnect_indication(void *instance
,
389 void *sap
, LM_REASON reason
,
390 struct sk_buff
*userdata
)
392 struct irlan_cb
*self
;
393 struct tsap_cb
*tsap
;
395 pr_debug("%s(), reason=%d\n", __func__
, reason
);
400 IRDA_ASSERT(self
!= NULL
, return;);
401 IRDA_ASSERT(self
->magic
== IRLAN_MAGIC
, return;);
402 IRDA_ASSERT(tsap
!= NULL
, return;);
403 IRDA_ASSERT(tsap
->magic
== TTP_TSAP_MAGIC
, return;);
405 IRDA_ASSERT(tsap
== self
->tsap_data
, return;);
407 pr_debug("IrLAN, data channel disconnected by peer!\n");
409 /* Save reason so we know if we should try to reconnect or not */
410 self
->disconnect_reason
= reason
;
413 case LM_USER_REQUEST
: /* User request */
414 pr_debug("%s(), User requested\n", __func__
);
416 case LM_LAP_DISCONNECT
: /* Unexpected IrLAP disconnect */
417 pr_debug("%s(), Unexpected IrLAP disconnect\n", __func__
);
419 case LM_CONNECT_FAILURE
: /* Failed to establish IrLAP connection */
420 pr_debug("%s(), IrLAP connect failed\n", __func__
);
422 case LM_LAP_RESET
: /* IrLAP reset */
423 pr_debug("%s(), IrLAP reset\n", __func__
);
425 case LM_INIT_DISCONNECT
:
426 pr_debug("%s(), IrLMP connect failed\n", __func__
);
429 net_err_ratelimited("%s(), Unknown disconnect reason\n",
434 /* If you want to pass the skb to *both* state machines, you will
435 * need to skb_clone() it, so that you don't free it twice.
436 * As the state machines don't need it, git rid of it here...
439 dev_kfree_skb(userdata
);
441 irlan_do_client_event(self
, IRLAN_LMP_DISCONNECT
, NULL
);
442 irlan_do_provider_event(self
, IRLAN_LMP_DISCONNECT
, NULL
);
444 wake_up_interruptible(&self
->open_wait
);
447 void irlan_open_data_tsap(struct irlan_cb
*self
)
449 struct tsap_cb
*tsap
;
452 IRDA_ASSERT(self
!= NULL
, return;);
453 IRDA_ASSERT(self
->magic
== IRLAN_MAGIC
, return;);
455 /* Check if already open */
459 irda_notify_init(¬ify
);
461 notify
.data_indication
= irlan_eth_receive
;
462 notify
.udata_indication
= irlan_eth_receive
;
463 notify
.connect_indication
= irlan_connect_indication
;
464 notify
.connect_confirm
= irlan_connect_confirm
;
465 notify
.flow_indication
= irlan_eth_flow_indication
;
466 notify
.disconnect_indication
= irlan_disconnect_indication
;
467 notify
.instance
= self
;
468 strlcpy(notify
.name
, "IrLAN data", sizeof(notify
.name
));
470 tsap
= irttp_open_tsap(LSAP_ANY
, DEFAULT_INITIAL_CREDIT
, ¬ify
);
472 pr_debug("%s(), Got no tsap!\n", __func__
);
475 self
->tsap_data
= tsap
;
478 * This is the data TSAP selector which we will pass to the client
479 * when the client ask for it.
481 self
->stsap_sel_data
= self
->tsap_data
->stsap_sel
;
484 void irlan_close_tsaps(struct irlan_cb
*self
)
486 IRDA_ASSERT(self
!= NULL
, return;);
487 IRDA_ASSERT(self
->magic
== IRLAN_MAGIC
, return;);
489 /* Disconnect and close all open TSAP connections */
490 if (self
->tsap_data
) {
491 irttp_disconnect_request(self
->tsap_data
, NULL
, P_NORMAL
);
492 irttp_close_tsap(self
->tsap_data
);
493 self
->tsap_data
= NULL
;
495 if (self
->client
.tsap_ctrl
) {
496 irttp_disconnect_request(self
->client
.tsap_ctrl
, NULL
,
498 irttp_close_tsap(self
->client
.tsap_ctrl
);
499 self
->client
.tsap_ctrl
= NULL
;
501 if (self
->provider
.tsap_ctrl
) {
502 irttp_disconnect_request(self
->provider
.tsap_ctrl
, NULL
,
504 irttp_close_tsap(self
->provider
.tsap_ctrl
);
505 self
->provider
.tsap_ctrl
= NULL
;
507 self
->disconnect_reason
= LM_USER_REQUEST
;
511 * Function irlan_ias_register (self, tsap_sel)
513 * Register with LM-IAS
516 void irlan_ias_register(struct irlan_cb
*self
, __u8 tsap_sel
)
518 struct ias_object
*obj
;
519 struct ias_value
*new_value
;
521 IRDA_ASSERT(self
!= NULL
, return;);
522 IRDA_ASSERT(self
->magic
== IRLAN_MAGIC
, return;);
525 * Check if object has already been registered by a previous provider.
526 * If that is the case, we just change the value of the attribute
528 if (!irias_find_object("IrLAN")) {
529 obj
= irias_new_object("IrLAN", IAS_IRLAN_ID
);
530 irias_add_integer_attrib(obj
, "IrDA:TinyTP:LsapSel", tsap_sel
,
532 irias_insert_object(obj
);
534 new_value
= irias_new_integer_value(tsap_sel
);
535 irias_object_change_attribute("IrLAN", "IrDA:TinyTP:LsapSel",
539 /* Register PnP object only if not registered before */
540 if (!irias_find_object("PnP")) {
541 obj
= irias_new_object("PnP", IAS_PNP_ID
);
543 irias_add_string_attrib(obj
, "Name", sysctl_devname
,
546 irias_add_string_attrib(obj
, "Name", "Linux", IAS_KERNEL_ATTR
);
548 irias_add_string_attrib(obj
, "DeviceID", "HWP19F0",
550 irias_add_integer_attrib(obj
, "CompCnt", 1, IAS_KERNEL_ATTR
);
551 if (self
->provider
.access_type
== ACCESS_PEER
)
552 irias_add_string_attrib(obj
, "Comp#01", "PNP8389",
555 irias_add_string_attrib(obj
, "Comp#01", "PNP8294",
558 irias_add_string_attrib(obj
, "Manufacturer",
559 "Linux-IrDA Project", IAS_KERNEL_ATTR
);
560 irias_insert_object(obj
);
565 * Function irlan_run_ctrl_tx_queue (self)
567 * Try to send the next command in the control transmit queue
570 int irlan_run_ctrl_tx_queue(struct irlan_cb
*self
)
574 if (irda_lock(&self
->client
.tx_busy
) == FALSE
)
577 skb
= skb_dequeue(&self
->client
.txq
);
579 self
->client
.tx_busy
= FALSE
;
583 /* Check that it's really possible to send commands */
584 if ((self
->client
.tsap_ctrl
== NULL
) ||
585 (self
->client
.state
== IRLAN_IDLE
))
587 self
->client
.tx_busy
= FALSE
;
591 pr_debug("%s(), sending ...\n", __func__
);
593 return irttp_data_request(self
->client
.tsap_ctrl
, skb
);
597 * Function irlan_ctrl_data_request (self, skb)
599 * This function makes sure that commands on the control channel is being
600 * sent in a command/response fashion
602 static void irlan_ctrl_data_request(struct irlan_cb
*self
, struct sk_buff
*skb
)
605 skb_queue_tail(&self
->client
.txq
, skb
);
607 /* Try to send command */
608 irlan_run_ctrl_tx_queue(self
);
612 * Function irlan_get_provider_info (self)
614 * Send Get Provider Information command to peer IrLAN layer
617 void irlan_get_provider_info(struct irlan_cb
*self
)
622 IRDA_ASSERT(self
!= NULL
, return;);
623 IRDA_ASSERT(self
->magic
== IRLAN_MAGIC
, return;);
625 skb
= alloc_skb(IRLAN_MAX_HEADER
+ IRLAN_CMD_HEADER
,
630 /* Reserve space for TTP, LMP, and LAP header */
631 skb_reserve(skb
, self
->client
.max_header_size
);
636 frame
[0] = CMD_GET_PROVIDER_INFO
;
637 frame
[1] = 0x00; /* Zero parameters */
639 irlan_ctrl_data_request(self
, skb
);
643 * Function irlan_open_data_channel (self)
645 * Send an Open Data Command to provider
648 void irlan_open_data_channel(struct irlan_cb
*self
)
653 IRDA_ASSERT(self
!= NULL
, return;);
654 IRDA_ASSERT(self
->magic
== IRLAN_MAGIC
, return;);
656 skb
= alloc_skb(IRLAN_MAX_HEADER
+ IRLAN_CMD_HEADER
+
657 IRLAN_STRING_PARAMETER_LEN("MEDIA", "802.3") +
658 IRLAN_STRING_PARAMETER_LEN("ACCESS_TYPE", "DIRECT"),
663 skb_reserve(skb
, self
->client
.max_header_size
);
669 frame
[0] = CMD_OPEN_DATA_CHANNEL
;
670 frame
[1] = 0x02; /* Two parameters */
672 irlan_insert_string_param(skb
, "MEDIA", "802.3");
673 irlan_insert_string_param(skb
, "ACCESS_TYPE", "DIRECT");
674 /* irlan_insert_string_param(skb, "MODE", "UNRELIABLE"); */
676 /* self->use_udata = TRUE; */
678 irlan_ctrl_data_request(self
, skb
);
681 void irlan_close_data_channel(struct irlan_cb
*self
)
686 IRDA_ASSERT(self
!= NULL
, return;);
687 IRDA_ASSERT(self
->magic
== IRLAN_MAGIC
, return;);
689 /* Check if the TSAP is still there */
690 if (self
->client
.tsap_ctrl
== NULL
)
693 skb
= alloc_skb(IRLAN_MAX_HEADER
+ IRLAN_CMD_HEADER
+
694 IRLAN_BYTE_PARAMETER_LEN("DATA_CHAN"),
699 skb_reserve(skb
, self
->client
.max_header_size
);
705 frame
[0] = CMD_CLOSE_DATA_CHAN
;
706 frame
[1] = 0x01; /* One parameter */
708 irlan_insert_byte_param(skb
, "DATA_CHAN", self
->dtsap_sel_data
);
710 irlan_ctrl_data_request(self
, skb
);
714 * Function irlan_open_unicast_addr (self)
716 * Make IrLAN provider accept ethernet frames addressed to the unicast
720 static void irlan_open_unicast_addr(struct irlan_cb
*self
)
725 IRDA_ASSERT(self
!= NULL
, return;);
726 IRDA_ASSERT(self
->magic
== IRLAN_MAGIC
, return;);
728 skb
= alloc_skb(IRLAN_MAX_HEADER
+ IRLAN_CMD_HEADER
+
729 IRLAN_BYTE_PARAMETER_LEN("DATA_CHAN") +
730 IRLAN_STRING_PARAMETER_LEN("FILTER_TYPE", "DIRECTED") +
731 IRLAN_STRING_PARAMETER_LEN("FILTER_MODE", "FILTER"),
736 /* Reserve space for TTP, LMP, and LAP header */
737 skb_reserve(skb
, self
->max_header_size
);
742 frame
[0] = CMD_FILTER_OPERATION
;
743 frame
[1] = 0x03; /* Three parameters */
744 irlan_insert_byte_param(skb
, "DATA_CHAN" , self
->dtsap_sel_data
);
745 irlan_insert_string_param(skb
, "FILTER_TYPE", "DIRECTED");
746 irlan_insert_string_param(skb
, "FILTER_MODE", "FILTER");
748 irlan_ctrl_data_request(self
, skb
);
752 * Function irlan_set_broadcast_filter (self, status)
754 * Make IrLAN provider accept ethernet frames addressed to the broadcast
755 * address. Be careful with the use of this one, since there may be a lot
756 * of broadcast traffic out there. We can still function without this
757 * one but then _we_ have to initiate all communication with other
758 * hosts, since ARP request for this host will not be answered.
760 void irlan_set_broadcast_filter(struct irlan_cb
*self
, int status
)
765 IRDA_ASSERT(self
!= NULL
, return;);
766 IRDA_ASSERT(self
->magic
== IRLAN_MAGIC
, return;);
768 skb
= alloc_skb(IRLAN_MAX_HEADER
+ IRLAN_CMD_HEADER
+
769 IRLAN_BYTE_PARAMETER_LEN("DATA_CHAN") +
770 IRLAN_STRING_PARAMETER_LEN("FILTER_TYPE", "BROADCAST") +
771 /* We may waste one byte here...*/
772 IRLAN_STRING_PARAMETER_LEN("FILTER_MODE", "FILTER"),
777 /* Reserve space for TTP, LMP, and LAP header */
778 skb_reserve(skb
, self
->client
.max_header_size
);
783 frame
[0] = CMD_FILTER_OPERATION
;
784 frame
[1] = 0x03; /* Three parameters */
785 irlan_insert_byte_param(skb
, "DATA_CHAN", self
->dtsap_sel_data
);
786 irlan_insert_string_param(skb
, "FILTER_TYPE", "BROADCAST");
788 irlan_insert_string_param(skb
, "FILTER_MODE", "FILTER");
790 irlan_insert_string_param(skb
, "FILTER_MODE", "NONE");
792 irlan_ctrl_data_request(self
, skb
);
796 * Function irlan_set_multicast_filter (self, status)
798 * Make IrLAN provider accept ethernet frames addressed to the multicast
802 void irlan_set_multicast_filter(struct irlan_cb
*self
, int status
)
807 IRDA_ASSERT(self
!= NULL
, return;);
808 IRDA_ASSERT(self
->magic
== IRLAN_MAGIC
, return;);
810 skb
= alloc_skb(IRLAN_MAX_HEADER
+ IRLAN_CMD_HEADER
+
811 IRLAN_BYTE_PARAMETER_LEN("DATA_CHAN") +
812 IRLAN_STRING_PARAMETER_LEN("FILTER_TYPE", "MULTICAST") +
813 /* We may waste one byte here...*/
814 IRLAN_STRING_PARAMETER_LEN("FILTER_MODE", "NONE"),
819 /* Reserve space for TTP, LMP, and LAP header */
820 skb_reserve(skb
, self
->client
.max_header_size
);
825 frame
[0] = CMD_FILTER_OPERATION
;
826 frame
[1] = 0x03; /* Three parameters */
827 irlan_insert_byte_param(skb
, "DATA_CHAN", self
->dtsap_sel_data
);
828 irlan_insert_string_param(skb
, "FILTER_TYPE", "MULTICAST");
830 irlan_insert_string_param(skb
, "FILTER_MODE", "ALL");
832 irlan_insert_string_param(skb
, "FILTER_MODE", "NONE");
834 irlan_ctrl_data_request(self
, skb
);
838 * Function irlan_get_unicast_addr (self)
840 * Retrieves the unicast address from the IrLAN provider. This address
841 * will be inserted into the devices structure, so the ethernet layer
842 * can construct its packets.
845 static void irlan_get_unicast_addr(struct irlan_cb
*self
)
850 IRDA_ASSERT(self
!= NULL
, return;);
851 IRDA_ASSERT(self
->magic
== IRLAN_MAGIC
, return;);
853 skb
= alloc_skb(IRLAN_MAX_HEADER
+ IRLAN_CMD_HEADER
+
854 IRLAN_BYTE_PARAMETER_LEN("DATA_CHAN") +
855 IRLAN_STRING_PARAMETER_LEN("FILTER_TYPE", "DIRECTED") +
856 IRLAN_STRING_PARAMETER_LEN("FILTER_OPERATION",
862 /* Reserve space for TTP, LMP, and LAP header */
863 skb_reserve(skb
, self
->client
.max_header_size
);
868 frame
[0] = CMD_FILTER_OPERATION
;
869 frame
[1] = 0x03; /* Three parameters */
870 irlan_insert_byte_param(skb
, "DATA_CHAN", self
->dtsap_sel_data
);
871 irlan_insert_string_param(skb
, "FILTER_TYPE", "DIRECTED");
872 irlan_insert_string_param(skb
, "FILTER_OPERATION", "DYNAMIC");
874 irlan_ctrl_data_request(self
, skb
);
878 * Function irlan_get_media_char (self)
883 void irlan_get_media_char(struct irlan_cb
*self
)
888 IRDA_ASSERT(self
!= NULL
, return;);
889 IRDA_ASSERT(self
->magic
== IRLAN_MAGIC
, return;);
891 skb
= alloc_skb(IRLAN_MAX_HEADER
+ IRLAN_CMD_HEADER
+
892 IRLAN_STRING_PARAMETER_LEN("MEDIA", "802.3"),
898 /* Reserve space for TTP, LMP, and LAP header */
899 skb_reserve(skb
, self
->client
.max_header_size
);
905 frame
[0] = CMD_GET_MEDIA_CHAR
;
906 frame
[1] = 0x01; /* One parameter */
908 irlan_insert_string_param(skb
, "MEDIA", "802.3");
909 irlan_ctrl_data_request(self
, skb
);
913 * Function insert_byte_param (skb, param, value)
915 * Insert byte parameter into frame
918 int irlan_insert_byte_param(struct sk_buff
*skb
, char *param
, __u8 value
)
920 return __irlan_insert_param(skb
, param
, IRLAN_BYTE
, value
, 0, NULL
, 0);
923 int irlan_insert_short_param(struct sk_buff
*skb
, char *param
, __u16 value
)
925 return __irlan_insert_param(skb
, param
, IRLAN_SHORT
, 0, value
, NULL
, 0);
929 * Function insert_string (skb, param, value)
931 * Insert string parameter into frame
934 int irlan_insert_string_param(struct sk_buff
*skb
, char *param
, char *string
)
936 int string_len
= strlen(string
);
938 return __irlan_insert_param(skb
, param
, IRLAN_ARRAY
, 0, 0, string
,
943 * Function insert_array_param(skb, param, value, len_value)
945 * Insert array parameter into frame
948 int irlan_insert_array_param(struct sk_buff
*skb
, char *name
, __u8
*array
,
951 return __irlan_insert_param(skb
, name
, IRLAN_ARRAY
, 0, 0, array
,
956 * Function insert_param (skb, param, value, byte)
958 * Insert parameter at end of buffer, structure of a parameter is:
960 * -----------------------------------------------------------------------
961 * | Name Length[1] | Param Name[1..255] | Val Length[2] | Value[0..1016]|
962 * -----------------------------------------------------------------------
964 static int __irlan_insert_param(struct sk_buff
*skb
, char *param
, int type
,
965 __u8 value_byte
, __u16 value_short
,
966 __u8
*value_array
, __u16 value_len
)
970 __le16 tmp_le
; /* Temporary value in little endian format */
974 pr_debug("%s(), Got NULL skb\n", __func__
);
978 param_len
= strlen(param
);
987 IRDA_ASSERT(value_array
!= NULL
, return 0;);
988 IRDA_ASSERT(value_len
> 0, return 0;);
991 pr_debug("%s(), Unknown parameter type!\n", __func__
);
995 /* Insert at end of sk-buffer */
996 frame
= skb_tail_pointer(skb
);
998 /* Make space for data */
999 if (skb_tailroom(skb
) < (param_len
+value_len
+3)) {
1000 pr_debug("%s(), No more space at end of skb\n", __func__
);
1003 skb_put(skb
, param_len
+value_len
+3);
1005 /* Insert parameter length */
1006 frame
[n
++] = param_len
;
1008 /* Insert parameter */
1009 memcpy(frame
+n
, param
, param_len
); n
+= param_len
;
1011 /* Insert value length (2 byte little endian format, LSB first) */
1012 tmp_le
= cpu_to_le16(value_len
);
1013 memcpy(frame
+n
, &tmp_le
, 2); n
+= 2; /* To avoid alignment problems */
1018 frame
[n
++] = value_byte
;
1021 tmp_le
= cpu_to_le16(value_short
);
1022 memcpy(frame
+n
, &tmp_le
, 2); n
+= 2;
1025 memcpy(frame
+n
, value_array
, value_len
); n
+=value_len
;
1030 IRDA_ASSERT(n
== (param_len
+value_len
+3), return 0;);
1032 return param_len
+value_len
+3;
1036 * Function irlan_extract_param (buf, name, value, len)
1038 * Extracts a single parameter name/value pair from buffer and updates
1039 * the buffer pointer to point to the next name/value pair.
1041 int irlan_extract_param(__u8
*buf
, char *name
, char *value
, __u16
*len
)
1047 /* get length of parameter name (1 byte) */
1048 name_len
= buf
[n
++];
1050 if (name_len
> 254) {
1051 pr_debug("%s(), name_len > 254\n", __func__
);
1052 return -RSP_INVALID_COMMAND_FORMAT
;
1055 /* get parameter name */
1056 memcpy(name
, buf
+n
, name_len
);
1057 name
[name_len
] = '\0';
1061 * Get length of parameter value (2 bytes in little endian
1064 memcpy(&val_len
, buf
+n
, 2); /* To avoid alignment problems */
1065 le16_to_cpus(&val_len
); n
+=2;
1067 if (val_len
>= 1016) {
1068 pr_debug("%s(), parameter length to long\n", __func__
);
1069 return -RSP_INVALID_COMMAND_FORMAT
;
1073 /* get parameter value */
1074 memcpy(value
, buf
+n
, val_len
);
1075 value
[val_len
] = '\0';
1078 pr_debug("Parameter: %s ", name
);
1079 pr_debug("Value: %s\n", value
);
1084 #ifdef CONFIG_PROC_FS
1087 * Start of reading /proc entries.
1088 * Return entry at pos,
1089 * or start_token to indicate print header line
1090 * or NULL if end of file
1092 static void *irlan_seq_start(struct seq_file
*seq
, loff_t
*pos
)
1095 return seq_list_start_head(&irlans
, *pos
);
1098 /* Return entry after v, and increment pos */
1099 static void *irlan_seq_next(struct seq_file
*seq
, void *v
, loff_t
*pos
)
1101 return seq_list_next(v
, &irlans
, pos
);
1104 /* End of reading /proc file */
1105 static void irlan_seq_stop(struct seq_file
*seq
, void *v
)
1112 * Show one entry in /proc file.
1114 static int irlan_seq_show(struct seq_file
*seq
, void *v
)
1117 seq_puts(seq
, "IrLAN instances:\n");
1119 struct irlan_cb
*self
= list_entry(v
, struct irlan_cb
, dev_list
);
1121 IRDA_ASSERT(self
!= NULL
, return -1;);
1122 IRDA_ASSERT(self
->magic
== IRLAN_MAGIC
, return -1;);
1124 seq_printf(seq
,"ifname: %s,\n",
1126 seq_printf(seq
,"client state: %s, ",
1127 irlan_state
[ self
->client
.state
]);
1128 seq_printf(seq
,"provider state: %s,\n",
1129 irlan_state
[ self
->provider
.state
]);
1130 seq_printf(seq
,"saddr: %#08x, ",
1132 seq_printf(seq
,"daddr: %#08x\n",
1134 seq_printf(seq
,"version: %d.%d,\n",
1135 self
->version
[1], self
->version
[0]);
1136 seq_printf(seq
,"access type: %s\n",
1137 irlan_access
[self
->client
.access_type
]);
1138 seq_printf(seq
,"media: %s\n",
1139 irlan_media
[self
->media
]);
1141 seq_printf(seq
,"local filter:\n");
1142 seq_printf(seq
,"remote filter: ");
1143 irlan_print_filter(seq
, self
->client
.filter_type
);
1144 seq_printf(seq
,"tx busy: %s\n",
1145 netif_queue_stopped(self
->dev
) ? "TRUE" : "FALSE");
1152 static const struct seq_operations irlan_seq_ops
= {
1153 .start
= irlan_seq_start
,
1154 .next
= irlan_seq_next
,
1155 .stop
= irlan_seq_stop
,
1156 .show
= irlan_seq_show
,
1159 static int irlan_seq_open(struct inode
*inode
, struct file
*file
)
1161 return seq_open(file
, &irlan_seq_ops
);
1165 MODULE_AUTHOR("Dag Brattli <dagb@cs.uit.no>");
1166 MODULE_DESCRIPTION("The Linux IrDA LAN protocol");
1167 MODULE_LICENSE("GPL");
1169 module_param(eth
, bool, 0);
1170 MODULE_PARM_DESC(eth
, "Name devices ethX (0) or irlanX (1)");
1171 module_param(access
, int, 0);
1172 MODULE_PARM_DESC(access
, "Access type DIRECT=1, PEER=2, HOSTED=3");
1174 module_init(irlan_init
);
1175 module_exit(irlan_cleanup
);