Loading...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 | /*
* This file provides /sys/class/ieee80211/<wiphy name>/
* and some default attributes.
*
* Copyright 2005-2006 Jiri Benc <jbenc@suse.cz>
* Copyright 2006 Johannes Berg <johannes@sipsolutions.net>
*
* This file is GPLv2 as found in COPYING.
*/
#include <linux/device.h>
#include <linux/module.h>
#include <linux/netdevice.h>
#include <linux/nl80211.h>
#include <linux/rtnetlink.h>
#include <net/cfg80211.h>
#include "sysfs.h"
#include "core.h"
#include "rdev-ops.h"
static inline struct cfg80211_registered_device *dev_to_rdev(
struct device *dev)
{
return container_of(dev, struct cfg80211_registered_device, wiphy.dev);
}
#define SHOW_FMT(name, fmt, member) \
static ssize_t name ## _show(struct device *dev, \
struct device_attribute *attr, \
char *buf) \
{ \
return sprintf(buf, fmt "\n", dev_to_rdev(dev)->member); \
} \
static DEVICE_ATTR_RO(name)
SHOW_FMT(index, "%d", wiphy_idx);
SHOW_FMT(macaddress, "%pM", wiphy.perm_addr);
SHOW_FMT(address_mask, "%pM", wiphy.addr_mask);
static ssize_t name_show(struct device *dev,
struct device_attribute *attr,
char *buf) {
struct wiphy *wiphy = &dev_to_rdev(dev)->wiphy;
return sprintf(buf, "%s\n", dev_name(&wiphy->dev));
}
static DEVICE_ATTR_RO(name);
static ssize_t addresses_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
struct wiphy *wiphy = &dev_to_rdev(dev)->wiphy;
char *start = buf;
int i;
if (!wiphy->addresses)
return sprintf(buf, "%pM\n", wiphy->perm_addr);
for (i = 0; i < wiphy->n_addresses; i++)
buf += sprintf(buf, "%pM\n", &wiphy->addresses[i].addr);
return buf - start;
}
static DEVICE_ATTR_RO(addresses);
static struct attribute *ieee80211_attrs[] = {
&dev_attr_index.attr,
&dev_attr_macaddress.attr,
&dev_attr_address_mask.attr,
&dev_attr_addresses.attr,
&dev_attr_name.attr,
NULL,
};
ATTRIBUTE_GROUPS(ieee80211);
static void wiphy_dev_release(struct device *dev)
{
struct cfg80211_registered_device *rdev = dev_to_rdev(dev);
cfg80211_dev_free(rdev);
}
static int wiphy_uevent(struct device *dev, struct kobj_uevent_env *env)
{
/* TODO, we probably need stuff here */
return 0;
}
#ifdef CONFIG_PM
static void cfg80211_leave_all(struct cfg80211_registered_device *rdev)
{
struct wireless_dev *wdev;
list_for_each_entry(wdev, &rdev->wdev_list, list)
cfg80211_leave(rdev, wdev);
}
static int wiphy_suspend(struct device *dev, pm_message_t state)
{
struct cfg80211_registered_device *rdev = dev_to_rdev(dev);
int ret = 0;
rdev->suspend_at = get_seconds();
rtnl_lock();
if (rdev->wiphy.registered) {
if (!rdev->wiphy.wowlan_config)
cfg80211_leave_all(rdev);
if (rdev->ops->suspend)
ret = rdev_suspend(rdev, rdev->wiphy.wowlan_config);
if (ret == 1) {
/* Driver refuse to configure wowlan */
cfg80211_leave_all(rdev);
ret = rdev_suspend(rdev, NULL);
}
}
rtnl_unlock();
return ret;
}
static int wiphy_resume(struct device *dev)
{
struct cfg80211_registered_device *rdev = dev_to_rdev(dev);
int ret = 0;
/* Age scan results with time spent in suspend */
cfg80211_bss_age(rdev, get_seconds() - rdev->suspend_at);
if (rdev->ops->resume) {
rtnl_lock();
if (rdev->wiphy.registered)
ret = rdev_resume(rdev);
rtnl_unlock();
}
return ret;
}
#endif
static const void *wiphy_namespace(struct device *d)
{
struct wiphy *wiphy = container_of(d, struct wiphy, dev);
return wiphy_net(wiphy);
}
struct class ieee80211_class = {
.name = "ieee80211",
.owner = THIS_MODULE,
.dev_release = wiphy_dev_release,
.dev_groups = ieee80211_groups,
.dev_uevent = wiphy_uevent,
#ifdef CONFIG_PM
.suspend = wiphy_suspend,
.resume = wiphy_resume,
#endif
.ns_type = &net_ns_type_operations,
.namespace = wiphy_namespace,
};
int wiphy_sysfs_init(void)
{
return class_register(&ieee80211_class);
}
void wiphy_sysfs_exit(void)
{
class_unregister(&ieee80211_class);
}
|