Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 150684
b: refs/heads/master
c: 7643a2c
h: refs/heads/master
v: v3
  • Loading branch information
Johannes Berg authored and John W. Linville committed Jun 3, 2009
1 parent 7016b6f commit 0735419
Show file tree
Hide file tree
Showing 5 changed files with 167 additions and 79 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: c64fb01627e24725d1f9d535e4426475a4415753
refs/heads/master: 7643a2c3fcc13cd6fbd731f214463547383418ae
30 changes: 30 additions & 0 deletions trunk/include/net/cfg80211.h
Original file line number Diff line number Diff line change
Expand Up @@ -751,6 +751,21 @@ enum wiphy_params_flags {
WIPHY_PARAM_RTS_THRESHOLD = 1 << 3,
};

/**
* enum tx_power_setting - TX power adjustment
*
* @TX_POWER_AUTOMATIC: the dbm parameter is ignored
* @TX_POWER_LIMITED: limit TX power by the dbm parameter
* @TX_POWER_FIXED: fix TX power to the dbm parameter
* @TX_POWER_OFF: turn off completely (will go away)
*/
enum tx_power_setting {
TX_POWER_AUTOMATIC,
TX_POWER_LIMITED,
TX_POWER_FIXED,
TX_POWER_OFF,
};

/**
* struct cfg80211_ops - backend description for wireless configuration
*
Expand Down Expand Up @@ -837,6 +852,11 @@ enum wiphy_params_flags {
* @changed bitfield (see &enum wiphy_params_flags) describes which values
* have changed. The actual parameter values are available in
* struct wiphy. If returning an error, no value should be changed.
*
* @set_tx_power: set the transmit power according to the parameters
* @get_tx_power: store the current TX power into the dbm variable;
* return 0 if successful; or -ENETDOWN if successful but power
* is disabled (this will go away)
*/
struct cfg80211_ops {
int (*suspend)(struct wiphy *wiphy);
Expand Down Expand Up @@ -928,6 +948,10 @@ struct cfg80211_ops {
int (*leave_ibss)(struct wiphy *wiphy, struct net_device *dev);

int (*set_wiphy_params)(struct wiphy *wiphy, u32 changed);

int (*set_tx_power)(struct wiphy *wiphy,
enum tx_power_setting type, int dbm);
int (*get_tx_power)(struct wiphy *wiphy, int *dbm);
};

/*
Expand Down Expand Up @@ -1451,6 +1475,12 @@ int cfg80211_wext_siwencode(struct net_device *dev,
int cfg80211_wext_giwencode(struct net_device *dev,
struct iw_request_info *info,
struct iw_point *erq, char *keybuf);
int cfg80211_wext_siwtxpower(struct net_device *dev,
struct iw_request_info *info,
union iwreq_data *data, char *keybuf);
int cfg80211_wext_giwtxpower(struct net_device *dev,
struct iw_request_info *info,
union iwreq_data *data, char *keybuf);

/*
* callbacks for asynchronous cfg80211 methods, notification
Expand Down
54 changes: 54 additions & 0 deletions trunk/net/mac80211/cfg.c
Original file line number Diff line number Diff line change
Expand Up @@ -1334,6 +1334,58 @@ static int ieee80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
return 0;
}

static int ieee80211_set_tx_power(struct wiphy *wiphy,
enum tx_power_setting type, int dbm)
{
struct ieee80211_local *local = wiphy_priv(wiphy);
struct ieee80211_channel *chan = local->hw.conf.channel;
u32 changes = 0;
bool radio_enabled = true;

switch (type) {
case TX_POWER_AUTOMATIC:
local->user_power_level = -1;
break;
case TX_POWER_LIMITED:
if (dbm < 0)
return -EINVAL;
local->user_power_level = dbm;
break;
case TX_POWER_FIXED:
if (dbm < 0)
return -EINVAL;
/* TODO: move to cfg80211 when it knows the channel */
if (dbm > chan->max_power)
return -EINVAL;
local->user_power_level = dbm;
break;
case TX_POWER_OFF:
radio_enabled = false;
break;
}

