aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/rndis_wlan.c
diff options
context:
space:
mode:
authorJussi Kivilinna <jussi.kivilinna@mbnet.fi>2009-06-16 10:17:32 -0400
committerJohn W. Linville <linville@tuxdriver.com>2009-07-10 14:57:53 -0400
commit222ec50a0a5d20e75522aacf4c767df6585e8548 (patch)
tree80e1a42db9a03c381fcb9f18c4750716fc799373 /drivers/net/wireless/rndis_wlan.c
parenta33e9e7f35ef6dcab528e0327f29188475f60691 (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>
Diffstat (limited to 'drivers/net/wireless/rndis_wlan.c')
-rw-r--r--drivers/net/wireless/rndis_wlan.c148
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
431static int rndis_set_wiphy_params(struct wiphy *wiphy, u32 changed); 437static int rndis_set_wiphy_params(struct wiphy *wiphy, u32 changed);
432 438
439static int rndis_set_tx_power(struct wiphy *wiphy, enum tx_power_setting type,
440 int dbm);
441static int rndis_get_tx_power(struct wiphy *wiphy, int *dbm);
442
433static struct cfg80211_ops rndis_config_ops = { 443static 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
439static void *rndis_wiphy_privid = &rndis_wiphy_privid; 451static void *rndis_wiphy_privid = &rndis_wiphy_privid;
440 452
441static const int bcm4320_power_output[4] = { 25, 50, 75, 100 };
442 453
443static const unsigned char zero_bssid[ETH_ALEN] = {0,}; 454static const unsigned char zero_bssid[ETH_ALEN] = {0,};
444static const unsigned char ffff_bssid[ETH_ALEN] = { 0xff, 0xff, 0xff, 455static 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
454static u32 get_bcm4320_power(struct rndis_wlan_private *priv) 465static 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
1324static 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
1347static 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)
1305static int rndis_scan(struct wiphy *wiphy, struct net_device *dev, 1361static 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
1867static 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
1893static 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
1932static int rndis_iw_get_rate(struct net_device *dev, 1923static 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
2509static int rndis_wlan_reset(struct usbnet *usbdev) 2500static 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
2507static int rndis_wlan_stop(struct usbnet *usbdev)
2508{
2509 devdbg(usbdev, "rndis_wlan_stop");
2510 return disassociate(usbdev, 0);
2511}
2512
2513
2515static const struct driver_info bcm4320b_info = { 2514static 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};