diff options
author | Jussi Kivilinna <jussi.kivilinna@mbnet.fi> | 2009-06-16 10:17:32 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2009-07-10 14:57:53 -0400 |
commit | 222ec50a0a5d20e75522aacf4c767df6585e8548 (patch) | |
tree | 80e1a42db9a03c381fcb9f18c4750716fc799373 | |
parent | a33e9e7f35ef6dcab528e0327f29188475f60691 (diff) |
rndis_wlan: convert set/get txpower to cfg80211
Convert set/get txpower to cfg80211 and add stop netdev handler to turn off
radio for rfkill.
Signed-off-by: Jussi Kivilinna <jussi.kivilinna@mbnet.fi>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r-- | drivers/net/wireless/rndis_wlan.c | 148 |
1 files changed, 75 insertions, 73 deletions
diff --git a/drivers/net/wireless/rndis_wlan.c b/drivers/net/wireless/rndis_wlan.c index edd4aad68be9..09c0702ae645 100644 --- a/drivers/net/wireless/rndis_wlan.c +++ b/drivers/net/wireless/rndis_wlan.c | |||
@@ -139,9 +139,15 @@ MODULE_PARM_DESC(workaround_interval, | |||
139 | /* Assume that Broadcom 4320 (only chipset at time of writing known to be | 139 | /* Assume that Broadcom 4320 (only chipset at time of writing known to be |
140 | * based on wireless rndis) has default txpower of 13dBm. | 140 | * based on wireless rndis) has default txpower of 13dBm. |
141 | * This value is from Linksys WUSB54GSC User Guide, Appendix F: Specifications. | 141 | * This value is from Linksys WUSB54GSC User Guide, Appendix F: Specifications. |
142 | * 13dBm == 19.9mW | 142 | * 100% : 20 mW ~ 13dBm |
143 | * 75% : 15 mW ~ 12dBm | ||
144 | * 50% : 10 mW ~ 10dBm | ||
145 | * 25% : 5 mW ~ 7dBm | ||
143 | */ | 146 | */ |
144 | #define BCM4320_DEFAULT_TXPOWER 20 | 147 | #define BCM4320_DEFAULT_TXPOWER_DBM_100 13 |
148 | #define BCM4320_DEFAULT_TXPOWER_DBM_75 12 | ||
149 | #define BCM4320_DEFAULT_TXPOWER_DBM_50 10 | ||
150 | #define BCM4320_DEFAULT_TXPOWER_DBM_25 7 | ||
145 | 151 | ||
146 | 152 | ||
147 | /* codes for "status" field of completion messages */ | 153 | /* codes for "status" field of completion messages */ |
@@ -430,15 +436,20 @@ static int rndis_scan(struct wiphy *wiphy, struct net_device *dev, | |||
430 | 436 | ||
431 | static int rndis_set_wiphy_params(struct wiphy *wiphy, u32 changed); | 437 | static int rndis_set_wiphy_params(struct wiphy *wiphy, u32 changed); |
432 | 438 | ||
439 | static int rndis_set_tx_power(struct wiphy *wiphy, enum tx_power_setting type, | ||
440 | int dbm); | ||
441 | static int rndis_get_tx_power(struct wiphy *wiphy, int *dbm); | ||
442 | |||
433 | static struct cfg80211_ops rndis_config_ops = { | 443 | static struct cfg80211_ops rndis_config_ops = { |
434 | .change_virtual_intf = rndis_change_virtual_intf, | 444 | .change_virtual_intf = rndis_change_virtual_intf, |
435 | .scan = rndis_scan, | 445 | .scan = rndis_scan, |
436 | .set_wiphy_params = rndis_set_wiphy_params, | 446 | .set_wiphy_params = rndis_set_wiphy_params, |
447 | .set_tx_power = rndis_set_tx_power, | ||
448 | .get_tx_power = rndis_get_tx_power, | ||
437 | }; | 449 | }; |
438 | 450 | ||
439 | static void *rndis_wiphy_privid = &rndis_wiphy_privid; | 451 | static void *rndis_wiphy_privid = &rndis_wiphy_privid; |
440 | 452 | ||
441 | static const int bcm4320_power_output[4] = { 25, 50, 75, 100 }; | ||
442 | 453 | ||
443 | static const unsigned char zero_bssid[ETH_ALEN] = {0,}; | 454 | static const unsigned char zero_bssid[ETH_ALEN] = {0,}; |
444 | static const unsigned char ffff_bssid[ETH_ALEN] = { 0xff, 0xff, 0xff, | 455 | static const unsigned char ffff_bssid[ETH_ALEN] = { 0xff, 0xff, 0xff, |
@@ -451,10 +462,19 @@ static struct rndis_wlan_private *get_rndis_wlan_priv(struct usbnet *dev) | |||
451 | } | 462 | } |
452 | 463 | ||
453 | 464 | ||
454 | static u32 get_bcm4320_power(struct rndis_wlan_private *priv) | 465 | static u32 get_bcm4320_power_dbm(struct rndis_wlan_private *priv) |
455 | { | 466 | { |
456 | return BCM4320_DEFAULT_TXPOWER * | 467 | switch (priv->param_power_output) { |
457 | bcm4320_power_output[priv->param_power_output] / 100; | 468 | default: |
469 | case 3: | ||
470 | return BCM4320_DEFAULT_TXPOWER_DBM_100; | ||
471 | case 2: | ||
472 | return BCM4320_DEFAULT_TXPOWER_DBM_75; | ||
473 | case 1: | ||
474 | return BCM4320_DEFAULT_TXPOWER_DBM_50; | ||
475 | case 0: | ||
476 | return BCM4320_DEFAULT_TXPOWER_DBM_25; | ||
477 | } | ||
458 | } | 478 | } |
459 | 479 | ||
460 | 480 | ||
@@ -1301,6 +1321,42 @@ static int rndis_set_wiphy_params(struct wiphy *wiphy, u32 changed) | |||
1301 | } | 1321 | } |
1302 | 1322 | ||
1303 | 1323 | ||
1324 | static int rndis_set_tx_power(struct wiphy *wiphy, enum tx_power_setting type, | ||
1325 | int dbm) | ||
1326 | { | ||
1327 | struct rndis_wlan_private *priv = wiphy_priv(wiphy); | ||
1328 | struct usbnet *usbdev = priv->usbdev; | ||
1329 | |||
1330 | devdbg(usbdev, "rndis_set_tx_power type:0x%x dbm:%i", type, dbm); | ||
1331 | |||
1332 | /* Device doesn't support changing txpower after initialization, only | ||
1333 | * turn off/on radio. Support 'auto' mode and setting same dBm that is | ||
1334 | * currently used. | ||
1335 | */ | ||
1336 | if (type == TX_POWER_AUTOMATIC || dbm == get_bcm4320_power_dbm(priv)) { | ||
1337 | if (!priv->radio_on) | ||
1338 | disassociate(usbdev, 1); /* turn on radio */ | ||
1339 | |||
1340 | return 0; | ||
1341 | } | ||
1342 | |||
1343 | return -ENOTSUPP; | ||
1344 | } | ||
1345 | |||
1346 | |||
1347 | static int rndis_get_tx_power(struct wiphy *wiphy, int *dbm) | ||
1348 | { | ||
1349 | struct rndis_wlan_private *priv = wiphy_priv(wiphy); | ||
1350 | struct usbnet *usbdev = priv->usbdev; | ||
1351 | |||
1352 | *dbm = get_bcm4320_power_dbm(priv); | ||
1353 | |||
1354 | devdbg(usbdev, "rndis_get_tx_power dbm:%i", *dbm); | ||
1355 | |||
1356 | return 0; | ||
1357 | } | ||
1358 | |||
1359 | |||
1304 | #define SCAN_DELAY_JIFFIES (HZ) | 1360 | #define SCAN_DELAY_JIFFIES (HZ) |
1305 | static int rndis_scan(struct wiphy *wiphy, struct net_device *dev, | 1361 | static int rndis_scan(struct wiphy *wiphy, struct net_device *dev, |
1306 | struct cfg80211_scan_request *request) | 1362 | struct cfg80211_scan_request *request) |
@@ -1864,71 +1920,6 @@ static int rndis_iw_get_freq(struct net_device *dev, | |||
1864 | } | 1920 | } |
1865 | 1921 | ||
1866 | 1922 | ||
1867 | static int rndis_iw_get_txpower(struct net_device *dev, | ||
1868 | struct iw_request_info *info, union iwreq_data *wrqu, char *extra) | ||
1869 | { | ||
1870 | struct usbnet *usbdev = netdev_priv(dev); | ||
1871 | struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev); | ||
1872 | __le32 tx_power; | ||
1873 | |||
1874 | if (priv->radio_on) { | ||
1875 | /* fake since changing tx_power (by userlevel) not supported */ | ||
1876 | tx_power = cpu_to_le32(get_bcm4320_power(priv)); | ||
1877 | |||
1878 | wrqu->txpower.flags = IW_TXPOW_MWATT; | ||
1879 | wrqu->txpower.value = le32_to_cpu(tx_power); | ||
1880 | wrqu->txpower.disabled = 0; | ||
1881 | } else { | ||
1882 | wrqu->txpower.flags = IW_TXPOW_MWATT; | ||
1883 | wrqu->txpower.value = 0; | ||
1884 | wrqu->txpower.disabled = 1; | ||
1885 | } | ||
1886 | |||
1887 | devdbg(usbdev, "SIOCGIWTXPOW: %d", wrqu->txpower.value); | ||
1888 | |||
1889 | return 0; | ||
1890 | } | ||
1891 | |||
1892 | |||
1893 | static int rndis_iw_set_txpower(struct net_device *dev, | ||
1894 | struct iw_request_info *info, union iwreq_data *wrqu, char *extra) | ||
1895 | { | ||
1896 | struct usbnet *usbdev = netdev_priv(dev); | ||
1897 | struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev); | ||
1898 | __le32 tx_power = 0; | ||
1899 | |||
1900 | if (!wrqu->txpower.disabled) { | ||
1901 | if (wrqu->txpower.flags == IW_TXPOW_MWATT) | ||
1902 | tx_power = cpu_to_le32(wrqu->txpower.value); | ||
1903 | else { /* wrqu->txpower.flags == IW_TXPOW_DBM */ | ||
1904 | if (wrqu->txpower.value > 20) | ||
1905 | tx_power = cpu_to_le32(128); | ||
1906 | else if (wrqu->txpower.value < -43) | ||
1907 | tx_power = cpu_to_le32(127); | ||
1908 | else { | ||
1909 | signed char tmp; | ||
1910 | tmp = wrqu->txpower.value; | ||
1911 | tmp = -12 - tmp; | ||
1912 | tmp <<= 2; | ||
1913 | tx_power = cpu_to_le32((unsigned char)tmp); | ||
1914 | } | ||
1915 | } | ||
1916 | } | ||
1917 | |||
1918 | devdbg(usbdev, "SIOCSIWTXPOW: %d", le32_to_cpu(tx_power)); | ||
1919 | |||
1920 | if (le32_to_cpu(tx_power) != 0) { | ||
1921 | /* txpower unsupported, just turn radio on */ | ||
1922 | if (!priv->radio_on) | ||
1923 | return disassociate(usbdev, 1); | ||
1924 | return 0; /* all ready on */ | ||
1925 | } | ||
1926 | |||
1927 | /* tx_power == 0, turn off radio */ | ||
1928 | return disassociate(usbdev, 0); | ||
1929 | } | ||
1930 | |||
1931 | |||
1932 | static int rndis_iw_get_rate(struct net_device *dev, | 1923 | static int rndis_iw_get_rate(struct net_device *dev, |
1933 | struct iw_request_info *info, union iwreq_data *wrqu, char *extra) | 1924 | struct iw_request_info *info, union iwreq_data *wrqu, char *extra) |
1934 | { | 1925 | { |
@@ -2008,8 +1999,8 @@ static const iw_handler rndis_iw_handler[] = | |||
2008 | IW_IOCTL(SIOCGIWRTS) = (iw_handler) cfg80211_wext_giwrts, | 1999 | IW_IOCTL(SIOCGIWRTS) = (iw_handler) cfg80211_wext_giwrts, |
2009 | IW_IOCTL(SIOCSIWFRAG) = (iw_handler) cfg80211_wext_siwfrag, | 2000 | IW_IOCTL(SIOCSIWFRAG) = (iw_handler) cfg80211_wext_siwfrag, |
2010 | IW_IOCTL(SIOCGIWFRAG) = (iw_handler) cfg80211_wext_giwfrag, | 2001 | IW_IOCTL(SIOCGIWFRAG) = (iw_handler) cfg80211_wext_giwfrag, |
2011 | IW_IOCTL(SIOCSIWTXPOW) = rndis_iw_set_txpower, | 2002 | IW_IOCTL(SIOCSIWTXPOW) = (iw_handler) cfg80211_wext_siwtxpower, |
2012 | IW_IOCTL(SIOCGIWTXPOW) = rndis_iw_get_txpower, | 2003 | IW_IOCTL(SIOCGIWTXPOW) = (iw_handler) cfg80211_wext_giwtxpower, |
2013 | IW_IOCTL(SIOCSIWENCODE) = rndis_iw_set_encode, | 2004 | IW_IOCTL(SIOCSIWENCODE) = rndis_iw_set_encode, |
2014 | IW_IOCTL(SIOCSIWENCODEEXT) = rndis_iw_set_encode_ext, | 2005 | IW_IOCTL(SIOCSIWENCODEEXT) = rndis_iw_set_encode_ext, |
2015 | IW_IOCTL(SIOCSIWAUTH) = rndis_iw_set_auth, | 2006 | IW_IOCTL(SIOCSIWAUTH) = rndis_iw_set_auth, |
@@ -2508,10 +2499,18 @@ static void rndis_wlan_unbind(struct usbnet *usbdev, struct usb_interface *intf) | |||
2508 | 2499 | ||
2509 | static int rndis_wlan_reset(struct usbnet *usbdev) | 2500 | static int rndis_wlan_reset(struct usbnet *usbdev) |
2510 | { | 2501 | { |
2502 | devdbg(usbdev, "rndis_wlan_reset"); | ||
2511 | return deauthenticate(usbdev); | 2503 | return deauthenticate(usbdev); |
2512 | } | 2504 | } |
2513 | 2505 | ||
2514 | 2506 | ||
2507 | static int rndis_wlan_stop(struct usbnet *usbdev) | ||
2508 | { | ||
2509 | devdbg(usbdev, "rndis_wlan_stop"); | ||
2510 | return disassociate(usbdev, 0); | ||
2511 | } | ||
2512 | |||
2513 | |||
2515 | static const struct driver_info bcm4320b_info = { | 2514 | static const struct driver_info bcm4320b_info = { |
2516 | .description = "Wireless RNDIS device, BCM4320b based", | 2515 | .description = "Wireless RNDIS device, BCM4320b based", |
2517 | .flags = FLAG_WLAN | FLAG_FRAMING_RN | FLAG_NO_SETINT, | 2516 | .flags = FLAG_WLAN | FLAG_FRAMING_RN | FLAG_NO_SETINT, |
@@ -2521,6 +2520,7 @@ static const struct driver_info bcm4320b_info = { | |||
2521 | .rx_fixup = rndis_rx_fixup, | 2520 | .rx_fixup = rndis_rx_fixup, |
2522 | .tx_fixup = rndis_tx_fixup, | 2521 | .tx_fixup = rndis_tx_fixup, |
2523 | .reset = rndis_wlan_reset, | 2522 | .reset = rndis_wlan_reset, |
2523 | .stop = rndis_wlan_stop, | ||
2524 | .early_init = bcm4320b_early_init, | 2524 | .early_init = bcm4320b_early_init, |
2525 | .link_change = rndis_wlan_link_change, | 2525 | .link_change = rndis_wlan_link_change, |
2526 | }; | 2526 | }; |
@@ -2534,6 +2534,7 @@ static const struct driver_info bcm4320a_info = { | |||
2534 | .rx_fixup = rndis_rx_fixup, | 2534 | .rx_fixup = rndis_rx_fixup, |
2535 | .tx_fixup = rndis_tx_fixup, | 2535 | .tx_fixup = rndis_tx_fixup, |
2536 | .reset = rndis_wlan_reset, | 2536 | .reset = rndis_wlan_reset, |
2537 | .stop = rndis_wlan_stop, | ||
2537 | .early_init = bcm4320a_early_init, | 2538 | .early_init = bcm4320a_early_init, |
2538 | .link_change = rndis_wlan_link_change, | 2539 | .link_change = rndis_wlan_link_change, |
2539 | }; | 2540 | }; |
@@ -2547,6 +2548,7 @@ static const struct driver_info rndis_wlan_info = { | |||
2547 | .rx_fixup = rndis_rx_fixup, | 2548 | .rx_fixup = rndis_rx_fixup, |
2548 | .tx_fixup = rndis_tx_fixup, | 2549 | .tx_fixup = rndis_tx_fixup, |
2549 | .reset = rndis_wlan_reset, | 2550 | .reset = rndis_wlan_reset, |
2551 | .stop = rndis_wlan_stop, | ||
2550 | .early_init = bcm4320a_early_init, | 2552 | .early_init = bcm4320a_early_init, |
2551 | .link_change = rndis_wlan_link_change, | 2553 | .link_change = rndis_wlan_link_change, |
2552 | }; | 2554 | }; |