if (radio_enabled != local->hw.conf.radio_enabled) {
changes |= IEEE80211_CONF_CHANGE_RADIO_ENABLED;
local->hw.conf.radio_enabled = radio_enabled;
}

ieee80211_hw_config(local, changes);

return 0;
}

static int ieee80211_get_tx_power(struct wiphy *wiphy, int *dbm)
{
struct ieee80211_local *local = wiphy_priv(wiphy);

*dbm = local->hw.conf.power_level;

if (!local->hw.conf.radio_enabled)
return -ENETDOWN;

return 0;
}

struct cfg80211_ops mac80211_config_ops = {
.add_virtual_intf = ieee80211_add_iface,
.del_virtual_intf = ieee80211_del_iface,
Expand Down Expand Up @@ -1373,4 +1425,6 @@ struct cfg80211_ops mac80211_config_ops = {
.join_ibss = ieee80211_join_ibss,
.leave_ibss = ieee80211_leave_ibss,
.set_wiphy_params = ieee80211_set_wiphy_params,
.set_tx_power = ieee80211_set_tx_power,
.get_tx_power = ieee80211_get_tx_power,
};
80 changes: 2 additions & 78 deletions trunk/net/mac80211/wext.c
Original file line number Diff line number Diff line change
Expand Up @@ -306,82 +306,6 @@ static int ieee80211_ioctl_giwrate(struct net_device *dev,
return 0;
}

static int ieee80211_ioctl_siwtxpower(struct net_device *dev,
struct iw_request_info *info,
union iwreq_data *data, char *extra)
{
struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
struct ieee80211_channel* chan = local->hw.conf.channel;
bool reconf = false;
u32 reconf_flags = 0;
int new_power_level;

if ((data->txpower.flags & IW_TXPOW_TYPE) != IW_TXPOW_DBM)
return -EINVAL;
if (data->txpower.flags & IW_TXPOW_RANGE)
return -EINVAL;
if (!chan)
return -EINVAL;

/* only change when not disabling */
if (!data->txpower.disabled) {
if (data->txpower.fixed) {
if (data->txpower.value < 0)
return -EINVAL;
new_power_level = data->txpower.value;
/*
* Debatable, but we cannot do a fixed power
* level above the regulatory constraint.
* Use "iwconfig wlan0 txpower 15dBm" instead.
*/
if (new_power_level > chan->max_power)
return -EINVAL;
} else {
/*
* Automatic power level setting, max being the value
* passed in from userland.
*/
if (data->txpower.value < 0)
new_power_level = -1;
else
new_power_level = data->txpower.value;
}

reconf = true;

/*
* ieee80211_hw_config() will limit to the channel's
* max power and possibly power constraint from AP.
*/
local->user_power_level = new_power_level;
}

if (local->hw.conf.radio_enabled != !(data->txpower.disabled)) {
local->hw.conf.radio_enabled = !(data->txpower.disabled);
reconf_flags |= IEEE80211_CONF_CHANGE_RADIO_ENABLED;
ieee80211_led_radio(local, local->hw.conf.radio_enabled);
}

if (reconf || reconf_flags)
ieee80211_hw_config(local, reconf_flags);

return 0;
}

static int ieee80211_ioctl_giwtxpower(struct net_device *dev,
struct iw_request_info *info,
union iwreq_data *data, char *extra)
{
struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);

data->txpower.fixed = 1;
data->txpower.disabled = !(local->hw.conf.radio_enabled);
data->txpower.value = local->hw.conf.power_level;
data->txpower.flags = IW_TXPOW_DBM;

return 0;
}

