aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/rndis_wlan.c
diff options
context:
space:
mode:
authorJohn W. Linville <linville@tuxdriver.com>2009-03-26 17:39:53 -0400
committerJohn W. Linville <linville@tuxdriver.com>2009-04-22 16:54:36 -0400
commit5c8fa4f7e7fcceabb3b37d7ec66d3e7115a4bba3 (patch)
tree9f883762a20ca60336a21c0ebedda2deecef1326 /drivers/net/wireless/rndis_wlan.c
parentf13027af5cd567757c18b85776232e31a2ba55d4 (diff)
rndis_wlan: initiate cfg80211 conversion
Signed-off-by: John W. Linville <linville@tuxdriver.com> 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.c114
1 files changed, 85 insertions, 29 deletions
diff --git a/drivers/net/wireless/rndis_wlan.c b/drivers/net/wireless/rndis_wlan.c
index db91db776508..c995d7c3139c 100644
--- a/drivers/net/wireless/rndis_wlan.c
+++ b/drivers/net/wireless/rndis_wlan.c
@@ -42,6 +42,8 @@
42#include <linux/ctype.h> 42#include <linux/ctype.h>
43#include <linux/spinlock.h> 43#include <linux/spinlock.h>
44#include <net/iw_handler.h> 44#include <net/iw_handler.h>
45#include <net/wireless.h>
46#include <net/cfg80211.h>
45#include <linux/usb/usbnet.h> 47#include <linux/usb/usbnet.h>
46#include <linux/usb/rndis_host.h> 48#include <linux/usb/rndis_host.h>
47 49
@@ -316,12 +318,44 @@ enum wpa_key_mgmt { KEY_MGMT_802_1X, KEY_MGMT_PSK, KEY_MGMT_NONE,
316 318
317#define COMMAND_BUFFER_SIZE (CONTROL_BUFFER_SIZE + sizeof(struct rndis_set)) 319#define COMMAND_BUFFER_SIZE (CONTROL_BUFFER_SIZE + sizeof(struct rndis_set))
318 320
321static const struct ieee80211_channel rndis_channels[] = {
322 { .center_freq = 2412 },
323 { .center_freq = 2417 },
324 { .center_freq = 2422 },
325 { .center_freq = 2427 },
326 { .center_freq = 2432 },
327 { .center_freq = 2437 },
328 { .center_freq = 2442 },
329 { .center_freq = 2447 },
330 { .center_freq = 2452 },
331 { .center_freq = 2457 },
332 { .center_freq = 2462 },
333 { .center_freq = 2467 },
334 { .center_freq = 2472 },
335 { .center_freq = 2484 },
336};
337
338static const struct ieee80211_rate rndis_rates[] = {
339 { .bitrate = 10 },
340 { .bitrate = 20, .flags = IEEE80211_RATE_SHORT_PREAMBLE },
341 { .bitrate = 55, .flags = IEEE80211_RATE_SHORT_PREAMBLE },
342 { .bitrate = 110, .flags = IEEE80211_RATE_SHORT_PREAMBLE },
343 { .bitrate = 60 },
344 { .bitrate = 90 },
345 { .bitrate = 120 },
346 { .bitrate = 180 },
347 { .bitrate = 240 },
348 { .bitrate = 360 },
349 { .bitrate = 480 },
350 { .bitrate = 540 }
351};
352
319/* RNDIS device private data */ 353/* RNDIS device private data */
320struct rndis_wext_private { 354struct rndis_wext_private {
321 char name[32];
322
323 struct usbnet *usbdev; 355 struct usbnet *usbdev;
324 356
357 struct wireless_dev wdev;
358
325 struct workqueue_struct *workqueue; 359 struct workqueue_struct *workqueue;
326 struct delayed_work stats_work; 360 struct delayed_work stats_work;
327 struct work_struct work; 361 struct work_struct work;
@@ -329,6 +363,10 @@ struct rndis_wext_private {
329 spinlock_t stats_lock; 363 spinlock_t stats_lock;
330 unsigned long work_pending; 364 unsigned long work_pending;
331 365
366 struct ieee80211_supported_band band;
367 struct ieee80211_channel channels[ARRAY_SIZE(rndis_channels)];
368 struct ieee80211_rate rates[ARRAY_SIZE(rndis_rates)];
369
332 struct iw_statistics iwstats; 370 struct iw_statistics iwstats;
333 struct iw_statistics privstats; 371 struct iw_statistics privstats;
334 372
@@ -369,7 +407,8 @@ struct rndis_wext_private {
369}; 407};
370 408
371 409
372static const int rates_80211g[8] = { 6, 9, 12, 18, 24, 36, 48, 54 }; 410struct cfg80211_ops rndis_config_ops = { };
411void *rndis_wiphy_privid = &rndis_wiphy_privid;
373 412
374static const int bcm4320_power_output[4] = { 25, 50, 75, 100 }; 413static const int bcm4320_power_output[4] = { 25, 50, 75, 100 };
375 414
@@ -1151,15 +1190,15 @@ static int rndis_iw_get_range(struct net_device *dev,
1151 /* fill in 802.11g rates */ 1190 /* fill in 802.11g rates */
1152 if (has_80211g_rates) { 1191 if (has_80211g_rates) {
1153 num = range->num_bitrates; 1192 num = range->num_bitrates;
1154 for (i = 0; i < ARRAY_SIZE(rates_80211g); i++) { 1193 for (i = 4; i < ARRAY_SIZE(rndis_rates); i++) {
1155 for (j = 0; j < num; j++) { 1194 for (j = 0; j < num; j++) {
1156 if (range->bitrate[j] == 1195 if (range->bitrate[j] ==
1157 rates_80211g[i] * 1000000) 1196 rndis_rates[i].bitrate * 100000)
1158 break; 1197 break;
1159 } 1198 }
1160 if (j == num) 1199 if (j == num)
1161 range->bitrate[range->num_bitrates++] = 1200 range->bitrate[range->num_bitrates++] =
1162 rates_80211g[i] * 1000000; 1201 rndis_rates[i].bitrate * 100000;
1163 if (range->num_bitrates == IW_MAX_BITRATES) 1202 if (range->num_bitrates == IW_MAX_BITRATES)
1164 break; 1203 break;
1165 } 1204 }
@@ -1204,17 +1243,6 @@ static int rndis_iw_get_range(struct net_device *dev,
1204} 1243}
1205 1244
1206 1245
1207static int rndis_iw_get_name(struct net_device *dev,
1208 struct iw_request_info *info, union iwreq_data *wrqu, char *extra)
1209{
1210 struct usbnet *usbdev = netdev_priv(dev);
1211 struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev);
1212
1213 strcpy(wrqu->name, priv->name);
1214 return 0;
1215}
1216
1217
1218static int rndis_iw_set_essid(struct net_device *dev, 1246static int rndis_iw_set_essid(struct net_device *dev,
1219 struct iw_request_info *info, union iwreq_data *wrqu, char *essid) 1247 struct iw_request_info *info, union iwreq_data *wrqu, char *essid)
1220{ 1248{
@@ -2165,7 +2193,7 @@ static struct iw_statistics *rndis_get_wireless_stats(struct net_device *dev)
2165static const iw_handler rndis_iw_handler[] = 2193static const iw_handler rndis_iw_handler[] =
2166{ 2194{
2167 IW_IOCTL(SIOCSIWCOMMIT) = rndis_iw_commit, 2195 IW_IOCTL(SIOCSIWCOMMIT) = rndis_iw_commit,
2168 IW_IOCTL(SIOCGIWNAME) = rndis_iw_get_name, 2196 IW_IOCTL(SIOCGIWNAME) = (iw_handler) cfg80211_wext_giwname,
2169 IW_IOCTL(SIOCSIWFREQ) = rndis_iw_set_freq, 2197 IW_IOCTL(SIOCSIWFREQ) = rndis_iw_set_freq,
2170 IW_IOCTL(SIOCGIWFREQ) = rndis_iw_get_freq, 2198 IW_IOCTL(SIOCGIWFREQ) = rndis_iw_get_freq,
2171 IW_IOCTL(SIOCSIWMODE) = rndis_iw_set_mode, 2199 IW_IOCTL(SIOCSIWMODE) = rndis_iw_set_mode,
@@ -2338,12 +2366,6 @@ static int rndis_wext_get_caps(struct usbnet *usbdev)
2338 break; 2366 break;
2339 } 2367 }
2340 } 2368 }
2341 if (priv->caps & CAP_MODE_80211A)
2342 strcat(priv->name, "a");
2343 if (priv->caps & CAP_MODE_80211B)
2344 strcat(priv->name, "b");
2345 if (priv->caps & CAP_MODE_80211G)
2346 strcat(priv->name, "g");
2347 } 2369 }
2348 2370
2349 return retval; 2371 return retval;
@@ -2538,20 +2560,28 @@ static const struct net_device_ops rndis_wext_netdev_ops = {
2538 2560
2539static int rndis_wext_bind(struct usbnet *usbdev, struct usb_interface *intf) 2561static int rndis_wext_bind(struct usbnet *usbdev, struct usb_interface *intf)
2540{ 2562{
2563 struct wiphy *wiphy;
2541 struct rndis_wext_private *priv; 2564 struct rndis_wext_private *priv;
2542 int retval, len; 2565 int retval, len;
2543 __le32 tmp; 2566 __le32 tmp;
2544 2567
2545 /* allocate rndis private data */ 2568 /* allocate wiphy and rndis private data
2546 priv = kzalloc(sizeof(struct rndis_wext_private), GFP_KERNEL); 2569 * NOTE: We only support a single virtual interface, so wiphy
2547 if (!priv) 2570 * and wireless_dev are somewhat synonymous for this device.
2571 */
2572 wiphy = wiphy_new(&rndis_config_ops, sizeof(struct rndis_wext_private));
2573 if (!wiphy)
2548 return -ENOMEM; 2574 return -ENOMEM;
2549 2575
2576 priv = wiphy_priv(wiphy);
2577 usbdev->net->ieee80211_ptr = &priv->wdev;
2578 priv->wdev.wiphy = wiphy;
2579 priv->wdev.iftype = NL80211_IFTYPE_STATION;
2580
2550 /* These have to be initialized before calling generic_rndis_bind(). 2581 /* These have to be initialized before calling generic_rndis_bind().
2551 * Otherwise we'll be in big trouble in rndis_wext_early_init(). 2582 * Otherwise we'll be in big trouble in rndis_wext_early_init().
2552 */ 2583 */
2553 usbdev->driver_priv = priv; 2584 usbdev->driver_priv = priv;
2554 strcpy(priv->name, "IEEE802.11");
2555 usbdev->net->wireless_handlers = &rndis_iw_handlers; 2585 usbdev->net->wireless_handlers = &rndis_iw_handlers;
2556 priv->usbdev = usbdev; 2586 priv->usbdev = usbdev;
2557 2587
@@ -2595,7 +2625,31 @@ static int rndis_wext_bind(struct usbnet *usbdev, struct usb_interface *intf)
2595 | IW_QUAL_QUAL_INVALID 2625 | IW_QUAL_QUAL_INVALID
2596 | IW_QUAL_LEVEL_INVALID; 2626 | IW_QUAL_LEVEL_INVALID;
2597 2627
2628 /* fill-out wiphy structure and register w/ cfg80211 */
2629 memcpy(wiphy->perm_addr, usbdev->net->dev_addr, ETH_ALEN);
2630 wiphy->privid = rndis_wiphy_privid;
2631 wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION)
2632 | BIT(NL80211_IFTYPE_ADHOC);
2633 wiphy->max_scan_ssids = 1;
2634
2635 /* TODO: fill-out band information based on priv->caps */
2598 rndis_wext_get_caps(usbdev); 2636 rndis_wext_get_caps(usbdev);
2637
2638 memcpy(priv->channels, rndis_channels, sizeof(rndis_channels));
2639 memcpy(priv->rates, rndis_rates, sizeof(rndis_rates));
2640 priv->band.channels = priv->channels;
2641 priv->band.n_channels = ARRAY_SIZE(rndis_channels);
2642 priv->band.bitrates = priv->rates;
2643 priv->band.n_bitrates = ARRAY_SIZE(rndis_rates);
2644 wiphy->bands[IEEE80211_BAND_2GHZ] = &priv->band;
2645
2646 set_wiphy_dev(wiphy, &usbdev->udev->dev);
2647
2648 if (wiphy_register(wiphy)) {
2649 wiphy_free(wiphy);
2650 return -ENODEV;
2651 }
2652
2599 set_default_iw_params(usbdev); 2653 set_default_iw_params(usbdev);
2600 2654
2601 /* turn radio on */ 2655 /* turn radio on */
@@ -2632,9 +2686,11 @@ static void rndis_wext_unbind(struct usbnet *usbdev, struct usb_interface *intf)
2632 2686
2633 if (priv && priv->wpa_ie_len) 2687 if (priv && priv->wpa_ie_len)
2634 kfree(priv->wpa_ie); 2688 kfree(priv->wpa_ie);
2635 kfree(priv);
2636 2689
2637 rndis_unbind(usbdev, intf); 2690 rndis_unbind(usbdev, intf);
2691
2692 wiphy_unregister(priv->wdev.wiphy);
2693 wiphy_free(priv->wdev.wiphy);
2638} 2694}
2639 2695
2640 2696