diff options
| author | Christoph Hellwig <hch@lst.de> | 2005-06-18 19:27:33 -0400 |
|---|---|---|
| committer | Jeff Garzik <jgarzik@pobox.com> | 2005-06-27 00:23:54 -0400 |
| commit | 620554e406e3cc01434c658a1e597162d7e56fd6 (patch) | |
| tree | c78c04de8b3809927de6ac0721a3cf5d2a4de8a6 /drivers/net/wireless/orinoco.c | |
| parent | 5d558b7f36cc577d31b770d8987681ec6e6545e7 (diff) | |
[PATCH] orinoco: wireless API 15 support
(patch from Moustafa Youssef, updated by Jim Carter and Pavel Roskin).
Diffstat (limited to 'drivers/net/wireless/orinoco.c')
| -rw-r--r-- | drivers/net/wireless/orinoco.c | 1118 |
1 files changed, 547 insertions, 571 deletions
diff --git a/drivers/net/wireless/orinoco.c b/drivers/net/wireless/orinoco.c index 7cf3b98227..0e1edce910 100644 --- a/drivers/net/wireless/orinoco.c +++ b/drivers/net/wireless/orinoco.c | |||
| @@ -463,6 +463,7 @@ | |||
| 463 | #include <linux/if_arp.h> | 463 | #include <linux/if_arp.h> |
| 464 | #include <linux/etherdevice.h> | 464 | #include <linux/etherdevice.h> |
| 465 | #include <linux/wireless.h> | 465 | #include <linux/wireless.h> |
| 466 | #include <net/iw_handler.h> | ||
| 466 | #include <net/ieee80211.h> | 467 | #include <net/ieee80211.h> |
| 467 | 468 | ||
| 468 | #include <asm/uaccess.h> | 469 | #include <asm/uaccess.h> |
| @@ -538,6 +539,10 @@ MODULE_PARM_DESC(ignore_disconnect, "Don't report lost link to the network layer | |||
| 538 | | HERMES_EV_WTERR | HERMES_EV_INFO \ | 539 | | HERMES_EV_WTERR | HERMES_EV_INFO \ |
| 539 | | HERMES_EV_INFDROP ) | 540 | | HERMES_EV_INFDROP ) |
| 540 | 541 | ||
| 542 | #define MAX_RID_LEN 1024 | ||
| 543 | |||
| 544 | static const struct iw_handler_def orinoco_handler_def; | ||
| 545 | |||
| 541 | /********************************************************************/ | 546 | /********************************************************************/ |
| 542 | /* Data tables */ | 547 | /* Data tables */ |
| 543 | /********************************************************************/ | 548 | /********************************************************************/ |
| @@ -605,7 +610,6 @@ struct hermes_rx_descriptor { | |||
| 605 | /* Function prototypes */ | 610 | /* Function prototypes */ |
| 606 | /********************************************************************/ | 611 | /********************************************************************/ |
| 607 | 612 | ||
| 608 | static int orinoco_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); | ||
| 609 | static int __orinoco_program_rids(struct net_device *dev); | 613 | static int __orinoco_program_rids(struct net_device *dev); |
| 610 | static void __orinoco_set_multicast_list(struct net_device *dev); | 614 | static void __orinoco_set_multicast_list(struct net_device *dev); |
| 611 | 615 | ||
| @@ -1870,55 +1874,6 @@ __orinoco_set_multicast_list(struct net_device *dev) | |||
| 1870 | dev->flags &= ~IFF_PROMISC; | 1874 | dev->flags &= ~IFF_PROMISC; |
| 1871 | } | 1875 | } |
| 1872 | 1876 | ||
| 1873 | static int orinoco_reconfigure(struct net_device *dev) | ||
| 1874 | { | ||
| 1875 | struct orinoco_private *priv = netdev_priv(dev); | ||
| 1876 | struct hermes *hw = &priv->hw; | ||
| 1877 | unsigned long flags; | ||
| 1878 | int err = 0; | ||
| 1879 | |||
| 1880 | if (priv->broken_disableport) { | ||
| 1881 | schedule_work(&priv->reset_work); | ||
| 1882 | return 0; | ||
| 1883 | } | ||
| 1884 | |||
| 1885 | if (orinoco_lock(priv, &flags) != 0) | ||
| 1886 | return -EBUSY; | ||
| 1887 | |||
| 1888 | err = hermes_disable_port(hw, 0); | ||
| 1889 | if (err) { | ||
| 1890 | printk(KERN_WARNING "%s: Unable to disable port while reconfiguring card\n", | ||
| 1891 | dev->name); | ||
| 1892 | priv->broken_disableport = 1; | ||
| 1893 | goto out; | ||
| 1894 | } | ||
| 1895 | |||
| 1896 | err = __orinoco_program_rids(dev); | ||
| 1897 | if (err) { | ||
| 1898 | printk(KERN_WARNING "%s: Unable to reconfigure card\n", | ||
| 1899 | dev->name); | ||
| 1900 | goto out; | ||
| 1901 | } | ||
| 1902 | |||
| 1903 | err = hermes_enable_port(hw, 0); | ||
| 1904 | if (err) { | ||
| 1905 | printk(KERN_WARNING "%s: Unable to enable port while reconfiguring card\n", | ||
| 1906 | dev->name); | ||
| 1907 | goto out; | ||
| 1908 | } | ||
| 1909 | |||
| 1910 | out: | ||
| 1911 | if (err) { | ||
| 1912 | printk(KERN_WARNING "%s: Resetting instead...\n", dev->name); | ||
| 1913 | schedule_work(&priv->reset_work); | ||
| 1914 | err = 0; | ||
| 1915 | } | ||
| 1916 | |||
| 1917 | orinoco_unlock(priv, &flags); | ||
| 1918 | return err; | ||
| 1919 | |||
| 1920 | } | ||
| 1921 | |||
| 1922 | /* This must be called from user context, without locks held - use | 1877 | /* This must be called from user context, without locks held - use |
| 1923 | * schedule_work() */ | 1878 | * schedule_work() */ |
| 1924 | static void orinoco_reset(struct net_device *dev) | 1879 | static void orinoco_reset(struct net_device *dev) |
| @@ -2458,7 +2413,7 @@ struct net_device *alloc_orinocodev(int sizeof_card, | |||
| 2458 | dev->watchdog_timeo = HZ; /* 1 second timeout */ | 2413 | dev->watchdog_timeo = HZ; /* 1 second timeout */ |
| 2459 | dev->get_stats = orinoco_get_stats; | 2414 | dev->get_stats = orinoco_get_stats; |
| 2460 | dev->get_wireless_stats = orinoco_get_wireless_stats; | 2415 | dev->get_wireless_stats = orinoco_get_wireless_stats; |
| 2461 | dev->do_ioctl = orinoco_ioctl; | 2416 | dev->wireless_handlers = (struct iw_handler_def *)&orinoco_handler_def; |
| 2462 | dev->change_mtu = orinoco_change_mtu; | 2417 | dev->change_mtu = orinoco_change_mtu; |
| 2463 | dev->set_multicast_list = orinoco_set_multicast_list; | 2418 | dev->set_multicast_list = orinoco_set_multicast_list; |
| 2464 | /* we use the default eth_mac_addr for setting the MAC addr */ | 2419 | /* we use the default eth_mac_addr for setting the MAC addr */ |
| @@ -2491,24 +2446,6 @@ void free_orinocodev(struct net_device *dev) | |||
| 2491 | /* Wireless extensions */ | 2446 | /* Wireless extensions */ |
| 2492 | /********************************************************************/ | 2447 | /********************************************************************/ |
| 2493 | 2448 | ||
| 2494 | static int orinoco_hw_get_bssid(struct orinoco_private *priv, | ||
| 2495 | char buf[ETH_ALEN]) | ||
| 2496 | { | ||
| 2497 | hermes_t *hw = &priv->hw; | ||
| 2498 | int err = 0; | ||
| 2499 | unsigned long flags; | ||
| 2500 | |||
| 2501 | if (orinoco_lock(priv, &flags) != 0) | ||
| 2502 | return -EBUSY; | ||
| 2503 | |||
| 2504 | err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_CURRENTBSSID, | ||
| 2505 | ETH_ALEN, NULL, buf); | ||
| 2506 | |||
| 2507 | orinoco_unlock(priv, &flags); | ||
| 2508 | |||
| 2509 | return err; | ||
| 2510 | } | ||
| 2511 | |||
| 2512 | static int orinoco_hw_get_essid(struct orinoco_private *priv, int *active, | 2449 | static int orinoco_hw_get_essid(struct orinoco_private *priv, int *active, |
| 2513 | char buf[IW_ESSID_MAX_SIZE+1]) | 2450 | char buf[IW_ESSID_MAX_SIZE+1]) |
| 2514 | { | 2451 | { |
| @@ -2634,140 +2571,201 @@ static int orinoco_hw_get_bitratelist(struct orinoco_private *priv, | |||
| 2634 | return 0; | 2571 | return 0; |
| 2635 | } | 2572 | } |
| 2636 | 2573 | ||
| 2637 | static int orinoco_ioctl_getiwrange(struct net_device *dev, struct iw_point *rrq) | 2574 | static int orinoco_ioctl_getname(struct net_device *dev, |
| 2575 | struct iw_request_info *info, | ||
| 2576 | char *name, | ||
| 2577 | char *extra) | ||
| 2638 | { | 2578 | { |
| 2639 | struct orinoco_private *priv = netdev_priv(dev); | 2579 | struct orinoco_private *priv = netdev_priv(dev); |
| 2640 | int err = 0; | ||
| 2641 | int mode; | ||
| 2642 | struct iw_range range; | ||
| 2643 | int numrates; | 2580 | int numrates; |
| 2644 | int i, k; | 2581 | int err; |
| 2582 | |||
| 2583 | err = orinoco_hw_get_bitratelist(priv, &numrates, NULL, 0); | ||
| 2584 | |||
| 2585 | if (!err && (numrates > 2)) | ||
| 2586 | strcpy(name, "IEEE 802.11b"); | ||
| 2587 | else | ||
| 2588 | strcpy(name, "IEEE 802.11-DS"); | ||
| 2589 | |||
| 2590 | return 0; | ||
| 2591 | } | ||
| 2592 | |||
| 2593 | static int orinoco_ioctl_getwap(struct net_device *dev, | ||
| 2594 | struct iw_request_info *info, | ||
| 2595 | struct sockaddr *ap_addr, | ||
| 2596 | char *extra) | ||
| 2597 | { | ||
| 2598 | struct orinoco_private *priv = netdev_priv(dev); | ||
| 2599 | |||
| 2600 | hermes_t *hw = &priv->hw; | ||
| 2601 | int err = 0; | ||
| 2645 | unsigned long flags; | 2602 | unsigned long flags; |
| 2646 | 2603 | ||
| 2647 | TRACE_ENTER(dev->name); | 2604 | if (orinoco_lock(priv, &flags) != 0) |
| 2605 | return -EBUSY; | ||
| 2648 | 2606 | ||
| 2649 | if (!access_ok(VERIFY_WRITE, rrq->pointer, sizeof(range))) | 2607 | ap_addr->sa_family = ARPHRD_ETHER; |
| 2650 | return -EFAULT; | 2608 | err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_CURRENTBSSID, |
| 2609 | ETH_ALEN, NULL, ap_addr->sa_data); | ||
| 2651 | 2610 | ||
| 2652 | rrq->length = sizeof(range); | 2611 | orinoco_unlock(priv, &flags); |
| 2612 | |||
| 2613 | return err; | ||
| 2614 | } | ||
| 2615 | |||
| 2616 | static int orinoco_ioctl_setmode(struct net_device *dev, | ||
| 2617 | struct iw_request_info *info, | ||
| 2618 | u32 *mode, | ||
| 2619 | char *extra) | ||
| 2620 | { | ||
| 2621 | struct orinoco_private *priv = netdev_priv(dev); | ||
| 2622 | int err = -EINPROGRESS; /* Call commit handler */ | ||
| 2623 | unsigned long flags; | ||
| 2624 | |||
| 2625 | if (priv->iw_mode == *mode) | ||
| 2626 | return 0; | ||
| 2653 | 2627 | ||
| 2654 | if (orinoco_lock(priv, &flags) != 0) | 2628 | if (orinoco_lock(priv, &flags) != 0) |
| 2655 | return -EBUSY; | 2629 | return -EBUSY; |
| 2656 | 2630 | ||
| 2657 | mode = priv->iw_mode; | 2631 | switch (*mode) { |
| 2632 | case IW_MODE_ADHOC: | ||
| 2633 | if (!priv->has_ibss && !priv->has_port3) | ||
| 2634 | err = -EOPNOTSUPP; | ||
| 2635 | break; | ||
| 2636 | |||
| 2637 | case IW_MODE_INFRA: | ||
| 2638 | break; | ||
| 2639 | |||
| 2640 | default: | ||
| 2641 | err = -EOPNOTSUPP; | ||
| 2642 | break; | ||
| 2643 | } | ||
| 2644 | |||
| 2645 | if (err == -EINPROGRESS) { | ||
| 2646 | priv->iw_mode = *mode; | ||
| 2647 | set_port_type(priv); | ||
| 2648 | } | ||
| 2649 | |||
| 2658 | orinoco_unlock(priv, &flags); | 2650 | orinoco_unlock(priv, &flags); |
| 2659 | 2651 | ||
| 2660 | memset(&range, 0, sizeof(range)); | 2652 | return err; |
| 2653 | } | ||
| 2654 | |||
| 2655 | static int orinoco_ioctl_getmode(struct net_device *dev, | ||
| 2656 | struct iw_request_info *info, | ||
| 2657 | u32 *mode, | ||
| 2658 | char *extra) | ||
| 2659 | { | ||
| 2660 | struct orinoco_private *priv = netdev_priv(dev); | ||
| 2661 | 2661 | ||
| 2662 | /* Much of this shamelessly taken from wvlan_cs.c. No idea | 2662 | *mode = priv->iw_mode; |
| 2663 | * what it all means -dgibson */ | 2663 | return 0; |
| 2664 | range.we_version_compiled = WIRELESS_EXT; | 2664 | } |
| 2665 | range.we_version_source = 11; | ||
| 2666 | 2665 | ||
| 2667 | range.min_nwid = range.max_nwid = 0; /* We don't use nwids */ | 2666 | static int orinoco_ioctl_getiwrange(struct net_device *dev, |
| 2667 | struct iw_request_info *info, | ||
| 2668 | struct iw_point *rrq, | ||
| 2669 | char *extra) | ||
| 2670 | { | ||
| 2671 | struct orinoco_private *priv = netdev_priv(dev); | ||
| 2672 | int err = 0; | ||
| 2673 | struct iw_range *range = (struct iw_range *) extra; | ||
| 2674 | int numrates; | ||
| 2675 | int i, k; | ||
| 2676 | |||
| 2677 | TRACE_ENTER(dev->name); | ||
| 2678 | |||
| 2679 | rrq->length = sizeof(struct iw_range); | ||
| 2680 | memset(range, 0, sizeof(struct iw_range)); | ||
| 2681 | |||
| 2682 | range->we_version_compiled = WIRELESS_EXT; | ||
| 2683 | range->we_version_source = 14; | ||
| 2668 | 2684 | ||
| 2669 | /* Set available channels/frequencies */ | 2685 | /* Set available channels/frequencies */ |
| 2670 | range.num_channels = NUM_CHANNELS; | 2686 | range->num_channels = NUM_CHANNELS; |
| 2671 | k = 0; | 2687 | k = 0; |
| 2672 | for (i = 0; i < NUM_CHANNELS; i++) { | 2688 | for (i = 0; i < NUM_CHANNELS; i++) { |
| 2673 | if (priv->channel_mask & (1 << i)) { | 2689 | if (priv->channel_mask & (1 << i)) { |
| 2674 | range.freq[k].i = i + 1; | 2690 | range->freq[k].i = i + 1; |
| 2675 | range.freq[k].m = channel_frequency[i] * 100000; | 2691 | range->freq[k].m = channel_frequency[i] * 100000; |
| 2676 | range.freq[k].e = 1; | 2692 | range->freq[k].e = 1; |
| 2677 | k++; | 2693 | k++; |
| 2678 | } | 2694 | } |
| 2679 | 2695 | ||
| 2680 | if (k >= IW_MAX_FREQUENCIES) | 2696 | if (k >= IW_MAX_FREQUENCIES) |
| 2681 | break; | 2697 | break; |
| 2682 | } | 2698 | } |
| 2683 | range.num_frequency = k; | 2699 | range->num_frequency = k; |
| 2700 | range->sensitivity = 3; | ||
| 2684 | 2701 | ||
| 2685 | range.sensitivity = 3; | 2702 | if (priv->has_wep) { |
| 2703 | range->max_encoding_tokens = ORINOCO_MAX_KEYS; | ||
| 2704 | range->encoding_size[0] = SMALL_KEY_SIZE; | ||
| 2705 | range->num_encoding_sizes = 1; | ||
| 2686 | 2706 | ||
| 2687 | if ((mode == IW_MODE_ADHOC) && (priv->spy_number == 0)){ | 2707 | if (priv->has_big_wep) { |
| 2708 | range->encoding_size[1] = LARGE_KEY_SIZE; | ||
| 2709 | range->num_encoding_sizes = 2; | ||
| 2710 | } | ||
| 2711 | } | ||
| 2712 | |||
| 2713 | if ((priv->iw_mode == IW_MODE_ADHOC) && (priv->spy_number == 0)){ | ||
| 2688 | /* Quality stats meaningless in ad-hoc mode */ | 2714 | /* Quality stats meaningless in ad-hoc mode */ |
| 2689 | range.max_qual.qual = 0; | ||
| 2690 | range.max_qual.level = 0; | ||
| 2691 | range.max_qual.noise = 0; | ||
| 2692 | range.avg_qual.qual = 0; | ||
| 2693 | range.avg_qual.level = 0; | ||
| 2694 | range.avg_qual.noise = 0; | ||
| 2695 | } else { | 2715 | } else { |
| 2696 | range.max_qual.qual = 0x8b - 0x2f; | 2716 | range->max_qual.qual = 0x8b - 0x2f; |
| 2697 | range.max_qual.level = 0x2f - 0x95 - 1; | 2717 | range->max_qual.level = 0x2f - 0x95 - 1; |
| 2698 | range.max_qual.noise = 0x2f - 0x95 - 1; | 2718 | range->max_qual.noise = 0x2f - 0x95 - 1; |
| 2699 | /* Need to get better values */ | 2719 | /* Need to get better values */ |
| 2700 | range.avg_qual.qual = 0x24; | 2720 | range->avg_qual.qual = 0x24; |
| 2701 | range.avg_qual.level = 0xC2; | 2721 | range->avg_qual.level = 0xC2; |
| 2702 | range.avg_qual.noise = 0x9E; | 2722 | range->avg_qual.noise = 0x9E; |
| 2703 | } | 2723 | } |
| 2704 | 2724 | ||
| 2705 | err = orinoco_hw_get_bitratelist(priv, &numrates, | 2725 | err = orinoco_hw_get_bitratelist(priv, &numrates, |
| 2706 | range.bitrate, IW_MAX_BITRATES); | 2726 | range->bitrate, IW_MAX_BITRATES); |
| 2707 | if (err) | 2727 | if (err) |
| 2708 | return err; | 2728 | return err; |
| 2709 | range.num_bitrates = numrates; | 2729 | range->num_bitrates = numrates; |
| 2710 | 2730 | ||
| 2711 | /* Set an indication of the max TCP throughput in bit/s that we can | 2731 | /* Set an indication of the max TCP throughput in bit/s that we can |
| 2712 | * expect using this interface. May be use for QoS stuff... | 2732 | * expect using this interface. May be use for QoS stuff... |
| 2713 | * Jean II */ | 2733 | * Jean II */ |
| 2714 | if(numrates > 2) | 2734 | if (numrates > 2) |
| 2715 | range.throughput = 5 * 1000 * 1000; /* ~5 Mb/s */ | 2735 | range->throughput = 5 * 1000 * 1000; /* ~5 Mb/s */ |
| 2716 | else | 2736 | else |
| 2717 | range.throughput = 1.5 * 1000 * 1000; /* ~1.5 Mb/s */ | 2737 | range->throughput = 1.5 * 1000 * 1000; /* ~1.5 Mb/s */ |
| 2718 | 2738 | ||
| 2719 | range.min_rts = 0; | 2739 | range->min_rts = 0; |
| 2720 | range.max_rts = 2347; | 2740 | range->max_rts = 2347; |
| 2721 | range.min_frag = 256; | 2741 | range->min_frag = 256; |
| 2722 | range.max_frag = 2346; | 2742 | range->max_frag = 2346; |
| 2723 | 2743 | ||
| 2724 | if (orinoco_lock(priv, &flags) != 0) | 2744 | range->min_pmp = 0; |
| 2725 | return -EBUSY; | 2745 | range->max_pmp = 65535000; |
| 2726 | if (priv->has_wep) { | 2746 | range->min_pmt = 0; |
| 2727 | range.max_encoding_tokens = ORINOCO_MAX_KEYS; | 2747 | range->max_pmt = 65535 * 1000; /* ??? */ |
| 2728 | 2748 | range->pmp_flags = IW_POWER_PERIOD; | |
| 2729 | range.encoding_size[0] = SMALL_KEY_SIZE; | 2749 | range->pmt_flags = IW_POWER_TIMEOUT; |
| 2730 | range.num_encoding_sizes = 1; | 2750 | range->pm_capa = IW_POWER_PERIOD | IW_POWER_TIMEOUT | IW_POWER_UNICAST_R; |
| 2731 | 2751 | ||
| 2732 | if (priv->has_big_wep) { | 2752 | range->retry_capa = IW_RETRY_LIMIT | IW_RETRY_LIFETIME; |
| 2733 | range.encoding_size[1] = LARGE_KEY_SIZE; | 2753 | range->retry_flags = IW_RETRY_LIMIT; |
| 2734 | range.num_encoding_sizes = 2; | 2754 | range->r_time_flags = IW_RETRY_LIFETIME; |
| 2735 | } | 2755 | range->min_retry = 0; |
| 2736 | } else { | 2756 | range->max_retry = 65535; /* ??? */ |
| 2737 | range.num_encoding_sizes = 0; | 2757 | range->min_r_time = 0; |
| 2738 | range.max_encoding_tokens = 0; | 2758 | range->max_r_time = 65535 * 1000; /* ??? */ |
| 2739 | } | ||
| 2740 | orinoco_unlock(priv, &flags); | ||
| 2741 | |||
| 2742 | range.min_pmp = 0; | ||
| 2743 | range.max_pmp = 65535000; | ||
| 2744 | range.min_pmt = 0; | ||
| 2745 | range.max_pmt = 65535 * 1000; /* ??? */ | ||
| 2746 | range.pmp_flags = IW_POWER_PERIOD; | ||
| 2747 | range.pmt_flags = IW_POWER_TIMEOUT; | ||
| 2748 | range.pm_capa = IW_POWER_PERIOD | IW_POWER_TIMEOUT | IW_POWER_UNICAST_R; | ||
| 2749 | |||
| 2750 | range.num_txpower = 1; | ||
| 2751 | range.txpower[0] = 15; /* 15dBm */ | ||
| 2752 | range.txpower_capa = IW_TXPOW_DBM; | ||
| 2753 | |||
| 2754 | range.retry_capa = IW_RETRY_LIMIT | IW_RETRY_LIFETIME; | ||
| 2755 | range.retry_flags = IW_RETRY_LIMIT; | ||
| 2756 | range.r_time_flags = IW_RETRY_LIFETIME; | ||
| 2757 | range.min_retry = 0; | ||
| 2758 | range.max_retry = 65535; /* ??? */ | ||
| 2759 | range.min_r_time = 0; | ||
| 2760 | range.max_r_time = 65535 * 1000; /* ??? */ | ||
| 2761 | |||
| 2762 | if (copy_to_user(rrq->pointer, &range, sizeof(range))) | ||
| 2763 | return -EFAULT; | ||
| 2764 | 2759 | ||
| 2765 | TRACE_EXIT(dev->name); | 2760 | TRACE_EXIT(dev->name); |
| 2766 | 2761 | ||
| 2767 | return 0; | 2762 | return 0; |
| 2768 | } | 2763 | } |
| 2769 | 2764 | ||
| 2770 | static int orinoco_ioctl_setiwencode(struct net_device *dev, struct iw_point *erq) | 2765 | static int orinoco_ioctl_setiwencode(struct net_device *dev, |
| 2766 | struct iw_request_info *info, | ||
| 2767 | struct iw_point *erq, | ||
| 2768 | char *keybuf) | ||
| 2771 | { | 2769 | { |
| 2772 | struct orinoco_private *priv = netdev_priv(dev); | 2770 | struct orinoco_private *priv = netdev_priv(dev); |
| 2773 | int index = (erq->flags & IW_ENCODE_INDEX) - 1; | 2771 | int index = (erq->flags & IW_ENCODE_INDEX) - 1; |
| @@ -2775,8 +2773,7 @@ static int orinoco_ioctl_setiwencode(struct net_device *dev, struct iw_point *er | |||
| 2775 | int enable = priv->wep_on; | 2773 | int enable = priv->wep_on; |
| 2776 | int restricted = priv->wep_restrict; | 2774 | int restricted = priv->wep_restrict; |
| 2777 | u16 xlen = 0; | 2775 | u16 xlen = 0; |
| 2778 | int err = 0; | 2776 | int err = -EINPROGRESS; /* Call commit handler */ |
| 2779 | char keybuf[ORINOCO_MAX_KEY_SIZE]; | ||
| 2780 | unsigned long flags; | 2777 | unsigned long flags; |
| 2781 | 2778 | ||
| 2782 | if (! priv->has_wep) | 2779 | if (! priv->has_wep) |
| @@ -2789,9 +2786,6 @@ static int orinoco_ioctl_setiwencode(struct net_device *dev, struct iw_point *er | |||
| 2789 | 2786 | ||
| 2790 | if ( (erq->length > SMALL_KEY_SIZE) && !priv->has_big_wep ) | 2787 | if ( (erq->length > SMALL_KEY_SIZE) && !priv->has_big_wep ) |
| 2791 | return -E2BIG; | 2788 | return -E2BIG; |
| 2792 | |||
| 2793 | if (copy_from_user(keybuf, erq->pointer, erq->length)) | ||
| 2794 | return -EFAULT; | ||
| 2795 | } | 2789 | } |
| 2796 | 2790 | ||
| 2797 | if (orinoco_lock(priv, &flags) != 0) | 2791 | if (orinoco_lock(priv, &flags) != 0) |
| @@ -2865,12 +2859,14 @@ static int orinoco_ioctl_setiwencode(struct net_device *dev, struct iw_point *er | |||
| 2865 | return err; | 2859 | return err; |
| 2866 | } | 2860 | } |
| 2867 | 2861 | ||
| 2868 | static int orinoco_ioctl_getiwencode(struct net_device *dev, struct iw_point *erq) | 2862 | static int orinoco_ioctl_getiwencode(struct net_device *dev, |
| 2863 | struct iw_request_info *info, | ||
| 2864 | struct iw_point *erq, | ||
| 2865 | char *keybuf) | ||
| 2869 | { | 2866 | { |
| 2870 | struct orinoco_private *priv = netdev_priv(dev); | 2867 | struct orinoco_private *priv = netdev_priv(dev); |
| 2871 | int index = (erq->flags & IW_ENCODE_INDEX) - 1; | 2868 | int index = (erq->flags & IW_ENCODE_INDEX) - 1; |
| 2872 | u16 xlen = 0; | 2869 | u16 xlen = 0; |
| 2873 | char keybuf[ORINOCO_MAX_KEY_SIZE]; | ||
| 2874 | unsigned long flags; | 2870 | unsigned long flags; |
| 2875 | 2871 | ||
| 2876 | if (! priv->has_wep) | 2872 | if (! priv->has_wep) |
| @@ -2899,51 +2895,47 @@ static int orinoco_ioctl_getiwencode(struct net_device *dev, struct iw_point *er | |||
| 2899 | memcpy(keybuf, priv->keys[index].data, ORINOCO_MAX_KEY_SIZE); | 2895 | memcpy(keybuf, priv->keys[index].data, ORINOCO_MAX_KEY_SIZE); |
| 2900 | 2896 | ||
| 2901 | orinoco_unlock(priv, &flags); | 2897 | orinoco_unlock(priv, &flags); |
| 2902 | |||
| 2903 | if (erq->pointer) { | ||
| 2904 | if (copy_to_user(erq->pointer, keybuf, xlen)) | ||
| 2905 | return -EFAULT; | ||
| 2906 | } | ||
| 2907 | |||
| 2908 | return 0; | 2898 | return 0; |
| 2909 | } | 2899 | } |
| 2910 | 2900 | ||
| 2911 | static int orinoco_ioctl_setessid(struct net_device *dev, struct iw_point *erq) | 2901 | static int orinoco_ioctl_setessid(struct net_device *dev, |
| 2902 | struct iw_request_info *info, | ||
| 2903 | struct iw_point *erq, | ||
| 2904 | char *essidbuf) | ||
| 2912 | { | 2905 | { |
| 2913 | struct orinoco_private *priv = netdev_priv(dev); | 2906 | struct orinoco_private *priv = netdev_priv(dev); |
| 2914 | char essidbuf[IW_ESSID_MAX_SIZE+1]; | ||
| 2915 | unsigned long flags; | 2907 | unsigned long flags; |
| 2916 | 2908 | ||
| 2917 | /* Note : ESSID is ignored in Ad-Hoc demo mode, but we can set it | 2909 | /* Note : ESSID is ignored in Ad-Hoc demo mode, but we can set it |
| 2918 | * anyway... - Jean II */ | 2910 | * anyway... - Jean II */ |
| 2919 | 2911 | ||
| 2920 | memset(&essidbuf, 0, sizeof(essidbuf)); | 2912 | /* Hum... Should not use Wireless Extension constant (may change), |
| 2921 | 2913 | * should use our own... - Jean II */ | |
| 2922 | if (erq->flags) { | 2914 | if (erq->length > IW_ESSID_MAX_SIZE) |
| 2923 | /* iwconfig includes the NUL in the specified length */ | 2915 | return -E2BIG; |
| 2924 | if (erq->length > IW_ESSID_MAX_SIZE+1) | ||
| 2925 | return -E2BIG; | ||
| 2926 | |||
| 2927 | if (copy_from_user(&essidbuf, erq->pointer, erq->length)) | ||
| 2928 | return -EFAULT; | ||
| 2929 | |||
| 2930 | essidbuf[IW_ESSID_MAX_SIZE] = '\0'; | ||
| 2931 | } | ||
| 2932 | 2916 | ||
| 2933 | if (orinoco_lock(priv, &flags) != 0) | 2917 | if (orinoco_lock(priv, &flags) != 0) |
| 2934 | return -EBUSY; | 2918 | return -EBUSY; |
| 2935 | 2919 | ||
| 2936 | memcpy(priv->desired_essid, essidbuf, sizeof(priv->desired_essid)); | 2920 | /* NULL the string (for NULL termination & ESSID = ANY) - Jean II */ |
| 2921 | memset(priv->desired_essid, 0, sizeof(priv->desired_essid)); | ||
| 2922 | |||
| 2923 | /* If not ANY, get the new ESSID */ | ||
| 2924 | if (erq->flags) { | ||
| 2925 | memcpy(priv->desired_essid, essidbuf, erq->length); | ||
| 2926 | } | ||
| 2937 | 2927 | ||
| 2938 | orinoco_unlock(priv, &flags); | 2928 | orinoco_unlock(priv, &flags); |
| 2939 | 2929 | ||
| 2940 | return 0; | 2930 | return -EINPROGRESS; /* Call commit handler */ |
| 2941 | } | 2931 | } |
| 2942 | 2932 | ||
| 2943 | static int orinoco_ioctl_getessid(struct net_device *dev, struct iw_point *erq) | 2933 | static int orinoco_ioctl_getessid(struct net_device *dev, |
| 2934 | struct iw_request_info *info, | ||
| 2935 | struct iw_point *erq, | ||
| 2936 | char *essidbuf) | ||
| 2944 | { | 2937 | { |
| 2945 | struct orinoco_private *priv = netdev_priv(dev); | 2938 | struct orinoco_private *priv = netdev_priv(dev); |
| 2946 | char essidbuf[IW_ESSID_MAX_SIZE+1]; | ||
| 2947 | int active; | 2939 | int active; |
| 2948 | int err = 0; | 2940 | int err = 0; |
| 2949 | unsigned long flags; | 2941 | unsigned long flags; |
| @@ -2957,51 +2949,46 @@ static int orinoco_ioctl_getessid(struct net_device *dev, struct iw_point *erq) | |||
| 2957 | } else { | 2949 | } else { |
| 2958 | if (orinoco_lock(priv, &flags) != 0) | 2950 | if (orinoco_lock(priv, &flags) != 0) |
| 2959 | return -EBUSY; | 2951 | return -EBUSY; |
| 2960 | memcpy(essidbuf, priv->desired_essid, sizeof(essidbuf)); | 2952 | memcpy(essidbuf, priv->desired_essid, IW_ESSID_MAX_SIZE + 1); |
| 2961 | orinoco_unlock(priv, &flags); | 2953 | orinoco_unlock(priv, &flags); |
| 2962 | } | 2954 | } |
| 2963 | 2955 | ||
| 2964 | erq->flags = 1; | 2956 | erq->flags = 1; |
| 2965 | erq->length = strlen(essidbuf) + 1; | 2957 | erq->length = strlen(essidbuf) + 1; |
| 2966 | if (erq->pointer) | ||
| 2967 | if (copy_to_user(erq->pointer, essidbuf, erq->length)) | ||
| 2968 | return -EFAULT; | ||
| 2969 | 2958 | ||
| 2970 | TRACE_EXIT(dev->name); | 2959 | TRACE_EXIT(dev->name); |
| 2971 | 2960 | ||
| 2972 | return 0; | 2961 | return 0; |
| 2973 | } | 2962 | } |
| 2974 | 2963 | ||
| 2975 | static int orinoco_ioctl_setnick(struct net_device *dev, struct iw_point *nrq) | 2964 | static int orinoco_ioctl_setnick(struct net_device *dev, |
| 2965 | struct iw_request_info *info, | ||
| 2966 | struct iw_point *nrq, | ||
| 2967 | char *nickbuf) | ||
| 2976 | { | 2968 | { |
| 2977 | struct orinoco_private *priv = netdev_priv(dev); | 2969 | struct orinoco_private *priv = netdev_priv(dev); |
| 2978 | char nickbuf[IW_ESSID_MAX_SIZE+1]; | ||
| 2979 | unsigned long flags; | 2970 | unsigned long flags; |
| 2980 | 2971 | ||
| 2981 | if (nrq->length > IW_ESSID_MAX_SIZE) | 2972 | if (nrq->length > IW_ESSID_MAX_SIZE) |
| 2982 | return -E2BIG; | 2973 | return -E2BIG; |
| 2983 | 2974 | ||
| 2984 | memset(nickbuf, 0, sizeof(nickbuf)); | ||
| 2985 | |||
| 2986 | if (copy_from_user(nickbuf, nrq->pointer, nrq->length)) | ||
| 2987 | return -EFAULT; | ||
| 2988 | |||
| 2989 | nickbuf[nrq->length] = '\0'; | ||
| 2990 | |||
| 2991 | if (orinoco_lock(priv, &flags) != 0) | 2975 | if (orinoco_lock(priv, &flags) != 0) |
| 2992 | return -EBUSY; | 2976 | return -EBUSY; |
| 2993 | 2977 | ||
| 2994 | memcpy(priv->nick, nickbuf, sizeof(priv->nick)); | 2978 | memset(priv->nick, 0, sizeof(priv->nick)); |
| 2979 | memcpy(priv->nick, nickbuf, nrq->length); | ||
| 2995 | 2980 | ||
| 2996 | orinoco_unlock(priv, &flags); | 2981 | orinoco_unlock(priv, &flags); |
| 2997 | 2982 | ||
| 2998 | return 0; | 2983 | return -EINPROGRESS; /* Call commit handler */ |
| 2999 | } | 2984 | } |
| 3000 | 2985 | ||
| 3001 | static int orinoco_ioctl_getnick(struct net_device *dev, struct iw_point *nrq) | 2986 | static int orinoco_ioctl_getnick(struct net_device *dev, |
| 2987 | struct iw_request_info *info, | ||
| 2988 | struct iw_point *nrq, | ||
| 2989 | char *nickbuf) | ||
| 3002 | { | 2990 | { |
| 3003 | struct orinoco_private *priv = netdev_priv(dev); | 2991 | struct orinoco_private *priv = netdev_priv(dev); |
| 3004 | char nickbuf[IW_ESSID_MAX_SIZE+1]; | ||
| 3005 | unsigned long flags; | 2992 | unsigned long flags; |
| 3006 | 2993 | ||
| 3007 | if (orinoco_lock(priv, &flags) != 0) | 2994 | if (orinoco_lock(priv, &flags) != 0) |
| @@ -3012,17 +2999,18 @@ static int orinoco_ioctl_getnick(struct net_device *dev, struct iw_point *nrq) | |||
| 3012 | 2999 | ||
| 3013 | nrq->length = strlen(nickbuf)+1; | 3000 | nrq->length = strlen(nickbuf)+1; |
| 3014 | 3001 | ||
| 3015 | if (copy_to_user(nrq->pointer, nickbuf, sizeof(nickbuf))) | ||
| 3016 | return -EFAULT; | ||
| 3017 | |||
| 3018 | return 0; | 3002 | return 0; |
| 3019 | } | 3003 | } |
| 3020 | 3004 | ||
| 3021 | static int orinoco_ioctl_setfreq(struct net_device *dev, struct iw_freq *frq) | 3005 | static int orinoco_ioctl_setfreq(struct net_device *dev, |
| 3006 | struct iw_request_info *info, | ||
| 3007 | struct iw_freq *frq, | ||
| 3008 | char *extra) | ||
| 3022 | { | 3009 | { |
| 3023 | struct orinoco_private *priv = netdev_priv(dev); | 3010 | struct orinoco_private *priv = netdev_priv(dev); |
| 3024 | int chan = -1; | 3011 | int chan = -1; |
| 3025 | unsigned long flags; | 3012 | unsigned long flags; |
| 3013 | int err = -EINPROGRESS; /* Call commit handler */ | ||
| 3026 | 3014 | ||
| 3027 | /* We can only use this in Ad-Hoc demo mode to set the operating | 3015 | /* We can only use this in Ad-Hoc demo mode to set the operating |
| 3028 | * frequency, or in IBSS mode to set the frequency where the IBSS | 3016 | * frequency, or in IBSS mode to set the frequency where the IBSS |
| @@ -3055,10 +3043,33 @@ static int orinoco_ioctl_setfreq(struct net_device *dev, struct iw_freq *frq) | |||
| 3055 | priv->channel = chan; | 3043 | priv->channel = chan; |
| 3056 | orinoco_unlock(priv, &flags); | 3044 | orinoco_unlock(priv, &flags); |
| 3057 | 3045 | ||
| 3046 | return err; | ||
| 3047 | } | ||
| 3048 | |||
| 3049 | static int orinoco_ioctl_getfreq(struct net_device *dev, | ||
| 3050 | struct iw_request_info *info, | ||
| 3051 | struct iw_freq *frq, | ||
| 3052 | char *extra) | ||
| 3053 | { | ||
| 3054 | struct orinoco_private *priv = netdev_priv(dev); | ||
| 3055 | int tmp; | ||
| 3056 | |||
| 3057 | /* Locking done in there */ | ||
| 3058 | tmp = orinoco_hw_get_freq(priv); | ||
| 3059 | if (tmp < 0) { | ||
| 3060 | return tmp; | ||
| 3061 | } | ||
| 3062 | |||
| 3063 | frq->m = tmp; | ||
| 3064 | frq->e = 1; | ||
| 3065 | |||
| 3058 | return 0; | 3066 | return 0; |
| 3059 | } | 3067 | } |
| 3060 | 3068 | ||
| 3061 | static int orinoco_ioctl_getsens(struct net_device *dev, struct iw_param *srq) | 3069 | static int orinoco_ioctl_getsens(struct net_device *dev, |
| 3070 | struct iw_request_info *info, | ||
| 3071 | struct iw_param *srq, | ||
| 3072 | char *extra) | ||
| 3062 | { | 3073 | { |
| 3063 | struct orinoco_private *priv = netdev_priv(dev); | 3074 | struct orinoco_private *priv = netdev_priv(dev); |
| 3064 | hermes_t *hw = &priv->hw; | 3075 | hermes_t *hw = &priv->hw; |
| @@ -3084,7 +3095,10 @@ static int orinoco_ioctl_getsens(struct net_device *dev, struct iw_param *srq) | |||
| 3084 | return 0; | 3095 | return 0; |
| 3085 | } | 3096 | } |
| 3086 | 3097 | ||
| 3087 | static int orinoco_ioctl_setsens(struct net_device *dev, struct iw_param *srq) | 3098 | static int orinoco_ioctl_setsens(struct net_device *dev, |
| 3099 | struct iw_request_info *info, | ||
| 3100 | struct iw_param *srq, | ||
| 3101 | char *extra) | ||
| 3088 | { | 3102 | { |
| 3089 | struct orinoco_private *priv = netdev_priv(dev); | 3103 | struct orinoco_private *priv = netdev_priv(dev); |
| 3090 | int val = srq->value; | 3104 | int val = srq->value; |
| @@ -3101,10 +3115,13 @@ static int orinoco_ioctl_setsens(struct net_device *dev, struct iw_param *srq) | |||
| 3101 | priv->ap_density = val; | 3115 | priv->ap_density = val; |
| 3102 | orinoco_unlock(priv, &flags); | 3116 | orinoco_unlock(priv, &flags); |
| 3103 | 3117 | ||
| 3104 | return 0; | 3118 | return -EINPROGRESS; /* Call commit handler */ |
| 3105 | } | 3119 | } |
| 3106 | 3120 | ||
| 3107 | static int orinoco_ioctl_setrts(struct net_device *dev, struct iw_param *rrq) | 3121 | static int orinoco_ioctl_setrts(struct net_device *dev, |
| 3122 | struct iw_request_info *info, | ||
| 3123 | struct iw_param *rrq, | ||
| 3124 | char *extra) | ||
| 3108 | { | 3125 | { |
| 3109 | struct orinoco_private *priv = netdev_priv(dev); | 3126 | struct orinoco_private *priv = netdev_priv(dev); |
| 3110 | int val = rrq->value; | 3127 | int val = rrq->value; |
| @@ -3122,13 +3139,30 @@ static int orinoco_ioctl_setrts(struct net_device *dev, struct iw_param *rrq) | |||
| 3122 | priv->rts_thresh = val; | 3139 | priv->rts_thresh = val; |
| 3123 | orinoco_unlock(priv, &flags); | 3140 | orinoco_unlock(priv, &flags); |
| 3124 | 3141 | ||
| 3142 | return -EINPROGRESS; /* Call commit handler */ | ||
| 3143 | } | ||
| 3144 | |||
| 3145 | static int orinoco_ioctl_getrts(struct net_device *dev, | ||
| 3146 | struct iw_request_info *info, | ||
| 3147 | struct iw_param *rrq, | ||
| 3148 | char *extra) | ||
| 3149 | { | ||
| 3150 | struct orinoco_private *priv = netdev_priv(dev); | ||
| 3151 | |||
| 3152 | rrq->value = priv->rts_thresh; | ||
| 3153 | rrq->disabled = (rrq->value == 2347); | ||
| 3154 | rrq->fixed = 1; | ||
| 3155 | |||
| 3125 | return 0; | 3156 | return 0; |
| 3126 | } | 3157 | } |
| 3127 | 3158 | ||
| 3128 | static int orinoco_ioctl_setfrag(struct net_device *dev, struct iw_param *frq) | 3159 | static int orinoco_ioctl_setfrag(struct net_device *dev, |
| 3160 | struct iw_request_info *info, | ||
| 3161 | struct iw_param *frq, | ||
| 3162 | char *extra) | ||
| 3129 | { | 3163 | { |
| 3130 | struct orinoco_private *priv = netdev_priv(dev); | 3164 | struct orinoco_private *priv = netdev_priv(dev); |
| 3131 | int err = 0; | 3165 | int err = -EINPROGRESS; /* Call commit handler */ |
| 3132 | unsigned long flags; | 3166 | unsigned long flags; |
| 3133 | 3167 | ||
| 3134 | if (orinoco_lock(priv, &flags) != 0) | 3168 | if (orinoco_lock(priv, &flags) != 0) |
| @@ -3160,11 +3194,14 @@ static int orinoco_ioctl_setfrag(struct net_device *dev, struct iw_param *frq) | |||
| 3160 | return err; | 3194 | return err; |
| 3161 | } | 3195 | } |
| 3162 | 3196 | ||
| 3163 | static int orinoco_ioctl_getfrag(struct net_device *dev, struct iw_param *frq) | 3197 | static int orinoco_ioctl_getfrag(struct net_device *dev, |
| 3198 | struct iw_request_info *info, | ||
| 3199 | struct iw_param *frq, | ||
| 3200 | char *extra) | ||
| 3164 | { | 3201 | { |
| 3165 | struct orinoco_private *priv = netdev_priv(dev); | 3202 | struct orinoco_private *priv = netdev_priv(dev); |
| 3166 | hermes_t *hw = &priv->hw; | 3203 | hermes_t *hw = &priv->hw; |
| 3167 | int err = 0; | 3204 | int err; |
| 3168 | u16 val; | 3205 | u16 val; |
| 3169 | unsigned long flags; | 3206 | unsigned long flags; |
| 3170 | 3207 | ||
| @@ -3197,10 +3234,12 @@ static int orinoco_ioctl_getfrag(struct net_device *dev, struct iw_param *frq) | |||
| 3197 | return err; | 3234 | return err; |
| 3198 | } | 3235 | } |
| 3199 | 3236 | ||
| 3200 | static int orinoco_ioctl_setrate(struct net_device *dev, struct iw_param *rrq) | 3237 | static int orinoco_ioctl_setrate(struct net_device *dev, |
| 3238 | struct iw_request_info *info, | ||
| 3239 | struct iw_param *rrq, | ||
| 3240 | char *extra) | ||
| 3201 | { | 3241 | { |
| 3202 | struct orinoco_private *priv = netdev_priv(dev); | 3242 | struct orinoco_private *priv = netdev_priv(dev); |
| 3203 | int err = 0; | ||
| 3204 | int ratemode = -1; | 3243 | int ratemode = -1; |
| 3205 | int bitrate; /* 100s of kilobits */ | 3244 | int bitrate; /* 100s of kilobits */ |
| 3206 | int i; | 3245 | int i; |
| @@ -3236,10 +3275,13 @@ static int orinoco_ioctl_setrate(struct net_device *dev, struct iw_param *rrq) | |||
| 3236 | priv->bitratemode = ratemode; | 3275 | priv->bitratemode = ratemode; |
| 3237 | orinoco_unlock(priv, &flags); | 3276 | orinoco_unlock(priv, &flags); |
| 3238 | 3277 | ||
| 3239 | return err; | 3278 | return -EINPROGRESS; |
| 3240 | } | 3279 | } |
| 3241 | 3280 | ||
| 3242 | static int orinoco_ioctl_getrate(struct net_device *dev, struct iw_param *rrq) | 3281 | static int orinoco_ioctl_getrate(struct net_device *dev, |
| 3282 | struct iw_request_info *info, | ||
| 3283 | struct iw_param *rrq, | ||
| 3284 | char *extra) | ||
| 3243 | { | 3285 | { |
| 3244 | struct orinoco_private *priv = netdev_priv(dev); | 3286 | struct orinoco_private *priv = netdev_priv(dev); |
| 3245 | hermes_t *hw = &priv->hw; | 3287 | hermes_t *hw = &priv->hw; |
| @@ -3304,10 +3346,13 @@ static int orinoco_ioctl_getrate(struct net_device *dev, struct iw_param *rrq) | |||
| 3304 | return err; | 3346 | return err; |
| 3305 | } | 3347 | } |
| 3306 | 3348 | ||
| 3307 | static int orinoco_ioctl_setpower(struct net_device *dev, struct iw_param *prq) | 3349 | static int orinoco_ioctl_setpower(struct net_device *dev, |
| 3350 | struct iw_request_info *info, | ||
| 3351 | struct iw_param *prq, | ||
| 3352 | char *extra) | ||
| 3308 | { | 3353 | { |
| 3309 | struct orinoco_private *priv = netdev_priv(dev); | 3354 | struct orinoco_private *priv = netdev_priv(dev); |
| 3310 | int err = 0; | 3355 | int err = -EINPROGRESS; /* Call commit handler */ |
| 3311 | unsigned long flags; | 3356 | unsigned long flags; |
| 3312 | 3357 | ||
| 3313 | if (orinoco_lock(priv, &flags) != 0) | 3358 | if (orinoco_lock(priv, &flags) != 0) |
| @@ -3356,7 +3401,10 @@ static int orinoco_ioctl_setpower(struct net_device *dev, struct iw_param *prq) | |||
| 3356 | return err; | 3401 | return err; |
| 3357 | } | 3402 | } |
| 3358 | 3403 | ||
| 3359 | static int orinoco_ioctl_getpower(struct net_device *dev, struct iw_param *prq) | 3404 | static int orinoco_ioctl_getpower(struct net_device *dev, |
| 3405 | struct iw_request_info *info, | ||
| 3406 | struct iw_param *prq, | ||
| 3407 | char *extra) | ||
| 3360 | { | 3408 | { |
| 3361 | struct orinoco_private *priv = netdev_priv(dev); | 3409 | struct orinoco_private *priv = netdev_priv(dev); |
| 3362 | hermes_t *hw = &priv->hw; | 3410 | hermes_t *hw = &priv->hw; |
| @@ -3404,7 +3452,10 @@ static int orinoco_ioctl_getpower(struct net_device *dev, struct iw_param *prq) | |||
| 3404 | return err; | 3452 | return err; |
| 3405 | } | 3453 | } |
| 3406 | 3454 | ||
| 3407 | static int orinoco_ioctl_getretry(struct net_device *dev, struct iw_param *rrq) | 3455 | static int orinoco_ioctl_getretry(struct net_device *dev, |
| 3456 | struct iw_request_info *info, | ||
| 3457 | struct iw_param *rrq, | ||
| 3458 | char *extra) | ||
| 3408 | { | 3459 | { |
| 3409 | struct orinoco_private *priv = netdev_priv(dev); | 3460 | struct orinoco_private *priv = netdev_priv(dev); |
| 3410 | hermes_t *hw = &priv->hw; | 3461 | hermes_t *hw = &priv->hw; |
| @@ -3455,10 +3506,38 @@ static int orinoco_ioctl_getretry(struct net_device *dev, struct iw_param *rrq) | |||
| 3455 | return err; | 3506 | return err; |
| 3456 | } | 3507 | } |
| 3457 | 3508 | ||
| 3458 | static int orinoco_ioctl_setibssport(struct net_device *dev, struct iwreq *wrq) | 3509 | static int orinoco_ioctl_reset(struct net_device *dev, |
| 3510 | struct iw_request_info *info, | ||
| 3511 | void *wrqu, | ||
| 3512 | char *extra) | ||
| 3513 | { | ||
| 3514 | struct orinoco_private *priv = netdev_priv(dev); | ||
| 3515 | |||
| 3516 | if (! capable(CAP_NET_ADMIN)) | ||
| 3517 | return -EPERM; | ||
| 3518 | |||
| 3519 | if (info->cmd == (SIOCIWFIRSTPRIV + 0x1)) { | ||
| 3520 | printk(KERN_DEBUG "%s: Forcing reset!\n", dev->name); | ||
| 3521 | |||
| 3522 | /* Firmware reset */ | ||
| 3523 | orinoco_reset(dev); | ||
| 3524 | } else { | ||
| 3525 | printk(KERN_DEBUG "%s: Force scheduling reset!\n", dev->name); | ||
| 3526 | |||
| 3527 | schedule_work(&priv->reset_work); | ||
| 3528 | } | ||
| 3529 | |||
| 3530 | return 0; | ||
| 3531 | } | ||
| 3532 | |||
| 3533 | static int orinoco_ioctl_setibssport(struct net_device *dev, | ||
| 3534 | struct iw_request_info *info, | ||
| 3535 | void *wrqu, | ||
| 3536 | char *extra) | ||
| 3537 | |||
| 3459 | { | 3538 | { |
| 3460 | struct orinoco_private *priv = netdev_priv(dev); | 3539 | struct orinoco_private *priv = netdev_priv(dev); |
| 3461 | int val = *( (int *) wrq->u.name ); | 3540 | int val = *( (int *) extra ); |
| 3462 | unsigned long flags; | 3541 | unsigned long flags; |
| 3463 | 3542 | ||
| 3464 | if (orinoco_lock(priv, &flags) != 0) | 3543 | if (orinoco_lock(priv, &flags) != 0) |
| @@ -3470,28 +3549,28 @@ static int orinoco_ioctl_setibssport(struct net_device *dev, struct iwreq *wrq) | |||
| 3470 | set_port_type(priv); | 3549 | set_port_type(priv); |
| 3471 | 3550 | ||
| 3472 | orinoco_unlock(priv, &flags); | 3551 | orinoco_unlock(priv, &flags); |
| 3473 | return 0; | 3552 | return -EINPROGRESS; /* Call commit handler */ |
| 3474 | } | 3553 | } |
| 3475 | 3554 | ||
| 3476 | static int orinoco_ioctl_getibssport(struct net_device *dev, struct iwreq *wrq) | 3555 | static int orinoco_ioctl_getibssport(struct net_device *dev, |
| 3556 | struct iw_request_info *info, | ||
| 3557 | void *wrqu, | ||
| 3558 | char *extra) | ||
| 3477 | { | 3559 | { |
| 3478 | struct orinoco_private *priv = netdev_priv(dev); | 3560 | struct orinoco_private *priv = netdev_priv(dev); |
| 3479 | int *val = (int *)wrq->u.name; | 3561 | int *val = (int *) extra; |
| 3480 | unsigned long flags; | ||
| 3481 | |||
| 3482 | if (orinoco_lock(priv, &flags) != 0) | ||
| 3483 | return -EBUSY; | ||
| 3484 | 3562 | ||
| 3485 | *val = priv->ibss_port; | 3563 | *val = priv->ibss_port; |
| 3486 | orinoco_unlock(priv, &flags); | ||
| 3487 | |||
| 3488 | return 0; | 3564 | return 0; |
| 3489 | } | 3565 | } |
| 3490 | 3566 | ||
| 3491 | static int orinoco_ioctl_setport3(struct net_device *dev, struct iwreq *wrq) | 3567 | static int orinoco_ioctl_setport3(struct net_device *dev, |
| 3568 | struct iw_request_info *info, | ||
| 3569 | void *wrqu, | ||
| 3570 | char *extra) | ||
| 3492 | { | 3571 | { |
| 3493 | struct orinoco_private *priv = netdev_priv(dev); | 3572 | struct orinoco_private *priv = netdev_priv(dev); |
| 3494 | int val = *( (int *) wrq->u.name ); | 3573 | int val = *( (int *) extra ); |
| 3495 | int err = 0; | 3574 | int err = 0; |
| 3496 | unsigned long flags; | 3575 | unsigned long flags; |
| 3497 | 3576 | ||
| @@ -3520,51 +3599,131 @@ static int orinoco_ioctl_setport3(struct net_device *dev, struct iwreq *wrq) | |||
| 3520 | err = -EINVAL; | 3599 | err = -EINVAL; |
| 3521 | } | 3600 | } |
| 3522 | 3601 | ||
| 3523 | if (! err) | 3602 | if (! err) { |
| 3524 | /* Actually update the mode we are using */ | 3603 | /* Actually update the mode we are using */ |
| 3525 | set_port_type(priv); | 3604 | set_port_type(priv); |
| 3605 | err = -EINPROGRESS; | ||
| 3606 | } | ||
| 3526 | 3607 | ||
| 3527 | orinoco_unlock(priv, &flags); | 3608 | orinoco_unlock(priv, &flags); |
| 3528 | 3609 | ||
| 3529 | return err; | 3610 | return err; |
| 3530 | } | 3611 | } |
| 3531 | 3612 | ||
| 3532 | static int orinoco_ioctl_getport3(struct net_device *dev, struct iwreq *wrq) | 3613 | static int orinoco_ioctl_getport3(struct net_device *dev, |
| 3614 | struct iw_request_info *info, | ||
| 3615 | void *wrqu, | ||
| 3616 | char *extra) | ||
| 3617 | { | ||
| 3618 | struct orinoco_private *priv = netdev_priv(dev); | ||
| 3619 | int *val = (int *) extra; | ||
| 3620 | |||
| 3621 | *val = priv->prefer_port3; | ||
| 3622 | return 0; | ||
| 3623 | } | ||
| 3624 | |||
| 3625 | static int orinoco_ioctl_setpreamble(struct net_device *dev, | ||
| 3626 | struct iw_request_info *info, | ||
| 3627 | void *wrqu, | ||
| 3628 | char *extra) | ||
| 3533 | { | 3629 | { |
| 3534 | struct orinoco_private *priv = netdev_priv(dev); | 3630 | struct orinoco_private *priv = netdev_priv(dev); |
| 3535 | int *val = (int *)wrq->u.name; | ||
| 3536 | unsigned long flags; | 3631 | unsigned long flags; |
| 3632 | int val; | ||
| 3633 | |||
| 3634 | if (! priv->has_preamble) | ||
| 3635 | return -EOPNOTSUPP; | ||
| 3636 | |||
| 3637 | /* 802.11b has recently defined some short preamble. | ||
| 3638 | * Basically, the Phy header has been reduced in size. | ||
| 3639 | * This increase performance, especially at high rates | ||
| 3640 | * (the preamble is transmitted at 1Mb/s), unfortunately | ||
| 3641 | * this give compatibility troubles... - Jean II */ | ||
| 3642 | val = *( (int *) extra ); | ||
| 3537 | 3643 | ||
| 3538 | if (orinoco_lock(priv, &flags) != 0) | 3644 | if (orinoco_lock(priv, &flags) != 0) |
| 3539 | return -EBUSY; | 3645 | return -EBUSY; |
| 3540 | 3646 | ||
| 3541 | *val = priv->prefer_port3; | 3647 | if (val) |
| 3648 | priv->preamble = 1; | ||
| 3649 | else | ||
| 3650 | priv->preamble = 0; | ||
| 3651 | |||
| 3542 | orinoco_unlock(priv, &flags); | 3652 | orinoco_unlock(priv, &flags); |
| 3653 | |||
| 3654 | return -EINPROGRESS; /* Call commit handler */ | ||
| 3655 | } | ||
| 3656 | |||
| 3657 | static int orinoco_ioctl_getpreamble(struct net_device *dev, | ||
| 3658 | struct iw_request_info *info, | ||
| 3659 | void *wrqu, | ||
| 3660 | char *extra) | ||
| 3661 | { | ||
| 3662 | struct orinoco_private *priv = netdev_priv(dev); | ||
| 3663 | int *val = (int *) extra; | ||
| 3664 | |||
| 3665 | if (! priv->has_preamble) | ||
| 3666 | return -EOPNOTSUPP; | ||
| 3667 | |||
| 3668 | *val = priv->preamble; | ||
| 3543 | return 0; | 3669 | return 0; |
| 3544 | } | 3670 | } |
| 3545 | 3671 | ||
| 3672 | /* ioctl interface to hermes_read_ltv() | ||
| 3673 | * To use with iwpriv, pass the RID as the token argument, e.g. | ||
| 3674 | * iwpriv get_rid [0xfc00] | ||
| 3675 | * At least Wireless Tools 25 is required to use iwpriv. | ||
| 3676 | * For Wireless Tools 25 and 26 append "dummy" are the end. */ | ||
| 3677 | static int orinoco_ioctl_getrid(struct net_device *dev, | ||
| 3678 | struct iw_request_info *info, | ||
| 3679 | struct iw_point *data, | ||
| 3680 | char *extra) | ||
| 3681 | { | ||
| 3682 | struct orinoco_private *priv = netdev_priv(dev); | ||
| 3683 | hermes_t *hw = &priv->hw; | ||
| 3684 | int rid = data->flags; | ||
| 3685 | u16 length; | ||
| 3686 | int err; | ||
| 3687 | unsigned long flags; | ||
| 3688 | |||
| 3689 | /* It's a "get" function, but we don't want users to access the | ||
| 3690 | * WEP key and other raw firmware data */ | ||
| 3691 | if (! capable(CAP_NET_ADMIN)) | ||
| 3692 | return -EPERM; | ||
| 3693 | |||
| 3694 | if (rid < 0xfc00 || rid > 0xffff) | ||
| 3695 | return -EINVAL; | ||
| 3696 | |||
| 3697 | if (orinoco_lock(priv, &flags) != 0) | ||
| 3698 | return -EBUSY; | ||
| 3699 | |||
| 3700 | err = hermes_read_ltv(hw, USER_BAP, rid, MAX_RID_LEN, &length, | ||
| 3701 | extra); | ||
| 3702 | if (err) | ||
| 3703 | goto out; | ||
| 3704 | |||
| 3705 | data->length = min_t(u16, HERMES_RECLEN_TO_BYTES(length), | ||
| 3706 | MAX_RID_LEN); | ||
| 3707 | |||
| 3708 | out: | ||
| 3709 | orinoco_unlock(priv, &flags); | ||
| 3710 | return err; | ||
| 3711 | } | ||
| 3712 | |||
| 3546 | /* Spy is used for link quality/strength measurements in Ad-Hoc mode | 3713 | /* Spy is used for link quality/strength measurements in Ad-Hoc mode |
| 3547 | * Jean II */ | 3714 | * Jean II */ |
| 3548 | static int orinoco_ioctl_setspy(struct net_device *dev, struct iw_point *srq) | 3715 | static int orinoco_ioctl_setspy(struct net_device *dev, |
| 3716 | struct iw_request_info *info, | ||
| 3717 | struct iw_point *srq, | ||
| 3718 | char *extra) | ||
| 3719 | |||
| 3549 | { | 3720 | { |
| 3550 | struct orinoco_private *priv = netdev_priv(dev); | 3721 | struct orinoco_private *priv = netdev_priv(dev); |
| 3551 | struct sockaddr address[IW_MAX_SPY]; | 3722 | struct sockaddr *address = (struct sockaddr *) extra; |
| 3552 | int number = srq->length; | 3723 | int number = srq->length; |
| 3553 | int i; | 3724 | int i; |
| 3554 | int err = 0; | ||
| 3555 | unsigned long flags; | 3725 | unsigned long flags; |
| 3556 | 3726 | ||
| 3557 | /* Check the number of addresses */ | ||
| 3558 | if (number > IW_MAX_SPY) | ||
| 3559 | return -E2BIG; | ||
| 3560 | |||
| 3561 | /* Get the data in the driver */ | ||
| 3562 | if (srq->pointer) { | ||
| 3563 | if (copy_from_user(address, srq->pointer, | ||
| 3564 | sizeof(struct sockaddr) * number)) | ||
| 3565 | return -EFAULT; | ||
| 3566 | } | ||
| 3567 | |||
| 3568 | /* Make sure nobody mess with the structure while we do */ | 3727 | /* Make sure nobody mess with the structure while we do */ |
| 3569 | if (orinoco_lock(priv, &flags) != 0) | 3728 | if (orinoco_lock(priv, &flags) != 0) |
| 3570 | return -EBUSY; | 3729 | return -EBUSY; |
| @@ -3588,14 +3747,17 @@ static int orinoco_ioctl_setspy(struct net_device *dev, struct iw_point *srq) | |||
| 3588 | /* Now, let the others play */ | 3747 | /* Now, let the others play */ |
| 3589 | orinoco_unlock(priv, &flags); | 3748 | orinoco_unlock(priv, &flags); |
| 3590 | 3749 | ||
| 3591 | return err; | 3750 | /* Do NOT call commit handler */ |
| 3751 | return 0; | ||
| 3592 | } | 3752 | } |
| 3593 | 3753 | ||
| 3594 | static int orinoco_ioctl_getspy(struct net_device *dev, struct iw_point *srq) | 3754 | static int orinoco_ioctl_getspy(struct net_device *dev, |
| 3755 | struct iw_request_info *info, | ||
| 3756 | struct iw_point *srq, | ||
| 3757 | char *extra) | ||
| 3595 | { | 3758 | { |
| 3596 | struct orinoco_private *priv = netdev_priv(dev); | 3759 | struct orinoco_private *priv = netdev_priv(dev); |
| 3597 | struct sockaddr address[IW_MAX_SPY]; | 3760 | struct sockaddr *address = (struct sockaddr *) extra; |
| 3598 | struct iw_quality spy_stat[IW_MAX_SPY]; | ||
| 3599 | int number; | 3761 | int number; |
| 3600 | int i; | 3762 | int i; |
| 3601 | unsigned long flags; | 3763 | unsigned long flags; |
| @@ -3604,7 +3766,12 @@ static int orinoco_ioctl_getspy(struct net_device *dev, struct iw_point *srq) | |||
| 3604 | return -EBUSY; | 3766 | return -EBUSY; |
| 3605 | 3767 | ||
| 3606 | number = priv->spy_number; | 3768 | number = priv->spy_number; |
| 3607 | if ((number > 0) && (srq->pointer)) { | 3769 | /* Create address struct */ |
| 3770 | for (i = 0; i < number; i++) { | ||
| 3771 | memcpy(address[i].sa_data, priv->spy_address[i], ETH_ALEN); | ||
| 3772 | address[i].sa_family = AF_UNIX; | ||
| 3773 | } | ||
| 3774 | if (number > 0) { | ||
| 3608 | /* Create address struct */ | 3775 | /* Create address struct */ |
| 3609 | for (i = 0; i < number; i++) { | 3776 | for (i = 0; i < number; i++) { |
| 3610 | memcpy(address[i].sa_data, priv->spy_address[i], | 3777 | memcpy(address[i].sa_data, priv->spy_address[i], |
| @@ -3615,344 +3782,153 @@ static int orinoco_ioctl_getspy(struct net_device *dev, struct iw_point *srq) | |||
| 3615 | /* In theory, we should disable irqs while copying the stats | 3782 | /* In theory, we should disable irqs while copying the stats |
| 3616 | * because the rx path might update it in the middle... | 3783 | * because the rx path might update it in the middle... |
| 3617 | * Bah, who care ? - Jean II */ | 3784 | * Bah, who care ? - Jean II */ |
| 3618 | memcpy(&spy_stat, priv->spy_stat, | 3785 | memcpy(extra + (sizeof(struct sockaddr) * number), |
| 3619 | sizeof(struct iw_quality) * IW_MAX_SPY); | 3786 | priv->spy_stat, sizeof(struct iw_quality) * number); |
| 3620 | for (i=0; i < number; i++) | ||
| 3621 | priv->spy_stat[i].updated = 0; | ||
| 3622 | } | 3787 | } |
| 3788 | /* Reset updated flags. */ | ||
| 3789 | for (i = 0; i < number; i++) | ||
| 3790 | priv->spy_stat[i].updated = 0; | ||
| 3623 | 3791 | ||
| 3624 | orinoco_unlock(priv, &flags); | 3792 | orinoco_unlock(priv, &flags); |
| 3625 | 3793 | ||
| 3626 | /* Push stuff to user space */ | ||
| 3627 | srq->length = number; | 3794 | srq->length = number; |
| 3628 | if(copy_to_user(srq->pointer, address, | ||
| 3629 | sizeof(struct sockaddr) * number)) | ||
| 3630 | return -EFAULT; | ||
| 3631 | if(copy_to_user(srq->pointer + (sizeof(struct sockaddr)*number), | ||
| 3632 | &spy_stat, sizeof(struct iw_quality) * number)) | ||
| 3633 | return -EFAULT; | ||
| 3634 | 3795 | ||
| 3635 | return 0; | 3796 | return 0; |
| 3636 | } | 3797 | } |
| 3637 | 3798 | ||
| 3638 | static int | 3799 | /* Commit handler, called after set operations */ |
| 3639 | orinoco_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) | 3800 | static int orinoco_ioctl_commit(struct net_device *dev, |
| 3801 | struct iw_request_info *info, | ||
| 3802 | void *wrqu, | ||
| 3803 | char *extra) | ||
| 3640 | { | 3804 | { |
| 3641 | struct orinoco_private *priv = netdev_priv(dev); | 3805 | struct orinoco_private *priv = netdev_priv(dev); |
| 3642 | struct iwreq *wrq = (struct iwreq *)rq; | 3806 | struct hermes *hw = &priv->hw; |
| 3643 | int err = 0; | ||
| 3644 | int tmp; | ||
| 3645 | int changed = 0; | ||
| 3646 | unsigned long flags; | 3807 | unsigned long flags; |
| 3808 | int err = 0; | ||
| 3647 | 3809 | ||
| 3648 | TRACE_ENTER(dev->name); | 3810 | if (!priv->open) |
| 3649 | 3811 | return 0; | |
| 3650 | /* In theory, we could allow most of the the SET stuff to be | ||
| 3651 | * done. In practice, the lapse of time at startup when the | ||
| 3652 | * card is not ready is very short, so why bother... Note | ||
| 3653 | * that netif_device_present is different from up/down | ||
| 3654 | * (ifconfig), when the device is not yet up, it is usually | ||
| 3655 | * already ready... Jean II */ | ||
| 3656 | if (! netif_device_present(dev)) | ||
| 3657 | return -ENODEV; | ||
| 3658 | |||
| 3659 | switch (cmd) { | ||
| 3660 | case SIOCGIWNAME: | ||
| 3661 | strcpy(wrq->u.name, "IEEE 802.11-DS"); | ||
| 3662 | break; | ||
| 3663 | |||
| 3664 | case SIOCGIWAP: | ||
| 3665 | wrq->u.ap_addr.sa_family = ARPHRD_ETHER; | ||
| 3666 | err = orinoco_hw_get_bssid(priv, wrq->u.ap_addr.sa_data); | ||
| 3667 | break; | ||
| 3668 | |||
| 3669 | case SIOCGIWRANGE: | ||
| 3670 | err = orinoco_ioctl_getiwrange(dev, &wrq->u.data); | ||
| 3671 | break; | ||
| 3672 | |||
| 3673 | case SIOCSIWMODE: | ||
| 3674 | if (orinoco_lock(priv, &flags) != 0) | ||
| 3675 | return -EBUSY; | ||
| 3676 | switch (wrq->u.mode) { | ||
| 3677 | case IW_MODE_ADHOC: | ||
| 3678 | if (! (priv->has_ibss || priv->has_port3) ) | ||
| 3679 | err = -EINVAL; | ||
| 3680 | else { | ||
| 3681 | priv->iw_mode = IW_MODE_ADHOC; | ||
| 3682 | changed = 1; | ||
| 3683 | } | ||
| 3684 | break; | ||
| 3685 | |||
| 3686 | case IW_MODE_INFRA: | ||
| 3687 | priv->iw_mode = IW_MODE_INFRA; | ||
| 3688 | changed = 1; | ||
| 3689 | break; | ||
| 3690 | |||
| 3691 | default: | ||
| 3692 | err = -EINVAL; | ||
| 3693 | break; | ||
| 3694 | } | ||
| 3695 | set_port_type(priv); | ||
| 3696 | orinoco_unlock(priv, &flags); | ||
| 3697 | break; | ||
| 3698 | |||
| 3699 | case SIOCGIWMODE: | ||
| 3700 | if (orinoco_lock(priv, &flags) != 0) | ||
| 3701 | return -EBUSY; | ||
| 3702 | wrq->u.mode = priv->iw_mode; | ||
| 3703 | orinoco_unlock(priv, &flags); | ||
| 3704 | break; | ||
| 3705 | |||
| 3706 | case SIOCSIWENCODE: | ||
| 3707 | err = orinoco_ioctl_setiwencode(dev, &wrq->u.encoding); | ||
| 3708 | if (! err) | ||
| 3709 | changed = 1; | ||
| 3710 | break; | ||
| 3711 | |||
| 3712 | case SIOCGIWENCODE: | ||
| 3713 | if (! capable(CAP_NET_ADMIN)) { | ||
| 3714 | err = -EPERM; | ||
| 3715 | break; | ||
| 3716 | } | ||
| 3717 | |||
| 3718 | err = orinoco_ioctl_getiwencode(dev, &wrq->u.encoding); | ||
| 3719 | break; | ||
| 3720 | |||
| 3721 | case SIOCSIWESSID: | ||
| 3722 | err = orinoco_ioctl_setessid(dev, &wrq->u.essid); | ||
| 3723 | if (! err) | ||
| 3724 | changed = 1; | ||
| 3725 | break; | ||
| 3726 | |||
| 3727 | case SIOCGIWESSID: | ||
| 3728 | err = orinoco_ioctl_getessid(dev, &wrq->u.essid); | ||
| 3729 | break; | ||
| 3730 | |||
| 3731 | case SIOCSIWNICKN: | ||
| 3732 | err = orinoco_ioctl_setnick(dev, &wrq->u.data); | ||
| 3733 | if (! err) | ||
| 3734 | changed = 1; | ||
| 3735 | break; | ||
| 3736 | |||
| 3737 | case SIOCGIWNICKN: | ||
| 3738 | err = orinoco_ioctl_getnick(dev, &wrq->u.data); | ||
| 3739 | break; | ||
| 3740 | |||
| 3741 | case SIOCGIWFREQ: | ||
| 3742 | tmp = orinoco_hw_get_freq(priv); | ||
| 3743 | if (tmp < 0) { | ||
| 3744 | err = tmp; | ||
| 3745 | } else { | ||
| 3746 | wrq->u.freq.m = tmp; | ||
| 3747 | wrq->u.freq.e = 1; | ||
| 3748 | } | ||
| 3749 | break; | ||
| 3750 | |||
| 3751 | case SIOCSIWFREQ: | ||
| 3752 | err = orinoco_ioctl_setfreq(dev, &wrq->u.freq); | ||
| 3753 | if (! err) | ||
| 3754 | changed = 1; | ||
| 3755 | break; | ||
| 3756 | |||
| 3757 | case SIOCGIWSENS: | ||
| 3758 | err = orinoco_ioctl_getsens(dev, &wrq->u.sens); | ||
| 3759 | break; | ||
| 3760 | |||
| 3761 | case SIOCSIWSENS: | ||
| 3762 | err = orinoco_ioctl_setsens(dev, &wrq->u.sens); | ||
| 3763 | if (! err) | ||
| 3764 | changed = 1; | ||
| 3765 | break; | ||
| 3766 | |||
| 3767 | case SIOCGIWRTS: | ||
| 3768 | wrq->u.rts.value = priv->rts_thresh; | ||
| 3769 | wrq->u.rts.disabled = (wrq->u.rts.value == 2347); | ||
| 3770 | wrq->u.rts.fixed = 1; | ||
| 3771 | break; | ||
| 3772 | |||
| 3773 | case SIOCSIWRTS: | ||
| 3774 | err = orinoco_ioctl_setrts(dev, &wrq->u.rts); | ||
| 3775 | if (! err) | ||
| 3776 | changed = 1; | ||
| 3777 | break; | ||
| 3778 | |||
| 3779 | case SIOCSIWFRAG: | ||
| 3780 | err = orinoco_ioctl_setfrag(dev, &wrq->u.frag); | ||
| 3781 | if (! err) | ||
| 3782 | changed = 1; | ||
| 3783 | break; | ||
| 3784 | |||
| 3785 | case SIOCGIWFRAG: | ||
| 3786 | err = orinoco_ioctl_getfrag(dev, &wrq->u.frag); | ||
| 3787 | break; | ||
| 3788 | |||
| 3789 | case SIOCSIWRATE: | ||
| 3790 | err = orinoco_ioctl_setrate(dev, &wrq->u.bitrate); | ||
| 3791 | if (! err) | ||
| 3792 | changed = 1; | ||
| 3793 | break; | ||
| 3794 | |||
| 3795 | case SIOCGIWRATE: | ||
| 3796 | err = orinoco_ioctl_getrate(dev, &wrq->u.bitrate); | ||
| 3797 | break; | ||
| 3798 | |||
| 3799 | case SIOCSIWPOWER: | ||
| 3800 | err = orinoco_ioctl_setpower(dev, &wrq->u.power); | ||
| 3801 | if (! err) | ||
| 3802 | changed = 1; | ||
| 3803 | break; | ||
| 3804 | |||
| 3805 | case SIOCGIWPOWER: | ||
| 3806 | err = orinoco_ioctl_getpower(dev, &wrq->u.power); | ||
| 3807 | break; | ||
| 3808 | |||
| 3809 | case SIOCGIWTXPOW: | ||
| 3810 | /* The card only supports one tx power, so this is easy */ | ||
| 3811 | wrq->u.txpower.value = 15; /* dBm */ | ||
| 3812 | wrq->u.txpower.fixed = 1; | ||
| 3813 | wrq->u.txpower.disabled = 0; | ||
| 3814 | wrq->u.txpower.flags = IW_TXPOW_DBM; | ||
| 3815 | break; | ||
| 3816 | 3812 | ||
| 3817 | case SIOCSIWRETRY: | 3813 | if (priv->broken_disableport) { |
| 3818 | err = -EOPNOTSUPP; | 3814 | orinoco_reset(dev); |
| 3819 | break; | 3815 | return 0; |
| 3816 | } | ||
| 3820 | 3817 | ||
| 3821 | case SIOCGIWRETRY: | 3818 | if (orinoco_lock(priv, &flags) != 0) |
| 3822 | err = orinoco_ioctl_getretry(dev, &wrq->u.retry); | 3819 | return err; |
| 3823 | break; | ||
| 3824 | 3820 | ||
| 3825 | case SIOCSIWSPY: | 3821 | err = hermes_disable_port(hw, 0); |
| 3826 | err = orinoco_ioctl_setspy(dev, &wrq->u.data); | 3822 | if (err) { |
| 3827 | break; | 3823 | printk(KERN_WARNING "%s: Unable to disable port " |
| 3824 | "while reconfiguring card\n", dev->name); | ||
| 3825 | priv->broken_disableport = 1; | ||
| 3826 | goto out; | ||
| 3827 | } | ||
| 3828 | 3828 | ||
| 3829 | case SIOCGIWSPY: | 3829 | err = __orinoco_program_rids(dev); |
| 3830 | err = orinoco_ioctl_getspy(dev, &wrq->u.data); | 3830 | if (err) { |
| 3831 | break; | 3831 | printk(KERN_WARNING "%s: Unable to reconfigure card\n", |
| 3832 | dev->name); | ||
| 3833 | goto out; | ||
| 3834 | } | ||
| 3832 | 3835 | ||
| 3833 | case SIOCGIWPRIV: | 3836 | err = hermes_enable_port(hw, 0); |
| 3834 | if (wrq->u.data.pointer) { | 3837 | if (err) { |
| 3835 | struct iw_priv_args privtab[] = { | 3838 | printk(KERN_WARNING "%s: Unable to enable port while reconfiguring card\n", |
| 3836 | { SIOCIWFIRSTPRIV + 0x0, 0, 0, "force_reset" }, | 3839 | dev->name); |
| 3837 | { SIOCIWFIRSTPRIV + 0x1, 0, 0, "card_reset" }, | 3840 | goto out; |
| 3838 | { SIOCIWFIRSTPRIV + 0x2, | 3841 | } |
| 3839 | IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, | ||
| 3840 | 0, "set_port3" }, | ||
| 3841 | { SIOCIWFIRSTPRIV + 0x3, 0, | ||
| 3842 | IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, | ||
| 3843 | "get_port3" }, | ||
| 3844 | { SIOCIWFIRSTPRIV + 0x4, | ||
| 3845 | IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, | ||
| 3846 | 0, "set_preamble" }, | ||
| 3847 | { SIOCIWFIRSTPRIV + 0x5, 0, | ||
| 3848 | IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, | ||
| 3849 | "get_preamble" }, | ||
| 3850 | { SIOCIWFIRSTPRIV + 0x6, | ||
| 3851 | IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, | ||
| 3852 | 0, "set_ibssport" }, | ||
| 3853 | { SIOCIWFIRSTPRIV + 0x7, 0, | ||
| 3854 | IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, | ||
| 3855 | "get_ibssport" }, | ||
| 3856 | }; | ||
| 3857 | |||
| 3858 | wrq->u.data.length = sizeof(privtab) / sizeof(privtab[0]); | ||
| 3859 | if (copy_to_user(wrq->u.data.pointer, privtab, sizeof(privtab))) | ||
| 3860 | err = -EFAULT; | ||
| 3861 | } | ||
| 3862 | break; | ||
| 3863 | |||
| 3864 | case SIOCIWFIRSTPRIV + 0x0: /* force_reset */ | ||
| 3865 | case SIOCIWFIRSTPRIV + 0x1: /* card_reset */ | ||
| 3866 | if (! capable(CAP_NET_ADMIN)) { | ||
| 3867 | err = -EPERM; | ||
| 3868 | break; | ||
| 3869 | } | ||
| 3870 | |||
| 3871 | printk(KERN_DEBUG "%s: Force scheduling reset!\n", dev->name); | ||
| 3872 | 3842 | ||
| 3843 | out: | ||
| 3844 | if (err) { | ||
| 3845 | printk(KERN_WARNING "%s: Resetting instead...\n", dev->name); | ||
| 3873 | schedule_work(&priv->reset_work); | 3846 | schedule_work(&priv->reset_work); |
| 3874 | break; | 3847 | err = 0; |
| 3875 | 3848 | } | |
| 3876 | case SIOCIWFIRSTPRIV + 0x2: /* set_port3 */ | ||
| 3877 | if (! capable(CAP_NET_ADMIN)) { | ||
| 3878 | err = -EPERM; | ||
| 3879 | break; | ||
| 3880 | } | ||
| 3881 | |||
| 3882 | err = orinoco_ioctl_setport3(dev, wrq); | ||
| 3883 | if (! err) | ||
| 3884 | changed = 1; | ||
| 3885 | break; | ||
| 3886 | |||
| 3887 | case SIOCIWFIRSTPRIV + 0x3: /* get_port3 */ | ||
| 3888 | err = orinoco_ioctl_getport3(dev, wrq); | ||
| 3889 | break; | ||
| 3890 | |||
| 3891 | case SIOCIWFIRSTPRIV + 0x4: /* set_preamble */ | ||
| 3892 | if (! capable(CAP_NET_ADMIN)) { | ||
| 3893 | err = -EPERM; | ||
| 3894 | break; | ||
| 3895 | } | ||
| 3896 | |||
| 3897 | /* 802.11b has recently defined some short preamble. | ||
| 3898 | * Basically, the Phy header has been reduced in size. | ||
| 3899 | * This increase performance, especially at high rates | ||
| 3900 | * (the preamble is transmitted at 1Mb/s), unfortunately | ||
| 3901 | * this give compatibility troubles... - Jean II */ | ||
| 3902 | if(priv->has_preamble) { | ||
| 3903 | int val = *( (int *) wrq->u.name ); | ||
| 3904 | |||
| 3905 | if (orinoco_lock(priv, &flags) != 0) | ||
| 3906 | return -EBUSY; | ||
| 3907 | if (val) | ||
| 3908 | priv->preamble = 1; | ||
| 3909 | else | ||
| 3910 | priv->preamble = 0; | ||
| 3911 | orinoco_unlock(priv, &flags); | ||
| 3912 | changed = 1; | ||
| 3913 | } else | ||
| 3914 | err = -EOPNOTSUPP; | ||
| 3915 | break; | ||
| 3916 | 3849 | ||
| 3917 | case SIOCIWFIRSTPRIV + 0x5: /* get_preamble */ | 3850 | orinoco_unlock(priv, &flags); |
| 3918 | if(priv->has_preamble) { | 3851 | return err; |
| 3919 | int *val = (int *)wrq->u.name; | 3852 | } |
| 3920 | 3853 | ||
| 3921 | if (orinoco_lock(priv, &flags) != 0) | 3854 | static const struct iw_priv_args orinoco_privtab[] = { |
| 3922 | return -EBUSY; | 3855 | { SIOCIWFIRSTPRIV + 0x0, 0, 0, "force_reset" }, |
| 3923 | *val = priv->preamble; | 3856 | { SIOCIWFIRSTPRIV + 0x1, 0, 0, "card_reset" }, |
| 3924 | orinoco_unlock(priv, &flags); | 3857 | { SIOCIWFIRSTPRIV + 0x2, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, |
| 3925 | } else | 3858 | 0, "set_port3" }, |
| 3926 | err = -EOPNOTSUPP; | 3859 | { SIOCIWFIRSTPRIV + 0x3, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, |
| 3927 | break; | 3860 | "get_port3" }, |
| 3928 | case SIOCIWFIRSTPRIV + 0x6: /* set_ibssport */ | 3861 | { SIOCIWFIRSTPRIV + 0x4, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, |
| 3929 | if (! capable(CAP_NET_ADMIN)) { | 3862 | 0, "set_preamble" }, |
| 3930 | err = -EPERM; | 3863 | { SIOCIWFIRSTPRIV + 0x5, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, |
| 3931 | break; | 3864 | "get_preamble" }, |
| 3932 | } | 3865 | { SIOCIWFIRSTPRIV + 0x6, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, |
| 3866 | 0, "set_ibssport" }, | ||
| 3867 | { SIOCIWFIRSTPRIV + 0x7, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, | ||
| 3868 | "get_ibssport" }, | ||
| 3869 | { SIOCIWFIRSTPRIV + 0x9, 0, IW_PRIV_TYPE_BYTE | MAX_RID_LEN, | ||
| 3870 | "get_rid" }, | ||
| 3871 | }; | ||
| 3933 | 3872 | ||
| 3934 | err = orinoco_ioctl_setibssport(dev, wrq); | ||
| 3935 | if (! err) | ||
| 3936 | changed = 1; | ||
| 3937 | break; | ||
| 3938 | 3873 | ||
| 3939 | case SIOCIWFIRSTPRIV + 0x7: /* get_ibssport */ | 3874 | /* |
| 3940 | err = orinoco_ioctl_getibssport(dev, wrq); | 3875 | * Structures to export the Wireless Handlers |
| 3941 | break; | 3876 | */ |
| 3942 | 3877 | ||
| 3943 | default: | 3878 | static const iw_handler orinoco_handler[] = { |
| 3944 | err = -EOPNOTSUPP; | 3879 | [SIOCSIWCOMMIT-SIOCIWFIRST] (iw_handler) orinoco_ioctl_commit, |
| 3945 | } | 3880 | [SIOCGIWNAME -SIOCIWFIRST] (iw_handler) orinoco_ioctl_getname, |
| 3946 | 3881 | [SIOCSIWFREQ -SIOCIWFIRST] (iw_handler) orinoco_ioctl_setfreq, | |
| 3947 | if (! err && changed && netif_running(dev)) { | 3882 | [SIOCGIWFREQ -SIOCIWFIRST] (iw_handler) orinoco_ioctl_getfreq, |
| 3948 | err = orinoco_reconfigure(dev); | 3883 | [SIOCSIWMODE -SIOCIWFIRST] (iw_handler) orinoco_ioctl_setmode, |
| 3949 | } | 3884 | [SIOCGIWMODE -SIOCIWFIRST] (iw_handler) orinoco_ioctl_getmode, |
| 3885 | [SIOCSIWSENS -SIOCIWFIRST] (iw_handler) orinoco_ioctl_setsens, | ||
| 3886 | [SIOCGIWSENS -SIOCIWFIRST] (iw_handler) orinoco_ioctl_getsens, | ||
| 3887 | [SIOCGIWRANGE -SIOCIWFIRST] (iw_handler) orinoco_ioctl_getiwrange, | ||
| 3888 | [SIOCSIWSPY -SIOCIWFIRST] (iw_handler) orinoco_ioctl_setspy, | ||
| 3889 | [SIOCGIWSPY -SIOCIWFIRST] (iw_handler) orinoco_ioctl_getspy, | ||
| 3890 | [SIOCGIWAP -SIOCIWFIRST] (iw_handler) orinoco_ioctl_getwap, | ||
| 3891 | [SIOCSIWESSID -SIOCIWFIRST] (iw_handler) orinoco_ioctl_setessid, | ||
| 3892 | [SIOCGIWESSID -SIOCIWFIRST] (iw_handler) orinoco_ioctl_getessid, | ||
| 3893 | [SIOCSIWNICKN -SIOCIWFIRST] (iw_handler) orinoco_ioctl_setnick, | ||
| 3894 | [SIOCGIWNICKN -SIOCIWFIRST] (iw_handler) orinoco_ioctl_getnick, | ||
| 3895 | [SIOCSIWRATE -SIOCIWFIRST] (iw_handler) orinoco_ioctl_setrate, | ||
| 3896 | [SIOCGIWRATE -SIOCIWFIRST] (iw_handler) orinoco_ioctl_getrate, | ||
| 3897 | [SIOCSIWRTS -SIOCIWFIRST] (iw_handler) orinoco_ioctl_setrts, | ||
| 3898 | [SIOCGIWRTS -SIOCIWFIRST] (iw_handler) orinoco_ioctl_getrts, | ||
| 3899 | [SIOCSIWFRAG -SIOCIWFIRST] (iw_handler) orinoco_ioctl_setfrag, | ||
| 3900 | [SIOCGIWFRAG -SIOCIWFIRST] (iw_handler) orinoco_ioctl_getfrag, | ||
| 3901 | [SIOCGIWRETRY -SIOCIWFIRST] (iw_handler) orinoco_ioctl_getretry, | ||
| 3902 | [SIOCSIWENCODE-SIOCIWFIRST] (iw_handler) orinoco_ioctl_setiwencode, | ||
| 3903 | [SIOCGIWENCODE-SIOCIWFIRST] (iw_handler) orinoco_ioctl_getiwencode, | ||
| 3904 | [SIOCSIWPOWER -SIOCIWFIRST] (iw_handler) orinoco_ioctl_setpower, | ||
| 3905 | [SIOCGIWPOWER -SIOCIWFIRST] (iw_handler) orinoco_ioctl_getpower, | ||
| 3906 | }; | ||
| 3950 | 3907 | ||
| 3951 | TRACE_EXIT(dev->name); | ||
| 3952 | 3908 | ||
| 3953 | return err; | 3909 | /* |
| 3954 | } | 3910 | Added typecasting since we no longer use iwreq_data -- Moustafa |
| 3911 | */ | ||
| 3912 | static const iw_handler orinoco_private_handler[] = { | ||
| 3913 | [0] (iw_handler) orinoco_ioctl_reset, | ||
| 3914 | [1] (iw_handler) orinoco_ioctl_reset, | ||
| 3915 | [2] (iw_handler) orinoco_ioctl_setport3, | ||
| 3916 | [3] (iw_handler) orinoco_ioctl_getport3, | ||
| 3917 | [4] (iw_handler) orinoco_ioctl_setpreamble, | ||
| 3918 | [5] (iw_handler) orinoco_ioctl_getpreamble, | ||
| 3919 | [6] (iw_handler) orinoco_ioctl_setibssport, | ||
| 3920 | [7] (iw_handler) orinoco_ioctl_getibssport, | ||
| 3921 | [9] (iw_handler) orinoco_ioctl_getrid, | ||
| 3922 | }; | ||
| 3955 | 3923 | ||
| 3924 | static const struct iw_handler_def orinoco_handler_def = { | ||
| 3925 | .num_standard = ARRAY_SIZE(orinoco_handler), | ||
| 3926 | .num_private = ARRAY_SIZE(orinoco_private_handler), | ||
| 3927 | .num_private_args = ARRAY_SIZE(orinoco_privtab), | ||
| 3928 | .standard = orinoco_handler, | ||
| 3929 | .private = orinoco_private_handler, | ||
| 3930 | .private_args = orinoco_privtab, | ||
| 3931 | }; | ||
| 3956 | 3932 | ||
| 3957 | /********************************************************************/ | 3933 | /********************************************************************/ |
| 3958 | /* Debugging */ | 3934 | /* Debugging */ |