static int ieee80211_ioctl_siwpower(struct net_device *dev,
struct iw_request_info *info,
struct iw_param *wrq,
Expand Down Expand Up @@ -658,8 +582,8 @@ static const iw_handler ieee80211_handler[] =
(iw_handler) cfg80211_wext_giwrts, /* SIOCGIWRTS */
(iw_handler) cfg80211_wext_siwfrag, /* SIOCSIWFRAG */
(iw_handler) cfg80211_wext_giwfrag, /* SIOCGIWFRAG */
(iw_handler) ieee80211_ioctl_siwtxpower, /* SIOCSIWTXPOW */
(iw_handler) ieee80211_ioctl_giwtxpower, /* SIOCGIWTXPOW */
(iw_handler) cfg80211_wext_siwtxpower, /* SIOCSIWTXPOW */
(iw_handler) cfg80211_wext_giwtxpower, /* SIOCGIWTXPOW */
(iw_handler) cfg80211_wext_siwretry, /* SIOCSIWRETRY */
(iw_handler) cfg80211_wext_giwretry, /* SIOCGIWRETRY */
(iw_handler) cfg80211_wext_siwencode, /* SIOCSIWENCODE */
Expand Down
80 changes: 80 additions & 0 deletions trunk/net/wireless/wext-compat.c
Original file line number Diff line number Diff line change
Expand Up @@ -744,3 +744,83 @@ int cfg80211_wext_giwencode(struct net_device *dev,
return err;
}
EXPORT_SYMBOL_GPL(cfg80211_wext_giwencode);

int cfg80211_wext_siwtxpower(struct net_device *dev,
struct iw_request_info *info,
union iwreq_data *data, char *extra)
{
struct wireless_dev *wdev = dev->ieee80211_ptr;
struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
enum tx_power_setting type;
int dbm = 0;

if ((data->txpower.flags & IW_TXPOW_TYPE) != IW_TXPOW_DBM)
return -EINVAL;
if (data->txpower.flags & IW_TXPOW_RANGE)
return -EINVAL;

if (!rdev->ops->set_tx_power)
return -EOPNOTSUPP;

/* only change when not disabling */
if (!data->txpower.disabled) {
if (data->txpower.fixed) {
/*
* wext doesn't support negative values, see
* below where it's for automatic
*/
if (data->txpower.value < 0)
return -EINVAL;
dbm = data->txpower.value;
type = TX_POWER_FIXED;
/* TODO: do regulatory check! */
} else {
/*
* Automatic power level setting, max being the value
* passed in from userland.
*/
if (data->txpower.value < 0) {
type = TX_POWER_AUTOMATIC;
} else {
dbm = data->txpower.value;
type = TX_POWER_LIMITED;
}
}
} else {
type = TX_POWER_OFF;
}

return rdev->ops->set_tx_power(wdev->wiphy, type, dbm);;
}
EXPORT_SYMBOL_GPL(cfg80211_wext_siwtxpower);

int cfg80211_wext_giwtxpower(struct net_device *dev,
struct iw_request_info *info,
union iwreq_data *data, char *extra)
{
struct wireless_dev *wdev = dev->ieee80211_ptr;
struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
int err, val;

if ((data->txpower.flags & IW_TXPOW_TYPE) != IW_TXPOW_DBM)
return -EINVAL;
if (data->txpower.flags & IW_TXPOW_RANGE)
return -EINVAL;

if (!rdev->ops->get_tx_power)
return -EOPNOTSUPP;

err = rdev->ops->get_tx_power(wdev->wiphy, &val);
/* HACK!!! */
if (err && err != -ENETDOWN)
return err;

/* well... oh well */
data->txpower.fixed = 1;
data->txpower.disabled = err == -ENETDOWN;
data->txpower.value = val;
data->txpower.flags = IW_TXPOW_DBM;

return 0;
}
EXPORT_SYMBOL_GPL(cfg80211_wext_giwtxpower);

0 comments on commit 0735419

Please sign in to comment.