Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(482)

Side by Side Diff: chromeos/compat-wireless/drivers/net/wireless/orinoco/wext.c

Issue 5326002: Update compat-wireless to 2.6.36-5-spn (Closed) Base URL: http://git.chromium.org/git/kernel.git@master
Patch Set: Fixes for !ACK handling, missing local changes, log message fixes Created 10 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 /* Wireless extensions support.
2 *
3 * See copyright notice in main.c
4 */
5 #include <linux/slab.h>
6 #include <linux/kernel.h>
7 #include <linux/if_arp.h>
8 #include <linux/wireless.h>
9 #include <linux/ieee80211.h>
10 #include <net/iw_handler.h>
11 #include <net/cfg80211.h>
12
13 #include "hermes.h"
14 #include "hermes_rid.h"
15 #include "orinoco.h"
16
17 #include "hw.h"
18 #include "mic.h"
19 #include "scan.h"
20 #include "main.h"
21
22 #include "wext.h"
23
24 #define MAX_RID_LEN 1024
25
26 /* Helper routine to record keys
27 * It is called under orinoco_lock so it may not sleep */
28 static int orinoco_set_key(struct orinoco_private *priv, int index,
29 enum orinoco_alg alg, const u8 *key, int key_len,
30 const u8 *seq, int seq_len)
31 {
32 #if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,28)
33 int len;
34 if (!unlikely(ZERO_OR_NULL_PTR(priv->keys[index].key))) {
35 len = priv->keys[index].key_len;
36 memset(priv->keys[index].key, 0, len);
37 kfree(priv->keys[index].key);
38 }
39 if (!unlikely(ZERO_OR_NULL_PTR(priv->keys[index].seq))) {
40 len = priv->keys[index].seq_len;
41 memset(priv->keys[index].seq, 0, len);
42 kfree(priv->keys[index].seq);
43 }
44 #else
45 kzfree(priv->keys[index].key);
46 kzfree(priv->keys[index].seq);
47 #endif
48
49 if (key_len) {
50 priv->keys[index].key = kzalloc(key_len, GFP_ATOMIC);
51 if (!priv->keys[index].key)
52 goto nomem;
53 } else
54 priv->keys[index].key = NULL;
55
56 if (seq_len) {
57 priv->keys[index].seq = kzalloc(seq_len, GFP_ATOMIC);
58 if (!priv->keys[index].seq)
59 goto free_key;
60 } else
61 priv->keys[index].seq = NULL;
62
63 priv->keys[index].key_len = key_len;
64 priv->keys[index].seq_len = seq_len;
65
66 if (key_len)
67 memcpy(priv->keys[index].key, key, key_len);
68 if (seq_len)
69 memcpy(priv->keys[index].seq, seq, seq_len);
70
71 switch (alg) {
72 case ORINOCO_ALG_TKIP:
73 priv->keys[index].cipher = WLAN_CIPHER_SUITE_TKIP;
74 break;
75
76 case ORINOCO_ALG_WEP:
77 priv->keys[index].cipher = (key_len > SMALL_KEY_SIZE) ?
78 WLAN_CIPHER_SUITE_WEP104 : WLAN_CIPHER_SUITE_WEP40;
79 break;
80
81 case ORINOCO_ALG_NONE:
82 default:
83 priv->keys[index].cipher = 0;
84 break;
85 }
86
87 return 0;
88
89 free_key:
90 kfree(priv->keys[index].key);
91 priv->keys[index].key = NULL;
92
93 nomem:
94 priv->keys[index].key_len = 0;
95 priv->keys[index].seq_len = 0;
96 priv->keys[index].cipher = 0;
97
98 return -ENOMEM;
99 }
100
101 static struct iw_statistics *orinoco_get_wireless_stats(struct net_device *dev)
102 {
103 struct orinoco_private *priv = ndev_priv(dev);
104 hermes_t *hw = &priv->hw;
105 struct iw_statistics *wstats = &priv->wstats;
106 int err;
107 unsigned long flags;
108
109 if (!netif_device_present(dev)) {
110 printk(KERN_WARNING "%s: get_wireless_stats() called while devic e not present\n",
111 dev->name);
112 return NULL; /* FIXME: Can we do better than this? */
113 }
114
115 /* If busy, return the old stats. Returning NULL may cause
116 * the interface to disappear from /proc/net/wireless */
117 if (orinoco_lock(priv, &flags) != 0)
118 return wstats;
119
120 /* We can't really wait for the tallies inquiry command to
121 * complete, so we just use the previous results and trigger
122 * a new tallies inquiry command for next time - Jean II */
123 /* FIXME: Really we should wait for the inquiry to come back -
124 * as it is the stats we give don't make a whole lot of sense.
125 * Unfortunately, it's not clear how to do that within the
126 * wireless extensions framework: I think we're in user
127 * context, but a lock seems to be held by the time we get in
128 * here so we're not safe to sleep here. */
129 hermes_inquire(hw, HERMES_INQ_TALLIES);
130
131 if (priv->iw_mode == NL80211_IFTYPE_ADHOC) {
132 memset(&wstats->qual, 0, sizeof(wstats->qual));
133 /* If a spy address is defined, we report stats of the
134 * first spy address - Jean II */
135 if (SPY_NUMBER(priv)) {
136 wstats->qual.qual = priv->spy_data.spy_stat[0].qual;
137 wstats->qual.level = priv->spy_data.spy_stat[0].level;
138 wstats->qual.noise = priv->spy_data.spy_stat[0].noise;
139 wstats->qual.updated =
140 priv->spy_data.spy_stat[0].updated;
141 }
142 } else {
143 struct {
144 __le16 qual, signal, noise, unused;
145 } __packed cq;
146
147 err = HERMES_READ_RECORD(hw, USER_BAP,
148 HERMES_RID_COMMSQUALITY, &cq);
149
150 if (!err) {
151 wstats->qual.qual = (int)le16_to_cpu(cq.qual);
152 wstats->qual.level = (int)le16_to_cpu(cq.signal) - 0x95;
153 wstats->qual.noise = (int)le16_to_cpu(cq.noise) - 0x95;
154 wstats->qual.updated =
155 IW_QUAL_ALL_UPDATED | IW_QUAL_DBM;
156 }
157 }
158
159 orinoco_unlock(priv, &flags);
160 return wstats;
161 }
162
163 /********************************************************************/
164 /* Wireless extensions */
165 /********************************************************************/
166
167 static int orinoco_ioctl_setwap(struct net_device *dev,
168 struct iw_request_info *info,
169 struct sockaddr *ap_addr,
170 char *extra)
171 {
172 struct orinoco_private *priv = ndev_priv(dev);
173 int err = -EINPROGRESS; /* Call commit handler */
174 unsigned long flags;
175 static const u8 off_addr[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
176 static const u8 any_addr[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
177
178 if (orinoco_lock(priv, &flags) != 0)
179 return -EBUSY;
180
181 /* Enable automatic roaming - no sanity checks are needed */
182 if (memcmp(&ap_addr->sa_data, off_addr, ETH_ALEN) == 0 ||
183 memcmp(&ap_addr->sa_data, any_addr, ETH_ALEN) == 0) {
184 priv->bssid_fixed = 0;
185 memset(priv->desired_bssid, 0, ETH_ALEN);
186
187 /* "off" means keep existing connection */
188 if (ap_addr->sa_data[0] == 0) {
189 __orinoco_hw_set_wap(priv);
190 err = 0;
191 }
192 goto out;
193 }
194
195 if (priv->firmware_type == FIRMWARE_TYPE_AGERE) {
196 printk(KERN_WARNING "%s: Lucent/Agere firmware doesn't "
197 "support manual roaming\n",
198 dev->name);
199 err = -EOPNOTSUPP;
200 goto out;
201 }
202
203 if (priv->iw_mode != NL80211_IFTYPE_STATION) {
204 printk(KERN_WARNING "%s: Manual roaming supported only in "
205 "managed mode\n", dev->name);
206 err = -EOPNOTSUPP;
207 goto out;
208 }
209
210 /* Intersil firmware hangs without Desired ESSID */
211 if (priv->firmware_type == FIRMWARE_TYPE_INTERSIL &&
212 strlen(priv->desired_essid) == 0) {
213 printk(KERN_WARNING "%s: Desired ESSID must be set for "
214 "manual roaming\n", dev->name);
215 err = -EOPNOTSUPP;
216 goto out;
217 }
218
219 /* Finally, enable manual roaming */
220 priv->bssid_fixed = 1;
221 memcpy(priv->desired_bssid, &ap_addr->sa_data, ETH_ALEN);
222
223 out:
224 orinoco_unlock(priv, &flags);
225 return err;
226 }
227
228 static int orinoco_ioctl_getwap(struct net_device *dev,
229 struct iw_request_info *info,
230 struct sockaddr *ap_addr,
231 char *extra)
232 {
233 struct orinoco_private *priv = ndev_priv(dev);
234
235 int err = 0;
236 unsigned long flags;
237
238 if (orinoco_lock(priv, &flags) != 0)
239 return -EBUSY;
240
241 ap_addr->sa_family = ARPHRD_ETHER;
242 err = orinoco_hw_get_current_bssid(priv, ap_addr->sa_data);
243
244 orinoco_unlock(priv, &flags);
245
246 return err;
247 }
248
249 static int orinoco_ioctl_setiwencode(struct net_device *dev,
250 struct iw_request_info *info,
251 struct iw_point *erq,
252 char *keybuf)
253 {
254 struct orinoco_private *priv = ndev_priv(dev);
255 int index = (erq->flags & IW_ENCODE_INDEX) - 1;
256 int setindex = priv->tx_key;
257 enum orinoco_alg encode_alg = priv->encode_alg;
258 int restricted = priv->wep_restrict;
259 int err = -EINPROGRESS; /* Call commit handler */
260 unsigned long flags;
261
262 if (!priv->has_wep)
263 return -EOPNOTSUPP;
264
265 if (erq->pointer) {
266 /* We actually have a key to set - check its length */
267 if (erq->length > LARGE_KEY_SIZE)
268 return -E2BIG;
269
270 if ((erq->length > SMALL_KEY_SIZE) && !priv->has_big_wep)
271 return -E2BIG;
272 }
273
274 if (orinoco_lock(priv, &flags) != 0)
275 return -EBUSY;
276
277 /* Clear any TKIP key we have */
278 if ((priv->has_wpa) && (priv->encode_alg == ORINOCO_ALG_TKIP))
279 (void) orinoco_clear_tkip_key(priv, setindex);
280
281 if (erq->length > 0) {
282 if ((index < 0) || (index >= ORINOCO_MAX_KEYS))
283 index = priv->tx_key;
284
285 /* Switch on WEP if off */
286 if (encode_alg != ORINOCO_ALG_WEP) {
287 setindex = index;
288 encode_alg = ORINOCO_ALG_WEP;
289 }
290 } else {
291 /* Important note : if the user do "iwconfig eth0 enc off",
292 * we will arrive there with an index of -1. This is valid
293 * but need to be taken care off... Jean II */
294 if ((index < 0) || (index >= ORINOCO_MAX_KEYS)) {
295 if ((index != -1) || (erq->flags == 0)) {
296 err = -EINVAL;
297 goto out;
298 }
299 } else {
300 /* Set the index : Check that the key is valid */
301 if (priv->keys[index].key_len == 0) {
302 err = -EINVAL;
303 goto out;
304 }
305 setindex = index;
306 }
307 }
308
309 if (erq->flags & IW_ENCODE_DISABLED)
310 encode_alg = ORINOCO_ALG_NONE;
311 if (erq->flags & IW_ENCODE_OPEN)
312 restricted = 0;
313 if (erq->flags & IW_ENCODE_RESTRICTED)
314 restricted = 1;
315
316 if (erq->pointer && erq->length > 0) {
317 err = orinoco_set_key(priv, index, ORINOCO_ALG_WEP, keybuf,
318 erq->length, NULL, 0);
319 }
320 priv->tx_key = setindex;
321
322 /* Try fast key change if connected and only keys are changed */
323 if ((priv->encode_alg == encode_alg) &&
324 (priv->wep_restrict == restricted) &&
325 netif_carrier_ok(dev)) {
326 err = __orinoco_hw_setup_wepkeys(priv);
327 /* No need to commit if successful */
328 goto out;
329 }
330
331 priv->encode_alg = encode_alg;
332 priv->wep_restrict = restricted;
333
334 out:
335 orinoco_unlock(priv, &flags);
336
337 return err;
338 }
339
340 static int orinoco_ioctl_getiwencode(struct net_device *dev,
341 struct iw_request_info *info,
342 struct iw_point *erq,
343 char *keybuf)
344 {
345 struct orinoco_private *priv = ndev_priv(dev);
346 int index = (erq->flags & IW_ENCODE_INDEX) - 1;
347 unsigned long flags;
348
349 if (!priv->has_wep)
350 return -EOPNOTSUPP;
351
352 if (orinoco_lock(priv, &flags) != 0)
353 return -EBUSY;
354
355 if ((index < 0) || (index >= ORINOCO_MAX_KEYS))
356 index = priv->tx_key;
357
358 erq->flags = 0;
359 if (!priv->encode_alg)
360 erq->flags |= IW_ENCODE_DISABLED;
361 erq->flags |= index + 1;
362
363 if (priv->wep_restrict)
364 erq->flags |= IW_ENCODE_RESTRICTED;
365 else
366 erq->flags |= IW_ENCODE_OPEN;
367
368 erq->length = priv->keys[index].key_len;
369
370 memcpy(keybuf, priv->keys[index].key, erq->length);
371
372 orinoco_unlock(priv, &flags);
373 return 0;
374 }
375
376 static int orinoco_ioctl_setessid(struct net_device *dev,
377 struct iw_request_info *info,
378 struct iw_point *erq,
379 char *essidbuf)
380 {
381 struct orinoco_private *priv = ndev_priv(dev);
382 unsigned long flags;
383
384 /* Note : ESSID is ignored in Ad-Hoc demo mode, but we can set it
385 * anyway... - Jean II */
386
387 /* Hum... Should not use Wireless Extension constant (may change),
388 * should use our own... - Jean II */
389 if (erq->length > IW_ESSID_MAX_SIZE)
390 return -E2BIG;
391
392 if (orinoco_lock(priv, &flags) != 0)
393 return -EBUSY;
394
395 /* NULL the string (for NULL termination & ESSID = ANY) - Jean II */
396 memset(priv->desired_essid, 0, sizeof(priv->desired_essid));
397
398 /* If not ANY, get the new ESSID */
399 if (erq->flags)
400 memcpy(priv->desired_essid, essidbuf, erq->length);
401
402 orinoco_unlock(priv, &flags);
403
404 return -EINPROGRESS; /* Call commit handler */
405 }
406
407 static int orinoco_ioctl_getessid(struct net_device *dev,
408 struct iw_request_info *info,
409 struct iw_point *erq,
410 char *essidbuf)
411 {
412 struct orinoco_private *priv = ndev_priv(dev);
413 int active;
414 int err = 0;
415 unsigned long flags;
416
417 if (netif_running(dev)) {
418 err = orinoco_hw_get_essid(priv, &active, essidbuf);
419 if (err < 0)
420 return err;
421 erq->length = err;
422 } else {
423 if (orinoco_lock(priv, &flags) != 0)
424 return -EBUSY;
425 memcpy(essidbuf, priv->desired_essid, IW_ESSID_MAX_SIZE);
426 erq->length = strlen(priv->desired_essid);
427 orinoco_unlock(priv, &flags);
428 }
429
430 erq->flags = 1;
431
432 return 0;
433 }
434
435 static int orinoco_ioctl_setfreq(struct net_device *dev,
436 struct iw_request_info *info,
437 struct iw_freq *frq,
438 char *extra)
439 {
440 struct orinoco_private *priv = ndev_priv(dev);
441 int chan = -1;
442 unsigned long flags;
443 int err = -EINPROGRESS; /* Call commit handler */
444
445 /* In infrastructure mode the AP sets the channel */
446 if (priv->iw_mode == NL80211_IFTYPE_STATION)
447 return -EBUSY;
448
449 if ((frq->e == 0) && (frq->m <= 1000)) {
450 /* Setting by channel number */
451 chan = frq->m;
452 } else {
453 /* Setting by frequency */
454 int denom = 1;
455 int i;
456
457 /* Calculate denominator to rescale to MHz */
458 for (i = 0; i < (6 - frq->e); i++)
459 denom *= 10;
460
461 chan = ieee80211_freq_to_dsss_chan(frq->m / denom);
462 }
463
464 if ((chan < 1) || (chan > NUM_CHANNELS) ||
465 !(priv->channel_mask & (1 << (chan-1))))
466 return -EINVAL;
467
468 if (orinoco_lock(priv, &flags) != 0)
469 return -EBUSY;
470
471 priv->channel = chan;
472 if (priv->iw_mode == NL80211_IFTYPE_MONITOR) {
473 /* Fast channel change - no commit if successful */
474 hermes_t *hw = &priv->hw;
475 err = hw->ops->cmd_wait(hw, HERMES_CMD_TEST |
476 HERMES_TEST_SET_CHANNEL,
477 chan, NULL);
478 }
479 orinoco_unlock(priv, &flags);
480
481 return err;
482 }
483
484 static int orinoco_ioctl_getfreq(struct net_device *dev,
485 struct iw_request_info *info,
486 struct iw_freq *frq,
487 char *extra)
488 {
489 struct orinoco_private *priv = ndev_priv(dev);
490 int tmp;
491
492 /* Locking done in there */
493 tmp = orinoco_hw_get_freq(priv);
494 if (tmp < 0)
495 return tmp;
496
497 frq->m = tmp * 100000;
498 frq->e = 1;
499
500 return 0;
501 }
502
503 static int orinoco_ioctl_getsens(struct net_device *dev,
504 struct iw_request_info *info,
505 struct iw_param *srq,
506 char *extra)
507 {
508 struct orinoco_private *priv = ndev_priv(dev);
509 hermes_t *hw = &priv->hw;
510 u16 val;
511 int err;
512 unsigned long flags;
513
514 if (!priv->has_sensitivity)
515 return -EOPNOTSUPP;
516
517 if (orinoco_lock(priv, &flags) != 0)
518 return -EBUSY;
519 err = hermes_read_wordrec(hw, USER_BAP,
520 HERMES_RID_CNFSYSTEMSCALE, &val);
521 orinoco_unlock(priv, &flags);
522
523 if (err)
524 return err;
525
526 srq->value = val;
527 srq->fixed = 0; /* auto */
528
529 return 0;
530 }
531
532 static int orinoco_ioctl_setsens(struct net_device *dev,
533 struct iw_request_info *info,
534 struct iw_param *srq,
535 char *extra)
536 {
537 struct orinoco_private *priv = ndev_priv(dev);
538 int val = srq->value;
539 unsigned long flags;
540
541 if (!priv->has_sensitivity)
542 return -EOPNOTSUPP;
543
544 if ((val < 1) || (val > 3))
545 return -EINVAL;
546
547 if (orinoco_lock(priv, &flags) != 0)
548 return -EBUSY;
549 priv->ap_density = val;
550 orinoco_unlock(priv, &flags);
551
552 return -EINPROGRESS; /* Call commit handler */
553 }
554
555 static int orinoco_ioctl_setrate(struct net_device *dev,
556 struct iw_request_info *info,
557 struct iw_param *rrq,
558 char *extra)
559 {
560 struct orinoco_private *priv = ndev_priv(dev);
561 int ratemode;
562 int bitrate; /* 100s of kilobits */
563 unsigned long flags;
564
565 /* As the user space doesn't know our highest rate, it uses -1
566 * to ask us to set the highest rate. Test it using "iwconfig
567 * ethX rate auto" - Jean II */
568 if (rrq->value == -1)
569 bitrate = 110;
570 else {
571 if (rrq->value % 100000)
572 return -EINVAL;
573 bitrate = rrq->value / 100000;
574 }
575
576 ratemode = orinoco_get_bitratemode(bitrate, !rrq->fixed);
577
578 if (ratemode == -1)
579 return -EINVAL;
580
581 if (orinoco_lock(priv, &flags) != 0)
582 return -EBUSY;
583 priv->bitratemode = ratemode;
584 orinoco_unlock(priv, &flags);
585
586 return -EINPROGRESS;
587 }
588
589 static int orinoco_ioctl_getrate(struct net_device *dev,
590 struct iw_request_info *info,
591 struct iw_param *rrq,
592 char *extra)
593 {
594 struct orinoco_private *priv = ndev_priv(dev);
595 int err = 0;
596 int bitrate, automatic;
597 unsigned long flags;
598
599 if (orinoco_lock(priv, &flags) != 0)
600 return -EBUSY;
601
602 orinoco_get_ratemode_cfg(priv->bitratemode, &bitrate, &automatic);
603
604 /* If the interface is running we try to find more about the
605 current mode */
606 if (netif_running(dev))
607 err = orinoco_hw_get_act_bitrate(priv, &bitrate);
608
609 orinoco_unlock(priv, &flags);
610
611 rrq->value = bitrate;
612 rrq->fixed = !automatic;
613 rrq->disabled = 0;
614
615 return err;
616 }
617
618 static int orinoco_ioctl_setpower(struct net_device *dev,
619 struct iw_request_info *info,
620 struct iw_param *prq,
621 char *extra)
622 {
623 struct orinoco_private *priv = ndev_priv(dev);
624 int err = -EINPROGRESS; /* Call commit handler */
625 unsigned long flags;
626
627 if (orinoco_lock(priv, &flags) != 0)
628 return -EBUSY;
629
630 if (prq->disabled) {
631 priv->pm_on = 0;
632 } else {
633 switch (prq->flags & IW_POWER_MODE) {
634 case IW_POWER_UNICAST_R:
635 priv->pm_mcast = 0;
636 priv->pm_on = 1;
637 break;
638 case IW_POWER_ALL_R:
639 priv->pm_mcast = 1;
640 priv->pm_on = 1;
641 break;
642 case IW_POWER_ON:
643 /* No flags : but we may have a value - Jean II */
644 break;
645 default:
646 err = -EINVAL;
647 goto out;
648 }
649
650 if (prq->flags & IW_POWER_TIMEOUT) {
651 priv->pm_on = 1;
652 priv->pm_timeout = prq->value / 1000;
653 }
654 if (prq->flags & IW_POWER_PERIOD) {
655 priv->pm_on = 1;
656 priv->pm_period = prq->value / 1000;
657 }
658 /* It's valid to not have a value if we are just toggling
659 * the flags... Jean II */
660 if (!priv->pm_on) {
661 err = -EINVAL;
662 goto out;
663 }
664 }
665
666 out:
667 orinoco_unlock(priv, &flags);
668
669 return err;
670 }
671
672 static int orinoco_ioctl_getpower(struct net_device *dev,
673 struct iw_request_info *info,
674 struct iw_param *prq,
675 char *extra)
676 {
677 struct orinoco_private *priv = ndev_priv(dev);
678 hermes_t *hw = &priv->hw;
679 int err = 0;
680 u16 enable, period, timeout, mcast;
681 unsigned long flags;
682
683 if (orinoco_lock(priv, &flags) != 0)
684 return -EBUSY;
685
686 err = hermes_read_wordrec(hw, USER_BAP,
687 HERMES_RID_CNFPMENABLED, &enable);
688 if (err)
689 goto out;
690
691 err = hermes_read_wordrec(hw, USER_BAP,
692 HERMES_RID_CNFMAXSLEEPDURATION, &period);
693 if (err)
694 goto out;
695
696 err = hermes_read_wordrec(hw, USER_BAP,
697 HERMES_RID_CNFPMHOLDOVERDURATION, &timeout);
698 if (err)
699 goto out;
700
701 err = hermes_read_wordrec(hw, USER_BAP,
702 HERMES_RID_CNFMULTICASTRECEIVE, &mcast);
703 if (err)
704 goto out;
705
706 prq->disabled = !enable;
707 /* Note : by default, display the period */
708 if ((prq->flags & IW_POWER_TYPE) == IW_POWER_TIMEOUT) {
709 prq->flags = IW_POWER_TIMEOUT;
710 prq->value = timeout * 1000;
711 } else {
712 prq->flags = IW_POWER_PERIOD;
713 prq->value = period * 1000;
714 }
715 if (mcast)
716 prq->flags |= IW_POWER_ALL_R;
717 else
718 prq->flags |= IW_POWER_UNICAST_R;
719
720 out:
721 orinoco_unlock(priv, &flags);
722
723 return err;
724 }
725
726 static int orinoco_ioctl_set_encodeext(struct net_device *dev,
727 struct iw_request_info *info,
728 union iwreq_data *wrqu,
729 char *extra)
730 {
731 struct orinoco_private *priv = ndev_priv(dev);
732 struct iw_point *encoding = &wrqu->encoding;
733 struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
734 int idx, alg = ext->alg, set_key = 1;
735 unsigned long flags;
736 int err = -EINVAL;
737
738 if (orinoco_lock(priv, &flags) != 0)
739 return -EBUSY;
740
741 /* Determine and validate the key index */
742 idx = encoding->flags & IW_ENCODE_INDEX;
743 if (idx) {
744 if ((idx < 1) || (idx > 4))
745 goto out;
746 idx--;
747 } else
748 idx = priv->tx_key;
749
750 if (encoding->flags & IW_ENCODE_DISABLED)
751 alg = IW_ENCODE_ALG_NONE;
752
753 if (priv->has_wpa && (alg != IW_ENCODE_ALG_TKIP)) {
754 /* Clear any TKIP TX key we had */
755 (void) orinoco_clear_tkip_key(priv, priv->tx_key);
756 }
757
758 if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) {
759 priv->tx_key = idx;
760 set_key = ((alg == IW_ENCODE_ALG_TKIP) ||
761 (ext->key_len > 0)) ? 1 : 0;
762 }
763
764 if (set_key) {
765 /* Set the requested key first */
766 switch (alg) {
767 case IW_ENCODE_ALG_NONE:
768 priv->encode_alg = ORINOCO_ALG_NONE;
769 err = orinoco_set_key(priv, idx, ORINOCO_ALG_NONE,
770 NULL, 0, NULL, 0);
771 break;
772
773 case IW_ENCODE_ALG_WEP:
774 if (ext->key_len <= 0)
775 goto out;
776
777 priv->encode_alg = ORINOCO_ALG_WEP;
778 err = orinoco_set_key(priv, idx, ORINOCO_ALG_WEP,
779 ext->key, ext->key_len, NULL, 0);
780 break;
781
782 case IW_ENCODE_ALG_TKIP:
783 {
784 u8 *tkip_iv = NULL;
785
786 if (!priv->has_wpa ||
787 (ext->key_len > sizeof(struct orinoco_tkip_key)))
788 goto out;
789
790 priv->encode_alg = ORINOCO_ALG_TKIP;
791
792 if (ext->ext_flags & IW_ENCODE_EXT_RX_SEQ_VALID)
793 tkip_iv = &ext->rx_seq[0];
794
795 err = orinoco_set_key(priv, idx, ORINOCO_ALG_TKIP,
796 ext->key, ext->key_len, tkip_iv,
797 ORINOCO_SEQ_LEN);
798
799 err = __orinoco_hw_set_tkip_key(priv, idx,
800 ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY,
801 priv->keys[idx].key,
802 tkip_iv, ORINOCO_SEQ_LEN, NULL, 0);
803 if (err)
804 printk(KERN_ERR "%s: Error %d setting TKIP key"
805 "\n", dev->name, err);
806
807 goto out;
808 }
809 default:
810 goto out;
811 }
812 }
813 err = -EINPROGRESS;
814 out:
815 orinoco_unlock(priv, &flags);
816
817 return err;
818 }
819
820 static int orinoco_ioctl_get_encodeext(struct net_device *dev,
821 struct iw_request_info *info,
822 union iwreq_data *wrqu,
823 char *extra)
824 {
825 struct orinoco_private *priv = ndev_priv(dev);
826 struct iw_point *encoding = &wrqu->encoding;
827 struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
828 int idx, max_key_len;
829 unsigned long flags;
830 int err;
831
832 if (orinoco_lock(priv, &flags) != 0)
833 return -EBUSY;
834
835 err = -EINVAL;
836 max_key_len = encoding->length - sizeof(*ext);
837 if (max_key_len < 0)
838 goto out;
839
840 idx = encoding->flags & IW_ENCODE_INDEX;
841 if (idx) {
842 if ((idx < 1) || (idx > 4))
843 goto out;
844 idx--;
845 } else
846 idx = priv->tx_key;
847
848 encoding->flags = idx + 1;
849 memset(ext, 0, sizeof(*ext));
850
851 switch (priv->encode_alg) {
852 case ORINOCO_ALG_NONE:
853 ext->alg = IW_ENCODE_ALG_NONE;
854 ext->key_len = 0;
855 encoding->flags |= IW_ENCODE_DISABLED;
856 break;
857 case ORINOCO_ALG_WEP:
858 ext->alg = IW_ENCODE_ALG_WEP;
859 ext->key_len = min(priv->keys[idx].key_len, max_key_len);
860 memcpy(ext->key, priv->keys[idx].key, ext->key_len);
861 encoding->flags |= IW_ENCODE_ENABLED;
862 break;
863 case ORINOCO_ALG_TKIP:
864 ext->alg = IW_ENCODE_ALG_TKIP;
865 ext->key_len = min(priv->keys[idx].key_len, max_key_len);
866 memcpy(ext->key, priv->keys[idx].key, ext->key_len);
867 encoding->flags |= IW_ENCODE_ENABLED;
868 break;
869 }
870
871 err = 0;
872 out:
873 orinoco_unlock(priv, &flags);
874
875 return err;
876 }
877
878 static int orinoco_ioctl_set_auth(struct net_device *dev,
879 struct iw_request_info *info,
880 union iwreq_data *wrqu, char *extra)
881 {
882 struct orinoco_private *priv = ndev_priv(dev);
883 hermes_t *hw = &priv->hw;
884 struct iw_param *param = &wrqu->param;
885 unsigned long flags;
886 int ret = -EINPROGRESS;
887
888 if (orinoco_lock(priv, &flags) != 0)
889 return -EBUSY;
890
891 switch (param->flags & IW_AUTH_INDEX) {
892 case IW_AUTH_WPA_VERSION:
893 case IW_AUTH_CIPHER_PAIRWISE:
894 case IW_AUTH_CIPHER_GROUP:
895 case IW_AUTH_RX_UNENCRYPTED_EAPOL:
896 case IW_AUTH_PRIVACY_INVOKED:
897 case IW_AUTH_DROP_UNENCRYPTED:
898 /*
899 * orinoco does not use these parameters
900 */
901 break;
902
903 case IW_AUTH_KEY_MGMT:
904 /* wl_lkm implies value 2 == PSK for Hermes I
905 * which ties in with WEXT
906 * no other hints tho :(
907 */
908 priv->key_mgmt = param->value;
909 break;
910
911 case IW_AUTH_TKIP_COUNTERMEASURES:
912 /* When countermeasures are enabled, shut down the
913 * card; when disabled, re-enable the card. This must
914 * take effect immediately.
915 *
916 * TODO: Make sure that the EAPOL message is getting
917 * out before card disabled
918 */
919 if (param->value) {
920 priv->tkip_cm_active = 1;
921 ret = hermes_enable_port(hw, 0);
922 } else {
923 priv->tkip_cm_active = 0;
924 ret = hermes_disable_port(hw, 0);
925 }
926 break;
927
928 case IW_AUTH_80211_AUTH_ALG:
929 if (param->value & IW_AUTH_ALG_SHARED_KEY)
930 priv->wep_restrict = 1;
931 else if (param->value & IW_AUTH_ALG_OPEN_SYSTEM)
932 priv->wep_restrict = 0;
933 else
934 ret = -EINVAL;
935 break;
936
937 case IW_AUTH_WPA_ENABLED:
938 if (priv->has_wpa) {
939 priv->wpa_enabled = param->value ? 1 : 0;
940 } else {
941 if (param->value)
942 ret = -EOPNOTSUPP;
943 /* else silently accept disable of WPA */
944 priv->wpa_enabled = 0;
945 }
946 break;
947
948 default:
949 ret = -EOPNOTSUPP;
950 }
951
952 orinoco_unlock(priv, &flags);
953 return ret;
954 }
955
956 static int orinoco_ioctl_get_auth(struct net_device *dev,
957 struct iw_request_info *info,
958 union iwreq_data *wrqu, char *extra)
959 {
960 struct orinoco_private *priv = ndev_priv(dev);
961 struct iw_param *param = &wrqu->param;
962 unsigned long flags;
963 int ret = 0;
964
965 if (orinoco_lock(priv, &flags) != 0)
966 return -EBUSY;
967
968 switch (param->flags & IW_AUTH_INDEX) {
969 case IW_AUTH_KEY_MGMT:
970 param->value = priv->key_mgmt;
971 break;
972
973 case IW_AUTH_TKIP_COUNTERMEASURES:
974 param->value = priv->tkip_cm_active;
975 break;
976
977 case IW_AUTH_80211_AUTH_ALG:
978 if (priv->wep_restrict)
979 param->value = IW_AUTH_ALG_SHARED_KEY;
980 else
981 param->value = IW_AUTH_ALG_OPEN_SYSTEM;
982 break;
983
984 case IW_AUTH_WPA_ENABLED:
985 param->value = priv->wpa_enabled;
986 break;
987
988 default:
989 ret = -EOPNOTSUPP;
990 }
991
992 orinoco_unlock(priv, &flags);
993 return ret;
994 }
995
996 static int orinoco_ioctl_set_genie(struct net_device *dev,
997 struct iw_request_info *info,
998 union iwreq_data *wrqu, char *extra)
999 {
1000 struct orinoco_private *priv = ndev_priv(dev);
1001 u8 *buf;
1002 unsigned long flags;
1003
1004 /* cut off at IEEE80211_MAX_DATA_LEN */
1005 if ((wrqu->data.length > IEEE80211_MAX_DATA_LEN) ||
1006 (wrqu->data.length && (extra == NULL)))
1007 return -EINVAL;
1008
1009 if (wrqu->data.length) {
1010 buf = kmemdup(extra, wrqu->data.length, GFP_KERNEL);
1011 if (buf == NULL)
1012 return -ENOMEM;
1013 } else
1014 buf = NULL;
1015
1016 if (orinoco_lock(priv, &flags) != 0) {
1017 kfree(buf);
1018 return -EBUSY;
1019 }
1020
1021 kfree(priv->wpa_ie);
1022 priv->wpa_ie = buf;
1023 priv->wpa_ie_len = wrqu->data.length;
1024
1025 if (priv->wpa_ie) {
1026 /* Looks like wl_lkm wants to check the auth alg, and
1027 * somehow pass it to the firmware.
1028 * Instead it just calls the key mgmt rid
1029 * - we do this in set auth.
1030 */
1031 }
1032
1033 orinoco_unlock(priv, &flags);
1034 return 0;
1035 }
1036
1037 static int orinoco_ioctl_get_genie(struct net_device *dev,
1038 struct iw_request_info *info,
1039 union iwreq_data *wrqu, char *extra)
1040 {
1041 struct orinoco_private *priv = ndev_priv(dev);
1042 unsigned long flags;
1043 int err = 0;
1044
1045 if (orinoco_lock(priv, &flags) != 0)
1046 return -EBUSY;
1047
1048 if ((priv->wpa_ie_len == 0) || (priv->wpa_ie == NULL)) {
1049 wrqu->data.length = 0;
1050 goto out;
1051 }
1052
1053 if (wrqu->data.length < priv->wpa_ie_len) {
1054 err = -E2BIG;
1055 goto out;
1056 }
1057
1058 wrqu->data.length = priv->wpa_ie_len;
1059 memcpy(extra, priv->wpa_ie, priv->wpa_ie_len);
1060
1061 out:
1062 orinoco_unlock(priv, &flags);
1063 return err;
1064 }
1065
1066 static int orinoco_ioctl_set_mlme(struct net_device *dev,
1067 struct iw_request_info *info,
1068 union iwreq_data *wrqu, char *extra)
1069 {
1070 struct orinoco_private *priv = ndev_priv(dev);
1071 struct iw_mlme *mlme = (struct iw_mlme *)extra;
1072 unsigned long flags;
1073 int ret = 0;
1074
1075 if (orinoco_lock(priv, &flags) != 0)
1076 return -EBUSY;
1077
1078 switch (mlme->cmd) {
1079 case IW_MLME_DEAUTH:
1080 /* silently ignore */
1081 break;
1082
1083 case IW_MLME_DISASSOC:
1084
1085 ret = orinoco_hw_disassociate(priv, mlme->addr.sa_data,
1086 mlme->reason_code);
1087 break;
1088
1089 default:
1090 ret = -EOPNOTSUPP;
1091 }
1092
1093 orinoco_unlock(priv, &flags);
1094 return ret;
1095 }
1096
1097 static int orinoco_ioctl_reset(struct net_device *dev,
1098 struct iw_request_info *info,
1099 void *wrqu,
1100 char *extra)
1101 {
1102 struct orinoco_private *priv = ndev_priv(dev);
1103
1104 if (!capable(CAP_NET_ADMIN))
1105 return -EPERM;
1106
1107 if (info->cmd == (SIOCIWFIRSTPRIV + 0x1)) {
1108 printk(KERN_DEBUG "%s: Forcing reset!\n", dev->name);
1109
1110 /* Firmware reset */
1111 orinoco_reset(&priv->reset_work);
1112 } else {
1113 printk(KERN_DEBUG "%s: Force scheduling reset!\n", dev->name);
1114
1115 schedule_work(&priv->reset_work);
1116 }
1117
1118 return 0;
1119 }
1120
1121 static int orinoco_ioctl_setibssport(struct net_device *dev,
1122 struct iw_request_info *info,
1123 void *wrqu,
1124 char *extra)
1125
1126 {
1127 struct orinoco_private *priv = ndev_priv(dev);
1128 int val = *((int *) extra);
1129 unsigned long flags;
1130
1131 if (orinoco_lock(priv, &flags) != 0)
1132 return -EBUSY;
1133
1134 priv->ibss_port = val;
1135
1136 /* Actually update the mode we are using */
1137 set_port_type(priv);
1138
1139 orinoco_unlock(priv, &flags);
1140 return -EINPROGRESS; /* Call commit handler */
1141 }
1142
1143 static int orinoco_ioctl_getibssport(struct net_device *dev,
1144 struct iw_request_info *info,
1145 void *wrqu,
1146 char *extra)
1147 {
1148 struct orinoco_private *priv = ndev_priv(dev);
1149 int *val = (int *) extra;
1150
1151 *val = priv->ibss_port;
1152 return 0;
1153 }
1154
1155 static int orinoco_ioctl_setport3(struct net_device *dev,
1156 struct iw_request_info *info,
1157 void *wrqu,
1158 char *extra)
1159 {
1160 struct orinoco_private *priv = ndev_priv(dev);
1161 int val = *((int *) extra);
1162 int err = 0;
1163 unsigned long flags;
1164
1165 if (orinoco_lock(priv, &flags) != 0)
1166 return -EBUSY;
1167
1168 switch (val) {
1169 case 0: /* Try to do IEEE ad-hoc mode */
1170 if (!priv->has_ibss) {
1171 err = -EINVAL;
1172 break;
1173 }
1174 priv->prefer_port3 = 0;
1175
1176 break;
1177
1178 case 1: /* Try to do Lucent proprietary ad-hoc mode */
1179 if (!priv->has_port3) {
1180 err = -EINVAL;
1181 break;
1182 }
1183 priv->prefer_port3 = 1;
1184 break;
1185
1186 default:
1187 err = -EINVAL;
1188 }
1189
1190 if (!err) {
1191 /* Actually update the mode we are using */
1192 set_port_type(priv);
1193 err = -EINPROGRESS;
1194 }
1195
1196 orinoco_unlock(priv, &flags);
1197
1198 return err;
1199 }
1200
1201 static int orinoco_ioctl_getport3(struct net_device *dev,
1202 struct iw_request_info *info,
1203 void *wrqu,
1204 char *extra)
1205 {
1206 struct orinoco_private *priv = ndev_priv(dev);
1207 int *val = (int *) extra;
1208
1209 *val = priv->prefer_port3;
1210 return 0;
1211 }
1212
1213 static int orinoco_ioctl_setpreamble(struct net_device *dev,
1214 struct iw_request_info *info,
1215 void *wrqu,
1216 char *extra)
1217 {
1218 struct orinoco_private *priv = ndev_priv(dev);
1219 unsigned long flags;
1220 int val;
1221
1222 if (!priv->has_preamble)
1223 return -EOPNOTSUPP;
1224
1225 /* 802.11b has recently defined some short preamble.
1226 * Basically, the Phy header has been reduced in size.
1227 * This increase performance, especially at high rates
1228 * (the preamble is transmitted at 1Mb/s), unfortunately
1229 * this give compatibility troubles... - Jean II */
1230 val = *((int *) extra);
1231
1232 if (orinoco_lock(priv, &flags) != 0)
1233 return -EBUSY;
1234
1235 if (val)
1236 priv->preamble = 1;
1237 else
1238 priv->preamble = 0;
1239
1240 orinoco_unlock(priv, &flags);
1241
1242 return -EINPROGRESS; /* Call commit handler */
1243 }
1244
1245 static int orinoco_ioctl_getpreamble(struct net_device *dev,
1246 struct iw_request_info *info,
1247 void *wrqu,
1248 char *extra)
1249 {
1250 struct orinoco_private *priv = ndev_priv(dev);
1251 int *val = (int *) extra;
1252
1253 if (!priv->has_preamble)
1254 return -EOPNOTSUPP;
1255
1256 *val = priv->preamble;
1257 return 0;
1258 }
1259
1260 /* ioctl interface to hermes_read_ltv()
1261 * To use with iwpriv, pass the RID as the token argument, e.g.
1262 * iwpriv get_rid [0xfc00]
1263 * At least Wireless Tools 25 is required to use iwpriv.
1264 * For Wireless Tools 25 and 26 append "dummy" are the end. */
1265 static int orinoco_ioctl_getrid(struct net_device *dev,
1266 struct iw_request_info *info,
1267 struct iw_point *data,
1268 char *extra)
1269 {
1270 struct orinoco_private *priv = ndev_priv(dev);
1271 hermes_t *hw = &priv->hw;
1272 int rid = data->flags;
1273 u16 length;
1274 int err;
1275 unsigned long flags;
1276
1277 /* It's a "get" function, but we don't want users to access the
1278 * WEP key and other raw firmware data */
1279 if (!capable(CAP_NET_ADMIN))
1280 return -EPERM;
1281
1282 if (rid < 0xfc00 || rid > 0xffff)
1283 return -EINVAL;
1284
1285 if (orinoco_lock(priv, &flags) != 0)
1286 return -EBUSY;
1287
1288 err = hw->ops->read_ltv(hw, USER_BAP, rid, MAX_RID_LEN, &length,
1289 extra);
1290 if (err)
1291 goto out;
1292
1293 data->length = min_t(u16, HERMES_RECLEN_TO_BYTES(length),
1294 MAX_RID_LEN);
1295
1296 out:
1297 orinoco_unlock(priv, &flags);
1298 return err;
1299 }
1300
1301
1302 /* Commit handler, called after set operations */
1303 static int orinoco_ioctl_commit(struct net_device *dev,
1304 struct iw_request_info *info,
1305 void *wrqu,
1306 char *extra)
1307 {
1308 struct orinoco_private *priv = ndev_priv(dev);
1309 unsigned long flags;
1310 int err = 0;
1311
1312 if (!priv->open)
1313 return 0;
1314
1315 if (orinoco_lock(priv, &flags) != 0)
1316 return err;
1317
1318 err = orinoco_commit(priv);
1319
1320 orinoco_unlock(priv, &flags);
1321 return err;
1322 }
1323
1324 static const struct iw_priv_args orinoco_privtab[] = {
1325 { SIOCIWFIRSTPRIV + 0x0, 0, 0, "force_reset" },
1326 { SIOCIWFIRSTPRIV + 0x1, 0, 0, "card_reset" },
1327 { SIOCIWFIRSTPRIV + 0x2, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
1328 0, "set_port3" },
1329 { SIOCIWFIRSTPRIV + 0x3, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
1330 "get_port3" },
1331 { SIOCIWFIRSTPRIV + 0x4, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
1332 0, "set_preamble" },
1333 { SIOCIWFIRSTPRIV + 0x5, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
1334 "get_preamble" },
1335 { SIOCIWFIRSTPRIV + 0x6, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
1336 0, "set_ibssport" },
1337 { SIOCIWFIRSTPRIV + 0x7, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
1338 "get_ibssport" },
1339 { SIOCIWFIRSTPRIV + 0x9, 0, IW_PRIV_TYPE_BYTE | MAX_RID_LEN,
1340 "get_rid" },
1341 };
1342
1343
1344 /*
1345 * Structures to export the Wireless Handlers
1346 */
1347
1348 static const iw_handler orinoco_handler[] = {
1349 IW_HANDLER(SIOCSIWCOMMIT, (iw_handler)orinoco_ioctl_commit),
1350 IW_HANDLER(SIOCGIWNAME, (iw_handler)cfg80211_wext_giwname),
1351 IW_HANDLER(SIOCSIWFREQ, (iw_handler)orinoco_ioctl_setfreq),
1352 IW_HANDLER(SIOCGIWFREQ, (iw_handler)orinoco_ioctl_getfreq),
1353 IW_HANDLER(SIOCSIWMODE, (iw_handler)cfg80211_wext_siwmode),
1354 IW_HANDLER(SIOCGIWMODE, (iw_handler)cfg80211_wext_giwmode),
1355 IW_HANDLER(SIOCSIWSENS, (iw_handler)orinoco_ioctl_setsens),
1356 IW_HANDLER(SIOCGIWSENS, (iw_handler)orinoco_ioctl_getsens),
1357 IW_HANDLER(SIOCGIWRANGE, (iw_handler)cfg80211_wext_giwrange),
1358 IW_HANDLER(SIOCSIWSPY, iw_handler_set_spy),
1359 IW_HANDLER(SIOCGIWSPY, iw_handler_get_spy),
1360 IW_HANDLER(SIOCSIWTHRSPY, iw_handler_set_thrspy),
1361 IW_HANDLER(SIOCGIWTHRSPY, iw_handler_get_thrspy),
1362 IW_HANDLER(SIOCSIWAP, (iw_handler)orinoco_ioctl_setwap),
1363 IW_HANDLER(SIOCGIWAP, (iw_handler)orinoco_ioctl_getwap),
1364 IW_HANDLER(SIOCSIWSCAN, (iw_handler)cfg80211_wext_siwscan),
1365 IW_HANDLER(SIOCGIWSCAN, (iw_handler)cfg80211_wext_giwscan),
1366 IW_HANDLER(SIOCSIWESSID, (iw_handler)orinoco_ioctl_setessid),
1367 IW_HANDLER(SIOCGIWESSID, (iw_handler)orinoco_ioctl_getessid),
1368 IW_HANDLER(SIOCSIWRATE, (iw_handler)orinoco_ioctl_setrate),
1369 IW_HANDLER(SIOCGIWRATE, (iw_handler)orinoco_ioctl_getrate),
1370 IW_HANDLER(SIOCSIWRTS, (iw_handler)cfg80211_wext_siwrts),
1371 IW_HANDLER(SIOCGIWRTS, (iw_handler)cfg80211_wext_giwrts),
1372 IW_HANDLER(SIOCSIWFRAG, (iw_handler)cfg80211_wext_siwfrag),
1373 IW_HANDLER(SIOCGIWFRAG, (iw_handler)cfg80211_wext_giwfrag),
1374 IW_HANDLER(SIOCGIWRETRY, (iw_handler)cfg80211_wext_giwretry),
1375 IW_HANDLER(SIOCSIWENCODE, (iw_handler)orinoco_ioctl_setiwencode),
1376 IW_HANDLER(SIOCGIWENCODE, (iw_handler)orinoco_ioctl_getiwencode),
1377 IW_HANDLER(SIOCSIWPOWER, (iw_handler)orinoco_ioctl_setpower),
1378 IW_HANDLER(SIOCGIWPOWER, (iw_handler)orinoco_ioctl_getpower),
1379 IW_HANDLER(SIOCSIWGENIE, orinoco_ioctl_set_genie),
1380 IW_HANDLER(SIOCGIWGENIE, orinoco_ioctl_get_genie),
1381 IW_HANDLER(SIOCSIWMLME, orinoco_ioctl_set_mlme),
1382 IW_HANDLER(SIOCSIWAUTH, orinoco_ioctl_set_auth),
1383 IW_HANDLER(SIOCGIWAUTH, orinoco_ioctl_get_auth),
1384 IW_HANDLER(SIOCSIWENCODEEXT, orinoco_ioctl_set_encodeext),
1385 IW_HANDLER(SIOCGIWENCODEEXT, orinoco_ioctl_get_encodeext),
1386 };
1387
1388
1389 /*
1390 Added typecasting since we no longer use iwreq_data -- Moustafa
1391 */
1392 static const iw_handler orinoco_private_handler[] = {
1393 [0] = (iw_handler)orinoco_ioctl_reset,
1394 [1] = (iw_handler)orinoco_ioctl_reset,
1395 [2] = (iw_handler)orinoco_ioctl_setport3,
1396 [3] = (iw_handler)orinoco_ioctl_getport3,
1397 [4] = (iw_handler)orinoco_ioctl_setpreamble,
1398 [5] = (iw_handler)orinoco_ioctl_getpreamble,
1399 [6] = (iw_handler)orinoco_ioctl_setibssport,
1400 [7] = (iw_handler)orinoco_ioctl_getibssport,
1401 [9] = (iw_handler)orinoco_ioctl_getrid,
1402 };
1403
1404 const struct iw_handler_def orinoco_handler_def = {
1405 .num_standard = ARRAY_SIZE(orinoco_handler),
1406 .num_private = ARRAY_SIZE(orinoco_private_handler),
1407 .num_private_args = ARRAY_SIZE(orinoco_privtab),
1408 .standard = orinoco_handler,
1409 .private = orinoco_private_handler,
1410 .private_args = orinoco_privtab,
1411 .get_wireless_stats = orinoco_get_wireless_stats,
1412 };
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698