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