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