Import 2.3.18pre1
[davej-history.git] / net / irda / irda_device.c
blob1f4571a5d4ba6c342adeab1f11b8bbea8adc9c4e
1 /*********************************************************************
2 *
3 * Filename: irda_device.c
4 * Version: 0.5
5 * Description: Abstract device driver layer and helper functions
6 * Status: Experimental.
7 * Author: Dag Brattli <dagb@cs.uit.no>
8 * Created at: Wed Sep 2 20:22:08 1998
9 * Modified at: Tue Aug 24 14:31:13 1999
10 * Modified by: Dag Brattli <dagb@cs.uit.no>
11 * Modified at: Fri May 28 3:11 CST 1999
12 * Modified by: Horst von Brand <vonbrand@sleipnir.valparaiso.cl>
14 * Copyright (c) 1998-1999 Dag Brattli, All Rights Reserved.
16 * This program is free software; you can redistribute it and/or
17 * modify it under the terms of the GNU General Public License as
18 * published by the Free Software Foundation; either version 2 of
19 * the License, or (at your option) any later version.
21 * Neither Dag Brattli nor University of Tromsø admit liability nor
22 * provide warranty for any of this software. This material is
23 * provided "AS-IS" and at no charge.
25 ********************************************************************/
27 #include <linux/config.h>
28 #include <linux/string.h>
29 #include <linux/proc_fs.h>
30 #include <linux/skbuff.h>
31 #include <linux/if.h>
32 #include <linux/if_ether.h>
33 #include <linux/if_arp.h>
34 #include <linux/netdevice.h>
35 #include <linux/init.h>
36 #include <linux/tty.h>
37 #include <linux/kmod.h>
38 #include <linux/wireless.h>
39 #include <linux/spinlock.h>
41 #include <asm/ioctls.h>
42 #include <asm/segment.h>
43 #include <asm/uaccess.h>
44 #include <asm/dma.h>
46 #include <net/pkt_sched.h>
48 #include <net/irda/irda_device.h>
49 #include <net/irda/irlap_frame.h>
50 #include <net/irda/timer.h>
51 #include <net/irda/wrapper.h>
53 extern int irtty_init(void);
54 extern int pc87108_init(void);
55 extern int w83977af_init(void);
56 extern int esi_init(void);
57 extern int tekram_init(void);
58 extern int actisys_init(void);
59 extern int girbil_init(void);
61 static hashbin_t *irda_device = NULL;
62 static hashbin_t *dongles = NULL;
64 /* Netdevice functions */
65 static int irda_device_net_rebuild_header(struct sk_buff *skb);
66 static int irda_device_net_hard_header(struct sk_buff *skb,
67 struct net_device *dev,
68 unsigned short type, void *daddr,
69 void *saddr, unsigned len);
70 static int irda_device_net_set_config(struct net_device *dev, struct ifmap *map);
71 static int irda_device_net_change_mtu(struct net_device *dev, int new_mtu);
72 static int irda_device_net_ioctl(struct net_device *dev, struct ifreq *rq,int cmd);
73 #ifdef CONFIG_PROC_FS
74 int irda_device_proc_read( char *buf, char **start, off_t offset, int len,
75 int unused);
77 #endif /* CONFIG_PROC_FS */
79 int __init irda_device_init( void)
81 /* Allocate master array */
82 irda_device = hashbin_new( HB_LOCAL);
83 if (irda_device == NULL) {
84 WARNING("IrDA: Can't allocate irda_device hashbin!\n");
85 return -ENOMEM;
88 dongles = hashbin_new(HB_LOCAL);
89 if (dongles == NULL) {
90 printk(KERN_WARNING
91 "IrDA: Can't allocate dongles hashbin!\n");
92 return -ENOMEM;
95 /*
96 * Call the init function of the device drivers that has not been
97 * compiled as a module
99 #ifdef CONFIG_IRTTY_SIR
100 irtty_init();
101 #endif
102 #ifdef CONFIG_WINBOND_FIR
103 w83977af_init();
104 #endif
105 #ifdef CONFIG_NSC_FIR
106 pc87108_init();
107 #endif
108 #ifdef CONFIG_TOSHIBA_FIR
109 toshoboe_init();
110 #endif
111 #ifdef CONFIG_SMC_IRCC_FIR
112 ircc_init();
113 #endif
114 #ifdef CONFIG_ESI_DONGLE
115 esi_init();
116 #endif
117 #ifdef CONFIG_TEKRAM_DONGLE
118 tekram_init();
119 #endif
120 #ifdef CONFIG_ACTISYS_DONGLE
121 actisys_init();
122 #endif
123 #ifdef CONFIG_GIRBIL_DONGLE
124 girbil_init();
125 #endif
126 #ifdef CONFIG_LITELINK_DONGLE
127 litelink_init();
128 #endif
129 #ifdef CONFIG_AIRPORT_DONGLE
130 airport_init();
131 #endif
132 return 0;
135 void irda_device_cleanup(void)
137 DEBUG(4, __FUNCTION__ "()\n");
139 ASSERT(irda_device != NULL, return;);
141 hashbin_delete(dongles, NULL);
142 hashbin_delete(irda_device, (FREE_FUNC) irda_device_close);
146 * Function irda_device_open (self)
148 * Open a new IrDA port device
151 int irda_device_open(struct irda_device *self, char *name, void *priv)
153 int result;
154 int i=0;
156 /* Allocate memory if needed */
157 if (self->rx_buff.truesize > 0) {
158 self->rx_buff.head = ( __u8 *) kmalloc(self->rx_buff.truesize,
159 self->rx_buff.flags);
160 if (self->rx_buff.head == NULL)
161 return -ENOMEM;
163 memset(self->rx_buff.head, 0, self->rx_buff.truesize);
165 if (self->tx_buff.truesize > 0) {
166 self->tx_buff.head = ( __u8 *) kmalloc(self->tx_buff.truesize,
167 self->tx_buff.flags);
168 if (self->tx_buff.head == NULL) {
169 kfree(self->rx_buff.head);
170 return -ENOMEM;
173 memset(self->tx_buff.head, 0, self->tx_buff.truesize);
176 self->magic = IRDA_DEVICE_MAGIC;
178 self->rx_buff.in_frame = FALSE;
179 self->rx_buff.state = OUTSIDE_FRAME;
180 self->tx_buff.data = self->tx_buff.head;
181 self->rx_buff.data = self->rx_buff.head;
183 /* Initialize timers */
184 init_timer(&self->media_busy_timer);
186 self->lock = SPIN_LOCK_UNLOCKED;
188 /* A pointer to the low level implementation */
189 self->priv = priv;
191 /* Initialize IrDA net device */
192 do {
193 sprintf(self->name, "%s%d", "irda", i++);
194 } while (dev_get(self->name) != NULL);
196 self->netdev.name = self->name;
197 self->netdev.priv = (void *) self;
198 self->netdev.next = NULL;
200 if ((result = register_netdev(&self->netdev)) != 0) {
201 DEBUG(0, __FUNCTION__ "(), register_netdev() failed!\n");
202 return -1;
206 * Make the description for the device. self->netdev.name will get
207 * a name like "irda0" and the self->descriptin will get a name
208 * like "irda0 <-> irtty0"
210 strncpy(self->description, self->name, 5);
211 strcat(self->description, " <-> ");
212 strncat(self->description, name, 23);
214 hashbin_insert(irda_device, (QUEUE *) self, (int) self, NULL);
216 /* Open network device */
217 dev_open(&self->netdev);
219 MESSAGE("IrDA: Registered device %s\n", self->name);
221 irda_device_set_media_busy(self, FALSE);
223 return 0;
227 * Function irda_device_close (self)
229 * Close this instance of the irda_device, just deallocate buffers
232 void __irda_device_close(struct irda_device *self)
234 DEBUG(4, __FUNCTION__ "()\n");
236 ASSERT(self != NULL, return;);
237 ASSERT(self->magic == IRDA_DEVICE_MAGIC, return;);
239 /* We do this test to know if the device has been registered at all */
240 if (self->netdev.type == ARPHRD_IRDA) {
241 dev_close(&self->netdev);
243 /* Remove netdevice */
244 unregister_netdev(&self->netdev);
247 /* Stop timers */
248 del_timer(&self->media_busy_timer);
250 if (self->tx_buff.head)
251 kfree(self->tx_buff.head);
253 if (self->rx_buff.head)
254 kfree(self->rx_buff.head);
256 self->magic = 0;
260 * Function irda_device_close (self)
262 * Close the device
265 void irda_device_close(struct irda_device *self)
267 DEBUG(4, __FUNCTION__ "()\n");
269 ASSERT(self != NULL, return;);
270 ASSERT(self->magic == IRDA_DEVICE_MAGIC, return;);
272 /* We are not using any dongle anymore! */
273 if (self->dongle)
274 self->dongle->close(self);
276 hashbin_remove(irda_device, (int) self, NULL);
278 __irda_device_close(self);
282 * Function irda_device_set_media_busy (self, status)
284 * Called when we have detected that another station is transmiting
285 * in contention mode.
287 void irda_device_set_media_busy(struct irda_device *self, int status)
289 DEBUG(4, __FUNCTION__ "(%s)\n", status ? "TRUE" : "FALSE");
291 ASSERT(self != NULL, return;);
292 ASSERT(self->magic == IRDA_DEVICE_MAGIC, return;);
294 if (status) {
295 self->media_busy = TRUE;
296 irda_device_start_mbusy_timer(self);
297 DEBUG( 4, "Media busy!\n");
298 } else {
299 self->media_busy = FALSE;
300 del_timer(&self->media_busy_timer);
305 * Function __irda_device_change_speed (self, speed)
307 * When this function is called, we will have a process context so its
308 * possible for us to sleep, wait or whatever :-)
310 static void __irda_device_change_speed(struct irda_device *self, int speed)
312 int n = 0;
314 ASSERT(self != NULL, return;);
315 ASSERT(self->magic == IRDA_DEVICE_MAGIC, return;);
318 * Is is possible to change speed yet? Wait until the last byte
319 * has been transmitted.
321 if (!self->wait_until_sent) {
322 ERROR("IrDA: wait_until_sent() "
323 "has not implemented by the IrDA device driver!\n");
324 return;
327 /* Make sure all transmitted data has actually been sent */
328 self->wait_until_sent(self);
330 /* Make sure nobody tries to transmit during the speed change */
331 while (irda_lock((void *) &self->netdev.tbusy) == FALSE) {
332 WARNING(__FUNCTION__ "(), device locked!\n");
333 current->state = TASK_INTERRUPTIBLE;
334 schedule_timeout(MSECS_TO_JIFFIES(10));
336 if (n++ > 10) {
337 WARNING(__FUNCTION__ "(), breaking loop!\n");
338 return;
342 /* Change speed of dongle */
343 if (self->dongle)
344 self->dongle->change_speed(self, speed);
346 /* Change speed of IrDA port */
347 if (self->change_speed) {
348 self->change_speed(self, speed);
350 /* Update the QoS value only */
351 self->qos.baud_rate.value = speed;
353 self->netdev.tbusy = FALSE;
357 * Function irda_device_change_speed (self, speed)
359 * Change the speed of the currently used irda_device
362 inline void irda_device_change_speed(struct irda_device *self, int speed)
364 ASSERT(self != NULL, return;);
365 ASSERT(self->magic == IRDA_DEVICE_MAGIC, return;);
367 irda_execute_as_process(self,
368 (TODO_CALLBACK) __irda_device_change_speed,
369 speed);
372 inline int irda_device_is_media_busy( struct irda_device *self)
374 ASSERT(self != NULL, return FALSE;);
375 ASSERT(self->magic == IRDA_DEVICE_MAGIC, return FALSE;);
377 return self->media_busy;
380 inline int irda_device_is_receiving( struct irda_device *self)
382 ASSERT(self != NULL, return FALSE;);
383 ASSERT(self->magic == IRDA_DEVICE_MAGIC, return FALSE;);
385 if (self->is_receiving)
386 return self->is_receiving(self);
387 else
388 return FALSE;
391 inline struct qos_info *irda_device_get_qos(struct irda_device *self)
393 ASSERT(self != NULL, return NULL;);
394 ASSERT(self->magic == IRDA_DEVICE_MAGIC, return NULL;);
396 return &self->qos;
399 static struct enet_statistics *irda_device_get_stats( struct net_device *dev)
401 struct irda_device *priv = (struct irda_device *) dev->priv;
403 return &priv->stats;
407 * Function irda_device_setup (dev)
409 * This function should be used by low level device drivers in a similar way
410 * as ether_setup() is used by normal network device drivers
412 int irda_device_setup(struct net_device *dev)
414 struct irda_device *self;
416 ASSERT(dev != NULL, return -1;);
418 self = (struct irda_device *) dev->priv;
420 ASSERT(self != NULL, return -1;);
421 ASSERT(self->magic == IRDA_DEVICE_MAGIC, return -1;);
423 dev->get_stats = irda_device_get_stats;
424 dev->rebuild_header = irda_device_net_rebuild_header;
425 dev->set_config = irda_device_net_set_config;
426 dev->change_mtu = irda_device_net_change_mtu;
427 /* dev->hard_header = irda_device_net_hard_header; */
428 dev->do_ioctl = irda_device_net_ioctl;
429 dev->hard_header_len = 0;
430 dev->addr_len = 0;
432 dev->type = ARPHRD_IRDA;
433 dev->tx_queue_len = 8; /* Window size + 1 s-frame */
435 memset(dev->broadcast, 0xff, 4);
437 dev->mtu = 2048;
438 dev->tbusy = 1;
440 dev_init_buffers(dev);
442 dev->flags = IFF_NOARP;
444 return 0;
447 int irda_device_net_open(struct net_device *dev)
449 struct irda_device *self;
451 ASSERT(dev != NULL, return -1;);
453 self = dev->priv;
455 ASSERT(self != NULL, return 0;);
456 ASSERT(self->magic == IRDA_DEVICE_MAGIC, return -1;);
458 /* Ready to play! */
459 dev->tbusy = 0;
460 dev->interrupt = 0;
461 dev->start = 1;
464 * Open new IrLAP layer instance, now that everything should be
465 * initialized properly
467 self->irlap = irlap_open(self);
469 /* It's now safe to initilize the saddr */
470 memcpy(self->netdev.dev_addr, &self->irlap->saddr, 4);
472 return 0;
475 int irda_device_net_close(struct net_device *dev)
477 struct irda_device *self;
479 ASSERT(dev != NULL, return -1;);
481 self = dev->priv;
483 ASSERT(self != NULL, return 0;);
484 ASSERT(self->magic == IRDA_DEVICE_MAGIC, return -1;);
486 /* Stop device */
487 dev->tbusy = 1;
488 dev->start = 0;
490 /* Stop and remove instance of IrLAP */
491 if (self->irlap)
492 irlap_close(self->irlap);
493 self->irlap = NULL;
495 return 0;
499 * Function irda_device_net_rebuild_header (buff, dev, dst, skb)
504 static int irda_device_net_rebuild_header( struct sk_buff *skb)
506 DEBUG( 4, __FUNCTION__ "()\n");
508 return 0;
511 static int irda_device_net_hard_header(struct sk_buff *skb, struct net_device *dev,
512 unsigned short type, void *daddr,
513 void *saddr, unsigned len)
515 DEBUG( 0, __FUNCTION__ "()\n");
517 skb->mac.raw = skb->data;
518 /* skb_push(skb,PPP_HARD_HDR_LEN); */
519 /* return PPP_HARD_HDR_LEN; */
521 return 0;
524 static int irda_device_net_set_config( struct net_device *dev, struct ifmap *map)
526 DEBUG( 0, __FUNCTION__ "()\n");
528 return 0;
531 static int irda_device_net_change_mtu( struct net_device *dev, int new_mtu)
533 DEBUG( 0, __FUNCTION__ "()\n");
535 return 0;
539 #define SIOCSDONGLE SIOCDEVPRIVATE
540 static int irda_device_net_ioctl(struct net_device *dev, /* ioctl device */
541 struct ifreq *rq, /* Data passed */
542 int cmd) /* Ioctl number */
544 unsigned long flags;
545 int ret = 0;
546 #ifdef WIRELESS_EXT
547 struct iwreq *wrq = (struct iwreq *) rq;
548 #endif
549 struct irda_device *self;
551 DEBUG(4, __FUNCTION__ "()\n");
553 ASSERT(dev != NULL, return -1;);
555 self = (struct irda_device *) dev->priv;
557 ASSERT(self != NULL, return -1;);
558 ASSERT(self->magic == IRDA_DEVICE_MAGIC, return -1;);
560 DEBUG(0, "%s: ->irda_device_net_ioctl(cmd=0x%X)\n", dev->name, cmd);
562 /* Disable interrupts & save flags */
563 save_flags(flags);
564 cli();
566 /* Look what is the request */
567 switch (cmd) {
568 #ifdef WIRELESS_EXT
569 case SIOCGIWNAME:
570 /* Get name */
571 strcpy(wrq->u.name, self->name);
572 break;
573 case SIOCSIWNWID:
574 /* Set domain */
575 if (wrq->u.nwid.on) {
577 } break;
578 case SIOCGIWNWID:
579 /* Read domain*/
580 /* wrq->u.nwid.nwid = domain; */
581 /* wrq->u.nwid.on = 1; */
582 break;
583 case SIOCGIWENCODE:
584 /* Get scramble key */
585 /* wrq->u.encoding.code = scramble_key; */
586 /* wrq->u.encoding.method = 1; */
587 break;
588 case SIOCSIWENCODE:
589 /* Set scramble key */
590 /* scramble_key = wrq->u.encoding.code; */
591 break;
592 case SIOCGIWRANGE:
593 /* Basic checking... */
594 if(wrq->u.data.pointer != (caddr_t) 0) {
595 struct iw_range range;
597 /* Verify the user buffer */
598 ret = verify_area(VERIFY_WRITE, wrq->u.data.pointer,
599 sizeof(struct iw_range));
600 if(ret)
601 break;
603 /* Set the length (useless : its constant...) */
604 wrq->u.data.length = sizeof(struct iw_range);
606 /* Set information in the range struct */
607 range.throughput = 1.6 * 1024 * 1024; /* don't argue on this ! */
608 range.min_nwid = 0x0000;
609 range.max_nwid = 0x01FF;
611 range.num_channels = range.num_frequency = 0;
613 range.sensitivity = 0x3F;
614 range.max_qual.qual = 255;
615 range.max_qual.level = 255;
616 range.max_qual.noise = 0;
618 /* Copy structure to the user buffer */
619 copy_to_user(wrq->u.data.pointer, &range,
620 sizeof(struct iw_range));
622 break;
623 case SIOCGIWPRIV:
624 /* Basic checking... */
625 #if 0
626 if (wrq->u.data.pointer != (caddr_t) 0) {
627 struct iw_priv_args priv[] =
628 { /* cmd, set_args, get_args, name */
629 { SIOCGIPSNAP, IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 0,
630 sizeof(struct site_survey),
631 "getsitesurvey" },
634 /* Verify the user buffer */
635 ret = verify_area(VERIFY_WRITE, wrq->u.data.pointer,
636 sizeof(priv));
637 if (ret)
638 break;
640 /* Set the number of ioctl available */
641 wrq->u.data.length = 1;
643 /* Copy structure to the user buffer */
644 copy_to_user(wrq->u.data.pointer, (u_char *) priv,
645 sizeof(priv));
647 #endif
648 break;
649 #endif
650 case SIOCSDONGLE: /* Set dongle */
651 /* Initialize dongle */
652 irda_device_init_dongle(self, (int) rq->ifr_data);
653 break;
654 default:
655 ret = -EOPNOTSUPP;
658 restore_flags(flags);
660 return ret;
664 * Function irda_device_txqueue_empty (irda_device)
666 * Check if there is still some frames in the transmit queue for this
667 * device. Maybe we should use: q->q.qlen == 0.
670 int irda_device_txqueue_empty(struct irda_device *self)
672 ASSERT(self != NULL, return -1;);
673 ASSERT(self->magic == IRDA_DEVICE_MAGIC, return -1;);
675 if (skb_queue_len(&self->netdev.qdisc->q))
676 return FALSE;
678 return TRUE;
682 * Function irda_device_init_dongle (self, type)
684 * Initialize attached dongle. Warning, must be called with a process
685 * context!
687 void irda_device_init_dongle(struct irda_device *self, int type)
689 struct dongle_q *node;
691 ASSERT(self != NULL, return;);
692 ASSERT(self->magic == IRDA_DEVICE_MAGIC, return;);
694 #ifdef CONFIG_KMOD
695 /* Try to load the module needed */
696 switch (type) {
697 case ESI_DONGLE:
698 MESSAGE("IrDA: Initializing ESI dongle!\n");
699 request_module("esi");
700 break;
701 case TEKRAM_DONGLE:
702 MESSAGE("IrDA: Initializing Tekram dongle!\n");
703 request_module("tekram");
704 break;
705 case ACTISYS_DONGLE: /* FALLTHROUGH */
706 case ACTISYS_PLUS_DONGLE:
707 MESSAGE("IrDA: Initializing ACTiSYS dongle!\n");
708 request_module("actisys");
709 break;
710 case GIRBIL_DONGLE:
711 MESSAGE("IrDA: Initializing GIrBIL dongle!\n");
712 request_module("girbil");
713 break;
714 case LITELINK_DONGLE:
715 MESSAGE("IrDA: Initializing Litelink dongle!\n");
716 request_module("litelink");
717 break;
718 case AIRPORT_DONGLE:
719 MESSAGE("IrDA: Initializing Airport dongle!\n");
720 request_module("airport");
721 break;
722 default:
723 ERROR("Unknown dongle type!\n");
724 return;
726 #endif /* CONFIG_KMOD */
728 node = hashbin_find(dongles, type, NULL);
729 if (!node) {
730 ERROR("IrDA: Unable to find requested dongle\n");
731 return;
734 /* Check if we're already using a dongle */
735 if (self->dongle) {
736 self->dongle->close(self);
739 /* Set the dongle to be used by this driver */
740 self->dongle = node->dongle;
742 /* Now initialize the dongle! */
743 node->dongle->open(self, type);
744 node->dongle->qos_init(self, &self->qos);
746 /* Reset dongle */
747 node->dongle->reset(self);
749 /* Set to default baudrate */
750 irda_device_change_speed(self, 9600);
754 * Function irda_device_register_dongle (dongle)
759 int irda_device_register_dongle(struct dongle *dongle)
761 struct dongle_q *new;
763 /* Check if this dongle has been registred before */
764 if (hashbin_find(dongles, dongle->type, NULL)) {
765 MESSAGE(__FUNCTION__ "(), Dongle already registered\n");
766 return 0;
769 /* Make new IrDA dongle */
770 new = (struct dongle_q *) kmalloc(sizeof(struct dongle_q), GFP_KERNEL);
771 if (new == NULL)
772 return -1;
774 memset(new, 0, sizeof( struct dongle_q));
775 new->dongle = dongle;
777 /* Insert IrDA dongle into hashbin */
778 hashbin_insert(dongles, (QUEUE *) new, dongle->type, NULL);
780 return 0;
784 * Function irda_device_unregister_dongle (dongle)
789 void irda_device_unregister_dongle(struct dongle *dongle)
791 struct dongle_q *node;
793 node = hashbin_remove(dongles, dongle->type, NULL);
794 if (!node) {
795 ERROR(__FUNCTION__ "(), dongle not found!\n");
796 return;
798 kfree(node);
802 * Function irda_device_set_raw_mode (self, status)
807 int irda_device_set_raw_mode(struct irda_device* self, int status)
809 DEBUG(2, __FUNCTION__ "()\n");
811 ASSERT(self != NULL, return -1;);
812 ASSERT(self->magic == IRDA_DEVICE_MAGIC, return -1;);
814 if (self->set_raw_mode == NULL) {
815 ERROR(__FUNCTION__ "(), set_raw_mode not impl. by "
816 "device driver\n");
817 return -1;
820 self->raw_mode = status;
821 self->set_raw_mode(self, status);
823 return 0;
827 * Function setup_dma (idev, buffer, count, mode)
829 * Setup the DMA channel
832 void setup_dma(int channel, char *buffer, int count, int mode)
834 unsigned long flags;
836 flags = claim_dma_lock();
838 disable_dma(channel);
839 clear_dma_ff(channel);
840 set_dma_mode(channel, mode);
841 set_dma_addr(channel, virt_to_bus(buffer));
842 set_dma_count(channel, count);
843 enable_dma(channel);
845 release_dma_lock(flags);
848 #ifdef CONFIG_PROC_FS
850 int irda_device_print_flags(struct irda_device *idev, char *buf)
852 int len=0;
854 len += sprintf( buf+len, "\t");
856 if (idev->netdev.flags & IFF_UP)
857 len += sprintf( buf+len, "UP ");
858 if (!idev->netdev.tbusy)
859 len += sprintf( buf+len, "RUNNING ");
861 if (idev->flags & IFF_SIR)
862 len += sprintf( buf+len, "SIR ");
863 if (idev->flags & IFF_MIR)
864 len += sprintf( buf+len, "MIR ");
865 if (idev->flags & IFF_FIR)
866 len += sprintf( buf+len, "FIR ");
867 if (idev->flags & IFF_PIO)
868 len += sprintf( buf+len, "PIO ");
869 if (idev->flags & IFF_DMA)
870 len += sprintf( buf+len, "DMA ");
871 if (idev->flags & IFF_SHM)
872 len += sprintf( buf+len, "SHM ");
873 if (idev->flags & IFF_DONGLE)
874 len += sprintf( buf+len, "DONGLE ");
876 len += sprintf( buf+len, "\n");
878 return len;
882 * Function irda_device_proc_read (buf, start, offset, len, unused)
884 * Give some info to the /proc file system
887 int irda_device_proc_read(char *buf, char **start, off_t offset, int len,
888 int unused)
890 struct irda_device *self;
891 unsigned long flags;
893 save_flags(flags);
894 cli();
896 len = 0;
898 self = (struct irda_device *) hashbin_get_first(irda_device);
899 while ( self != NULL) {
900 len += sprintf(buf+len, "\n%s,", self->name);
901 len += sprintf(buf+len, "\tbinding: %s\n",
902 self->description);
904 len += irda_device_print_flags(self, buf+len);
905 len += sprintf(buf+len, "\tbps\tmaxtt\tdsize\twinsize\taddbofs\tmintt\tldisc\n");
907 len += sprintf(buf+len, "\t%d\t",
908 self->qos.baud_rate.value);
909 len += sprintf(buf+len, "%d\t",
910 self->qos.max_turn_time.value);
911 len += sprintf(buf+len, "%d\t",
912 self->qos.data_size.value);
913 len += sprintf(buf+len, "%d\t",
914 self->qos.window_size.value);
915 len += sprintf(buf+len, "%d\t",
916 self->qos.additional_bofs.value);
917 len += sprintf(buf+len, "%d\t",
918 self->qos.min_turn_time.value);
919 len += sprintf(buf+len, "%d",
920 self->qos.link_disc_time.value);
921 len += sprintf(buf+len, "\n");
923 self = (struct irda_device *) hashbin_get_next(irda_device);
925 restore_flags(flags);
927 return len;
930 #endif /* CONFIG_PROC_FS */