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