aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless
diff options
context:
space:
mode:
authorJussi Kivilinna <jussi.kivilinna@mbnet.fi>2008-01-25 17:51:51 -0500
committerDavid S. Miller <davem@davemloft.net>2008-01-31 22:27:01 -0500
commitbf164cc054d568fa7889ffab41d3b091f5758c75 (patch)
treeb7a9d3000fc73b0e269466c9c3eedebad31f1495 /drivers/net/wireless
parent3692e94f1559523b84a5a0e65929ee84b276e83f (diff)
Add new driver 'rndis_wlan' for wireless RNDIS devices.
New driver for wireless RNDIS devices. So far only known chip that uses wireless RNDIS is Broadcom 4320. Driver detects all RNDIS devices that have RNDIS wireless physical medium. At least following devices are detected: Buffalo WLI-U2-KG125S U.S. Robotics USR5421 Belkin F5D7051 Linksys WUSB54GSv2 Linksys WUSB54GSC Asus WL169gE Eminent EM4045 BT Voyager 1055 Linksys WUSB54GSv1 U.S. Robotics USR5420 BUFFALO WLI-USB-G54 Signed-off-by: Jussi Kivilinna <jussi.kivilinna@mbnet.fi> Signed-off-by: John W. Linville <linville@tuxdriver.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/wireless')
-rw-r--r--drivers/net/wireless/Kconfig28
-rw-r--r--drivers/net/wireless/Makefile2
-rw-r--r--drivers/net/wireless/rndis_wlan.c2757
3 files changed, 2787 insertions, 0 deletions
diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig
index f372960904b2..714a6ca30ad2 100644
--- a/drivers/net/wireless/Kconfig
+++ b/drivers/net/wireless/Kconfig
@@ -545,6 +545,34 @@ config USB_ZD1201
545 To compile this driver as a module, choose M here: the 545 To compile this driver as a module, choose M here: the
546 module will be called zd1201. 546 module will be called zd1201.
547 547
548config USB_NET_RNDIS_WLAN
549 tristate "Wireless RNDIS USB support"
550 depends on USB && WLAN_80211 && EXPERIMENTAL
551 select USB_USBNET
552 select USB_NET_CDCETHER
553 select USB_NET_RNDIS_HOST
554 select WIRELESS_EXT
555 ---help---
556 This is a driver for wireless RNDIS devices.
557 These are USB based adapters found in devices such as:
558
559 Buffalo WLI-U2-KG125S
560 U.S. Robotics USR5421
561 Belkin F5D7051
562 Linksys WUSB54GSv2
563 Linksys WUSB54GSC
564 Asus WL169gE
565 Eminent EM4045
566 BT Voyager 1055
567 Linksys WUSB54GSv1
568 U.S. Robotics USR5420
569 BUFFALO WLI-USB-G54
570
571 All of these devices are based on Broadcom 4320 chip which is the
572 only wireless RNDIS chip known to date.
573
574 If you choose to build a module, it'll be called rndis_wlan.
575
548config RTL8180 576config RTL8180
549 tristate "Realtek 8180/8185 PCI support" 577 tristate "Realtek 8180/8185 PCI support"
550 depends on MAC80211 && PCI && WLAN_80211 && EXPERIMENTAL 578 depends on MAC80211 && PCI && WLAN_80211 && EXPERIMENTAL
diff --git a/drivers/net/wireless/Makefile b/drivers/net/wireless/Makefile
index 6af7b158624e..091dfe2e574e 100644
--- a/drivers/net/wireless/Makefile
+++ b/drivers/net/wireless/Makefile
@@ -44,6 +44,8 @@ obj-$(CONFIG_ZD1211RW) += zd1211rw/
44obj-$(CONFIG_PCMCIA_RAYCS) += ray_cs.o 44obj-$(CONFIG_PCMCIA_RAYCS) += ray_cs.o
45obj-$(CONFIG_PCMCIA_WL3501) += wl3501_cs.o 45obj-$(CONFIG_PCMCIA_WL3501) += wl3501_cs.o
46 46
47obj-$(CONFIG_USB_NET_RNDIS_WLAN) += rndis_wlan.o
48
47obj-$(CONFIG_USB_ZD1201) += zd1201.o 49obj-$(CONFIG_USB_ZD1201) += zd1201.o
48obj-$(CONFIG_LIBERTAS) += libertas/ 50obj-$(CONFIG_LIBERTAS) += libertas/
49 51
diff --git a/drivers/net/wireless/rndis_wlan.c b/drivers/net/wireless/rndis_wlan.c
new file mode 100644
index 000000000000..d3ecf89abd93
--- /dev/null
+++ b/drivers/net/wireless/rndis_wlan.c
@@ -0,0 +1,2757 @@
1/*
2 * Driver for RNDIS based wireless USB devices.
3 *
4 * Copyright (C) 2007 by Bjorge Dijkstra <bjd@jooz.net>
5 * Copyright (C) 2008 by Jussi Kivilinna <jussi.kivilinna@mbnet.fi>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 *
21 * Portions of this file are based on NDISwrapper project,
22 * Copyright (C) 2003-2005 Pontus Fuchs, Giridhar Pemmasani
23 * http://ndiswrapper.sourceforge.net/
24 */
25
26// #define DEBUG // error path messages, extra info
27// #define VERBOSE // more; success messages
28
29#include <linux/module.h>
30#include <linux/init.h>
31#include <linux/netdevice.h>
32#include <linux/etherdevice.h>
33#include <linux/ethtool.h>
34#include <linux/workqueue.h>
35#include <linux/mutex.h>
36#include <linux/mii.h>
37#include <linux/usb.h>
38#include <linux/usb/cdc.h>
39#include <linux/wireless.h>
40#include <linux/if_arp.h>
41#include <linux/ctype.h>
42#include <linux/spinlock.h>
43#include <net/iw_handler.h>
44#include <net/ieee80211.h>
45#include <linux/usb/usbnet.h>
46#include <linux/usb/rndis_host.h>
47
48
49/* NOTE: All these are settings for Broadcom chipset */
50static char modparam_country[4] = "EU";
51module_param_string(country, modparam_country, 4, 0444);
52MODULE_PARM_DESC(country, "Country code (ISO 3166-1 alpha-2), default: EU");
53
54static int modparam_frameburst = 1;
55module_param_named(frameburst, modparam_frameburst, int, 0444);
56MODULE_PARM_DESC(frameburst, "enable frame bursting (default: on)");
57
58static int modparam_afterburner = 0;
59module_param_named(afterburner, modparam_afterburner, int, 0444);
60MODULE_PARM_DESC(afterburner,
61 "enable afterburner aka '125 High Speed Mode' (default: off)");
62
63static int modparam_power_save = 0;
64module_param_named(power_save, modparam_power_save, int, 0444);
65MODULE_PARM_DESC(power_save,
66 "set power save mode: 0=off, 1=on, 2=fast (default: off)");
67
68static int modparam_power_output = 3;
69module_param_named(power_output, modparam_power_output, int, 0444);
70MODULE_PARM_DESC(power_output,
71 "set power output: 0=25%, 1=50%, 2=75%, 3=100% (default: 100%)");
72
73static int modparam_roamtrigger = -70;
74module_param_named(roamtrigger, modparam_roamtrigger, int, 0444);
75MODULE_PARM_DESC(roamtrigger,
76 "set roaming dBm trigger: -80=optimize for distance, "
77 "-60=bandwidth (default: -70)");
78
79static int modparam_roamdelta = 1;
80module_param_named(roamdelta, modparam_roamdelta, int, 0444);
81MODULE_PARM_DESC(roamdelta,
82 "set roaming tendency: 0=aggressive, 1=moderate, "
83 "2=conservative (default: moderate)");
84
85static int modparam_workaround_interval = 500;
86module_param_named(workaround_interval, modparam_workaround_interval,
87 int, 0444);
88MODULE_PARM_DESC(workaround_interval,
89 "set stall workaround interval in msecs (default: 500)");
90
91
92/* various RNDIS OID defs */
93#define OID_GEN_LINK_SPEED ccpu2(0x00010107)
94#define OID_GEN_RNDIS_CONFIG_PARAMETER ccpu2(0x0001021b)
95
96#define OID_GEN_XMIT_OK ccpu2(0x00020101)
97#define OID_GEN_RCV_OK ccpu2(0x00020102)
98#define OID_GEN_XMIT_ERROR ccpu2(0x00020103)
99#define OID_GEN_RCV_ERROR ccpu2(0x00020104)
100#define OID_GEN_RCV_NO_BUFFER ccpu2(0x00020105)
101
102#define OID_802_3_PERMANENT_ADDRESS ccpu2(0x01010101)
103#define OID_802_3_CURRENT_ADDRESS ccpu2(0x01010102)
104#define OID_802_3_MULTICAST_LIST ccpu2(0x01010103)
105#define OID_802_3_MAXIMUM_LIST_SIZE ccpu2(0x01010104)
106
107#define OID_802_11_BSSID ccpu2(0x0d010101)
108#define OID_802_11_SSID ccpu2(0x0d010102)
109#define OID_802_11_INFRASTRUCTURE_MODE ccpu2(0x0d010108)
110#define OID_802_11_ADD_WEP ccpu2(0x0d010113)
111#define OID_802_11_REMOVE_WEP ccpu2(0x0d010114)
112#define OID_802_11_DISASSOCIATE ccpu2(0x0d010115)
113#define OID_802_11_AUTHENTICATION_MODE ccpu2(0x0d010118)
114#define OID_802_11_PRIVACY_FILTER ccpu2(0x0d010119)
115#define OID_802_11_BSSID_LIST_SCAN ccpu2(0x0d01011a)
116#define OID_802_11_ENCRYPTION_STATUS ccpu2(0x0d01011b)
117#define OID_802_11_ADD_KEY ccpu2(0x0d01011d)
118#define OID_802_11_REMOVE_KEY ccpu2(0x0d01011e)
119#define OID_802_11_PMKID ccpu2(0x0d010123)
120#define OID_802_11_NETWORK_TYPES_SUPPORTED ccpu2(0x0d010203)
121#define OID_802_11_NETWORK_TYPE_IN_USE ccpu2(0x0d010204)
122#define OID_802_11_TX_POWER_LEVEL ccpu2(0x0d010205)
123#define OID_802_11_RSSI ccpu2(0x0d010206)
124#define OID_802_11_RSSI_TRIGGER ccpu2(0x0d010207)
125#define OID_802_11_FRAGMENTATION_THRESHOLD ccpu2(0x0d010209)
126#define OID_802_11_RTS_THRESHOLD ccpu2(0x0d01020a)
127#define OID_802_11_SUPPORTED_RATES ccpu2(0x0d01020e)
128#define OID_802_11_CONFIGURATION ccpu2(0x0d010211)
129#define OID_802_11_BSSID_LIST ccpu2(0x0d010217)
130
131
132/* Typical noise/maximum signal level values taken from ndiswrapper iw_ndis.h */
133#define WL_NOISE -96 /* typical noise level in dBm */
134#define WL_SIGMAX -32 /* typical maximum signal level in dBm */
135
136
137/* Assume that Broadcom 4320 (only chipset at time of writing known to be
138 * based on wireless rndis) has default txpower of 13dBm.
139 * This value is from Linksys WUSB54GSC User Guide, Appendix F: Specifications.
140 * 13dBm == 19.9mW
141 */
142#define BCM4320_DEFAULT_TXPOWER 20
143
144
145/* codes for "status" field of completion messages */
146#define RNDIS_STATUS_ADAPTER_NOT_READY ccpu2(0xc0010011)
147#define RNDIS_STATUS_ADAPTER_NOT_OPEN ccpu2(0xc0010012)
148
149
150/* NDIS data structures. Taken from wpa_supplicant driver_ndis.c
151 * slightly modified for datatype endianess, etc
152 */
153#define NDIS_802_11_LENGTH_SSID 32
154#define NDIS_802_11_LENGTH_RATES 8
155#define NDIS_802_11_LENGTH_RATES_EX 16
156
157struct NDIS_802_11_SSID {
158 __le32 SsidLength;
159 u8 Ssid[NDIS_802_11_LENGTH_SSID];
160} __attribute__((packed));
161
162enum NDIS_802_11_NETWORK_TYPE {
163 Ndis802_11FH,
164 Ndis802_11DS,
165 Ndis802_11OFDM5,
166 Ndis802_11OFDM24,
167 Ndis802_11NetworkTypeMax
168};
169
170struct NDIS_802_11_CONFIGURATION_FH {
171 __le32 Length;
172 __le32 HopPattern;
173 __le32 HopSet;
174 __le32 DwellTime;
175} __attribute__((packed));
176
177struct NDIS_802_11_CONFIGURATION {
178 __le32 Length;
179 __le32 BeaconPeriod;
180 __le32 ATIMWindow;
181 __le32 DSConfig;
182 struct NDIS_802_11_CONFIGURATION_FH FHConfig;
183} __attribute__((packed));
184
185enum NDIS_802_11_NETWORK_INFRASTRUCTURE {
186 Ndis802_11IBSS,
187 Ndis802_11Infrastructure,
188 Ndis802_11AutoUnknown,
189 Ndis802_11InfrastructureMax
190};
191
192enum NDIS_802_11_AUTHENTICATION_MODE {
193 Ndis802_11AuthModeOpen,
194 Ndis802_11AuthModeShared,
195 Ndis802_11AuthModeAutoSwitch,
196 Ndis802_11AuthModeWPA,
197 Ndis802_11AuthModeWPAPSK,
198 Ndis802_11AuthModeWPANone,
199 Ndis802_11AuthModeWPA2,
200 Ndis802_11AuthModeWPA2PSK,
201 Ndis802_11AuthModeMax
202};
203
204enum NDIS_802_11_ENCRYPTION_STATUS {
205 Ndis802_11WEPEnabled,
206 Ndis802_11Encryption1Enabled = Ndis802_11WEPEnabled,
207 Ndis802_11WEPDisabled,
208 Ndis802_11EncryptionDisabled = Ndis802_11WEPDisabled,
209 Ndis802_11WEPKeyAbsent,
210 Ndis802_11Encryption1KeyAbsent = Ndis802_11WEPKeyAbsent,
211 Ndis802_11WEPNotSupported,
212 Ndis802_11EncryptionNotSupported = Ndis802_11WEPNotSupported,
213 Ndis802_11Encryption2Enabled,
214 Ndis802_11Encryption2KeyAbsent,
215 Ndis802_11Encryption3Enabled,
216 Ndis802_11Encryption3KeyAbsent
217};
218
219enum NDIS_802_11_PRIVACY_FILTER {
220 Ndis802_11PrivFilterAcceptAll,
221 Ndis802_11PrivFilter8021xWEP
222};
223
224struct NDIS_WLAN_BSSID_EX {
225 __le32 Length;
226 u8 MacAddress[6];
227 u8 Padding[2];
228 struct NDIS_802_11_SSID Ssid;
229 __le32 Privacy;
230 __le32 Rssi;
231 enum NDIS_802_11_NETWORK_TYPE NetworkTypeInUse;
232 struct NDIS_802_11_CONFIGURATION Configuration;
233 enum NDIS_802_11_NETWORK_INFRASTRUCTURE InfrastructureMode;
234 u8 SupportedRates[NDIS_802_11_LENGTH_RATES_EX];
235 __le32 IELength;
236 u8 IEs[0];
237} __attribute__((packed));
238
239struct NDIS_802_11_BSSID_LIST_EX {
240 __le32 NumberOfItems;
241 struct NDIS_WLAN_BSSID_EX Bssid[0];
242} __attribute__((packed));
243
244struct NDIS_802_11_FIXED_IEs {
245 u8 Timestamp[8];
246 __le16 BeaconInterval;
247 __le16 Capabilities;
248} __attribute__((packed));
249
250struct NDIS_802_11_WEP {
251 __le32 Length;
252 __le32 KeyIndex;
253 __le32 KeyLength;
254 u8 KeyMaterial[32];
255} __attribute__((packed));
256
257struct NDIS_802_11_KEY {
258 __le32 Length;
259 __le32 KeyIndex;
260 __le32 KeyLength;
261 u8 Bssid[6];
262 u8 Padding[6];
263 __le64 KeyRSC;
264 u8 KeyMaterial[32];
265} __attribute__((packed));
266
267struct NDIS_802_11_REMOVE_KEY {
268 __le32 Length;
269 __le32 KeyIndex;
270 u8 Bssid[6];
271} __attribute__((packed));
272
273struct RNDIS_CONFIG_PARAMETER_INFOBUFFER {
274 __le32 ParameterNameOffset;
275 __le32 ParameterNameLength;
276 __le32 ParameterType;
277 __le32 ParameterValueOffset;
278 __le32 ParameterValueLength;
279} __attribute__((packed));
280
281/* these have to match what is in wpa_supplicant */
282enum { WPA_ALG_NONE, WPA_ALG_WEP, WPA_ALG_TKIP, WPA_ALG_CCMP } wpa_alg;
283enum { CIPHER_NONE, CIPHER_WEP40, CIPHER_TKIP, CIPHER_CCMP, CIPHER_WEP104 }
284 wpa_cipher;
285enum { KEY_MGMT_802_1X, KEY_MGMT_PSK, KEY_MGMT_NONE, KEY_MGMT_802_1X_NO_WPA,
286 KEY_MGMT_WPA_NONE } wpa_key_mgmt;
287
288/*
289 * private data
290 */
291#define NET_TYPE_11FB 0
292
293#define CAP_MODE_80211A 1
294#define CAP_MODE_80211B 2
295#define CAP_MODE_80211G 4
296#define CAP_MODE_MASK 7
297#define CAP_SUPPORT_TXPOWER 8
298
299#define WORK_CONNECTION_EVENT (1<<0)
300#define WORK_SET_MULTICAST_LIST (1<<1)
301
302/* RNDIS device private data */
303struct rndis_wext_private {
304 char name[32];
305
306 struct usbnet *usbdev;
307
308 struct workqueue_struct *workqueue;
309 struct delayed_work stats_work;
310 struct work_struct work;
311 struct mutex command_lock;
312 spinlock_t stats_lock;
313 unsigned long work_pending;
314
315 struct iw_statistics iwstats;
316 struct iw_statistics privstats;
317
318 int nick_len;
319 char nick[32];
320
321 int caps;
322 int multicast_size;
323
324 /* module parameters */
325 char param_country[4];
326 int param_frameburst;
327 int param_afterburner;
328 int param_power_save;
329 int param_power_output;
330 int param_roamtrigger;
331 int param_roamdelta;
332 u32 param_workaround_interval;
333
334 /* hardware state */
335 int radio_on;
336 int infra_mode;
337 struct NDIS_802_11_SSID essid;
338
339 /* encryption stuff */
340 int encr_tx_key_index;
341 char encr_keys[4][32];
342 int encr_key_len[4];
343 int wpa_version;
344 int wpa_keymgmt;
345 int wpa_authalg;
346 int wpa_ie_len;
347 u8 *wpa_ie;
348 int wpa_cipher_pair;
349 int wpa_cipher_group;
350};
351
352
353static const int freq_chan[] = { 2412, 2417, 2422, 2427, 2432, 2437, 2442,
354 2447, 2452, 2457, 2462, 2467, 2472, 2484 };
355
356static const int rates_80211g[8] = { 6, 9, 12, 18, 24, 36, 48, 54 };
357
358static const int bcm4320_power_output[4] = { 25, 50, 75, 100 };
359
360static const unsigned char zero_bssid[ETH_ALEN] = {0,};
361static const unsigned char ffff_bssid[ETH_ALEN] = { 0xff, 0xff, 0xff,
362 0xff, 0xff, 0xff };
363
364
365static struct rndis_wext_private *get_rndis_wext_priv(struct usbnet *dev)
366{
367 return (struct rndis_wext_private *)dev->driver_priv;
368}
369
370
371static u32 get_bcm4320_power(struct rndis_wext_private *priv)
372{
373 return BCM4320_DEFAULT_TXPOWER *
374 bcm4320_power_output[priv->param_power_output] / 100;
375}
376
377
378/* translate error code */
379static int rndis_error_status(__le32 rndis_status)
380{
381 int ret = -EINVAL;
382 switch (rndis_status) {
383 case RNDIS_STATUS_SUCCESS:
384 ret = 0;
385 break;
386 case RNDIS_STATUS_FAILURE:
387 case RNDIS_STATUS_INVALID_DATA:
388 ret = -EINVAL;
389 break;
390 case RNDIS_STATUS_NOT_SUPPORTED:
391 ret = -EOPNOTSUPP;
392 break;
393 case RNDIS_STATUS_ADAPTER_NOT_READY:
394 case RNDIS_STATUS_ADAPTER_NOT_OPEN:
395 ret = -EBUSY;
396 break;
397 }
398 return ret;
399}
400
401
402static int rndis_query_oid(struct usbnet *dev, __le32 oid, void *data, int *len)
403{
404 struct rndis_wext_private *priv = get_rndis_wext_priv(dev);
405 union {
406 void *buf;
407 struct rndis_msg_hdr *header;
408 struct rndis_query *get;
409 struct rndis_query_c *get_c;
410 } u;
411 int ret, buflen;
412
413 buflen = *len + sizeof(*u.get);
414 if (buflen < CONTROL_BUFFER_SIZE)
415 buflen = CONTROL_BUFFER_SIZE;
416 u.buf = kmalloc(buflen, GFP_KERNEL);
417 if (!u.buf)
418 return -ENOMEM;
419 memset(u.get, 0, sizeof *u.get);
420 u.get->msg_type = RNDIS_MSG_QUERY;
421 u.get->msg_len = ccpu2(sizeof *u.get);
422 u.get->oid = oid;
423
424 mutex_lock(&priv->command_lock);
425 ret = rndis_command(dev, u.header);
426 mutex_unlock(&priv->command_lock);
427
428 if (ret == 0) {
429 ret = le32_to_cpu(u.get_c->len);
430 *len = (*len > ret) ? ret : *len;
431 memcpy(data, u.buf + le32_to_cpu(u.get_c->offset) + 8, *len);
432 ret = rndis_error_status(u.get_c->status);
433 }
434
435 kfree(u.buf);
436 return ret;
437}
438
439
440static int rndis_set_oid(struct usbnet *dev, __le32 oid, void *data, int len)
441{
442 struct rndis_wext_private *priv = get_rndis_wext_priv(dev);
443 union {
444 void *buf;
445 struct rndis_msg_hdr *header;
446 struct rndis_set *set;
447 struct rndis_set_c *set_c;
448 } u;
449 int ret, buflen;
450
451 buflen = len + sizeof(*u.set);
452 if (buflen < CONTROL_BUFFER_SIZE)
453 buflen = CONTROL_BUFFER_SIZE;
454 u.buf = kmalloc(buflen, GFP_KERNEL);
455 if (!u.buf)
456 return -ENOMEM;
457
458 memset(u.set, 0, sizeof *u.set);
459 u.set->msg_type = RNDIS_MSG_SET;
460 u.set->msg_len = cpu_to_le32(sizeof(*u.set) + len);
461 u.set->oid = oid;
462 u.set->len = cpu_to_le32(len);
463 u.set->offset = ccpu2(sizeof(*u.set) - 8);
464 u.set->handle = ccpu2(0);
465 memcpy(u.buf + sizeof(*u.set), data, len);
466
467 mutex_lock(&priv->command_lock);
468 ret = rndis_command(dev, u.header);
469 mutex_unlock(&priv->command_lock);
470
471 if (ret == 0)
472 ret = rndis_error_status(u.set_c->status);
473
474 kfree(u.buf);
475 return ret;
476}
477
478
479/*
480 * Specs say that we can only set config parameters only soon after device
481 * initialization.
482 * value_type: 0 = u32, 2 = unicode string
483 */
484static int rndis_set_config_parameter(struct usbnet *dev, char *param,
485 int value_type, void *value)
486{
487 struct RNDIS_CONFIG_PARAMETER_INFOBUFFER *infobuf;
488 int value_len, info_len, param_len, ret, i;
489 __le16 *unibuf;
490 __le32 *dst_value;
491
492 if (value_type == 0)
493 value_len = sizeof(__le32);
494 else if (value_type == 2)
495 value_len = strlen(value) * sizeof(__le16);
496 else
497 return -EINVAL;
498
499 param_len = strlen(param) * sizeof(__le16);
500 info_len = sizeof(*infobuf) + param_len + value_len;
501
502#ifdef DEBUG
503 info_len += 12;
504#endif
505 infobuf = kmalloc(info_len, GFP_KERNEL);
506 if (!infobuf)
507 return -ENOMEM;
508
509#ifdef DEBUG
510 info_len -= 12;
511 /* extra 12 bytes are for padding (debug output) */
512 memset(infobuf, 0xCC, info_len + 12);
513#endif
514
515 if (value_type == 2)
516 devdbg(dev, "setting config parameter: %s, value: %s",
517 param, (u8 *)value);
518 else
519 devdbg(dev, "setting config parameter: %s, value: %d",
520 param, *(u32 *)value);
521
522 infobuf->ParameterNameOffset = cpu_to_le32(sizeof(*infobuf));
523 infobuf->ParameterNameLength = cpu_to_le32(param_len);
524 infobuf->ParameterType = cpu_to_le32(value_type);
525 infobuf->ParameterValueOffset = cpu_to_le32(sizeof(*infobuf) +
526 param_len);
527 infobuf->ParameterValueLength = cpu_to_le32(value_len);
528
529 /* simple string to unicode string conversion */
530 unibuf = (void *)infobuf + sizeof(*infobuf);
531 for (i = 0; i < param_len / sizeof(__le16); i++)
532 unibuf[i] = cpu_to_le16(param[i]);
533
534 if (value_type == 2) {
535 unibuf = (void *)infobuf + sizeof(*infobuf) + param_len;
536 for (i = 0; i < value_len / sizeof(__le16); i++)
537 unibuf[i] = cpu_to_le16(((u8 *)value)[i]);
538 } else {
539 dst_value = (void *)infobuf + sizeof(*infobuf) + param_len;
540 *dst_value = cpu_to_le32(*(u32 *)value);
541 }
542
543#ifdef DEBUG
544 devdbg(dev, "info buffer (len: %d):", info_len);
545 for (i = 0; i < info_len; i += 12) {
546 u32 *tmp = (u32 *)((u8 *)infobuf + i);
547 devdbg(dev, "%08X:%08X:%08X",
548 cpu_to_be32(tmp[0]),
549 cpu_to_be32(tmp[1]),
550 cpu_to_be32(tmp[2]));
551 }
552#endif
553
554 ret = rndis_set_oid(dev, OID_GEN_RNDIS_CONFIG_PARAMETER,
555 infobuf, info_len);
556 if (ret != 0)
557 devdbg(dev, "setting rndis config paramater failed, %d.", ret);
558
559 kfree(infobuf);
560 return ret;
561}
562
563static int rndis_set_config_parameter_str(struct usbnet *dev,
564 char *param, char *value)
565{
566 return(rndis_set_config_parameter(dev, param, 2, value));
567}
568
569/*static int rndis_set_config_parameter_u32(struct usbnet *dev,
570 char *param, u32 value)
571{
572 return(rndis_set_config_parameter(dev, param, 0, &value));
573}*/
574
575
576/*
577 * data conversion functions
578 */
579static int level_to_qual(int level)
580{
581 int qual = 100 * (level - WL_NOISE) / (WL_SIGMAX - WL_NOISE);
582 return qual >= 0 ? (qual <= 100 ? qual : 100) : 0;
583}
584
585
586static void dsconfig_to_freq(unsigned int dsconfig, struct iw_freq *freq)
587{
588 freq->e = 0;
589 freq->i = 0;
590 freq->flags = 0;
591
592 /* see comment in wireless.h above the "struct iw_freq"
593 * definition for an explanation of this if
594 * NOTE: 1000000 is due to the kHz
595 */
596 if (dsconfig > 1000000) {
597 freq->m = dsconfig / 10;
598 freq->e = 1;
599 } else
600 freq->m = dsconfig;
601
602 /* convert from kHz to Hz */
603 freq->e += 3;
604}
605
606
607static int freq_to_dsconfig(struct iw_freq *freq, unsigned int *dsconfig)
608{
609 if (freq->m < 1000 && freq->e == 0) {
610 if (freq->m >= 1 &&
611 freq->m <= (sizeof(freq_chan) / sizeof(freq_chan[0])))
612 *dsconfig = freq_chan[freq->m - 1] * 1000;
613 else
614 return -1;
615 } else {
616 int i;
617 *dsconfig = freq->m;
618 for (i = freq->e; i > 0; i--)
619 *dsconfig *= 10;
620 *dsconfig /= 1000;
621 }
622
623 return 0;
624}
625
626
627/*
628 * common functions
629 */
630static int
631add_wep_key(struct usbnet *usbdev, char *key, int key_len, int index);
632
633static int get_essid(struct usbnet *usbdev, struct NDIS_802_11_SSID *ssid)
634{
635 int ret, len;
636
637 len = sizeof(*ssid);
638 ret = rndis_query_oid(usbdev, OID_802_11_SSID, ssid, &len);
639
640 if (ret != 0)
641 ssid->SsidLength = 0;
642
643#ifdef DEBUG
644 {
645 unsigned char tmp[NDIS_802_11_LENGTH_SSID + 1];
646
647 memcpy(tmp, ssid->Ssid, le32_to_cpu(ssid->SsidLength));
648 tmp[le32_to_cpu(ssid->SsidLength)] = 0;
649 devdbg(usbdev, "get_essid: '%s', ret: %d", tmp, ret);
650 }
651#endif
652 return ret;
653}
654
655
656static int set_essid(struct usbnet *usbdev, struct NDIS_802_11_SSID *ssid)
657{
658 struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev);
659 int ret;
660
661 ret = rndis_set_oid(usbdev, OID_802_11_SSID, ssid, sizeof(*ssid));
662 if (ret == 0) {
663 memcpy(&priv->essid, ssid, sizeof(priv->essid));
664 priv->radio_on = 1;
665 devdbg(usbdev, "set_essid: radio_on = 1");
666 }
667
668 return ret;
669}
670
671
672static int get_bssid(struct usbnet *usbdev, u8 bssid[ETH_ALEN])
673{
674 int ret, len;
675
676 len = ETH_ALEN;
677 ret = rndis_query_oid(usbdev, OID_802_11_BSSID, bssid, &len);
678
679 if (ret != 0)
680 memset(bssid, 0, ETH_ALEN);
681
682 return ret;
683}
684
685
686static int is_associated(struct usbnet *usbdev)
687{
688 u8 bssid[ETH_ALEN];
689 int ret;
690
691 ret = get_bssid(usbdev, bssid);
692
693 return(ret == 0 && memcmp(bssid, zero_bssid, ETH_ALEN) != 0);
694}
695
696
697static int disassociate(struct usbnet *usbdev, int reset_ssid)
698{
699 struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev);
700 struct NDIS_802_11_SSID ssid;
701 int i, ret = 0;
702
703 if (priv->radio_on) {
704 ret = rndis_set_oid(usbdev, OID_802_11_DISASSOCIATE, NULL, 0);
705 if (ret == 0) {
706 priv->radio_on = 0;
707 devdbg(usbdev, "disassociate: radio_on = 0");
708
709 if (reset_ssid)
710 msleep(100);
711 }
712 }
713
714 /* disassociate causes radio to be turned off; if reset_ssid
715 * is given, set random ssid to enable radio */
716 if (reset_ssid) {
717 ssid.SsidLength = cpu_to_le32(sizeof(ssid.Ssid));
718 get_random_bytes(&ssid.Ssid[2], sizeof(ssid.Ssid)-2);
719 ssid.Ssid[0] = 0x1;
720 ssid.Ssid[1] = 0xff;
721 for (i = 2; i < sizeof(ssid.Ssid); i++)
722 ssid.Ssid[i] = 0x1 + (ssid.Ssid[i] * 0xfe / 0xff);
723 ret = set_essid(usbdev, &ssid);
724 }
725 return ret;
726}
727
728
729static int set_auth_mode(struct usbnet *usbdev, int wpa_version, int authalg)
730{
731 struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev);
732 __le32 tmp;
733 int auth_mode, ret;
734
735 devdbg(usbdev, "set_auth_mode: wpa_version=0x%x authalg=0x%x "
736 "keymgmt=0x%x", wpa_version, authalg, priv->wpa_keymgmt);
737
738 if (wpa_version & IW_AUTH_WPA_VERSION_WPA2) {
739 if (priv->wpa_keymgmt & IW_AUTH_KEY_MGMT_802_1X)
740 auth_mode = Ndis802_11AuthModeWPA2;
741 else
742 auth_mode = Ndis802_11AuthModeWPA2PSK;
743 } else if (wpa_version & IW_AUTH_WPA_VERSION_WPA) {
744 if (priv->wpa_keymgmt & IW_AUTH_KEY_MGMT_802_1X)
745 auth_mode = Ndis802_11AuthModeWPA;
746 else if (priv->wpa_keymgmt & IW_AUTH_KEY_MGMT_PSK)
747 auth_mode = Ndis802_11AuthModeWPAPSK;
748 else
749 auth_mode = Ndis802_11AuthModeWPANone;
750 } else if (authalg & IW_AUTH_ALG_SHARED_KEY) {
751 if (authalg & IW_AUTH_ALG_OPEN_SYSTEM)
752 auth_mode = Ndis802_11AuthModeAutoSwitch;
753 else
754 auth_mode = Ndis802_11AuthModeShared;
755 } else
756 auth_mode = Ndis802_11AuthModeOpen;
757
758 tmp = cpu_to_le32(auth_mode);
759 ret = rndis_set_oid(usbdev, OID_802_11_AUTHENTICATION_MODE, &tmp,
760 sizeof(tmp));
761 if (ret != 0) {
762 devwarn(usbdev, "setting auth mode failed (%08X)", ret);
763 return ret;
764 }
765
766 priv->wpa_version = wpa_version;
767 priv->wpa_authalg = authalg;
768 return 0;
769}
770
771
772static int set_priv_filter(struct usbnet *usbdev)
773{
774 struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev);
775 __le32 tmp;
776
777 devdbg(usbdev, "set_priv_filter: wpa_version=0x%x", priv->wpa_version);
778
779 if (priv->wpa_version & IW_AUTH_WPA_VERSION_WPA2 ||
780 priv->wpa_version & IW_AUTH_WPA_VERSION_WPA)
781 tmp = cpu_to_le32(Ndis802_11PrivFilter8021xWEP);
782 else
783 tmp = cpu_to_le32(Ndis802_11PrivFilterAcceptAll);
784
785 return rndis_set_oid(usbdev, OID_802_11_PRIVACY_FILTER, &tmp,
786 sizeof(tmp));
787}
788
789
790static int set_encr_mode(struct usbnet *usbdev, int pairwise, int groupwise)
791{
792 struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev);
793 __le32 tmp;
794 int encr_mode, ret;
795
796 devdbg(usbdev, "set_encr_mode: cipher_pair=0x%x cipher_group=0x%x",
797 pairwise,
798 groupwise);
799
800 if (pairwise & IW_AUTH_CIPHER_CCMP)
801 encr_mode = Ndis802_11Encryption3Enabled;
802 else if (pairwise & IW_AUTH_CIPHER_TKIP)
803 encr_mode = Ndis802_11Encryption2Enabled;
804 else if (pairwise &
805 (IW_AUTH_CIPHER_WEP40 | IW_AUTH_CIPHER_WEP104))
806 encr_mode = Ndis802_11Encryption1Enabled;
807 else if (groupwise & IW_AUTH_CIPHER_CCMP)
808 encr_mode = Ndis802_11Encryption3Enabled;
809 else if (groupwise & IW_AUTH_CIPHER_TKIP)
810 encr_mode = Ndis802_11Encryption2Enabled;
811 else
812 encr_mode = Ndis802_11EncryptionDisabled;
813
814 tmp = cpu_to_le32(encr_mode);
815 ret = rndis_set_oid(usbdev, OID_802_11_ENCRYPTION_STATUS, &tmp,
816 sizeof(tmp));
817 if (ret != 0) {
818 devwarn(usbdev, "setting encr mode failed (%08X)", ret);
819 return ret;
820 }
821
822 priv->wpa_cipher_pair = pairwise;
823 priv->wpa_cipher_group = groupwise;
824 return 0;
825}
826
827
828static int set_assoc_params(struct usbnet *usbdev)
829{
830 struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev);
831
832 set_auth_mode(usbdev, priv->wpa_version, priv->wpa_authalg);
833 set_priv_filter(usbdev);
834 set_encr_mode(usbdev, priv->wpa_cipher_pair, priv->wpa_cipher_group);
835
836 return 0;
837}
838
839
840static int set_infra_mode(struct usbnet *usbdev, int mode)
841{
842 struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev);
843 __le32 tmp;
844 int ret, i;
845
846 devdbg(usbdev, "set_infra_mode: infra_mode=0x%x", priv->infra_mode);
847
848 tmp = cpu_to_le32(mode);
849 ret = rndis_set_oid(usbdev, OID_802_11_INFRASTRUCTURE_MODE, &tmp,
850 sizeof(tmp));
851 if (ret != 0) {
852 devwarn(usbdev, "setting infra mode failed (%08X)", ret);
853 return ret;
854 }
855
856 /* NDIS drivers clear keys when infrastructure mode is
857 * changed. But Linux tools assume otherwise. So set the
858 * keys */
859 if (priv->wpa_keymgmt == 0 ||
860 priv->wpa_keymgmt == IW_AUTH_KEY_MGMT_802_1X) {
861 for (i = 0; i < 4; i++) {
862 if (priv->encr_key_len[i] > 0)
863 add_wep_key(usbdev, priv->encr_keys[i],
864 priv->encr_key_len[i], i);
865 }
866 }
867
868 priv->infra_mode = mode;
869 return 0;
870}
871
872
873static void set_default_iw_params(struct usbnet *usbdev)
874{
875 struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev);
876
877 priv->wpa_keymgmt = 0;
878 priv->wpa_version = 0;
879
880 set_infra_mode(usbdev, Ndis802_11Infrastructure);
881 set_auth_mode(usbdev, IW_AUTH_WPA_VERSION_DISABLED,
882 IW_AUTH_ALG_OPEN_SYSTEM);
883 set_priv_filter(usbdev);
884 set_encr_mode(usbdev, IW_AUTH_CIPHER_NONE, IW_AUTH_CIPHER_NONE);
885}
886
887
888static int deauthenticate(struct usbnet *usbdev)
889{
890 int ret;
891
892 ret = disassociate(usbdev, 1);
893 set_default_iw_params(usbdev);
894 return ret;
895}
896
897
898/* index must be 0 - N, as per NDIS */
899static int add_wep_key(struct usbnet *usbdev, char *key, int key_len, int index)
900{
901 struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev);
902 struct NDIS_802_11_WEP ndis_key;
903 int ret;
904
905 if (key_len <= 0 || key_len > 32 || index < 0 || index >= 4)
906 return -EINVAL;
907
908 memset(&ndis_key, 0, sizeof(ndis_key));
909
910 ndis_key.Length = cpu_to_le32(sizeof(ndis_key));
911 ndis_key.KeyLength = cpu_to_le32(key_len);
912 ndis_key.KeyIndex = cpu_to_le32(index);
913 memcpy(&ndis_key.KeyMaterial, key, key_len);
914
915 if (index == priv->encr_tx_key_index) {
916 ndis_key.KeyIndex |= cpu_to_le32(1 << 31);
917 ret = set_encr_mode(usbdev, IW_AUTH_CIPHER_WEP104,
918 IW_AUTH_CIPHER_NONE);
919 if (ret)
920 devwarn(usbdev, "encryption couldn't be enabled (%08X)",
921 ret);
922 }
923
924 ret = rndis_set_oid(usbdev, OID_802_11_ADD_WEP, &ndis_key,
925 sizeof(ndis_key));
926 if (ret != 0) {
927 devwarn(usbdev, "adding encryption key %d failed (%08X)",
928 index+1, ret);
929 return ret;
930 }
931
932 priv->encr_key_len[index] = key_len;
933 memcpy(&priv->encr_keys[index], key, key_len);
934
935 return 0;
936}
937
938
939/* remove_key is for both wep and wpa */
940static int remove_key(struct usbnet *usbdev, int index, u8 bssid[ETH_ALEN])
941{
942 struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev);
943 struct NDIS_802_11_REMOVE_KEY remove_key;
944 __le32 keyindex;
945 int ret;
946
947 if (priv->encr_key_len[index] == 0)
948 return 0;
949
950 priv->encr_key_len[index] = 0;
951 memset(&priv->encr_keys[index], 0, sizeof(priv->encr_keys[index]));
952
953 if (priv->wpa_cipher_pair == IW_AUTH_CIPHER_TKIP ||
954 priv->wpa_cipher_pair == IW_AUTH_CIPHER_CCMP ||
955 priv->wpa_cipher_group == IW_AUTH_CIPHER_TKIP ||
956 priv->wpa_cipher_group == IW_AUTH_CIPHER_CCMP) {
957 remove_key.Length = cpu_to_le32(sizeof(remove_key));
958 remove_key.KeyIndex = cpu_to_le32(index);
959 if (bssid) {
960 /* pairwise key */
961 if (memcmp(bssid, ffff_bssid, ETH_ALEN) != 0)
962 remove_key.KeyIndex |= cpu_to_le32(1 << 30);
963 memcpy(remove_key.Bssid, bssid,
964 sizeof(remove_key.Bssid));
965 } else
966 memset(remove_key.Bssid, 0xff,
967 sizeof(remove_key.Bssid));
968
969 ret = rndis_set_oid(usbdev, OID_802_11_REMOVE_KEY, &remove_key,
970 sizeof(remove_key));
971 if (ret != 0)
972 return ret;
973 } else {
974 keyindex = cpu_to_le32(index);
975 ret = rndis_set_oid(usbdev, OID_802_11_REMOVE_WEP, &keyindex,
976 sizeof(keyindex));
977 if (ret != 0) {
978 devwarn(usbdev,
979 "removing encryption key %d failed (%08X)",
980 index, ret);
981 return ret;
982 }
983 }
984
985 /* if it is transmit key, disable encryption */
986 if (index == priv->encr_tx_key_index)
987 set_encr_mode(usbdev, IW_AUTH_CIPHER_NONE, IW_AUTH_CIPHER_NONE);
988
989 return 0;
990}
991
992
993static void set_multicast_list(struct usbnet *usbdev)
994{
995 struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev);
996 struct dev_mc_list *mclist;
997 __le32 filter;
998 int ret, i, size;
999 char *buf;
1000
1001 filter = RNDIS_PACKET_TYPE_DIRECTED | RNDIS_PACKET_TYPE_BROADCAST;
1002
1003 if (usbdev->net->flags & IFF_PROMISC) {
1004 filter |= RNDIS_PACKET_TYPE_PROMISCUOUS |
1005 RNDIS_PACKET_TYPE_ALL_LOCAL;
1006 } else if (usbdev->net->flags & IFF_ALLMULTI ||
1007 usbdev->net->mc_count > priv->multicast_size) {
1008 filter |= RNDIS_PACKET_TYPE_ALL_MULTICAST;
1009 } else if (usbdev->net->mc_count > 0) {
1010 size = min(priv->multicast_size, usbdev->net->mc_count);
1011 buf = kmalloc(size * ETH_ALEN, GFP_KERNEL);
1012 if (!buf) {
1013 devwarn(usbdev,
1014 "couldn't alloc %d bytes of memory",
1015 size * ETH_ALEN);
1016 return;
1017 }
1018
1019 mclist = usbdev->net->mc_list;
1020 for (i = 0; i < size && mclist; mclist = mclist->next) {
1021 if (mclist->dmi_addrlen != ETH_ALEN)
1022 continue;
1023
1024 memcpy(buf + i * ETH_ALEN, mclist->dmi_addr, ETH_ALEN);
1025 i++;
1026 }
1027
1028 ret = rndis_set_oid(usbdev, OID_802_3_MULTICAST_LIST, buf,
1029 i * ETH_ALEN);
1030 if (ret == 0 && i > 0)
1031 filter |= RNDIS_PACKET_TYPE_MULTICAST;
1032 else
1033 filter |= RNDIS_PACKET_TYPE_ALL_MULTICAST;
1034
1035 devdbg(usbdev, "OID_802_3_MULTICAST_LIST(%d, max: %d) -> %d",
1036 i, priv->multicast_size, ret);
1037
1038 kfree(buf);
1039 }
1040
1041 ret = rndis_set_oid(usbdev, OID_GEN_CURRENT_PACKET_FILTER, &filter,
1042 sizeof(filter));
1043 if (ret < 0) {
1044 devwarn(usbdev, "couldn't set packet filter: %08x",
1045 le32_to_cpu(filter));
1046 }
1047
1048 devdbg(usbdev, "OID_GEN_CURRENT_PACKET_FILTER(%08x) -> %d",
1049 le32_to_cpu(filter), ret);
1050}
1051
1052
1053/*
1054 * wireless extension handlers
1055 */
1056
1057static int rndis_iw_commit(struct net_device *dev,
1058 struct iw_request_info *info, union iwreq_data *wrqu, char *extra)
1059{
1060 /* dummy op */
1061 return 0;
1062}
1063
1064
1065static int rndis_iw_get_range(struct net_device *dev,
1066 struct iw_request_info *info, union iwreq_data *wrqu, char *extra)
1067{
1068 struct iw_range *range = (struct iw_range *)extra;
1069 struct usbnet *usbdev = dev->priv;
1070 struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev);
1071 int len, ret, i, j, num, has_80211g_rates;
1072 u8 rates[8];
1073 __le32 tx_power;
1074
1075 devdbg(usbdev, "SIOCGIWRANGE");
1076
1077 /* clear iw_range struct */
1078 memset(range, 0, sizeof(*range));
1079 wrqu->data.length = sizeof(*range);
1080
1081 range->txpower_capa = IW_TXPOW_MWATT;
1082 range->num_txpower = 1;
1083 if (priv->caps & CAP_SUPPORT_TXPOWER) {
1084 len = sizeof(tx_power);
1085 ret = rndis_query_oid(usbdev, OID_802_11_TX_POWER_LEVEL,
1086 &tx_power, &len);
1087 if (ret == 0 && le32_to_cpu(tx_power) != 0xFF)
1088 range->txpower[0] = le32_to_cpu(tx_power);
1089 else
1090 range->txpower[0] = get_bcm4320_power(priv);
1091 } else
1092 range->txpower[0] = get_bcm4320_power(priv);
1093
1094 len = sizeof(rates);
1095 ret = rndis_query_oid(usbdev, OID_802_11_SUPPORTED_RATES, &rates,
1096 &len);
1097 has_80211g_rates = 0;
1098 if (ret == 0) {
1099 j = 0;
1100 for (i = 0; i < len; i++) {
1101 if (rates[i] == 0)
1102 break;
1103 range->bitrate[j] = (rates[i] & 0x7f) * 500000;
1104 /* check for non 802.11b rates */
1105 if (range->bitrate[j] == 6000000 ||
1106 range->bitrate[j] == 9000000 ||
1107 (range->bitrate[j] >= 12000000 &&
1108 range->bitrate[j] != 22000000))
1109 has_80211g_rates = 1;
1110 j++;
1111 }
1112 range->num_bitrates = j;
1113 } else
1114 range->num_bitrates = 0;
1115
1116 /* fill in 802.11g rates */
1117 if (has_80211g_rates) {
1118 num = range->num_bitrates;
1119 for (i = 0; i < sizeof(rates_80211g); i++) {
1120 for (j = 0; j < num; j++) {
1121 if (range->bitrate[j] ==
1122 rates_80211g[i] * 1000000)
1123 break;
1124 }
1125 if (j == num)
1126 range->bitrate[range->num_bitrates++] =
1127 rates_80211g[i] * 1000000;
1128 if (range->num_bitrates == IW_MAX_BITRATES)
1129 break;
1130 }
1131
1132 /* estimated max real througput in bps */
1133 range->throughput = 54 * 1000 * 1000 / 2;
1134
1135 /* ~35% more with afterburner */
1136 if (priv->param_afterburner)
1137 range->throughput = range->throughput / 100 * 135;
1138 } else {
1139 /* estimated max real througput in bps */
1140 range->throughput = 11 * 1000 * 1000 / 2;
1141 }
1142
1143 range->num_channels = (sizeof(freq_chan)/sizeof(freq_chan[0]));
1144
1145 for (i = 0; i < (sizeof(freq_chan)/sizeof(freq_chan[0])) &&
1146 i < IW_MAX_FREQUENCIES; i++) {
1147 range->freq[i].i = i + 1;
1148 range->freq[i].m = freq_chan[i] * 100000;
1149 range->freq[i].e = 1;
1150 }
1151 range->num_frequency = i;
1152
1153 range->min_rts = 0;
1154 range->max_rts = 2347;
1155 range->min_frag = 256;
1156 range->max_frag = 2346;
1157
1158 range->max_qual.qual = 100;
1159 range->max_qual.level = 154;
1160 range->max_qual.updated = IW_QUAL_QUAL_UPDATED
1161 | IW_QUAL_LEVEL_UPDATED
1162 | IW_QUAL_NOISE_INVALID;
1163
1164 range->we_version_compiled = WIRELESS_EXT;
1165 range->we_version_source = WIRELESS_EXT;
1166
1167 range->enc_capa = IW_ENC_CAPA_WPA | IW_ENC_CAPA_WPA2 |
1168 IW_ENC_CAPA_CIPHER_TKIP | IW_ENC_CAPA_CIPHER_CCMP;
1169 return 0;
1170}
1171
1172
1173static int rndis_iw_get_name(struct net_device *dev,
1174 struct iw_request_info *info, union iwreq_data *wrqu, char *extra)
1175{
1176 struct usbnet *usbdev = dev->priv;
1177 struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev);
1178
1179 strcpy(wrqu->name, priv->name);
1180 return 0;
1181}
1182
1183
1184static int rndis_iw_set_essid(struct net_device *dev,
1185 struct iw_request_info *info, union iwreq_data *wrqu, char *essid)
1186{
1187 struct NDIS_802_11_SSID ssid;
1188 int length = wrqu->essid.length;
1189 struct usbnet *usbdev = dev->priv;
1190
1191 devdbg(usbdev, "SIOCSIWESSID: [flags:%d,len:%d] '%.32s'",
1192 wrqu->essid.flags, wrqu->essid.length, essid);
1193
1194 if (length > NDIS_802_11_LENGTH_SSID)
1195 length = NDIS_802_11_LENGTH_SSID;
1196
1197 ssid.SsidLength = cpu_to_le32(length);
1198 if (length > 0)
1199 memcpy(ssid.Ssid, essid, length);
1200 else
1201 memset(ssid.Ssid, 0, NDIS_802_11_LENGTH_SSID);
1202
1203 set_assoc_params(usbdev);
1204
1205 if (!wrqu->essid.flags || length == 0)
1206 return disassociate(usbdev, 1);
1207 else
1208 return set_essid(usbdev, &ssid);
1209}
1210
1211
1212static int rndis_iw_get_essid(struct net_device *dev,
1213 struct iw_request_info *info, union iwreq_data *wrqu, char *essid)
1214{
1215 struct NDIS_802_11_SSID ssid;
1216 struct usbnet *usbdev = dev->priv;
1217 int ret;
1218
1219 ret = get_essid(usbdev, &ssid);
1220
1221 if (ret == 0 && le32_to_cpu(ssid.SsidLength) > 0) {
1222 wrqu->essid.flags = 1;
1223 wrqu->essid.length = le32_to_cpu(ssid.SsidLength);
1224 memcpy(essid, ssid.Ssid, wrqu->essid.length);
1225 essid[wrqu->essid.length] = 0;
1226 } else {
1227 memset(essid, 0, sizeof(NDIS_802_11_LENGTH_SSID));
1228 wrqu->essid.flags = 0;
1229 wrqu->essid.length = 0;
1230 }
1231 devdbg(usbdev, "SIOCGIWESSID: %s", essid);
1232 return ret;
1233}
1234
1235
1236static int rndis_iw_get_bssid(struct net_device *dev,
1237 struct iw_request_info *info, union iwreq_data *wrqu, char *extra)
1238{
1239 struct usbnet *usbdev = dev->priv;
1240 unsigned char bssid[ETH_ALEN];
1241 int ret;
1242 DECLARE_MAC_BUF(mac);
1243
1244 ret = get_bssid(usbdev, bssid);
1245
1246 if (ret == 0)
1247 devdbg(usbdev, "SIOCGIWAP: %s", print_mac(mac, bssid));
1248 else
1249 devdbg(usbdev, "SIOCGIWAP: <not associated>");
1250
1251 wrqu->ap_addr.sa_family = ARPHRD_ETHER;
1252 memcpy(wrqu->ap_addr.sa_data, bssid, ETH_ALEN);
1253
1254 return ret;
1255}
1256
1257
1258static int rndis_iw_set_bssid(struct net_device *dev,
1259 struct iw_request_info *info, union iwreq_data *wrqu, char *extra)
1260{
1261 struct usbnet *usbdev = dev->priv;
1262 u8 *bssid = (u8 *)wrqu->ap_addr.sa_data;
1263 DECLARE_MAC_BUF(mac);
1264 int ret;
1265
1266 devdbg(usbdev, "SIOCSIWAP: %s", print_mac(mac, bssid));
1267
1268 ret = rndis_set_oid(usbdev, OID_802_11_BSSID, bssid, ETH_ALEN);
1269
1270 /* user apps may set ap's mac address, which is not required;
1271 * they may fail to work if this function fails, so return
1272 * success */
1273 if (ret)
1274 devwarn(usbdev, "setting AP mac address failed (%08X)", ret);
1275
1276 return 0;
1277}
1278
1279
1280static int rndis_iw_set_auth(struct net_device *dev,
1281 struct iw_request_info *info, union iwreq_data *wrqu, char *extra)
1282{
1283 struct iw_param *p = &wrqu->param;
1284 struct usbnet *usbdev = dev->priv;
1285 struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev);
1286 int ret = -ENOTSUPP;
1287
1288 switch (p->flags & IW_AUTH_INDEX) {
1289 case IW_AUTH_WPA_VERSION:
1290 devdbg(usbdev, "SIOCSIWAUTH: WPA_VERSION, %08x", p->value);
1291 priv->wpa_version = p->value;
1292 ret = 0;
1293 break;
1294
1295 case IW_AUTH_CIPHER_PAIRWISE:
1296 devdbg(usbdev, "SIOCSIWAUTH: CIPHER_PAIRWISE, %08x", p->value);
1297 priv->wpa_cipher_pair = p->value;
1298 ret = 0;
1299 break;
1300
1301 case IW_AUTH_CIPHER_GROUP:
1302 devdbg(usbdev, "SIOCSIWAUTH: CIPHER_GROUP, %08x", p->value);
1303 priv->wpa_cipher_group = p->value;
1304 ret = 0;
1305 break;
1306
1307 case IW_AUTH_KEY_MGMT:
1308 devdbg(usbdev, "SIOCSIWAUTH: KEY_MGMT, %08x", p->value);
1309 priv->wpa_keymgmt = p->value;
1310 ret = 0;
1311 break;
1312
1313 case IW_AUTH_TKIP_COUNTERMEASURES:
1314 devdbg(usbdev, "SIOCSIWAUTH: TKIP_COUNTERMEASURES, %08x",
1315 p->value);
1316 ret = 0;
1317 break;
1318
1319 case IW_AUTH_DROP_UNENCRYPTED:
1320 devdbg(usbdev, "SIOCSIWAUTH: DROP_UNENCRYPTED, %08x", p->value);
1321 ret = 0;
1322 break;
1323
1324 case IW_AUTH_80211_AUTH_ALG:
1325 devdbg(usbdev, "SIOCSIWAUTH: 80211_AUTH_ALG, %08x", p->value);
1326 priv->wpa_authalg = p->value;
1327 ret = 0;
1328 break;
1329
1330 case IW_AUTH_WPA_ENABLED:
1331 devdbg(usbdev, "SIOCSIWAUTH: WPA_ENABLED, %08x", p->value);
1332 if (wrqu->param.value)
1333 deauthenticate(usbdev);
1334 ret = 0;
1335 break;
1336
1337 case IW_AUTH_RX_UNENCRYPTED_EAPOL:
1338 devdbg(usbdev, "SIOCSIWAUTH: RX_UNENCRYPTED_EAPOL, %08x",
1339 p->value);
1340 ret = 0;
1341 break;
1342
1343 case IW_AUTH_ROAMING_CONTROL:
1344 devdbg(usbdev, "SIOCSIWAUTH: ROAMING_CONTROL, %08x", p->value);
1345 ret = 0;
1346 break;
1347
1348 case IW_AUTH_PRIVACY_INVOKED:
1349 devdbg(usbdev, "SIOCSIWAUTH: invalid cmd %d",
1350 wrqu->param.flags & IW_AUTH_INDEX);
1351 return -EOPNOTSUPP;
1352
1353 default:
1354 devdbg(usbdev, "SIOCSIWAUTH: UNKNOWN %08x, %08x",
1355 p->flags & IW_AUTH_INDEX, p->value);
1356 }
1357 return ret;
1358}
1359
1360
1361static int rndis_iw_get_auth(struct net_device *dev,
1362 struct iw_request_info *info, union iwreq_data *wrqu, char *extra)
1363{
1364 struct iw_param *p = &wrqu->param;
1365 struct usbnet *usbdev = dev->priv;
1366 struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev);
1367
1368 switch (p->flags & IW_AUTH_INDEX) {
1369 case IW_AUTH_WPA_VERSION:
1370 p->value = priv->wpa_version;
1371 break;
1372 case IW_AUTH_CIPHER_PAIRWISE:
1373 p->value = priv->wpa_cipher_pair;
1374 break;
1375 case IW_AUTH_CIPHER_GROUP:
1376 p->value = priv->wpa_cipher_group;
1377 break;
1378 case IW_AUTH_KEY_MGMT:
1379 p->value = priv->wpa_keymgmt;
1380 break;
1381 case IW_AUTH_80211_AUTH_ALG:
1382 p->value = priv->wpa_authalg;
1383 break;
1384 default:
1385 devdbg(usbdev, "SIOCGIWAUTH: invalid cmd %d",
1386 wrqu->param.flags & IW_AUTH_INDEX);
1387 return -EOPNOTSUPP;
1388 }
1389 return 0;
1390}
1391
1392
1393static int rndis_iw_get_mode(struct net_device *dev,
1394 struct iw_request_info *info,
1395 union iwreq_data *wrqu, char *extra)
1396{
1397 struct usbnet *usbdev = dev->priv;
1398 struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev);
1399
1400 switch (priv->infra_mode) {
1401 case Ndis802_11IBSS:
1402 wrqu->mode = IW_MODE_ADHOC;
1403 break;
1404 case Ndis802_11Infrastructure:
1405 wrqu->mode = IW_MODE_INFRA;
1406 break;
1407 /*case Ndis802_11AutoUnknown:*/
1408 default:
1409 wrqu->mode = IW_MODE_AUTO;
1410 break;
1411 }
1412 devdbg(usbdev, "SIOCGIWMODE: %08x", wrqu->mode);
1413 return 0;
1414}
1415
1416
1417static int rndis_iw_set_mode(struct net_device *dev,
1418 struct iw_request_info *info, union iwreq_data *wrqu, char *extra)
1419{
1420 struct usbnet *usbdev = dev->priv;
1421 int mode;
1422
1423 devdbg(usbdev, "SIOCSIWMODE: %08x", wrqu->mode);
1424
1425 switch (wrqu->mode) {
1426 case IW_MODE_ADHOC:
1427 mode = Ndis802_11IBSS;
1428 break;
1429 case IW_MODE_INFRA:
1430 mode = Ndis802_11Infrastructure;
1431 break;
1432 /*case IW_MODE_AUTO:*/
1433 default:
1434 mode = Ndis802_11AutoUnknown;
1435 break;
1436 }
1437
1438 return set_infra_mode(usbdev, mode);
1439}
1440
1441
1442static int rndis_iw_set_encode(struct net_device *dev,
1443 struct iw_request_info *info, union iwreq_data *wrqu, char *extra)
1444{
1445 struct usbnet *usbdev = dev->priv;
1446 struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev);
1447 int ret, index, key_len;
1448 u8 *key;
1449
1450 index = (wrqu->encoding.flags & IW_ENCODE_INDEX);
1451
1452 /* iwconfig gives index as 1 - N */
1453 if (index > 0)
1454 index--;
1455 else
1456 index = priv->encr_tx_key_index;
1457
1458 if (index < 0 || index >= 4) {
1459 devwarn(usbdev, "encryption index out of range (%u)", index);
1460 return -EINVAL;
1461 }
1462
1463 /* remove key if disabled */
1464 if (wrqu->data.flags & IW_ENCODE_DISABLED) {
1465 if (remove_key(usbdev, index, NULL))
1466 return -EINVAL;
1467 else
1468 return 0;
1469 }
1470
1471 /* global encryption state (for all keys) */
1472 if (wrqu->data.flags & IW_ENCODE_OPEN)
1473 ret = set_auth_mode(usbdev, IW_AUTH_WPA_VERSION_DISABLED,
1474 IW_AUTH_ALG_OPEN_SYSTEM);
1475 else /*if (wrqu->data.flags & IW_ENCODE_RESTRICTED)*/
1476 ret = set_auth_mode(usbdev, IW_AUTH_WPA_VERSION_DISABLED,
1477 IW_AUTH_ALG_SHARED_KEY);
1478 if (ret != 0)
1479 return ret;
1480
1481 if (wrqu->data.length > 0) {
1482 key_len = wrqu->data.length;
1483 key = extra;
1484 } else {
1485 /* must be set as tx key */
1486 if (priv->encr_key_len[index] == 0)
1487 return -EINVAL;
1488 key_len = priv->encr_key_len[index];
1489 key = priv->encr_keys[index];
1490 priv->encr_tx_key_index = index;
1491 }
1492
1493 if (add_wep_key(usbdev, key, key_len, index) != 0)
1494 return -EINVAL;
1495
1496 if (index == priv->encr_tx_key_index)
1497 /* ndis drivers want essid to be set after setting encr */
1498 set_essid(usbdev, &priv->essid);
1499
1500 return 0;
1501}
1502
1503
1504static int rndis_iw_set_encode_ext(struct net_device *dev,
1505 struct iw_request_info *info, union iwreq_data *wrqu, char *extra)
1506{
1507 struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
1508 struct usbnet *usbdev = dev->priv;
1509 struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev);
1510 struct NDIS_802_11_KEY ndis_key;
1511 int i, keyidx, ret;
1512 u8 *addr;
1513
1514 keyidx = wrqu->encoding.flags & IW_ENCODE_INDEX;
1515
1516 /* iwconfig gives index as 1 - N */
1517 if (keyidx)
1518 keyidx--;
1519 else
1520 keyidx = priv->encr_tx_key_index;
1521
1522 if (keyidx < 0 || keyidx >= 4)
1523 return -EINVAL;
1524
1525 if (ext->alg == WPA_ALG_WEP) {
1526 if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY)
1527 priv->encr_tx_key_index = keyidx;
1528 return add_wep_key(usbdev, ext->key, ext->key_len, keyidx);
1529 }
1530
1531 if ((wrqu->encoding.flags & IW_ENCODE_DISABLED) ||
1532 ext->alg == IW_ENCODE_ALG_NONE || ext->key_len == 0)
1533 return remove_key(usbdev, keyidx, NULL);
1534
1535 if (ext->key_len > sizeof(ndis_key.KeyMaterial))
1536 return -1;
1537
1538 memset(&ndis_key, 0, sizeof(ndis_key));
1539
1540 ndis_key.Length = cpu_to_le32(sizeof(ndis_key) -
1541 sizeof(ndis_key.KeyMaterial) + ext->key_len);
1542 ndis_key.KeyLength = cpu_to_le32(ext->key_len);
1543 ndis_key.KeyIndex = cpu_to_le32(keyidx);
1544
1545 if (ext->ext_flags & IW_ENCODE_EXT_RX_SEQ_VALID) {
1546 for (i = 0; i < 6; i++)
1547 ndis_key.KeyRSC |=
1548 cpu_to_le64(ext->rx_seq[i] << (i * 8));
1549 ndis_key.KeyIndex |= cpu_to_le32(1 << 29);
1550 }
1551
1552 addr = ext->addr.sa_data;
1553 if (ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) {
1554 /* group key */
1555 if (priv->infra_mode == Ndis802_11IBSS)
1556 memset(ndis_key.Bssid, 0xff, ETH_ALEN);
1557 else
1558 get_bssid(usbdev, ndis_key.Bssid);
1559 } else {
1560 /* pairwise key */
1561 ndis_key.KeyIndex |= cpu_to_le32(1 << 30);
1562 memcpy(ndis_key.Bssid, addr, ETH_ALEN);
1563 }
1564
1565 if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY)
1566 ndis_key.KeyIndex |= cpu_to_le32(1 << 31);
1567
1568 if (ext->alg == IW_ENCODE_ALG_TKIP && ext->key_len == 32) {
1569 /* wpa_supplicant gives us the Michael MIC RX/TX keys in
1570 * different order than NDIS spec, so swap the order here. */
1571 memcpy(ndis_key.KeyMaterial, ext->key, 16);
1572 memcpy(ndis_key.KeyMaterial + 16, ext->key + 24, 8);
1573 memcpy(ndis_key.KeyMaterial + 24, ext->key + 16, 8);
1574 } else
1575 memcpy(ndis_key.KeyMaterial, ext->key, ext->key_len);
1576
1577 ret = rndis_set_oid(usbdev, OID_802_11_ADD_KEY, &ndis_key,
1578 le32_to_cpu(ndis_key.Length));
1579 devdbg(usbdev, "SIOCSIWENCODEEXT: OID_802_11_ADD_KEY -> %08X", ret);
1580 if (ret != 0)
1581 return ret;
1582
1583 priv->encr_key_len[keyidx] = ext->key_len;
1584 memcpy(&priv->encr_keys[keyidx], ndis_key.KeyMaterial, ext->key_len);
1585 if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY)
1586 priv->encr_tx_key_index = keyidx;
1587
1588 return 0;
1589}
1590
1591
1592static int rndis_iw_set_scan(struct net_device *dev,
1593 struct iw_request_info *info, union iwreq_data *wrqu, char *extra)
1594{
1595 struct iw_param *param = &wrqu->param;
1596 struct usbnet *usbdev = dev->priv;
1597 union iwreq_data evt;
1598 int ret = -EINVAL;
1599 __le32 tmp;
1600
1601 devdbg(usbdev, "SIOCSIWSCAN");
1602
1603 if (param->flags == 0) {
1604 tmp = ccpu2(1);
1605 ret = rndis_set_oid(usbdev, OID_802_11_BSSID_LIST_SCAN, &tmp,
1606 sizeof(tmp));
1607 evt.data.flags = 0;
1608 evt.data.length = 0;
1609 wireless_send_event(dev, SIOCGIWSCAN, &evt, NULL);
1610 }
1611 return ret;
1612}
1613
1614
1615static char *rndis_translate_scan(struct net_device *dev,
1616 char *cev, char *end_buf, struct NDIS_WLAN_BSSID_EX *bssid)
1617{
1618#ifdef DEBUG
1619 struct usbnet *usbdev = dev->priv;
1620#endif
1621 struct ieee80211_info_element *ie;
1622 char *current_val;
1623 int bssid_len, ie_len, i;
1624 u32 beacon, atim;
1625 struct iw_event iwe;
1626 unsigned char sbuf[32];
1627 DECLARE_MAC_BUF(mac);
1628
1629 bssid_len = le32_to_cpu(bssid->Length);
1630
1631 devdbg(usbdev, "BSSID %s", print_mac(mac, bssid->MacAddress));
1632 iwe.cmd = SIOCGIWAP;
1633 iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
1634 memcpy(iwe.u.ap_addr.sa_data, bssid->MacAddress, ETH_ALEN);
1635 cev = iwe_stream_add_event(cev, end_buf, &iwe, IW_EV_ADDR_LEN);
1636
1637 devdbg(usbdev, "SSID(%d) %s",
1638 le32_to_cpu(bssid->Ssid.SsidLength),
1639 bssid->Ssid.Ssid);
1640 iwe.cmd = SIOCGIWESSID;
1641 iwe.u.essid.length = le32_to_cpu(bssid->Ssid.SsidLength);
1642 iwe.u.essid.flags = 1;
1643 cev = iwe_stream_add_point(cev, end_buf, &iwe,
1644 bssid->Ssid.Ssid);
1645
1646 devdbg(usbdev, "MODE %d",
1647 le32_to_cpu(bssid->InfrastructureMode));
1648 iwe.cmd = SIOCGIWMODE;
1649 switch (le32_to_cpu(bssid->InfrastructureMode)) {
1650 case Ndis802_11IBSS:
1651 iwe.u.mode = IW_MODE_ADHOC;
1652 break;
1653 case Ndis802_11Infrastructure:
1654 iwe.u.mode = IW_MODE_INFRA;
1655 break;
1656 /*case Ndis802_11AutoUnknown:*/
1657 default:
1658 iwe.u.mode = IW_MODE_AUTO;
1659 break;
1660 }
1661 cev = iwe_stream_add_event(cev, end_buf, &iwe, IW_EV_UINT_LEN);
1662
1663 devdbg(usbdev, "FREQ %d kHz",
1664 le32_to_cpu(bssid->Configuration.DSConfig));
1665 iwe.cmd = SIOCGIWFREQ;
1666 dsconfig_to_freq(le32_to_cpu(bssid->Configuration.DSConfig),
1667 &iwe.u.freq);
1668 cev = iwe_stream_add_event(cev, end_buf, &iwe, IW_EV_FREQ_LEN);
1669
1670 devdbg(usbdev, "QUAL %d", le32_to_cpu(bssid->Rssi));
1671 iwe.cmd = IWEVQUAL;
1672 iwe.u.qual.qual = level_to_qual(le32_to_cpu(bssid->Rssi));
1673 iwe.u.qual.level = le32_to_cpu(bssid->Rssi);
1674 iwe.u.qual.updated = IW_QUAL_QUAL_UPDATED
1675 | IW_QUAL_LEVEL_UPDATED
1676 | IW_QUAL_NOISE_INVALID;
1677 cev = iwe_stream_add_event(cev, end_buf, &iwe, IW_EV_QUAL_LEN);
1678
1679 devdbg(usbdev, "ENCODE %d", le32_to_cpu(bssid->Privacy));
1680 iwe.cmd = SIOCGIWENCODE;
1681 iwe.u.data.length = 0;
1682 if (le32_to_cpu(bssid->Privacy) == Ndis802_11PrivFilterAcceptAll)
1683 iwe.u.data.flags = IW_ENCODE_DISABLED;
1684 else
1685 iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
1686
1687 cev = iwe_stream_add_point(cev, end_buf, &iwe, NULL);
1688
1689 devdbg(usbdev, "RATES:");
1690 current_val = cev + IW_EV_LCP_LEN;
1691 iwe.cmd = SIOCGIWRATE;
1692 for (i = 0; i < sizeof(bssid->SupportedRates); i++) {
1693 if (bssid->SupportedRates[i] & 0x7f) {
1694 iwe.u.bitrate.value =
1695 ((bssid->SupportedRates[i] & 0x7f) *
1696 500000);
1697 devdbg(usbdev, " %d", iwe.u.bitrate.value);
1698 current_val = iwe_stream_add_value(cev,
1699 current_val, end_buf, &iwe,
1700 IW_EV_PARAM_LEN);
1701 }
1702 }
1703
1704 if ((current_val - cev) > IW_EV_LCP_LEN)
1705 cev = current_val;
1706
1707 beacon = le32_to_cpu(bssid->Configuration.BeaconPeriod);
1708 devdbg(usbdev, "BCN_INT %d", beacon);
1709 iwe.cmd = IWEVCUSTOM;
1710 snprintf(sbuf, sizeof(sbuf), "bcn_int=%d", beacon);
1711 iwe.u.data.length = strlen(sbuf);
1712 cev = iwe_stream_add_point(cev, end_buf, &iwe, sbuf);
1713
1714 atim = le32_to_cpu(bssid->Configuration.ATIMWindow);
1715 devdbg(usbdev, "ATIM %d", atim);
1716 iwe.cmd = IWEVCUSTOM;
1717 snprintf(sbuf, sizeof(sbuf), "atim=%u", atim);
1718 iwe.u.data.length = strlen(sbuf);
1719 cev = iwe_stream_add_point(cev, end_buf, &iwe, sbuf);
1720
1721 ie = (void *)(bssid->IEs + sizeof(struct NDIS_802_11_FIXED_IEs));
1722 ie_len = min(bssid_len - (int)sizeof(*bssid),
1723 (int)le32_to_cpu(bssid->IELength));
1724 ie_len -= sizeof(struct NDIS_802_11_FIXED_IEs);
1725 while (ie_len >= sizeof(*ie) && sizeof(*ie) + ie->len <= ie_len) {
1726 if ((ie->id == MFIE_TYPE_GENERIC && ie->len >= 4 &&
1727 memcmp(ie->data, "\x00\x50\xf2\x01", 4) == 0) ||
1728 ie->id == MFIE_TYPE_RSN) {
1729 devdbg(usbdev, "IE: WPA%d",
1730 (ie->id == MFIE_TYPE_RSN) ? 2 : 1);
1731 iwe.cmd = IWEVGENIE;
1732 iwe.u.data.length = min(ie->len + 2, MAX_WPA_IE_LEN);
1733 cev = iwe_stream_add_point(cev, end_buf, &iwe,
1734 (u8 *)ie);
1735 }
1736
1737 ie_len -= sizeof(*ie) + ie->len;
1738 ie = (struct ieee80211_info_element *)&ie->data[ie->len];
1739 }
1740
1741 return cev;
1742}
1743
1744
1745static int rndis_iw_get_scan(struct net_device *dev,
1746 struct iw_request_info *info, union iwreq_data *wrqu, char *extra)
1747{
1748 struct usbnet *usbdev = dev->priv;
1749 void *buf = NULL;
1750 char *cev = extra;
1751 struct NDIS_802_11_BSSID_LIST_EX *bssid_list;
1752 struct NDIS_WLAN_BSSID_EX *bssid;
1753 int ret = -EINVAL, len, count, bssid_len;
1754
1755 devdbg(usbdev, "SIOCGIWSCAN");
1756
1757 len = CONTROL_BUFFER_SIZE;
1758 buf = kmalloc(len, GFP_KERNEL);
1759 if (!buf) {
1760 ret = -ENOMEM;
1761 goto out;
1762 }
1763
1764 ret = rndis_query_oid(usbdev, OID_802_11_BSSID_LIST, buf, &len);
1765
1766 if (ret != 0)
1767 goto out;
1768
1769 bssid_list = buf;
1770 bssid = bssid_list->Bssid;
1771 bssid_len = le32_to_cpu(bssid->Length);
1772 count = le32_to_cpu(bssid_list->NumberOfItems);
1773 devdbg(usbdev, "SIOCGIWSCAN: %d BSSIDs found", count);
1774
1775 while (count && ((void *)bssid + bssid_len) <= (buf + len)) {
1776 cev = rndis_translate_scan(dev, cev, extra + IW_SCAN_MAX_DATA,
1777 bssid);
1778 bssid = (void *)bssid + bssid_len;
1779 bssid_len = le32_to_cpu(bssid->Length);
1780 count--;
1781 }
1782
1783out:
1784 wrqu->data.length = cev - extra;
1785 wrqu->data.flags = 0;
1786 kfree(buf);
1787 return ret;
1788}
1789
1790
1791static int rndis_iw_set_genie(struct net_device *dev,
1792 struct iw_request_info *info, union iwreq_data *wrqu, char *extra)
1793{
1794 struct usbnet *usbdev = dev->priv;
1795 struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev);
1796 int ret = 0;
1797
1798#ifdef DEBUG
1799 int j;
1800 u8 *gie = extra;
1801 for (j = 0; j < wrqu->data.length; j += 8)
1802 devdbg(usbdev,
1803 "SIOCSIWGENIE %04x - "
1804 "%02x %02x %02x %02x %02x %02x %02x %02x", j,
1805 gie[j + 0], gie[j + 1], gie[j + 2], gie[j + 3],
1806 gie[j + 4], gie[j + 5], gie[j + 6], gie[j + 7]);
1807#endif
1808 /* clear existing IEs */
1809 if (priv->wpa_ie_len) {
1810 kfree(priv->wpa_ie);
1811 priv->wpa_ie_len = 0;
1812 }
1813
1814 /* set new IEs */
1815 priv->wpa_ie = kmalloc(wrqu->data.length, GFP_KERNEL);
1816 if (priv->wpa_ie) {
1817 priv->wpa_ie_len = wrqu->data.length;
1818 memcpy(priv->wpa_ie, extra, priv->wpa_ie_len);
1819 } else
1820 ret = -ENOMEM;
1821 return ret;
1822}
1823
1824
1825static int rndis_iw_get_genie(struct net_device *dev,
1826 struct iw_request_info *info, union iwreq_data *wrqu, char *extra)
1827{
1828 struct usbnet *usbdev = dev->priv;
1829 struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev);
1830
1831 devdbg(usbdev, "SIOCGIWGENIE");
1832
1833 if (priv->wpa_ie_len == 0 || priv->wpa_ie == NULL) {
1834 wrqu->data.length = 0;
1835 return 0;
1836 }
1837
1838 if (wrqu->data.length < priv->wpa_ie_len)
1839 return -E2BIG;
1840
1841 wrqu->data.length = priv->wpa_ie_len;
1842 memcpy(extra, priv->wpa_ie, priv->wpa_ie_len);
1843
1844 return 0;
1845}
1846
1847
1848static int rndis_iw_set_rts(struct net_device *dev,
1849 struct iw_request_info *info, union iwreq_data *wrqu, char *extra)
1850{
1851 struct usbnet *usbdev = dev->priv;
1852 __le32 tmp;
1853 devdbg(usbdev, "SIOCSIWRTS");
1854
1855 tmp = cpu_to_le32(wrqu->rts.value);
1856 return rndis_set_oid(usbdev, OID_802_11_RTS_THRESHOLD, &tmp,
1857 sizeof(tmp));
1858}
1859
1860
1861static int rndis_iw_get_rts(struct net_device *dev,
1862 struct iw_request_info *info, union iwreq_data *wrqu, char *extra)
1863{
1864 struct usbnet *usbdev = dev->priv;
1865 __le32 tmp;
1866 int len, ret;
1867
1868 len = sizeof(tmp);
1869 ret = rndis_query_oid(usbdev, OID_802_11_RTS_THRESHOLD, &tmp, &len);
1870 if (ret == 0) {
1871 wrqu->rts.value = le32_to_cpu(tmp);
1872 wrqu->rts.flags = 1;
1873 wrqu->rts.disabled = 0;
1874 }
1875
1876 devdbg(usbdev, "SIOCGIWRTS: %d", wrqu->rts.value);
1877
1878 return ret;
1879}
1880
1881
1882static int rndis_iw_set_frag(struct net_device *dev,
1883 struct iw_request_info *info, union iwreq_data *wrqu, char *extra)
1884{
1885 struct usbnet *usbdev = dev->priv;
1886 __le32 tmp;
1887
1888 devdbg(usbdev, "SIOCSIWFRAG");
1889
1890 tmp = cpu_to_le32(wrqu->frag.value);
1891 return rndis_set_oid(usbdev, OID_802_11_FRAGMENTATION_THRESHOLD, &tmp,
1892 sizeof(tmp));
1893}
1894
1895
1896static int rndis_iw_get_frag(struct net_device *dev,
1897 struct iw_request_info *info, union iwreq_data *wrqu, char *extra)
1898{
1899 struct usbnet *usbdev = dev->priv;
1900 __le32 tmp;
1901 int len, ret;
1902
1903 len = sizeof(tmp);
1904 ret = rndis_query_oid(usbdev, OID_802_11_FRAGMENTATION_THRESHOLD, &tmp,
1905 &len);
1906 if (ret == 0) {
1907 wrqu->frag.value = le32_to_cpu(tmp);
1908 wrqu->frag.flags = 1;
1909 wrqu->frag.disabled = 0;
1910 }
1911 devdbg(usbdev, "SIOCGIWFRAG: %d", wrqu->frag.value);
1912 return ret;
1913}
1914
1915
1916static int rndis_iw_set_nick(struct net_device *dev,
1917 struct iw_request_info *info, union iwreq_data *wrqu, char *extra)
1918{
1919 struct usbnet *usbdev = dev->priv;
1920 struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev);
1921
1922 devdbg(usbdev, "SIOCSIWNICK");
1923
1924 priv->nick_len = wrqu->data.length;
1925 if (priv->nick_len > 32)
1926 priv->nick_len = 32;
1927
1928 memcpy(priv->nick, extra, priv->nick_len);
1929 return 0;
1930}
1931
1932
1933static int rndis_iw_get_nick(struct net_device *dev,
1934 struct iw_request_info *info, union iwreq_data *wrqu, char *extra)
1935{
1936 struct usbnet *usbdev = dev->priv;
1937 struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev);
1938
1939 wrqu->data.flags = 1;
1940 wrqu->data.length = priv->nick_len;
1941 memcpy(extra, priv->nick, priv->nick_len);
1942
1943 devdbg(usbdev, "SIOCGIWNICK: '%s'", priv->nick);
1944
1945 return 0;
1946}
1947
1948
1949static int rndis_iw_set_freq(struct net_device *dev,
1950 struct iw_request_info *info, union iwreq_data *wrqu, char *extra)
1951{
1952 struct usbnet *usbdev = dev->priv;
1953 struct NDIS_802_11_CONFIGURATION config;
1954 unsigned int dsconfig;
1955 int len, ret;
1956
1957 /* this OID is valid only when not associated */
1958 if (is_associated(usbdev))
1959 return 0;
1960
1961 dsconfig = 0;
1962 if (freq_to_dsconfig(&wrqu->freq, &dsconfig))
1963 return -EINVAL;
1964
1965 len = sizeof(config);
1966 ret = rndis_query_oid(usbdev, OID_802_11_CONFIGURATION, &config, &len);
1967 if (ret != 0) {
1968 devdbg(usbdev, "SIOCSIWFREQ: querying configuration failed");
1969 return 0;
1970 }
1971
1972 config.DSConfig = cpu_to_le32(dsconfig);
1973
1974 devdbg(usbdev, "SIOCSIWFREQ: %d * 10^%d", wrqu->freq.m, wrqu->freq.e);
1975 return rndis_set_oid(usbdev, OID_802_11_CONFIGURATION, &config,
1976 sizeof(config));
1977}
1978
1979
1980static int rndis_iw_get_freq(struct net_device *dev,
1981 struct iw_request_info *info, union iwreq_data *wrqu, char *extra)
1982{
1983 struct usbnet *usbdev = dev->priv;
1984 struct NDIS_802_11_CONFIGURATION config;
1985 int len, ret;
1986
1987 len = sizeof(config);
1988 ret = rndis_query_oid(usbdev, OID_802_11_CONFIGURATION, &config, &len);
1989 if (ret == 0)
1990 dsconfig_to_freq(le32_to_cpu(config.DSConfig), &wrqu->freq);
1991
1992 devdbg(usbdev, "SIOCGIWFREQ: %d", wrqu->freq.m);
1993 return ret;
1994}
1995
1996
1997static int rndis_iw_get_txpower(struct net_device *dev,
1998 struct iw_request_info *info, union iwreq_data *wrqu, char *extra)
1999{
2000 struct usbnet *usbdev = dev->priv;
2001 struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev);
2002 __le32 tx_power;
2003 int ret = 0, len;
2004
2005 if (priv->radio_on) {
2006 if (priv->caps & CAP_SUPPORT_TXPOWER) {
2007 len = sizeof(tx_power);
2008 ret = rndis_query_oid(usbdev, OID_802_11_TX_POWER_LEVEL,
2009 &tx_power, &len);
2010 if (ret != 0)
2011 return ret;
2012 } else
2013 /* fake incase not supported */
2014 tx_power = cpu_to_le32(get_bcm4320_power(priv));
2015
2016 wrqu->txpower.flags = IW_TXPOW_MWATT;
2017 wrqu->txpower.value = le32_to_cpu(tx_power);
2018 wrqu->txpower.disabled = 0;
2019 } else {
2020 wrqu->txpower.flags = IW_TXPOW_MWATT;
2021 wrqu->txpower.value = 0;
2022 wrqu->txpower.disabled = 1;
2023 }
2024
2025 devdbg(usbdev, "SIOCGIWTXPOW: %d", wrqu->txpower.value);
2026
2027 return ret;
2028}
2029
2030
2031static int rndis_iw_set_txpower(struct net_device *dev,
2032 struct iw_request_info *info, union iwreq_data *wrqu, char *extra)
2033{
2034 struct usbnet *usbdev = dev->priv;
2035 struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev);
2036 __le32 tx_power = 0;
2037 int ret = 0;
2038
2039 if (!wrqu->txpower.disabled) {
2040 if (wrqu->txpower.flags == IW_TXPOW_MWATT)
2041 tx_power = cpu_to_le32(wrqu->txpower.value);
2042 else { /* wrqu->txpower.flags == IW_TXPOW_DBM */
2043 if (wrqu->txpower.value > 20)
2044 tx_power = cpu_to_le32(128);
2045 else if (wrqu->txpower.value < -43)
2046 tx_power = cpu_to_le32(127);
2047 else {
2048 signed char tmp;
2049 tmp = wrqu->txpower.value;
2050 tmp = -12 - tmp;
2051 tmp <<= 2;
2052 tx_power = cpu_to_le32((unsigned char)tmp);
2053 }
2054 }
2055 }
2056
2057 devdbg(usbdev, "SIOCSIWTXPOW: %d", le32_to_cpu(tx_power));
2058
2059 if (le32_to_cpu(tx_power) != 0) {
2060 if (priv->caps & CAP_SUPPORT_TXPOWER) {
2061 /* turn radio on first */
2062 if (!priv->radio_on)
2063 disassociate(usbdev, 1);
2064
2065 ret = rndis_set_oid(usbdev, OID_802_11_TX_POWER_LEVEL,
2066 &tx_power, sizeof(tx_power));
2067 if (ret != 0)
2068 ret = -EOPNOTSUPP;
2069 return ret;
2070 } else {
2071 /* txpower unsupported, just turn radio on */
2072 if (!priv->radio_on)
2073 return disassociate(usbdev, 1);
2074 return 0; /* all ready on */
2075 }
2076 }
2077
2078 /* tx_power == 0, turn off radio */
2079 return disassociate(usbdev, 0);
2080}
2081
2082
2083static int rndis_iw_get_rate(struct net_device *dev,
2084 struct iw_request_info *info, union iwreq_data *wrqu, char *extra)
2085{
2086 struct usbnet *usbdev = dev->priv;
2087 __le32 tmp;
2088 int ret, len;
2089
2090 len = sizeof(tmp);
2091 ret = rndis_query_oid(usbdev, OID_GEN_LINK_SPEED, &tmp, &len);
2092 if (ret == 0) {
2093 wrqu->bitrate.value = le32_to_cpu(tmp) * 100;
2094 wrqu->bitrate.disabled = 0;
2095 wrqu->bitrate.flags = 1;
2096 }
2097 return ret;
2098}
2099
2100
2101static int rndis_iw_set_mlme(struct net_device *dev,
2102 struct iw_request_info *info, union iwreq_data *wrqu, char *extra)
2103{
2104 struct usbnet *usbdev = dev->priv;
2105 struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev);
2106 struct iw_mlme *mlme = (struct iw_mlme *)extra;
2107 unsigned char bssid[ETH_ALEN];
2108
2109 get_bssid(usbdev, bssid);
2110
2111 if (memcmp(bssid, mlme->addr.sa_data, ETH_ALEN))
2112 return -EINVAL;
2113
2114 switch (mlme->cmd) {
2115 case IW_MLME_DEAUTH:
2116 return deauthenticate(usbdev);
2117 case IW_MLME_DISASSOC:
2118 return disassociate(usbdev, priv->radio_on);
2119 default:
2120 return -EOPNOTSUPP;
2121 }
2122
2123 return 0;
2124}
2125
2126
2127static struct iw_statistics *rndis_get_wireless_stats(struct net_device *dev)
2128{
2129 struct usbnet *usbdev = dev->priv;
2130 struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev);
2131 unsigned long flags;
2132
2133 spin_lock_irqsave(&priv->stats_lock, flags);
2134 memcpy(&priv->iwstats, &priv->privstats, sizeof(priv->iwstats));
2135 spin_unlock_irqrestore(&priv->stats_lock, flags);
2136
2137 return &priv->iwstats;
2138}
2139
2140
2141#define IW_IOCTL(x) [(x) - SIOCSIWCOMMIT]
2142static const iw_handler rndis_iw_handler[] =
2143{
2144 IW_IOCTL(SIOCSIWCOMMIT) = rndis_iw_commit,
2145 IW_IOCTL(SIOCGIWNAME) = rndis_iw_get_name,
2146 IW_IOCTL(SIOCSIWFREQ) = rndis_iw_set_freq,
2147 IW_IOCTL(SIOCGIWFREQ) = rndis_iw_get_freq,
2148 IW_IOCTL(SIOCSIWMODE) = rndis_iw_set_mode,
2149 IW_IOCTL(SIOCGIWMODE) = rndis_iw_get_mode,
2150 IW_IOCTL(SIOCGIWRANGE) = rndis_iw_get_range,
2151 IW_IOCTL(SIOCSIWAP) = rndis_iw_set_bssid,
2152 IW_IOCTL(SIOCGIWAP) = rndis_iw_get_bssid,
2153 IW_IOCTL(SIOCSIWSCAN) = rndis_iw_set_scan,
2154 IW_IOCTL(SIOCGIWSCAN) = rndis_iw_get_scan,
2155 IW_IOCTL(SIOCSIWESSID) = rndis_iw_set_essid,
2156 IW_IOCTL(SIOCGIWESSID) = rndis_iw_get_essid,
2157 IW_IOCTL(SIOCSIWNICKN) = rndis_iw_set_nick,
2158 IW_IOCTL(SIOCGIWNICKN) = rndis_iw_get_nick,
2159 IW_IOCTL(SIOCGIWRATE) = rndis_iw_get_rate,
2160 IW_IOCTL(SIOCSIWRTS) = rndis_iw_set_rts,
2161 IW_IOCTL(SIOCGIWRTS) = rndis_iw_get_rts,
2162 IW_IOCTL(SIOCSIWFRAG) = rndis_iw_set_frag,
2163 IW_IOCTL(SIOCGIWFRAG) = rndis_iw_get_frag,
2164 IW_IOCTL(SIOCSIWTXPOW) = rndis_iw_set_txpower,
2165 IW_IOCTL(SIOCGIWTXPOW) = rndis_iw_get_txpower,
2166 IW_IOCTL(SIOCSIWENCODE) = rndis_iw_set_encode,
2167 IW_IOCTL(SIOCSIWENCODEEXT) = rndis_iw_set_encode_ext,
2168 IW_IOCTL(SIOCSIWAUTH) = rndis_iw_set_auth,
2169 IW_IOCTL(SIOCGIWAUTH) = rndis_iw_get_auth,
2170 IW_IOCTL(SIOCSIWGENIE) = rndis_iw_set_genie,
2171 IW_IOCTL(SIOCGIWGENIE) = rndis_iw_get_genie,
2172 IW_IOCTL(SIOCSIWMLME) = rndis_iw_set_mlme,
2173};
2174
2175static const iw_handler rndis_wext_private_handler[] = {
2176};
2177
2178static const struct iw_priv_args rndis_wext_private_args[] = {
2179};
2180
2181
2182static const struct iw_handler_def rndis_iw_handlers = {
2183 .num_standard = ARRAY_SIZE(rndis_iw_handler),
2184 .num_private = ARRAY_SIZE(rndis_wext_private_handler),
2185 .num_private_args = ARRAY_SIZE(rndis_wext_private_args),
2186 .standard = (iw_handler *)rndis_iw_handler,
2187 .private = (iw_handler *)rndis_wext_private_handler,
2188 .private_args = (struct iw_priv_args *)rndis_wext_private_args,
2189 .get_wireless_stats = rndis_get_wireless_stats,
2190};
2191
2192
2193static void rndis_wext_worker(struct work_struct *work)
2194{
2195 struct rndis_wext_private *priv =
2196 container_of(work, struct rndis_wext_private, work);
2197 struct usbnet *usbdev = priv->usbdev;
2198 union iwreq_data evt;
2199 unsigned char bssid[ETH_ALEN];
2200 int ret;
2201
2202 if (test_and_clear_bit(WORK_CONNECTION_EVENT, &priv->work_pending)) {
2203 ret = get_bssid(usbdev, bssid);
2204
2205 if (!ret) {
2206 evt.data.flags = 0;
2207 evt.data.length = 0;
2208 memcpy(evt.ap_addr.sa_data, bssid, ETH_ALEN);
2209 wireless_send_event(usbdev->net, SIOCGIWAP, &evt, NULL);
2210 }
2211 }
2212
2213 if (test_and_clear_bit(WORK_SET_MULTICAST_LIST, &priv->work_pending))
2214 set_multicast_list(usbdev);
2215}
2216
2217static void rndis_wext_set_multicast_list(struct net_device *dev)
2218{
2219 struct usbnet *usbdev = dev->priv;
2220 struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev);
2221
2222 set_bit(WORK_SET_MULTICAST_LIST, &priv->work_pending);
2223 queue_work(priv->workqueue, &priv->work);
2224}
2225
2226static void rndis_wext_link_change(struct usbnet *dev, int state)
2227{
2228 struct rndis_wext_private *priv = get_rndis_wext_priv(dev);
2229 union iwreq_data evt;
2230
2231 if (state) {
2232 /* queue work to avoid recursive calls into rndis_command */
2233 set_bit(WORK_CONNECTION_EVENT, &priv->work_pending);
2234 queue_work(priv->workqueue, &priv->work);
2235 } else {
2236 evt.data.flags = 0;
2237 evt.data.length = 0;
2238 memset(evt.ap_addr.sa_data, 0, ETH_ALEN);
2239 wireless_send_event(dev->net, SIOCGIWAP, &evt, NULL);
2240 }
2241}
2242
2243
2244static int rndis_wext_get_caps(struct usbnet *dev)
2245{
2246 struct {
2247 __le32 num_items;
2248 __le32 items[8];
2249 } networks_supported;
2250 int len, retval, i, n;
2251 __le32 tx_power;
2252 struct rndis_wext_private *priv = get_rndis_wext_priv(dev);
2253
2254 /* determine if supports setting txpower */
2255 len = sizeof(tx_power);
2256 retval = rndis_query_oid(dev, OID_802_11_TX_POWER_LEVEL, &tx_power,
2257 &len);
2258 if (retval == 0 && le32_to_cpu(tx_power) != 0xFF)
2259 priv->caps |= CAP_SUPPORT_TXPOWER;
2260
2261 /* determine supported modes */
2262 len = sizeof(networks_supported);
2263 retval = rndis_query_oid(dev, OID_802_11_NETWORK_TYPES_SUPPORTED,
2264 &networks_supported, &len);
2265 if (retval >= 0) {
2266 n = le32_to_cpu(networks_supported.num_items);
2267 if (n > 8)
2268 n = 8;
2269 for (i = 0; i < n; i++) {
2270 switch (le32_to_cpu(networks_supported.items[i])) {
2271 case Ndis802_11FH:
2272 case Ndis802_11DS:
2273 priv->caps |= CAP_MODE_80211B;
2274 break;
2275 case Ndis802_11OFDM5:
2276 priv->caps |= CAP_MODE_80211A;
2277 break;
2278 case Ndis802_11OFDM24:
2279 priv->caps |= CAP_MODE_80211G;
2280 break;
2281 }
2282 }
2283 if (priv->caps & CAP_MODE_80211A)
2284 strcat(priv->name, "a");
2285 if (priv->caps & CAP_MODE_80211B)
2286 strcat(priv->name, "b");
2287 if (priv->caps & CAP_MODE_80211G)
2288 strcat(priv->name, "g");
2289 }
2290
2291 return retval;
2292}
2293
2294
2295#define STATS_UPDATE_JIFFIES (HZ)
2296static void rndis_update_wireless_stats(struct work_struct *work)
2297{
2298 struct rndis_wext_private *priv =
2299 container_of(work, struct rndis_wext_private, stats_work.work);
2300 struct usbnet *usbdev = priv->usbdev;
2301 struct iw_statistics iwstats;
2302 __le32 rssi, tmp;
2303 int len, ret, bitrate, j;
2304 unsigned long flags;
2305 int update_jiffies = STATS_UPDATE_JIFFIES;
2306 void *buf;
2307
2308 spin_lock_irqsave(&priv->stats_lock, flags);
2309 memcpy(&iwstats, &priv->privstats, sizeof(iwstats));
2310 spin_unlock_irqrestore(&priv->stats_lock, flags);
2311
2312 /* only update stats when connected */
2313 if (!is_associated(usbdev)) {
2314 iwstats.qual.qual = 0;
2315 iwstats.qual.level = 0;
2316 iwstats.qual.updated = IW_QUAL_QUAL_UPDATED
2317 | IW_QUAL_LEVEL_UPDATED
2318 | IW_QUAL_NOISE_INVALID
2319 | IW_QUAL_QUAL_INVALID
2320 | IW_QUAL_LEVEL_INVALID;
2321 goto end;
2322 }
2323
2324 len = sizeof(rssi);
2325 ret = rndis_query_oid(usbdev, OID_802_11_RSSI, &rssi, &len);
2326
2327 devdbg(usbdev, "stats: OID_802_11_RSSI -> %d, rssi:%d", ret,
2328 le32_to_cpu(rssi));
2329 if (ret == 0) {
2330 memset(&iwstats.qual, 0, sizeof(iwstats.qual));
2331 iwstats.qual.qual = level_to_qual(le32_to_cpu(rssi));
2332 iwstats.qual.level = le32_to_cpu(rssi);
2333 iwstats.qual.updated = IW_QUAL_QUAL_UPDATED
2334 | IW_QUAL_LEVEL_UPDATED
2335 | IW_QUAL_NOISE_INVALID;
2336 }
2337
2338 memset(&iwstats.discard, 0, sizeof(iwstats.discard));
2339
2340 len = sizeof(tmp);
2341 ret = rndis_query_oid(usbdev, OID_GEN_XMIT_ERROR, &tmp, &len);
2342 if (ret == 0)
2343 iwstats.discard.misc += le32_to_cpu(tmp);
2344
2345 len = sizeof(tmp);
2346 ret = rndis_query_oid(usbdev, OID_GEN_RCV_ERROR, &tmp, &len);
2347 if (ret == 0)
2348 iwstats.discard.misc += le32_to_cpu(tmp);
2349
2350 len = sizeof(tmp);
2351 ret = rndis_query_oid(usbdev, OID_GEN_RCV_NO_BUFFER, &tmp, &len);
2352 if (ret == 0)
2353 iwstats.discard.misc += le32_to_cpu(tmp);
2354
2355 /* Workaround transfer stalls on poor quality links. */
2356 len = sizeof(tmp);
2357 ret = rndis_query_oid(usbdev, OID_GEN_LINK_SPEED, &tmp, &len);
2358 if (ret == 0) {
2359 bitrate = le32_to_cpu(tmp) * 100;
2360 if (bitrate > 11000000)
2361 goto end;
2362
2363 /* Decrease stats worker interval to catch stalls.
2364 * faster. Faster than 400-500ms causes packet loss,
2365 * Slower doesn't catch stalls fast enough.
2366 */
2367 j = msecs_to_jiffies(priv->param_workaround_interval);
2368 if (j > STATS_UPDATE_JIFFIES)
2369 j = STATS_UPDATE_JIFFIES;
2370 else if (j <= 0)
2371 j = 1;
2372 update_jiffies = j;
2373
2374 /* Send scan OID. Use of both OIDs is required to get device
2375 * working.
2376 */
2377 tmp = ccpu2(1);
2378 rndis_set_oid(usbdev, OID_802_11_BSSID_LIST_SCAN, &tmp,
2379 sizeof(tmp));
2380
2381 len = CONTROL_BUFFER_SIZE;
2382 buf = kmalloc(len, GFP_KERNEL);
2383 if (!buf)
2384 goto end;
2385
2386 rndis_query_oid(usbdev, OID_802_11_BSSID_LIST, buf, &len);
2387 kfree(buf);
2388 }
2389end:
2390 spin_lock_irqsave(&priv->stats_lock, flags);
2391 memcpy(&priv->privstats, &iwstats, sizeof(iwstats));
2392 spin_unlock_irqrestore(&priv->stats_lock, flags);
2393
2394 if (update_jiffies >= HZ)
2395 update_jiffies = round_jiffies_relative(update_jiffies);
2396 else {
2397 j = round_jiffies_relative(update_jiffies);
2398 if (abs(j - update_jiffies) <= 10)
2399 update_jiffies = j;
2400 }
2401
2402 queue_delayed_work(priv->workqueue, &priv->stats_work, update_jiffies);
2403}
2404
2405
2406static int bcm4320_early_init(struct usbnet *dev)
2407{
2408 struct rndis_wext_private *priv = get_rndis_wext_priv(dev);
2409 char buf[8];
2410
2411 /* Early initialization settings, setting these won't have effect
2412 * if called after generic_rndis_bind().
2413 */
2414
2415 priv->param_country[0] = modparam_country[0];
2416 priv->param_country[1] = modparam_country[1];
2417 priv->param_country[2] = 0;
2418 priv->param_frameburst = modparam_frameburst;
2419 priv->param_afterburner = modparam_afterburner;
2420 priv->param_power_save = modparam_power_save;
2421 priv->param_power_output = modparam_power_output;
2422 priv->param_roamtrigger = modparam_roamtrigger;
2423 priv->param_roamdelta = modparam_roamdelta;
2424 priv->param_workaround_interval = modparam_workaround_interval;
2425
2426 priv->param_country[0] = toupper(priv->param_country[0]);
2427 priv->param_country[1] = toupper(priv->param_country[1]);
2428 /* doesn't support EU as country code, use FI instead */
2429 if (!strcmp(priv->param_country, "EU"))
2430 strcpy(priv->param_country, "FI");
2431
2432 if (priv->param_power_save < 0)
2433 priv->param_power_save = 0;
2434 else if (priv->param_power_save > 2)
2435 priv->param_power_save = 2;
2436
2437 if (priv->param_roamtrigger < -80)
2438 priv->param_roamtrigger = -80;
2439 else if (priv->param_roamtrigger > -60)
2440 priv->param_roamtrigger = -60;
2441
2442 if (priv->param_roamdelta < 0)
2443 priv->param_roamdelta = 0;
2444 else if (priv->param_roamdelta > 2)
2445 priv->param_roamdelta = 2;
2446
2447 if (priv->param_workaround_interval < 0)
2448 priv->param_workaround_interval = 500;
2449
2450 rndis_set_config_parameter_str(dev, "Country", priv->param_country);
2451 rndis_set_config_parameter_str(dev, "FrameBursting",
2452 priv->param_frameburst ? "1" : "0");
2453 rndis_set_config_parameter_str(dev, "Afterburner",
2454 priv->param_afterburner ? "1" : "0");
2455 sprintf(buf, "%d", priv->param_power_save);
2456 rndis_set_config_parameter_str(dev, "PowerSaveMode", buf);
2457 sprintf(buf, "%d", priv->param_power_output);
2458 rndis_set_config_parameter_str(dev, "PwrOut", buf);
2459 sprintf(buf, "%d", priv->param_roamtrigger);
2460 rndis_set_config_parameter_str(dev, "RoamTrigger", buf);
2461 sprintf(buf, "%d", priv->param_roamdelta);
2462 rndis_set_config_parameter_str(dev, "RoamDelta", buf);
2463
2464 return 0;
2465}
2466
2467
2468static int rndis_wext_bind(struct usbnet *dev, struct usb_interface *intf)
2469{
2470 struct net_device *net = dev->net;
2471 struct rndis_wext_private *priv;
2472 int retval, len;
2473 __le32 tmp;
2474
2475 /* allocate rndis private data */
2476 priv = kmalloc(sizeof(struct rndis_wext_private), GFP_KERNEL);
2477 if (!priv)
2478 return -ENOMEM;
2479
2480 /* These have to be initialized before calling generic_rndis_bind().
2481 * Otherwise we'll be in big trouble in rndis_wext_early_init().
2482 */
2483 dev->driver_priv = priv;
2484 memset(priv, 0, sizeof(*priv));
2485 memset(priv->name, 0, sizeof(priv->name));
2486 strcpy(priv->name, "IEEE802.11");
2487 net->wireless_handlers = &rndis_iw_handlers;
2488 priv->usbdev = dev;
2489
2490 mutex_init(&priv->command_lock);
2491 spin_lock_init(&priv->stats_lock);
2492
2493 /* try bind rndis_host */
2494 retval = generic_rndis_bind(dev, intf, FLAG_RNDIS_PHYM_WIRELESS);
2495 if (retval < 0)
2496 goto fail;
2497
2498 /* generic_rndis_bind set packet filter to multicast_all+
2499 * promisc mode which doesn't work well for our devices (device
2500 * picks up rssi to closest station instead of to access point).
2501 *
2502 * rndis_host wants to avoid all OID as much as possible
2503 * so do promisc/multicast handling in rndis_wext.
2504 */
2505 dev->net->set_multicast_list = rndis_wext_set_multicast_list;
2506 tmp = RNDIS_PACKET_TYPE_DIRECTED | RNDIS_PACKET_TYPE_BROADCAST;
2507 retval = rndis_set_oid(dev, OID_GEN_CURRENT_PACKET_FILTER, &tmp,
2508 sizeof(tmp));
2509
2510 len = sizeof(tmp);
2511 retval = rndis_query_oid(dev, OID_802_3_MAXIMUM_LIST_SIZE, &tmp, &len);
2512 priv->multicast_size = le32_to_cpu(tmp);
2513 if (retval < 0 || priv->multicast_size < 0)
2514 priv->multicast_size = 0;
2515 if (priv->multicast_size > 0)
2516 dev->net->flags |= IFF_MULTICAST;
2517 else
2518 dev->net->flags &= ~IFF_MULTICAST;
2519
2520 priv->iwstats.qual.qual = 0;
2521 priv->iwstats.qual.level = 0;
2522 priv->iwstats.qual.updated = IW_QUAL_QUAL_UPDATED
2523 | IW_QUAL_LEVEL_UPDATED
2524 | IW_QUAL_NOISE_INVALID
2525 | IW_QUAL_QUAL_INVALID
2526 | IW_QUAL_LEVEL_INVALID;
2527
2528 rndis_wext_get_caps(dev);
2529 set_default_iw_params(dev);
2530
2531 /* turn radio on */
2532 priv->radio_on = 1;
2533 disassociate(dev, 1);
2534
2535 /* because rndis_command() sleeps we need to use workqueue */
2536 priv->workqueue = create_singlethread_workqueue("rndis_wlan");
2537 INIT_DELAYED_WORK(&priv->stats_work, rndis_update_wireless_stats);
2538 queue_delayed_work(priv->workqueue, &priv->stats_work,
2539 round_jiffies_relative(STATS_UPDATE_JIFFIES));
2540 INIT_WORK(&priv->work, rndis_wext_worker);
2541
2542 return 0;
2543
2544fail:
2545 kfree(priv);
2546 return retval;
2547}
2548
2549
2550static void rndis_wext_unbind(struct usbnet *dev, struct usb_interface *intf)
2551{
2552 struct rndis_wext_private *priv = get_rndis_wext_priv(dev);
2553
2554 /* turn radio off */
2555 disassociate(dev, 0);
2556
2557 cancel_delayed_work_sync(&priv->stats_work);
2558 cancel_work_sync(&priv->work);
2559 flush_workqueue(priv->workqueue);
2560 destroy_workqueue(priv->workqueue);
2561
2562 if (priv && priv->wpa_ie_len)
2563 kfree(priv->wpa_ie);
2564 kfree(priv);
2565
2566 rndis_unbind(dev, intf);
2567}
2568
2569
2570static int rndis_wext_reset(struct usbnet *dev)
2571{
2572 return deauthenticate(dev);
2573}
2574
2575
2576static const struct driver_info bcm4320b_info = {
2577 .description = "Wireless RNDIS device, BCM4320b based",
2578 .flags = FLAG_WLAN | FLAG_FRAMING_RN | FLAG_NO_SETINT,
2579 .bind = rndis_wext_bind,
2580 .unbind = rndis_wext_unbind,
2581 .status = rndis_status,
2582 .rx_fixup = rndis_rx_fixup,
2583 .tx_fixup = rndis_tx_fixup,
2584 .reset = rndis_wext_reset,
2585 .early_init = bcm4320_early_init,
2586 .link_change = rndis_wext_link_change,
2587};
2588
2589static const struct driver_info bcm4320a_info = {
2590 .description = "Wireless RNDIS device, BCM4320a based",
2591 .flags = FLAG_WLAN | FLAG_FRAMING_RN | FLAG_NO_SETINT,
2592 .bind = rndis_wext_bind,
2593 .unbind = rndis_wext_unbind,
2594 .status = rndis_status,
2595 .rx_fixup = rndis_rx_fixup,
2596 .tx_fixup = rndis_tx_fixup,
2597 .reset = rndis_wext_reset,
2598 .early_init = bcm4320_early_init,
2599 .link_change = rndis_wext_link_change,
2600};
2601
2602static const struct driver_info rndis_wext_info = {
2603 .description = "Wireless RNDIS device",
2604 .flags = FLAG_WLAN | FLAG_FRAMING_RN | FLAG_NO_SETINT,
2605 .bind = rndis_wext_bind,
2606 .unbind = rndis_wext_unbind,
2607 .status = rndis_status,
2608 .rx_fixup = rndis_rx_fixup,
2609 .tx_fixup = rndis_tx_fixup,
2610 .reset = rndis_wext_reset,
2611 .early_init = bcm4320_early_init,
2612 .link_change = rndis_wext_link_change,
2613};
2614
2615/*-------------------------------------------------------------------------*/
2616
2617static const struct usb_device_id products [] = {
2618#define RNDIS_MASTER_INTERFACE \
2619 .bInterfaceClass = USB_CLASS_COMM, \
2620 .bInterfaceSubClass = 2 /* ACM */, \
2621 .bInterfaceProtocol = 0x0ff
2622
2623/* INF driver for these devices have DriverVer >= 4.xx.xx.xx and many custom
2624 * parameters available. Chipset marked as 'BCM4320SKFBG' in NDISwrapper-wiki.
2625 */
2626{
2627 .match_flags = USB_DEVICE_ID_MATCH_INT_INFO
2628 | USB_DEVICE_ID_MATCH_DEVICE,
2629 .idVendor = 0x0411,
2630 .idProduct = 0x00bc, /* Buffalo WLI-U2-KG125S */
2631 RNDIS_MASTER_INTERFACE,
2632 .driver_info = (unsigned long) &bcm4320b_info,
2633}, {
2634 .match_flags = USB_DEVICE_ID_MATCH_INT_INFO
2635 | USB_DEVICE_ID_MATCH_DEVICE,
2636 .idVendor = 0x0baf,
2637 .idProduct = 0x011b, /* U.S. Robotics USR5421 */
2638 RNDIS_MASTER_INTERFACE,
2639 .driver_info = (unsigned long) &bcm4320b_info,
2640}, {
2641 .match_flags = USB_DEVICE_ID_MATCH_INT_INFO
2642 | USB_DEVICE_ID_MATCH_DEVICE,
2643 .idVendor = 0x050d,
2644 .idProduct = 0x011b, /* Belkin F5D7051 */
2645 RNDIS_MASTER_INTERFACE,
2646 .driver_info = (unsigned long) &bcm4320b_info,
2647}, {
2648 .match_flags = USB_DEVICE_ID_MATCH_INT_INFO
2649 | USB_DEVICE_ID_MATCH_DEVICE,
2650 .idVendor = 0x1799, /* Belkin has two vendor ids */
2651 .idProduct = 0x011b, /* Belkin F5D7051 */
2652 RNDIS_MASTER_INTERFACE,
2653 .driver_info = (unsigned long) &bcm4320b_info,
2654}, {
2655 .match_flags = USB_DEVICE_ID_MATCH_INT_INFO
2656 | USB_DEVICE_ID_MATCH_DEVICE,
2657 .idVendor = 0x13b1,
2658 .idProduct = 0x0014, /* Linksys WUSB54GSv2 */
2659 RNDIS_MASTER_INTERFACE,
2660 .driver_info = (unsigned long) &bcm4320b_info,
2661}, {
2662 .match_flags = USB_DEVICE_ID_MATCH_INT_INFO
2663 | USB_DEVICE_ID_MATCH_DEVICE,
2664 .idVendor = 0x13b1,
2665 .idProduct = 0x0026, /* Linksys WUSB54GSC */
2666 RNDIS_MASTER_INTERFACE,
2667 .driver_info = (unsigned long) &bcm4320b_info,
2668}, {
2669 .match_flags = USB_DEVICE_ID_MATCH_INT_INFO
2670 | USB_DEVICE_ID_MATCH_DEVICE,
2671 .idVendor = 0x0b05,
2672 .idProduct = 0x1717, /* Asus WL169gE */
2673 RNDIS_MASTER_INTERFACE,
2674 .driver_info = (unsigned long) &bcm4320b_info,
2675}, {
2676 .match_flags = USB_DEVICE_ID_MATCH_INT_INFO
2677 | USB_DEVICE_ID_MATCH_DEVICE,
2678 .idVendor = 0x0a5c,
2679 .idProduct = 0xd11b, /* Eminent EM4045 */
2680 RNDIS_MASTER_INTERFACE,
2681 .driver_info = (unsigned long) &bcm4320b_info,
2682}, {
2683 .match_flags = USB_DEVICE_ID_MATCH_INT_INFO
2684 | USB_DEVICE_ID_MATCH_DEVICE,
2685 .idVendor = 0x1690,
2686 .idProduct = 0x0715, /* BT Voyager 1055 */
2687 RNDIS_MASTER_INTERFACE,
2688 .driver_info = (unsigned long) &bcm4320b_info,
2689},
2690/* These devices have DriverVer < 4.xx.xx.xx and do not have any custom
2691 * parameters available, hardware probably contain older firmware version with
2692 * no way of updating. Chipset marked as 'BCM4320????' in NDISwrapper-wiki.
2693 */
2694{
2695 .match_flags = USB_DEVICE_ID_MATCH_INT_INFO
2696 | USB_DEVICE_ID_MATCH_DEVICE,
2697 .idVendor = 0x13b1,
2698 .idProduct = 0x000e, /* Linksys WUSB54GSv1 */
2699 RNDIS_MASTER_INTERFACE,
2700 .driver_info = (unsigned long) &bcm4320a_info,
2701}, {
2702 .match_flags = USB_DEVICE_ID_MATCH_INT_INFO
2703 | USB_DEVICE_ID_MATCH_DEVICE,
2704 .idVendor = 0x0baf,
2705 .idProduct = 0x0111, /* U.S. Robotics USR5420 */
2706 RNDIS_MASTER_INTERFACE,
2707 .driver_info = (unsigned long) &bcm4320a_info,
2708}, {
2709 .match_flags = USB_DEVICE_ID_MATCH_INT_INFO
2710 | USB_DEVICE_ID_MATCH_DEVICE,
2711 .idVendor = 0x0411,
2712 .idProduct = 0x004b, /* BUFFALO WLI-USB-G54 */
2713 RNDIS_MASTER_INTERFACE,
2714 .driver_info = (unsigned long) &bcm4320a_info,
2715},
2716/* Generic Wireless RNDIS devices that we don't have exact
2717 * idVendor/idProduct/chip yet.
2718 */
2719{
2720 /* RNDIS is MSFT's un-official variant of CDC ACM */
2721 USB_INTERFACE_INFO(USB_CLASS_COMM, 2 /* ACM */, 0x0ff),
2722 .driver_info = (unsigned long) &rndis_wext_info,
2723}, {
2724 /* "ActiveSync" is an undocumented variant of RNDIS, used in WM5 */
2725 USB_INTERFACE_INFO(USB_CLASS_MISC, 1, 1),
2726 .driver_info = (unsigned long) &rndis_wext_info,
2727},
2728 { }, // END
2729};
2730MODULE_DEVICE_TABLE(usb, products);
2731
2732static struct usb_driver rndis_wlan_driver = {
2733 .name = "rndis_wlan",
2734 .id_table = products,
2735 .probe = usbnet_probe,
2736 .disconnect = usbnet_disconnect,
2737 .suspend = usbnet_suspend,
2738 .resume = usbnet_resume,
2739};
2740
2741static int __init rndis_wlan_init(void)
2742{
2743 return usb_register(&rndis_wlan_driver);
2744}
2745module_init(rndis_wlan_init);
2746
2747static void __exit rndis_wlan_exit(void)
2748{
2749 usb_deregister(&rndis_wlan_driver);
2750}
2751module_exit(rndis_wlan_exit);
2752
2753MODULE_AUTHOR("Bjorge Dijkstra");
2754MODULE_AUTHOR("Jussi Kivilinna");
2755MODULE_DESCRIPTION("Driver for RNDIS based USB Wireless adapters");
2756MODULE_LICENSE("GPL");
2757