This patch exports the hardware rfkill bits to sysfs, as Joe Jezak
suggested. I tested it on my bcm4318, but it seems that those bits can't be
set, so this shouldn't solve any issue with radio buttons. Please tell me
if it gives different behaviour on laptops with a radio button switch.


Signed-off-by: Stefano Brivio <[EMAIL PROTECTED]>

Index: wireless-dev/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.c
===================================================================
--- wireless-dev.orig/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.c
+++ wireless-dev/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.c
@@ -305,6 +305,83 @@ static DEVICE_ATTR(shortpreamble, 0644,
                   bcm43xx_attr_preamble_show,
                   bcm43xx_attr_preamble_store);
 
+static ssize_t bcm43xx_attr_rfkill_show(struct device *dev,
+                                       struct device_attribute *attr,
+                                       char *buf)
+{
+       struct bcm43xx_private *bcm = dev_to_bcm(dev);
+       unsigned long flags;
+       ssize_t count;
+
+       if (!capable(CAP_NET_ADMIN))
+               return -EPERM;
+
+       bcm43xx_lock_mmio(bcm, flags);
+       assert(bcm->initialized);
+
+       if (bcm->core_80211[0].rev >= 3) {
+               if (bcm43xx_read32(bcm, 0x0158) & (1 << 16))
+                       count = snprintf(buf, PAGE_SIZE, "1 (Radio disabled by 
hardware)\n");
+               else
+                       count = snprintf(buf, PAGE_SIZE, "0 (Radio not disabled 
by hardware)\n");
+       } else {
+               if (bcm43xx_read16(bcm, 0x049A) & (1 << 4))
+                       count = snprintf(buf, PAGE_SIZE, "0 (Radio not disabled 
by hardware)\n");
+               else
+                       count = snprintf(buf, PAGE_SIZE, "1 (Radio disabled by 
hardware)\n");
+       }
+
+       bcm43xx_unlock_mmio(bcm, flags);
+
+       return count;
+}
+
+static ssize_t bcm43xx_attr_rfkill_store(struct device *dev,
+                                       struct device_attribute *attr,
+                                       const char *buf, size_t count)
+{
+       struct bcm43xx_private *bcm = dev_to_bcm(dev);
+       unsigned long flags;
+       int value;
+
+       if (!capable(CAP_NET_ADMIN))
+               return -EPERM;
+
+       value = get_boolean(buf, count);
+       if (value < 0)
+               return value;
+       bcm43xx_lock_mmio(bcm, flags);
+       assert(bcm->initialized);
+
+       if (value) {
+               if (bcm->core_80211[0].rev >= 3)
+                       bcm43xx_write32(bcm, BCM43xx_MMIO_RADIO_HWENABLED_HI,
+                                       bcm43xx_read32(bcm, 
BCM43xx_MMIO_RADIO_HWENABLED_HI)
+                                       | (1 << 16));
+               else
+                       bcm43xx_write16(bcm, BCM43xx_MMIO_RADIO_HWENABLED_LO,
+                                       bcm43xx_read16(bcm, 
BCM43xx_MMIO_RADIO_HWENABLED_LO)
+                                       & ~(1 << 4));
+       } else {
+               if (bcm->core_80211[0].rev >= 3)
+                       bcm43xx_write32(bcm, BCM43xx_MMIO_RADIO_HWENABLED_HI,
+                                       bcm43xx_read32(bcm, 
BCM43xx_MMIO_RADIO_HWENABLED_HI)
+                                       & ~(1 << 16));
+               else
+                       bcm43xx_write16(bcm, BCM43xx_MMIO_RADIO_HWENABLED_LO,
+                                       bcm43xx_read16(bcm, 
BCM43xx_MMIO_RADIO_HWENABLED_LO)
+                                       | (1 << 4));
+       }
+
+       bcm43xx_unlock_mmio(bcm, flags);
+
+       return count;
+}
+
+static DEVICE_ATTR(rfkill, 0644,
+                  bcm43xx_attr_rfkill_show,
+                  bcm43xx_attr_rfkill_store);
+
 int bcm43xx_sysfs_register(struct bcm43xx_private *bcm)
 {
        struct device *dev = &bcm->pci_dev->dev;
@@ -321,9 +398,14 @@ int bcm43xx_sysfs_register(struct bcm43x
        err = device_create_file(dev, &dev_attr_shortpreamble);
        if (err)
                goto err_remove_interfmode;
+       err = device_create_file(dev, &dev_attr_rfkill);
+       if (err)
+               goto err_remove_shortpreamble;
 
 out:
        return err;
+err_remove_shortpreamble:
+       device_remove_file(dev, &dev_attr_shortpreamble);
 err_remove_interfmode:
        device_remove_file(dev, &dev_attr_interference);
 err_remove_sprom:
@@ -335,6 +417,7 @@ void bcm43xx_sysfs_unregister(struct bcm
 {
        struct device *dev = &bcm->pci_dev->dev;
 
+       device_remove_file(dev, &dev_attr_rfkill);
        device_remove_file(dev, &dev_attr_shortpreamble);
        device_remove_file(dev, &dev_attr_interference);
        device_remove_file(dev, &dev_attr_sprom);


-- 
Ciao
Stefano
_______________________________________________
Bcm43xx-dev mailing list
Bcm43xx-dev@lists.berlios.de
http://lists.berlios.de/mailman/listinfo/bcm43xx-dev

Reply via email to